diff options
author | Olivier Bertrand <bertrandop@gmail.com> | 2015-05-13 19:58:21 +0200 |
---|---|---|
committer | Olivier Bertrand <bertrandop@gmail.com> | 2015-05-13 19:58:21 +0200 |
commit | e6b60ee5af76a574a9c87733143e608a2bc648bb (patch) | |
tree | 0a1644fa7112ab32e447fba28ae97a5a1735489e | |
parent | 3810fefc65dfaecfac0b0f4c2210126b1e0bc8fa (diff) | |
download | mariadb-git-e6b60ee5af76a574a9c87733143e608a2bc648bb.tar.gz |
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
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | storage/connect/filamdbf.cpp | 74 | ||||
-rw-r--r-- | storage/connect/ha_connect.cc | 2 | ||||
-rw-r--r-- | storage/connect/tabfix.cpp | 104 | ||||
-rw-r--r-- | storage/connect/tabfix.h | 11 |
5 files changed, 148 insertions, 44 deletions
diff --git a/.gitignore b/.gitignore index 85d68f2853d..d7264cb8e60 100644 --- a/.gitignore +++ b/.gitignore @@ -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 diff --git a/storage/connect/filamdbf.cpp b/storage/connect/filamdbf.cpp index 8a88b743a15..4d66c2ab2ff 100644 --- a/storage/connect/filamdbf.cpp +++ b/storage/connect/filamdbf.cpp @@ -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; @@ -735,7 +741,7 @@ bool DBFFAM::CopyHeader(PGLOBAL g) if (Headlen) { void *hdr = PlugSubAlloc(g, NULL, Headlen); size_t n, hlen = (size_t)Headlen; - int pos = ftell(Stream); + int pos = ftell(Stream); if (fseek(Stream, 0, SEEK_SET)) strcpy(g->Message, "Seek error in CopyHeader"); @@ -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 = '*'; diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc index 72f48d72bb1..964185b1b27 100644 --- a/storage/connect/ha_connect.cc +++ b/storage/connect/ha_connect.cc @@ -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 diff --git a/storage/connect/tabfix.cpp b/storage/connect/tabfix.cpp index 5cfd5a726ef..724d8cfde75 100644 --- a/storage/connect/tabfix.cpp +++ b/storage/connect/tabfix.cpp @@ -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,19 +374,89 @@ 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 */ /* corresponding to this column. */ @@ -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 diff --git a/storage/connect/tabfix.h b/storage/connect/tabfix.h index 7d5b964da2a..2155077f11d 100644 --- a/storage/connect/tabfix.h +++ b/storage/connect/tabfix.h @@ -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 /***********************************************************************/ |