diff options
author | Olivier Bertrand <bertrandop@gmail.com> | 2015-05-15 11:56:29 +0200 |
---|---|---|
committer | Olivier Bertrand <bertrandop@gmail.com> | 2015-05-15 11:56:29 +0200 |
commit | b9c910909c3e04ceab8d0d514ba6213015787c5a (patch) | |
tree | fb8ee71de177393751c22f07efb5ccdb9ebdfa04 /storage | |
parent | e6b60ee5af76a574a9c87733143e608a2bc648bb (diff) | |
download | mariadb-git-b9c910909c3e04ceab8d0d514ba6213015787c5a.tar.gz |
Fix a bug in BIN buffer initialisation (in FIXFAM::AllocateBuffer)
modified: storage/connect/filamfix.cpp
Second version of BIN table new field format (1st one was buggy)
modified: storage/connect/tabfix.cpp
modified: storage/connect/tabfix.h
Make bin.test not to fail in big-endian machines
modified: storage/connect/mysql-test/connect/r/bin.result
modified: storage/connect/mysql-test/connect/t/bin.test
Fix a bug causing wrong default offset to be generated when virtual
or special columns were placed beetween standard columns. Also
calculate the good offset for BIN columns with new field format.
modified: storage/connect/reldef.cpp
Diffstat (limited to 'storage')
-rw-r--r-- | storage/connect/filamfix.cpp | 33 | ||||
-rw-r--r-- | storage/connect/mysql-test/connect/r/bin.result | 28 | ||||
-rw-r--r-- | storage/connect/mysql-test/connect/t/bin.test | 154 | ||||
-rw-r--r-- | storage/connect/reldef.cpp | 17 | ||||
-rw-r--r-- | storage/connect/tabfix.cpp | 56 | ||||
-rw-r--r-- | storage/connect/tabfix.h | 22 |
6 files changed, 173 insertions, 137 deletions
diff --git a/storage/connect/filamfix.cpp b/storage/connect/filamfix.cpp index 4dedd3375b0..c352db47044 100644 --- a/storage/connect/filamfix.cpp +++ b/storage/connect/filamfix.cpp @@ -46,6 +46,7 @@ #include "plgdbsem.h" #include "filamfix.h" #include "tabdos.h" +#include "tabfix.h" #include "osutil.h" #ifndef INVALID_SET_FILE_POINTER @@ -133,18 +134,35 @@ bool FIXFAM::AllocateBuffer(PGLOBAL g) if (Tdbp->GetFtype() == RECFM_BIN) { // The buffer must be prepared depending on column types int n = 0; + bool b = false; PDOSDEF defp = (PDOSDEF)Tdbp->GetDef(); - PCOLDEF cdp; +// PCOLDEF cdp; + PBINCOL colp; // Prepare the first line of the buffer memset(To_Buf, 0, Buflen); +#if 0 for (cdp = defp->GetCols(); cdp; cdp = cdp->GetNext()) { - if (IsTypeNum(cdp->GetType())) - memset(To_Buf + cdp->GetOffset(), ' ', cdp->GetClen()); + if (!IsTypeNum(cdp->GetType())) { + memset(To_Buf + cdp->GetOffset(), ' ', cdp->GetClen()); + b = true; + } // endif not num - n = MY_MAX(n, cdp->GetPoff() + cdp->GetClen()); + n = MY_MAX(n, cdp->GetOffset() + cdp->GetClen()); } // endfor cdp +#endif // 0 + + for (colp = (PBINCOL)Tdbp->GetColumns(); colp; + colp = (PBINCOL)colp->GetNext()) + if (!colp->IsSpecial()) { + if (!IsTypeNum(colp->GetResultType())) { + memset(To_Buf + colp->GetDeplac(), ' ', colp->GetLength()); + b = true; + } // endif not num + + n = MY_MAX(n, colp->GetDeplac() + colp->GetFileSize()); + } // endif !special // We do this for binary table because the lrecl can have been // specified with additional space to include line ending. @@ -156,9 +174,10 @@ bool FIXFAM::AllocateBuffer(PGLOBAL g) } // endif n - // Now repeat this for the whole buffer - for (int len = Lrecl; len <= Buflen - Lrecl; len += Lrecl) - memcpy(To_Buf + len, To_Buf, Lrecl); + if (b) + // Now repeat this for the whole buffer + for (int len = Lrecl; len <= Buflen - Lrecl; len += Lrecl) + memcpy(To_Buf + len, To_Buf, Lrecl); } else { memset(To_Buf, ' ', Buflen); diff --git a/storage/connect/mysql-test/connect/r/bin.result b/storage/connect/mysql-test/connect/r/bin.result index bbf5614b555..69453d97534 100644 --- a/storage/connect/mysql-test/connect/r/bin.result +++ b/storage/connect/mysql-test/connect/r/bin.result @@ -14,11 +14,11 @@ SET time_zone='+00:00'; CREATE TABLE t1 ( fig INT(4) NOT NULL FIELD_FORMAT='C', -name CHAR(10) not null, -birth DATE NOT NULL, -id CHAR(5) NOT NULL FIELD_FORMAT='S', +name CHAR(10) NOT NULL, +birth DATE NOT NULL FIELD_FORMAT='L', +id CHAR(5) NOT NULL FIELD_FORMAT='L2', salary DOUBLE(9,2) NOT NULL DEFAULT 0.00 FIELD_FORMAT='F', -dept INT(4) NOT NULL FIELD_FORMAT='S' +dept INT(4) NOT NULL FIELD_FORMAT='L2' ) ENGINE=CONNECT TABLE_TYPE=BIN BLOCK_SIZE=5 FILE_NAME='Testbal.dat'; SELECT * FROM t1; fig name birth id salary dept @@ -41,11 +41,11 @@ DROP TABLE t1; CREATE TABLE t1 ( fig INT(4) NOT NULL FIELD_FORMAT='C', -name CHAR(10) not null, -birth DATE NOT NULL, -id CHAR(5) NOT NULL FIELD_FORMAT='S', +name CHAR(10) NOT NULL, +birth DATE NOT NULL FIELD_FORMAT='L', +id CHAR(5) NOT NULL FIELD_FORMAT='L2', salary DOUBLE(9,2) NOT NULL DEFAULT 0.00 FIELD_FORMAT='F', -dept INT(4) NOT NULL FIELD_FORMAT='S' +dept INT(4) NOT NULL FIELD_FORMAT='L2' ) ENGINE=CONNECT TABLE_TYPE=BIN READONLY=Yes FILE_NAME='Testbal.dat'; INSERT INTO t1 VALUES (7777,'BILL','1973-06-30',4444,5555.555,777); ERROR HY000: Table 't1' is read only @@ -55,10 +55,10 @@ Table Create Table t1 CREATE TABLE `t1` ( `fig` int(4) NOT NULL `FIELD_FORMAT`='C', `name` char(10) NOT NULL, - `birth` date NOT NULL, - `id` char(5) NOT NULL `FIELD_FORMAT`='S', + `birth` date NOT NULL `FIELD_FORMAT`='L', + `id` char(5) NOT NULL `FIELD_FORMAT`='L2', `salary` double(9,2) NOT NULL DEFAULT '0.00' `FIELD_FORMAT`='F', - `dept` int(4) NOT NULL `FIELD_FORMAT`='S' + `dept` int(4) NOT NULL `FIELD_FORMAT`='L2' ) ENGINE=CONNECT DEFAULT CHARSET=latin1 `TABLE_TYPE`=BIN `FILE_NAME`='Testbal.dat' `READONLY`=NO INSERT INTO t1 VALUES (7777,'BILL','1973-06-30',4444,5555.555,777); SELECT * FROM t1; @@ -74,10 +74,10 @@ Table Create Table t1 CREATE TABLE `t1` ( `fig` int(4) NOT NULL `FIELD_FORMAT`='C', `name` char(10) NOT NULL, - `birth` date NOT NULL, - `id` char(5) NOT NULL `FIELD_FORMAT`='S', + `birth` date NOT NULL `FIELD_FORMAT`='L', + `id` char(5) NOT NULL `FIELD_FORMAT`='L2', `salary` double(9,2) NOT NULL DEFAULT '0.00' `FIELD_FORMAT`='F', - `dept` int(4) NOT NULL `FIELD_FORMAT`='S' + `dept` int(4) NOT NULL `FIELD_FORMAT`='L2' ) ENGINE=CONNECT DEFAULT CHARSET=latin1 `TABLE_TYPE`=BIN `FILE_NAME`='Testbal.dat' `READONLY`=YES INSERT INTO t1 VALUES (7777,'BILL','1973-06-30',4444,5555.555,777); ERROR HY000: Table 't1' is read only diff --git a/storage/connect/mysql-test/connect/t/bin.test b/storage/connect/mysql-test/connect/t/bin.test index 6ef0ffc75ec..e9d1ad58c37 100644 --- a/storage/connect/mysql-test/connect/t/bin.test +++ b/storage/connect/mysql-test/connect/t/bin.test @@ -1,77 +1,77 @@ -let $MYSQLD_DATADIR= `select @@datadir`;
-
---copy_file $MTR_SUITE_DIR/std_data/Testbal.dat $MYSQLD_DATADIR/test/Testbal.dat
-
---echo #
---echo # Testing errors
---echo #
-CREATE TABLE t1
-(
- ID INT NOT NULL
-) Engine=CONNECT TABLE_TYPE=BIN FILE_NAME='nonexistent.txt';
---replace_regex /on .*test.nonexistent.txt/on DATADIR\/test\/nonexistent.txt/
-# TODO: check why this is needed for Windows
---replace_result Open(rt) Open(rb)
-SELECT * FROM t1;
-DROP TABLE t1;
-
-SET time_zone='+00:00';
-CREATE TABLE t1
-(
- fig INT(4) NOT NULL FIELD_FORMAT='C',
- name CHAR(10) not null,
- birth DATE NOT NULL,
- id CHAR(5) NOT NULL FIELD_FORMAT='S',
- salary DOUBLE(9,2) NOT NULL DEFAULT 0.00 FIELD_FORMAT='F',
- dept INT(4) NOT NULL FIELD_FORMAT='S'
-) ENGINE=CONNECT TABLE_TYPE=BIN BLOCK_SIZE=5 FILE_NAME='Testbal.dat';
-SELECT * FROM t1;
-
---error ER_GET_ERRMSG
-INSERT INTO t1 VALUES (55555,'RONALD','1980-02-26','3333',4444.44,555);
-INSERT INTO t1 VALUES (5555,'RONALD','1980-02-26','3333',4444.44,555);
-SELECT * FROM t1;
-
-DROP TABLE t1;
-
---echo #
---echo # Testing READONLY tables
---echo #
-CREATE TABLE t1
-(
- fig INT(4) NOT NULL FIELD_FORMAT='C',
- name CHAR(10) not null,
- birth DATE NOT NULL,
- id CHAR(5) NOT NULL FIELD_FORMAT='S',
- salary DOUBLE(9,2) NOT NULL DEFAULT 0.00 FIELD_FORMAT='F',
- dept INT(4) NOT NULL FIELD_FORMAT='S'
-) ENGINE=CONNECT TABLE_TYPE=BIN READONLY=Yes FILE_NAME='Testbal.dat';
---error ER_OPEN_AS_READONLY
-INSERT INTO t1 VALUES (7777,'BILL','1973-06-30',4444,5555.555,777);
-ALTER TABLE t1 READONLY=NO;
-SHOW CREATE TABLE t1;
-INSERT INTO t1 VALUES (7777,'BILL','1973-06-30',4444,5555.555,777);
-SELECT * FROM t1;
-ALTER TABLE t1 READONLY=YES;
-SHOW CREATE TABLE t1;
---error ER_OPEN_AS_READONLY
-INSERT INTO t1 VALUES (7777,'BILL','1973-06-30',4444,5555.555,777);
-DROP TABLE t1;
-
-
---echo #
---echo # Testing that the underlying file is created
---echo #
-CREATE TABLE t1
-(
- c CHAR(4) NOT NULL FIELD_FORMAT='C'
-) ENGINE=CONNECT TABLE_TYPE=BIN FILE_NAME='bin2.dat';
-INSERT INTO t1 VALUES (10),(20),(300),(4000);
-SELECT * FROM t1;
-DROP TABLE t1;
-
-#
-# Clean up
-#
---remove_file $MYSQLD_DATADIR/test/Testbal.dat
---remove_file $MYSQLD_DATADIR/test/bin2.dat
+let $MYSQLD_DATADIR= `select @@datadir`; + +--copy_file $MTR_SUITE_DIR/std_data/Testbal.dat $MYSQLD_DATADIR/test/Testbal.dat + +--echo # +--echo # Testing errors +--echo # +CREATE TABLE t1 +( + ID INT NOT NULL +) Engine=CONNECT TABLE_TYPE=BIN FILE_NAME='nonexistent.txt'; +--replace_regex /on .*test.nonexistent.txt/on DATADIR\/test\/nonexistent.txt/ +# TODO: check why this is needed for Windows +--replace_result Open(rt) Open(rb) +SELECT * FROM t1; +DROP TABLE t1; + +SET time_zone='+00:00'; +CREATE TABLE t1 +( + fig INT(4) NOT NULL FIELD_FORMAT='C', + name CHAR(10) NOT NULL, + birth DATE NOT NULL FIELD_FORMAT='L', + id CHAR(5) NOT NULL FIELD_FORMAT='L2', + salary DOUBLE(9,2) NOT NULL DEFAULT 0.00 FIELD_FORMAT='F', + dept INT(4) NOT NULL FIELD_FORMAT='L2' +) ENGINE=CONNECT TABLE_TYPE=BIN BLOCK_SIZE=5 FILE_NAME='Testbal.dat'; +SELECT * FROM t1; + +--error ER_GET_ERRMSG +INSERT INTO t1 VALUES (55555,'RONALD','1980-02-26','3333',4444.44,555); +INSERT INTO t1 VALUES (5555,'RONALD','1980-02-26','3333',4444.44,555); +SELECT * FROM t1; + +DROP TABLE t1; + +--echo # +--echo # Testing READONLY tables +--echo # +CREATE TABLE t1 +( + fig INT(4) NOT NULL FIELD_FORMAT='C', + name CHAR(10) NOT NULL, + birth DATE NOT NULL FIELD_FORMAT='L', + id CHAR(5) NOT NULL FIELD_FORMAT='L2', + salary DOUBLE(9,2) NOT NULL DEFAULT 0.00 FIELD_FORMAT='F', + dept INT(4) NOT NULL FIELD_FORMAT='L2' +) ENGINE=CONNECT TABLE_TYPE=BIN READONLY=Yes FILE_NAME='Testbal.dat'; +--error ER_OPEN_AS_READONLY +INSERT INTO t1 VALUES (7777,'BILL','1973-06-30',4444,5555.555,777); +ALTER TABLE t1 READONLY=NO; +SHOW CREATE TABLE t1; +INSERT INTO t1 VALUES (7777,'BILL','1973-06-30',4444,5555.555,777); +SELECT * FROM t1; +ALTER TABLE t1 READONLY=YES; +SHOW CREATE TABLE t1; +--error ER_OPEN_AS_READONLY +INSERT INTO t1 VALUES (7777,'BILL','1973-06-30',4444,5555.555,777); +DROP TABLE t1; + + +--echo # +--echo # Testing that the underlying file is created +--echo # +CREATE TABLE t1 +( + c CHAR(4) NOT NULL FIELD_FORMAT='C' +) ENGINE=CONNECT TABLE_TYPE=BIN FILE_NAME='bin2.dat'; +INSERT INTO t1 VALUES (10),(20),(300),(4000); +SELECT * FROM t1; +DROP TABLE t1; + +# +# Clean up +# +--remove_file $MYSQLD_DATADIR/test/Testbal.dat +--remove_file $MYSQLD_DATADIR/test/bin2.dat diff --git a/storage/connect/reldef.cpp b/storage/connect/reldef.cpp index d0483b5075d..e3cea256227 100644 --- a/storage/connect/reldef.cpp +++ b/storage/connect/reldef.cpp @@ -322,7 +322,7 @@ int TABDEF::GetColCatInfo(PGLOBAL g) if ((nof= cdp->Define(g, NULL, pcf, poff)) < 0) return -1; // Error, probably unhandled type - else if (nof) + else loff= cdp->GetOffset(); switch (tc) { @@ -334,15 +334,23 @@ int TABDEF::GetColCatInfo(PGLOBAL g) // Field width is the internal representation width // that can also depend on the column format switch (cdp->Fmt ? *cdp->Fmt : 'X') { + case 'X': nof= cdp->Clen; case 'C': break; case 'R': case 'F': - case 'L': +// case 'L': case 'I': nof= 4; break; case 'D': nof= 8; break; case 'S': nof= 2; break; case 'T': nof= 1; break; - default: nof= cdp->Clen; + default: /* New format */ + for (nof= 0, i= 0; cdp->Fmt[i]; i++) + if (isdigit(cdp->Fmt[i])) + nof= (nof * 10 + (cdp->Fmt[i] - 48)); + + if (!nof) + nof= cdp->Clen; + } // endswitch Fmt default: @@ -745,7 +753,8 @@ int COLDEF::Define(PGLOBAL g, void *, PCOLINFO cfp, int poff) if (cfp->Datefmt) Decode = (PSZ)PlugDup(g, cfp->Datefmt); - } // endif special + } else + Offset = poff; if (cfp->Fieldfmt) Fmt = (PSZ)PlugDup(g, cfp->Fieldfmt); diff --git a/storage/connect/tabfix.cpp b/storage/connect/tabfix.cpp index 724d8cfde75..65295428d57 100644 --- a/storage/connect/tabfix.cpp +++ b/storage/connect/tabfix.cpp @@ -377,8 +377,8 @@ BINCOL::BINCOL(PGLOBAL g, PCOLDEF cdp, PTDB tp, PCOL cp, int i, PSZ am) char *fmt = cdp->GetFmt(); Buff = NULL; - M = GetTypeSize(Buf_Type, Long); - Lim = M; + M = GetTypeSize(Buf_Type, sizeof(longlong)); + Lim = 0; if (fmt) { Fmt = 'H'; @@ -396,7 +396,7 @@ BINCOL::BINCOL(PGLOBAL g, PCOLDEF cdp, PTDB tp, PCOL cp, int i, PSZ am) } else if (Fmt == 'L' || Fmt == 'B' || Fmt == 'H') { // This is a new format if (!N) - N = GetTypeSize(Buf_Type, 0); + N = GetTypeSize(Buf_Type, Long); if (Fmt == 'H') Fmt = Endian; @@ -440,23 +440,6 @@ void BINCOL::SetEndian(void) } // end of SetEndian /***********************************************************************/ -/* Copy according to Endian settings and sizes. */ -/***********************************************************************/ -void BINCOL::NumCpy(char *from, char *to) - { - for (int i = 0; i < Lim; i++) - if (Fmt == 'B' && Endian == 'L') - to[i] = from[N - i - 1]; - else if (Fmt == 'L' && Endian == 'B') - to[N - i - 1] = from[i]; - else if (Endian == 'B') - to[M - i - 1] = from[N - i - 1]; - else - to[i] = from[i]; - - } // end of NumCpy - -/***********************************************************************/ /* ReadColumn: what this routine does is to access the last line */ /* read from the corresponding table and extract from it the field */ /* corresponding to this column. */ @@ -488,8 +471,21 @@ void BINCOL::ReadColumn(PGLOBAL g) /* Set Value from the line field. */ /*********************************************************************/ if (N) { - NumCpy(p, Buff); - Value->SetBinValue(Buff); + for (int i = 0; i < Lim; i++) + if (Fmt == 'B' && Endian == 'L') + Buff[i] = p[N - i - 1]; + else if (Fmt == 'L' && Endian == 'B') + Buff[M - i - 1] = p[i]; + else if (Endian == 'B') + Buff[M - i - 1] = p[N - i - 1]; + else + Buff[i] = p[i]; + + if (IsTypeChar(Buf_Type)) + Value->SetValue(*(longlong*)Buff); + else + Value->SetBinValue(Buff); + } else switch (Fmt) { case 'X': // Standard not converted values Value->SetBinValue(p); @@ -565,14 +561,24 @@ void BINCOL::WriteColumn(PGLOBAL g) /* Conversion occurs if the external format Fmt is specified. */ /*********************************************************************/ if (N) { - if (Value->GetBinValue(Buff, M, Status)) { + if (IsTypeChar(Buf_Type)) + *(longlong *)Buff = Value->GetBigintValue(); + else if (Value->GetBinValue(Buff, M, Status)) { sprintf(g->Message, MSG(BIN_F_TOO_LONG), Name, Value->GetSize(), M); longjmp(g->jumper[g->jump_level], 31); } // endif Buff if (Status) - NumCpy(Buff, p); + for (int i = 0; i < Lim; i++) + if (Fmt == 'B' && Endian == 'L') + p[N - i - 1] = Buff[i]; + else if (Fmt == 'L' && Endian == 'B') + p[i] = Buff[M - i - 1]; + else if (Endian == 'B') + p[N - i - 1] = Buff[M - i - 1]; + else + p[i] = Buff[i]; } else switch (Fmt) { case 'X': @@ -619,7 +625,7 @@ void BINCOL::WriteColumn(PGLOBAL g) break; case 'B': // Large (big) integer if (Status) - *(longlong *)p = (longlong)Value->GetBigintValue(); + *(longlong *)p = Value->GetBigintValue(); break; case 'F': // Float diff --git a/storage/connect/tabfix.h b/storage/connect/tabfix.h index 2155077f11d..b6307e8f60b 100644 --- a/storage/connect/tabfix.h +++ b/storage/connect/tabfix.h @@ -1,7 +1,7 @@ /*************** TabDos H Declares Source Code File (.H) ***************/ -/* Name: TABFIX.H Version 2.3 */ +/* Name: TABFIX.H Version 2.4 */ /* */ -/* (C) Copyright to the author Olivier BERTRAND 1999-2012 */ +/* (C) Copyright to the author Olivier BERTRAND 1999-2015 */ /* */ /* This file contains the TDBFIX and (FIX/BIN)COL classes declares. */ /***********************************************************************/ @@ -12,7 +12,7 @@ typedef class FIXCOL *PFIXCOL; typedef class BINCOL *PBINCOL; -typedef class TXTFAM *PTXF; +typedef class TXTFAM *PTXF; /***********************************************************************/ /* This is the DOS/UNIX Access Method class declaration for files */ @@ -68,17 +68,19 @@ class DllExport BINCOL : public DOSCOL { BINCOL(BINCOL *colp, PTDB tdbp); // Constructor used in copy process // Implementation - virtual int GetAmType(void) {return TYPE_AM_BIN;} + virtual int GetAmType(void) {return TYPE_AM_BIN;} + int GetDeplac(void) {return Deplac;} + int GetFileSize(void) + {return N ? N : GetTypeSize(Buf_Type, Long);} // Methods - virtual void ReadColumn(PGLOBAL g); - virtual void WriteColumn(PGLOBAL g); + virtual void ReadColumn(PGLOBAL g); + virtual void WriteColumn(PGLOBAL g); // Static - static void SetEndian(void); + static void SetEndian(void); protected: - void NumCpy(char *from, char *to); BINCOL(void) {} // Default constructor not to be used // Members @@ -86,8 +88,8 @@ class DllExport BINCOL : public DOSCOL { char *Buff; // Utility buffer char Fmt; // The file endian setting or old format int N; // The number of bytes in the file - int M; // The column type size - int Lim; // Used in NumCpy + int M; // The buffer type size + int Lim; // Min(N,M) }; // end of class BINCOL /***********************************************************************/ |