Commit b9c91090 authored by Olivier Bertrand's avatar Olivier Bertrand

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
parent e6b60ee5
...@@ -46,6 +46,7 @@ ...@@ -46,6 +46,7 @@
#include "plgdbsem.h" #include "plgdbsem.h"
#include "filamfix.h" #include "filamfix.h"
#include "tabdos.h" #include "tabdos.h"
#include "tabfix.h"
#include "osutil.h" #include "osutil.h"
#ifndef INVALID_SET_FILE_POINTER #ifndef INVALID_SET_FILE_POINTER
...@@ -133,18 +134,35 @@ bool FIXFAM::AllocateBuffer(PGLOBAL g) ...@@ -133,18 +134,35 @@ bool FIXFAM::AllocateBuffer(PGLOBAL g)
if (Tdbp->GetFtype() == RECFM_BIN) { if (Tdbp->GetFtype() == RECFM_BIN) {
// The buffer must be prepared depending on column types // The buffer must be prepared depending on column types
int n = 0; int n = 0;
bool b = false;
PDOSDEF defp = (PDOSDEF)Tdbp->GetDef(); PDOSDEF defp = (PDOSDEF)Tdbp->GetDef();
PCOLDEF cdp; // PCOLDEF cdp;
PBINCOL colp;
// Prepare the first line of the buffer // Prepare the first line of the buffer
memset(To_Buf, 0, Buflen); memset(To_Buf, 0, Buflen);
#if 0
for (cdp = defp->GetCols(); cdp; cdp = cdp->GetNext()) { for (cdp = defp->GetCols(); cdp; cdp = cdp->GetNext()) {
if (IsTypeNum(cdp->GetType())) if (!IsTypeNum(cdp->GetType())) {
memset(To_Buf + cdp->GetOffset(), ' ', cdp->GetClen()); 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 } // 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 // We do this for binary table because the lrecl can have been
// specified with additional space to include line ending. // specified with additional space to include line ending.
...@@ -156,6 +174,7 @@ bool FIXFAM::AllocateBuffer(PGLOBAL g) ...@@ -156,6 +174,7 @@ bool FIXFAM::AllocateBuffer(PGLOBAL g)
} // endif n } // endif n
if (b)
// Now repeat this for the whole buffer // Now repeat this for the whole buffer
for (int len = Lrecl; len <= Buflen - Lrecl; len += Lrecl) for (int len = Lrecl; len <= Buflen - Lrecl; len += Lrecl)
memcpy(To_Buf + len, To_Buf, Lrecl); memcpy(To_Buf + len, To_Buf, Lrecl);
......
...@@ -14,11 +14,11 @@ SET time_zone='+00:00'; ...@@ -14,11 +14,11 @@ SET time_zone='+00:00';
CREATE TABLE t1 CREATE TABLE t1
( (
fig INT(4) NOT NULL FIELD_FORMAT='C', fig INT(4) NOT NULL FIELD_FORMAT='C',
name CHAR(10) not null, name CHAR(10) NOT NULL,
birth DATE NOT NULL, birth DATE NOT NULL FIELD_FORMAT='L',
id CHAR(5) NOT NULL FIELD_FORMAT='S', id CHAR(5) NOT NULL FIELD_FORMAT='L2',
salary DOUBLE(9,2) NOT NULL DEFAULT 0.00 FIELD_FORMAT='F', 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'; ) ENGINE=CONNECT TABLE_TYPE=BIN BLOCK_SIZE=5 FILE_NAME='Testbal.dat';
SELECT * FROM t1; SELECT * FROM t1;
fig name birth id salary dept fig name birth id salary dept
...@@ -41,11 +41,11 @@ DROP TABLE t1; ...@@ -41,11 +41,11 @@ DROP TABLE t1;
CREATE TABLE t1 CREATE TABLE t1
( (
fig INT(4) NOT NULL FIELD_FORMAT='C', fig INT(4) NOT NULL FIELD_FORMAT='C',
name CHAR(10) not null, name CHAR(10) NOT NULL,
birth DATE NOT NULL, birth DATE NOT NULL FIELD_FORMAT='L',
id CHAR(5) NOT NULL FIELD_FORMAT='S', id CHAR(5) NOT NULL FIELD_FORMAT='L2',
salary DOUBLE(9,2) NOT NULL DEFAULT 0.00 FIELD_FORMAT='F', 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'; ) ENGINE=CONNECT TABLE_TYPE=BIN READONLY=Yes FILE_NAME='Testbal.dat';
INSERT INTO t1 VALUES (7777,'BILL','1973-06-30',4444,5555.555,777); INSERT INTO t1 VALUES (7777,'BILL','1973-06-30',4444,5555.555,777);
ERROR HY000: Table 't1' is read only ERROR HY000: Table 't1' is read only
...@@ -55,10 +55,10 @@ Table Create Table ...@@ -55,10 +55,10 @@ Table Create Table
t1 CREATE TABLE `t1` ( t1 CREATE TABLE `t1` (
`fig` int(4) NOT NULL `FIELD_FORMAT`='C', `fig` int(4) NOT NULL `FIELD_FORMAT`='C',
`name` char(10) NOT NULL, `name` char(10) NOT NULL,
`birth` date NOT NULL, `birth` date NOT NULL `FIELD_FORMAT`='L',
`id` char(5) NOT NULL `FIELD_FORMAT`='S', `id` char(5) NOT NULL `FIELD_FORMAT`='L2',
`salary` double(9,2) NOT NULL DEFAULT '0.00' `FIELD_FORMAT`='F', `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 ) 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); INSERT INTO t1 VALUES (7777,'BILL','1973-06-30',4444,5555.555,777);
SELECT * FROM t1; SELECT * FROM t1;
...@@ -74,10 +74,10 @@ Table Create Table ...@@ -74,10 +74,10 @@ Table Create Table
t1 CREATE TABLE `t1` ( t1 CREATE TABLE `t1` (
`fig` int(4) NOT NULL `FIELD_FORMAT`='C', `fig` int(4) NOT NULL `FIELD_FORMAT`='C',
`name` char(10) NOT NULL, `name` char(10) NOT NULL,
`birth` date NOT NULL, `birth` date NOT NULL `FIELD_FORMAT`='L',
`id` char(5) NOT NULL `FIELD_FORMAT`='S', `id` char(5) NOT NULL `FIELD_FORMAT`='L2',
`salary` double(9,2) NOT NULL DEFAULT '0.00' `FIELD_FORMAT`='F', `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 ) 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); INSERT INTO t1 VALUES (7777,'BILL','1973-06-30',4444,5555.555,777);
ERROR HY000: Table 't1' is read only ERROR HY000: Table 't1' is read only
......
...@@ -19,11 +19,11 @@ SET time_zone='+00:00'; ...@@ -19,11 +19,11 @@ SET time_zone='+00:00';
CREATE TABLE t1 CREATE TABLE t1
( (
fig INT(4) NOT NULL FIELD_FORMAT='C', fig INT(4) NOT NULL FIELD_FORMAT='C',
name CHAR(10) not null, name CHAR(10) NOT NULL,
birth DATE NOT NULL, birth DATE NOT NULL FIELD_FORMAT='L',
id CHAR(5) NOT NULL FIELD_FORMAT='S', id CHAR(5) NOT NULL FIELD_FORMAT='L2',
salary DOUBLE(9,2) NOT NULL DEFAULT 0.00 FIELD_FORMAT='F', 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'; ) ENGINE=CONNECT TABLE_TYPE=BIN BLOCK_SIZE=5 FILE_NAME='Testbal.dat';
SELECT * FROM t1; SELECT * FROM t1;
...@@ -40,11 +40,11 @@ DROP TABLE t1; ...@@ -40,11 +40,11 @@ DROP TABLE t1;
CREATE TABLE t1 CREATE TABLE t1
( (
fig INT(4) NOT NULL FIELD_FORMAT='C', fig INT(4) NOT NULL FIELD_FORMAT='C',
name CHAR(10) not null, name CHAR(10) NOT NULL,
birth DATE NOT NULL, birth DATE NOT NULL FIELD_FORMAT='L',
id CHAR(5) NOT NULL FIELD_FORMAT='S', id CHAR(5) NOT NULL FIELD_FORMAT='L2',
salary DOUBLE(9,2) NOT NULL DEFAULT 0.00 FIELD_FORMAT='F', 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'; ) ENGINE=CONNECT TABLE_TYPE=BIN READONLY=Yes FILE_NAME='Testbal.dat';
--error ER_OPEN_AS_READONLY --error ER_OPEN_AS_READONLY
INSERT INTO t1 VALUES (7777,'BILL','1973-06-30',4444,5555.555,777); INSERT INTO t1 VALUES (7777,'BILL','1973-06-30',4444,5555.555,777);
......
...@@ -322,7 +322,7 @@ int TABDEF::GetColCatInfo(PGLOBAL g) ...@@ -322,7 +322,7 @@ int TABDEF::GetColCatInfo(PGLOBAL g)
if ((nof= cdp->Define(g, NULL, pcf, poff)) < 0) if ((nof= cdp->Define(g, NULL, pcf, poff)) < 0)
return -1; // Error, probably unhandled type return -1; // Error, probably unhandled type
else if (nof) else
loff= cdp->GetOffset(); loff= cdp->GetOffset();
switch (tc) { switch (tc) {
...@@ -334,15 +334,23 @@ int TABDEF::GetColCatInfo(PGLOBAL g) ...@@ -334,15 +334,23 @@ int TABDEF::GetColCatInfo(PGLOBAL g)
// Field width is the internal representation width // Field width is the internal representation width
// that can also depend on the column format // that can also depend on the column format
switch (cdp->Fmt ? *cdp->Fmt : 'X') { switch (cdp->Fmt ? *cdp->Fmt : 'X') {
case 'X': nof= cdp->Clen;
case 'C': break; case 'C': break;
case 'R': case 'R':
case 'F': case 'F':
case 'L': // case 'L':
case 'I': nof= 4; break; case 'I': nof= 4; break;
case 'D': nof= 8; break; case 'D': nof= 8; break;
case 'S': nof= 2; break; case 'S': nof= 2; break;
case 'T': nof= 1; 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 } // endswitch Fmt
default: default:
...@@ -745,7 +753,8 @@ int COLDEF::Define(PGLOBAL g, void *, PCOLINFO cfp, int poff) ...@@ -745,7 +753,8 @@ int COLDEF::Define(PGLOBAL g, void *, PCOLINFO cfp, int poff)
if (cfp->Datefmt) if (cfp->Datefmt)
Decode = (PSZ)PlugDup(g, cfp->Datefmt); Decode = (PSZ)PlugDup(g, cfp->Datefmt);
} // endif special } else
Offset = poff;
if (cfp->Fieldfmt) if (cfp->Fieldfmt)
Fmt = (PSZ)PlugDup(g, cfp->Fieldfmt); Fmt = (PSZ)PlugDup(g, cfp->Fieldfmt);
......
...@@ -377,8 +377,8 @@ BINCOL::BINCOL(PGLOBAL g, PCOLDEF cdp, PTDB tp, PCOL cp, int i, PSZ am) ...@@ -377,8 +377,8 @@ BINCOL::BINCOL(PGLOBAL g, PCOLDEF cdp, PTDB tp, PCOL cp, int i, PSZ am)
char *fmt = cdp->GetFmt(); char *fmt = cdp->GetFmt();
Buff = NULL; Buff = NULL;
M = GetTypeSize(Buf_Type, Long); M = GetTypeSize(Buf_Type, sizeof(longlong));
Lim = M; Lim = 0;
if (fmt) { if (fmt) {
Fmt = 'H'; Fmt = 'H';
...@@ -396,7 +396,7 @@ BINCOL::BINCOL(PGLOBAL g, PCOLDEF cdp, PTDB tp, PCOL cp, int i, PSZ am) ...@@ -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') { } else if (Fmt == 'L' || Fmt == 'B' || Fmt == 'H') {
// This is a new format // This is a new format
if (!N) if (!N)
N = GetTypeSize(Buf_Type, 0); N = GetTypeSize(Buf_Type, Long);
if (Fmt == 'H') if (Fmt == 'H')
Fmt = Endian; Fmt = Endian;
...@@ -439,23 +439,6 @@ void BINCOL::SetEndian(void) ...@@ -439,23 +439,6 @@ void BINCOL::SetEndian(void)
Endian = (C[0] == 1) ? 'L' : 'B'; Endian = (C[0] == 1) ? 'L' : 'B';
} // end of SetEndian } // 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 */ /* ReadColumn: what this routine does is to access the last line */
/* read from the corresponding table and extract from it the field */ /* read from the corresponding table and extract from it the field */
...@@ -488,8 +471,21 @@ void BINCOL::ReadColumn(PGLOBAL g) ...@@ -488,8 +471,21 @@ void BINCOL::ReadColumn(PGLOBAL g)
/* Set Value from the line field. */ /* Set Value from the line field. */
/*********************************************************************/ /*********************************************************************/
if (N) { if (N) {
NumCpy(p, 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); Value->SetBinValue(Buff);
} else switch (Fmt) { } else switch (Fmt) {
case 'X': // Standard not converted values case 'X': // Standard not converted values
Value->SetBinValue(p); Value->SetBinValue(p);
...@@ -565,14 +561,24 @@ void BINCOL::WriteColumn(PGLOBAL g) ...@@ -565,14 +561,24 @@ void BINCOL::WriteColumn(PGLOBAL g)
/* Conversion occurs if the external format Fmt is specified. */ /* Conversion occurs if the external format Fmt is specified. */
/*********************************************************************/ /*********************************************************************/
if (N) { 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), sprintf(g->Message, MSG(BIN_F_TOO_LONG),
Name, Value->GetSize(), M); Name, Value->GetSize(), M);
longjmp(g->jumper[g->jump_level], 31); longjmp(g->jumper[g->jump_level], 31);
} // endif Buff } // endif Buff
if (Status) 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) { } else switch (Fmt) {
case 'X': case 'X':
...@@ -619,7 +625,7 @@ void BINCOL::WriteColumn(PGLOBAL g) ...@@ -619,7 +625,7 @@ void BINCOL::WriteColumn(PGLOBAL g)
break; break;
case 'B': // Large (big) integer case 'B': // Large (big) integer
if (Status) if (Status)
*(longlong *)p = (longlong)Value->GetBigintValue(); *(longlong *)p = Value->GetBigintValue();
break; break;
case 'F': // Float case 'F': // Float
......
/*************** TabDos H Declares Source Code File (.H) ***************/ /*************** 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. */ /* This file contains the TDBFIX and (FIX/BIN)COL classes declares. */
/***********************************************************************/ /***********************************************************************/
...@@ -69,6 +69,9 @@ class DllExport BINCOL : public DOSCOL { ...@@ -69,6 +69,9 @@ class DllExport BINCOL : public DOSCOL {
// Implementation // 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 // Methods
virtual void ReadColumn(PGLOBAL g); virtual void ReadColumn(PGLOBAL g);
...@@ -78,7 +81,6 @@ class DllExport BINCOL : public DOSCOL { ...@@ -78,7 +81,6 @@ class DllExport BINCOL : public DOSCOL {
static void SetEndian(void); static void SetEndian(void);
protected: protected:
void NumCpy(char *from, char *to);
BINCOL(void) {} // Default constructor not to be used BINCOL(void) {} // Default constructor not to be used
// Members // Members
...@@ -86,8 +88,8 @@ class DllExport BINCOL : public DOSCOL { ...@@ -86,8 +88,8 @@ class DllExport BINCOL : public DOSCOL {
char *Buff; // Utility buffer char *Buff; // Utility buffer
char Fmt; // The file endian setting or old format char Fmt; // The file endian setting or old format
int N; // The number of bytes in the file int N; // The number of bytes in the file
int M; // The column type size int M; // The buffer type size
int Lim; // Used in NumCpy int Lim; // Min(N,M)
}; // end of class BINCOL }; // end of class BINCOL
/***********************************************************************/ /***********************************************************************/
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment