summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOlivier Bertrand <bertrandop@gmail.com>2015-05-15 11:56:29 +0200
committerOlivier Bertrand <bertrandop@gmail.com>2015-05-15 11:56:29 +0200
commitb9c910909c3e04ceab8d0d514ba6213015787c5a (patch)
treefb8ee71de177393751c22f07efb5ccdb9ebdfa04
parente6b60ee5af76a574a9c87733143e608a2bc648bb (diff)
downloadmariadb-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
-rw-r--r--storage/connect/filamfix.cpp33
-rw-r--r--storage/connect/mysql-test/connect/r/bin.result28
-rw-r--r--storage/connect/mysql-test/connect/t/bin.test154
-rw-r--r--storage/connect/reldef.cpp17
-rw-r--r--storage/connect/tabfix.cpp56
-rw-r--r--storage/connect/tabfix.h22
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
/***********************************************************************/