summaryrefslogtreecommitdiff
path: root/ndb
diff options
context:
space:
mode:
authortomas@poseidon.ndb.mysql.com <>2005-10-07 01:12:46 +0200
committertomas@poseidon.ndb.mysql.com <>2005-10-07 01:12:46 +0200
commite72fdf56194b529b14696bbb0b743e25eefb7f0e (patch)
tree73ff186be5c6524a0a96e1d6359b8f58263b7a4c /ndb
parent3703570c9c8a1040ad66dc4d933dcaa9a0e767b4 (diff)
parent38fd830f9e7fc4f239a5a3acb40354cc49e7b5e9 (diff)
downloadmariadb-git-e72fdf56194b529b14696bbb0b743e25eefb7f0e.tar.gz
Merge
Diffstat (limited to 'ndb')
-rw-r--r--ndb/include/mgmapi/ndbd_exit_codes.h156
-rw-r--r--ndb/src/kernel/error/ndbd_exit_codes.c251
-rw-r--r--ndb/src/kernel/vm/ndbd_malloc.cpp63
-rw-r--r--ndb/src/kernel/vm/ndbd_malloc.hpp26
-rw-r--r--ndb/test/sql/test_create_drop.pl179
-rw-r--r--ndb/test/sql/test_range_bounds.pl218
6 files changed, 893 insertions, 0 deletions
diff --git a/ndb/include/mgmapi/ndbd_exit_codes.h b/ndb/include/mgmapi/ndbd_exit_codes.h
new file mode 100644
index 00000000000..794329ce637
--- /dev/null
+++ b/ndb/include/mgmapi/ndbd_exit_codes.h
@@ -0,0 +1,156 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef NDBD_EXIT_CODES_H
+#define NDBD_EXIT_CODES_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+
+/**
+ * Exit error codes for NDBD
+ *
+ * These errorcodes should be used whenever a condition
+ * is detected where it's necesssary to shutdown NDB.
+ *
+ * Example: When another node fails while a NDB node are performing
+ * a system restart the node should be shutdown. This
+ * is kind of an error but the cause of the error is known
+ * and a proper errormessage describing the problem should
+ * be printed in error.log. It's therefore important to use
+ * the proper errorcode.
+ *
+ */
+
+typedef enum
+{
+ ndbd_exit_st_success = 0,
+ ndbd_exit_st_unknown = 1,
+ ndbd_exit_st_permanent = 2,
+ ndbd_exit_st_temporary = 3,
+ ndbd_exit_st_filesystem_error = 4
+} ndbd_exit_status_enum;
+
+typedef enum
+{
+ ndbd_exit_cl_none = 0,
+ ndbd_exit_cl_unknown = 1,
+ ndbd_exit_cl_internal_error = 2,
+ ndbd_exit_cl_configuration_error = 3,
+ ndbd_exit_cl_arbitration_error = 4,
+ ndbd_exit_cl_restart_error = 5,
+ ndbd_exit_cl_resource_configuration_error = 6,
+ ndbd_exit_cl_filesystem_full_error = 7,
+ ndbd_exit_cl_filesystem_inconsistency_error = 8,
+ ndbd_exit_cl_filesystem_limit = 9
+} ndbd_exit_classification_enum;
+
+typedef ndbd_exit_status_enum ndbd_exit_status;
+typedef ndbd_exit_classification_enum ndbd_exit_classification;
+
+/* Errorcodes before block division was used */
+#define NDBD_EXIT_PRGERR 2301
+#define NDBD_EXIT_NODE_NOT_IN_CONFIG 2302
+#define NDBD_EXIT_SYSTEM_ERROR 2303
+#define NDBD_EXIT_INDEX_NOTINRANGE 2304
+#define NDBD_EXIT_ARBIT_SHUTDOWN 2305
+#define NDBD_EXIT_POINTER_NOTINRANGE 2306
+#define NDBD_EXIT_SR_OTHERNODEFAILED 2308
+#define NDBD_EXIT_NODE_NOT_DEAD 2309
+#define NDBD_EXIT_SR_REDOLOG 2310
+/*
+#define NDBD_EXIT_SR_RESTARTCONFLICT 2311
+*/
+#define NDBD_EXIT_NO_MORE_UNDOLOG 2312
+#define NDBD_EXIT_SR_UNDOLOG 2313
+#define NDBD_EXIT_MEMALLOC 2327
+#define NDBD_EXIT_BLOCK_JBUFCONGESTION 2334
+#define NDBD_EXIT_TIME_QUEUE_SHORT 2335
+#define NDBD_EXIT_TIME_QUEUE_LONG 2336
+#define NDBD_EXIT_TIME_QUEUE_DELAY 2337
+#define NDBD_EXIT_TIME_QUEUE_INDEX 2338
+#define NDBD_EXIT_BLOCK_BNR_ZERO 2339
+#define NDBD_EXIT_WRONG_PRIO_LEVEL 2340
+#define NDBD_EXIT_NDBREQUIRE 2341
+#define NDBD_EXIT_ERROR_INSERT 2342
+#define NDBD_EXIT_NDBASSERT 2343
+#define NDBD_EXIT_INVALID_CONFIG 2350
+#define NDBD_EXIT_OUT_OF_LONG_SIGNAL_MEMORY 2351
+
+#define NDBD_EXIT_OS_SIGNAL_RECEIVED 6000
+
+/* VM 6050-> */
+#define NDBD_EXIT_WATCHDOG_TERMINATE 6050
+#define NDBD_EXIT_SIGNAL_LOST 6051
+#define NDBD_EXIT_SIGNAL_LOST_SEND_BUFFER_FULL 6052
+#define NDBD_EXIT_ILLEGAL_SIGNAL 6053
+
+/* NDBCNTR 6100-> */
+#define NDBD_EXIT_RESTART_TIMEOUT 6100
+
+/* TC 6200-> */
+/* DIH 6300-> */
+#define NDBD_EXIT_MAX_CRASHED_REPLICAS 6300
+#define NDBD_EXIT_MASTER_FAILURE_DURING_NR 6301
+#define NDBD_EXIT_LOST_NODE_GROUP 6302
+#define NDBD_EXIT_NO_RESTORABLE_REPLICA 6303
+
+/* ACC 6600-> */
+#define NDBD_EXIT_SR_OUT_OF_INDEXMEMORY 6600
+/* TUP 6800-> */
+#define NDBD_EXIT_SR_OUT_OF_DATAMEMORY 6800
+/* LQH 7200-> */
+
+
+/* Errorcodes for NDB filesystem */
+#define NDBD_EXIT_AFS_NOPATH 2801
+/*
+#define NDBD_EXIT_AFS_CHANNALFULL 2802
+#define NDBD_EXIT_AFS_NOMORETHREADS 2803
+*/
+#define NDBD_EXIT_AFS_PARAMETER 2804
+#define NDBD_EXIT_AFS_INVALIDPATH 2805
+#define NDBD_EXIT_AFS_MAXOPEN 2806
+#define NDBD_EXIT_AFS_ALREADY_OPEN 2807
+
+#define NDBD_EXIT_AFS_ENVIRONMENT 2808
+#define NDBD_EXIT_AFS_TEMP_NO_ACCESS 2809
+#define NDBD_EXIT_AFS_DISK_FULL 2810
+#define NDBD_EXIT_AFS_PERMISSION_DENIED 2811
+#define NDBD_EXIT_AFS_INVALID_PARAM 2812
+#define NDBD_EXIT_AFS_UNKNOWN 2813
+#define NDBD_EXIT_AFS_NO_MORE_RESOURCES 2814
+#define NDBD_EXIT_AFS_NO_SUCH_FILE 2815
+#define NDBD_EXIT_AFS_READ_UNDERFLOW 2816
+
+const char *
+ndbd_exit_message(int faultId, ndbd_exit_classification *cl);
+const char *
+ndbd_exit_classification_message(ndbd_exit_classification classification,
+ ndbd_exit_status *status);
+const char *
+ndbd_exit_status_message(ndbd_exit_status status);
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* NDBD_EXIT_CODES_H */
diff --git a/ndb/src/kernel/error/ndbd_exit_codes.c b/ndb/src/kernel/error/ndbd_exit_codes.c
new file mode 100644
index 00000000000..4d9a61d69d1
--- /dev/null
+++ b/ndb/src/kernel/error/ndbd_exit_codes.c
@@ -0,0 +1,251 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <ndbd_exit_codes.h>
+
+typedef struct ErrStruct {
+ int faultId;
+ ndbd_exit_classification classification;
+ const char* text;
+} ErrStruct;
+
+/**
+ * Shorter names in table below
+ */
+
+#define XST_S ndbd_exit_st_success
+#define XST_U ndbd_exit_st_unknown
+#define XST_P ndbd_exit_st_permanent
+#define XST_R ndbd_exit_st_temporary
+#define XST_I ndbd_exit_st_filesystem_error
+
+#define XNE ndbd_exit_cl_none
+#define XUE ndbd_exit_cl_unknown
+#define XIE ndbd_exit_cl_internal_error
+#define XCE ndbd_exit_cl_configuration_error
+#define XAE ndbd_exit_cl_arbitration_error
+#define XRE ndbd_exit_cl_restart_error
+#define XCR ndbd_exit_cl_resource_configuration_error
+#define XFF ndbd_exit_cl_filesystem_full_error
+#define XFI ndbd_exit_cl_filesystem_inconsistency_error
+#define XFL ndbd_exit_cl_filesystem_limit
+
+static const ErrStruct errArray[] =
+{
+ {NDBD_EXIT_PRGERR, XIE, "Assertion"},
+ {NDBD_EXIT_NODE_NOT_IN_CONFIG, XCE,
+ "node id in the configuration has the wrong type, (i.e. not an NDB node)"},
+ {NDBD_EXIT_SYSTEM_ERROR, XIE,
+ "System error, node killed during node restart by other node"},
+ {NDBD_EXIT_INDEX_NOTINRANGE, XIE, "Array index out of range"},
+ {NDBD_EXIT_ARBIT_SHUTDOWN, XAE, "Arbitrator shutdown, "
+ "please investigate error(s) on other node(s)"},
+ {NDBD_EXIT_POINTER_NOTINRANGE, XIE, "Pointer too large"},
+ {NDBD_EXIT_SR_OTHERNODEFAILED, XRE, "Another node failed during system "
+ "restart, please investigate error(s) on other node(s)"},
+ {NDBD_EXIT_NODE_NOT_DEAD, XRE, "Internal node state conflict, "
+ "most probably resolved by restarting node again"},
+ {NDBD_EXIT_SR_REDOLOG, XFI, "Error while reading the REDO log"},
+ /* Currently unused? */
+ {2311, XIE, "Conflict when selecting restart type"},
+ {NDBD_EXIT_NO_MORE_UNDOLOG, XCR,
+ "No more free UNDO log, increase UndoIndexBuffer"},
+ {NDBD_EXIT_SR_UNDOLOG, XFI,
+ "Error while reading the datapages and UNDO log"},
+ {NDBD_EXIT_MEMALLOC, XCE, "Memory allocation failure, "
+ "please decrease some configuration parameters"},
+ {NDBD_EXIT_BLOCK_JBUFCONGESTION, XIE, "Job buffer congestion"},
+ {NDBD_EXIT_TIME_QUEUE_SHORT, XIE, "Error in short time queue"},
+ {NDBD_EXIT_TIME_QUEUE_LONG, XIE, "Error in long time queue"},
+ {NDBD_EXIT_TIME_QUEUE_DELAY, XIE, "Error in time queue, too long delay"},
+ {NDBD_EXIT_TIME_QUEUE_INDEX, XIE, "Time queue index out of range"},
+ {NDBD_EXIT_BLOCK_BNR_ZERO, XIE, "Send signal error"},
+ {NDBD_EXIT_WRONG_PRIO_LEVEL, XIE, "Wrong priority level when sending signal"},
+ {NDBD_EXIT_NDBREQUIRE, XIE, "Internal program error (failed ndbrequire)"},
+ {NDBD_EXIT_NDBASSERT, XIE, "Internal program error (failed ndbassert)"},
+ {NDBD_EXIT_ERROR_INSERT, XNE, "Error insert executed" },
+ /* this error message is complemented by additional info when generated */
+ {NDBD_EXIT_INVALID_CONFIG, XCE,
+ "Invalid configuration received from Management Server"},
+ /* this error message is complemented by additional info when
+ generated, such as signal, and text
+ */
+ {NDBD_EXIT_OS_SIGNAL_RECEIVED, XIE, "Error OS signal received"},
+
+ /* VM */
+ {NDBD_EXIT_OUT_OF_LONG_SIGNAL_MEMORY, XCR,
+ "Signal lost, out of long signal memory, please increase LongMessageBuffer"},
+ {NDBD_EXIT_WATCHDOG_TERMINATE, XIE, "WatchDog terminate, internal error "
+ "or massive overload on the machine running this node"},
+ {NDBD_EXIT_SIGNAL_LOST_SEND_BUFFER_FULL, XCR,
+ "Signal lost, out of send buffer memory, please increase SendBufferMemory"},
+ {NDBD_EXIT_SIGNAL_LOST, XIE, "Signal lost (unknown reason)"},
+ {NDBD_EXIT_ILLEGAL_SIGNAL, XIE,
+ "Illegal signal (version mismatch a possibility)"},
+
+ /* Ndbcntr */
+ {NDBD_EXIT_RESTART_TIMEOUT, XCE,
+ "Total restart time too long, consider increasing StartFailureTimeout "
+ "or investigate error(s) on other node(s)"},
+
+ /* DIH */
+ {NDBD_EXIT_MAX_CRASHED_REPLICAS, XFL,
+ "Too many crashed replicas (8 consecutive node restart failures)"},
+ {NDBD_EXIT_MASTER_FAILURE_DURING_NR, XRE,
+ "Unhandled master failure during node restart"},
+ {NDBD_EXIT_LOST_NODE_GROUP, XAE,
+ "All nodes in a node group are unavailable"},
+ {NDBD_EXIT_NO_RESTORABLE_REPLICA, XFI,
+ "Unable to find a restorable replica"},
+
+ /* ACC */
+ {NDBD_EXIT_SR_OUT_OF_INDEXMEMORY, XCR,
+ "Out of index memory during system restart, please increase IndexMemory"},
+
+ /* TUP */
+ {NDBD_EXIT_SR_OUT_OF_DATAMEMORY, XCR,
+ "Out of data memory during system restart, please increase DataMemory"},
+
+ /* Ndbfs error messages */
+ /* Most codes will have additional info, such as OS error code */
+ {NDBD_EXIT_AFS_NOPATH, XIE, "No file system path"},
+ {2802, XIE, "Channel is full"},
+ {2803, XIE, "No more threads"},
+ {NDBD_EXIT_AFS_PARAMETER, XIE, "Bad parameter"},
+ {NDBD_EXIT_AFS_INVALIDPATH, XCE, "Illegal file system path"},
+ {NDBD_EXIT_AFS_MAXOPEN, XCR,
+ "Max number of open files exceeded, please increase MaxNoOfOpenFiles"},
+ {NDBD_EXIT_AFS_ALREADY_OPEN, XIE, "File has already been opened"},
+
+ {NDBD_EXIT_AFS_ENVIRONMENT , XIE, "Environment error using file"},
+ {NDBD_EXIT_AFS_TEMP_NO_ACCESS , XIE, "Temporary on access to file"},
+ {NDBD_EXIT_AFS_DISK_FULL , XFF, "The file system is full"},
+ {NDBD_EXIT_AFS_PERMISSION_DENIED , XCE, "Received permission denied for file"},
+ {NDBD_EXIT_AFS_INVALID_PARAM , XCE, "Invalid parameter for file"},
+ {NDBD_EXIT_AFS_UNKNOWN , XIE, "Unknown file system error"},
+ {NDBD_EXIT_AFS_NO_MORE_RESOURCES , XIE,
+ "System reports no more file system resources"},
+ {NDBD_EXIT_AFS_NO_SUCH_FILE , XFI, "File not found"},
+ {NDBD_EXIT_AFS_READ_UNDERFLOW , XFI, "Read underflow"},
+
+ /* Sentinel */
+ {0, XUE,
+ "No message slogan found (please report a bug if you get this error code)"}
+};
+
+typedef struct StatusExitMessage {
+ ndbd_exit_status status;
+ const char * message;
+} StatusExitMessage;
+
+typedef struct StatusExitClassification {
+ ndbd_exit_status status;
+ ndbd_exit_classification classification;
+ const char * message;
+} StatusExitClassification;
+
+/**
+ * Mapping between classification and status
+ */
+static
+const
+StatusExitMessage StatusExitMessageMapping[] = {
+ { XST_S, "Success"},
+ { XST_U ,"Unknown"},
+ { XST_P, "Permanent error, external action needed"},
+ { XST_R, "Temporary error, restart node"},
+ { XST_I, "Ndbd file system error, restart node initial"}
+};
+
+static
+const
+int NbExitStatus = sizeof(StatusExitMessageMapping)/sizeof(StatusExitMessage);
+
+static
+const
+StatusExitClassification StatusExitClassificationMapping[] = {
+ { XST_S, XNE, "No error"},
+ { XST_U, XUE, "Unknown"},
+ { XST_R, XIE, "Internal error, programming error or missing error message, "
+ "please report a bug"},
+ { XST_P, XCE, "Configuration error"},
+ { XST_R, XAE, "Arbitration error"},
+ { XST_R, XRE, "Restart error"},
+ { XST_P, XCR, "Resource configuration error"},
+ { XST_P, XFF, "File system full"},
+ { XST_I, XFI, "Ndbd file system inconsistency error, please report a bug"},
+ { XST_I, XFL, "Ndbd file system limit exceeded"}
+};
+
+static const int NbExitClassification =
+sizeof(StatusExitClassificationMapping)/sizeof(StatusExitClassification);
+
+const char *ndbd_exit_message(int faultId, ndbd_exit_classification *cl)
+{
+ int i = 0;
+ while (errArray[i].faultId != faultId && errArray[i].faultId != 0)
+ i++;
+ *cl = errArray[i].classification;
+ return errArray[i].text;
+}
+
+static const char* empty_xstring = "";
+
+const
+char *ndbd_exit_classification_message(ndbd_exit_classification classification,
+ ndbd_exit_status *status)
+{
+ int i;
+ for (i= 0; i < NbExitClassification; i++)
+ {
+ if (StatusExitClassificationMapping[i].classification == classification)
+ {
+ *status = StatusExitClassificationMapping[i].status;
+ return StatusExitClassificationMapping[i].message;
+ }
+ }
+ *status = XST_U;
+ return empty_xstring;
+}
+
+const char *ndbd_exit_status_message(ndbd_exit_status status)
+{
+ int i;
+ for (i= 0; i < NbExitStatus; i++)
+ if (StatusExitMessageMapping[i].status == status)
+ return StatusExitMessageMapping[i].message;
+ return empty_xstring;
+}
+
+int ndbd_exit_string(int err_no, char *str, unsigned int size)
+{
+ unsigned int len;
+
+ ndbd_exit_classification cl;
+ ndbd_exit_status st;
+ const char *msg = ndbd_exit_message(err_no, &cl);
+ if (msg[0] != '\0')
+ {
+ const char *cl_msg = ndbd_exit_classification_message(cl, &st);
+ const char *st_msg = ndbd_exit_status_message(st);
+
+ len = my_snprintf(str, size-1, "%s: %s: %s", msg, st_msg, cl_msg);
+ str[size-1]= '\0';
+
+ return len;
+ }
+ return -1;
+}
diff --git a/ndb/src/kernel/vm/ndbd_malloc.cpp b/ndb/src/kernel/vm/ndbd_malloc.cpp
new file mode 100644
index 00000000000..4bfccf828fc
--- /dev/null
+++ b/ndb/src/kernel/vm/ndbd_malloc.cpp
@@ -0,0 +1,63 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <ndb_global.h>
+#include "ndbd_malloc.hpp"
+#include <NdbMem.h>
+
+//#define TRACE_MALLOC
+#ifdef TRACE_MALLOC
+#include <stdio.h>
+#endif
+
+static void xxx(size_t size, size_t *s_m, size_t *s_k, size_t *s_b)
+{
+ *s_m = size/1024/1024;
+ *s_k = (size - *s_m*1024*1024)/1024;
+ *s_b = size - *s_m*1024*1024-*s_k*1024;
+}
+
+static Uint64 g_allocated_memory;
+void *ndbd_malloc(size_t size)
+{
+ void *p = NdbMem_Allocate(size);
+ if (p)
+ {
+ g_allocated_memory += size;
+#ifdef TRACE_MALLOC
+ {
+ size_t s_m, s_k, s_b;
+ xxx(size, &s_m, &s_k, &s_b);
+ fprintf(stderr, "%p malloc(%um %uk %ub)", p, s_m, s_k, s_b);
+ xxx(g_allocated_memory, &s_m, &s_k, &s_b);
+ fprintf(stderr, "\t\ttotal(%um %uk %ub)\n", s_m, s_k, s_b);
+ }
+#endif
+ }
+ return p;
+}
+
+void ndbd_free(void *p, size_t size)
+{
+ NdbMem_Free(p);
+ if (p)
+ {
+ g_allocated_memory -= size;
+#ifdef TRACE_MALLOC
+ fprintf(stderr, "%p free(%d)\n", p, size);
+#endif
+ }
+}
diff --git a/ndb/src/kernel/vm/ndbd_malloc.hpp b/ndb/src/kernel/vm/ndbd_malloc.hpp
new file mode 100644
index 00000000000..136e9f0c372
--- /dev/null
+++ b/ndb/src/kernel/vm/ndbd_malloc.hpp
@@ -0,0 +1,26 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef NDBD_MALLOC_H
+#define NDBD_MALLOC_H
+
+/**
+ * common memory allocation function for ndbd kernel
+ */
+void *ndbd_malloc(size_t size);
+void ndbd_free(void *p, size_t size);
+
+#endif
diff --git a/ndb/test/sql/test_create_drop.pl b/ndb/test/sql/test_create_drop.pl
new file mode 100644
index 00000000000..7f62898b3d1
--- /dev/null
+++ b/ndb/test/sql/test_create_drop.pl
@@ -0,0 +1,179 @@
+use strict;
+use IO::Socket;
+use DBI;
+
+# mgm info
+my $mgmhost = "localhost";
+my $mgmport = 38101;
+
+# location of ndb_x_fs
+my $datadir = "c2";
+my @schemafiles = <$datadir/ndb_*_fs/D[12]/DBDICT/P0.SchemaLog>;
+@schemafiles or die "no schemafiles in $datadir";
+
+my $dsn;
+$dsn = "dbi:mysql:test:localhost;port=38100";
+
+# this works better for me
+my $cnf = $ENV{MYSQL_HOME} . "/var/my.cnf";
+$dsn = "dbi:mysql:database=test;host=localhost;mysql_read_default_file=$cnf";
+
+my $dbh;
+$dbh = DBI->connect($dsn, 'root', undef, { RaiseError => 0, PrintError => 0 });
+$dbh or die $DBI::errstr;
+
+# mgm commands
+
+my $mgm = undef;
+
+sub mgmconnect {
+ $mgm = IO::Socket::INET->new(
+ Proto => "tcp",
+ PeerHost => $mgmhost,
+ PeerPort => $mgmport);
+ $mgm or die "connect to mgm failed: $!";
+ $mgm->autoflush(1);
+};
+
+mgmconnect();
+warn "connected to mgm $mgmhost $mgmport\n";
+
+my $nodeinfo = {};
+
+sub getnodeinfo {
+ $nodeinfo = {};
+ $mgm->print("get status\n");
+ $mgm->print("\n");
+ while (defined($_ = $mgm->getline)) {
+ /^node\s+status/ && last;
+ }
+ while (defined($_ = $mgm->getline)) {
+ /^\s*$/ && last;
+ /^node\.(\d+)\.(\w+):\s*(\S+)/ && ($nodeinfo->{$1}{$2} = $3);
+ }
+}
+
+getnodeinfo();
+
+my @dbnode = ();
+for my $n (keys %$nodeinfo) {
+ my $p = $nodeinfo->{$n};
+ ($p->{type} eq 'NDB') && push(@dbnode, $n);
+}
+@dbnode = sort { $a <=> $b } @dbnode;
+@dbnode or die "mgm error, found no db nodes";
+warn "db nodes: @dbnode\n";
+
+sub restartnode {
+ my($n, $initialstart) = @_;
+ warn "restart node $n initialstart=$initialstart\n";
+ $mgm->print("restart node\n");
+ $mgm->print("node: $n\n");
+ $mgm->print("initialstart: $initialstart\n");
+ $mgm->print("\n");
+ while (1) {
+ sleep 5;
+ getnodeinfo();
+ my $status = $nodeinfo->{$n}{status};
+ my $sp = $nodeinfo->{$n}{startphase};
+ warn "node $n status: $status sp: $sp\n";
+ last if $status eq 'STARTED';
+ }
+}
+
+sub restartall {
+ warn "restart all\n";
+ $mgm->print("restart all\n");
+ $mgm->print("\n");
+ while (1) {
+ sleep 5;
+ getnodeinfo();
+ my $ok = 1;
+ for my $n (@dbnode) {
+ my $status = $nodeinfo->{$n}{status};
+ my $sp = $nodeinfo->{$n}{startphase};
+ warn "node $n status: $status sp: $sp\n";
+ $ok = 0 if $status ne 'STARTED';
+ }
+ last if $ok;
+ }
+}
+
+# the sql stuff
+
+my $maxtab = 300;
+my @tab = ();
+
+sub create {
+ my($n) = @_;
+ my $sql = "create table t$n (a int primary key, b varchar(20), key (b)) engine=ndb";
+ warn "create t$n\n";
+ $dbh->do($sql) or die "$sql\n$DBI::errstr";
+}
+
+sub drop {
+ my($n) = @_;
+ my $sql = "drop table t$n";
+ warn "drop t$n\n";
+ $dbh->do($sql) or die "$sql\n$DBI::errstr";
+}
+
+sub dropall {
+ for my $n (0..($maxtab-1)) {
+ my $sql = "drop table if exists t$n";
+ $dbh->do($sql) or die "$sql\n$DBI::errstr";
+ }
+}
+
+sub createdrop {
+ my $n = int(rand($maxtab));
+ if (! $tab[$n]) {
+ create($n);
+ $tab[$n] = 1;
+ } else {
+ drop($n);
+ $tab[$n] = 0;
+ }
+}
+
+sub checkschemafiles {
+ system("printSchemaFile -ce @schemafiles");
+ $? == 0 or die "schemafiles check failed";
+}
+
+sub randomrestart {
+ my($k) = @_;
+ my $s = int(rand(500));
+ if ($s < 2) {
+ my $i = $k % scalar(@dbnode);
+ my $n = $dbnode[$i];
+ my $initialstart = ($s < 1 ? 0 : 1);
+ restartnode($n, $initialstart);
+ return 1;
+ }
+ if ($s < 3) {
+ restartall();
+ return 1;
+ }
+ return 0;
+}
+
+# deterministic
+srand(1);
+
+warn "drop any old tables\n";
+dropall();
+
+my $loop = 1000000;
+for my $k (0..($loop-1)) {
+ warn "$k\n";
+ createdrop();
+ checkschemafiles();
+ if (randomrestart($k)) {
+ checkschemafiles();
+ }
+}
+
+$dbh->disconnect or die $DBI::errstr;
+
+# vim: set sw=2:
diff --git a/ndb/test/sql/test_range_bounds.pl b/ndb/test/sql/test_range_bounds.pl
new file mode 100644
index 00000000000..abe1ea28298
--- /dev/null
+++ b/ndb/test/sql/test_range_bounds.pl
@@ -0,0 +1,218 @@
+#
+# test range scan bounds
+# give option --all to test all cases
+# set MYSQL_HOME to installation top
+#
+
+use strict;
+use integer;
+use Getopt::Long;
+use DBI;
+
+my $opt_all = 0;
+my $opt_cnt = 5;
+my $opt_verbose = 0;
+GetOptions("all" => \$opt_all, "cnt=i" => \$opt_cnt, "verbose" => \$opt_verbose)
+ or die "options are: --all --cnt=N --verbose";
+
+my $mysql_home = $ENV{MYSQL_HOME};
+defined($mysql_home) or die "no MYSQL_HOME";
+my $dsn = "dbi:mysql:database=test;host=localhost;mysql_read_default_file=$mysql_home/var/my.cnf";
+my $opts = { RaiseError => 0, PrintError => 0, AutoCommit => 1, };
+
+my $dbh;
+my $sth;
+my $sql;
+
+$dbh = DBI->connect($dsn, "root", undef, $opts) or die $DBI::errstr;
+
+my $table = 't';
+
+$sql = "drop table if exists $table";
+$dbh->do($sql) or die $DBI::errstr;
+
+sub cut ($$$) {
+ my($op, $key, $val) = @_;
+ $op = '==' if $op eq '=';
+ my(@w) = @$val;
+ eval "\@w = grep(\$_ $op $key, \@w)";
+ $@ and die $@;
+ return [ @w ];
+}
+
+sub mkdummy ($) {
+ my ($val) = @_;
+ return {
+ 'dummy' => 1,
+ 'exp' => '9 = 9',
+ 'res' => $val,
+ };
+}
+
+sub mkone ($$$$) {
+ my($col, $op, $key, $val) = @_;
+ my $res = cut($op, $key, $val);
+ return {
+ 'exp' => "$col $op $key",
+ 'res' => $res,
+ };
+}
+
+sub mktwo ($$$$$$) {
+ my($col, $op1, $key1, $op2, $key2, $val) = @_;
+ my $res = cut($op2, $key2, cut($op1, $key1, $val));
+ return {
+ 'exp' => "$col $op1 $key1 and $col $op2 $key2",
+ 'res' => $res,
+ };
+}
+
+sub mkall ($$$$) {
+ my($col, $key1, $key2, $val) = @_;
+ my @a = ();
+ my $p = mkdummy($val);
+ push(@a, $p) if $opt_all;
+ my @ops = qw(< <= = >= >);
+ for my $op (@ops) {
+ my $p = mkone($col, $op, $key1, $val);
+ push(@a, $p) if $opt_all || @{$p->{res}} != 0;
+ }
+ my @ops1 = $opt_all ? @ops : qw(= >= >);
+ my @ops2 = $opt_all ? @ops : qw(<= <);
+ for my $op1 (@ops1) {
+ for my $op2 (@ops2) {
+ my $p = mktwo($col, $op1, $key1, $op2, $key2, $val);
+ push(@a, $p) if $opt_all || @{$p->{res}} != 0;
+ }
+ }
+ warn scalar(@a)." cases\n" if $opt_verbose;
+ return \@a;
+}
+
+my $casecnt = 0;
+
+sub verify ($$$) {
+ my($sql, $ord, $res) = @_;
+ warn "$sql\n" if $opt_verbose;
+ $sth = $dbh->prepare($sql) or die "prepare: $sql: $DBI::errstr";
+ $sth->execute() or die "execute: $sql: $DBI::errstr";
+ #
+ # BUG: execute can return success on error so check again
+ #
+ $sth->err and die "execute: $sql: $DBI::errstr";
+ my @out = ();
+ for my $b (@{$res->[0]}) {
+ for my $c (@{$res->[1]}) {
+ for my $d (@{$res->[2]}) {
+ push(@out, [$b, $c, $d]);
+ }
+ }
+ }
+ if ($ord) {
+ @out = sort {
+ $ord * ($a->[0] - $b->[0]) ||
+ $ord * ($a->[1] - $b->[1]) ||
+ $ord * ($a->[2] - $b->[2]) ||
+ 0
+ } @out;
+ }
+ my $cnt = scalar @out;
+ my $n = 0;
+ while (1) {
+ my $row = $sth->fetchrow_arrayref;
+ $row || last;
+ @$row == 3 or die "bad row: $sql: @$row";
+ for my $v (@$row) {
+ $v =~ s/^\s+|\s+$//g;
+ $v =~ /^\d+$/ or die "bad value: $sql: $v";
+ }
+ if ($ord) {
+ my $out = $out[$n];
+ $row->[0] == $out->[0] &&
+ $row->[1] == $out->[1] &&
+ $row->[2] == $out->[2] or
+ die "$sql: row $n: got row @$row != @$out";
+ }
+ $n++;
+ }
+ $sth->err and die "fetch: $sql: $DBI::errstr";
+ $n == $cnt or die "verify: $sql: got row count $n != $cnt";
+ $casecnt++;
+}
+
+for my $nn ("bcd", "") {
+ my %nn;
+ for my $x (qw(b c d)) {
+ $nn{$x} = $nn =~ /$x/ ? "not null" : "null";
+ }
+ warn "create table\n";
+ $sql = <<EOF;
+create table $table (
+ a int primary key,
+ b int $nn{b},
+ c int $nn{c},
+ d int $nn{d},
+ index (b, c, d)
+) engine=ndb
+EOF
+ $dbh->do($sql) or die $DBI::errstr;
+ warn "insert\n";
+ $sql = "insert into $table values(?, ?, ?, ?)";
+ $sth = $dbh->prepare($sql) or die $DBI::errstr;
+ my @val = (0..($opt_cnt-1));
+ my $v0 = 0;
+ for my $v1 (@val) {
+ for my $v2 (@val) {
+ for my $v3 (@val) {
+ $sth->bind_param(1, $v0) or die $DBI::errstr;
+ $sth->bind_param(2, $v1) or die $DBI::errstr;
+ $sth->bind_param(3, $v2) or die $DBI::errstr;
+ $sth->bind_param(4, $v3) or die $DBI::errstr;
+ $sth->execute or die $DBI::errstr;
+ $v0++;
+ }
+ }
+ }
+ warn "generate cases\n";
+ my $key1 = 1;
+ my $key2 = 3;
+ my $a1 = mkall('b', $key1, $key2, \@val);
+ my $a2 = mkall('c', $key1, $key2, \@val);
+ my $a3 = mkall('d', $key1, $key2, \@val);
+ warn "select\n";
+ for my $ord (0, +1, -1) {
+ my $orderby =
+ $ord == 0 ? "" :
+ $ord == +1 ? " order by b, c, d" :
+ $ord == -1 ? " order by b desc, c desc, d desc" : die "not here";
+ for my $p1 (@$a1) {
+ my $res = [ $p1->{res}, \@val, \@val ];
+ $sql = "select b, c, d from $table" .
+ " where $p1->{exp}" .
+ $orderby;
+ verify($sql, $ord, $res);
+ for my $p2 (@$a2) {
+ my $res = [ $p1->{res}, $p2->{res}, \@val ];
+ $sql = "select b, c, d from $table" .
+ " where $p1->{exp} and $p2->{exp}" .
+ $orderby;
+ verify($sql, $ord, $res);
+ for my $p3 (@$a3) {
+ my $res = [ $p1->{res}, $p2->{res}, $p3->{res} ];
+ $sql = "select b, c, d from $table" .
+ " where $p1->{exp} and $p2->{exp} and $p3->{exp}" .
+ $orderby;
+ verify($sql, $ord, $res);
+ }
+ }
+ }
+ }
+ warn "drop table\n";
+ $sql = "drop table $table";
+ $dbh->do($sql) or die $DBI::errstr;
+}
+
+warn "verified $casecnt cases\n";
+warn "done\n";
+
+# vim: set sw=2: