Commit e6b60ee5 authored by Olivier Bertrand's avatar Olivier Bertrand

Make BIN table files more flexible with new column format.

In particular enable to set length and endian setting.
This should solve all problems on IBM390s machines.
  modified:   storage/connect/ha_connect.cc
  modified:   storage/connect/tabfix.cpp
  modified:   storage/connect/tabfix.h

Make DBF tables to be usable in big-endian machines (test version)
  modified:   storage/connect/filamdbf.cpp

Ignore git files on storage/connect
  modified:   .gitignore
parent 3810fefc
......@@ -151,6 +151,7 @@ sql/mysqld
sql/sql_builtin.cc
sql/sql_yacc.cc
sql/sql_yacc.h
storage/connect/.*
storage/heap/hp_test1
storage/heap/hp_test2
storage/maria/aria_chk
......
......@@ -74,16 +74,28 @@ typedef struct _dbfheader {
//uchar Dbfox :4; /* FoxPro if equal to 3 */
uchar Version; /* Version information flags */
char Filedate[3]; /* date, YYMMDD, binary. YY=year-1900 */
uint Records; /* records in the file */
ushort Headlen; /* bytes in the header */
ushort Reclen; /* bytes in a record */
ushort Fields; /* Reserved but used to store fields */
private:
/* The following four members are stored in little-endian format on disk */
char m_RecordsBuf[4]; /* records in the file */
char m_HeadlenBuf[2]; /* bytes in the header */
char m_ReclenBuf[2]; /* bytes in a record */
char m_FieldsBuf[2]; /* Reserved but used to store fields */
public:
char Incompleteflag; /* 01 if incomplete, else 00 */
char Encryptflag; /* 01 if encrypted, else 00 */
char Reserved2[12]; /* for LAN use */
char Mdxflag; /* 01 if production .mdx, else 00 */
char Language; /* Codepage */
char Reserved3[2];
uint Records(void) const {return uint4korr(m_RecordsBuf);}
ushort Headlen(void) const {return uint2korr(m_HeadlenBuf);}
ushort Reclen(void) const {return uint2korr(m_ReclenBuf);}
ushort Fields(void) const {return uint2korr(m_FieldsBuf);}
void SetHeadlen(ushort num) {int2store(m_HeadlenBuf, num);}
void SetReclen(ushort num) {int2store(m_ReclenBuf, num);}
void SetFields(ushort num) {int2store(m_FieldsBuf, num);}
} DBFHEADER;
/****************************************************************************/
......@@ -115,7 +127,6 @@ typedef struct _descriptor {
/* Side effects: */
/* Moves file pointer to byte 32; fills buffer at buf with */
/* first 32 bytes of file. */
/* Converts numeric values to platform byte ordering (LE in file) */
/****************************************************************************/
static int dbfhead(PGLOBAL g, FILE *file, PSZ fn, DBFHEADER *buf)
{
......@@ -143,13 +154,8 @@ static int dbfhead(PGLOBAL g, FILE *file, PSZ fn, DBFHEADER *buf)
} else
strcpy(g->Message, MSG(DBASE_FILE));
// Convert numeric fields to have them in platform byte ordering
buf->Records = uint4korr(&buf->Records);
buf->Headlen = uint2korr(&buf->Headlen);
buf->Reclen = uint2korr(&buf->Reclen);
// Check last byte(s) of header
if (fseek(file, buf->Headlen - dbc, SEEK_SET) != 0) {
if (fseek(file, buf->Headlen() - dbc, SEEK_SET) != 0) {
sprintf(g->Message, MSG(BAD_HEADER), fn);
return RC_FX;
} // endif fseek
......@@ -169,7 +175,7 @@ static int dbfhead(PGLOBAL g, FILE *file, PSZ fn, DBFHEADER *buf)
} // endif endmark
// Calculate here the number of fields while we have the dbc info
buf->Fields = (buf->Headlen - dbc - 1) / 32;
buf->SetFields((buf->Headlen() - dbc - 1) / 32);
fseek(file, HEADLEN, SEEK_SET);
return rc;
} // end of dbfhead
......@@ -225,7 +231,7 @@ PQRYRES DBFColumns(PGLOBAL g, char *dp, const char *fn, bool info)
/************************************************************************/
/* Allocate the structures used to refer to the result set. */
/************************************************************************/
fields = mainhead.Fields;
fields = mainhead.Fields();
} else
fields = 0;
......@@ -242,11 +248,11 @@ PQRYRES DBFColumns(PGLOBAL g, char *dp, const char *fn, bool info)
if (trace) {
htrc("Structure of %s\n", filename);
htrc("headlen=%hd reclen=%hd degree=%d\n",
mainhead.Headlen, mainhead.Reclen, fields);
mainhead.Headlen(), mainhead.Reclen(), fields);
htrc("flags(iem)=%d,%d,%d cp=%d\n", mainhead.Incompleteflag,
mainhead.Encryptflag, mainhead.Mdxflag, mainhead.Language);
htrc("%hd records, last changed %02d/%02d/%d\n",
mainhead.Records, mainhead.Filedate[1], mainhead.Filedate[2],
mainhead.Records(), mainhead.Filedate[1], mainhead.Filedate[2],
mainhead.Filedate[0] + (mainhead.Filedate[0] <= 30) ? 2000 : 1900);
htrc("Field Type Offset Len Dec Set Mdx\n");
} // endif trace
......@@ -404,13 +410,13 @@ int DBFBASE::ScanHeader(PGLOBAL g, PSZ fname, int lrecl, char *defpath)
} else if (rc == RC_FX)
return -1;
if ((int)header.Reclen != lrecl) {
sprintf(g->Message, MSG(BAD_LRECL), lrecl, header.Reclen);
if ((int)header.Reclen() != lrecl) {
sprintf(g->Message, MSG(BAD_LRECL), lrecl, header.Reclen());
return -1;
} // endif Lrecl
Records = (int)header.Records;
return (int)header.Headlen;
Records = (int)header.Records();
return (int)header.Headlen();
} // end of ScanHeader
/* ---------------------------- Class DBFFAM ------------------------------ */
......@@ -571,8 +577,8 @@ bool DBFFAM::AllocateBuffer(PGLOBAL g)
header->Filedate[0] = datm->tm_year - 100;
header->Filedate[1] = datm->tm_mon + 1;
header->Filedate[2] = datm->tm_mday;
int2store(&header->Headlen, hlen);
int2store(&header->Reclen, reclen);
header->SetHeadlen((ushort)hlen);
header->SetReclen((ushort)reclen);
descp = (DESCRIPTOR*)header;
// Currently only standard Xbase types are supported
......@@ -633,13 +639,13 @@ bool DBFFAM::AllocateBuffer(PGLOBAL g)
DBFHEADER header;
if ((rc = dbfhead(g, Stream, Tdbp->GetFile(g), &header)) == RC_OK) {
if (Lrecl != (int)header.Reclen) {
sprintf(g->Message, MSG(BAD_LRECL), Lrecl, header.Reclen);
if (Lrecl != (int)header.Reclen()) {
sprintf(g->Message, MSG(BAD_LRECL), Lrecl, header.Reclen());
return true;
} // endif Lrecl
Records = (int)header.Records;
Headlen = (int)header.Headlen;
Records = (int)header.Records();
Headlen = (int)header.Headlen();
} else if (rc == RC_NF) {
Records = 0;
Headlen = 0;
......@@ -869,12 +875,14 @@ void DBFFAM::CloseTableFile(PGLOBAL g, bool abort)
if (n > Records) {
// Update the number of rows in the file header
char filename[_MAX_PATH], nRecords[4];
char filename[_MAX_PATH];
int4store(&nRecords, n);
PlugSetPath(filename, To_File, Tdbp->GetPath());
if ((Stream= global_fopen(g, MSGID_OPEN_MODE_STRERROR, filename, "r+b")))
{
char nRecords[4];
int4store(nRecords, n);
fseek(Stream, 4, SEEK_SET); // Get header.Records position
fwrite(nRecords, sizeof(nRecords), 1, Stream);
fclose(Stream);
......@@ -951,13 +959,13 @@ bool DBMFAM::AllocateBuffer(PGLOBAL g)
/************************************************************************/
DBFHEADER *hp = (DBFHEADER*)Memory;
if (Lrecl != (int)uint2korr(&hp->Reclen)) {
sprintf(g->Message, MSG(BAD_LRECL), Lrecl, uint2korr(&hp->Reclen));
if (Lrecl != (int)hp->Reclen()) {
sprintf(g->Message, MSG(BAD_LRECL), Lrecl, hp->Reclen());
return true;
} // endif Lrecl
Records = (int)uint4korr(&hp->Records);
Headlen = (int)uint2korr(&hp->Headlen);
Records = (int)hp->Records();
Headlen = (int)hp->Headlen();
} // endif Headlen
/**************************************************************************/
......@@ -1011,7 +1019,7 @@ int DBMFAM::ReadBuffer(PGLOBAL g)
/* Data Base delete line routine for DBF access methods. */
/* Deleted lines are just flagged in the first buffer character. */
/****************************************************************************/
int DBMFAM::DeleteRecords(PGLOBAL, int irc)
int DBMFAM::DeleteRecords(PGLOBAL g, int irc)
{
if (irc == RC_OK)
*Fpos = '*';
......
......@@ -153,6 +153,7 @@
#endif // LIBXML2_SUPPORT
#include "taboccur.h"
#include "tabpivot.h"
#include "tabfix.h"
#define my_strupr(p) my_caseup_str(default_charset_info, (p));
#define my_strlwr(p) my_casedn_str(default_charset_info, (p));
......@@ -656,6 +657,7 @@ static int connect_init_func(void *p)
sql_print_information("connect_init: hton=%p", p);
DTVAL::SetTimeShift(); // Initialize time zone shift once for all
BINCOL::SetEndian(); // Initialize host endian setting
DBUG_RETURN(0);
} // end of connect_init_func
......
......@@ -54,6 +54,7 @@
extern int num_read, num_there, num_eq[2]; // Statistics
static const longlong M2G = 0x80000000;
static const longlong M4G = (longlong)2 * M2G;
char BINCOL::Endian = 'H';
/***********************************************************************/
/* External function. */
......@@ -373,18 +374,88 @@ int TDBFIX::WriteDB(PGLOBAL g)
BINCOL::BINCOL(PGLOBAL g, PCOLDEF cdp, PTDB tp, PCOL cp, int i, PSZ am)
: DOSCOL(g, cdp, tp, cp, i, am)
{
Fmt = (cdp->GetFmt()) ? toupper(*cdp->GetFmt()) : 'X';
char *fmt = cdp->GetFmt();
Buff = NULL;
M = GetTypeSize(Buf_Type, Long);
Lim = M;
if (fmt) {
Fmt = 'H';
for (N = 0, i = 0; fmt[i]; i++)
if (isdigit(fmt[i]))
N = (N * 10 + (fmt[i] - 48));
else
Fmt = toupper(fmt[i]);
if (N == GetTypeSize(Buf_Type, -1) && (Fmt == 'H' || Fmt == Endian)) {
// New format is a no op
N = 0;
Fmt = 'X';
} else if (Fmt == 'L' || Fmt == 'B' || Fmt == 'H') {
// This is a new format
if (!N)
N = GetTypeSize(Buf_Type, 0);
if (Fmt == 'H')
Fmt = Endian;
Buff = (char*)PlugSubAlloc(g, NULL, M);
memset(Buff, 0, M);
Lim = MY_MIN(N, M);
} // endif Fmt
} else {
N = 0;
Fmt = 'X';
} // endif fmt
} // end of BINCOL constructor
/***********************************************************************/
/* FIXCOL constructor used for copying columns. */
/* BINCOL constructor used for copying columns. */
/* tdbp is the pointer to the new table descriptor. */
/***********************************************************************/
BINCOL::BINCOL(BINCOL *col1, PTDB tdbp) : DOSCOL(col1, tdbp)
{
Fmt = col1->Fmt;
N = col1->N;
M = col1->M;
Lim = col1->Lim;
} // end of BINCOL copy constructor
/***********************************************************************/
/* Set Endian according to the host setting. */
/***********************************************************************/
void BINCOL::SetEndian(void)
{
union {
short S;
char C[sizeof(short)];
};
S = 1;
Endian = (C[0] == 1) ? 'L' : 'B';
} // 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 */
......@@ -416,19 +487,22 @@ void BINCOL::ReadColumn(PGLOBAL g)
/*********************************************************************/
/* Set Value from the line field. */
/*********************************************************************/
switch (Fmt) {
if (N) {
NumCpy(p, Buff);
Value->SetBinValue(Buff);
} else switch (Fmt) {
case 'X': // Standard not converted values
Value->SetBinValue(p);
break;
case 'S': // Short integer
Value->SetValue((int)*(short*)p);
Value->SetValue(*(short*)p);
break;
case 'T': // Tiny integer
Value->SetValue((int)*p);
Value->SetValue(*p);
break;
case 'L': // Long Integer
strcpy(g->Message, "Format L is deprecated, use I");
longjmp(g->jumper[g->jump_level], 11);
// case 'L': // Long Integer
// strcpy(g->Message, "Format L is deprecated, use I");
// longjmp(g->jumper[g->jump_level], 11);
case 'I': // Integer
Value->SetValue(*(int*)p);
break;
......@@ -490,14 +564,24 @@ void BINCOL::WriteColumn(PGLOBAL g)
/* Updating will be done only during the second pass (Status=true) */
/* Conversion occurs if the external format Fmt is specified. */
/*********************************************************************/
switch (Fmt) {
if (N) {
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);
} else switch (Fmt) {
case 'X':
// Standard not converted values
if (Value->GetBinValue(p, Long, Status)) {
sprintf(g->Message, MSG(BIN_F_TOO_LONG),
Name, Value->GetSize(), Long);
longjmp(g->jumper[g->jump_level], 31);
} // endif Fmt
} // endif p
break;
case 'S': // Short integer
......
......@@ -74,11 +74,20 @@ class DllExport BINCOL : public DOSCOL {
virtual void ReadColumn(PGLOBAL g);
virtual void WriteColumn(PGLOBAL g);
// Static
static void SetEndian(void);
protected:
void NumCpy(char *from, char *to);
BINCOL(void) {} // Default constructor not to be used
// Members
char Fmt; // The column numeric format
static char Endian; // The host endian setting (L or B)
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
}; // 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