#At file:///home/frazer/bzr/mysql-5.1-telco-7.1/ based on revid:bernhard.ocklin@stripped
3584 Frazer Clement 2010-04-29 [merge]
Merge 7.0->7.1
added:
mysql-test/include/ndb_desc_print.inc
mysql-test/std_data/ndb_backup_before_native_default/
mysql-test/std_data/ndb_backup_before_native_default/BACKUP-1-0.1.Data
mysql-test/std_data/ndb_backup_before_native_default/BACKUP-1-0.2.Data
mysql-test/std_data/ndb_backup_before_native_default/BACKUP-1.1.ctl
mysql-test/std_data/ndb_backup_before_native_default/BACKUP-1.1.log
mysql-test/std_data/ndb_backup_before_native_default/BACKUP-1.2.ctl
mysql-test/std_data/ndb_backup_before_native_default/BACKUP-1.2.log
mysql-test/suite/ndb/r/ndb_native_default_support.result
mysql-test/suite/ndb/t/ndb_native_default_support.test
storage/ndb/test/ndbapi/testNativeDefault.cpp
modified:
mysql-test/Makefile.am
mysql-test/suite/ndb/r/ndb_restore_promotion.result
mysql-test/suite/ndb/t/ndb_restore_promotion.test
mysql-test/suite/rpl_ndb/r/rpl_ndb_2ndb.result
mysql-test/suite/rpl_ndb/r/rpl_ndb_extraCol.result
sql/ha_ndbcluster.cc
sql/ha_ndbcluster.h
storage/ndb/include/kernel/ndb_limits.h
storage/ndb/include/kernel/signaldata/DictTabInfo.hpp
storage/ndb/include/kernel/signaldata/LqhFrag.hpp
storage/ndb/include/kernel/signaldata/TupFrag.hpp
storage/ndb/include/ndb_version.h.in
storage/ndb/include/ndbapi/NdbDictionary.hpp
storage/ndb/include/ndbapi/NdbRecAttr.hpp
storage/ndb/include/util/UtilBuffer.hpp
storage/ndb/src/common/debugger/signaldata/DictTabInfo.cpp
storage/ndb/src/kernel/blocks/ERROR_codes.txt
storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp
storage/ndb/src/kernel/blocks/dblqh/Dblqh.hpp
storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp
storage/ndb/src/kernel/blocks/dblqh/DblqhProxy.cpp
storage/ndb/src/kernel/blocks/dbtup/Dbtup.hpp
storage/ndb/src/kernel/blocks/dbtup/DbtupDebug.cpp
storage/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp
storage/ndb/src/kernel/blocks/dbtup/DbtupGen.cpp
storage/ndb/src/kernel/blocks/dbtup/DbtupMeta.cpp
storage/ndb/src/kernel/blocks/dbtup/DbtupVarAlloc.cpp
storage/ndb/src/ndbapi/NdbDictionary.cpp
storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp
storage/ndb/src/ndbapi/NdbDictionaryImpl.hpp
storage/ndb/src/ndbapi/NdbRecAttr.cpp
storage/ndb/src/ndbapi/ndberror.c
storage/ndb/test/include/NDBT_Table.hpp
storage/ndb/test/ndbapi/CMakeLists.txt
storage/ndb/test/ndbapi/Makefile.am
storage/ndb/test/ndbapi/testBasic.cpp
storage/ndb/test/ndbapi/testBitfield.cpp
storage/ndb/test/ndbapi/testDict.cpp
storage/ndb/test/ndbapi/testUpgrade.cpp
storage/ndb/test/run-test/daily-basic-tests.txt
storage/ndb/test/src/NDBT_Tables.cpp
=== modified file 'mysql-test/Makefile.am'
--- a/mysql-test/Makefile.am 2010-03-15 14:38:19 +0000
+++ b/mysql-test/Makefile.am 2010-04-29 16:03:05 +0000
@@ -85,6 +85,7 @@ TEST_DIRS = t r include std_data std_dat
std_data/ndb_backup51_undolog_be \
std_data/ndb_backup51_undolog_le \
std_data/ndb_backup_hashmap \
+ std_data/ndb_backup_before_native_default \
std_data/funcs_1 \
extra/binlog_tests/ extra/rpl_tests \
suite/binlog suite/binlog/t suite/binlog/r suite/binlog/std_data \
=== added file 'mysql-test/include/ndb_desc_print.inc'
--- a/mysql-test/include/ndb_desc_print.inc 1970-01-01 00:00:00 +0000
+++ b/mysql-test/include/ndb_desc_print.inc 2010-04-29 14:52:05 +0000
@@ -0,0 +1,5 @@
+# Use replace_regex to remove non-deterministic values from the
+# ndb_desc output
+#
+--replace_regex /Version: [0-9]*/Version: Any/ /t2_unique_index\(j\) - OrderedIndex/Index/ /t2_unique_index\$unique\(j\) - UniqueHashIndex/Index/ /PRIMARY\(i\) - OrderedIndex/Index/ /BT=NDB\$BLOB_[0-9]*_/BT=NDB$BLOB_XX_/
+--exec $NDB_DESC --no-defaults $ndb_desc_opts
=== added directory 'mysql-test/std_data/ndb_backup_before_native_default'
=== added file 'mysql-test/std_data/ndb_backup_before_native_default/BACKUP-1-0.1.Data'
Binary files a/mysql-test/std_data/ndb_backup_before_native_default/BACKUP-1-0.1.Data 1970-01-01 00:00:00 +0000 and b/mysql-test/std_data/ndb_backup_before_native_default/BACKUP-1-0.1.Data 2010-04-29 14:52:05 +0000 differ
=== added file 'mysql-test/std_data/ndb_backup_before_native_default/BACKUP-1-0.2.Data'
Binary files a/mysql-test/std_data/ndb_backup_before_native_default/BACKUP-1-0.2.Data 1970-01-01 00:00:00 +0000 and b/mysql-test/std_data/ndb_backup_before_native_default/BACKUP-1-0.2.Data 2010-04-29 14:52:05 +0000 differ
=== added file 'mysql-test/std_data/ndb_backup_before_native_default/BACKUP-1.1.ctl'
Binary files a/mysql-test/std_data/ndb_backup_before_native_default/BACKUP-1.1.ctl 1970-01-01 00:00:00 +0000 and b/mysql-test/std_data/ndb_backup_before_native_default/BACKUP-1.1.ctl 2010-04-29 14:52:05 +0000 differ
=== added file 'mysql-test/std_data/ndb_backup_before_native_default/BACKUP-1.1.log'
Binary files a/mysql-test/std_data/ndb_backup_before_native_default/BACKUP-1.1.log 1970-01-01 00:00:00 +0000 and b/mysql-test/std_data/ndb_backup_before_native_default/BACKUP-1.1.log 2010-04-29 14:52:05 +0000 differ
=== added file 'mysql-test/std_data/ndb_backup_before_native_default/BACKUP-1.2.ctl'
Binary files a/mysql-test/std_data/ndb_backup_before_native_default/BACKUP-1.2.ctl 1970-01-01 00:00:00 +0000 and b/mysql-test/std_data/ndb_backup_before_native_default/BACKUP-1.2.ctl 2010-04-29 14:52:05 +0000 differ
=== added file 'mysql-test/std_data/ndb_backup_before_native_default/BACKUP-1.2.log'
Binary files a/mysql-test/std_data/ndb_backup_before_native_default/BACKUP-1.2.log 1970-01-01 00:00:00 +0000 and b/mysql-test/std_data/ndb_backup_before_native_default/BACKUP-1.2.log 2010-04-29 14:52:05 +0000 differ
=== added file 'mysql-test/suite/ndb/r/ndb_native_default_support.result'
--- a/mysql-test/suite/ndb/r/ndb_native_default_support.result 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/ndb/r/ndb_native_default_support.result 2010-04-29 14:52:05 +0000
@@ -0,0 +1,574 @@
+DROP TABLE IF EXISTS t1,bit1;
+DROP DATABASE IF EXISTS mysqltest;
+CREATE DATABASE mysqltest;
+USE mysqltest;
+***************************************************************
+* BASIC SQL STATEMENT TEST FOR NDB NATIVE DEFAULT VALUE SUPPORT
+***************************************************************
+CREATE TABLE t1(
+i INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
+j INT DEFAULT 6,
+f FLOAT NOT NULL DEFAULT 6.6,
+d DOUBLE DEFAULT 8.8,
+d2 DOUBLE NOT NULL, #d2 gets 'data-type-specific default', i.e. 0.
+ch CHAR(19) DEFAULT "aaa",
+vch VARCHAR(19) DEFAULT "bbb",
+b BINARY(19) DEFAULT "ccc",
+vb VARBINARY(19) DEFAULT "ddd",
+blob1 BLOB,
+text1 TEXT,
+timestamp_c TIMESTAMP DEFAULT CURRENT_TIMESTAMP
+)ENGINE=NDB;
+INSERT INTO t1 VALUES(),();
+INSERT INTO t1 VALUES(
+10, 10, 10.0, 10.0, 10.0,
+"nnnnn", "nnnnn", "nnnnn", "nnnnn", "nnnnn", "nnnnn",
+"2008-11-16 08:13:32");
+INSERT INTO t1(i, ch) VALUES(11, "mmm");
+SELECT i, j, f, d, d2, ch, vch, HEX(b), HEX(vb), HEX(blob1), text1, timestamp_c FROM t1 ORDER BY i;
+i j f d d2 ch vch HEX(b) HEX(vb) HEX(blob1) text1 timestamp_c
+1 6 6.6 8.8 0 aaa bbb 63636300000000000000000000000000000000 646464 NULL NULL CURRENT_TIMESTAMP
+2 6 6.6 8.8 0 aaa bbb 63636300000000000000000000000000000000 646464 NULL NULL CURRENT_TIMESTAMP
+10 10 10 10 10 nnnnn nnnnn 6E6E6E6E6E0000000000000000000000000000 6E6E6E6E6E 6E6E6E6E6E nnnnn CURRENT_TIMESTAMP
+11 6 6.6 8.8 0 mmm bbb 63636300000000000000000000000000000000 646464 NULL NULL CURRENT_TIMESTAMP
+UPDATE t1 SET ch = "xxx" WHERE i = 10;
+SELECT i, j, f, d, d2, ch, vch, HEX(b), HEX(vb), HEX(blob1), text1, timestamp_c FROM t1 ORDER BY i;
+i j f d d2 ch vch HEX(b) HEX(vb) HEX(blob1) text1 timestamp_c
+1 6 6.6 8.8 0 aaa bbb 63636300000000000000000000000000000000 646464 NULL NULL CURRENT_TIMESTAMP
+2 6 6.6 8.8 0 aaa bbb 63636300000000000000000000000000000000 646464 NULL NULL CURRENT_TIMESTAMP
+10 10 10 10 10 xxx nnnnn 6E6E6E6E6E0000000000000000000000000000 6E6E6E6E6E 6E6E6E6E6E nnnnn CURRENT_TIMESTAMP
+11 6 6.6 8.8 0 mmm bbb 63636300000000000000000000000000000000 646464 NULL NULL CURRENT_TIMESTAMP
+UPDATE t1 SET blob1 = "yyy" WHERE j = 10;
+SELECT i, j, f, d, d2, ch, vch, HEX(b), HEX(vb), HEX(blob1), text1, timestamp_c FROM t1 ORDER BY i;
+i j f d d2 ch vch HEX(b) HEX(vb) HEX(blob1) text1 timestamp_c
+1 6 6.6 8.8 0 aaa bbb 63636300000000000000000000000000000000 646464 NULL NULL CURRENT_TIMESTAMP
+2 6 6.6 8.8 0 aaa bbb 63636300000000000000000000000000000000 646464 NULL NULL CURRENT_TIMESTAMP
+10 10 10 10 10 xxx nnnnn 6E6E6E6E6E0000000000000000000000000000 6E6E6E6E6E 797979 nnnnn CURRENT_TIMESTAMP
+11 6 6.6 8.8 0 mmm bbb 63636300000000000000000000000000000000 646464 NULL NULL CURRENT_TIMESTAMP
+REPLACE INTO t1(i, j, ch) VALUES(1, 1, "zzz");
+REPLACE INTO t1(i, j, ch) VALUES(20, 20, "www");
+SELECT i, j, f, d, d2, ch, vch, HEX(b), HEX(vb), HEX(blob1), text1, timestamp_c FROM t1 ORDER BY i;
+i j f d d2 ch vch HEX(b) HEX(vb) HEX(blob1) text1 timestamp_c
+1 1 6.6 8.8 0 zzz bbb 63636300000000000000000000000000000000 646464 NULL NULL CURRENT_TIMESTAMP
+2 6 6.6 8.8 0 aaa bbb 63636300000000000000000000000000000000 646464 NULL NULL CURRENT_TIMESTAMP
+10 10 10 10 10 xxx nnnnn 6E6E6E6E6E0000000000000000000000000000 6E6E6E6E6E 797979 nnnnn CURRENT_TIMESTAMP
+11 6 6.6 8.8 0 mmm bbb 63636300000000000000000000000000000000 646464 NULL NULL CURRENT_TIMESTAMP
+20 20 6.6 8.8 0 www bbb 63636300000000000000000000000000000000 646464 NULL NULL CURRENT_TIMESTAMP
+DELETE FROM t1 WHERE i > 9;
+SELECT i, j, f, d, d2, ch, vch, HEX(b), HEX(vb), HEX(blob1), text1, timestamp_c FROM t1 ORDER BY i;
+i j f d d2 ch vch HEX(b) HEX(vb) HEX(blob1) text1 timestamp_c
+1 1 6.6 8.8 0 zzz bbb 63636300000000000000000000000000000000 646464 NULL NULL CURRENT_TIMESTAMP
+2 6 6.6 8.8 0 aaa bbb 63636300000000000000000000000000000000 646464 NULL NULL CURRENT_TIMESTAMP
+CREATE TABLE bit1(
+pk INT AUTO_INCREMENT NOT NULL PRIMARY KEY,
+b1 BIT(3) DEFAULT B'111',
+b2 BIT(9) DEFAULT B'101',
+b3 BIT(23) DEFAULT B'110',
+b4 BIT(37) DEFAULT B'011',
+b5 BIT(63) DEFAULT B'101011'
+)ENGINE = NDB;
+INSERT INTO bit1 VALUES();
+INSERT INTO bit1(b1,b4) VALUES(B'101',B'111');
+SELECT pk,BIN(b1),BIN(b2),BIN(b3),BIN(b4),BIN(b5) FROM bit1 ORDER BY pk;
+pk BIN(b1) BIN(b2) BIN(b3) BIN(b4) BIN(b5)
+1 111 101 110 11 101011
+2 101 101 110 111 101011
+UPDATE bit1 SET b5=B'11111' WHERE pk = 1;
+REPLACE INTO bit1(pk, b3) VALUES(2, B'1');
+REPLACE INTO bit1(pk, b3) VALUES(6, B'101');
+SELECT pk,BIN(b1),BIN(b2),BIN(b3),BIN(b4),BIN(b5) FROM bit1 ORDER BY pk;
+pk BIN(b1) BIN(b2) BIN(b3) BIN(b4) BIN(b5)
+1 111 101 110 11 11111
+2 111 101 1 11 101011
+6 111 101 101 11 101011
+DELETE FROM bit1 WHERE pk = 2;
+SELECT pk,BIN(b1),BIN(b2),BIN(b3),BIN(b4),BIN(b5) FROM bit1 ORDER BY pk;
+pk BIN(b1) BIN(b2) BIN(b3) BIN(b4) BIN(b5)
+1 111 101 110 11 11111
+6 111 101 101 11 101011
+********************************************************
+* Alter table to add column with default value
+********************************************************
+ALTER TABLE t1 ADD COLUMN ch2 CHAR(30) DEFAULT "alter table";
+SELECT i, j, f, d, d2, ch, vch, HEX(b), HEX(vb), HEX(blob1), text1, timestamp_c, ch2 FROM t1 ORDER BY i;
+i j f d d2 ch vch HEX(b) HEX(vb) HEX(blob1) text1 timestamp_c ch2
+1 1 6.6 8.8 0 zzz bbb 63636300000000000000000000000000000000 646464 NULL NULL CURRENT_TIMESTAMP alter table
+2 6 6.6 8.8 0 aaa bbb 63636300000000000000000000000000000000 646464 NULL NULL CURRENT_TIMESTAMP alter table
+INSERT INTO t1 VALUES();
+SELECT i, j, f, d, d2, ch, vch, HEX(b), HEX(vb), HEX(blob1), text1, timestamp_c, ch2 FROM t1 ORDER BY i;
+i j f d d2 ch vch HEX(b) HEX(vb) HEX(blob1) text1 timestamp_c ch2
+1 1 6.6 8.8 0 zzz bbb 63636300000000000000000000000000000000 646464 NULL NULL CURRENT_TIMESTAMP alter table
+2 6 6.6 8.8 0 aaa bbb 63636300000000000000000000000000000000 646464 NULL NULL CURRENT_TIMESTAMP alter table
+21 6 6.6 8.8 0 aaa bbb 63636300000000000000000000000000000000 646464 NULL NULL CURRENT_TIMESTAMP alter table
+********************************************************
+* Alter table with default value can fail safely
+********************************************************
+ALTER TABLE t1 ADD COLUMN ch2 CHAR(30) DEFAULT "alter table";
+ERROR 42S21: Duplicate column name 'ch2'
+ALTER TABLE t1 ADD COLUMN ch3 CHAR(3) DEFAULT "alter table";
+ERROR 42000: Invalid default value for 'ch3'
+INSERT INTO t1 VALUES();
+SELECT i, j, f, d, d2, ch, vch, HEX(b), HEX(vb), HEX(blob1), text1, timestamp_c, ch2 FROM t1 ORDER BY i;
+i j f d d2 ch vch HEX(b) HEX(vb) HEX(blob1) text1 timestamp_c ch2
+1 1 6.6 8.8 0 zzz bbb 63636300000000000000000000000000000000 646464 NULL NULL CURRENT_TIMESTAMP alter table
+2 6 6.6 8.8 0 aaa bbb 63636300000000000000000000000000000000 646464 NULL NULL CURRENT_TIMESTAMP alter table
+21 6 6.6 8.8 0 aaa bbb 63636300000000000000000000000000000000 646464 NULL NULL CURRENT_TIMESTAMP alter table
+22 6 6.6 8.8 0 aaa bbb 63636300000000000000000000000000000000 646464 NULL NULL CURRENT_TIMESTAMP alter table
+********************************************************
+* The tables with default values BACKUP and RESTORE test
+********************************************************
+DROP TABLE IF EXISTS t1, bit1;
+********************************************************
+* Begin to restore data from backup
+********************************************************
+SHOW TABLES;
+Tables_in_mysqltest
+bit1
+t1
+-- t1 --
+Version: Any
+Fragment type: 9
+K Value: 6
+Min load factor: 78
+Max load factor: 80
+Temporary table: no
+Number of attributes: 13
+Number of primary keys: 1
+Length of frm data: 518
+Row Checksum: 1
+Row GCI: 1
+SingleUserMode: 0
+ForceVarPart: 1
+FragmentCount: 2
+TableStatus: Retrieved
+-- Attributes --
+i Int PRIMARY KEY DISTRIBUTION KEY AT=FIXED ST=MEMORY AUTO_INCR
+j Int NULL AT=FIXED ST=MEMORY DEFAULT 6
+f Float NOT NULL AT=FIXED ST=MEMORY DEFAULT 6.600000
+d Double NULL AT=FIXED ST=MEMORY DEFAULT 8.800000
+d2 Double NOT NULL AT=FIXED ST=MEMORY
+ch Char(19;latin1_swedish_ci) NULL AT=FIXED ST=MEMORY DEFAULT "aaa"
+vch Varchar(19;latin1_swedish_ci) NULL AT=SHORT_VAR ST=MEMORY DEFAULT "bbb"
+b Binary(19) NULL AT=FIXED ST=MEMORY DEFAULT 0x636363
+vb Varbinary(19) NULL AT=SHORT_VAR ST=MEMORY DEFAULT 0x646464
+blob1 Blob(256,2000,0) NULL AT=MEDIUM_VAR ST=MEMORY BV=2 BT=NDB$BLOB_XX_9
+text1 Text(256,2000,0;latin1_swedish_ci) NULL AT=MEDIUM_VAR ST=MEMORY BV=2 BT=NDB$BLOB_XX_10
+timestamp_c Timestamp NOT NULL AT=FIXED ST=MEMORY DEFAULT 0
+ch2 Char(30;latin1_swedish_ci) NULL AT=FIXED ST=MEMORY DEFAULT "alter table"
+
+-- Indexes --
+PRIMARY KEY(i) - UniqueHashIndex
+Index
+
+
+NDBT_ProgramExit: 0 - OK
+
+-- bit1 --
+Version: Any
+Fragment type: 9
+K Value: 6
+Min load factor: 78
+Max load factor: 80
+Temporary table: no
+Number of attributes: 6
+Number of primary keys: 1
+Length of frm data: 324
+Row Checksum: 1
+Row GCI: 1
+SingleUserMode: 0
+ForceVarPart: 1
+FragmentCount: 2
+TableStatus: Retrieved
+-- Attributes --
+pk Int PRIMARY KEY DISTRIBUTION KEY AT=FIXED ST=MEMORY AUTO_INCR
+b1 Bit(3) NULL AT=FIXED ST=MEMORY DEFAULT H'0x7
+b2 Bit(9) NULL AT=FIXED ST=MEMORY DEFAULT H'0x5
+b3 Bit(23) NULL AT=FIXED ST=MEMORY DEFAULT H'0x6
+b4 Bit(37) NULL AT=FIXED ST=MEMORY DEFAULT H'0x3
+b5 Bit(63) NULL AT=FIXED ST=MEMORY DEFAULT H'0x2B
+
+-- Indexes --
+PRIMARY KEY(pk) - UniqueHashIndex
+PRIMARY(pk) - OrderedIndex
+
+
+NDBT_ProgramExit: 0 - OK
+
+SELECT pk,BIN(b1),BIN(b2),BIN(b3),BIN(b4),BIN(b5) FROM bit1 ORDER BY pk;
+pk BIN(b1) BIN(b2) BIN(b3) BIN(b4) BIN(b5)
+1 111 101 110 11 11111
+6 111 101 101 11 101011
+SELECT i, j, f, d, d2, ch, vch, HEX(b), HEX(vb), HEX(blob1), text1, timestamp_c, ch2 FROM t1 ORDER BY i;
+i j f d d2 ch vch HEX(b) HEX(vb) HEX(blob1) text1 timestamp_c ch2
+1 1 6.6 8.8 0 zzz bbb 63636300000000000000000000000000000000 646464 NULL NULL CURRENT_TIMESTAMP alter table
+2 6 6.6 8.8 0 aaa bbb 63636300000000000000000000000000000000 646464 NULL NULL CURRENT_TIMESTAMP alter table
+21 6 6.6 8.8 0 aaa bbb 63636300000000000000000000000000000000 646464 NULL NULL CURRENT_TIMESTAMP alter table
+22 6 6.6 8.8 0 aaa bbb 63636300000000000000000000000000000000 646464 NULL NULL CURRENT_TIMESTAMP alter table
+INSERT INTO t1(i, ch) VALUES(99, "restore");
+INSERT INTO bit1(pk, b5) VALUES(99, B'11111111');
+SELECT pk,BIN(b1),BIN(b2),BIN(b3),BIN(b4),BIN(b5) FROM bit1 ORDER BY pk;
+pk BIN(b1) BIN(b2) BIN(b3) BIN(b4) BIN(b5)
+1 111 101 110 11 11111
+6 111 101 101 11 101011
+99 111 101 110 11 11111111
+SELECT i, j, f, d, d2, ch, vch, HEX(b), HEX(vb), HEX(blob1), text1, timestamp_c, ch2 FROM t1 ORDER BY i;
+i j f d d2 ch vch HEX(b) HEX(vb) HEX(blob1) text1 timestamp_c ch2
+1 1 6.6 8.8 0 zzz bbb 63636300000000000000000000000000000000 646464 NULL NULL CURRENT_TIMESTAMP alter table
+2 6 6.6 8.8 0 aaa bbb 63636300000000000000000000000000000000 646464 NULL NULL CURRENT_TIMESTAMP alter table
+21 6 6.6 8.8 0 aaa bbb 63636300000000000000000000000000000000 646464 NULL NULL CURRENT_TIMESTAMP alter table
+22 6 6.6 8.8 0 aaa bbb 63636300000000000000000000000000000000 646464 NULL NULL CURRENT_TIMESTAMP alter table
+99 6 6.6 8.8 0 restore bbb 63636300000000000000000000000000000000 646464 NULL NULL CURRENT_TIMESTAMP alter table
+DROP TABLE IF EXISTS t1, bit1;
+SHOW TABLES;
+Tables_in_mysqltest
+bit1
+t1
+SELECT i, j, f, d, d2, ch, vch, HEX(b), HEX(vb), HEX(blob1), text1, timestamp_c, ch2 FROM t1 WHERE i >= (SELECT MAX(i) FROM t1) ORDER BY i;
+i j f d d2 ch vch HEX(b) HEX(vb) HEX(blob1) text1 timestamp_c ch2
+MAX_VALUE 6 6.6 8.8 0 aaa bbb 63636300000000000000000000000000000000 646464 NULL NULL CURRENT_TIMESTAMP alter table
+DROP TABLE IF EXISTS t1, bit1;
+DROP DATABASE mysqltest;
+******************************************************************************
+* Restore the backup from 6.3 or 6.4, which don't support native default value
+******************************************************************************
+USE test;
+SHOW TABLES;
+Tables_in_test
+bit1
+t1
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `i` int(11) NOT NULL AUTO_INCREMENT,
+ `j` int(11) DEFAULT '6',
+ `f` float NOT NULL DEFAULT '6.6',
+ `d` double DEFAULT '8.8',
+ `d2` double NOT NULL,
+ `ch` char(19) DEFAULT 'aaa',
+ `vch` varchar(19) DEFAULT 'bbb',
+ `b` binary(19) DEFAULT 'ccc\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0',
+ `vb` varbinary(19) DEFAULT 'ddd',
+ `blob1` blob,
+ `text1` text,
+ `timestamp_c` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ PRIMARY KEY (`i`)
+) ENGINE=ndbcluster AUTO_INCREMENT=12 DEFAULT CHARSET=latin1
+SHOW CREATE TABLE bit1;
+Table Create Table
+bit1 CREATE TABLE `bit1` (
+ `pk` int(11) NOT NULL AUTO_INCREMENT,
+ `b1` bit(3) DEFAULT b'111',
+ `b2` bit(9) DEFAULT b'101',
+ `b3` bit(23) DEFAULT b'110',
+ `b4` bit(37) DEFAULT b'11',
+ `b5` bit(63) DEFAULT b'101011',
+ PRIMARY KEY (`pk`)
+) ENGINE=ndbcluster AUTO_INCREMENT=3 DEFAULT CHARSET=latin1
+SELECT i, j, f, d, d2, ch, vch, HEX(b), HEX(vb), HEX(blob1), text1, timestamp_c FROM t1 ORDER BY i;
+i j f d d2 ch vch HEX(b) HEX(vb) HEX(blob1) text1 timestamp_c
+1 6 6.6 8.8 0 aaa bbb 63636300000000000000000000000000000000 646464 NULL NULL CURRENT_TIMESTAMP
+2 6 6.6 8.8 0 aaa bbb 63636300000000000000000000000000000000 646464 NULL NULL CURRENT_TIMESTAMP
+10 10 10 10 10 nnnnn nnnnn 6E6E6E6E6E0000000000000000000000000000 6E6E6E6E6E 6E6E6E6E6E nnnnn CURRENT_TIMESTAMP
+11 6 6.6 8.8 0 mmm bbb 63636300000000000000000000000000000000 646464 NULL NULL CURRENT_TIMESTAMP
+SELECT pk,BIN(b1),BIN(b2),BIN(b3),BIN(b4),BIN(b5) FROM bit1 ORDER BY pk;
+pk BIN(b1) BIN(b2) BIN(b3) BIN(b4) BIN(b5)
+1 111 101 110 11 101011
+2 101 101 110 111 101011
+INSERT INTO t1 VALUES();
+UPDATE t1 SET ch = "RESTORE FROM 6.3" WHERE i = 12;
+REPLACE INTO t1(i, j, ch) VALUES(20, 20, "RESTORE FROM 6.3");
+SELECT i, j, f, d, d2, ch, vch, HEX(b), HEX(vb), HEX(blob1), text1, timestamp_c FROM t1 ORDER BY i;
+i j f d d2 ch vch HEX(b) HEX(vb) HEX(blob1) text1 timestamp_c
+1 6 6.6 8.8 0 aaa bbb 63636300000000000000000000000000000000 646464 NULL NULL CURRENT_TIMESTAMP
+2 6 6.6 8.8 0 aaa bbb 63636300000000000000000000000000000000 646464 NULL NULL CURRENT_TIMESTAMP
+10 10 10 10 10 nnnnn nnnnn 6E6E6E6E6E0000000000000000000000000000 6E6E6E6E6E 6E6E6E6E6E nnnnn CURRENT_TIMESTAMP
+11 6 6.6 8.8 0 mmm bbb 63636300000000000000000000000000000000 646464 NULL NULL CURRENT_TIMESTAMP
+12 6 6.6 8.8 0 RESTORE FROM 6.3 bbb 63636300000000000000000000000000000000 646464 NULL NULL CURRENT_TIMESTAMP
+20 20 6.6 8.8 0 RESTORE FROM 6.3 bbb 63636300000000000000000000000000000000 646464 NULL NULL CURRENT_TIMESTAMP
+INSERT INTO bit1 VALUES();
+UPDATE bit1 SET b5=b'1111111' WHERE pk = 1;
+REPLACE INTO bit1(pk, b3) VALUES(6, B'110011');
+SELECT pk,BIN(b1),BIN(b2),BIN(b3),BIN(b4),BIN(b5) FROM bit1 ORDER BY pk;
+pk BIN(b1) BIN(b2) BIN(b3) BIN(b4) BIN(b5)
+1 111 101 110 11 1111111
+2 101 101 110 111 101011
+3 111 101 110 11 101011
+6 111 101 110011 11 101011
+********************************************************************************
+* Alter table restoring from 6.3 backup to new table with native default support
+********************************************************************************
+-- t1 --
+Version: Any
+Fragment type: 5
+K Value: 6
+Min load factor: 78
+Max load factor: 80
+Temporary table: no
+Number of attributes: 12
+Number of primary keys: 1
+Length of frm data: 484
+Row Checksum: 1
+Row GCI: 1
+SingleUserMode: 0
+ForceVarPart: 1
+FragmentCount: 2
+TableStatus: Retrieved
+-- Attributes --
+i Int PRIMARY KEY DISTRIBUTION KEY AT=FIXED ST=MEMORY AUTO_INCR
+j Int NULL AT=FIXED ST=MEMORY
+f Float NOT NULL AT=FIXED ST=MEMORY
+d Double NULL AT=FIXED ST=MEMORY
+d2 Double NOT NULL AT=FIXED ST=MEMORY
+ch Char(19;latin1_swedish_ci) NULL AT=FIXED ST=MEMORY
+vch Varchar(19;latin1_swedish_ci) NULL AT=SHORT_VAR ST=MEMORY
+b Binary(19) NULL AT=FIXED ST=MEMORY
+vb Varbinary(19) NULL AT=SHORT_VAR ST=MEMORY
+blob1 Blob(256,2000,0) NULL AT=MEDIUM_VAR ST=MEMORY BV=2 BT=NDB$BLOB_XX_9
+text1 Text(256,2000,0;latin1_swedish_ci) NULL AT=MEDIUM_VAR ST=MEMORY BV=2 BT=NDB$BLOB_XX_10
+timestamp_c Timestamp NOT NULL AT=FIXED ST=MEMORY
+
+-- Indexes --
+PRIMARY KEY(i) - UniqueHashIndex
+Index
+
+
+NDBT_ProgramExit: 0 - OK
+
+ALTER TABLE t1 CHANGE COLUMN j j INT DEFAULT 6;
+-- t1 --
+Version: Any
+Fragment type: 9
+K Value: 6
+Min load factor: 78
+Max load factor: 80
+Temporary table: no
+Number of attributes: 12
+Number of primary keys: 1
+Length of frm data: 487
+Row Checksum: 1
+Row GCI: 1
+SingleUserMode: 0
+ForceVarPart: 1
+FragmentCount: 2
+TableStatus: Retrieved
+-- Attributes --
+i Int PRIMARY KEY DISTRIBUTION KEY AT=FIXED ST=MEMORY AUTO_INCR
+j Int NULL AT=FIXED ST=MEMORY DEFAULT 6
+f Float NOT NULL AT=FIXED ST=MEMORY DEFAULT 6.600000
+d Double NULL AT=FIXED ST=MEMORY DEFAULT 8.800000
+d2 Double NOT NULL AT=FIXED ST=MEMORY
+ch Char(19;latin1_swedish_ci) NULL AT=FIXED ST=MEMORY DEFAULT "aaa"
+vch Varchar(19;latin1_swedish_ci) NULL AT=SHORT_VAR ST=MEMORY DEFAULT "bbb"
+b Binary(19) NULL AT=FIXED ST=MEMORY DEFAULT 0x636363
+vb Varbinary(19) NULL AT=SHORT_VAR ST=MEMORY DEFAULT 0x646464
+blob1 Blob(256,2000,0) NULL AT=MEDIUM_VAR ST=MEMORY BV=2 BT=NDB$BLOB_XX_9
+text1 Text(256,2000,0;latin1_swedish_ci) NULL AT=MEDIUM_VAR ST=MEMORY BV=2 BT=NDB$BLOB_XX_10
+timestamp_c Timestamp NOT NULL AT=FIXED ST=MEMORY DEFAULT 0
+
+-- Indexes --
+PRIMARY KEY(i) - UniqueHashIndex
+Index
+
+
+NDBT_ProgramExit: 0 - OK
+
+INSERT INTO t1(i, ch) VALUES(99, "native default support");
+SELECT i, j, f, d, d2, ch, vch, HEX(b), HEX(vb), HEX(blob1), text1, timestamp_c FROM t1 ORDER BY i;
+i j f d d2 ch vch HEX(b) HEX(vb) HEX(blob1) text1 timestamp_c
+1 6 6.6 8.8 0 aaa bbb 63636300000000000000000000000000000000 646464 NULL NULL CURRENT_TIMESTAMP
+2 6 6.6 8.8 0 aaa bbb 63636300000000000000000000000000000000 646464 NULL NULL CURRENT_TIMESTAMP
+10 10 10 10 10 nnnnn nnnnn 6E6E6E6E6E0000000000000000000000000000 6E6E6E6E6E 6E6E6E6E6E nnnnn CURRENT_TIMESTAMP
+11 6 6.6 8.8 0 mmm bbb 63636300000000000000000000000000000000 646464 NULL NULL CURRENT_TIMESTAMP
+12 6 6.6 8.8 0 RESTORE FROM 6.3 bbb 63636300000000000000000000000000000000 646464 NULL NULL CURRENT_TIMESTAMP
+20 20 6.6 8.8 0 RESTORE FROM 6.3 bbb 63636300000000000000000000000000000000 646464 NULL NULL CURRENT_TIMESTAMP
+99 6 6.6 8.8 0 native default supp bbb 63636300000000000000000000000000000000 646464 NULL NULL CURRENT_TIMESTAMP
+DROP TABLE IF EXISTS t1, bit1;
+*************************************************************
+* Test adding a unique index to a column with a default value
+*************************************************************
+CREATE TABLE t2(
+i INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
+j INT DEFAULT 6,
+f FLOAT NOT NULL DEFAULT 6.6,
+d DOUBLE DEFAULT 8.8,
+UNIQUE INDEX t2_unique_index(j)
+)ENGINE =NDB;
+INSERT INTO t2 VALUES();
+INSERT INTO t2 VALUES();
+ERROR 23000: Duplicate entry '6' for key 't2_unique_index'
+INSERT INTO t2 VALUES(10, 10, 10.0, 10.0);
+SELECT * FROM t2 ORDER BY i;
+i j f d
+1 6 6.6 8.8
+10 10 10 10
+*************************************************************
+* Test offline alter of default values
+*************************************************************
+ALTER TABLE t2 MODIFY COLUMN j INT DEFAULT 666;
+-- t2 --
+Version: Any
+Fragment type: 9
+K Value: 6
+Min load factor: 78
+Max load factor: 80
+Temporary table: no
+Number of attributes: 4
+Number of primary keys: 1
+Length of frm data: 331
+Row Checksum: 1
+Row GCI: 1
+SingleUserMode: 0
+ForceVarPart: 1
+FragmentCount: 2
+TableStatus: Retrieved
+-- Attributes --
+i Int PRIMARY KEY DISTRIBUTION KEY AT=FIXED ST=MEMORY AUTO_INCR
+j Int NULL AT=FIXED ST=MEMORY DEFAULT 666
+f Float NOT NULL AT=FIXED ST=MEMORY DEFAULT 6.600000
+d Double NULL AT=FIXED ST=MEMORY DEFAULT 8.800000
+
+-- Indexes --
+PRIMARY KEY(i) - UniqueHashIndex
+Index
+Index
+Index
+
+
+NDBT_ProgramExit: 0 - OK
+
+INSERT INTO t2 VALUES();
+SELECT * FROM t2 ORDER BY i;
+i j f d
+1 6 6.6 8.8
+10 10 10 10
+11 666 6.6 8.8
+*************************************************************
+* Test that online alter of default values fails
+*************************************************************
+ALTER ONLINE TABLE t2 MODIFY COLUMN j INT DEFAULT 888;
+ERROR 42000: This version of MySQL doesn't yet support 'ALTER ONLINE TABLE t2 MODIFY COLUMN j INT DEFAULT 888'
+DROP TABLE IF EXISTS t2;
+**************************************************************
+* Test not null-after-defaults example that failed previously
+**************************************************************
+CREATE TABLE t1 (a int primary key, b int default 12, c char not null) engine=ndb;
+-- t1 --
+Version: Any
+Fragment type: 9
+K Value: 6
+Min load factor: 78
+Max load factor: 80
+Temporary table: no
+Number of attributes: 3
+Number of primary keys: 1
+Length of frm data: 267
+Row Checksum: 1
+Row GCI: 1
+SingleUserMode: 0
+ForceVarPart: 1
+FragmentCount: 2
+TableStatus: Retrieved
+-- Attributes --
+a Int PRIMARY KEY DISTRIBUTION KEY AT=FIXED ST=MEMORY
+b Int NULL AT=FIXED ST=MEMORY DEFAULT 12
+c Char(1;latin1_swedish_ci) NOT NULL AT=FIXED ST=MEMORY
+
+-- Indexes --
+PRIMARY KEY(a) - UniqueHashIndex
+PRIMARY(a) - OrderedIndex
+
+
+NDBT_ProgramExit: 0 - OK
+
+DROP TABLE t1;
+**************************************************************
+* Test mix of null, not-null, default etc..
+**************************************************************
+CREATE TABLE t1 (a int primary key,
+b int default 12,
+c char not null,
+d varchar(6) default 'Daniel',
+e char(3) default 'Stu',
+f enum('NBFry','Kebab') default 'NBFry',
+g set('Chips','Pie','Fish') default 'Fish,Chips',
+h enum('Pig','Lion') not null,
+i char(2) default '66') engine=ndb;
+-- t1 --
+Version: Any
+Fragment type: 9
+K Value: 6
+Min load factor: 78
+Max load factor: 80
+Temporary table: no
+Number of attributes: 9
+Number of primary keys: 1
+Length of frm data: 409
+Row Checksum: 1
+Row GCI: 1
+SingleUserMode: 0
+ForceVarPart: 1
+FragmentCount: 2
+TableStatus: Retrieved
+-- Attributes --
+a Int PRIMARY KEY DISTRIBUTION KEY AT=FIXED ST=MEMORY
+b Int NULL AT=FIXED ST=MEMORY DEFAULT 12
+c Char(1;latin1_swedish_ci) NOT NULL AT=FIXED ST=MEMORY
+d Varchar(6;latin1_swedish_ci) NULL AT=SHORT_VAR ST=MEMORY DEFAULT "Daniel"
+e Char(3;latin1_swedish_ci) NULL AT=FIXED ST=MEMORY DEFAULT "Stu"
+f Char(1;binary) NULL AT=FIXED ST=MEMORY DEFAULT "0x01"
+g Char(1;binary) NULL AT=FIXED ST=MEMORY DEFAULT "0x05"
+h Char(1;binary) NOT NULL AT=FIXED ST=MEMORY
+i Char(2;latin1_swedish_ci) NULL AT=FIXED ST=MEMORY DEFAULT "66"
+
+-- Indexes --
+PRIMARY KEY(a) - UniqueHashIndex
+PRIMARY(a) - OrderedIndex
+
+
+NDBT_ProgramExit: 0 - OK
+
+DROP TABLE t1;
+******************************************
+* Test binary default with null char value
+******************************************
+CREATE TABLE t1 (a int primary key,
+b binary(10) default 0x4142430045464748494a,
+c varbinary(100) default 0x4142430045464748494a) engine=ndb;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) NOT NULL,
+ `b` binary(10) DEFAULT 'ABC\0EFGHIJ',
+ `c` varbinary(100) DEFAULT 'ABC\0EFGHIJ',
+ PRIMARY KEY (`a`)
+) ENGINE=ndbcluster DEFAULT CHARSET=latin1
+-- t1 --
+Version: Any
+Fragment type: 9
+K Value: 6
+Min load factor: 78
+Max load factor: 80
+Temporary table: no
+Number of attributes: 3
+Number of primary keys: 1
+Length of frm data: 284
+Row Checksum: 1
+Row GCI: 1
+SingleUserMode: 0
+ForceVarPart: 1
+FragmentCount: 2
+TableStatus: Retrieved
+-- Attributes --
+a Int PRIMARY KEY DISTRIBUTION KEY AT=FIXED ST=MEMORY
+b Binary(10) NULL AT=FIXED ST=MEMORY DEFAULT 0x4142430045464748494A
+c Varbinary(100) NULL AT=SHORT_VAR ST=MEMORY DEFAULT 0x4142430045464748494A
+
+-- Indexes --
+PRIMARY KEY(a) - UniqueHashIndex
+PRIMARY(a) - OrderedIndex
+
+
+NDBT_ProgramExit: 0 - OK
+
+DROP TABLE t1;
+End of ndb native default support test
=== modified file 'mysql-test/suite/ndb/r/ndb_restore_promotion.result'
--- a/mysql-test/suite/ndb/r/ndb_restore_promotion.result 2009-08-18 13:02:20 +0000
+++ b/mysql-test/suite/ndb/r/ndb_restore_promotion.result 2010-04-29 14:52:05 +0000
@@ -197,3 +197,40 @@ a c d e
3 c D e
4 c d E
drop table t1;
+create table subject(pk int primary key, band varchar(50), pos int) engine=ndb;
+insert into subject values (1, 'Elbow', 1), (2, 'Franz Ferdinand', 2), (3, 'Proclaimers', 3);
+insert into subject values (4, 'David Bowie', 4), (5, 'Rufus Wainwright', 1);
+select * from subject order by pk;
+pk band pos
+1 Elbow 1
+2 Franz Ferdinand 2
+3 Proclaimers 3
+4 David Bowie 4
+5 Rufus Wainwright 1
+**************************
+Performing backup of table
+**************************
+******************
+Throwing away data
+******************
+delete from subject;
+select * from subject order by pk;
+pk band pos
+*******************************************************
+Modifying table to include new, native defaulted column
+*******************************************************
+alter table subject add column song varchar(50) default 'Unknown';
+***********************************************************
+Restoring data back into table and picking up default value
+***********************************************************
+****************************************************
+All restored entries should have song name 'Unknown'
+****************************************************
+select * from subject order by pk;
+pk band pos song
+1 Elbow 1 Unknown
+2 Franz Ferdinand 2 Unknown
+3 Proclaimers 3 Unknown
+4 David Bowie 4 Unknown
+5 Rufus Wainwright 1 Unknown
+drop table subject;
=== added file 'mysql-test/suite/ndb/t/ndb_native_default_support.test'
--- a/mysql-test/suite/ndb/t/ndb_native_default_support.test 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/ndb/t/ndb_native_default_support.test 2010-04-29 14:52:05 +0000
@@ -0,0 +1,314 @@
+#############################################################
+# Author: Guangbao Ni
+# Date: 2008-12
+# Purpose: ndb native default support test
+##############################################################
+
+-- source include/have_ndb.inc
+-- source include/ndb_default_cluster.inc
+
+--disable_warnings
+DROP TABLE IF EXISTS t1,bit1;
+DROP DATABASE IF EXISTS mysqltest;
+--enable_warnings
+
+CREATE DATABASE mysqltest;
+USE mysqltest;
+###############################################################
+# BASIC SQL STATEMENT TEST FOR NDB NATIVE DEFAULT VALUE SUPPORT
+###############################################################
+# Create table with default values for some types.
+# Create table for bit type.
+# Test cases include:
+# 1. Create table with default values
+# 2. Insert statement:
+# --Insert default values into, the default values can be inserted into table correctly
+# --Insert record supplied by client, it can inserted correctly
+# --Insert record (including default value and value supplied by client)
+# 3. Update statement:
+# --Update with primary key condition
+# --Update with non-primary key condtion
+# 4. Replace statement:
+# --Replace with default values when the record isn't existed in table
+# --Replace with part default values and part value supplied by client when the record isn't existed in table.
+# --Replace with part default values and part value suppliced by client when the record already existed in table.
+# 5. Delete statement:
+
+--echo ***************************************************************
+--echo * BASIC SQL STATEMENT TEST FOR NDB NATIVE DEFAULT VALUE SUPPORT
+--echo ***************************************************************
+
+CREATE TABLE t1(
+ i INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
+ j INT DEFAULT 6,
+ f FLOAT NOT NULL DEFAULT 6.6,
+ d DOUBLE DEFAULT 8.8,
+ d2 DOUBLE NOT NULL, #d2 gets 'data-type-specific default', i.e. 0.
+ ch CHAR(19) DEFAULT "aaa",
+ vch VARCHAR(19) DEFAULT "bbb",
+ b BINARY(19) DEFAULT "ccc",
+ vb VARBINARY(19) DEFAULT "ddd",
+ blob1 BLOB,
+ text1 TEXT,
+ timestamp_c TIMESTAMP DEFAULT CURRENT_TIMESTAMP
+)ENGINE=NDB;
+
+--disable_warnings
+INSERT INTO t1 VALUES(),();
+
+INSERT INTO t1 VALUES(
+ 10, 10, 10.0, 10.0, 10.0,
+ "nnnnn", "nnnnn", "nnnnn", "nnnnn", "nnnnn", "nnnnn",
+ "2008-11-16 08:13:32");
+INSERT INTO t1(i, ch) VALUES(11, "mmm");
+--replace_column 12 CURRENT_TIMESTAMP
+SELECT i, j, f, d, d2, ch, vch, HEX(b), HEX(vb), HEX(blob1), text1, timestamp_c FROM t1 ORDER BY i;
+
+UPDATE t1 SET ch = "xxx" WHERE i = 10;
+--replace_column 12 CURRENT_TIMESTAMP
+SELECT i, j, f, d, d2, ch, vch, HEX(b), HEX(vb), HEX(blob1), text1, timestamp_c FROM t1 ORDER BY i;
+
+UPDATE t1 SET blob1 = "yyy" WHERE j = 10;
+--replace_column 12 CURRENT_TIMESTAMP
+SELECT i, j, f, d, d2, ch, vch, HEX(b), HEX(vb), HEX(blob1), text1, timestamp_c FROM t1 ORDER BY i;
+
+REPLACE INTO t1(i, j, ch) VALUES(1, 1, "zzz");
+REPLACE INTO t1(i, j, ch) VALUES(20, 20, "www");
+--enable_warnings
+--replace_column 12 CURRENT_TIMESTAMP
+SELECT i, j, f, d, d2, ch, vch, HEX(b), HEX(vb), HEX(blob1), text1, timestamp_c FROM t1 ORDER BY i;
+DELETE FROM t1 WHERE i > 9;
+--replace_column 12 CURRENT_TIMESTAMP
+SELECT i, j, f, d, d2, ch, vch, HEX(b), HEX(vb), HEX(blob1), text1, timestamp_c FROM t1 ORDER BY i;
+
+#Test BIT TYPE
+CREATE TABLE bit1(
+ pk INT AUTO_INCREMENT NOT NULL PRIMARY KEY,
+ b1 BIT(3) DEFAULT B'111',
+ b2 BIT(9) DEFAULT B'101',
+ b3 BIT(23) DEFAULT B'110',
+ b4 BIT(37) DEFAULT B'011',
+ b5 BIT(63) DEFAULT B'101011'
+)ENGINE = NDB;
+
+INSERT INTO bit1 VALUES();
+INSERT INTO bit1(b1,b4) VALUES(B'101',B'111');
+SELECT pk,BIN(b1),BIN(b2),BIN(b3),BIN(b4),BIN(b5) FROM bit1 ORDER BY pk;
+
+UPDATE bit1 SET b5=B'11111' WHERE pk = 1;
+REPLACE INTO bit1(pk, b3) VALUES(2, B'1');
+REPLACE INTO bit1(pk, b3) VALUES(6, B'101');
+SELECT pk,BIN(b1),BIN(b2),BIN(b3),BIN(b4),BIN(b5) FROM bit1 ORDER BY pk;
+
+DELETE FROM bit1 WHERE pk = 2;
+SELECT pk,BIN(b1),BIN(b2),BIN(b3),BIN(b4),BIN(b5) FROM bit1 ORDER BY pk;
+
+#############################################################
+# ALTER TABLE WITH DEFAULT VALUES TEST
+#############################################################
+--echo ********************************************************
+--echo * Alter table to add column with default value
+--echo ********************************************************
+ALTER TABLE t1 ADD COLUMN ch2 CHAR(30) DEFAULT "alter table";
+--replace_column 12 CURRENT_TIMESTAMP
+SELECT i, j, f, d, d2, ch, vch, HEX(b), HEX(vb), HEX(blob1), text1, timestamp_c, ch2 FROM t1 ORDER BY i;
+--disable_warnings
+INSERT INTO t1 VALUES();
+--enable_warnings
+--replace_column 12 CURRENT_TIMESTAMP
+SELECT i, j, f, d, d2, ch, vch, HEX(b), HEX(vb), HEX(blob1), text1, timestamp_c, ch2 FROM t1 ORDER BY i;
+
+--echo ********************************************************
+--echo * Alter table with default value can fail safely
+--echo ********************************************************
+--disable_warnings
+--error 1060
+ALTER TABLE t1 ADD COLUMN ch2 CHAR(30) DEFAULT "alter table";
+--error 1067
+ALTER TABLE t1 ADD COLUMN ch3 CHAR(3) DEFAULT "alter table";
+INSERT INTO t1 VALUES();
+--enable_warnings
+--replace_column 12 CURRENT_TIMESTAMP
+SELECT i, j, f, d, d2, ch, vch, HEX(b), HEX(vb), HEX(blob1), text1, timestamp_c, ch2 FROM t1 ORDER BY i;
+
+##############################################################
+# BACKUP AND RESTORE TEST FOR TABLE WITH DEFAULT VALUES
+##############################################################
+#the above two tables are backuped, they can restore correctly.
+#The default values can be inserted correctly after restored.
+--echo ********************************************************
+--echo * The tables with default values BACKUP and RESTORE test
+--echo ********************************************************
+--source include/ndb_backup.inc
+DROP TABLE IF EXISTS t1, bit1;
+
+--echo ********************************************************
+--echo * Begin to restore data from backup
+--echo ********************************************************
+--exec $NDB_RESTORE --no-defaults -b $the_backup_id -n 1 -A -m -r --print --print_meta $NDB_BACKUPS-$the_backup_id >> $NDB_TOOLS_OUTPUT
+--exec $NDB_RESTORE --no-defaults -b $the_backup_id -n 2 -A -r --print --print_meta $NDB_BACKUPS-$the_backup_id >> $NDB_TOOLS_OUTPUT
+
+--sorted_result
+SHOW TABLES;
+--let ndb_desc_opts= -d mysqltest t1
+--source include/ndb_desc_print.inc
+--let ndb_desc_opts= -d mysqltest bit1
+--source include/ndb_desc_print.inc
+SELECT pk,BIN(b1),BIN(b2),BIN(b3),BIN(b4),BIN(b5) FROM bit1 ORDER BY pk;
+--replace_column 12 CURRENT_TIMESTAMP
+SELECT i, j, f, d, d2, ch, vch, HEX(b), HEX(vb), HEX(blob1), text1, timestamp_c, ch2 FROM t1 ORDER BY i;
+
+--disable_warnings
+INSERT INTO t1(i, ch) VALUES(99, "restore");
+--enable_warnings
+INSERT INTO bit1(pk, b5) VALUES(99, B'11111111');
+SELECT pk,BIN(b1),BIN(b2),BIN(b3),BIN(b4),BIN(b5) FROM bit1 ORDER BY pk;
+--replace_column 12 CURRENT_TIMESTAMP
+SELECT i, j, f, d, d2, ch, vch, HEX(b), HEX(vb), HEX(blob1), text1, timestamp_c, ch2 FROM t1 ORDER BY i;
+DROP TABLE IF EXISTS t1, bit1;
+
+
+--exec $NDB_RESTORE --no-defaults -b $the_backup_id -n 1 -A -m -r --print_meta $NDB_BACKUPS-$the_backup_id >> $NDB_TOOLS_OUTPUT
+--exec $NDB_RESTORE --no-defaults -b $the_backup_id -n 2 -A -r --print_meta $NDB_BACKUPS-$the_backup_id >> $NDB_TOOLS_OUTPUT
+--sorted_result
+SHOW TABLES;
+--replace_column 1 MAX_VALUE 12 CURRENT_TIMESTAMP
+SELECT i, j, f, d, d2, ch, vch, HEX(b), HEX(vb), HEX(blob1), text1, timestamp_c, ch2 FROM t1 WHERE i >= (SELECT MAX(i) FROM t1) ORDER BY i;
+
+DROP TABLE IF EXISTS t1, bit1;
+DROP DATABASE mysqltest;
+
+###############################################################################
+# RESTORE THE BACKUP FROM 6.3 OR 6.4, WHICH DON'T SUPPORT NATIVE DEFAULT VALUE
+# SO DEFAULT VALUES AREN'T STORED IN NDBD KERNEL
+###############################################################################
+--echo ******************************************************************************
+--echo * Restore the backup from 6.3 or 6.4, which don't support native default value
+--echo ******************************************************************************
+
+--exec $NDB_RESTORE --no-defaults -b 1 -n 1 -m -r $MYSQL_TEST_DIR/std_data/ndb_backup_before_native_default >> $NDB_TOOLS_OUTPUT
+--exec $NDB_RESTORE --no-defaults -b 1 -n 2 -r $MYSQL_TEST_DIR/std_data/ndb_backup_before_native_default >> $NDB_TOOLS_OUTPUT
+
+USE test;
+--sorted_result
+SHOW TABLES;
+SHOW CREATE TABLE t1;
+SHOW CREATE TABLE bit1;
+--replace_column 12 CURRENT_TIMESTAMP
+SELECT i, j, f, d, d2, ch, vch, HEX(b), HEX(vb), HEX(blob1), text1, timestamp_c FROM t1 ORDER BY i;
+SELECT pk,BIN(b1),BIN(b2),BIN(b3),BIN(b4),BIN(b5) FROM bit1 ORDER BY pk;
+--disable_warnings
+INSERT INTO t1 VALUES();
+UPDATE t1 SET ch = "RESTORE FROM 6.3" WHERE i = 12;
+REPLACE INTO t1(i, j, ch) VALUES(20, 20, "RESTORE FROM 6.3");
+--enable_warnings
+--replace_column 12 CURRENT_TIMESTAMP
+SELECT i, j, f, d, d2, ch, vch, HEX(b), HEX(vb), HEX(blob1), text1, timestamp_c FROM t1 ORDER BY i;
+
+INSERT INTO bit1 VALUES();
+UPDATE bit1 SET b5=b'1111111' WHERE pk = 1;
+REPLACE INTO bit1(pk, b3) VALUES(6, B'110011');
+SELECT pk,BIN(b1),BIN(b2),BIN(b3),BIN(b4),BIN(b5) FROM bit1 ORDER BY pk;
+
+#########################################################################
+# OFFLINE ALTER OF 'OLD' TABLE WITH NO DEFAULTS TO 'NEW' TABLE
+# WITH NATIVE DEFAULTS.
+#########################################################################
+--echo ********************************************************************************
+--echo * Alter table restoring from 6.3 backup to new table with native default support
+--echo ********************************************************************************
+--let ndb_desc_opts= -d test t1
+--source include/ndb_desc_print.inc
+
+ALTER TABLE t1 CHANGE COLUMN j j INT DEFAULT 6;
+
+--let ndb_desc_opts= -d test t1
+--source include/ndb_desc_print.inc
+
+--disable_warnings
+INSERT INTO t1(i, ch) VALUES(99, "native default support");
+--enable_warnings
+--replace_column 12 CURRENT_TIMESTAMP
+SELECT i, j, f, d, d2, ch, vch, HEX(b), HEX(vb), HEX(blob1), text1, timestamp_c FROM t1 ORDER BY i;
+
+DROP TABLE IF EXISTS t1, bit1;
+--echo *************************************************************
+--echo * Test adding a unique index to a column with a default value
+--echo *************************************************************
+CREATE TABLE t2(
+ i INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
+ j INT DEFAULT 6,
+ f FLOAT NOT NULL DEFAULT 6.6,
+ d DOUBLE DEFAULT 8.8,
+ UNIQUE INDEX t2_unique_index(j)
+)ENGINE =NDB;
+INSERT INTO t2 VALUES();
+--error 1062
+INSERT INTO t2 VALUES();
+INSERT INTO t2 VALUES(10, 10, 10.0, 10.0);
+SELECT * FROM t2 ORDER BY i;
+
+--echo *************************************************************
+--echo * Test offline alter of default values
+--echo *************************************************************
+ALTER TABLE t2 MODIFY COLUMN j INT DEFAULT 666;
+
+--let ndb_desc_opts= -d test t2
+--source include/ndb_desc_print.inc
+INSERT INTO t2 VALUES();
+SELECT * FROM t2 ORDER BY i;
+
+--echo *************************************************************
+--echo * Test that online alter of default values fails
+--echo *************************************************************
+--error 1235
+ALTER ONLINE TABLE t2 MODIFY COLUMN j INT DEFAULT 888;
+
+DROP TABLE IF EXISTS t2;
+
+--echo **************************************************************
+--echo * Test not null-after-defaults example that failed previously
+--echo **************************************************************
+
+CREATE TABLE t1 (a int primary key, b int default 12, c char not null) engine=ndb;
+--let ndb_desc_opts= -d test t1
+--source include/ndb_desc_print.inc
+
+DROP TABLE t1;
+
+--echo **************************************************************
+--echo * Test mix of null, not-null, default etc..
+--echo **************************************************************
+
+CREATE TABLE t1 (a int primary key,
+ b int default 12,
+ c char not null,
+ d varchar(6) default 'Daniel',
+ e char(3) default 'Stu',
+ f enum('NBFry','Kebab') default 'NBFry',
+ g set('Chips','Pie','Fish') default 'Fish,Chips',
+ h enum('Pig','Lion') not null,
+ i char(2) default '66') engine=ndb;
+--let ndb_desc_opts= -d test t1
+--source include/ndb_desc_print.inc
+
+DROP TABLE t1;
+
+--echo ******************************************
+--echo * Test binary default with null char value
+--echo ******************************************
+
+CREATE TABLE t1 (a int primary key,
+ b binary(10) default 0x4142430045464748494a,
+ c varbinary(100) default 0x4142430045464748494a) engine=ndb;
+
+SHOW CREATE TABLE t1;
+
+--let ndb_desc_opts= -d test t1
+--source include/ndb_desc_print.inc
+
+DROP TABLE t1;
+
+
+
+--echo End of ndb native default support test
=== modified file 'mysql-test/suite/ndb/t/ndb_restore_promotion.test'
--- a/mysql-test/suite/ndb/t/ndb_restore_promotion.test 2009-08-18 13:21:50 +0000
+++ b/mysql-test/suite/ndb/t/ndb_restore_promotion.test 2010-04-29 14:52:05 +0000
@@ -256,3 +256,46 @@ create table t1(c char(1),
select a,c,d,e from t1 order by a;
drop table t1;
+
+# Testcase for restore with native default added to table (WL4197)
+create table subject(pk int primary key, band varchar(50), pos int) engine=ndb;
+
+insert into subject values (1, 'Elbow', 1), (2, 'Franz Ferdinand', 2), (3, 'Proclaimers', 3);
+insert into subject values (4, 'David Bowie', 4), (5, 'Rufus Wainwright', 1);
+
+select * from subject order by pk;
+
+--echo **************************
+--echo Performing backup of table
+--echo **************************
+
+--source include/ndb_backup.inc
+
+--echo ******************
+--echo Throwing away data
+--echo ******************
+delete from subject;
+
+select * from subject order by pk;
+
+--echo *******************************************************
+--echo Modifying table to include new, native defaulted column
+--echo *******************************************************
+alter table subject add column song varchar(50) default 'Unknown';
+
+--echo ***********************************************************
+--echo Restoring data back into table and picking up default value
+--echo ***********************************************************
+
+# Note testcase nastily assumes 2 nodes, called 1 + 2.
+--exec $NDB_RESTORE --no-defaults -b $the_backup_id -n 1 -r --print --print_meta --skip-table-check $NDB_BACKUPS-$the_backup_id >> $NDB_TOOLS_OUTPUT
+--exec $NDB_RESTORE --no-defaults -b $the_backup_id -n 2 -r --print --print_meta --skip-table-check $NDB_BACKUPS-$the_backup_id >> $NDB_TOOLS_OUTPUT
+
+--echo ****************************************************
+--echo All restored entries should have song name 'Unknown'
+--echo ****************************************************
+
+select * from subject order by pk;
+
+drop table subject;
+# End of testcase for WL4197
\ No newline at end of file
=== modified file 'mysql-test/suite/rpl_ndb/r/rpl_ndb_2ndb.result'
--- a/mysql-test/suite/rpl_ndb/r/rpl_ndb_2ndb.result 2008-02-11 14:06:07 +0000
+++ b/mysql-test/suite/rpl_ndb/r/rpl_ndb_2ndb.result 2010-04-29 14:52:05 +0000
@@ -266,14 +266,14 @@ select *
from t1
order by id;
id b1 vc bc d f total y t u v
-2 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1965-11-14 NULL NULL
+2 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1965-11-14 NULL default
3 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1905-11-14 7 default
-4 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1985-11-14 NULL NULL
+4 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1985-11-14 NULL default
20 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1965-11-14 7 explicit
-42 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1905-11-14 NULL NULL
+42 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1905-11-14 NULL default
50 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1985-11-14 NULL explicit
-142 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1995-11-14 NULL NULL
-412 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 2005-11-14 NULL NULL
+142 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 1995-11-14 NULL default
+412 1 Testing MySQL databases is a cool Must make it bug free for the customer 654321.4321 15.21 0 1965 2005-11-14 NULL default
--- Perform basic operation on master ---
--- and ensure replicated correctly ---
--- Update t1 on master --
@@ -298,11 +298,11 @@ FROM t1
WHERE id < 100
ORDER BY id;
id b1 vc bc d f total y t u v
-2 0 Testing MySQL databases is a cool updated 654321.4321 15.21 0 1965 2006-02-22 NULL NULL
+2 0 Testing MySQL databases is a cool updated 654321.4321 15.21 0 1965 2006-02-22 NULL default
3 0 Testing MySQL databases is a cool updated 654321.4321 15.21 0 1965 2006-02-22 7 default
-4 0 Testing MySQL databases is a cool updated 654321.4321 15.21 0 1965 2006-02-22 NULL NULL
+4 0 Testing MySQL databases is a cool updated 654321.4321 15.21 0 1965 2006-02-22 NULL default
20 0 Testing MySQL databases is a cool updated 654321.4321 15.21 0 1965 2006-02-22 7 explicit
-42 0 Testing MySQL databases is a cool updated 654321.4321 15.21 0 1965 2006-02-22 NULL NULL
+42 0 Testing MySQL databases is a cool updated 654321.4321 15.21 0 1965 2006-02-22 NULL default
50 0 Testing MySQL databases is a cool updated 654321.4321 15.21 0 1965 2006-02-22 NULL explicit
--- Remove a record from t1 on master ---
DELETE FROM t1 WHERE id = 412;
=== modified file 'mysql-test/suite/rpl_ndb/r/rpl_ndb_extraCol.result'
--- a/mysql-test/suite/rpl_ndb/r/rpl_ndb_extraCol.result 2010-03-16 07:53:04 +0000
+++ b/mysql-test/suite/rpl_ndb/r/rpl_ndb_extraCol.result 2010-04-29 14:52:05 +0000
@@ -31,9 +31,9 @@ a b c
*** Select from slave ***
SELECT * FROM t1 ORDER BY a;
a b c d e
-1 2 TEXAS NULL NULL
-2 1 AUSTIN NULL NULL
-3 4 QA NULL NULL
+1 2 TEXAS 2 TEST
+2 1 AUSTIN 2 TEST
+3 4 QA 2 TEST
SET GLOBAL SLAVE_TYPE_CONVERSIONS = @saved_slave_type_conversions;
*** Drop t1 ***
DROP TABLE t1;
@@ -395,9 +395,9 @@ a b c
*** Select from slave ***
SELECT * FROM t7 ORDER BY a;
a b c d e
-1 b1b1 Kyle NULL NULL
-2 b1b1 JOE NULL NULL
-3 b1b1 QA NULL NULL
+1 b1b1 Kyle 0000-00-00 00:00:00 Extra Column Testing
+2 b1b1 JOE 0000-00-00 00:00:00 Extra Column Testing
+3 b1b1 QA 0000-00-00 00:00:00 Extra Column Testing
*** Drop t7 ***
DROP TABLE t7;
*** Create t8 on slave ***
@@ -592,9 +592,9 @@ a b c
*** Select on Slave ***
SELECT * FROM t12 ORDER BY a;
a b f c e
-1 b1b1b1b1b1b1b1b1 Kyle NULL NULL
-2 b1b1b1b1b1b1b1b1 JOE NULL NULL
-3 b1b1b1b1b1b1b1b1 QA NULL NULL
+1 b1b1b1b1b1b1b1b1 Kyle test 1
+2 b1b1b1b1b1b1b1b1 JOE test 1
+3 b1b1b1b1b1b1b1b1 QA test 1
*** Drop t12 ***
DROP TABLE t12;
**** Extra Colums End ****
@@ -624,9 +624,9 @@ a b c
*** Select on Slave ****
SELECT * FROM t13 ORDER BY a;
a b c d e
-1 b1b1b1b1b1b1b1b1 Kyle NULL CURRENT_TIMESTAMP
-2 b1b1b1b1b1b1b1b1 JOE NULL CURRENT_TIMESTAMP
-3 b1b1b1b1b1b1b1b1 QA NULL CURRENT_TIMESTAMP
+1 b1b1b1b1b1b1b1b1 Kyle 1 CURRENT_TIMESTAMP
+2 b1b1b1b1b1b1b1b1 JOE 1 CURRENT_TIMESTAMP
+3 b1b1b1b1b1b1b1b1 QA 1 CURRENT_TIMESTAMP
*** Drop t13 ***
DROP TABLE t13;
*** 22117 END ***
@@ -660,9 +660,9 @@ c1 c2 c3 c4 c5
*** Select on Slave ****
SELECT * FROM t14 ORDER BY c1;
c1 c2 c3 c4 c5 c6 c7
-1 1.00 Replication Testing Extra Col b1b1b1b1b1b1b1b1 Kyle NULL CURRENT_TIMESTAMP
-2 2.00 This Test Should work b1b1b1b1b1b1b1b1 JOE NULL CURRENT_TIMESTAMP
-3 3.00 If is does not, I will open a bug b1b1b1b1b1b1b1b1 QA NULL CURRENT_TIMESTAMP
+1 1.00 Replication Testing Extra Col b1b1b1b1b1b1b1b1 Kyle 1 CURRENT_TIMESTAMP
+2 2.00 This Test Should work b1b1b1b1b1b1b1b1 JOE 1 CURRENT_TIMESTAMP
+3 3.00 If is does not, I will open a bug b1b1b1b1b1b1b1b1 QA 1 CURRENT_TIMESTAMP
*** Create t14a on slave ***
STOP SLAVE;
RESET SLAVE;
@@ -690,9 +690,9 @@ c1 c4 c5
*** Select on Slave ****
SELECT * FROM t14a ORDER BY c1;
c1 c4 c5 c6 c7
-1 b1b1b1b1b1b1b1b1 Kyle NULL CURRENT_TIMESTAMP
-2 b1b1b1b1b1b1b1b1 JOE NULL CURRENT_TIMESTAMP
-3 b1b1b1b1b1b1b1b1 QA NULL CURRENT_TIMESTAMP
+1 b1b1b1b1b1b1b1b1 Kyle 1 CURRENT_TIMESTAMP
+2 b1b1b1b1b1b1b1b1 JOE 1 CURRENT_TIMESTAMP
+3 b1b1b1b1b1b1b1b1 QA 1 CURRENT_TIMESTAMP
STOP SLAVE;
RESET SLAVE;
*** Master Drop c5 ***
@@ -717,12 +717,12 @@ c1 c4
*** Select on Slave ****
SELECT * FROM t14a ORDER BY c1;
c1 c4 c5 c6 c7
-1 b1b1b1b1b1b1b1b1 Kyle NULL CURRENT_TIMESTAMP
-2 b1b1b1b1b1b1b1b1 JOE NULL CURRENT_TIMESTAMP
-3 b1b1b1b1b1b1b1b1 QA NULL CURRENT_TIMESTAMP
-4 b1b1b1b1b1b1b1b1 NULL NULL CURRENT_TIMESTAMP
-5 b1b1b1b1b1b1b1b1 NULL NULL CURRENT_TIMESTAMP
-6 b1b1b1b1b1b1b1b1 NULL NULL CURRENT_TIMESTAMP
+1 b1b1b1b1b1b1b1b1 Kyle 1 CURRENT_TIMESTAMP
+2 b1b1b1b1b1b1b1b1 JOE 1 CURRENT_TIMESTAMP
+3 b1b1b1b1b1b1b1b1 QA 1 CURRENT_TIMESTAMP
+4 b1b1b1b1b1b1b1b1 NULL 1 CURRENT_TIMESTAMP
+5 b1b1b1b1b1b1b1b1 NULL 1 CURRENT_TIMESTAMP
+6 b1b1b1b1b1b1b1b1 NULL 1 CURRENT_TIMESTAMP
*** connect to master and drop columns ***
ALTER TABLE t14 DROP COLUMN c2;
ALTER TABLE t14 DROP COLUMN c4;
@@ -735,9 +735,9 @@ c1 c3 c5
*** Select from Slave ***
SELECT * FROM t14 ORDER BY c1;
c1 c3 c5 c6 c7
-1 Replication Testing Extra Col Kyle NULL CURRENT_TIMESTAMP
-2 This Test Should work JOE NULL CURRENT_TIMESTAMP
-3 If is does not, I will open a bug QA NULL CURRENT_TIMESTAMP
+1 Replication Testing Extra Col Kyle 1 CURRENT_TIMESTAMP
+2 This Test Should work JOE 1 CURRENT_TIMESTAMP
+3 If is does not, I will open a bug QA 1 CURRENT_TIMESTAMP
*** Drop t14 ***
DROP TABLE t14;
*** Create t15 on slave ***
@@ -768,9 +768,9 @@ c1 c2 c3 c4 c5
*** Select on Slave ****
SELECT * FROM t15 ORDER BY c1;
c1 c2 c3 c4 c5 c6 c7
-1 1.00 Replication Testing Extra Col b1b1b1b1b1b1b1b1 Kyle NULL CURRENT_TIMESTAMP
-2 2.00 This Test Should work b1b1b1b1b1b1b1b1 JOE NULL CURRENT_TIMESTAMP
-3 3.00 If is does not, I will open a bug b1b1b1b1b1b1b1b1 QA NULL CURRENT_TIMESTAMP
+1 1.00 Replication Testing Extra Col b1b1b1b1b1b1b1b1 Kyle 1 CURRENT_TIMESTAMP
+2 2.00 This Test Should work b1b1b1b1b1b1b1b1 JOE 1 CURRENT_TIMESTAMP
+3 3.00 If is does not, I will open a bug b1b1b1b1b1b1b1b1 QA 1 CURRENT_TIMESTAMP
*** Add column on master that is a Extra on Slave ***
ALTER TABLE t15 ADD COLUMN c6 INT AFTER c5;
********************************************
@@ -831,9 +831,9 @@ c1 c2 c3 c4 c5 c6
*** Try to select from slave ****
SELECT * FROM t15 ORDER BY c1;
c1 c2 c3 c4 c5 c6 c7
-1 1.00 Replication Testing Extra Col b1b1b1b1b1b1b1b1 Kyle NULL CURRENT_TIMESTAMP
-2 2.00 This Test Should work b1b1b1b1b1b1b1b1 JOE NULL CURRENT_TIMESTAMP
-3 3.00 If is does not, I will open a bug b1b1b1b1b1b1b1b1 QA NULL CURRENT_TIMESTAMP
+1 1.00 Replication Testing Extra Col b1b1b1b1b1b1b1b1 Kyle 1 CURRENT_TIMESTAMP
+2 2.00 This Test Should work b1b1b1b1b1b1b1b1 JOE 1 CURRENT_TIMESTAMP
+3 3.00 If is does not, I will open a bug b1b1b1b1b1b1b1b1 QA 1 CURRENT_TIMESTAMP
5 2.00 Replication Testing b1b1b1b1b1b1b1b1 Buda 2 CURRENT_TIMESTAMP
*** DROP TABLE t15 ***
DROP TABLE t15;
@@ -865,9 +865,9 @@ c1 c2 c3 c4 c5
*** Select on Slave ****
SELECT * FROM t16 ORDER BY c1;
c1 c2 c3 c4 c5 c6 c7
-1 1.00 Replication Testing Extra Col b1b1b1b1b1b1b1b1 Kyle NULL CURRENT_TIMESTAMP
-2 2.00 This Test Should work b1b1b1b1b1b1b1b1 JOE NULL CURRENT_TIMESTAMP
-3 3.00 If is does not, I will open a bug b1b1b1b1b1b1b1b1 QA NULL CURRENT_TIMESTAMP
+1 1.00 Replication Testing Extra Col b1b1b1b1b1b1b1b1 Kyle 1 CURRENT_TIMESTAMP
+2 2.00 This Test Should work b1b1b1b1b1b1b1b1 JOE 1 CURRENT_TIMESTAMP
+3 3.00 If is does not, I will open a bug b1b1b1b1b1b1b1b1 QA 1 CURRENT_TIMESTAMP
*** Add Partition on master ***
ALTER TABLE t16 PARTITION BY KEY(c1) PARTITIONS 4;
INSERT INTO t16 () VALUES(4,1.00,'Replication Rocks',@b1,'Omer');
=== modified file 'sql/ha_ndbcluster.cc'
--- a/sql/ha_ndbcluster.cc 2010-04-26 10:39:15 +0000
+++ b/sql/ha_ndbcluster.cc 2010-04-29 14:52:05 +0000
@@ -45,6 +45,7 @@
#include "ha_ndbcluster_connection.h"
#include <mysql/plugin.h>
+#include <ndb_version.h>
#ifdef ndb_dynamite
#undef assert
@@ -1260,6 +1261,7 @@ ha_ndbcluster::set_blob_values(const Ndb
ERR_RETURN(ndb_op->getNdbError());
if (field->is_null_in_record_with_offset(row_offset))
{
+ DBUG_PRINT("info", ("Setting Blob %d to NULL", field_no));
if (ndb_blob->setNull() != 0)
ERR_RETURN(ndb_op->getNdbError());
}
@@ -1447,6 +1449,108 @@ int cmp_frm(const NDBTAB *ndbtab, const
DBUG_RETURN(0);
}
+/*
+ Does type support a default value?
+*/
+static bool
+type_supports_default_value(enum_field_types mysql_type)
+{
+ bool ret = (mysql_type != MYSQL_TYPE_BLOB &&
+ mysql_type != MYSQL_TYPE_TINY_BLOB &&
+ mysql_type != MYSQL_TYPE_MEDIUM_BLOB &&
+ mysql_type != MYSQL_TYPE_LONG_BLOB &&
+ mysql_type != MYSQL_TYPE_GEOMETRY);
+
+ return ret;
+}
+
+/**
+ Check that Ndb data dictionary has the same default values
+ as MySQLD for the current table.
+ Called as part of a DBUG check as part of table open
+
+ Returns
+ 0 - Defaults are ok
+ -1 - Some default(s) are bad
+*/
+int ha_ndbcluster::check_default_values(const NDBTAB* ndbtab)
+{
+ /* Debug only method for checking table defaults aligned
+ between MySQLD and Ndb
+ */
+ bool defaults_aligned= true;
+
+ if (ndbtab->hasDefaultValues())
+ {
+ /* Ndb supports native defaults for non-pk columns */
+ my_bitmap_map *old_map= tmp_use_all_columns(table, table->read_set);
+
+ for (uint f=0; f < table_share->fields; f++)
+ {
+ Field* field= table->field[f]; // Use Field struct from MySQLD table rep
+ const NdbDictionary::Column* ndbCol= ndbtab->getColumn(field->field_index);
+ if ((! (field->flags & (PRI_KEY_FLAG |
+ NO_DEFAULT_VALUE_FLAG))) &&
+ (type_supports_default_value(field->real_type())))
+ {
+ /* We expect Ndb to have a native default for this
+ * column
+ */
+ my_ptrdiff_t src_offset= table_share->default_values -
+ field->table->record[0];
+
+ /* Move field by offset to refer to default value */
+ field->move_field_offset(src_offset);
+
+ const uchar* ndb_default= (const uchar*) ndbCol->getDefaultValue();
+
+ if (ndb_default == NULL)
+ /* MySQLD default must also be NULL */
+ defaults_aligned= field->is_null();
+ else
+ {
+ if (field->type() != MYSQL_TYPE_BIT)
+ {
+ defaults_aligned= (0 == field->cmp(ndb_default));
+ }
+ else
+ {
+ longlong value= (static_cast<Field_bit*>(field))->val_int();
+ defaults_aligned= (0 == memcmp(ndb_default,
+ &value,
+ field->used_length()));
+ }
+ }
+
+ field->move_field_offset(-src_offset);
+
+ if (unlikely(!defaults_aligned))
+ {
+ DBUG_PRINT("info", ("Default values differ for column %u",
+ field->field_index));
+ break;
+ }
+ }
+ else
+ {
+ /* We don't expect Ndb to have a native default for this column */
+ if (unlikely(ndbCol->getDefaultValue()))
+ {
+ /* Didn't expect that */
+ DBUG_PRINT("info", ("Column %u has native default, but shouldn't."
+ " Flags=%u, type=%u",
+ field->field_index, field->flags, field->real_type()));
+ defaults_aligned= false;
+ break;
+ }
+ }
+ }
+ tmp_restore_column_map(table->read_set, old_map);
+ }
+
+ return (defaults_aligned? 0: -1);
+}
+
int ha_ndbcluster::get_metadata(THD *thd, const char *path)
{
Ndb *ndb= get_thd_ndb(thd)->ndb;
@@ -1492,6 +1596,11 @@ int ha_ndbcluster::get_metadata(THD *thd
my_free((char*)data, MYF(0));
my_free((char*)pack_data, MYF(0));
+ /* Now check that any Ndb native defaults are aligned
+ with MySQLD defaults
+ */
+ DBUG_ASSERT(check_default_values(tab) == 0);
+
if (error)
goto err;
@@ -2407,7 +2516,20 @@ int ha_ndbcluster::ndb_pk_update_row(THD
{
DBUG_RETURN(error);
}
+
+ /*
+ We are mapping a MySQLD PK changing update to an NdbApi delete
+ and insert.
+ The original PK changing update may not have written new values
+ to all columns, so the write set may be partial.
+ We set the write set to be all columns so that all values are
+ copied from the old row to the new row.
+ */
+ my_bitmap_map *old_map=
+ tmp_use_all_columns(table, table->write_set);
error= ndb_write_row(new_data, TRUE, batched_update);
+ tmp_restore_column_map(table->write_set, old_map);
+
if (error)
{
DBUG_PRINT("info", ("insert failed"));
@@ -3489,7 +3611,10 @@ int ha_ndbcluster::ndb_write_row(uchar *
if (options.optionsPresent != 0)
poptions=&options;
- const MY_BITMAP *user_cols_written_bitmap;
+ const Uint32 bitmapSz= (NDB_MAX_ATTRIBUTES_IN_TABLE + 31)/32;
+ uint32 tmpBitmapSpace[bitmapSz];
+ MY_BITMAP tmpBitmap;
+ MY_BITMAP *user_cols_written_bitmap;
#ifdef HAVE_NDB_BINLOG
uchar* ex_data_buffer= NULL;
#endif
@@ -3502,8 +3627,6 @@ int ha_ndbcluster::ndb_write_row(uchar *
#endif
)
{
- uchar *mask;
-
/* Should we use the supplied table writeset or not?
* For a REPLACE command, we should ignore it, and write
* all columns to get correct REPLACE behaviour.
@@ -3520,6 +3643,7 @@ int ha_ndbcluster::ndb_write_row(uchar *
*/
useWriteSet |= thd->slave_thread;
#endif
+ uchar* mask;
if (useWriteSet)
{
@@ -3607,10 +3731,54 @@ int ha_ndbcluster::ndb_write_row(uchar *
poptions=&options;
}
#endif
- /* Using insert, we write all user visible columns */
- user_cols_written_bitmap= NULL;
+ uchar *mask;
+
+ /* Check whether Ndb table definition includes any default values. */
+ if (m_table->hasDefaultValues())
+ {
+ DBUG_PRINT("info", ("Not sending values for native defaulted columns"));
+
+ /*
+ If Ndb is unaware of the table's defaults, we must provide all column values to the insert.
+ This is done using a NULL column mask.
+ If Ndb is aware of the table's defaults, we only need to provide
+ the columns explicitly mentioned in the write set,
+ plus any extra columns required due to bug#41616.
+ plus the primary key columns required due to bug#42238.
+ */
+ /*
+ The following code for setting user_cols_written_bitmap
+ should be removed after BUG#41616 and Bug#42238 are fixed
+ */
+ /* Copy table write set so that we can add to it */
+ user_cols_written_bitmap= &tmpBitmap;
+ bitmap_init(user_cols_written_bitmap, tmpBitmapSpace,
+ table->write_set->n_bits, false);
+ bitmap_copy(user_cols_written_bitmap, table->write_set);
+
+ for (uint i= 0; i < table->s->fields; i++)
+ {
+ Field *field= table->field[i];
+ if (field->flags & (NO_DEFAULT_VALUE_FLAG | // bug 41616
+ PRI_KEY_FLAG)) // bug 42238
+ {
+ bitmap_set_bit(user_cols_written_bitmap, field->field_index);
+ }
+ }
+
+ mask= (uchar *)(user_cols_written_bitmap->bitmap);
+ }
+ else
+ {
+ /* No defaults in kernel, provide all columns ourselves */
+ DBUG_PRINT("info", ("No native defaults, sending all values"));
+ user_cols_written_bitmap= NULL;
+ mask = NULL;
+ }
+
+ /* Using insert, we write all non default columns */
op= trans->insertTuple(key_rec, (const char *)key_row, m_ndb_record,
- (char *)record, NULL, // No mask
+ (char *)record, mask, // Default value should be masked
poptions, sizeof(NdbOperation::OperationOptions));
}
if (!(op))
@@ -4645,6 +4813,58 @@ void ha_ndbcluster::unpack_record(uchar
}
}
+
+/**
+ Get the default value of the field from default_values of the table.
+*/
+static void get_default_value(void *def_val, Field *field)
+{
+ DBUG_ASSERT(field != NULL);
+
+ my_ptrdiff_t src_offset= field->table->s->default_values - field->table->record[0];
+
+ {
+ if (bitmap_is_set(field->table->read_set, field->field_index))
+ {
+ if (field->type() == MYSQL_TYPE_BIT)
+ {
+ Field_bit *field_bit= static_cast<Field_bit*>(field);
+ if (!field->is_null_in_record_with_offset(src_offset))
+ {
+ field->move_field_offset(src_offset);
+ longlong value= field_bit->val_int();
+ memcpy(def_val, &value, sizeof(longlong));
+ field->move_field_offset(-src_offset);
+ }
+ }
+ else if (field->flags & BLOB_FLAG)
+ {
+ assert(false);
+ }
+ else
+ {
+ field->move_field_offset(src_offset);
+ /* Normal field (not blob or bit type). */
+ if (!field->is_null())
+ {
+ /* Only copy actually used bytes of varstrings. */
+ uint32 actual_length= field->used_length();
+ uchar *src_ptr= field->ptr;
+ field->set_notnull();
+ memcpy(def_val, src_ptr, actual_length);
+#ifdef HAVE_purify
+ if (actual_length < field->pack_length())
+ bzero(((char*)def_val) + actual_length,
+ field->pack_length() - actual_length);
+#endif
+ }
+ field->move_field_offset(-src_offset);
+ /* No action needed for a NULL field. */
+ }
+ }
+ }
+}
+
/*
DBUG_EXECUTE("value", print_results(););
*/
@@ -6399,6 +6619,7 @@ static int create_ndb_column(THD *thd,
NDBCOL::StorageType type= NDBCOL::StorageTypeMemory;
bool dynamic= FALSE;
+ char buf[MAX_ATTR_DEFAULT_VALUE_SIZE];
DBUG_ENTER("create_ndb_column");
// Set name
if (col.setName(field->field_name))
@@ -6409,6 +6630,40 @@ static int create_ndb_column(THD *thd,
CHARSET_INFO *cs= field->charset();
// Set type and sizes
const enum enum_field_types mysql_type= field->real_type();
+
+ {
+ /* Clear default value (col obj is reused for whole table def) */
+ col.setDefaultValue(NULL, 0);
+
+ /* If the data nodes are capable then set native
+ * default.
+ */
+ bool nativeDefaults =
+ ! (thd &&
+ (! ndb_native_default_support(get_thd_ndb(thd)->
+ ndb->getMinDbNodeVersion())));
+
+ if (likely( nativeDefaults ))
+ {
+ if ((!(field->flags & PRI_KEY_FLAG) ) &&
+ type_supports_default_value(mysql_type))
+ {
+ if (!(field->flags & NO_DEFAULT_VALUE_FLAG))
+ {
+ my_ptrdiff_t src_offset= field->table->s->default_values
+ - field->table->record[0];
+ if ((! field->is_null_in_record_with_offset(src_offset)) ||
+ ((field->flags & NOT_NULL_FLAG)))
+ {
+ /* Set a non-null native default */
+ memset(buf, 0, MAX_ATTR_DEFAULT_VALUE_SIZE);
+ get_default_value(buf, field);
+ col.setDefaultValue(buf, field->used_length());
+ }
+ }
+ }
+ }
+ }
switch (mysql_type) {
// Numeric types
case MYSQL_TYPE_TINY:
@@ -7020,6 +7275,12 @@ int ha_ndbcluster::create(const char *na
/*
Setup columns
*/
+ my_bitmap_map *old_map;
+ {
+ restore_record(form, s->default_values);
+ old_map= tmp_use_all_columns(form, form->read_set);
+ }
+
for (i= 0; i < form->s->fields; i++)
{
Field *field= form->field[i];
@@ -7045,6 +7306,7 @@ int ha_ndbcluster::create(const char *na
pk_length += (field->pack_length() + 3) / 4;
}
+ tmp_restore_column_map(form->read_set, old_map);
if (use_disk)
{
tab.setLogging(TRUE);
@@ -7110,6 +7372,7 @@ int ha_ndbcluster::create(const char *na
col.setNullable(FALSE);
col.setPrimaryKey(TRUE);
col.setAutoIncrement(TRUE);
+ col.setDefaultValue(NULL, 0);
if (tab.addColumn(col))
{
my_errno= errno;
=== modified file 'sql/ha_ndbcluster.h'
--- a/sql/ha_ndbcluster.h 2010-03-01 20:10:49 +0000
+++ b/sql/ha_ndbcluster.h 2010-04-29 14:52:05 +0000
@@ -619,6 +619,7 @@ private:
int add_hidden_pk_ndb_record(NdbDictionary::Dictionary *dict);
int add_index_ndb_record(NdbDictionary::Dictionary *dict,
KEY *key_info, uint index_no);
+ int check_default_values(const NdbDictionary::Table* ndbtab);
int get_metadata(THD *thd, const char* path);
void release_metadata(THD *thd, Ndb *ndb);
NDB_INDEX_TYPE get_index_type(uint idx_no) const;
=== modified file 'storage/ndb/include/kernel/ndb_limits.h'
--- a/storage/ndb/include/kernel/ndb_limits.h 2009-05-27 15:21:45 +0000
+++ b/storage/ndb/include/kernel/ndb_limits.h 2010-04-29 14:52:05 +0000
@@ -74,7 +74,7 @@
#define NDB_MAX_TABLES 20320 /* SchemaFile.hpp */
#define MAX_TAB_NAME_SIZE 128
#define MAX_ATTR_NAME_SIZE NAME_LEN /* From mysql_com.h */
-#define MAX_ATTR_DEFAULT_VALUE_SIZE 128
+#define MAX_ATTR_DEFAULT_VALUE_SIZE ((MAX_TUPLE_SIZE_IN_WORDS + 1) * 4) //Add 1 word for AttributeHeader
#define MAX_ATTRIBUTES_IN_TABLE 128
#define MAX_ATTRIBUTES_IN_INDEX 32
#define MAX_TUPLE_SIZE_IN_WORDS 2013
=== modified file 'storage/ndb/include/kernel/signaldata/DictTabInfo.hpp'
--- a/storage/ndb/include/kernel/signaldata/DictTabInfo.hpp 2009-05-27 15:21:45 +0000
+++ b/storage/ndb/include/kernel/signaldata/DictTabInfo.hpp 2010-04-29 14:52:05 +0000
@@ -166,8 +166,14 @@ public:
AttributeExtScale = 1015, //Default 0
AttributeExtLength = 1016, //Default 0
AttributeAutoIncrement = 1017, //Default false
- AttributeDefaultValue = 1018, //Default value (printable string),
AttributeArrayType = 1019, //Default NDB_ARRAYTYPE_FIXED
+ AttributeDefaultValueLen = 1020, //Actual Length saved in AttributeDefaultValue
+ /* Default value (Binary type, not printable as string),
+ * For backward compatibility, the new keyValue
+ * (not use the old keyValue 1018) is added
+ when restoring data from low backup version data.
+ */
+ AttributeDefaultValue = 1021,
AttributeEnd = 1999 //
};
// ----------------------------------------------------------------------
@@ -434,7 +440,8 @@ public:
Uint32 AttributeAutoIncrement;
Uint32 AttributeStorageType;
Uint32 AttributeDynamic;
- char AttributeDefaultValue[MAX_ATTR_DEFAULT_VALUE_SIZE];
+ Uint32 AttributeDefaultValueLen; //byte sizes
+ Uint8 AttributeDefaultValue[MAX_ATTR_DEFAULT_VALUE_SIZE];
Attribute() {}
void init();
@@ -588,8 +595,11 @@ public:
fprintf(out, "AttributeExtPrecision = %d\n", AttributeExtPrecision);
fprintf(out, "AttributeExtScale = %d\n", AttributeExtScale);
fprintf(out, "AttributeExtLength = %d\n", AttributeExtLength);
- fprintf(out, "AttributeDefaultValue = \"%s\"\n",
- AttributeDefaultValue ? AttributeDefaultValue : "");
+ fprintf(out, "AttributeDefaultValueLen = %d\n",
+ AttributeDefaultValueLen);
+ fprintf(out, "AttributeDefaultValue: \n");
+ for (unsigned int i = 0; i < AttributeDefaultValueLen; i++)
+ fprintf(out, "0x%x", AttributeDefaultValue[i]);
}
};
=== modified file 'storage/ndb/include/kernel/signaldata/LqhFrag.hpp'
--- a/storage/ndb/include/kernel/signaldata/LqhFrag.hpp 2009-05-27 15:21:45 +0000
+++ b/storage/ndb/include/kernel/signaldata/LqhFrag.hpp 2010-04-29 14:52:05 +0000
@@ -215,6 +215,7 @@ public:
STATIC_CONST( HeaderLength = 4 );
STATIC_CONST( EntryLength = 3 );
STATIC_CONST( MAX_ATTRIBUTES = 6 );
+ STATIC_CONST( DEFAULT_VALUE_SECTION_NUM = 0 );
struct Entry {
Uint32 attrId; // for index, includes primary attr id << 16
Uint32 attrDescriptor; // 2 words type info
=== modified file 'storage/ndb/include/kernel/signaldata/TupFrag.hpp'
--- a/storage/ndb/include/kernel/signaldata/TupFrag.hpp 2009-05-27 15:21:45 +0000
+++ b/storage/ndb/include/kernel/signaldata/TupFrag.hpp 2010-04-29 14:52:05 +0000
@@ -123,6 +123,7 @@ class TupAddAttrReq {
friend class Dbtux;
public:
STATIC_CONST( SignalLength = 5 );
+ STATIC_CONST( DEFAULT_VALUE_SECTION_NUM = 0 );
private:
Uint32 tupConnectPtr;
Uint32 notused1;
=== modified file 'storage/ndb/include/ndb_version.h.in'
--- a/storage/ndb/include/ndb_version.h.in 2010-03-02 15:37:59 +0000
+++ b/storage/ndb/include/ndb_version.h.in 2010-04-29 14:52:05 +0000
@@ -386,4 +386,21 @@ ndb_route_exec_frag(Uint32 x)
return x >= NDBD_ROUTE_EXEC_FRAG;
}
+#define NDBD_NATIVE_DEFAULT_SUPPORT_70 NDB_MAKE_VERSION(7,0,15)
+#define NDBD_NATIVE_DEFAULT_SUPPORT_71 NDB_MAKE_VERSION(7,1,4)
+
+static
+inline
+int
+ndb_native_default_support(Uint32 x)
+{
+ const Uint32 major = (x >> 16) & 0xFF;
+ const Uint32 minor = (x >> 8) & 0xFF;
+
+ if (major == 7 && minor == 0)
+ return x >= NDBD_NATIVE_DEFAULT_SUPPORT_70;
+
+ return x >= NDBD_NATIVE_DEFAULT_SUPPORT_71;
+}
+
#endif
=== modified file 'storage/ndb/include/ndbapi/NdbDictionary.hpp'
--- a/storage/ndb/include/ndbapi/NdbDictionary.hpp 2010-03-01 14:13:01 +0000
+++ b/storage/ndb/include/ndbapi/NdbDictionary.hpp 2010-04-29 14:52:05 +0000
@@ -565,14 +565,32 @@ public:
/** @} *******************************************************************/
+#ifndef DOXYGEN_SHOULD_SKIP_DEPRECATED
+ int setDefaultValue(const char*);
+#endif
+ /* setDefaultValue
+ * Set buf to NULL for no default value, or null default value for
+ * NULLABLE column, otherwise set buf to pointer to default value.
+ * The len parameter is the number of significant bytes of default
+ * value supplied, which is the type size for fixed size types.
+ * For variable length types, the leading 1 or 2 bytes pointed to
+ * by buf also contain length information as normal for the type.
+ */
+ int setDefaultValue(const void* buf, unsigned int len);
+
+ /* getDefaultValue
+ * Get the default value data for this column.
+ * Optional int len* will be updated with the significant length
+ * of the default value, or set to 0 for NULL or no default.
+ */
+ const void* getDefaultValue(unsigned int* len = 0) const;
+
#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
const Table * getBlobTable() const;
void setAutoIncrement(bool);
bool getAutoIncrement() const;
void setAutoIncrementInitialValue(Uint64 val);
- int setDefaultValue(const char*);
- const char* getDefaultValue() const;
static const Column * FRAGMENT;
static const Column * FRAGMENT_FIXED_MEMORY;
@@ -1063,6 +1081,12 @@ public:
*/
Uint32 getPartitionId(Uint32 hashvalue) const ;
+ /*
+ * Return TRUE if any of the columns in the table have a
+ * non NULL default value defined
+ */
+ bool hasDefaultValues() const;
+
private:
#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
friend class Ndb;
@@ -2518,8 +2542,32 @@ public:
createRecord
*/
void releaseRecord(NdbRecord *rec);
+ }; // class Dictionary
+
+ class NdbDataPrintFormat
+ {
+ public:
+ NdbDataPrintFormat();
+ virtual ~NdbDataPrintFormat();
+ const char *lines_terminated_by;
+ const char *fields_terminated_by;
+ const char *start_array_enclosure;
+ const char *end_array_enclosure;
+ const char *fields_enclosed_by;
+ const char *fields_optionally_enclosed_by;
+ const char *hex_prefix;
+ const char *null_string;
+ int hex_format;
};
-};
+
+ static
+ class NdbOut& printFormattedValue(class NdbOut& out,
+ const NdbDataPrintFormat& format,
+ const NdbDictionary::Column* c,
+ const void* val);
+
+
+}; // class NdbDictionary
class NdbOut& operator <<(class NdbOut& out, const NdbDictionary::Column& col);
=== modified file 'storage/ndb/include/ndbapi/NdbRecAttr.hpp'
--- a/storage/ndb/include/ndbapi/NdbRecAttr.hpp 2009-06-13 18:56:08 +0000
+++ b/storage/ndb/include/ndbapi/NdbRecAttr.hpp 2010-04-29 14:52:05 +0000
@@ -463,21 +463,15 @@ NdbRecAttr::setUNDEFINED()
class NdbOut& operator <<(class NdbOut&, const NdbRecAttr &);
-class NdbRecordPrintFormat
+class NdbRecordPrintFormat : public NdbDictionary::NdbDataPrintFormat
{
public:
- NdbRecordPrintFormat();
- virtual ~NdbRecordPrintFormat();
- const char *lines_terminated_by;
- const char *fields_terminated_by;
- const char *start_array_enclosure;
- const char *end_array_enclosure;
- const char *fields_enclosed_by;
- const char *fields_optionally_enclosed_by;
- const char *hex_prefix;
- const char *null_string;
- int hex_format;
+ NdbRecordPrintFormat() : NdbDataPrintFormat() {};
+ virtual ~NdbRecordPrintFormat() {};
};
+
+/* See also NdbDictionary::printFormattedValue() */
+
NdbOut&
ndbrecattr_print_formatted(NdbOut& out, const NdbRecAttr &r,
const NdbRecordPrintFormat &f);
=== modified file 'storage/ndb/include/util/UtilBuffer.hpp'
--- a/storage/ndb/include/util/UtilBuffer.hpp 2009-05-26 18:53:34 +0000
+++ b/storage/ndb/include/util/UtilBuffer.hpp 2010-04-29 14:52:05 +0000
@@ -104,6 +104,14 @@ public:
else
return (memcmp(get_data(), cmp.get_data(), len) == 0);
}
+
+ int assign(const UtilBuffer& buf) {
+ int ret = 0;
+ if(this != &buf) {
+ ret = assign(buf.get_data(), buf.length());
+ }
+ return ret;
+ }
private:
void *data; /* Pointer to data storage */
size_t len; /* Size of the stored data */
=== modified file 'storage/ndb/src/common/debugger/signaldata/DictTabInfo.cpp'
--- a/storage/ndb/src/common/debugger/signaldata/DictTabInfo.cpp 2009-05-27 15:21:45 +0000
+++ b/storage/ndb/src/common/debugger/signaldata/DictTabInfo.cpp 2010-04-29 14:52:05 +0000
@@ -100,8 +100,12 @@ DictTabInfo::AttributeMapping[] = {
DTIMAP(Attribute, AttributeExtScale, AttributeExtScale),
DTIMAP(Attribute, AttributeExtLength, AttributeExtLength),
DTIMAP2(Attribute, AttributeAutoIncrement, AttributeAutoIncrement, 0, 1),
- DTIMAPS(Attribute, AttributeDefaultValue, AttributeDefaultValue,
- 0, MAX_ATTR_DEFAULT_VALUE_SIZE),
+
+ DTIMAP2(Attribute, AttributeDefaultValueLen, AttributeDefaultValueLen,
+ 0, MAX_ATTR_DEFAULT_VALUE_SIZE),
+ DTIMAPB(Attribute, AttributeDefaultValue, AttributeDefaultValue,
+ 0, MAX_ATTR_DEFAULT_VALUE_SIZE, AttributeDefaultValueLen),
+
DTIBREAK(AttributeEnd)
};
@@ -198,7 +202,8 @@ DictTabInfo::Attribute::init(){
AttributeAutoIncrement = false;
AttributeStorageType = 0;
AttributeDynamic = 0; // Default is not dynamic
- memset(AttributeDefaultValue, 0, sizeof(AttributeDefaultValue));//AttributeDefaultValue[0] = 0;
+ AttributeDefaultValueLen = 0; //Default byte sizes of binary default value is 0
+ memset(AttributeDefaultValue, 0, sizeof(AttributeDefaultValue));
}
//static
=== modified file 'storage/ndb/src/kernel/blocks/ERROR_codes.txt'
--- a/storage/ndb/src/kernel/blocks/ERROR_codes.txt 2010-03-11 09:44:08 +0000
+++ b/storage/ndb/src/kernel/blocks/ERROR_codes.txt 2010-04-29 14:52:05 +0000
@@ -2,7 +2,7 @@ Next QMGR 938
Next NDBCNTR 1002
Next NDBFS 2000
Next DBACC 3002
-Next DBTUP 4032
+Next DBTUP 4035
Next DBLQH 5055
Next DBDICT 6025
Next DBDIH 7221
@@ -531,6 +531,9 @@ Failed Create Table:
4010 12004: Fail create last attribute in 1st fragment
4011 12005: Fail create 1st attribute in 2nd fragment
4012 12006: Fail create last attribute in 2nd fragment
+4032 : Fail to receive first default value
+4033 : Fail to receive last default value
+4034 : Fail to store default values in def values fragment
Drop Table/Index:
-----------------
=== modified file 'storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp'
--- a/storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp 2010-04-27 11:50:25 +0000
+++ b/storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp 2010-04-29 14:52:05 +0000
@@ -832,8 +832,9 @@ Dbdict::packTableIntoPages(SimplePropert
ConstRope def(c_rope_pool, attrPtr.p->defaultValue);
def.copy(defaultValue);
- w.add(DictTabInfo::AttributeDefaultValue, defaultValue);
-
+
+ w.add(DictTabInfo::AttributeDefaultValueLen, def.size());
+ w.add(DictTabInfo::AttributeDefaultValue, defaultValue, def.size());
w.add(DictTabInfo::AttributeEnd, 1);
}
@@ -5235,7 +5236,8 @@ void Dbdict::handleTabInfo(SimplePropert
attrPtr.p->autoIncrement = attrDesc.AttributeAutoIncrement;
{
Rope defaultValue(c_rope_pool, attrPtr.p->defaultValue);
- defaultValue.assign(attrDesc.AttributeDefaultValue);
+ defaultValue.assign((const char*)attrDesc.AttributeDefaultValue,
+ attrDesc.AttributeDefaultValueLen);
}
keyCount += attrDesc.AttributeKeyFlag;
@@ -6115,6 +6117,9 @@ Dbdict::sendLQHADDATTRREQ(Signal* signal
LqhAddAttrReq * const req = (LqhAddAttrReq*)signal->getDataPtrSend();
Uint32 i = 0;
+ Uint32 startIndex = 25;
+ Uint32 *defVal_dst = &signal->theData[startIndex];
+ Uint32 defVal_length = 0;
for(i = 0; i<LqhAddAttrReq::MAX_ATTRIBUTES && attributePtrI != RNIL; i++){
jam();
AttributeRecordPtr attrPtr;
@@ -6125,6 +6130,14 @@ Dbdict::sendLQHADDATTRREQ(Signal* signal
entry.extTypeInfo = 0;
// charset number passed to TUP, TUX in upper half
entry.extTypeInfo |= (attrPtr.p->extPrecision & ~0xFFFF);
+
+ ConstRope def(c_rope_pool, attrPtr.p->defaultValue);
+ def.copy((char*)defVal_dst);
+
+ Uint32 defValueLen = def.size();
+ defVal_length += (defValueLen + 3)/4;
+ defVal_dst += (defValueLen + 3)/4;
+
if (tabPtr.p->isIndex()) {
Uint32 primaryAttrId;
if (attrPtr.p->nextList != RNIL) {
@@ -6165,8 +6178,18 @@ Dbdict::sendLQHADDATTRREQ(Signal* signal
req->senderAttrPtr = attributePtrI;
req->noOfAttributes = i;
- sendSignal(DBLQH_REF, GSN_LQHADDATTREQ, signal,
- LqhAddAttrReq::HeaderLength + LqhAddAttrReq::EntryLength * i, JBB);
+ if (defVal_length != 0)
+ {
+ LinearSectionPtr ptr[3];
+ ptr[0].p= &signal->theData[startIndex];
+ ptr[0].sz= defVal_length;
+
+ sendSignal(DBLQH_REF, GSN_LQHADDATTREQ, signal,
+ LqhAddAttrReq::HeaderLength + LqhAddAttrReq::EntryLength * i, JBB, ptr, 1);
+ }
+ else
+ sendSignal(DBLQH_REF, GSN_LQHADDATTREQ, signal,
+ LqhAddAttrReq::HeaderLength + LqhAddAttrReq::EntryLength * i, JBB);
}
void
=== modified file 'storage/ndb/src/kernel/blocks/dblqh/Dblqh.hpp'
--- a/storage/ndb/src/kernel/blocks/dblqh/Dblqh.hpp 2010-03-25 14:41:35 +0000
+++ b/storage/ndb/src/kernel/blocks/dblqh/Dblqh.hpp 2010-04-29 14:52:05 +0000
@@ -454,6 +454,8 @@ public:
Uint16 attrReceived;
Uint16 totalAttrReceived;
Uint16 fragCopyCreation;
+ Uint16 defValNextPos;
+ Uint32 defValSectionI;
};
typedef Ptr<AddFragRecord> AddFragRecordPtr;
=== modified file 'storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp'
--- a/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp 2010-03-25 14:41:35 +0000
+++ b/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp 2010-04-29 14:52:05 +0000
@@ -1432,6 +1432,21 @@ void Dblqh::execLQHADDATTREQ(Signal* sig
addfragptr.p->m_addAttrReq = * req;
const Uint32 tnoOfAttr = req->noOfAttributes;
+ const Uint32 numSections = signal->getNoOfSections();
+ bool isLongReq= ( numSections != 0 );
+ addfragptr.p->defValSectionI = RNIL;
+ addfragptr.p->defValNextPos = 0;
+
+ if (isLongReq)
+ {
+ SectionHandle handle(this, signal);
+ SegmentedSectionPtr defValSection;
+ handle.getSection(defValSection, LqhAddAttrReq::DEFAULT_VALUE_SECTION_NUM);
+ addfragptr.p->defValSectionI = defValSection.i;
+ addfragptr.p->defValNextPos = 0;
+ //Don't free Section here. Section is freed after default values are trasfered to TUP
+ handle.clear();
+ }
ndbrequire(addfragptr.p->addfragStatus == AddFragRecord::WAIT_ADD_ATTR);
ndbrequire((tnoOfAttr != 0) && (tnoOfAttr <= LqhAddAttrReq::MAX_ATTRIBUTES));
@@ -1504,6 +1519,13 @@ void Dblqh::execTUP_ADD_ATTCONF(Signal*
return;
}
+ if (addfragptr.p->defValSectionI != RNIL)
+ {
+ releaseSection(addfragptr.p->defValSectionI);
+ addfragptr.p->defValNextPos = 0;
+ addfragptr.p->defValSectionI = RNIL;
+ }
+
{ // Reply
LqhAddAttrConf *const conf = (LqhAddAttrConf*)signal->getDataPtrSend();
conf->senderData = addfragptr.p->m_addAttrReq.senderData;
@@ -1562,6 +1584,13 @@ void Dblqh::execTUP_ADD_ATTRREF(Signal*
break;
}
+ if (addfragptr.p->defValSectionI != RNIL)
+ {
+ releaseSection(addfragptr.p->defValSectionI);
+ addfragptr.p->defValNextPos = 0;
+ addfragptr.p->defValSectionI = RNIL;
+ }
+
const Uint32 Ref = addfragptr.p->m_createTabReq.senderRef;
const Uint32 senderData = addfragptr.p->m_addAttrReq.senderData;
@@ -1608,13 +1637,49 @@ Dblqh::sendAddAttrReq(Signal* signal)
jam();
TupAddAttrReq* const tupreq = (TupAddAttrReq*)signal->getDataPtrSend();
tupreq->tupConnectPtr = addfragptr.p->tupConnectptr;
- tupreq->notused1 = 0;
tupreq->attrId = attrId;
tupreq->attrDescriptor = entry.attrDescriptor;
tupreq->extTypeInfo = entry.extTypeInfo;
BlockReference tupRef = calcInstanceBlockRef(DBTUP);
- sendSignal(tupRef, GSN_TUP_ADD_ATTRREQ,
- signal, TupAddAttrReq::SignalLength, JBB);
+
+ Uint32 sectionLen = 0;
+ Uint32 startIndex = TupAddAttrReq::SignalLength;
+ if (addfragptr.p->defValSectionI != RNIL)
+ {
+ SegmentedSectionPtr defValSection;
+ getSection(defValSection, addfragptr.p->defValSectionI);
+
+ SectionReader defValueReader(defValSection, getSectionSegmentPool());
+ Uint32 defSectionWords = defValueReader.getSize();
+
+ ndbrequire(defValueReader.step(addfragptr.p->defValNextPos));
+
+ Uint32 defValueHeader;
+ ndbrequire(defValueReader.peekWord(&defValueHeader));
+
+ AttributeHeader ah(defValueHeader);
+ Uint32 defValueLen = ah.getByteSize();
+ Uint32 defValueWords = ((defValueLen +3)/4) + 1;
+ Uint32 *dst = &signal->theData[startIndex];
+ ndbassert(defSectionWords >= (addfragptr.p->defValNextPos + defValueWords));
+ ndbrequire(defValueReader.getWords(dst, defValueWords));
+ addfragptr.p->defValNextPos += defValueWords;
+ sectionLen = defValueWords;
+ }
+
+ //A long section is attached when a default value is sent.
+ if (sectionLen != 0)
+ {
+ LinearSectionPtr ptr[3];
+ ptr[0].p= &signal->theData[startIndex];
+ ptr[0].sz= sectionLen;
+ sendSignal(tupRef, GSN_TUP_ADD_ATTRREQ,
+ signal, TupAddAttrReq::SignalLength, JBB, ptr, 1);
+ }
+ else
+ sendSignal(tupRef, GSN_TUP_ADD_ATTRREQ,
+ signal, TupAddAttrReq::SignalLength, JBB);
+
return;
}
if (DictTabInfo::isOrderedIndex(tabptr.p->tableType) &&
@@ -20505,6 +20570,8 @@ void Dblqh::seizeAddfragrec(Signal* sign
addfragptr.p->accConnectptr = RNIL;
addfragptr.p->tupConnectptr = RNIL;
addfragptr.p->tuxConnectptr = RNIL;
+ addfragptr.p->defValSectionI = RNIL;
+ addfragptr.p->defValNextPos = 0;
bzero(&addfragptr.p->m_createTabReq, sizeof(addfragptr.p->m_createTabReq));
bzero(&addfragptr.p->m_lqhFragReq, sizeof(addfragptr.p->m_lqhFragReq));
bzero(&addfragptr.p->m_addAttrReq, sizeof(addfragptr.p->m_addAttrReq));
=== modified file 'storage/ndb/src/kernel/blocks/dblqh/DblqhProxy.cpp'
--- a/storage/ndb/src/kernel/blocks/dblqh/DblqhProxy.cpp 2010-03-26 11:52:10 +0000
+++ b/storage/ndb/src/kernel/blocks/dblqh/DblqhProxy.cpp 2010-04-29 14:52:05 +0000
@@ -269,6 +269,12 @@ DblqhProxy::execLQHADDATTREQ(Signal* sig
ndbrequire(ss_main.m_req.noOfAttributes >= req->noOfAttributes);
ss_main.m_req.noOfAttributes -= req->noOfAttributes;
+ /* Save long section(s) in ss for forwarding to
+ * workers
+ */
+ SectionHandle handle(this, signal);
+ saveSections(ss, handle);
+
sendREQ(signal, ss);
}
=== modified file 'storage/ndb/src/kernel/blocks/dbtup/Dbtup.hpp'
--- a/storage/ndb/src/kernel/blocks/dbtup/Dbtup.hpp 2010-03-05 15:03:09 +0000
+++ b/storage/ndb/src/kernel/blocks/dbtup/Dbtup.hpp 2010-04-29 14:52:05 +0000
@@ -241,6 +241,7 @@ inline const Uint32* ALIGN_WORD(const vo
#define ZAI_INCONSISTENCY_ERROR 829
#define ZNO_ILLEGAL_NULL_ATTR 839
#define ZNOT_NULL_ATTR 840
+#define ZBAD_DEFAULT_VALUE_LEN 850
#define ZNO_INSTRUCTION_ERROR 871
#define ZOUTSIDE_OF_PROGRAM_ERROR 876
#define ZSTORED_PROC_ID_ERROR 877
@@ -1100,6 +1101,7 @@ ArrayPool<TupTriggerData> c_triggerPool;
} m_dropTable;
struct {
Uint32 m_fragOpPtrI;
+ Uint32 defValSectionI;
} m_createTable;
struct {
Uint32 m_gci_hi;
@@ -1107,6 +1109,7 @@ ArrayPool<TupTriggerData> c_triggerPool;
};
State tableStatus;
+ Local_key m_default_value_location;
};
/*
@@ -2507,6 +2510,8 @@ private:
//------------------------------------------------------------------
//------------------------------------------------------------------
+ int store_default_record(const TablerecPtr& regTabPtr);
+ bool receive_defvalue(Signal* signal, const TablerecPtr& regTabPtr);
//------------------------------------------------------------------
//------------------------------------------------------------------
void bufferTRANSID_AI(Signal* signal, BlockReference aRef, Uint32 Tlen);
@@ -2836,6 +2841,7 @@ private:
void initializeTablerec();
void initializeTabDescr();
void initializeUndoPage();
+ void initializeDefaultValuesFrag();
void initTab(Tablerec* regTabPtr);
@@ -2979,6 +2985,7 @@ private:
#endif
Uint32 calculate_free_list_impl(Uint32) const ;
+ Uint64 calculate_used_var_words(Fragrecord* fragPtr);
void remove_free_page(Fragrecord*, Var_page*, Uint32);
void insert_free_page(Fragrecord*, Var_page*, Uint32);
@@ -2991,6 +2998,7 @@ private:
Uint32* alloc_var_rec(Uint32 * err,
Fragrecord*, Tablerec*, Uint32, Local_key*, Uint32*);
void free_var_rec(Fragrecord*, Tablerec*, Local_key*, Ptr<Page>);
+ void free_var_part(Fragrecord*, Tablerec*, Local_key*);
Uint32* alloc_var_part(Uint32*err,Fragrecord*, Tablerec*, Uint32, Local_key*);
Uint32 *realloc_var_part(Uint32 * err, Fragrecord*, Tablerec*,
PagePtr, Var_part_ref*, Uint32, Uint32);
@@ -3044,6 +3052,15 @@ private:
Uint32 cnoOfFragrec;
RSS_OP_COUNTER(cnoOfFreeFragrec);
RSS_OP_SNAPSHOT(cnoOfFreeFragrec);
+ /*
+ * DefaultValuesFragment is a normal struct Fragrecord.
+ * It is TUP block-variable.
+ * There is only ONE DefaultValuesFragment shared
+ * among all table fragments stored by this TUP block.
+ */
+ FragrecordPtr DefaultValuesFragment;
+ RSS_OP_SNAPSHOT(defaultValueWordsHi);
+ RSS_OP_SNAPSHOT(defaultValueWordsLo);
AlterTabOperation *alterTabOperRec;
Uint32 cfirstfreeAlterTabOp;
@@ -3125,6 +3142,7 @@ private:
Uint32* get_ptr(PagePtr*, Var_part_ref);
Uint32* get_ptr(PagePtr*, const Local_key*, const Tablerec*);
Uint32* get_dd_ptr(PagePtr*, const Local_key*, const Tablerec*);
+ Uint32* get_default_ptr(const Tablerec*, Uint32&);
Uint32 get_len(Ptr<Page>* pagePtr, Var_part_ref ref);
Tuple_header* alloc_copy_tuple(const Tablerec* tabPtrP, Local_key* ptr){
@@ -3393,6 +3411,20 @@ Dbtup::get_ptr(PagePtr* pagePtr,
inline
Uint32*
+Dbtup::get_default_ptr(const Tablerec* regTabPtr, Uint32& default_len)
+{
+ Var_part_ref ref;
+ ref.assign(®TabPtr->m_default_value_location);
+ Ptr<Page> page;
+
+ Uint32* default_data = get_ptr(&page, ref);
+ default_len = get_len(&page, ref);
+
+ return default_data;
+}
+
+inline
+Uint32*
Dbtup::get_dd_ptr(PagePtr* pagePtr,
const Local_key* key, const Tablerec* regTabPtr)
{
=== modified file 'storage/ndb/src/kernel/blocks/dbtup/DbtupDebug.cpp'
--- a/storage/ndb/src/kernel/blocks/dbtup/DbtupDebug.cpp 2010-03-05 15:03:09 +0000
+++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupDebug.cpp 2010-04-29 14:52:05 +0000
@@ -379,6 +379,15 @@ Dbtup::execDUMP_STATE_ORD(Signal* signal
if (signal->theData[0] == DumpStateOrd::SchemaResourceSnapshot)
{
+ {
+ Uint64 defaultValueWords= 0;
+ if (DefaultValuesFragment.i != RNIL)
+ defaultValueWords= calculate_used_var_words(DefaultValuesFragment.p);
+ Uint32 defaultValueWordsHi= (Uint32) (defaultValueWords >> 32);
+ Uint32 defaultValueWordsLo= (Uint32) (defaultValueWords & 0xFFFFFFFF);
+ RSS_OP_SNAPSHOT_SAVE(defaultValueWordsHi);
+ RSS_OP_SNAPSHOT_SAVE(defaultValueWordsLo);
+ }
RSS_OP_SNAPSHOT_SAVE(cnoOfFreeFragoprec);
RSS_OP_SNAPSHOT_SAVE(cnoOfFreeFragrec);
RSS_OP_SNAPSHOT_SAVE(cnoOfFreeTabDescrRec);
@@ -387,6 +396,15 @@ Dbtup::execDUMP_STATE_ORD(Signal* signal
if (signal->theData[0] == DumpStateOrd::SchemaResourceCheckLeak)
{
+ {
+ Uint64 defaultValueWords= 0;
+ if (DefaultValuesFragment.i != RNIL)
+ defaultValueWords= calculate_used_var_words(DefaultValuesFragment.p);
+ Uint32 defaultValueWordsHi= (Uint32) (defaultValueWords >> 32);
+ Uint32 defaultValueWordsLo= (Uint32) (defaultValueWords & 0xFFFFFFFF);
+ RSS_OP_SNAPSHOT_CHECK(defaultValueWordsHi);
+ RSS_OP_SNAPSHOT_CHECK(defaultValueWordsLo);
+ }
RSS_OP_SNAPSHOT_CHECK(cnoOfFreeFragoprec);
RSS_OP_SNAPSHOT_CHECK(cnoOfFreeFragrec);
RSS_OP_SNAPSHOT_CHECK(cnoOfFreeTabDescrRec);
=== modified file 'storage/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp'
--- a/storage/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp 2010-03-21 19:05:55 +0000
+++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp 2010-04-29 14:52:05 +0000
@@ -1466,7 +1466,27 @@ int Dbtup::handleInsertReq(Signal* signa
terrorCode = ZAI_INCONSISTENCY_ERROR;
goto update_error;
}
-
+
+ if (!regTabPtr->m_default_value_location.isNull())
+ {
+ jam();
+ Uint32 default_values_len;
+ /* Get default values ptr + len for this table */
+ Uint32* default_values = get_default_ptr(regTabPtr, default_values_len);
+ ndbrequire(default_values_len != 0 && default_values != NULL);
+ /*
+ * Update default values into row first,
+ * next update with data received from the client.
+ */
+ if(unlikely((res = updateAttributes(req_struct, default_values,
+ default_values_len)) < 0))
+ {
+ jam();
+ terrorCode = Uint32(-res);
+ goto update_error;
+ }
+ }
+
if(unlikely((res = updateAttributes(req_struct, &cinBuffer[0],
req_struct->attrinfo_len)) < 0))
{
=== modified file 'storage/ndb/src/kernel/blocks/dbtup/DbtupGen.cpp'
--- a/storage/ndb/src/kernel/blocks/dbtup/DbtupGen.cpp 2010-03-05 15:03:09 +0000
+++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupGen.cpp 2010-04-29 14:52:05 +0000
@@ -630,6 +630,7 @@ void Dbtup::execNDB_STTOR(Signal* signal
jam();
cownNodeId = ownNodeId;
cownref = calcInstanceBlockRef(DBTUP);
+ initializeDefaultValuesFrag();
break;
case ZSTARTPHASE2:
jam();
@@ -657,6 +658,30 @@ void Dbtup::startphase3Lab(Signal* signa
{
}//Dbtup::startphase3Lab()
+void Dbtup::initializeDefaultValuesFrag()
+{
+ /* Grab and initialize a fragment record for storing default
+ * values for the table fragments held by this TUP instance
+ */
+ seizeFragrecord(DefaultValuesFragment);
+ DefaultValuesFragment.p->fragStatus = Fragrecord::FS_ONLINE;
+ DefaultValuesFragment.p->m_undo_complete= false;
+ DefaultValuesFragment.p->m_lcp_scan_op = RNIL;
+ DefaultValuesFragment.p->m_lcp_keep_list = RNIL;
+ DefaultValuesFragment.p->noOfPages = 0;
+ DefaultValuesFragment.p->noOfVarPages = 0;
+ DefaultValuesFragment.p->m_max_page_no = 0;
+ DefaultValuesFragment.p->m_free_page_id_list = FREE_PAGE_RNIL;
+ ndbrequire(DefaultValuesFragment.p->m_page_map.isEmpty());
+ DefaultValuesFragment.p->m_restore_lcp_id = RNIL;
+ for (Uint32 i = 0; i<MAX_FREE_LIST+1; i++)
+ ndbrequire(DefaultValuesFragment.p->free_var_page_array[i].isEmpty());
+
+ DefaultValuesFragment.p->m_logfile_group_id = RNIL;
+
+ return;
+}
+
void Dbtup::initializeFragoperrec()
{
FragoperrecPtr fragoperPtr;
@@ -755,6 +780,7 @@ Dbtup::initTab(Tablerec* const regTabPtr
regTabPtr->m_dropTable.tabUserPtr = RNIL;
regTabPtr->m_dropTable.tabUserRef = 0;
regTabPtr->tableStatus = NOT_DEFINED;
+ regTabPtr->m_default_value_location.setNull();
// Clear trigger data
if (!regTabPtr->afterInsertTriggers.isEmpty())
=== modified file 'storage/ndb/src/kernel/blocks/dbtup/DbtupMeta.cpp'
--- a/storage/ndb/src/kernel/blocks/dbtup/DbtupMeta.cpp 2010-01-13 13:28:03 +0000
+++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupMeta.cpp 2010-04-29 14:52:05 +0000
@@ -38,6 +38,7 @@
#include "AttributeOffset.hpp"
#include <my_sys.h>
#include <signaldata/LqhFrag.hpp>
+#include <signaldata/AttrInfo.hpp>
#include <EventLogger.hpp>
extern EventLogger * g_eventLogger;
@@ -78,6 +79,7 @@ Dbtup::execCREATE_TAB_REQ(Signal* signal
fragOperPtr.p->lqhBlockrefFrag = req->senderRef;
regTabPtr.p->m_createTable.m_fragOpPtrI = fragOperPtr.i;
+ regTabPtr.p->m_createTable.defValSectionI = RNIL;
regTabPtr.p->tableStatus= DEFINING;
regTabPtr.p->m_bits = 0;
regTabPtr.p->m_bits |= (req->checksumIndicator ? Tablerec::TR_Checksum : 0);
@@ -297,6 +299,18 @@ void Dbtup::execTUP_ADD_ATTRREQ(Signal*
goto error;
}
+ if (!receive_defvalue(signal, regTabPtr))
+ goto error;
+
+ if ((ERROR_INSERTED(4032) && (attrId == 0)) ||
+ (ERROR_INSERTED(4033) && lastAttr))
+ {
+ jam();
+ CLEAR_ERROR_INSERT_VALUE;
+ terrorCode = 1;
+ goto error;
+ }
+
if (! lastAttr)
{
jam();
@@ -382,6 +396,12 @@ void Dbtup::execTUP_ADD_ATTRREQ(Signal*
}
#endif
+ if (store_default_record(regTabPtr) < 0)
+ {
+ jam();
+ goto error;
+ }
+
ndbrequire(regTabPtr.p->tableStatus == DEFINING);
regTabPtr.p->tableStatus= DEFINED;
@@ -393,6 +413,17 @@ void Dbtup::execTUP_ADD_ATTRREQ(Signal*
releaseFragoperrec(fragOperPtr);
return;
error:
+ {
+ /* Release any unprocessed sections */
+ SectionHandle handle(this, signal);
+ releaseSections(handle);
+ }
+ /* Release segmented section used to receive Attr default value */
+ releaseSection(regTabPtr.p->m_createTable.defValSectionI);
+ regTabPtr.p->m_createTable.defValSectionI = RNIL;
+ free_var_part(DefaultValuesFragment.p, regTabPtr.p, ®TabPtr.p->m_default_value_location);
+ regTabPtr.p->m_default_value_location.setNull();
+
signal->theData[0]= fragOperPtr.p->lqhPtrFrag;
signal->theData[1]= terrorCode;
sendSignal(fragOperPtr.p->lqhBlockrefFrag,
@@ -401,6 +432,156 @@ error:
return;
}
+bool Dbtup::receive_defvalue(Signal* signal, const TablerecPtr& regTabPtr)
+{
+ jam();
+ Uint32 defValueBytes = 0;
+ Uint32 defValueWords = 0;
+ Uint32 attrId = signal->theData[2];
+ Uint32 attrDescriptor = signal->theData[3];
+
+ Uint32 attrLen = AttributeDescriptor::getSize(attrDescriptor);
+ Uint32 arrayType = AttributeDescriptor::getArrayType(attrDescriptor);
+ Uint32 arraySize = AttributeDescriptor::getArraySize(attrDescriptor);
+
+ const Uint32 numSections = signal->getNoOfSections();
+
+ if (numSections == 0)
+ return true;
+
+ jam();
+ SectionHandle handle(this, signal);
+ SegmentedSectionPtr ptr;
+ handle.getSection(ptr, TupAddAttrReq::DEFAULT_VALUE_SECTION_NUM);
+
+ SimplePropertiesSectionReader r(ptr, getSectionSegmentPool());
+ r.reset();
+
+ Uint32 ahIn;
+ ndbrequire(r.getWord(&ahIn));
+
+ defValueBytes = AttributeHeader::getByteSize(ahIn);
+ defValueWords = (defValueBytes + 3) / 4;
+
+ Uint32 *dst = NULL;
+ AttributeHeader ah(attrId, defValueBytes);
+
+ if (defValueBytes == 0)
+ {
+ jam();
+ releaseSections(handle);
+ return true;
+ }
+
+ /* We have a default value, double check to be sure this is not
+ * a primary key
+ */
+ if (AttributeDescriptor::getPrimaryKey(attrDescriptor))
+ {
+ jam();
+ releaseSections(handle);
+ /* Default value for primary key column not supported */
+ terrorCode = 792;
+ return false;
+ }
+
+ Uint32 bytes;
+ if (attrLen)
+ bytes= AttributeDescriptor::getSizeInBytes(attrDescriptor);
+ else
+ bytes= ((arraySize + AD_SIZE_IN_WORDS_OFFSET)
+ >> AD_SIZE_IN_WORDS_SHIFT) * 4;
+
+ terrorCode= 0;
+
+ if (attrLen)
+ {
+ if (arrayType == NDB_ARRAYTYPE_FIXED)
+ {
+ if (defValueBytes != bytes)
+ {
+ terrorCode = ZBAD_DEFAULT_VALUE_LEN;
+ }
+ }
+ else
+ {
+ if (defValueBytes > bytes)
+ {
+ terrorCode = ZBAD_DEFAULT_VALUE_LEN;
+ }
+ }
+ }
+ else
+ {
+ /*
+ * The condition is for BIT type.
+ * Even though it is fixed, the compare operator should be > rather than ==,
+ * for the 4-byte alignemnt, the space for BIT type occupied 4 bytes at least.
+ * yet the bytes of default value can be 1, 2, 3, 4, 5, 6, 7, 8 bytes.
+ */
+ if (defValueBytes > bytes)
+ {
+ terrorCode = ZBAD_DEFAULT_VALUE_LEN;
+ }
+ }
+
+ jam();
+
+ if (likely( !terrorCode ))
+ {
+ dst = cinBuffer;
+
+ ndbrequire(r.getWords(dst, defValueWords));
+
+ /* Check that VAR types have valid inline length */
+ if ((attrLen) &&
+ (arrayType != NDB_ARRAYTYPE_FIXED))
+ {
+ jam();
+ const uchar* valPtr = (const uchar*) dst;
+ Uint32 internalVarSize = 0;
+
+ if (arrayType == NDB_ARRAYTYPE_SHORT_VAR)
+ {
+ internalVarSize = 1 + valPtr[0];
+ }
+ else if (arrayType == NDB_ARRAYTYPE_MEDIUM_VAR)
+ {
+ internalVarSize = 2 + valPtr[0] + (256 * Uint32(valPtr[1]));
+ }
+ else
+ {
+ ndbrequire(false);
+ }
+
+ if (unlikely(internalVarSize != defValueBytes))
+ {
+ jam();
+ terrorCode = ZBAD_DEFAULT_VALUE_LEN;
+ releaseSections(handle);
+ return false;
+ }
+ }
+
+ if (likely( appendToSection(regTabPtr.p->m_createTable.defValSectionI,
+ (const Uint32 *)&ah, 1) ))
+ {
+ if (likely( appendToSection(regTabPtr.p->m_createTable.defValSectionI,
+ (const Uint32*)dst,
+ defValueWords)))
+ {
+ jam();
+ releaseSections(handle);
+ return true;
+ }
+ }
+ terrorCode = ZMEM_NOMEM_ERROR;
+ }
+
+ releaseSections(handle);
+ return false;
+}
+
void Dbtup::execTUPFRAGREQ(Signal* signal)
{
jamEntry();
@@ -553,12 +734,75 @@ void Dbtup::execTUPFRAGREQ(Signal* signa
return;
sendref:
-
signal->theData[0]= userptr;
signal->theData[1]= terrorCode;
sendSignal(userRef, GSN_TUPFRAGREF, signal, 2, JBB);
}
+/*
+ Store the default values for a table, as the ATTRINFO "program"
+ (i.e AttributeHeader|Data AttributeHeader|Data...)
+ in varsize memory associated with the dummy fragment(DefaultValuesFragment).
+ There is a DBTUP global set of defaults records in DefaultValuesFragment.
+ One record per table stored on varsize pages.
+
+ Each Table_record has a Local_key pointing to start of its default values
+ in TUP's default values fragment.
+*/
+int Dbtup::store_default_record(const TablerecPtr& regTabPtr)
+{
+ Uint32 RdefValSectionI = regTabPtr.p->m_createTable.defValSectionI;
+ jam();
+
+ if (RdefValSectionI == RNIL) //No default values are stored for the table
+ {
+ jam();
+ if (ERROR_INSERTED(4034))
+ {
+ jam();
+ CLEAR_ERROR_INSERT_VALUE;
+ terrorCode = 1;
+ return -1;
+ }
+
+ return 0;
+ }
+
+ SegmentedSectionPtr defValSection;
+ getSection(defValSection, RdefValSectionI);
+ Uint32 sizes = defValSection.p->m_sz;
+ /**
+ * Alloc var-length memory for storing defaults
+ */
+ Uint32* var_data_ptr= alloc_var_part(&terrorCode,
+ DefaultValuesFragment.p,
+ regTabPtr.p,
+ sizes,
+ ®TabPtr.p->m_default_value_location);
+ if (unlikely( var_data_ptr == 0 ))
+ {
+ jam();
+ /* Caller releases the default values section */
+ return -1;
+ }
+
+ if (ERROR_INSERTED(4034))
+ {
+ jam();
+ CLEAR_ERROR_INSERT_VALUE;
+ terrorCode = 1;
+ return -1;
+ }
+
+
+ copy(var_data_ptr, RdefValSectionI);
+ releaseSection(RdefValSectionI);
+ regTabPtr.p->m_createTable.defValSectionI= RNIL;
+
+ return 0;
+}
+
+
bool Dbtup::addfragtotab(Tablerec* const regTabPtr,
Uint32 fragId,
Uint32 fragIndex)
@@ -1889,6 +2133,8 @@ Dbtup::drop_table_logsync_callback(Signa
signal, DropTabConf::SignalLength, JBB);
releaseTabDescr(tabPtr.p);
+ free_var_part(DefaultValuesFragment.p, tabPtr.p, &tabPtr.p->m_default_value_location);
+ tabPtr.p->m_default_value_location.setNull();
initTab(tabPtr.p);
}
=== modified file 'storage/ndb/src/kernel/blocks/dbtup/DbtupVarAlloc.cpp'
--- a/storage/ndb/src/kernel/blocks/dbtup/DbtupVarAlloc.cpp 2009-12-14 10:58:03 +0000
+++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupVarAlloc.cpp 2010-04-29 14:52:05 +0000
@@ -139,6 +139,39 @@ Dbtup::alloc_var_part(Uint32 * err,
}
/*
+ free_var_part is used to free the variable length storage associated
+ with the passed local key.
+ It is not assumed that there is a corresponding fixed-length part.
+ // TODO : Any need for tabPtr?
+*/
+void Dbtup::free_var_part(Fragrecord* fragPtr,
+ Tablerec* tabPtr,
+ Local_key* key)
+{
+ Ptr<Page> pagePtr;
+ if (key->m_page_no != RNIL)
+ {
+ c_page_pool.getPtr(pagePtr, key->m_page_no);
+ ((Var_page*)pagePtr.p)->free_record(key->m_page_idx, Var_page::CHAIN);
+
+ ndbassert(pagePtr.p->free_space <= Var_page::DATA_WORDS);
+ if (pagePtr.p->free_space == Var_page::DATA_WORDS - 1)
+ {
+ jam();
+ Uint32 idx = pagePtr.p->list_index;
+ LocalDLList<Page> list(c_page_pool, fragPtr->free_var_page_array[idx]);
+ list.remove(pagePtr);
+ returnCommonArea(pagePtr.i, 1);
+ fragPtr->noOfVarPages --;
+ } else {
+ jam();
+ update_free_page_list(fragPtr, pagePtr);
+ }
+ }
+ return;
+}
+
+/*
Deallocator for variable sized segments
Part of the external interface for variable sized segments
@@ -474,6 +507,30 @@ Uint32 Dbtup::calculate_free_list_impl(U
return 0;
}
+Uint64 Dbtup::calculate_used_var_words(Fragrecord* fragPtr)
+{
+ /* Loop over all VarSize pages in this fragment, summing
+ * their used space
+ */
+ Uint64 totalUsed= 0;
+ for (Uint32 freeList= 0; freeList <= MAX_FREE_LIST; freeList++)
+ {
+ LocalDLList<Page> list(c_page_pool,
+ fragPtr->free_var_page_array[freeList]);
+ Ptr<Page> pagePtr;
+
+ if (list.first(pagePtr))
+ {
+ do
+ {
+ totalUsed+= (Tup_varsize_page::DATA_WORDS - pagePtr.p->free_space);
+ } while (list.next(pagePtr));
+ };
+ };
+
+ return totalUsed;
+}
+
Uint32*
Dbtup::alloc_var_rowid(Uint32 * err,
Fragrecord* fragPtr,
=== modified file 'storage/ndb/src/ndbapi/NdbDictionary.cpp'
--- a/storage/ndb/src/ndbapi/NdbDictionary.cpp 2010-03-01 14:13:01 +0000
+++ b/storage/ndb/src/ndbapi/NdbDictionary.cpp 2010-04-29 14:52:05 +0000
@@ -20,6 +20,10 @@
#include "NdbDictionaryImpl.hpp"
#include <NdbOut.hpp>
#include <signaldata/CreateHashMap.hpp>
+#include <NdbBlob.hpp>
+C_MODE_START
+#include <decimal.h>
+C_MODE_END
/* NdbRecord static helper methods */
@@ -350,16 +354,37 @@ NdbDictionary::Column::setAutoIncrementI
m_impl.m_autoIncrementInitialValue = val;
}
+/*
+* setDefaultValue() with only one const char * parameter is reserved
+* for backward compatible api consideration, but is broken.
+*/
int
NdbDictionary::Column::setDefaultValue(const char* defaultValue)
{
- return !m_impl.m_defaultValue.assign(defaultValue);
+ return -1;
}
-const char*
-NdbDictionary::Column::getDefaultValue() const
+/*
+ The significant length of a column can't easily be calculated before
+ the column type is fully defined, so the length of the default value
+ is passed in as a parameter explicitly.
+*/
+int
+NdbDictionary::Column::setDefaultValue(const void* defaultValue, unsigned int n)
{
- return m_impl.m_defaultValue.c_str();
+ if (defaultValue == NULL)
+ return m_impl.m_defaultValue.assign(NULL, 0);
+
+ return m_impl.m_defaultValue.assign(defaultValue, n);
+}
+
+const void*
+NdbDictionary::Column::getDefaultValue(unsigned int* len) const
+{
+ if (len)
+ *len = m_impl.m_defaultValue.length();
+
+ return m_impl.m_defaultValue.get_data();
}
int
@@ -899,6 +924,11 @@ NdbDictionary::Table::getForceVarPart()
return m_impl.m_force_var_part;
}
+bool
+NdbDictionary::Table::hasDefaultValues() const {
+ return m_impl.m_has_default_values;
+}
+
const NdbRecord*
NdbDictionary::Table::getDefaultRecord() const {
return m_impl.m_ndbrecord;
@@ -1031,6 +1061,9 @@ NdbDictionary::Index::addColumn(const Co
(* col) = NdbColumnImpl::getImpl(c);
col->m_indexSourced=true;
+
+ /* Remove defaults from indexed columns */
+ col->m_defaultValue.clear();
if (m_impl.m_columns.push_back(col))
{
@@ -2614,6 +2647,436 @@ NdbDictionary::Dictionary::getWarningFla
// printers
+void
+pretty_print_string(NdbOut& out,
+ const NdbDictionary::NdbDataPrintFormat &f,
+ const char *type, bool is_binary,
+ const void *aref, unsigned sz)
+{
+ const unsigned char* ref = (const unsigned char*)aref;
+ int i, len, printable= 1;
+ // trailing zeroes are not printed
+ for (i=sz-1; i >= 0; i--)
+ if (ref[i] == 0) sz--;
+ else break;
+ if (!is_binary)
+ {
+ // trailing spaces are not printed
+ for (i=sz-1; i >= 0; i--)
+ if (ref[i] == 32) sz--;
+ else break;
+ }
+ if (is_binary && f.hex_format)
+ {
+ if (sz == 0)
+ {
+ out.print("0x0");
+ return;
+ }
+ out.print("0x");
+ for (len = 0; len < (int)sz; len++)
+ out.print("%02X", (int)ref[len]);
+ return;
+ }
+ if (sz == 0) return; // empty
+
+ for (len=0; len < (int)sz && ref[i] != 0; len++)
+ if (printable && !isprint((int)ref[i]))
+ printable= 0;
+
+ if (printable)
+ out.print("%.*s", len, ref);
+ else
+ {
+ out.print("0x");
+ for (i=0; i < len; i++)
+ out.print("%02X", (int)ref[i]);
+ }
+ if (len != (int)sz)
+ {
+ out.print("[");
+ for (i= len+1; ref[i] != 0; i++)
+ out.print("%u]",len-i);
+ assert((int)sz > i);
+ pretty_print_string(out,f,type,is_binary,ref+i,sz-i);
+ }
+}
+
+/* Three MySQL defs duplicated here : */
+static const int MaxMySQLDecimalPrecision= 65;
+static const int MaxMySQLDecimalScale= 30;
+static const int DigitsPerDigit_t= 9; // (Decimal digits in 2^32)
+
+/* Implications */
+/* Space for -, . and \0 */
+static const int MaxDecimalStrLen= MaxMySQLDecimalPrecision + 3;
+static const int IntPartDigit_ts=
+ ((MaxMySQLDecimalPrecision -
+ MaxMySQLDecimalScale) +
+ DigitsPerDigit_t -1) / DigitsPerDigit_t;
+static const int FracPartDigit_ts=
+ (MaxMySQLDecimalScale +
+ DigitsPerDigit_t - 1) / DigitsPerDigit_t;
+static const int DigitArraySize= IntPartDigit_ts + FracPartDigit_ts;
+
+NdbOut&
+NdbDictionary::printFormattedValue(NdbOut& out,
+ const NdbDataPrintFormat& format,
+ const NdbDictionary::Column* c,
+ const void* val)
+{
+ if (val == NULL)
+ {
+ out << format.null_string;
+ return out;
+ }
+
+ const unsigned char* val_p= (const unsigned char*) val;
+
+ uint length = c->getLength();
+ Uint32 j;
+ {
+ const char *fields_optionally_enclosed_by;
+ if (format.fields_enclosed_by[0] == '\0')
+ fields_optionally_enclosed_by=
+ format.fields_optionally_enclosed_by;
+ else
+ fields_optionally_enclosed_by= "";
+ out << format.fields_enclosed_by;
+
+ switch(c->getType()){
+ case NdbDictionary::Column::Bigunsigned:
+ {
+ Uint64 temp;
+ memcpy(&temp, val, 8);
+ out << temp;
+ break;
+ }
+ case NdbDictionary::Column::Bit:
+ {
+ out << format.hex_prefix << "0x";
+ {
+ const Uint32 *buf = (const Uint32 *)val;
+ unsigned int k = (length+31)/32;
+ const unsigned int sigbits= length & 31;
+ Uint32 wordMask= (1 << sigbits) -1;
+
+ /* Skip leading all-0 words */
+ while (k > 0)
+ {
+ const Uint32 v= buf[--k] & wordMask;
+ if (v != 0)
+ break;
+ /* Following words have all bits significant */
+ wordMask= ~0;
+ }
+
+ /* Write first sig word with non-zero bits */
+ out.print("%X", (buf[k] & wordMask));
+
+ /* Write remaining words (less significant) */
+ while (k > 0)
+ out.print("%.8X", buf[--k]);
+ }
+ break;
+ }
+ case NdbDictionary::Column::Unsigned:
+ {
+ if (length > 1)
+ out << format.start_array_enclosure;
+ out << *(const Uint32*)val;
+ for (j = 1; j < length; j++)
+ out << " " << *((const Uint32*)val) + j;
+ if (length > 1)
+ out << format.end_array_enclosure;
+ break;
+ }
+ case NdbDictionary::Column::Mediumunsigned:
+ out << (const Uint32) uint3korr(val_p);
+ break;
+ case NdbDictionary::Column::Smallunsigned:
+ out << *((const Uint16*) val);
+ break;
+ case NdbDictionary::Column::Tinyunsigned:
+ out << *((const Uint8*) val);
+ break;
+ case NdbDictionary::Column::Bigint:
+ {
+ Int64 temp;
+ memcpy(&temp, val, 8);
+ out << temp;
+ break;
+ }
+ case NdbDictionary::Column::Int:
+ out << *((Int32*)val);
+ break;
+ case NdbDictionary::Column::Mediumint:
+ out << sint3korr(val_p);
+ break;
+ case NdbDictionary::Column::Smallint:
+ out << *((const short*) val);
+ break;
+ case NdbDictionary::Column::Tinyint:
+ out << *((Int8*) val);
+ break;
+ case NdbDictionary::Column::Binary:
+ if (!format.hex_format)
+ out << fields_optionally_enclosed_by;
+ j = c->getLength();
+ pretty_print_string(out,format,"Binary", true, val, j);
+ if (!format.hex_format)
+ out << fields_optionally_enclosed_by;
+ break;
+ case NdbDictionary::Column::Char:
+ out << fields_optionally_enclosed_by;
+ j = c->getLength();
+ pretty_print_string(out,format,"Char", false, val, j);
+ out << fields_optionally_enclosed_by;
+ break;
+ case NdbDictionary::Column::Varchar:
+ {
+ out << fields_optionally_enclosed_by;
+ unsigned len = *val_p;
+ pretty_print_string(out,format,"Varchar", false, val_p+1,len);
+ j = length;
+ out << fields_optionally_enclosed_by;
+ }
+ break;
+ case NdbDictionary::Column::Varbinary:
+ {
+ if (!format.hex_format)
+ out << fields_optionally_enclosed_by;
+ unsigned len = *val_p;
+ pretty_print_string(out,format,"Varbinary", true, val_p+1,len);
+ j = length;
+ if (!format.hex_format)
+ out << fields_optionally_enclosed_by;
+ }
+ break;
+ case NdbDictionary::Column::Float:
+ {
+ float temp;
+ memcpy(&temp, val, sizeof(temp));
+ out << temp;
+ break;
+ }
+ case NdbDictionary::Column::Double:
+ {
+ double temp;
+ memcpy(&temp, val, sizeof(temp));
+ out << temp;
+ break;
+ }
+ case NdbDictionary::Column::Olddecimal:
+ {
+ short len = 1 + c->getPrecision() + (c->getScale() > 0);
+ out.print("%.*s", len, val_p);
+ }
+ break;
+ case NdbDictionary::Column::Olddecimalunsigned:
+ {
+ short len = 0 + c->getPrecision() + (c->getScale() > 0);
+ out.print("%.*s", len, val_p);
+ }
+ break;
+ case NdbDictionary::Column::Decimal:
+ case NdbDictionary::Column::Decimalunsigned:
+ {
+ int precision= c->getPrecision();
+ int scale= c->getScale();
+
+ assert(precision <= MaxMySQLDecimalPrecision);
+ assert(scale <= MaxMySQLDecimalScale);
+ assert(decimal_size(precision, scale) <= DigitArraySize );
+ decimal_digit_t buff[ DigitArraySize ];
+ decimal_t tmpDec;
+ tmpDec.buf= buff;
+ tmpDec.len= DigitArraySize;
+ decimal_make_zero(&tmpDec);
+ int rc;
+
+ const uchar* data= (const uchar*) val_p;
+ if ((rc= bin2decimal(data, &tmpDec, precision, scale)))
+ {
+ out.print("***Error : Bad bin2decimal conversion %d ***",
+ rc);
+ break;
+ }
+
+ /* Get null terminated var-length string representation */
+ char decStr[MaxDecimalStrLen];
+ assert(decimal_string_size(&tmpDec) <= MaxDecimalStrLen);
+ int len= MaxDecimalStrLen;
+ if ((rc= decimal2string(&tmpDec, decStr,
+ &len,
+ 0, // 0 = Var length output length
+ 0, // 0 = Var length fractional part
+ 0))) // Filler char for fixed length
+ {
+ out.print("***Error : bad decimal2string conversion %d ***",
+ rc);
+ break;
+ }
+
+ out.print("%s", decStr);
+
+ break;
+ }
+ // for dates cut-and-paste from field.cc
+ case NdbDictionary::Column::Datetime:
+ {
+ ulonglong tmp;
+ memcpy(&tmp, val, 8);
+
+ long part1,part2,part3;
+ part1=(long) (tmp/LL(1000000));
+ part2=(long) (tmp - (ulonglong) part1*LL(1000000));
+ char buf[40];
+ char* pos=(char*) buf+19;
+ *pos--=0;
+ *pos--= (char) ('0'+(char) (part2%10)); part2/=10;
+ *pos--= (char) ('0'+(char) (part2%10)); part3= (int) (part2 / 10);
+ *pos--= ':';
+ *pos--= (char) ('0'+(char) (part3%10)); part3/=10;
+ *pos--= (char) ('0'+(char) (part3%10)); part3/=10;
+ *pos--= ':';
+ *pos--= (char) ('0'+(char) (part3%10)); part3/=10;
+ *pos--= (char) ('0'+(char) part3);
+ *pos--= '/';
+ *pos--= (char) ('0'+(char) (part1%10)); part1/=10;
+ *pos--= (char) ('0'+(char) (part1%10)); part1/=10;
+ *pos--= '-';
+ *pos--= (char) ('0'+(char) (part1%10)); part1/=10;
+ *pos--= (char) ('0'+(char) (part1%10)); part3= (int) (part1/10);
+ *pos--= '-';
+ *pos--= (char) ('0'+(char) (part3%10)); part3/=10;
+ *pos--= (char) ('0'+(char) (part3%10)); part3/=10;
+ *pos--= (char) ('0'+(char) (part3%10)); part3/=10;
+ *pos=(char) ('0'+(char) part3);
+ out << buf;
+ }
+ break;
+ case NdbDictionary::Column::Date:
+ {
+ uint32 tmp=(uint32) uint3korr(val_p);
+ int part;
+ char buf[40];
+ char *pos=(char*) buf+10;
+ *pos--=0;
+ part=(int) (tmp & 31);
+ *pos--= (char) ('0'+part%10);
+ *pos--= (char) ('0'+part/10);
+ *pos--= '-';
+ part=(int) (tmp >> 5 & 15);
+ *pos--= (char) ('0'+part%10);
+ *pos--= (char) ('0'+part/10);
+ *pos--= '-';
+ part=(int) (tmp >> 9);
+ *pos--= (char) ('0'+part%10); part/=10;
+ *pos--= (char) ('0'+part%10); part/=10;
+ *pos--= (char) ('0'+part%10); part/=10;
+ *pos= (char) ('0'+part);
+ out << buf;
+ }
+ break;
+ case NdbDictionary::Column::Time:
+ {
+ long tmp=(long) sint3korr(val_p);
+ int hour=(uint) (tmp/10000);
+ int minute=(uint) (tmp/100 % 100);
+ int second=(uint) (tmp % 100);
+ char buf[40];
+ sprintf(buf, "%02d:%02d:%02d", hour, minute, second);
+ out << buf;
+ }
+ break;
+ case NdbDictionary::Column::Year:
+ {
+ uint year = 1900 + *((const Uint8*) val);
+ char buf[40];
+ sprintf(buf, "%04d", year);
+ out << buf;
+ }
+ break;
+ case NdbDictionary::Column::Timestamp:
+ {
+ time_t time = *(const Uint32*) val;
+ out << (uint)time;
+ }
+ break;
+ case NdbDictionary::Column::Blob:
+ case NdbDictionary::Column::Text:
+ {
+ NdbBlob::Head head;
+ NdbBlob::unpackBlobHead(head, (const char*) val_p, c->getBlobVersion());
+ out << head.length << ":";
+ const unsigned char* p = val_p + head.headsize;
+ if ((unsigned int) c->getLength() < head.headsize)
+ out << "***error***"; // really cannot happen
+ else {
+ unsigned n = c->getLength() - head.headsize;
+ for (unsigned k = 0; k < n && k < head.length; k++) {
+ if (c->getType() == NdbDictionary::Column::Blob)
+ out.print("%02X", (int)p[k]);
+ else
+ out.print("%c", (int)p[k]);
+ }
+ }
+ j = length;
+ }
+ break;
+ case NdbDictionary::Column::Longvarchar:
+ {
+ out << fields_optionally_enclosed_by;
+ unsigned len = uint2korr(val_p);
+ pretty_print_string(out,format,"Longvarchar", false,
+ val_p+2,len);
+ j = length;
+ out << fields_optionally_enclosed_by;
+ }
+ break;
+ case NdbDictionary::Column::Longvarbinary:
+ {
+ if (!format.hex_format)
+ out << fields_optionally_enclosed_by;
+ unsigned len = uint2korr(val_p);
+ pretty_print_string(out,format,"Longvarbinary", true,
+ val_p+2,len);
+ j = length;
+ if (!format.hex_format)
+ out << fields_optionally_enclosed_by;
+ }
+ break;
+
+ default: /* no print functions for the rest, just print type */
+ out << "Unable to format type ("
+ << (int) c->getType()
+ << ")";
+ if (length > 1)
+ out << " " << length << " times";
+ break;
+ }
+ out << format.fields_enclosed_by;
+ }
+
+ return out;
+}
+
+NdbDictionary::NdbDataPrintFormat::NdbDataPrintFormat()
+{
+ fields_terminated_by= ";";
+ start_array_enclosure= "[";
+ end_array_enclosure= "]";
+ fields_enclosed_by= "";
+ fields_optionally_enclosed_by= "\"";
+ lines_terminated_by= "\n";
+ hex_prefix= "H'";
+ null_string= "[NULL]";
+ hex_format= 0;
+}
+NdbDictionary::NdbDataPrintFormat::~NdbDataPrintFormat() {};
+
+
NdbOut&
operator<<(NdbOut& out, const NdbDictionary::Column& col)
{
@@ -2792,6 +3255,23 @@ operator<<(NdbOut& out, const NdbDiction
if(col.getDynamic())
out << " DYNAMIC";
+ const void *default_data = col.getDefaultValue();
+
+ if (default_data != NULL)
+ {
+ NdbDictionary::NdbDataPrintFormat f;
+
+ /* Display binary field defaults as hex */
+ f.hex_format = 1;
+
+ out << " DEFAULT ";
+
+ NdbDictionary::printFormattedValue(out,
+ f,
+ &col,
+ default_data);
+ }
+
return out;
}
=== modified file 'storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp'
--- a/storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp 2010-03-26 07:13:06 +0000
+++ b/storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp 2010-04-29 14:52:05 +0000
@@ -101,7 +101,7 @@ NdbColumnImpl::operator=(const NdbColumn
m_nullable = col.m_nullable;
m_autoIncrement = col.m_autoIncrement;
m_autoIncrementInitialValue = col.m_autoIncrementInitialValue;
- m_defaultValue = col.m_defaultValue;
+ m_defaultValue.assign(col.m_defaultValue);
m_attrSize = col.m_attrSize;
m_arraySize = col.m_arraySize;
m_arrayType = col.m_arrayType;
@@ -307,7 +307,10 @@ NdbColumnImpl::equal(const NdbColumnImpl
if (m_autoIncrement != col.m_autoIncrement){
DBUG_RETURN(false);
}
- if(strcmp(m_defaultValue.c_str(), col.m_defaultValue.c_str()) != 0){
+ if (m_defaultValue.length() != col.m_defaultValue.length())
+ DBUG_RETURN(false);
+
+ if(memcmp(m_defaultValue.get_data(), col.m_defaultValue.get_data(), m_defaultValue.length()) != 0){
DBUG_RETURN(false);
}
@@ -585,6 +588,7 @@ NdbTableImpl::init(){
m_row_gci = true;
m_row_checksum = true;
m_force_var_part = false;
+ m_has_default_values = false;
m_kvalue= 6;
m_minLoadFactor= 78;
m_maxLoadFactor= 80;
@@ -858,6 +862,7 @@ NdbTableImpl::assign(const NdbTableImpl&
m_row_gci = org.m_row_gci;
m_row_checksum = org.m_row_checksum;
m_force_var_part = org.m_force_var_part;
+ m_has_default_values = org.m_has_default_values;
m_kvalue = org.m_kvalue;
m_minLoadFactor = org.m_minLoadFactor;
m_maxLoadFactor = org.m_maxLoadFactor;
@@ -2776,13 +2781,19 @@ NdbDictInterface::parseTableInfo(NdbTabl
col->m_nullable = attrDesc.AttributeNullableFlag;
col->m_autoIncrement = (attrDesc.AttributeAutoIncrement != 0);
col->m_autoIncrementInitialValue = ~0;
- if (!col->m_defaultValue.assign(attrDesc.AttributeDefaultValue))
+ AttributeHeader ah(*(Uint32*)attrDesc.AttributeDefaultValue);
+ Uint32 bytesize = ah.getByteSize();
+
+ if (col->m_defaultValue.assign((const char*)(attrDesc.AttributeDefaultValue + 4), bytesize))
{
delete col;
delete impl;
DBUG_RETURN(4000);
}
+ if (bytesize > 0)
+ impl->m_has_default_values = true;
+
col->m_column_no = impl->m_columns.size();
impl->m_columns.push_back(col);
it.next();
@@ -2867,6 +2878,12 @@ NdbDictionaryImpl::createTable(NdbTableI
autoIncrement = true;
initialValue = c->m_autoIncrementInitialValue;
}
+
+ if (c->m_pk && (! c->m_defaultValue.empty())) {
+ /* Default value for primary key column not supported */
+ m_error.code = 792;
+ DBUG_RETURN(-1);
+ }
}
// create table
@@ -3461,9 +3478,31 @@ loop:
}
tmpAttr.AttributeAutoIncrement = col->m_autoIncrement;
- BaseString::snprintf(tmpAttr.AttributeDefaultValue,
- sizeof(tmpAttr.AttributeDefaultValue),
- "%s", col->m_defaultValue.c_str());
+ {
+ Uint32 ah;
+ Uint32 byteSize = col->m_defaultValue.length();
+
+ if (byteSize)
+ {
+ if (unlikely(! ndb_native_default_support(ndb.getMinDbNodeVersion())))
+ {
+ /* We can't create a table with native defaults with
+ * this kernel version
+ * Schema feature requires data node upgrade
+ */
+ m_error.code = 794;
+ DBUG_RETURN(-1);
+ }
+ }
+
+ //The AttributeId of a column isn't decided now, so 0 is used.
+ AttributeHeader::init(&ah, 0, byteSize);
+
+ memcpy(tmpAttr.AttributeDefaultValue, &ah, 4);
+ memcpy(tmpAttr.AttributeDefaultValue + 4, col->m_defaultValue.get_data(), byteSize);
+
+ tmpAttr.AttributeDefaultValueLen = (((col->m_defaultValue.length() + 3) / 4) * 4) + 4;
+ }
s = SimpleProperties::pack(w,
&tmpAttr,
DictTabInfo::AttributeMapping,
=== modified file 'storage/ndb/src/ndbapi/NdbDictionaryImpl.hpp'
--- a/storage/ndb/src/ndbapi/NdbDictionaryImpl.hpp 2010-03-01 14:13:01 +0000
+++ b/storage/ndb/src/ndbapi/NdbDictionaryImpl.hpp 2010-04-29 14:52:05 +0000
@@ -96,7 +96,7 @@ public:
bool m_nullable;
bool m_autoIncrement;
Uint64 m_autoIncrementInitialValue;
- BaseString m_defaultValue;
+ UtilBuffer m_defaultValue;
/*
* Table holding the blob parts.
*
@@ -226,6 +226,7 @@ public:
bool m_row_gci;
bool m_row_checksum;
bool m_force_var_part;
+ bool m_has_default_values;
int m_kvalue;
int m_minLoadFactor;
int m_maxLoadFactor;
=== modified file 'storage/ndb/src/ndbapi/NdbRecAttr.cpp'
--- a/storage/ndb/src/ndbapi/NdbRecAttr.cpp 2009-05-27 15:21:45 +0000
+++ b/storage/ndb/src/ndbapi/NdbRecAttr.cpp 2010-04-29 14:52:05 +0000
@@ -23,9 +23,6 @@
#include <NdbBlob.hpp>
#include "NdbDictionaryImpl.hpp"
#include <NdbTCP.h>
-C_MODE_START
-#include <decimal.h>
-C_MODE_END
NdbRecAttr::NdbRecAttr(Ndb*)
{
@@ -177,390 +174,16 @@ NdbRecAttr::receive_data(const Uint32 *
return false;
}
-NdbRecordPrintFormat::NdbRecordPrintFormat()
-{
- fields_terminated_by= ";";
- start_array_enclosure= "[";
- end_array_enclosure= "]";
- fields_enclosed_by= "";
- fields_optionally_enclosed_by= "\"";
- lines_terminated_by= "\n";
- hex_prefix= "H'";
- null_string= "[NULL]";
- hex_format= 0;
-}
-NdbRecordPrintFormat::~NdbRecordPrintFormat() {}
static const NdbRecordPrintFormat default_print_format;
-static void
-ndbrecattr_print_string(NdbOut& out, const NdbRecordPrintFormat &f,
- const char *type, bool is_binary,
- const char *aref, unsigned sz)
-{
- const unsigned char* ref = (const unsigned char*)aref;
- int i, len, printable= 1;
- // trailing zeroes are not printed
- for (i=sz-1; i >= 0; i--)
- if (ref[i] == 0) sz--;
- else break;
- if (!is_binary)
- {
- // trailing spaces are not printed
- for (i=sz-1; i >= 0; i--)
- if (ref[i] == 32) sz--;
- else break;
- }
- if (is_binary && f.hex_format)
- {
- if (sz == 0)
- {
- out.print("0x0");
- return;
- }
- out.print("0x");
- for (len = 0; len < (int)sz; len++)
- out.print("%02X", (int)ref[len]);
- return;
- }
- if (sz == 0) return; // empty
-
- for (len=0; len < (int)sz && ref[i] != 0; len++)
- if (printable && !isprint((int)ref[i]))
- printable= 0;
-
- if (printable)
- out.print("%.*s", len, ref);
- else
- {
- out.print("0x");
- for (i=0; i < len; i++)
- out.print("%02X", (int)ref[i]);
- }
- if (len != (int)sz)
- {
- out.print("[");
- for (i= len+1; ref[i] != 0; i++)
- out.print("%u]",len-i);
- assert((int)sz > i);
- ndbrecattr_print_string(out,f,type,is_binary,aref+i,sz-i);
- }
-}
-
-/* Three MySQL defs duplicated here : */
-static const int MaxMySQLDecimalPrecision= 65;
-static const int MaxMySQLDecimalScale= 30;
-static const int DigitsPerDigit_t= 9; // (Decimal digits in 2^32)
-
-/* Implications */
-/* Space for -, . and \0 */
-static const int MaxDecimalStrLen= MaxMySQLDecimalPrecision + 3;
-static const int IntPartDigit_ts=
- ((MaxMySQLDecimalPrecision -
- MaxMySQLDecimalScale) +
- DigitsPerDigit_t -1) / DigitsPerDigit_t;
-static const int FracPartDigit_ts=
- (MaxMySQLDecimalScale +
- DigitsPerDigit_t - 1) / DigitsPerDigit_t;
-static const int DigitArraySize= IntPartDigit_ts + FracPartDigit_ts;
-
NdbOut&
ndbrecattr_print_formatted(NdbOut& out, const NdbRecAttr &r,
const NdbRecordPrintFormat &f)
{
- if (r.isNULL())
- {
- out << f.null_string;
- return out;
- }
-
- const NdbDictionary::Column* c = r.getColumn();
- uint length = c->getLength();
- {
- const char *fields_optionally_enclosed_by;
- if (f.fields_enclosed_by[0] == '\0')
- fields_optionally_enclosed_by=
- f.fields_optionally_enclosed_by;
- else
- fields_optionally_enclosed_by= "";
- out << f.fields_enclosed_by;
- Uint32 j;
- switch(r.getType()){
- case NdbDictionary::Column::Bigunsigned:
- out << r.u_64_value();
- break;
- case NdbDictionary::Column::Bit:
- out << f.hex_prefix << "0x";
- {
- const Uint32 *buf = (Uint32 *)r.aRef();
- int k = (length+31)/32;
- while (k > 0 && (buf[--k] == 0));
- out.print("%X", buf[k]);
- while (k > 0)
- out.print("%.8X", buf[--k]);
- }
- break;
- case NdbDictionary::Column::Unsigned:
- if (length > 1)
- out << f.start_array_enclosure;
- out << *(Uint32*)r.aRef();
- for (j = 1; j < length; j++)
- out << " " << *((Uint32*)r.aRef() + j);
- if (length > 1)
- out << f.end_array_enclosure;
- break;
- case NdbDictionary::Column::Mediumunsigned:
- out << r.u_medium_value();
- break;
- case NdbDictionary::Column::Smallunsigned:
- out << r.u_short_value();
- break;
- case NdbDictionary::Column::Tinyunsigned:
- out << (unsigned) r.u_8_value();
- break;
- case NdbDictionary::Column::Bigint:
- out << r.int64_value();
- break;
- case NdbDictionary::Column::Int:
- out << r.int32_value();
- break;
- case NdbDictionary::Column::Mediumint:
- out << r.medium_value();
- break;
- case NdbDictionary::Column::Smallint:
- out << r.short_value();
- break;
- case NdbDictionary::Column::Tinyint:
- out << (int) r.int8_value();
- break;
- case NdbDictionary::Column::Binary:
- if (!f.hex_format)
- out << fields_optionally_enclosed_by;
- j = r.get_size_in_bytes();
- ndbrecattr_print_string(out,f,"Binary", true, r.aRef(), j);
- if (!f.hex_format)
- out << fields_optionally_enclosed_by;
- break;
- case NdbDictionary::Column::Char:
- out << fields_optionally_enclosed_by;
- j = r.get_size_in_bytes();
- ndbrecattr_print_string(out,f,"Char", false, r.aRef(), j);
- out << fields_optionally_enclosed_by;
- break;
- case NdbDictionary::Column::Varchar:
- {
- out << fields_optionally_enclosed_by;
- unsigned len = *(const unsigned char*)r.aRef();
- ndbrecattr_print_string(out,f,"Varchar", false, r.aRef()+1,len);
- j = length;
- out << fields_optionally_enclosed_by;
- }
- break;
- case NdbDictionary::Column::Varbinary:
- {
- if (!f.hex_format)
- out << fields_optionally_enclosed_by;
- unsigned len = *(const unsigned char*)r.aRef();
- ndbrecattr_print_string(out,f,"Varbinary", true, r.aRef()+1,len);
- j = length;
- if (!f.hex_format)
- out << fields_optionally_enclosed_by;
- }
- break;
- case NdbDictionary::Column::Float:
- out << r.float_value();
- break;
- case NdbDictionary::Column::Double:
- out << r.double_value();
- break;
- case NdbDictionary::Column::Olddecimal:
- {
- short len = 1 + c->getPrecision() + (c->getScale() > 0);
- out.print("%.*s", len, r.aRef());
- }
- break;
- case NdbDictionary::Column::Olddecimalunsigned:
- {
- short len = 0 + c->getPrecision() + (c->getScale() > 0);
- out.print("%.*s", len, r.aRef());
- }
- break;
- case NdbDictionary::Column::Decimal:
- case NdbDictionary::Column::Decimalunsigned:
- {
- int precision= c->getPrecision();
- int scale= c->getScale();
-
- assert(precision <= MaxMySQLDecimalPrecision);
- assert(scale <= MaxMySQLDecimalScale);
- assert(decimal_size(precision, scale) <= DigitArraySize );
- decimal_digit_t buff[ DigitArraySize ];
- decimal_t tmpDec;
- tmpDec.buf= buff;
- tmpDec.len= DigitArraySize;
- decimal_make_zero(&tmpDec);
- int rc;
-
- const uchar* data= (const uchar*) r.aRef();
- if ((rc= bin2decimal(data, &tmpDec, precision, scale)))
- {
- out.print("***Error : Bad bin2decimal conversion %d ***",
- rc);
- break;
- }
-
- /* Get null terminated var-length string representation */
- char decStr[MaxDecimalStrLen];
- assert(decimal_string_size(&tmpDec) <= MaxDecimalStrLen);
- int len= MaxDecimalStrLen;
- if ((rc= decimal2string(&tmpDec, decStr,
- &len,
- 0, // 0 = Var length output length
- 0, // 0 = Var length fractional part
- 0))) // Filler char for fixed length
- {
- out.print("***Error : bad decimal2string conversion %d ***",
- rc);
- break;
- }
-
- out.print("%s", decStr);
-
- break;
- }
- // for dates cut-and-paste from field.cc
- case NdbDictionary::Column::Datetime:
- {
- ulonglong tmp=r.u_64_value();
- long part1,part2,part3;
- part1=(long) (tmp/LL(1000000));
- part2=(long) (tmp - (ulonglong) part1*LL(1000000));
- char buf[40];
- char* pos=(char*) buf+19;
- *pos--=0;
- *pos--= (char) ('0'+(char) (part2%10)); part2/=10;
- *pos--= (char) ('0'+(char) (part2%10)); part3= (int) (part2 / 10);
- *pos--= ':';
- *pos--= (char) ('0'+(char) (part3%10)); part3/=10;
- *pos--= (char) ('0'+(char) (part3%10)); part3/=10;
- *pos--= ':';
- *pos--= (char) ('0'+(char) (part3%10)); part3/=10;
- *pos--= (char) ('0'+(char) part3);
- *pos--= '/';
- *pos--= (char) ('0'+(char) (part1%10)); part1/=10;
- *pos--= (char) ('0'+(char) (part1%10)); part1/=10;
- *pos--= '-';
- *pos--= (char) ('0'+(char) (part1%10)); part1/=10;
- *pos--= (char) ('0'+(char) (part1%10)); part3= (int) (part1/10);
- *pos--= '-';
- *pos--= (char) ('0'+(char) (part3%10)); part3/=10;
- *pos--= (char) ('0'+(char) (part3%10)); part3/=10;
- *pos--= (char) ('0'+(char) (part3%10)); part3/=10;
- *pos=(char) ('0'+(char) part3);
- out << buf;
- }
- break;
- case NdbDictionary::Column::Date:
- {
- uint32 tmp=(uint32) uint3korr(r.aRef());
- int part;
- char buf[40];
- char *pos=(char*) buf+10;
- *pos--=0;
- part=(int) (tmp & 31);
- *pos--= (char) ('0'+part%10);
- *pos--= (char) ('0'+part/10);
- *pos--= '-';
- part=(int) (tmp >> 5 & 15);
- *pos--= (char) ('0'+part%10);
- *pos--= (char) ('0'+part/10);
- *pos--= '-';
- part=(int) (tmp >> 9);
- *pos--= (char) ('0'+part%10); part/=10;
- *pos--= (char) ('0'+part%10); part/=10;
- *pos--= (char) ('0'+part%10); part/=10;
- *pos= (char) ('0'+part);
- out << buf;
- }
- break;
- case NdbDictionary::Column::Time:
- {
- long tmp=(long) sint3korr(r.aRef());
- int hour=(uint) (tmp/10000);
- int minute=(uint) (tmp/100 % 100);
- int second=(uint) (tmp % 100);
- char buf[40];
- sprintf(buf, "%02d:%02d:%02d", hour, minute, second);
- out << buf;
- }
- break;
- case NdbDictionary::Column::Year:
- {
- uint year = 1900 + r.u_8_value();
- char buf[40];
- sprintf(buf, "%04d", year);
- out << buf;
- }
- break;
- case NdbDictionary::Column::Timestamp:
- {
- time_t time = r.u_32_value();
- out << (uint)time;
- }
- break;
- case NdbDictionary::Column::Blob:
- case NdbDictionary::Column::Text:
- {
- NdbBlob::Head head;
- NdbBlob::unpackBlobHead(head, r.aRef(), c->getBlobVersion());
- out << head.length << ":";
- const unsigned char* p = (const unsigned char*)r.aRef() + head.headsize;
- if (r.get_size_in_bytes() < head.headsize)
- out << "***error***"; // really cannot happen
- else {
- unsigned n = r.get_size_in_bytes() - head.headsize;
- for (unsigned k = 0; k < n && k < head.length; k++) {
- if (r.getType() == NdbDictionary::Column::Blob)
- out.print("%02X", (int)p[k]);
- else
- out.print("%c", (int)p[k]);
- }
- }
- j = length;
- }
- break;
- case NdbDictionary::Column::Longvarchar:
- {
- out << fields_optionally_enclosed_by;
- unsigned len = uint2korr(r.aRef());
- ndbrecattr_print_string(out,f,"Longvarchar", false, r.aRef()+2,len);
- j = length;
- out << fields_optionally_enclosed_by;
- }
- break;
- case NdbDictionary::Column::Longvarbinary:
- {
- if (!f.hex_format)
- out << fields_optionally_enclosed_by;
- unsigned len = uint2korr(r.aRef());
- ndbrecattr_print_string(out,f,"Longvarbinary", true, r.aRef()+2,len);
- j = length;
- if (!f.hex_format)
- out << fields_optionally_enclosed_by;
- }
- break;
-
- default: /* no print functions for the rest, just print type */
- out << "Unable to format type ("
- << (int) r.getType()
- << ")";
- if (length > 1)
- out << " " << length << " times";
- break;
- }
- out << f.fields_enclosed_by;
- }
-
- return out;
+ return NdbDictionary::printFormattedValue(out,
+ f,
+ r.getColumn(),
+ r.aRef());
}
NdbOut& operator<<(NdbOut& out, const NdbRecAttr &r)
=== modified file 'storage/ndb/src/ndbapi/ndberror.c'
--- a/storage/ndb/src/ndbapi/ndberror.c 2010-04-01 05:20:25 +0000
+++ b/storage/ndb/src/ndbapi/ndberror.c 2010-04-29 14:52:05 +0000
@@ -317,6 +317,7 @@ ErrorBundle ErrorCodes[] = {
{ 823, DMEC, AE, "Too much attrinfo from application in tuple manager" },
{ 829, DMEC, AE, "Corrupt data received for insert/update" },
{ 831, DMEC, AE, "Too many nullable/bitfields in table definition" },
+ { 850, DMEC, AE, "Too long or too short default value"},
{ 876, DMEC, AE, "876" },
{ 877, DMEC, AE, "877" },
{ 878, DMEC, AE, "878" },
@@ -472,6 +473,8 @@ ErrorBundle ErrorCodes[] = {
{ 777, DMEC, AE, "Cannot create a temporary index on a non-temporary table" },
{ 778, DMEC, AE, "A temporary table or index must be specified as not logging" },
{ 786, DMEC, NR, "Schema transaction aborted due to node-failure" },
+ { 792, DMEC, SE, "Default value for primary key column not supported" },
+ { 794, DMEC, AE, "Schema feature requires data node upgrade" },
/**
* FunctionNotImplemented
=== modified file 'storage/ndb/test/include/NDBT_Table.hpp'
--- a/storage/ndb/test/include/NDBT_Table.hpp 2009-05-27 15:21:45 +0000
+++ b/storage/ndb/test/include/NDBT_Table.hpp 2010-04-29 14:52:05 +0000
@@ -33,7 +33,9 @@ public:
bool _nullable = false,
CHARSET_INFO *cs= 0,
NdbDictionary::Column::StorageType storage = NdbDictionary::Column::StorageTypeMemory,
- bool dynamic = false):
+ bool dynamic = false,
+ const void* defaultVal = NULL,
+ Uint32 defaultValBytes = 0):
NdbDictionary::Column(_name)
{
assert(_name != 0);
@@ -48,6 +50,7 @@ public:
}
setStorageType(storage);
setDynamic(dynamic);
+ setDefaultValue(defaultVal, defaultValBytes);
}
};
=== modified file 'storage/ndb/test/ndbapi/CMakeLists.txt'
--- a/storage/ndb/test/ndbapi/CMakeLists.txt 2010-04-16 12:25:53 +0000
+++ b/storage/ndb/test/ndbapi/CMakeLists.txt 2010-04-29 14:52:05 +0000
@@ -66,6 +66,7 @@ ADD_EXECUTABLE(DbAsyncGenerator bench/ma
ADD_EXECUTABLE(testSRBank testSRBank.cpp)
ADD_EXECUTABLE(test_event_merge test_event_merge.cpp)
Add_EXECUTABLE(testNdbinfo testNdbinfo.cpp)
+ADD_EXECUTABLE(testNativeDefault testNativeDefault.cpp)
##testDict_INCLUDES = $(INCLUDES) -I$(top_srcdir)/ndb/include/kernel
##testIndex_INCLUDES = $(INCLUDES) -I$(top_srcdir)/ndb/include/kernel
##testSystemRestart_INCLUDES = $(INCLUDES) -I$(top_srcdir)/ndb/include/kernel
=== modified file 'storage/ndb/test/ndbapi/Makefile.am'
--- a/storage/ndb/test/ndbapi/Makefile.am 2009-11-08 12:52:27 +0000
+++ b/storage/ndb/test/ndbapi/Makefile.am 2010-04-29 14:52:05 +0000
@@ -37,6 +37,7 @@ testLimits \
testMgm \
testMgmd \
testSingleUserMode \
+testNativeDefault \
testNdbApi \
testNodeRestart \
testUpgrade \
@@ -104,6 +105,7 @@ testMgmd_SOURCES = testMgmd.cpp \
testMgmd_LDFLAGS = -static
testMgmd_CXXFLAGS = -I$(top_srcdir)/storage/ndb/src/mgmapi -I$(top_srcdir)/storage/ndb/include/debugger
testSingleUserMode_SOURCES = testSingleUserMode.cpp
+testNativeDefault_SOURCES = testNativeDefault.cpp
testNdbApi_SOURCES = testNdbApi.cpp
testNodeRestart_SOURCES = testNodeRestart.cpp
testUpgrade_SOURCES = testUpgrade.cpp
=== modified file 'storage/ndb/test/ndbapi/testBasic.cpp'
--- a/storage/ndb/test/ndbapi/testBasic.cpp 2010-01-28 15:16:46 +0000
+++ b/storage/ndb/test/ndbapi/testBasic.cpp 2010-04-29 14:52:05 +0000
@@ -1497,19 +1497,19 @@ runBug20535(NDBT_Context* ctx, NDBT_Step
{
Ndb* pNdb = GETNDB(step);
const NdbDictionary::Table * tab = ctx->getTab();
- NdbDictionary::Dictionary * dict = pNdb->getDictionary();
- bool null = false;
+ bool hasDefault = false;
for (Uint32 i = 0; i<(Uint32)tab->getNoOfColumns(); i++)
{
- if (tab->getColumn(i)->getNullable())
+ if (tab->getColumn(i)->getNullable() ||
+ tab->getColumn(i)->getDefaultValue())
{
- null = true;
+ hasDefault = true;
break;
}
}
- if (!null)
+ if (!hasDefault)
return NDBT_OK;
HugoTransactions hugoTrans(* tab);
@@ -1528,7 +1528,8 @@ runBug20535(NDBT_Context* ctx, NDBT_Step
for (Uint32 i = 0; i<(Uint32)tab->getNoOfColumns(); i++)
{
if (!tab->getColumn(i)->getPrimaryKey() &&
- !tab->getColumn(i)->getNullable())
+ !tab->getColumn(i)->getNullable() &&
+ !tab->getColumn(i)->getDefaultValue())
{
hugoTrans.setValueForAttr(pOp, i, 0, 1);
}
@@ -1547,7 +1548,8 @@ runBug20535(NDBT_Context* ctx, NDBT_Step
for (Uint32 i = 0; i<(Uint32)tab->getNoOfColumns(); i++)
{
if (!tab->getColumn(i)->getPrimaryKey() &&
- tab->getColumn(i)->getNullable())
+ (tab->getColumn(i)->getNullable() ||
+ tab->getColumn(i)->getDefaultValue()))
{
values.push_back(pOp->getValue(i));
}
@@ -1556,19 +1558,48 @@ runBug20535(NDBT_Context* ctx, NDBT_Step
if (pTrans->execute(Commit) != 0)
return NDBT_FAILED;
- null = true;
+ bool defaultOk = true;
for (unsigned int i = 0; i<values.size(); i++)
{
- if (!values[i]->isNULL())
+ const NdbRecAttr* recAttr = values[i];
+ const NdbDictionary::Column* col = recAttr->getColumn();
+ unsigned int defaultLen = 0;
+ const char* def = (const char*) col->getDefaultValue(&defaultLen);
+
+ if (def)
+ {
+ /* Column has a native default, check that it was set */
+
+ if (!recAttr->isNULL())
+ {
+ if (memcmp(def, recAttr->aRef(), defaultLen) != 0)
+ {
+ defaultOk = false;
+ ndbout_c("column %s does not have correct default value",
+ recAttr->getColumn()->getName());
+ }
+ }
+ else
+ {
+ defaultOk = false;
+ ndbout_c("column %s is null, should have default value",
+ recAttr->getColumn()->getName());
+ }
+ }
+ else
{
- null = false;
- ndbout_c("column %s is not NULL", values[i]->getColumn()->getName());
+ /* Column has Null as its default */
+ if (!recAttr->isNULL())
+ {
+ defaultOk = false;
+ ndbout_c("column %s is not NULL", recAttr->getColumn()->getName());
+ }
}
}
pTrans->close();
- if (null)
+ if (defaultOk)
return NDBT_OK;
else
return NDBT_FAILED;
=== modified file 'storage/ndb/test/ndbapi/testBitfield.cpp'
--- a/storage/ndb/test/ndbapi/testBitfield.cpp 2009-09-25 14:08:15 +0000
+++ b/storage/ndb/test/ndbapi/testBitfield.cpp 2010-04-29 14:52:05 +0000
@@ -69,7 +69,7 @@ main(int argc, char** argv){
Ndb* pNdb;
pNdb = new Ndb(&con, _dbname);
pNdb->init();
- while (pNdb->waitUntilReady() != 0);
+ while (pNdb->waitUntilReady() != 0) {};
NdbDictionary::Dictionary * dict = pNdb->getDictionary();
@@ -130,7 +130,9 @@ create_random_table(Ndb* pNdb)
do {
NdbDictionary::Table tab;
Uint32 cols = 1 + (rand() % (NDB_MAX_ATTRIBUTES_IN_TABLE - 1));
- Uint32 length = 4090;
+ const Uint32 maxLength = 4090;
+ Uint32 length = maxLength;
+ Uint8 defbuf[(maxLength + 7)/8];
BaseString name;
name.assfmt("TAB_%d", rand() & 65535);
@@ -153,6 +155,10 @@ create_random_table(Ndb* pNdb)
col.setType(NdbDictionary::Column::Bit);
Uint32 len = 1 + (rand() % (length - 1));
+ memset(defbuf, 0, (length + 7)/8);
+ for (Uint32 j = 0; j < len/8; j++)
+ defbuf[j] = 0x63;
+ col.setDefaultValue(defbuf, (len + 7)/8);
col.setLength(len); length -= len;
int nullable = (rand() >> 16) & 1;
col.setNullable(nullable); length -= nullable;
=== modified file 'storage/ndb/test/ndbapi/testDict.cpp'
--- a/storage/ndb/test/ndbapi/testDict.cpp 2010-01-18 11:12:17 +0000
+++ b/storage/ndb/test/ndbapi/testDict.cpp 2010-04-29 14:52:05 +0000
@@ -25,6 +25,7 @@
#include <signaldata/DumpStateOrd.hpp>
#include <../../include/kernel/ndb_limits.h>
#include <../../include/kernel/trigger_definitions.h>
+#include <signaldata/DictTabInfo.hpp>
#include <random.h>
#include <NdbAutoPtr.hpp>
#include <NdbMixRestarter.hpp>
@@ -1854,13 +1855,38 @@ runCreateDiskTable(NDBT_Context* ctx, ND
return NDBT_OK;
}
+int getColumnMaxLength(const NdbDictionary::Column* c)
+{
+ int length= c->getLength();
+ if (c->getArrayType() == NDB_ARRAYTYPE_FIXED)
+ {
+ /* Not yet set - need to calculate from type etc. */
+ DictTabInfo::Attribute attrDesc;
+
+ attrDesc.init();
+ attrDesc.AttributeExtType= c->getType();
+ attrDesc.AttributeExtLength= c->getLength();
+ attrDesc.AttributeExtPrecision= c->getPrecision();
+ attrDesc.AttributeExtScale= c->getScale();
+
+ if (!attrDesc.translateExtType())
+ {
+ return 0;
+ }
+
+ length= ((1 << attrDesc.AttributeSize) * c->getLength()) >> 3;
+ }
+
+ return length;
+}
+
#include <NDBT_Tables.hpp>
#define SAFTY 300
int runFailAddFragment(NDBT_Context* ctx, NDBT_Step* step){
static int acclst[] = { 3001, 6200, 6202 };
- static int tuplst[] = { 4007, 4008, 4009, 4010 };
+ static int tuplst[] = { 4007, 4008, 4009, 4010, 4032, 4033, 4034 };
static int tuxlst[] = { 12001, 12002, 12003, 12004,
6201, 6203 };
static unsigned acccnt = sizeof(acclst)/sizeof(acclst[0]);
@@ -1881,7 +1907,44 @@ int runFailAddFragment(NDBT_Context* ctx
errNo = atoi(buf);
ndbout_c("Using errno: %u", errNo);
}
-
+
+ const NdbDictionary::Table* origTab= ctx->getTab();
+ HugoCalculator calc(*origTab);
+
+ // Add defaults to some columns
+ for (int colNum= 0; colNum < tab.getNoOfColumns(); colNum++)
+ {
+ const NdbDictionary::Column* origCol= origTab->getColumn(colNum);
+ NdbDictionary::Column* col= tab.getColumn(colNum);
+ if (!origCol->getPrimaryKey())
+ {
+ if (myRandom48(2) == 0)
+ {
+ char defaultBuf[ NDB_MAX_TUPLE_SIZE ];
+ Uint32 real_len;
+ Uint32 updatesVal = myRandom48(1 << 16);
+ const char* def= calc.calcValue(0, colNum, updatesVal,
+ defaultBuf,
+ getColumnMaxLength(origCol),
+ &real_len);
+ if (col->setDefaultValue(def, real_len) != 0)
+ {
+ ndbout_c("Error setting default value\n");
+ return NDBT_FAILED;
+ }
+ NdbDictionary::NdbDataPrintFormat dpf;
+ ndbout << "Set default for column " << origCol->getName()
+ << " to ";
+
+ NdbDictionary::printFormattedValue(ndbout,
+ dpf,
+ col,
+ def);
+ ndbout << endl;
+ }
+ }
+ }
+
// ordered index on first few columns
NdbDictionary::Index idx("X");
idx.setTable(tab.getName());
=== added file 'storage/ndb/test/ndbapi/testNativeDefault.cpp'
--- a/storage/ndb/test/ndbapi/testNativeDefault.cpp 1970-01-01 00:00:00 +0000
+++ b/storage/ndb/test/ndbapi/testNativeDefault.cpp 2010-04-29 14:52:05 +0000
@@ -0,0 +1,810 @@
+/* Copyright (C) 2008 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; version 2 of the License.
+
+ 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 <NdbOut.hpp>
+#include <NdbApi.hpp>
+#include <NdbSleep.h>
+#include <NDBT.hpp>
+#include <NdbError.hpp>
+
+static Ndb_cluster_connection *g_cluster_connection= 0;
+static Ndb* g_ndb = 0;
+static const char* g_tablename1 = "T_DEF1"; //The normal table with default values
+static const char* g_tablename2 = "T_DEF2"; //The table for Test that maximum length defaults work
+//The table for Test that an attempt to insert to a table containing defaults
+//without supplying a value for a not-null, non-defaulted column still fails
+static const char* g_tablename3 = "T_DEF3";
+static NdbDictionary::Dictionary* g_dict = 0;
+static const unsigned int column_count_table1 = 8;
+static const unsigned int column_count_table2 = 2;
+static const unsigned int column_count_table3 = 2;
+
+static int connect_ndb();
+static int disconnect_ndb();
+
+static struct NdbError g_ndberror;
+static int create_table();
+
+static int connect_ndb()
+{
+ g_cluster_connection = new Ndb_cluster_connection();
+ if(g_cluster_connection->connect(12, 5, 1) != 0)
+ {
+ return NDBT_FAILED;
+ }
+ g_ndb = new Ndb(g_cluster_connection, "TEST");
+ g_ndb->init();
+ if(g_ndb->waitUntilReady(30) == 0){
+ return NDBT_OK;
+ }
+ return NDBT_FAILED;
+}
+
+static int disconnect_ndb() {
+ delete g_ndb;
+ delete g_cluster_connection;
+ g_ndb = 0;
+// g_table = 0;
+ g_cluster_connection= 0;
+ return NDBT_OK;
+}
+
+#define PRINT_ERROR(error) \
+ ndbout << "Error in " << __FILE__ << ", line: " << __LINE__ \
+ << ", code: " << error.code \
+ << ", msg: " << error.message << "." << endl
+#define FAIL(error_msg) \
+ ndbout << error_msg << " at line " << __LINE__ << endl; \
+ return NDBT_FAILED
+
+static const int tab1_c1_default= 6;
+static const float tab1_c2_default= float(1234.56);
+static const double tab1_c3_default= 4567.89;
+static const char tab1_c4_default[]= "aaaaaa ";
+static const unsigned int tab1_c4_default_siglen= 12;
+static const char tab1_c5_default[]= "\x6" "aaaaaa\0\0\0\0";
+static const unsigned int tab1_c5_default_siglen= 7;
+static const char tab1_c6_default[]= "aaaaaa ";
+static const unsigned int tab1_c6_default_siglen= 0;
+static const char tab1_c7_default[]= "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
+static const char tab1_c7_default_siglen= 1;
+
+static const int tab2_c1_default_len= 8052 - 4 - 2;
+/* Max row length minus 4 bytes for key, minus 2 bytes for length info */
+static const char tab2_c1_default_char= 'V';
+
+static int
+create_table()
+{
+ g_dict = g_ndb->getDictionary();
+ if ((g_dict->getTable(g_tablename1) != 0) &&
+ (g_dict->dropTable(g_tablename1) != 0))
+ {
+ PRINT_ERROR(g_dict->getNdbError());
+ return NDBT_FAILED;
+ }
+
+ if ((g_dict->getTable(g_tablename2) != 0) &&
+ (g_dict->dropTable(g_tablename2) != 0))
+ {
+ PRINT_ERROR(g_dict->getNdbError());
+ return NDBT_FAILED;
+ }
+
+ if ((g_dict->getTable(g_tablename3) != 0) &&
+ (g_dict->dropTable(g_tablename3) != 0))
+ {
+ PRINT_ERROR(g_dict->getNdbError());
+ return NDBT_FAILED;
+ }
+
+ NdbDictionary::Table tab(g_tablename1);
+ tab.setLogging(false);
+
+ NdbDictionary::Table tab2(g_tablename2);
+ tab2.setLogging(false);
+
+ NdbDictionary::Table tab3(g_tablename3);
+ tab3.setLogging(false);
+
+ // col PK - Uint32
+ { NdbDictionary::Column col("PK");
+ col.setType(NdbDictionary::Column::Unsigned);
+ col.setPrimaryKey(true);
+ col.setNullable(FALSE);
+ col.setAutoIncrement(TRUE);
+ col.setDefaultValue(NULL);
+ tab.addColumn(col);
+ }
+
+ {
+ NdbDictionary::Column col("C1");
+ col.setType(NdbDictionary::Column::Int);
+ col.setDefaultValue(&tab1_c1_default,sizeof(int));
+ tab.addColumn(col);
+ }
+
+ {
+ NdbDictionary::Column col("C2");
+ col.setType(NdbDictionary::Column::Float);
+ col.setDefaultValue(&tab1_c2_default, sizeof(float));
+ tab.addColumn(col);
+ }
+
+ {
+ NdbDictionary::Column col("C3");
+ col.setType(NdbDictionary::Column::Double);
+ col.setDefaultValue(&tab1_c3_default, sizeof(double));
+ tab.addColumn(col);
+ }
+
+ {
+ NdbDictionary::Column col("C4");
+ col.setType(NdbDictionary::Column::Char);
+ col.setLength(12);
+ col.setDefaultValue(tab1_c4_default, 12);
+ tab.addColumn(col);
+ }
+
+ {
+ NdbDictionary::Column col("C5");
+ col.setType(NdbDictionary::Column::Varchar);
+ col.setLength(199);
+ col.setDefaultValue(tab1_c5_default, tab1_c5_default_siglen);
+ tab.addColumn(col);
+ }
+
+
+ {
+ /* Test non-null pointer passed, but with zero length? */
+ NdbDictionary::Column col("C6");
+ col.setType(NdbDictionary::Column::Char);
+ col.setLength(12);
+ col.setNullable(TRUE);
+ col.setDefaultValue(tab1_c6_default, tab1_c6_default_siglen);
+ tab.addColumn(col);
+ }
+
+ //Test that a zero-length VARCHAR default works
+ {
+ NdbDictionary::Column col("C7");
+ col.setType(NdbDictionary::Column::Varchar);
+ col.setLength(10);
+ col.setDefaultValue(tab1_c7_default, tab1_c7_default_siglen);
+ tab.addColumn(col);
+ }
+
+ //create table T_DEF2
+ { NdbDictionary::Column col("PK");
+ col.setType(NdbDictionary::Column::Unsigned);
+ col.setPrimaryKey(true);
+ col.setNullable(FALSE);
+ col.setAutoIncrement(FALSE);
+ col.setDefaultValue(NULL, 0);
+ tab2.addColumn(col);
+ }
+
+ //Test that maximum length defaults work
+ {
+ char default_data[tab2_c1_default_len + 2];
+ default_data[0] = (tab2_c1_default_len >> 0) & 0xff;
+ default_data[1] = (tab2_c1_default_len >> 8) & 0xff;
+ memset(default_data + 2, tab2_c1_default_char, tab2_c1_default_len);
+ NdbDictionary::Column col("C1");
+ col.setType(NdbDictionary::Column::Longvarchar);
+ col.setLength(tab2_c1_default_len);
+ col.setDefaultValue(default_data, tab2_c1_default_len + 2);
+ tab2.addColumn(col);
+ }
+
+ //Create table T_DEF3
+ { NdbDictionary::Column col("PK");
+ col.setType(NdbDictionary::Column::Unsigned);
+ col.setPrimaryKey(true);
+ col.setNullable(FALSE);
+ col.setAutoIncrement(FALSE);
+ col.setDefaultValue(NULL, 0);
+ tab3.addColumn(col);
+ }
+
+ //For column without supplying a value for a not-null, non-defaulted column
+ { NdbDictionary::Column col("C1");
+ col.setType(NdbDictionary::Column::Unsigned);
+ col.setNullable(FALSE);
+ col.setDefaultValue(NULL, 0);
+ tab3.addColumn(col);
+ }
+
+ // create table
+ if(g_dict->createTable(tab) != 0)
+ {
+ PRINT_ERROR(g_dict->getNdbError());
+ return NDBT_FAILED;
+ }
+
+ if(g_dict->createTable(tab2) != 0)
+ {
+ PRINT_ERROR(g_dict->getNdbError());
+ return NDBT_FAILED;
+ }
+
+ if(g_dict->createTable(tab3) != 0)
+ {
+ PRINT_ERROR(g_dict->getNdbError());
+ return NDBT_FAILED;
+ }
+
+ return NDBT_OK;
+}
+
+static int
+ndb_error_check(const struct NdbError& error, unsigned int line)
+{
+ if (error.code != 850)
+ {
+ PRINT_ERROR(error);
+ ndbout << " at line " << line << "\n";
+ return NDBT_FAILED;
+ }
+ return NDBT_OK;
+}
+
+#define CHECK_ERROR(error) { \
+ if (ndb_error_check(error, __LINE__) == NDBT_FAILED) \
+ return NDBT_FAILED; \
+ }
+
+static int
+create_table_error()
+{
+ g_dict = g_ndb->getDictionary();
+
+ /*
+ * 1. The following test case is for fixed columns that
+ * there are too long or too short default values.
+ */
+ //for too long default value
+ NdbDictionary::Table tab1("T_DEF_TEST1");
+ tab1.setLogging(false);
+
+ { NdbDictionary::Column col("PK");
+ col.setType(NdbDictionary::Column::Unsigned);
+ col.setPrimaryKey(true);
+ col.setNullable(FALSE);
+ col.setDefaultValue(NULL);
+ tab1.addColumn(col);
+ }
+
+ { int default_data = 6;
+ NdbDictionary::Column col("C1");
+ col.setType(NdbDictionary::Column::Int);
+ col.setDefaultValue(&default_data, 8);
+ tab1.addColumn(col);
+ }
+
+ if(g_dict->createTable(tab1) != 0)
+ {
+ CHECK_ERROR(g_dict->getNdbError());
+ }
+ else
+ {
+ FAIL("Create table should not have succeeded");
+ }
+
+ //for too short default value
+ NdbDictionary::Table tab2("T_DEF_TEST2");
+ tab2.setLogging(false);
+
+ { NdbDictionary::Column col("PK");
+ col.setType(NdbDictionary::Column::Unsigned);
+ col.setPrimaryKey(true);
+ col.setNullable(FALSE);
+ col.setAutoIncrement(TRUE);
+ col.setDefaultValue(NULL);
+ tab2.addColumn(col);
+ }
+
+ { const char default_data[] = "aaaaaa";
+ NdbDictionary::Column col("C4");
+ col.setType(NdbDictionary::Column::Char);
+ col.setLength(12);
+ col.setDefaultValue(default_data, 6);
+ tab2.addColumn(col);
+ }
+
+ if(g_dict->createTable(tab2) != 0)
+ {
+ CHECK_ERROR(g_dict->getNdbError());
+ }
+ else
+ {
+ FAIL("Create table should not have succeeded");
+ }
+
+ /*
+ * 2. The following test case is for Var-type columns that
+ * there are too long default values.
+ */
+ NdbDictionary::Table tab3("T_DEF_TEST3");
+ tab3.setLogging(false);
+
+ { NdbDictionary::Column col("PK");
+ col.setType(NdbDictionary::Column::Unsigned);
+ col.setPrimaryKey(true);
+ col.setNullable(FALSE);
+ col.setAutoIncrement(TRUE);
+ col.setDefaultValue(NULL);
+ tab3.addColumn(col);
+ }
+
+ { char default_data[20];
+ memset(default_data, 0, 20);
+ Uint8 * p = (Uint8*)default_data;
+ *p = 10;
+ memcpy(default_data + 1, "aaaaaaaaaa", 10);
+ NdbDictionary::Column col("C5");
+ col.setType(NdbDictionary::Column::Varchar);
+ col.setLength(9);
+ col.setDefaultValue(default_data, 11);
+ tab3.addColumn(col);
+ }
+
+ if(g_dict->createTable(tab3) != 0)
+ {
+ CHECK_ERROR(g_dict->getNdbError());
+ }
+ else
+ {
+ FAIL("Create table should not have succeeded");
+ }
+
+
+ /*
+ * 3. Test attempt to set default value for primary key
+ */
+ NdbDictionary::Table tab4("T_DEF_TEST4");
+ tab4.setLogging(false);
+
+ { NdbDictionary::Column col("PK");
+ unsigned int default_val=22;
+ col.setType(NdbDictionary::Column::Unsigned);
+ col.setPrimaryKey(true);
+ col.setNullable(FALSE);
+ col.setAutoIncrement(TRUE);
+ col.setDefaultValue(&default_val, sizeof(default_val));
+ tab4.addColumn(col);
+ }
+
+ if(g_dict->createTable(tab4) == 0)
+ {
+ FAIL("Create table should not have succeeded");
+ }
+
+ if(g_dict->getNdbError().code != 792)
+ {
+ PRINT_ERROR(g_dict->getNdbError());
+ return NDBT_FAILED;
+ }
+
+ /*
+ * 4. The following test case is for Var-type columns that
+ * there are too long default values, where the passed
+ * value is short, but the implied value is too long
+ */
+ NdbDictionary::Table tab5("T_DEF_TEST5");
+ tab5.setLogging(false);
+
+ { NdbDictionary::Column col("PK");
+ col.setType(NdbDictionary::Column::Unsigned);
+ col.setPrimaryKey(true);
+ col.setNullable(FALSE);
+ col.setAutoIncrement(TRUE);
+ col.setDefaultValue(NULL);
+ tab5.addColumn(col);
+ }
+
+ { char default_data[20];
+ memset(default_data, 0, 20);
+ Uint8 * p = (Uint8*)default_data;
+ *p = 15;
+ memcpy(default_data + 1, "aaaaaaaaaa", 15);
+ NdbDictionary::Column col("C5");
+ col.setType(NdbDictionary::Column::Varchar);
+ col.setLength(9);
+ /* Within range, but contained VARCHAR is too long */
+ col.setDefaultValue(default_data, 10);
+ tab5.addColumn(col);
+ }
+
+ if(g_dict->createTable(tab5) != 0)
+ {
+ CHECK_ERROR(g_dict->getNdbError());
+ }
+ else
+ {
+ FAIL("Create table should not have succeeded");
+ }
+
+ return NDBT_OK;
+}
+
+static int
+drop_table()
+{
+ if ((g_dict != 0) && ( g_dict->getTable(g_tablename1) != 0))
+ {
+ if(g_dict->dropTable(g_tablename1))
+ PRINT_ERROR(g_dict->getNdbError());
+ }
+
+ if ((g_dict != 0) && ( g_dict->getTable(g_tablename2) != 0))
+ {
+ if(g_dict->dropTable(g_tablename2))
+ PRINT_ERROR(g_dict->getNdbError());
+ }
+
+ if ((g_dict != 0) && ( g_dict->getTable(g_tablename3) != 0))
+ {
+ if(g_dict->dropTable(g_tablename3))
+ PRINT_ERROR(g_dict->getNdbError());
+ }
+
+ return NDBT_OK;
+}
+
+static int do_insert()
+{
+ const NdbDictionary::Table *myTable= g_dict->getTable(g_tablename1);
+
+ if (myTable == NULL)
+ {
+ PRINT_ERROR(g_dict->getNdbError());
+ return NDBT_FAILED;
+ }
+
+ NdbTransaction *myTransaction= g_ndb->startTransaction();
+ if (myTransaction == NULL)
+ {
+ PRINT_ERROR(g_ndb->getNdbError());
+ return NDBT_FAILED;
+ }
+
+ NdbOperation *myOperation= myTransaction->getNdbOperation(myTable);
+ NdbOperation *myOperation1= myTransaction->getNdbOperation(myTable);
+ if (myOperation == NULL || myOperation1 == NULL)
+ {
+ PRINT_ERROR(myTransaction->getNdbError());
+ g_ndb->closeTransaction(myTransaction);
+ return NDBT_FAILED;
+ }
+
+ myOperation->insertTuple();
+ myOperation->equal("PK", 1);
+ myOperation1->insertTuple();
+ myOperation1->equal("PK", 2);
+
+ //insert the second table T_DEF2
+ const NdbDictionary::Table *myTable2= g_dict->getTable(g_tablename2);
+
+ if (myTable == NULL)
+ {
+ PRINT_ERROR(g_dict->getNdbError());
+ return NDBT_FAILED;
+ }
+ NdbOperation *myOperation2 = myTransaction->getNdbOperation(myTable2);
+ if (myOperation2 == NULL)
+ {
+ PRINT_ERROR(myTransaction->getNdbError());
+ g_ndb->closeTransaction(myTransaction);
+ return NDBT_FAILED;
+ }
+
+ myOperation2->insertTuple();
+ myOperation2->equal("PK", 1);
+
+
+ /* Test insert of max length tuple with max length default
+ * Could theoretically expose kernel overflow with default
+ * + supplied value
+ */
+ myOperation2=myTransaction->getNdbOperation(myTable2);
+ if (myOperation2 == NULL)
+ {
+ PRINT_ERROR(myTransaction->getNdbError());
+ g_ndb->closeTransaction(myTransaction);
+ return NDBT_FAILED;
+ }
+
+ myOperation2->insertTuple();
+ myOperation2->equal("PK", 2);
+
+ {
+ char default_data[tab2_c1_default_len + 2];
+ default_data[0] = (tab2_c1_default_len >> 0) & 0xff;
+ default_data[1] = (tab2_c1_default_len >> 8) & 0xff;
+ memset(default_data + 2, tab2_c1_default_char, tab2_c1_default_len);
+
+ myOperation2->setValue("C1", default_data);
+ }
+
+ if (myTransaction->execute(NdbTransaction::Commit) == -1)
+ {
+ PRINT_ERROR(myTransaction->getNdbError());
+ g_ndb->closeTransaction(myTransaction);
+ return NDBT_FAILED;
+ }
+
+ g_ndb->closeTransaction(myTransaction);
+
+ //The following insert should fail, and return error code
+ const NdbDictionary::Table *myTable3= g_dict->getTable(g_tablename3);
+
+ if (myTable3 == NULL)
+ {
+ PRINT_ERROR(g_dict->getNdbError());
+ return NDBT_FAILED;
+ }
+
+ NdbTransaction *myTransaction3 = g_ndb->startTransaction();
+ if (myTransaction3 == NULL)
+ {
+ PRINT_ERROR(g_ndb->getNdbError());
+ return NDBT_FAILED;
+ }
+
+ NdbOperation *myOperation3 = myTransaction3->getNdbOperation(myTable3);
+ if (myOperation3 == NULL)
+ {
+ PRINT_ERROR(myTransaction3->getNdbError());
+ g_ndb->closeTransaction(myTransaction3);
+ return NDBT_FAILED;
+ }
+ myOperation3->insertTuple();
+ myOperation3->equal("PK", 1);
+
+ /* It should return error code 839 ( msg: Illegal null attribute)
+ * for an attempt to insert to a table containing defaults
+ * without supplying a value for a not-null, non-defaulted column
+ */
+ if (myTransaction3->execute(NdbTransaction::Commit) == -1)
+ {
+ PRINT_ERROR(myTransaction3->getNdbError());
+
+ if (myTransaction3->getNdbError().code != 839)
+ {
+ ndbout << "Expected error 839" << endl;
+ g_ndb->closeTransaction(myTransaction3);
+ return NDBT_FAILED;
+ }
+ }
+ g_ndb->closeTransaction(myTransaction3);
+
+ return NDBT_OK;
+}
+
+#define CHECK_VAL_EQ(ref, test) { \
+ if ((ref) != (test)) { \
+ ndbout << "Equality failed at line " << __LINE__ << "\n" \
+ << test << " != " << ref << "\n"; \
+ return NDBT_FAILED; \
+ } }
+
+#define CHECK_BYTES_EQ(ref, test, len) { \
+ if (memcmp((ref), (test), (len))) { \
+ ndbout << "Bytes differ at line " << __LINE__ << "\n"; \
+ return NDBT_FAILED; \
+ }}
+
+
+
+
+static int do_read()
+{
+ NdbRecAttr *myRecAttr[column_count_table1];
+ NdbRecAttr *myRecAttr2[column_count_table2];
+ NdbRecAttr *myRecAttr3[column_count_table3];
+
+ const NdbDictionary::Table *myTable= g_dict->getTable(g_tablename1);
+ const NdbDictionary::Table *myTable2 = g_dict->getTable(g_tablename2);
+ const NdbDictionary::Table *myTable3 = g_dict->getTable(g_tablename3);
+
+ if (myTable == NULL || myTable2 == NULL || myTable3 == NULL)
+ {
+ PRINT_ERROR(g_dict->getNdbError());
+ return NDBT_FAILED;
+ }
+
+ NdbTransaction *myTransaction= g_ndb->startTransaction();
+ if (myTransaction == NULL)
+ {
+ PRINT_ERROR(g_ndb->getNdbError());
+ return NDBT_FAILED;
+ }
+
+ //Define Scan Operation for T_DEF1
+ NdbScanOperation *myScanOp = myTransaction->getNdbScanOperation(myTable);
+ if (myScanOp == NULL)
+ {
+ PRINT_ERROR(myTransaction->getNdbError());
+ g_ndb->closeTransaction(myTransaction);
+ return NDBT_FAILED;
+ }
+
+ if(myScanOp->readTuples(NdbOperation::LM_CommittedRead) == -1)
+ {
+ PRINT_ERROR(myTransaction->getNdbError());
+ g_ndb->closeTransaction(myTransaction);
+ return NDBT_FAILED;
+ }
+
+ myRecAttr[0] = myScanOp->getValue("PK");
+ myRecAttr[1] = myScanOp->getValue("C1");
+ myRecAttr[2] = myScanOp->getValue("C2");
+ myRecAttr[3] = myScanOp->getValue("C3");
+ myRecAttr[4] = myScanOp->getValue("C4");
+ myRecAttr[5] = myScanOp->getValue("C5");
+ myRecAttr[6] = myScanOp->getValue("C6");
+ myRecAttr[7] = myScanOp->getValue("C7");
+
+ for (unsigned int i = 0; i < column_count_table1; i++)
+ if (myRecAttr[i] == NULL)
+ {
+ PRINT_ERROR(myTransaction->getNdbError());
+ g_ndb->closeTransaction(myTransaction);
+ return NDBT_FAILED;
+ }
+
+ //Define Scan Operation for T_DEF2
+ NdbScanOperation *myScanOp2 = myTransaction->getNdbScanOperation(myTable2);
+ if (myScanOp2 == NULL)
+ {
+ PRINT_ERROR(myTransaction->getNdbError());
+ g_ndb->closeTransaction(myTransaction);
+ return NDBT_FAILED;
+ }
+
+ if(myScanOp2->readTuples(NdbOperation::LM_CommittedRead) == -1)
+ {
+ PRINT_ERROR(myTransaction->getNdbError());
+ g_ndb->closeTransaction(myTransaction);
+ return NDBT_FAILED;
+ }
+
+ myRecAttr2[0] = myScanOp2->getValue("PK");
+ myRecAttr2[1] = myScanOp2->getValue("C1");
+ if (myRecAttr2[0] == NULL || myRecAttr2[1] == NULL)
+ {
+ PRINT_ERROR(myTransaction->getNdbError());
+ g_ndb->closeTransaction(myTransaction);
+ return NDBT_FAILED;
+ }
+
+ //Define Scan Operation for T_DEF3
+ NdbScanOperation *myScanOp3 = myTransaction->getNdbScanOperation(myTable3);
+ if (myScanOp3 == NULL)
+ {
+ PRINT_ERROR(myTransaction->getNdbError());
+ g_ndb->closeTransaction(myTransaction);
+ return NDBT_FAILED;
+ }
+
+ if(myScanOp3->readTuples(NdbOperation::LM_CommittedRead) == -1)
+ {
+ PRINT_ERROR(myTransaction->getNdbError());
+ g_ndb->closeTransaction(myTransaction);
+ return NDBT_FAILED;
+ }
+
+ myRecAttr3[0] = myScanOp3->getValue("PK");
+ myRecAttr3[1] = myScanOp3->getValue("C1");
+ if (myRecAttr3[0] == NULL || myRecAttr3[1] == NULL)
+ {
+ PRINT_ERROR(myTransaction->getNdbError());
+ g_ndb->closeTransaction(myTransaction);
+ return NDBT_FAILED;
+ }
+
+ //Execute the Transcation for the 3 scan operations
+ if(myTransaction->execute(NdbTransaction::NoCommit) != 0)
+ {
+ PRINT_ERROR(myTransaction->getNdbError());
+ g_ndb->closeTransaction(myTransaction);
+ return NDBT_FAILED;
+ }
+
+ //The following print out the result
+ int check;
+ ndbout<< "Table: " << g_tablename1 << endl;
+// ndbout << "PK";
+// for (unsigned int i = 0; i < column_count_table1; i++)
+// ndbout << "\tC" << i ;
+// ndbout << endl;
+ while((check = myScanOp->nextResult(true)) == 0){
+ do {
+// for (Uint32 i = 0; i < column_count_table1; i++)
+// ndbout << *myRecAttr[i] << "\t";
+// ndbout << endl;
+
+ for (Uint32 i = 0; i < column_count_table1; i++)
+ {
+ /* Check that all columns are non NULL except c6 */
+ CHECK_VAL_EQ((i == 6), myRecAttr[i]->isNULL());
+ }
+
+ CHECK_VAL_EQ(tab1_c1_default, (int) myRecAttr[1]->int32_value());
+ CHECK_VAL_EQ(tab1_c2_default, myRecAttr[2]->float_value());
+ CHECK_VAL_EQ(tab1_c3_default, myRecAttr[3]->double_value());
+ CHECK_BYTES_EQ(tab1_c4_default, (const char*) myRecAttr[4]->aRef(), tab1_c4_default_siglen);
+ CHECK_BYTES_EQ(tab1_c5_default, (const char*) myRecAttr[5]->aRef(), tab1_c5_default_siglen);
+ CHECK_BYTES_EQ(tab1_c6_default, (const char*) myRecAttr[6]->aRef(), tab1_c6_default_siglen);
+ CHECK_BYTES_EQ(tab1_c7_default, (const char*) myRecAttr[7]->aRef(), tab1_c7_default_siglen);
+ } while((check = myScanOp->nextResult(false)) == 0);
+
+ if(check == -1)
+ {
+ ndbout << "Error with transaction " << check << " "
+ << myTransaction->getNdbError().code << "\n";
+ return NDBT_FAILED;
+ }
+ }
+
+ ndbout<< "Table: " << g_tablename2 << endl;
+ // ndbout << "PK\tC1" << endl;
+ while((check = myScanOp2->nextResult(true)) == 0){
+ do {
+// for (Uint32 i = 0; i < column_count_table2; i++)
+// {
+// if (i == 1)
+// ndbout << myRecAttr2[i]->get_size_in_bytes() << " ";
+// ndbout << *myRecAttr2[i] << "\t";
+// }
+// ndbout << endl;
+ const char* valPtr= (const char*)myRecAttr2[1]->aRef();
+ char default_data[tab2_c1_default_len + 2];
+ default_data[0] = (tab2_c1_default_len >> 0) & 0xff;
+ default_data[1] = (tab2_c1_default_len >> 8) & 0xff;
+ memset(default_data + 2, tab2_c1_default_char, tab2_c1_default_len);
+
+ CHECK_BYTES_EQ(default_data, valPtr, tab2_c1_default_len + 2);
+
+ } while((check = myScanOp2->nextResult(false)) == 0);
+ }
+
+
+ return NDBT_OK;
+}
+
+int main(int argc, char* argv[])
+{
+ int ret = NDBT_OK;
+ ndb_init();
+ connect_ndb();
+ if ((ret = create_table_error()) == NDBT_FAILED)
+ return ret;
+
+ if ((ret = create_table()) == NDBT_FAILED)
+ return ret;
+ if ((ret = do_insert()) == NDBT_FAILED)
+ return ret;
+ if ((ret = do_read()) == NDBT_FAILED)
+ return ret;
+
+ if ((ret = drop_table()) == NDBT_FAILED)
+ return ret;
+
+ disconnect_ndb();
+
+ ndbout << "All tests successful" << endl;
+ return NDBT_OK;
+}
=== modified file 'storage/ndb/test/ndbapi/testUpgrade.cpp'
--- a/storage/ndb/test/ndbapi/testUpgrade.cpp 2010-03-22 12:38:39 +0000
+++ b/storage/ndb/test/ndbapi/testUpgrade.cpp 2010-04-29 14:52:05 +0000
@@ -847,11 +847,14 @@ runPostUpgradeChecks(NDBT_Context* ctx,
ndbout << "done" << endl;
- if (ctx->getProperty("NoDDL", Uint32(0)) == 0)
+ if ((ctx->getProperty("NoDDL", Uint32(0)) == 0) &&
+ (ctx->getProperty("KeepFS", Uint32(0)) != 0))
{
/**
* Bug48227
- *
+ * Upgrade with FS 6.3->7.0, followed by table
+ * create, followed by Sys restart resulted in
+ * table loss.
*/
Ndb* pNdb = GETNDB(step);
NdbDictionary::Dictionary *pDict = pNdb->getDictionary();
@@ -915,6 +918,17 @@ runWait(NDBT_Context* ctx, NDBT_Step* st
return NDBT_OK;
}
+bool versionsSpanBoundary(int verA, int verB, int incBoundaryVer)
+{
+ int minPeerVer = MIN(verA, verB);
+ int maxPeerVer = MAX(verA, verB);
+
+ return ( (minPeerVer < incBoundaryVer) &&
+ (maxPeerVer >= incBoundaryVer) );
+}
+
+#define SchemaTransVersion NDB_MAKE_VERSION(6,4,0)
+
int runPostUpgradeDecideDDL(NDBT_Context* ctx, NDBT_Step* step)
{
/* We are running post-upgrade, now examine the versions
@@ -923,10 +937,11 @@ int runPostUpgradeDecideDDL(NDBT_Context
*/
/* DDL should be ok as long as
* 1) All data nodes have the same version
- * 2) We are at the same version as the data nodes
+ * 2) There is not some version specific exception
*/
bool useDDL = true;
+ Ndb* pNdb = GETNDB(step);
NdbRestarter restarter;
int minNdbVer = 0;
int maxNdbVer = 0;
@@ -945,14 +960,53 @@ int runPostUpgradeDecideDDL(NDBT_Context
useDDL = false;
ndbout << "Ndbd nodes have mixed versions, DDL not supported" << endl;
}
- if (myVer != minNdbVer)
+ if (versionsSpanBoundary(myVer, minNdbVer, SchemaTransVersion))
{
useDDL = false;
- ndbout << "Api has different version to Ndbd nodes, DDL not supported" << endl;
+ ndbout << "Api and Ndbd versions span schema-trans boundary, DDL not supported" << endl;
}
ctx->setProperty("NoDDL", useDDL?0:1);
+ if (useDDL)
+ {
+ ndbout << "Dropping and recreating tables..." << endl;
+
+ for (int i=0; i < NDBT_Tables::getNumTables(); i++)
+ {
+ /* Drop table (ignoring rc if it doesn't exist etc...) */
+ pNdb->getDictionary()->dropTable(NDBT_Tables::getTable(i)->getName());
+ int ret= NDBT_Tables::createTable(pNdb,
+ NDBT_Tables::getTable(i)->getName(),
+ false, // temp
+ false); // exists ok
+ if(ret)
+ {
+ NdbError err = pNdb->getDictionary()->getNdbError();
+
+ g_err << "Failed to create table "
+ << NDBT_Tables::getTable(i)->getName()
+ << " error : "
+ << err
+ << endl;
+
+ /* Check for allowed exceptions during upgrade */
+ if (err.code == 794)
+ {
+ /* Schema feature requires data node upgrade */
+ if (minNdbVer >= myVer)
+ {
+ g_err << "Error 794 received, but data nodes are upgraded" << endl;
+ // TODO : Dump versions here
+ return NDBT_FAILED;
+ }
+ g_err << "Create table failure due to old version NDBDs, continuing" << endl;
+ }
+ }
+ }
+ ndbout << "Done" << endl;
+ }
+
return NDBT_OK;
}
=== modified file 'storage/ndb/test/run-test/daily-basic-tests.txt'
--- a/storage/ndb/test/run-test/daily-basic-tests.txt 2010-03-17 12:37:40 +0000
+++ b/storage/ndb/test/run-test/daily-basic-tests.txt 2010-04-29 14:52:05 +0000
@@ -1548,3 +1548,7 @@ max-time: 300
cmd: testNodeRestart
args: -n MixReadUnlockRestart T1
+mas-time: 500
+cmd: testNativeDefault
+args:
+
=== modified file 'storage/ndb/test/src/NDBT_Tables.cpp'
--- a/storage/ndb/test/src/NDBT_Tables.cpp 2010-01-20 09:51:06 +0000
+++ b/storage/ndb/test/src/NDBT_Tables.cpp 2010-04-29 14:52:05 +0000
@@ -407,16 +407,42 @@ const
NDBT_Table D1("D1", sizeof(D1Attribs)/sizeof(NDBT_Attribute), D1Attribs);
static
+const char* BigVarDefault =
+ "\x80\x1"
+ "KOL7 default in table D2"
+ "KOL7 default in table D2"
+ "KOL7 default in table D2"
+ "KOL7 default in table D2"
+ "KOL7 default in table D2"
+ "KOL7 default in table D2"
+ "KOL7 default in table D2"
+ "KOL7 default in table D2"
+ "KOL7 default in table D2"
+ "KOL7 default in table D2"
+ "KOL7 default in table D2"
+ "KOL7 default in table D2"
+ "KOL7 default in table D2"
+ "KOL7 default in table D2"
+ "KOL7 default in table D2"
+ "KOL7 default in table D2";
+
+static unsigned smallUintDefault = 77;
+
+static
const
NDBT_Attribute D2Attribs[] = {
NDBT_Attribute("KOL1", NdbDictionary::Column::Varbinary, 127, true),
- NDBT_Attribute("KOL2", NdbDictionary::Column::Unsigned, 1, false, false, 0, NdbDictionary::Column::StorageTypeDisk),
+ NDBT_Attribute("KOL2", NdbDictionary::Column::Unsigned, 1, false, false, 0, NdbDictionary::Column::StorageTypeDisk, false,
+ &smallUintDefault, sizeof(unsigned)),
NDBT_Attribute("KOL3", NdbDictionary::Column::Unsigned),
- NDBT_Attribute("KOL4", NdbDictionary::Column::Varbinary, 133, false, true, 0, MM, true),
+ NDBT_Attribute("KOL4", NdbDictionary::Column::Varbinary, 133, false, true, 0, MM, true,
+ "\x1E" "A default value for KOL4 in D2", 31),
NDBT_Attribute("KOL5", NdbDictionary::Column::Char, 199, false, true, 0, NdbDictionary::Column::StorageTypeDisk),
NDBT_Attribute("KOL6", NdbDictionary::Column::Bit, 21, false, false, 0, NdbDictionary::Column::StorageTypeDisk),
- NDBT_Attribute("KOL7", NdbDictionary::Column::Longvarbinary, 384, false, true, 0, NdbDictionary::Column::StorageTypeDisk),
- NDBT_Attribute("KOL8", NdbDictionary::Column::Varbinary, 88, false, true, 0, NdbDictionary::Column::StorageTypeDisk)
+ NDBT_Attribute("KOL7", NdbDictionary::Column::Longvarbinary, 384, false, true, 0, NdbDictionary::Column::StorageTypeDisk, false,
+ BigVarDefault, 386),
+ NDBT_Attribute("KOL8", NdbDictionary::Column::Varbinary, 88, false, true, 0, NdbDictionary::Column::StorageTypeDisk, false,
+ "\x1E""A default value for KOL8 in D2", 31)
};
static
Attachment: [text/bzr-bundle] bzr/frazer@mysql.com-20100429160305-6115p1it2wltva83.bundle
| Thread |
|---|
| • bzr commit into mysql-5.1-telco-7.1 branch (frazer:3584) | Frazer Clement | 29 Apr |