Commit aecef761 authored by monty@hundin.mysql.fi's avatar monty@hundin.mysql.fi

Removed wrong warning from thr_lock

Fixed problem with UPDATE and BDB tables
Fixed problem with GRANT FILE privilege on database level
mysqld --warnings works now
Fixed problem with SHOW OPEN TABLES when not using BDB
Added some tests for ALTER TABLE to the test scripts
parent 02f72a80
...@@ -3582,7 +3582,7 @@ in your applications or when you add not free extensions to the ...@@ -3582,7 +3582,7 @@ in your applications or when you add not free extensions to the
become GPL through the GPL license that acts as a virus. By licensing become GPL through the GPL license that acts as a virus. By licensing
@strong{MySQL} server from @strong{MySQL AB} under a commercial @strong{MySQL} server from @strong{MySQL AB} under a commercial
license you will avoid this problem. license you will avoid this problem.
See @uref{http://www.gnu.org/copyleft/gpl-faq.html}.
@item @item
You have a commercial application that ONLY works with @strong{MySQL} You have a commercial application that ONLY works with @strong{MySQL}
and ships the application with the @strong{MySQL} server. This is and ships the application with the @strong{MySQL} server. This is
...@@ -45717,6 +45717,11 @@ not yet 100% confident in this code. ...@@ -45717,6 +45717,11 @@ not yet 100% confident in this code.
@appendixsubsec Changes in release 3.23.40 @appendixsubsec Changes in release 3.23.40
@itemize @bullet @itemize @bullet
@item @item
Fixed problem with @code{UPDATE} and BDB tables.
@item
Fixed problem when using the @code{GRANT FILE ON database.* ...}; Previously
we added the @code{DROP} privilege for the database.
@item
Fixed that @code{DELETE FROM table_name ... LIMIT 0} and Fixed that @code{DELETE FROM table_name ... LIMIT 0} and
@code{UPDATE FROM table_name ... LIMIT 0} doesn't delete/update anything. @code{UPDATE FROM table_name ... LIMIT 0} doesn't delete/update anything.
@item @item
...@@ -45747,8 +45752,8 @@ Fixed bug in @code{BDB} tables when querying empty tables. ...@@ -45747,8 +45752,8 @@ Fixed bug in @code{BDB} tables when querying empty tables.
Fixed a bug when using @code{COUNT(DISTINCT)} with @code{LEFT JOIN} and Fixed a bug when using @code{COUNT(DISTINCT)} with @code{LEFT JOIN} and
there wasn't any matching rows. there wasn't any matching rows.
@item @item
Removed all documentation referring to the @code{GEMINI} table type. @code{GEMINI} Removed all documentation referring to the @code{GEMINI} table
is not released under an Open Source license. type. @code{GEMINI} is not released under an Open Source license.
@end itemize @end itemize
@node News-3.23.39, News-3.23.38, News-3.23.40, News-3.23.x @node News-3.23.39, News-3.23.38, News-3.23.40, News-3.23.x
...@@ -50795,16 +50800,20 @@ Don't execute @code{ALTER TABLE} on a @code{BDB} table on which you are ...@@ -50795,16 +50800,20 @@ Don't execute @code{ALTER TABLE} on a @code{BDB} table on which you are
running not completed multi-statement transactions. (The transaction running not completed multi-statement transactions. (The transaction
will probably be ignored). will probably be ignored).
@item
@code{ANALYZE TABLE}, @code{OPTIMIZE TABLE} and @code{REPAIR TABLE} may
cause problems on tables for which you are using @code{INSERT DELAYED}.
@item @item
Doing a @code{LOCK TABLE ..} and @code{FLUSH TABLES ..} doesn't Doing a @code{LOCK TABLE ..} and @code{FLUSH TABLES ..} doesn't
guarantee that there isn't a half-finished transaction in progress on the guarantee that there isn't a half-finished transaction in progress on the
table. table.
@item @item
BDB tables are a bit slow to open from this. If you have many BDB tables BDB tables are a bit slow to open. If you have many BDB tables in a
in a database, it will take a long time to use the @code{mysql} client database, it will take a long time to use the @code{mysql} client on the
on the database if you are not using the @code{-A} option or if you are database if you are not using the @code{-A} option or if you are using
using @code{rehash}. This is especially notable when you have a big table @code{rehash}. This is especially notable when you have a big table
cache. cache.
@item @item
...@@ -50959,6 +50968,8 @@ values in double. Using these will cause problems when trying to export ...@@ -50959,6 +50968,8 @@ values in double. Using these will cause problems when trying to export
and import data. We should as an intermediate solution change @code{NaN} to and import data. We should as an intermediate solution change @code{NaN} to
@code{NULL} (if possible) and @code{-Inf} and @code{Inf} to the @code{NULL} (if possible) and @code{-Inf} and @code{Inf} to the
Minimum respective maximum possible @code{double} value. Minimum respective maximum possible @code{double} value.
@item
@code{LIMIT} on negative numbers are treated as big positive numbers.
@end itemize @end itemize
The following are known bugs in earlier versions of @strong{MySQL}: The following are known bugs in earlier versions of @strong{MySQL}:
...@@ -2011,7 +2011,7 @@ and GNU make work together causes some files to depend on this ...@@ -2011,7 +2011,7 @@ and GNU make work together causes some files to depend on this
header, even if we're not building with Berkeley DB. header, even if we're not building with Berkeley DB.
Obviously, if this file *is* used, it'll break and hopefully we can find Obviously, if this file *is* used, it'll break and hopefully we can find
out why this file was generated by $(top_srcdir)/configure instead of out why this file was generated by ${top_srcdir}/configure instead of
the real db.h. the real db.h.
If you run into some problems because of this file, please use mysql_bug If you run into some problems because of this file, please use mysql_bug
......
...@@ -110,7 +110,8 @@ my_bool init_thr_lock() ...@@ -110,7 +110,8 @@ my_bool init_thr_lock()
} }
#ifdef EXTRA_DEBUG #ifdef EXTRA_DEBUG
static int found_errors=0; #define MAX_FOUND_ERRORS 10 /* Report 10 first errors */
static uint found_errors=0;
static int check_lock(struct st_lock_list *list, const char* lock_type, static int check_lock(struct st_lock_list *list, const char* lock_type,
const char *where, my_bool same_thread) const char *where, my_bool same_thread)
...@@ -167,15 +168,16 @@ static int check_lock(struct st_lock_list *list, const char* lock_type, ...@@ -167,15 +168,16 @@ static int check_lock(struct st_lock_list *list, const char* lock_type,
static void check_locks(THR_LOCK *lock, const char *where, static void check_locks(THR_LOCK *lock, const char *where,
my_bool allow_no_locks) my_bool allow_no_locks)
{ {
if (!found_errors) uint old_found_errors=found_errors;
if (found_errors < MAX_FOUND_ERRORS)
{ {
if (check_lock(&lock->write,"write",where,1) | if (check_lock(&lock->write,"write",where,1) |
check_lock(&lock->write_wait,"write_wait",where,0) | check_lock(&lock->write_wait,"write_wait",where,0) |
check_lock(&lock->read,"read",where,0) | check_lock(&lock->read,"read",where,0) |
check_lock(&lock->read_wait,"read_wait",where,0)) check_lock(&lock->read_wait,"read_wait",where,0))
found_errors=1; found_errors++;
if (!found_errors) if (found_errors < MAX_FOUND_ERRORS)
{ {
uint count=0; uint count=0;
THR_LOCK_DATA *data; THR_LOCK_DATA *data;
...@@ -186,7 +188,7 @@ static void check_locks(THR_LOCK *lock, const char *where, ...@@ -186,7 +188,7 @@ static void check_locks(THR_LOCK *lock, const char *where,
} }
if (count != lock->read_no_write_count) if (count != lock->read_no_write_count)
{ {
found_errors=1; found_errors++;
fprintf(stderr, fprintf(stderr,
"Warning at '%s': Locks read_no_write_count was %u when it should have been %u\n", where, lock->read_no_write_count,count); "Warning at '%s': Locks read_no_write_count was %u when it should have been %u\n", where, lock->read_no_write_count,count);
} }
...@@ -196,7 +198,7 @@ static void check_locks(THR_LOCK *lock, const char *where, ...@@ -196,7 +198,7 @@ static void check_locks(THR_LOCK *lock, const char *where,
if (!allow_no_locks && !lock->read.data && if (!allow_no_locks && !lock->read.data &&
(lock->write_wait.data || lock->read_wait.data)) (lock->write_wait.data || lock->read_wait.data))
{ {
found_errors=1; found_errors++;
fprintf(stderr, fprintf(stderr,
"Warning at '%s': No locks in use but locks are in wait queue\n", "Warning at '%s': No locks in use but locks are in wait queue\n",
where); where);
...@@ -205,7 +207,7 @@ static void check_locks(THR_LOCK *lock, const char *where, ...@@ -205,7 +207,7 @@ static void check_locks(THR_LOCK *lock, const char *where,
{ {
if (!allow_no_locks && lock->read_wait.data) if (!allow_no_locks && lock->read_wait.data)
{ {
found_errors=1; found_errors++;
fprintf(stderr, fprintf(stderr,
"Warning at '%s': No write locks and waiting read locks\n", "Warning at '%s': No write locks and waiting read locks\n",
where); where);
...@@ -221,7 +223,7 @@ static void check_locks(THR_LOCK *lock, const char *where, ...@@ -221,7 +223,7 @@ static void check_locks(THR_LOCK *lock, const char *where,
(lock->write_wait.data->type == TL_WRITE_DELAYED && (lock->write_wait.data->type == TL_WRITE_DELAYED &&
!lock->read.data))) !lock->read.data)))
{ {
found_errors=1; found_errors++;
fprintf(stderr, fprintf(stderr,
"Warning at '%s': Write lock %d waiting while no exclusive read locks\n",where,(int) lock->write_wait.data->type); "Warning at '%s': Write lock %d waiting while no exclusive read locks\n",where,(int) lock->write_wait.data->type);
} }
...@@ -235,7 +237,7 @@ static void check_locks(THR_LOCK *lock, const char *where, ...@@ -235,7 +237,7 @@ static void check_locks(THR_LOCK *lock, const char *where,
lock->write.data->type == TL_WRITE_ALLOW_WRITE && lock->write.data->type == TL_WRITE_ALLOW_WRITE &&
lock->write_wait.data->type == TL_WRITE_ALLOW_WRITE) lock->write_wait.data->type == TL_WRITE_ALLOW_WRITE)
{ {
found_errors=1; found_errors++;
fprintf(stderr, fprintf(stderr,
"Warning at '%s': Found WRITE_ALLOW_WRITE lock waiting for WRITE_ALLOW_WRITE lock\n", "Warning at '%s': Found WRITE_ALLOW_WRITE lock waiting for WRITE_ALLOW_WRITE lock\n",
where); where);
...@@ -243,16 +245,18 @@ static void check_locks(THR_LOCK *lock, const char *where, ...@@ -243,16 +245,18 @@ static void check_locks(THR_LOCK *lock, const char *where,
} }
if (lock->read.data) if (lock->read.data)
{ {
if ((!pthread_equal(lock->write.data->thread,lock->read.data->thread) && if ((!pthread_equal(lock->write.data->thread,
lock->write.data->type > TL_WRITE_DELAYED) || lock->read.data->thread) &&
lock->write.data->type > TL_WRITE_DELAYED &&
lock->write.data->type != TL_WRITE_ONLY) ||
((lock->write.data->type == TL_WRITE_CONCURRENT_INSERT || ((lock->write.data->type == TL_WRITE_CONCURRENT_INSERT ||
lock->write.data->type == TL_WRITE_ALLOW_WRITE) && lock->write.data->type == TL_WRITE_ALLOW_WRITE) &&
lock->read_no_write_count)) lock->read_no_write_count))
{ {
found_errors=1; found_errors++;
fprintf(stderr, fprintf(stderr,
"Warning at '%s': Found lock that is write and read locked\n", "Warning at '%s': Found lock of type %d that is write and read locked\n",
where); where, lock->write.data->type);
} }
} }
if (lock->read_wait.data) if (lock->read_wait.data)
...@@ -260,7 +264,7 @@ static void check_locks(THR_LOCK *lock, const char *where, ...@@ -260,7 +264,7 @@ static void check_locks(THR_LOCK *lock, const char *where,
if (!allow_no_locks && lock->write.data->type <= TL_WRITE_DELAYED && if (!allow_no_locks && lock->write.data->type <= TL_WRITE_DELAYED &&
lock->read_wait.data->type <= TL_READ_HIGH_PRIORITY) lock->read_wait.data->type <= TL_READ_HIGH_PRIORITY)
{ {
found_errors=1; found_errors++;
fprintf(stderr, fprintf(stderr,
"Warning at '%s': Found read lock of type %d waiting for write lock of type %d\n", "Warning at '%s': Found read lock of type %d waiting for write lock of type %d\n",
where, where,
...@@ -270,7 +274,7 @@ static void check_locks(THR_LOCK *lock, const char *where, ...@@ -270,7 +274,7 @@ static void check_locks(THR_LOCK *lock, const char *where,
} }
} }
} }
if (found_errors) if (found_errors != old_found_errors)
{ {
DBUG_PRINT("error",("Found wrong lock")); DBUG_PRINT("error",("Found wrong lock"));
} }
......
...@@ -453,8 +453,10 @@ int ha_berkeley::open(const char *name, int mode, uint test_if_locked) ...@@ -453,8 +453,10 @@ int ha_berkeley::open(const char *name, int mode, uint test_if_locked)
if ((primary_key=table->primary_key) >= MAX_KEY) if ((primary_key=table->primary_key) >= MAX_KEY)
{ // No primary key { // No primary key
primary_key=table->keys; primary_key=table->keys;
key_used_on_scan=MAX_KEY;
ref_length=hidden_primary_key=BDB_HIDDEN_PRIMARY_KEY_LENGTH; ref_length=hidden_primary_key=BDB_HIDDEN_PRIMARY_KEY_LENGTH;
} }
else
key_used_on_scan=primary_key; key_used_on_scan=primary_key;
/* Need some extra memory in case of packed keys */ /* Need some extra memory in case of packed keys */
......
...@@ -1824,9 +1824,8 @@ int mysql_grant (THD *thd, const char *db, List <LEX_USER> &list, uint rights, ...@@ -1824,9 +1824,8 @@ int mysql_grant (THD *thd, const char *db, List <LEX_USER> &list, uint rights,
*Str, *Str,
(!db ? rights : 0), what))) (!db ? rights : 0), what)))
result= -1; result= -1;
if (db) if (db && replace_db_table(tables[1].table, db, *Str, rights & DB_ACLS,
if (( replace_db_table(tables[1].table, db, *Str, rights, what))
what)))
result= -1; result= -1;
} }
VOID(pthread_mutex_unlock(&acl_cache->lock)); VOID(pthread_mutex_unlock(&acl_cache->lock));
......
...@@ -554,7 +554,7 @@ pthread_handler_decl(handle_one_connection,arg) ...@@ -554,7 +554,7 @@ pthread_handler_decl(handle_one_connection,arg)
free_root(&thd->mem_root,MYF(0)); free_root(&thd->mem_root,MYF(0));
if (net->error && net->vio != 0) if (net->error && net->vio != 0)
{ {
if (!thd->killed && ! opt_warnings) if (!thd->killed && opt_warnings)
sql_print_error(ER(ER_NEW_ABORTING_CONNECTION), sql_print_error(ER(ER_NEW_ABORTING_CONNECTION),
thd->thread_id,(thd->db ? thd->db : "unconnected"), thd->thread_id,(thd->db ? thd->db : "unconnected"),
thd->user ? thd->user : "unauthenticated", thd->user ? thd->user : "unauthenticated",
......
...@@ -599,7 +599,7 @@ mysqld_show_logs(THD *thd) ...@@ -599,7 +599,7 @@ mysqld_show_logs(THD *thd)
DBUG_RETURN(1); DBUG_RETURN(1);
#ifdef HAVE_BERKELEY_DB #ifdef HAVE_BERKELEY_DB
if (berkeley_show_logs(thd)) if (!berkeley_skip && berkeley_show_logs(thd))
DBUG_RETURN(-1); DBUG_RETURN(-1);
#endif #endif
......
...@@ -6,6 +6,9 @@ ...@@ -6,6 +6,9 @@
# the last 3 does different selects on the tables. # the last 3 does different selects on the tables.
# Er, hmmm..., something like that :^) # Er, hmmm..., something like that :^)
# Modified to do crazy-join, la Nasdaq. # Modified to do crazy-join, la Nasdaq.
#
# This test uses the old obsolete mysql interface. For a test that uses
# DBI, please take a look at fork_big.pl
$opt_loop_count=10000; # Change this to make test harder/easier $opt_loop_count=10000; # Change this to make test harder/easier
...@@ -26,8 +29,8 @@ GetOptions("host=s","db=s","loop-count=i","skip-create","skip-in", ...@@ -26,8 +29,8 @@ GetOptions("host=s","db=s","loop-count=i","skip-create","skip-in",
"force") || die "Aborted"; "force") || die "Aborted";
$opt_verbose=$opt_debug=$opt_lock_tables=$opt_fast_insert=$opt_fast=$opt_skip_in=$Mysql::db_errstr=$opt_force=undef; # Ignore warnings from these $opt_verbose=$opt_debug=$opt_lock_tables=$opt_fast_insert=$opt_fast=$opt_skip_in=$Mysql::db_errstr=$opt_force=undef; # Ignore warnings from these
print "Testing 9 multiple connections to a server with 1 insert/update\n"; print "Testing 10 multiple connections to a server with 1 insert/update\n";
print "and 8 select connections.\n"; print "and 8 select connections and one ALTER TABLE.\n";
@testtables = qw(bench_f21 bench_f22 bench_f23 bench_f24 bench_f25); @testtables = qw(bench_f21 bench_f22 bench_f23 bench_f24 bench_f25);
...@@ -83,6 +86,7 @@ test_2() if (($pid=fork()) == 0); $work{$pid}="simple3"; ...@@ -83,6 +86,7 @@ test_2() if (($pid=fork()) == 0); $work{$pid}="simple3";
test_3() if (($pid=fork()) == 0); $work{$pid}="funny3"; test_3() if (($pid=fork()) == 0); $work{$pid}="funny3";
test_2() if (($pid=fork()) == 0); $work{$pid}="simple4"; test_2() if (($pid=fork()) == 0); $work{$pid}="simple4";
test_3() if (($pid=fork()) == 0); $work{$pid}="funny4"; test_3() if (($pid=fork()) == 0); $work{$pid}="funny4";
alter_test() if (($pid=fork()) == 0); $work{$pid}="alter";
$errors=0; $errors=0;
while (($pid=wait()) != -1) while (($pid=wait()) != -1)
...@@ -205,6 +209,33 @@ sub test_3 ...@@ -205,6 +209,33 @@ sub test_3
exit(0); exit(0);
} }
#
# Do an ALTER TABLE every 20 seconds
#
sub alter_test
{
my ($dbh,$count,$old_row_count,$row_count,$id,@row,$sth);
$dbh = Mysql->Connect($opt_host, $opt_db) || die $Mysql::db_errstr;
$id=$count=$row_count=0; $old_row_count= -1;
# Execute the test as long as we get more data into the table
while ($row_count != $old_row_count)
{
sleep(10);
$sth=$dbh->Query("ALTER TABLE $testtables[$id] modify info varchar(32)") or die "Couldn't execute ALTER TABLE\n";
$sth=0;
$id=($id+1) % $numtables;
# Test if insert test has ended
$sth=$dbh->query("select count(*) from $testtables[0]") or die "Couldn't execute count(*)\n";
@row = $sth->FetchRow();
$old_row_count= $row_count;
$row_count=$row[0];
$count++;
}
$dbh=0;
print "alter: Executed $count ALTER TABLE commands\n";
exit(0);
}
...@@ -23,7 +23,7 @@ GetOptions("host=s","db=s","user=s","password=s","loop-count=i","skip-create","s ...@@ -23,7 +23,7 @@ GetOptions("host=s","db=s","user=s","password=s","loop-count=i","skip-create","s
$opt_verbose=$opt_debug=$opt_lock_tables=$opt_fast_insert=$opt_fast=$opt_skip_in=$opt_force=undef; # Ignore warnings from these $opt_verbose=$opt_debug=$opt_lock_tables=$opt_fast_insert=$opt_fast=$opt_skip_in=$opt_force=undef; # Ignore warnings from these
print "Test of multiple connections that test the following things:\n"; print "Test of multiple connections that test the following things:\n";
print "insert, select, delete, update, check, repair and flush\n"; print "insert, select, delete, update, alter, check, repair and flush\n";
@testtables = ( ["bench_f31", ""], @testtables = ( ["bench_f31", ""],
["bench_f32", "row_format=fixed"], ["bench_f32", "row_format=fixed"],
...@@ -34,6 +34,7 @@ $abort_table="bench_f39"; ...@@ -34,6 +34,7 @@ $abort_table="bench_f39";
$numtables = $#testtables+1; $numtables = $#testtables+1;
srand 100; # Make random numbers repeatable srand 100; # Make random numbers repeatable
#### ####
#### Start timeing and start test #### Start timeing and start test
#### ####
...@@ -88,12 +89,14 @@ for ($i=0 ; $i < $opt_threads ; $i ++) ...@@ -88,12 +89,14 @@ for ($i=0 ; $i < $opt_threads ; $i ++)
{ {
test_select() if (($pid=fork()) == 0); $work{$pid}="select_key"; test_select() if (($pid=fork()) == 0); $work{$pid}="select_key";
} }
test_join() if (($pid=fork()) == 0); $work{$pid}="test_join";
test_select_count() if (($pid=fork()) == 0); $work{$pid}="select_count"; test_select_count() if (($pid=fork()) == 0); $work{$pid}="select_count";
test_delete() if (($pid=fork()) == 0); $work{$pid}="delete"; test_delete() if (($pid=fork()) == 0); $work{$pid}="delete";
test_update() if (($pid=fork()) == 0); $work{$pid}="update"; test_update() if (($pid=fork()) == 0); $work{$pid}="update";
test_flush() if (($pid=fork()) == 0); $work{$pid}= "flush"; test_flush() if (($pid=fork()) == 0); $work{$pid}= "flush";
test_check() if (($pid=fork()) == 0); $work{$pid}="check"; test_check() if (($pid=fork()) == 0); $work{$pid}="check";
test_repair() if (($pid=fork()) == 0); $work{$pid}="repair"; test_repair() if (($pid=fork()) == 0); $work{$pid}="repair";
test_alter() if (($pid=fork()) == 0); $work{$pid}="alter";
#test_database("test2") if (($pid=fork()) == 0); $work{$pid}="check_database"; #test_database("test2") if (($pid=fork()) == 0); $work{$pid}="check_database";
print "Started " . ($opt_threads*2+4) . " threads\n"; print "Started " . ($opt_threads*2+4) . " threads\n";
...@@ -243,6 +246,44 @@ sub test_select_count ...@@ -243,6 +246,44 @@ sub test_select_count
exit(0); exit(0);
} }
#
# select records
# Do continously joins between the first and second table
#
sub test_join
{
my ($dbh, $i, $j, $count, $loop);
$dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
$opt_user, $opt_password,
{ PrintError => 0}) || die $DBI::errstr;
$count_query=make_count_query($numtables);
$count=0;
$loop=9999;
$i=0;
while (($i++ % 100) || !test_if_abort($dbh))
{
if ($loop++ >= 100)
{
$loop=0;
$row_counts=simple_query($dbh, $count_query);
}
for ($j=0 ; $j < $numtables-1 ; $j++)
{
my ($id)= int rand $row_counts->[$j];
my ($t1,$t2)= ($testtables[$j]->[0],$testtables[$j+1]->[0]);
simple_query($dbh, "select $t1.id,$t2.info from $t1, $t2 where $t1.id=$t2.id and $t1.id=$id");
$count++;
}
}
$dbh->disconnect; $dbh=0;
print "Test_join: Executed $count joins\n";
exit(0);
}
# #
# Delete 1-5 rows from the first 2 tables. # Delete 1-5 rows from the first 2 tables.
# Test ends when the number of rows for table 3 didn't change during # Test ends when the number of rows for table 3 didn't change during
...@@ -457,6 +498,29 @@ sub test_database ...@@ -457,6 +498,29 @@ sub test_database
exit(0); exit(0);
} }
#
# Test ALTER TABLE on the second table
#
sub test_alter
{
my ($dbh, $row, $i, $type, $table);
$dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
$opt_user, $opt_password,
{ PrintError => 0}) || die $DBI::errstr;
for ($i=0 ; !test_if_abort($dbh) ; $i++)
{
sleep(100);
$table=$testtables[1]->[0];
$sth=$dbh->prepare("ALTER table $table modify info char(32)") || die "Got error on prepare: $DBI::errstr\n";
$sth->execute || die $DBI::errstr;
}
$dbh->disconnect; $dbh=0;
print "test_alter: Executed $i ALTER TABLE\n";
exit(0);
}
# #
# Help functions # Help functions
...@@ -507,8 +571,8 @@ sub simple_query() ...@@ -507,8 +571,8 @@ sub simple_query()
my ($dbh, $query)= @_; my ($dbh, $query)= @_;
my ($sth,$row); my ($sth,$row);
$sth=$dbh->prepare($query) || die "Got error on '$query': $DBI::errstr\n"; $sth=$dbh->prepare($query) || die "Got error on '$query': " . $dbh->errstr . "\n";
$sth->execute || die "Got error on '$query': $dbh->errstr\n"; $sth->execute || die "Got error on '$query': " . $dbh->errstr . "\n";
$row= $sth->fetchrow_arrayref(); $row= $sth->fetchrow_arrayref();
$sth=0; $sth=0;
return $row; return $row;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment