Tuesday, July 26, 2011
Firebird 2.5 SuperServer and MacOSX 10.7 (Lion)
There is a small problem with Firebird 2.5 SuperServer and MacOSX 10.7 (Lion)...
SuperServer will not start, and produces a crash report header similar to this
Update 26th August 2011
Its not just 2.5 SuperServer, reports have come in that SuperServer for Firebird 2.1.4 will not start, also the same problem exists for Firebird 2.5 SuperClassic.
Process: fbserver [706]
Path: /Library/Frameworks/firebird.framework/Versions/A/Resources/bin/fbserver
Identifier: fbserver
Version: ??? (???)
Code Type: X86 (Native)
Parent Process: fbguard [166]
Date/Time: 2011-06-10 07:59:42.374 -0400
OS Version: Mac OS X 10.7 (11A480b)
Report Version: 9
Anonymous UUID: B7EDF790-CE72-4B21-A982-B9EA4F4E2088
Crashed Thread: 1 Dispatch queue: com.apple.libdispatch-manager
Exception Type: EXC_BAD_INSTRUCTION (SIGILL)
Exception Codes: 0x0000000000000001, 0x0000000000000000
Application Specific Information:
BUG IN CLIENT OF LIBDISPATCH: Do not close random Unix descriptors
The bug is fixed in Firebird 2.5.1 but Firebird 2.5.1 is not available yet. So I have fixed the problem also in the Firebird 2.5 code and produced 32bit and 64bit builds that work properly.
I have had new builds uploaded to Sourceforge to fix the problem with Firebird
2.1.4 SuperServer, you can distinguish the new builds from the old by the build no.
Old = 18393, New = 18393. Because we have some issues with 2.5.1 that are currently being investigated, I plan to update the 2.5 builds on Sourceforge soon.
Update 28th Sep 2011
The Firebird 2.5 builds have also been replaced on Sourceforge, so you just need to download the latest build. However Firebird 2.5 will be replaced by Firebird 2.5.1 very shortly, builds are now taking place and will be QA'd and released shortly.
Any problems - please let me know.
Monday, July 4, 2011
Firebird V2.1 Error: value exceeds the range for valid dates
You are restoring a backup of a Firebird 1.5 or 2.0 database to Firebird 2.1 and you see an error similar to this:
gbak: writing data for table xyz
gbak:20000 records written
gbak: Error: value exceeds the range for valid dates
gbak: Error: gds_$receive failed
gbak:Exiting before completion due to errors
How do you go about solving the problem?
Well first of all a quick visit to the Firebird bug tracker reveals
http://tracker.firebirdsql.org/browse/CORE-1714 and a couple of comments from Dimitry Yemanov.
“The error means to say that some column has an invalid date value (outside the supported range). Prior to V2.1, it was possible to store such invalid values in the database, but now it's prohibited. A verbose output should point you to a problematic table.” Also “The current behavior is intended and is unlikely to be changed.”
1. Firstly use the –v (verbose option of gbak) to find out the table that is causing the problem.
2. Check the table xyz for date columns
3. Perform the following SQL operation on all the date columns you found in 2.
isql> update XYZ set MY_DATE_COLUMN = MY_DATE_COLUMN;
At some point during the process you will see the same error that gbak produced, but now you will know which column is causing the problem.
4. Install Firebird 1.5 or 2.0, by going back to the version of Firebird that allows for invalid dates, you will be at least able to correct the invalid date to something more appropriate.
5. Now lets check for dates that are outside of their proper range (01 Jan 0001 - 31 Dec 9999)
Below date zero:
isql> select PRIMARY_KEY from XYZ where MY_DATE_COLUMN < '0001-01-01'
if an error occurs correct the date to something more appropriate and meaningful
Maximum date
isql> select PRIMARY_KEY from XYZ where MY_DATE_COLUMN > '9999-12-31'
if an error occurs correct the date to something more appropriate and meaningful
6. You can now backup the database using Firebird 1.5 or 2.1 and successfully restore under 2.1
For anyone interested, the following is a shell script provided by a friend that can be used on Linux to correct the above errors automagically across multiple databases.
#!/bin/bash -u
# correct OLD invalid dates in a DB
#
# Ray Holme, July 2013 - 207-583-6613
# Rainbow Applications Inc., Waterford, ME 04088
#
ARGCNT=$#
MYNAME=`/bin/basename $0`
DATEL="'1/1/0001'"
DATEH="'12/31/9999'"
DRYRUN=0
ERRCNT=0
FLDS=/tmp/$$.flds
ISQL=/opt/firebird/bin/isql
ListDBS=""
LOG=/tmp/$$.out
NOFILE="could not find"
NOTNULL="is not null"
RANGE="not between $DATEL and $DATEH"
RM=/bin/rm
SQL=/tmp/$$.sql
USAGE="usage: $MYNAME <-d> DBname1
WORK=/tmp/$$.wrk
ABORT() { $RM -f $FLDS $SQL $WORK; echo $MYNAME aborted; exit $1; }
INCR_ERRCNT() { ERRCNT=`echo $ERRCNT + 1 | /bin/bc`; }
ANSWER_ME() {
OK=2; until [ $OK -ne 2 ];
do
echo "Please type '$2' or '$3'."; echo -n "$1 [$2]: "; read ANS
if [ "$ANS" = "$2" -o "$ANS" = "" ]; then OK=1
elif [ "$ANS" = "$2" ]; then OK=0
fi
done
}
#get list of dbs to do
until [ $# -eq 0 ];
do case "$1" in
-d) DRYRUN=1; ARGCNT=`echo $ARGCNT - 1 | /bin/bc` ;;
*) if [ ! -f $1 ]; then echo $NOFILE $1; INCR_ERRCNT;
else ListDBS="$ListDBS $1" ;
fi ;;
esac
shift
done
if [ "$ListDBS" = "" ]; then echo "$USAGE"; exit 1; fi
trap "ABORT 1" 1 2 3
if [ ! -w /etc/passwd ]; then echo you must be root to execute $MYNAME; exit 1; fi
$RM -f $LOG # get what we need to do (worst case)
for DB in $ListDBS
do
$RM -f $FLDS
if [ $ARGCNT -gt 1 ]; then
ANSWER_ME "about to check $DB - c to continue, s to skip" c s
if [ $OK -eq 0 ]; then continue; fi # skipped
fi
$ISQL $DB -pag 9999 > /dev/null 2> $WORK <
select r.rdb\$relation_name, rf.rdb\$field_name
from rdb\$relations r
inner join rdb\$relation_fields rf on (r.rdb\$relation_name = rf.rdb\$relation_name)
inner join rdb\$fields f on (f.rdb\$field_name = rf.rdb\$field_source)
where r.rdb\$view_source is null and r.rdb\$system_flag = 0
and f.rdb\$field_type = 35
order by 1, 2;
EOF
if [ -f $WORK ]; then XXX=`cat $WORK`; else XXX=""; fi
if [ "$XXX" != "" ]; then echo problems working $DB; INCR_ERRCNT; continue; fi
/bin/egrep -v "RELATION_NAME|==========" < $FLDS | grep -v '^$' \
| /bin/awk '{printf("%-32.32s %s\n", $1, $2)}'> $WORK
/bin/mv $WORK $FLDS
if [ -f $FLDS ]; then XXX=`cat $FLDS`; else XXX=""; fi
if [ "$XXX" = "" ]; then echo "no dates in $DB - curious (skip)"; continue; fi
# pass 1 - we show the records with errors embedded
echo "Listing effected records in DB: $DB" >> $LOG
echo "output $LOG;" > $SQL
LastTable=""
while read TABLE FIELD
do
if [ "$TABLE" != "$LastTable" ]; then
if [ "$LastTable" != "" ]; then echo ";" >> $SQL; fi
LastTable="$TABLE"
echo "select distinct 'table: $TABLE' from rdb\$database;" >> $SQL
echo "select * from $TABLE where " >> $SQL
else echo -n " or " >> $SQL
fi
echo "( $FIELD $NOTNULL and ($FIELD $RANGE ))" >> $SQL
done < $FLDS
if [ "$LastTable" != "" ]; then echo ";" >> $SQL; fi
$ISQL $DB -pag 9999 -i $SQL
# pass 2 - do clean up
$RM $SQL
while read TABLE FIELD
do
echo "update $TABLE set $FIELD = $DATEL where $FIELD $NOTNULL and $FIELD < $DATEL;" >> $SQL
echo "update $TABLE set $FIELD = $DATEH where $FIELD $NOTNULL and $FIELD > $DATEH;" >> $SQL
echo "commit;" >> $SQL
done < $FLDS
echo "exit;" >> $SQL
if [ $DRYRUN -eq 0 ]; then $ISQL $DB -pag 9999 -i $SQL
else echo "Would run this sql on $DB"; /bin/more $SQL
fi
done # end of outer (DB) loop
$RM -f $FLDS $SQL $WORK
echo file $LOG contains a list of all effected records
exit $ERRCNT
Subscribe to:
Posts (Atom)