1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-08 11:22:35 +03:00

Adding an Olivier's changeset:

pre_create function and one is now able to create table
without giving the column specifications for tables of types:
DBF, ODBC, MYSQL, CSV, and WMI (on Windows)

modified:
  sql/handler.h
  sql/sql_table.cc
  storage/connect/ha_connect.cc
  storage/connect/ha_connect.h
  storage/connect/mycat.cc
  storage/connect/odbconn.cpp
  storage/connect/plgcnx.h
  storage/connect/tabfmt.cpp
  storage/connect/tabmysql.cpp
  storage/connect/tabwmi.cpp
This commit is contained in:
Alexander Barkov
2013-01-22 18:14:34 +04:00
parent 2e175a4652
commit 37465ea2fe
10 changed files with 1027 additions and 225 deletions

View File

@@ -1,11 +1,11 @@
/************* TabFmt C++ Program Source Code File (.CPP) **************/
/* PROGRAM NAME: TABFMT */
/* ------------- */
/* Version 3.6 */
/* Version 3.7 */
/* */
/* COPYRIGHT: */
/* ---------- */
/* (C) Copyright to the author Olivier BERTRAND 2001 - 2012 */
/* (C) Copyright to the author Olivier BERTRAND 2001 - 2013 */
/* */
/* WHAT THIS PROGRAM DOES: */
/* ----------------------- */
@@ -74,6 +74,300 @@ extern "C" int trace;
PQRYRES PlgAllocResult(PGLOBAL, int, int, int, int *, int *,
unsigned int *, bool blank = true, bool nonull = false);
/***********************************************************************/
/* CSVColumns: constructs the result blocks containing the description */
/* of all the columns of a CSV file that will be retrieved by #GetData.*/
/* Note: the algorithm to set the type is based on the internal values */
/* of types (TYPE_STRING < TYPE_FLOAT < TYPE_INT) (1 < 2 < 7). */
/* If these values are changed, this will have to be revisited. */
/***********************************************************************/
PQRYRES CSVColumns(PGLOBAL g, char *fn, char sep, char q, int hdr, int mxr)
{
static int dbtype[] = {DB_CHAR, DB_SHORT, DB_CHAR,
DB_INT, DB_INT, DB_SHORT};
static int buftyp[] = {TYPE_STRING, TYPE_SHORT, TYPE_STRING,
TYPE_INT, TYPE_INT, TYPE_SHORT};
static unsigned int length[] = {6, 6, 8, 10, 10, 6};
char *p, *colname[MAXCOL], dechar, filename[_MAX_PATH], buf[4096];
int i, imax, hmax, n, nerr, phase, blank, digit, dec, type;
int ncol = sizeof(dbtype) / sizeof(int);
int num_read = 0, num_max = 10000000; // Statistics
int len[MAXCOL], typ[MAXCOL], prc[MAXCOL];
FILE *infile;
PQRYRES qrp;
PCOLRES crp;
// num_max = atoi(p+1); // Max num of record to test
#if defined(WIN32)
if (strnicmp(setlocale(LC_NUMERIC, NULL), "French", 6))
dechar = '.';
else
dechar = ',';
#else // !WIN32
dechar = '.';
#endif // !WIN32
if (trace)
htrc("File %s sep=%c q=%c hdr=%d mxr=%d\n",
SVP(fn), sep, q, hdr, mxr);
if (!fn) {
strcpy(g->Message, MSG(MISSING_FNAME));
return NULL;
} // endif fn
imax = hmax = nerr = 0;
mxr = max(0, mxr);
for (i = 0; i < MAXCOL; i++) {
colname[i] = NULL;
len[i] = 0;
typ[i] = TYPE_UNKNOWN;
prc[i] = 0;
} // endfor i
/*********************************************************************/
/* Open the input file. */
/*********************************************************************/
PlugSetPath(filename, fn, PlgGetDataPath(g));
if (!(infile = fopen(filename, "r"))) {
sprintf(g->Message, MSG(CANNOT_OPEN), filename);
return NULL;
} // endif infile
if (hdr) {
/*******************************************************************/
/* Make the column names from the first line. */
/*******************************************************************/
phase = 0;
if (fgets(buf, sizeof(buf), infile)) {
n = strlen(buf) + 1;
buf[n - 2] = '\0';
p = (char*)PlugSubAlloc(g, NULL, n);
memcpy(p, buf, n);
//skip leading blanks
for (; *p == ' '; p++) ;
if (q && *p == q) {
// Header is quoted
p++;
phase = 1;
} // endif q
colname[0] = p;
} else {
sprintf(g->Message, MSG(FILE_IS_EMPTY), fn);
goto err;
} // endif's
for (i = 1; *p; p++)
if (phase == 1 && *p == q) {
*p = '\0';
phase = 0;
} else if (*p == sep && !phase) {
*p = '\0';
//skip leading blanks
for (; *(p+1) == ' '; p++) ;
if (q && *(p+1) == q) {
// Header is quoted
p++;
phase = 1;
} // endif q
colname[i++] = p + 1;
} // endif sep
num_read++;
imax = hmax = i;
for (i = 0; i < hmax; i++)
length[0] = max(length[0], strlen(colname[i]));
} // endif hdr
for (num_read++; num_read <= num_max; num_read++) {
/*******************************************************************/
/* Now start the reading process. Read one line. */
/*******************************************************************/
if (fgets(buf, sizeof(buf), infile)) {
buf[strlen(buf) - 1] = '\0';
} else if (feof(infile)) {
sprintf(g->Message, MSG(EOF_AFTER_LINE), num_read -1);
break;
} else {
sprintf(g->Message, MSG(ERR_READING_REC), num_read, fn);
goto err;
} // endif's
/*******************************************************************/
/* Make the test for field lengths. */
/*******************************************************************/
i = n = phase = blank = digit = dec = 0;
for (p = buf; *p; p++)
if (*p == sep) {
if (phase != 1) {
if (i == MAXCOL - 1) {
sprintf(g->Message, MSG(TOO_MANY_FIELDS), num_read, fn);
goto err;
} // endif i
if (n) {
len[i] = max(len[i], n);
type = (digit || (dec && n == 1)) ? TYPE_STRING
: (dec) ? TYPE_FLOAT : TYPE_INT;
typ[i] = min(type, typ[i]);
prc[i] = max((typ[i] == TYPE_FLOAT) ? (dec - 1) : 0, prc[i]);
} // endif n
i++;
n = phase = blank = digit = dec = 0;
} else // phase == 1
n++;
} else if (*p == ' ') {
if (phase < 2)
n++;
if (blank)
digit = 1;
} else if (*p == q) {
if (phase == 0) {
if (blank)
if (++nerr > mxr) {
sprintf(g->Message, MSG(MISPLACED_QUOTE), num_read);
goto err;
} else
goto skip;
n = 0;
phase = digit = 1;
} else if (phase == 1) {
if (*(p+1) == q) {
// This is currently not implemented for CSV tables
// if (++nerr > mxr) {
// sprintf(g->Message, MSG(QUOTE_IN_QUOTE), num_read);
// goto err;
// } else
// goto skip;
p++;
n++;
} else
phase = 2;
} else if (++nerr > mxr) { // phase == 2
sprintf(g->Message, MSG(MISPLACED_QUOTE), num_read);
goto err;
} else
goto skip;
} else {
if (phase == 2)
if (++nerr > mxr) {
sprintf(g->Message, MSG(MISPLACED_QUOTE), num_read);
goto err;
} else
goto skip;
// isdigit cannot be used here because of debug assert
if (!strchr("0123456789", *p)) {
if (!digit && *p == dechar)
dec = 1; // Decimal point found
else if (blank || !(*p == '-' || *p == '+'))
digit = 1;
} else if (dec)
dec++; // More decimals
n++;
blank = 1;
} // endif's *p
if (phase == 1)
if (++nerr > mxr) {
sprintf(g->Message, MSG(UNBALANCE_QUOTE), num_read);
goto err;
} else
goto skip;
if (n) {
len[i] = max(len[i], n);
type = (digit || n == 0 || (dec && n == 1)) ? TYPE_STRING
: (dec) ? TYPE_FLOAT : TYPE_INT;
typ[i] = min(type, typ[i]);
prc[i] = max((typ[i] == TYPE_FLOAT) ? (dec - 1) : 0, prc[i]);
} // endif n
imax = max(imax, i+1);
skip: ; // Skip erroneous line
} // endfor num_read
if (trace) {
htrc("imax=%d Lengths:", imax);
for (i = 0; i < imax; i++)
htrc(" %d", len[i]);
htrc("\n");
} // endif trace
fclose(infile);
if (trace)
htrc("CSVColumns: imax=%d hmax=%d len=%d\n",
imax, hmax, length[0]);
/*********************************************************************/
/* Allocate the structures used to refer to the result set. */
/*********************************************************************/
qrp = PlgAllocResult(g, ncol, imax, IDS_COLUMNS + 3,
dbtype, buftyp, length);
qrp->Nblin = imax;
/*********************************************************************/
/* Now get the results into blocks. */
/*********************************************************************/
for (i = 0; i < imax; i++) {
if (i >= hmax) {
sprintf(buf, "COL%.3d", i+1);
p = buf;
} else
p = colname[i];
if (typ[i] == TYPE_UNKNOWN) // Void column
typ[i] = TYPE_STRING;
crp = qrp->Colresp; // Column Name
crp->Kdata->SetValue(p, i);
crp = crp->Next; // Data Type
crp->Kdata->SetValue(typ[i], i);
crp = crp->Next; // Type Name
crp->Kdata->SetValue(GetTypeName(typ[i]), i);
crp = crp->Next; // Precision
crp->Kdata->SetValue(len[i], i);
crp = crp->Next; // Length
crp->Kdata->SetValue(len[i], i);
crp = crp->Next; // Scale (precision)
crp->Kdata->SetValue(prc[i], i);
} // endfor i
/*********************************************************************/
/* Return the result pointer for use by GetData routines. */
/*********************************************************************/
return qrp;
err:
fclose(infile);
return NULL;
} // end of CSVCColumns
/* --------------------------- Class CSVDEF -------------------------- */
/***********************************************************************/