Commit 4d5f5f4c authored by Alexander Barkov's avatar Alexander Barkov

Merg 10.0-connect -> 10.0

parents a1a49ec9 bec94a15
...@@ -41,7 +41,8 @@ typedef struct _colinfo { ...@@ -41,7 +41,8 @@ typedef struct _colinfo {
int Offset; int Offset;
int Length; int Length;
int Key; int Key;
int Prec; int Precision;
int Scale;
int Opt; int Opt;
char *Remark; char *Remark;
char *Datefmt; char *Datefmt;
......
...@@ -38,6 +38,7 @@ COLBLK::COLBLK(PCOLDEF cdp, PTDB tdbp, int i) ...@@ -38,6 +38,7 @@ COLBLK::COLBLK(PCOLDEF cdp, PTDB tdbp, int i)
Format = cdp->F; Format = cdp->F;
Opt = cdp->Opt; Opt = cdp->Opt;
Long = cdp->Long; Long = cdp->Long;
Precision = cdp->Precision;
Buf_Type = cdp->Buf_Type; Buf_Type = cdp->Buf_Type;
ColUse |= cdp->Flags; // Used by CONNECT ColUse |= cdp->Flags; // Used by CONNECT
Nullable = !!(cdp->Flags & U_NULLS); Nullable = !!(cdp->Flags & U_NULLS);
...@@ -47,6 +48,7 @@ COLBLK::COLBLK(PCOLDEF cdp, PTDB tdbp, int i) ...@@ -47,6 +48,7 @@ COLBLK::COLBLK(PCOLDEF cdp, PTDB tdbp, int i)
memset(&Format, 0, sizeof(FORMAT)); memset(&Format, 0, sizeof(FORMAT));
Opt = 0; Opt = 0;
Long = 0; Long = 0;
Precision = 0;
Buf_Type = TYPE_ERROR; Buf_Type = TYPE_ERROR;
Nullable = false; Nullable = false;
Unsigned = false; Unsigned = false;
...@@ -165,7 +167,7 @@ bool COLBLK::CheckSort(PTDB tdbp) ...@@ -165,7 +167,7 @@ bool COLBLK::CheckSort(PTDB tdbp)
/* InitValue: prepare a column block for read operation. */ /* InitValue: prepare a column block for read operation. */
/* Now we use Format.Length for the len parameter to avoid strings */ /* Now we use Format.Length for the len parameter to avoid strings */
/* to be truncated when converting from string to coded string. */ /* to be truncated when converting from string to coded string. */
/* Added in version 1.5 is the arguments GetPrecision() and Domain */ /* Added in version 1.5 is the arguments GetScale() and Domain */
/* in calling AllocateValue. Domain is used for TYPE_DATE only. */ /* in calling AllocateValue. Domain is used for TYPE_DATE only. */
/***********************************************************************/ /***********************************************************************/
bool COLBLK::InitValue(PGLOBAL g) bool COLBLK::InitValue(PGLOBAL g)
...@@ -173,12 +175,9 @@ bool COLBLK::InitValue(PGLOBAL g) ...@@ -173,12 +175,9 @@ bool COLBLK::InitValue(PGLOBAL g)
if (Value) if (Value)
return false; // Already done return false; // Already done
// Unsigned can be set only for valid value types
int prec = (Unsigned) ? 1 : GetPrecision();
// Allocate a Value object // Allocate a Value object
if (!(Value = AllocateValue(g, Buf_Type, Format.Length, if (!(Value = AllocateValue(g, Buf_Type, Precision,
prec, GetDomain()))) GetScale(), Unsigned, GetDomain())))
return true; return true;
AddStatus(BUF_READY); AddStatus(BUF_READY);
...@@ -270,7 +269,7 @@ SPCBLK::SPCBLK(PCOLUMN cp) ...@@ -270,7 +269,7 @@ SPCBLK::SPCBLK(PCOLUMN cp)
: COLBLK((PCOLDEF)NULL, cp->GetTo_Table()->GetTo_Tdb(), 0) : COLBLK((PCOLDEF)NULL, cp->GetTo_Table()->GetTo_Tdb(), 0)
{ {
Name = (char*)cp->GetName(); Name = (char*)cp->GetName();
Long = 0; Precision = Long = 0;
Buf_Type = TYPE_ERROR; Buf_Type = TYPE_ERROR;
} // end of SPCBLK constructor } // end of SPCBLK constructor
...@@ -290,7 +289,7 @@ void SPCBLK::WriteColumn(PGLOBAL g) ...@@ -290,7 +289,7 @@ void SPCBLK::WriteColumn(PGLOBAL g)
/***********************************************************************/ /***********************************************************************/
RIDBLK::RIDBLK(PCOLUMN cp, bool rnm) : SPCBLK(cp) RIDBLK::RIDBLK(PCOLUMN cp, bool rnm) : SPCBLK(cp)
{ {
Long = 10; Precision = Long = 10;
Buf_Type = TYPE_INT; Buf_Type = TYPE_INT;
Rnm = rnm; Rnm = rnm;
*Format.Type = 'N'; *Format.Type = 'N';
...@@ -313,7 +312,7 @@ void RIDBLK::ReadColumn(PGLOBAL g) ...@@ -313,7 +312,7 @@ void RIDBLK::ReadColumn(PGLOBAL g)
FIDBLK::FIDBLK(PCOLUMN cp) : SPCBLK(cp) FIDBLK::FIDBLK(PCOLUMN cp) : SPCBLK(cp)
{ {
//Is_Key = 2; for when the MUL table indexed reading will be implemented. //Is_Key = 2; for when the MUL table indexed reading will be implemented.
Long = _MAX_PATH; Precision = Long = _MAX_PATH;
Buf_Type = TYPE_STRING; Buf_Type = TYPE_STRING;
*Format.Type = 'C'; *Format.Type = 'C';
Format.Length = Long; Format.Length = Long;
...@@ -348,7 +347,7 @@ void FIDBLK::ReadColumn(PGLOBAL g) ...@@ -348,7 +347,7 @@ void FIDBLK::ReadColumn(PGLOBAL g)
TIDBLK::TIDBLK(PCOLUMN cp) : SPCBLK(cp) TIDBLK::TIDBLK(PCOLUMN cp) : SPCBLK(cp)
{ {
//Is_Key = 2; for when the MUL table indexed reading will be implemented. //Is_Key = 2; for when the MUL table indexed reading will be implemented.
Long = 64; Precision = Long = 64;
Buf_Type = TYPE_STRING; Buf_Type = TYPE_STRING;
*Format.Type = 'C'; *Format.Type = 'C';
Format.Length = Long; Format.Length = Long;
...@@ -375,7 +374,7 @@ void TIDBLK::ReadColumn(PGLOBAL g) ...@@ -375,7 +374,7 @@ void TIDBLK::ReadColumn(PGLOBAL g)
SIDBLK::SIDBLK(PCOLUMN cp) : SPCBLK(cp) SIDBLK::SIDBLK(PCOLUMN cp) : SPCBLK(cp)
{ {
//Is_Key = 2; for when the MUL table indexed reading will be implemented. //Is_Key = 2; for when the MUL table indexed reading will be implemented.
Long = 64; Precision = Long = 64;
Buf_Type = TYPE_STRING; Buf_Type = TYPE_STRING;
*Format.Type = 'C'; *Format.Type = 'C';
Format.Length = Long; Format.Length = Long;
......
...@@ -29,7 +29,8 @@ class DllExport COLBLK : public XOBJECT { ...@@ -29,7 +29,8 @@ class DllExport COLBLK : public XOBJECT {
// Implementation // Implementation
virtual int GetType(void) {return TYPE_COLBLK;} virtual int GetType(void) {return TYPE_COLBLK;}
virtual int GetResultType(void) {return Buf_Type;} virtual int GetResultType(void) {return Buf_Type;}
virtual int GetPrecision(void) {return Format.Prec;} virtual int GetScale(void) {return Format.Prec;}
virtual int GetPrecision(void) {return Precision;}
virtual int GetLength(void) {return Long;} virtual int GetLength(void) {return Long;}
virtual int GetLengthEx(void); virtual int GetLengthEx(void);
virtual int GetAmType() {return TYPE_AM_ERROR;} virtual int GetAmType() {return TYPE_AM_ERROR;}
...@@ -53,6 +54,7 @@ class DllExport COLBLK : public XOBJECT { ...@@ -53,6 +54,7 @@ class DllExport COLBLK : public XOBJECT {
PSZ GetDomain(void) {return (Cdp) ? Cdp->Decode : NULL;} PSZ GetDomain(void) {return (Cdp) ? Cdp->Decode : NULL;}
PSZ GetDesc(void) {return (Cdp) ? Cdp->Desc : NULL;} PSZ GetDesc(void) {return (Cdp) ? Cdp->Desc : NULL;}
PSZ GetFmt(void) {return (Cdp) ? Cdp->Fmt : NULL;} PSZ GetFmt(void) {return (Cdp) ? Cdp->Fmt : NULL;}
bool IsUnsigned(void) {return Unsigned;}
bool IsNullable(void) {return Nullable;} bool IsNullable(void) {return Nullable;}
void SetNullable(bool b) {Nullable = b;} void SetNullable(bool b) {Nullable = b;}
...@@ -88,6 +90,7 @@ class DllExport COLBLK : public XOBJECT { ...@@ -88,6 +90,7 @@ class DllExport COLBLK : public XOBJECT {
int Opt; // Cluster/sort information int Opt; // Cluster/sort information
int Buf_Type; // Data type int Buf_Type; // Data type
int Long; // Internal length in table int Long; // Internal length in table
int Precision; // Column length (as for ODBC)
FORMAT Format; // Output format FORMAT Format; // Output format
ushort ColUse; // Column usage ushort ColUse; // Column usage
ushort Status; // Column read status ushort Status; // Column read status
......
...@@ -178,18 +178,18 @@ static int dbfhead(PGLOBAL g, FILE *file, PSZ fn, DBFHEADER *buf) ...@@ -178,18 +178,18 @@ static int dbfhead(PGLOBAL g, FILE *file, PSZ fn, DBFHEADER *buf)
/****************************************************************************/ /****************************************************************************/
PQRYRES DBFColumns(PGLOBAL g, const char *fn, BOOL info) PQRYRES DBFColumns(PGLOBAL g, const char *fn, BOOL info)
{ {
static int buftyp[] = {TYPE_STRING, TYPE_SHORT, TYPE_STRING, int buftyp[] = {TYPE_STRING, TYPE_SHORT, TYPE_STRING,
TYPE_INT, TYPE_INT, TYPE_SHORT}; TYPE_INT, TYPE_INT, TYPE_SHORT};
static XFLD fldtyp[] = {FLD_NAME, FLD_TYPE, FLD_TYPENAME, XFLD fldtyp[] = {FLD_NAME, FLD_TYPE, FLD_TYPENAME,
FLD_PREC, FLD_LENGTH, FLD_SCALE}; FLD_PREC, FLD_LENGTH, FLD_SCALE};
static unsigned int length[] = {11, 6, 8, 10, 10, 6}; unsigned int length[] = {11, 6, 8, 10, 10, 6};
char buf[2], filename[_MAX_PATH]; char buf[2], filename[_MAX_PATH];
int ncol = sizeof(buftyp) / sizeof(int); int ncol = sizeof(buftyp) / sizeof(int);
int rc, type, len, field, fields; int rc, type, len, field, fields;
BOOL bad; BOOL bad;
DBFHEADER mainhead; DBFHEADER mainhead;
DESCRIPTOR thisfield; DESCRIPTOR thisfield;
FILE *infile; FILE *infile = NULL;
PQRYRES qrp; PQRYRES qrp;
PCOLRES crp; PCOLRES crp;
...@@ -228,8 +228,12 @@ PQRYRES DBFColumns(PGLOBAL g, const char *fn, BOOL info) ...@@ -228,8 +228,12 @@ PQRYRES DBFColumns(PGLOBAL g, const char *fn, BOOL info)
qrp = PlgAllocResult(g, ncol, fields, IDS_COLUMNS + 3, qrp = PlgAllocResult(g, ncol, fields, IDS_COLUMNS + 3,
buftyp, fldtyp, length, true, false); buftyp, fldtyp, length, true, false);
if (info || !qrp) if (info || !qrp) {
if (infile)
fclose(infile);
return qrp; return qrp;
} // endif info
if (trace) { if (trace) {
htrc("Structure of %s\n", filename); htrc("Structure of %s\n", filename);
...@@ -271,11 +275,11 @@ PQRYRES DBFColumns(PGLOBAL g, const char *fn, BOOL info) ...@@ -271,11 +275,11 @@ PQRYRES DBFColumns(PGLOBAL g, const char *fn, BOOL info)
type = TYPE_STRING; type = TYPE_STRING;
break; break;
case 'N': case 'N':
type = (thisfield.Decimals) ? TYPE_FLOAT type = (thisfield.Decimals) ? TYPE_DOUBLE
: (len > 10) ? TYPE_BIGINT : TYPE_INT; : (len > 10) ? TYPE_BIGINT : TYPE_INT;
break; break;
case 'F': case 'F':
type = TYPE_FLOAT; type = TYPE_DOUBLE;
break; break;
case 'D': case 'D':
type = TYPE_DATE; // Is this correct ??? type = TYPE_DATE; // Is this correct ???
......
...@@ -77,12 +77,13 @@ ...@@ -77,12 +77,13 @@
#define TYPE_SEMX 0 /* Initial semantic function type? */ #define TYPE_SEMX 0 /* Initial semantic function type? */
#define TYPE_ERROR 0 #define TYPE_ERROR 0
#define TYPE_STRING 1 #define TYPE_STRING 1
#define TYPE_FLOAT 2 #define TYPE_DOUBLE 2
#define TYPE_SHORT 3 #define TYPE_SHORT 3
#define TYPE_TINY 4 #define TYPE_TINY 4
#define TYPE_BIGINT 5 #define TYPE_BIGINT 5
#define TYPE_LIST 6 #define TYPE_LIST 6
#define TYPE_INT 7 #define TYPE_INT 7
#define TYPE_DECIM 9
#if defined(OS32) #if defined(OS32)
#define SYS_STAMP "OS32" #define SYS_STAMP "OS32"
......
...@@ -862,12 +862,14 @@ void *ha_connect::GetColumnOption(PGLOBAL g, void *field, PCOLINFO pcf) ...@@ -862,12 +862,14 @@ void *ha_connect::GetColumnOption(PGLOBAL g, void *field, PCOLINFO pcf)
return fldp; return fldp;
} // endif special } // endif special
pcf->Prec= 0; pcf->Scale= 0;
pcf->Opt= (fop) ? (int)fop->opt : 0; pcf->Opt= (fop) ? (int)fop->opt : 0;
if ((pcf->Length= fp->field_length) < 0) if ((pcf->Length= fp->field_length) < 0)
pcf->Length= 256; // BLOB? pcf->Length= 256; // BLOB?
pcf->Precision= pcf->Length;
if (fop) { if (fop) {
pcf->Offset= (int)fop->offset; pcf->Offset= (int)fop->offset;
// pcf->Freq= fop->freq; // pcf->Freq= fop->freq;
...@@ -898,13 +900,17 @@ void *ha_connect::GetColumnOption(PGLOBAL g, void *field, PCOLINFO pcf) ...@@ -898,13 +900,17 @@ void *ha_connect::GetColumnOption(PGLOBAL g, void *field, PCOLINFO pcf)
// Find if collation name ends by _ci // Find if collation name ends by _ci
if (!strcmp(cp + strlen(cp) - 3, "_ci")) { if (!strcmp(cp + strlen(cp) - 3, "_ci")) {
pcf->Prec= 1; // Case insensitive pcf->Scale= 1; // Case insensitive
pcf->Opt= 0; // Prevent index opt until it is safe pcf->Opt= 0; // Prevent index opt until it is safe
} // endif ci } // endif ci
break; break;
case TYPE_FLOAT: case TYPE_DOUBLE:
pcf->Prec= max(min(fp->decimals(), ((unsigned)pcf->Length - 2)), 0); pcf->Scale= max(min(fp->decimals(), ((unsigned)pcf->Length - 2)), 0);
break;
case TYPE_DECIM:
pcf->Precision= ((Field_new_decimal*)fp)->precision;
pcf->Scale= fp->decimals();
break; break;
case TYPE_DATE: case TYPE_DATE:
// Field_length is only used for DATE columns // Field_length is only used for DATE columns
...@@ -1109,12 +1115,12 @@ PTDB ha_connect::GetTDB(PGLOBAL g) ...@@ -1109,12 +1115,12 @@ PTDB ha_connect::GetTDB(PGLOBAL g)
|| tdbp->GetAmType() == TYPE_AM_XML)) { || tdbp->GetAmType() == TYPE_AM_XML)) {
tp= tdbp; tp= tdbp;
// tp->SetMode(xmod); // tp->SetMode(xmod);
} else if ((tp= CntGetTDB(g, table_name, xmod, this))) } else if ((tp= CntGetTDB(g, table_name, xmod, this))) {
valid_query_id= xp->last_query_id; valid_query_id= xp->last_query_id;
else tp->SetMode(xmod);
} else
printf("GetTDB: %s\n", g->Message); printf("GetTDB: %s\n", g->Message);
tp->SetMode(xmod);
return tp; return tp;
} // end of GetTDB } // end of GetTDB
...@@ -1326,7 +1332,7 @@ int ha_connect::MakeRecord(char *buf) ...@@ -1326,7 +1332,7 @@ int ha_connect::MakeRecord(char *buf)
value->FormatValue(sdvalout, fmt); value->FormatValue(sdvalout, fmt);
p= sdvalout->GetCharValue(); p= sdvalout->GetCharValue();
break; break;
case TYPE_FLOAT: case TYPE_DOUBLE:
p= NULL; p= NULL;
break; break;
case TYPE_STRING: case TYPE_STRING:
...@@ -1422,7 +1428,7 @@ int ha_connect::ScanRecord(PGLOBAL g, uchar *buf) ...@@ -1422,7 +1428,7 @@ int ha_connect::ScanRecord(PGLOBAL g, uchar *buf)
value->Reset(); value->Reset();
} else switch (value->GetType()) { } else switch (value->GetType()) {
case TYPE_FLOAT: case TYPE_DOUBLE:
value->SetValue(fp->val_real()); value->SetValue(fp->val_real());
break; break;
case TYPE_DATE: case TYPE_DATE:
...@@ -2743,8 +2749,10 @@ int ha_connect::delete_all_rows() ...@@ -2743,8 +2749,10 @@ int ha_connect::delete_all_rows()
} // end of delete_all_rows } // end of delete_all_rows
bool ha_connect::check_privileges(THD *thd, PTOS options) bool ha_connect::check_privileges(THD *thd, PTOS options, char *dbn)
{ {
const char *db= (dbn && *dbn) ? dbn : NULL;
if (!options->type) { if (!options->type) {
if (options->srcdef) if (options->srcdef)
options->type= "MYSQL"; options->type= "MYSQL";
...@@ -2794,7 +2802,7 @@ bool ha_connect::check_privileges(THD *thd, PTOS options) ...@@ -2794,7 +2802,7 @@ bool ha_connect::check_privileges(THD *thd, PTOS options)
case TAB_MAC: case TAB_MAC:
case TAB_WMI: case TAB_WMI:
case TAB_OEM: case TAB_OEM:
return check_access(thd, FILE_ACL, NULL, NULL, NULL, 0, 0); return check_access(thd, FILE_ACL, db, NULL, NULL, 0, 0);
// This is temporary until a solution is found // This is temporary until a solution is found
case TAB_TBL: case TAB_TBL:
...@@ -3020,12 +3028,6 @@ int ha_connect::external_lock(THD *thd, int lock_type) ...@@ -3020,12 +3028,6 @@ int ha_connect::external_lock(THD *thd, int lock_type)
if (!g) if (!g)
DBUG_RETURN(HA_ERR_INTERNAL_ERROR); DBUG_RETURN(HA_ERR_INTERNAL_ERROR);
if (lock_type != F_UNLCK && check_privileges(thd, options)) {
strcpy(g->Message, "This operation requires the FILE privilege");
printf("%s\n", g->Message);
DBUG_RETURN(HA_ERR_INTERNAL_ERROR);
} // endif check_privileges
// Action will depend on lock_type // Action will depend on lock_type
switch (lock_type) { switch (lock_type) {
case F_WRLCK: case F_WRLCK:
...@@ -3129,7 +3131,17 @@ int ha_connect::external_lock(THD *thd, int lock_type) ...@@ -3129,7 +3131,17 @@ int ha_connect::external_lock(THD *thd, int lock_type)
if (adp) if (adp)
// Here we do make the new indexes // Here we do make the new indexes
tdp->MakeIndex(g, adp, true); if (tdp->MakeIndex(g, adp, true) == RC_FX) {
//#if defined(_DEBUG)
// Make it a warning to avoid crash on debug
push_warning(thd, Sql_condition::WARN_LEVEL_WARN,
0, g->Message);
rc= 0;
//#else // !_DEBUG
// my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0));
// rc= HA_ERR_INTERNAL_ERROR;
//#endif // !DEBUG
} // endif MakeIndex
} // endif Mode } // endif Mode
...@@ -3151,6 +3163,14 @@ int ha_connect::external_lock(THD *thd, int lock_type) ...@@ -3151,6 +3163,14 @@ int ha_connect::external_lock(THD *thd, int lock_type)
DBUG_RETURN(rc); DBUG_RETURN(rc);
} // endif MODE_ANY } // endif MODE_ANY
DBUG_ASSERT(table && table->s);
if (check_privileges(thd, options, table->s->db.str)) {
strcpy(g->Message, "This operation requires the FILE privilege");
printf("%s\n", g->Message);
DBUG_RETURN(HA_ERR_INTERNAL_ERROR);
} // endif check_privileges
// Table mode depends on the query type // Table mode depends on the query type
newmode= CheckMode(g, thd, newmode, &xcheck, &cras); newmode= CheckMode(g, thd, newmode, &xcheck, &cras);
...@@ -3196,9 +3216,6 @@ int ha_connect::external_lock(THD *thd, int lock_type) ...@@ -3196,9 +3216,6 @@ int ha_connect::external_lock(THD *thd, int lock_type)
xmod= newmode; xmod= newmode;
if (!table)
rc= 3; // Logical error
// Delay open until used fields are known // Delay open until used fields are known
} // endif tdbp } // endif tdbp
...@@ -3311,7 +3328,7 @@ filename_to_dbname_and_tablename(const char *filename, ...@@ -3311,7 +3328,7 @@ filename_to_dbname_and_tablename(const char *filename,
memcpy(database, d.str, d.length); memcpy(database, d.str, d.length);
database[d.length]= '\0'; database[d.length]= '\0';
return false; return false;
} } // end of filename_to_dbname_and_tablename
/** /**
...@@ -3369,7 +3386,7 @@ int ha_connect::delete_or_rename_table(const char *name, const char *to) ...@@ -3369,7 +3386,7 @@ int ha_connect::delete_or_rename_table(const char *name, const char *to)
// Now we can work // Now we can work
pos= share->option_struct; pos= share->option_struct;
if (check_privileges(thd, pos)) if (check_privileges(thd, pos, db))
{ {
free_table_share(share); free_table_share(share);
DBUG_RETURN(HA_ERR_INTERNAL_ERROR); DBUG_RETURN(HA_ERR_INTERNAL_ERROR);
...@@ -3508,7 +3525,7 @@ static bool add_fields(PGLOBAL g, ...@@ -3508,7 +3525,7 @@ static bool add_fields(PGLOBAL g,
length= (char*)PlugSubAlloc(g, NULL, 8); length= (char*)PlugSubAlloc(g, NULL, 8);
sprintf(length, "%d", len); sprintf(length, "%d", len);
if (typ == TYPE_FLOAT) { if (typ == TYPE_DOUBLE) {
decimals= (char*)PlugSubAlloc(g, NULL, 8); decimals= (char*)PlugSubAlloc(g, NULL, 8);
sprintf(decimals, "%d", min(dec, (min(len, 31) - 1))); sprintf(decimals, "%d", min(dec, (min(len, 31) - 1)));
} // endif dec } // endif dec
...@@ -3574,6 +3591,10 @@ static bool add_field(String *sql, const char *field_name, int typ, ...@@ -3574,6 +3591,10 @@ static bool add_field(String *sql, const char *field_name, int typ,
error|= sql->append(','); error|= sql->append(',');
// dec must be < len and < 31 // dec must be < len and < 31
error|= sql->append_ulonglong(min(dec, (min(len, 31) - 1))); error|= sql->append_ulonglong(min(dec, (min(len, 31) - 1)));
} else if (dec > 0 && !strcmp(type, "DECIMAL")) {
error|= sql->append(',');
// dec must be < len
error|= sql->append_ulonglong(min(dec, len - 1));
} // endif dec } // endif dec
error|= sql->append(')'); error|= sql->append(')');
...@@ -3590,7 +3611,7 @@ static bool add_field(String *sql, const char *field_name, int typ, ...@@ -3590,7 +3611,7 @@ static bool add_field(String *sql, const char *field_name, int typ,
if (dft && *dft) { if (dft && *dft) {
error|= sql->append(" DEFAULT "); error|= sql->append(" DEFAULT ");
if (IsTypeChar(typ)) { if (!IsTypeNum(typ)) {
error|= sql->append("'"); error|= sql->append("'");
error|= sql->append_for_single_quote(dft, strlen(dft)); error|= sql->append_for_single_quote(dft, strlen(dft));
error|= sql->append("'"); error|= sql->append("'");
...@@ -4086,7 +4107,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd, ...@@ -4086,7 +4107,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
case TAB_TBL: case TAB_TBL:
case TAB_XCL: case TAB_XCL:
case TAB_OCCUR: case TAB_OCCUR:
if (!stricmp(tab, create_info->alias) && if (!src && !stricmp(tab, create_info->alias) &&
(!db || !stricmp(db, table_s->db.str))) (!db || !stricmp(db, table_s->db.str)))
sprintf(g->Message, "A %s table cannot refer to itself", topt->type); sprintf(g->Message, "A %s table cannot refer to itself", topt->type);
else else
...@@ -4295,11 +4316,15 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd, ...@@ -4295,11 +4316,15 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
} else } else
typ= plgtyp; typ= plgtyp;
switch (typ) {
case TYPE_DOUBLE:
// Some data sources do not count dec in length (prec) // Some data sources do not count dec in length (prec)
if (typ == TYPE_FLOAT)
prec += (dec + 2); // To be safe prec += (dec + 2); // To be safe
else case TYPE_DECIM:
break;
default:
dec= 0; dec= 0;
} // endswitch typ
} // endif ttp } // endif ttp
#endif // ODBC_SUPPORT #endif // ODBC_SUPPORT
...@@ -4307,7 +4332,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd, ...@@ -4307,7 +4332,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
// Make the arguments as required by add_fields // Make the arguments as required by add_fields
if (typ == TYPE_DATE) if (typ == TYPE_DATE)
prec= 0; prec= 0;
else if (typ == TYPE_FLOAT) else if (typ == TYPE_DOUBLE)
prec= len; prec= len;
// Now add the field // Now add the field
...@@ -4336,6 +4361,28 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd, ...@@ -4336,6 +4361,28 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
return HA_ERR_INTERNAL_ERROR; return HA_ERR_INTERNAL_ERROR;
} // end of connect_assisted_discovery } // end of connect_assisted_discovery
/**
Get the database name from a qualified table name.
*/
char *ha_connect::GetDBfromName(const char *name)
{
char *db, dbname[128], tbname[128];
if (filename_to_dbname_and_tablename(name, dbname, sizeof(dbname),
tbname, sizeof(tbname)))
*dbname= 0;
if (*dbname) {
assert(xp && xp->g);
db= (char*)PlugSubAlloc(xp->g, NULL, strlen(dbname + 1));
strcpy(db, dbname);
} else
db= NULL;
return db;
} // end of GetDBfromName
/** /**
@brief @brief
create() is called to create a database. The variable name will have the name create() is called to create a database. The variable name will have the name
...@@ -4394,7 +4441,7 @@ int ha_connect::create(const char *name, TABLE *table_arg, ...@@ -4394,7 +4441,7 @@ int ha_connect::create(const char *name, TABLE *table_arg,
DBUG_RETURN(HA_ERR_INTERNAL_ERROR); DBUG_RETURN(HA_ERR_INTERNAL_ERROR);
} // endif ttp } // endif ttp
if (check_privileges(thd, options)) if (check_privileges(thd, options, GetDBfromName(name)))
DBUG_RETURN(HA_ERR_INTERNAL_ERROR); DBUG_RETURN(HA_ERR_INTERNAL_ERROR);
if (options->data_charset) { if (options->data_charset) {
......
...@@ -445,8 +445,9 @@ const char *GetValStr(OPVAL vop, bool neg); ...@@ -445,8 +445,9 @@ const char *GetValStr(OPVAL vop, bool neg);
int optimize(THD* thd, HA_CHECK_OPT* check_opt); int optimize(THD* thd, HA_CHECK_OPT* check_opt);
protected: protected:
bool check_privileges(THD *thd, PTOS options); bool check_privileges(THD *thd, PTOS options, char *dbn);
MODE CheckMode(PGLOBAL g, THD *thd, MODE newmode, bool *chk, bool *cras); MODE CheckMode(PGLOBAL g, THD *thd, MODE newmode, bool *chk, bool *cras);
char *GetDBfromName(const char *name);
// Members // Members
static ulong num; // Tracable handler number static ulong num; // Tracable handler number
......
...@@ -723,7 +723,8 @@ PQRYRES MYSQLC::GetResult(PGLOBAL g, bool pdb) ...@@ -723,7 +723,8 @@ PQRYRES MYSQLC::GetResult(PGLOBAL g, bool pdb)
// For direct MySQL connection, display the MySQL date string // For direct MySQL connection, display the MySQL date string
crp->Type = TYPE_STRING; crp->Type = TYPE_STRING;
crp->Prec = (crp->Type == TYPE_FLOAT) ? fld->decimals : 0; crp->Prec = (crp->Type == TYPE_DOUBLE || crp->Type == TYPE_DECIM)
? fld->decimals : 0;
crp->Length = fld->max_length; crp->Length = fld->max_length;
crp->Clen = GetTypeSize(crp->Type, crp->Length); crp->Clen = GetTypeSize(crp->Type, crp->Length);
uns = (fld->flags & (UNSIGNED_FLAG | ZEROFILL_FLAG)) ? true : false; uns = (fld->flags & (UNSIGNED_FLAG | ZEROFILL_FLAG)) ? true : false;
......
...@@ -141,7 +141,7 @@ t1 CREATE TABLE `t1` ( ...@@ -141,7 +141,7 @@ t1 CREATE TABLE `t1` (
`e` bigint(20) DEFAULT NULL, `e` bigint(20) DEFAULT NULL,
`f` double DEFAULT NULL, `f` double DEFAULT NULL,
`g` double DEFAULT NULL, `g` double DEFAULT NULL,
`h` double(20,5) DEFAULT NULL `h` decimal(20,5) DEFAULT NULL
) ENGINE=CONNECT DEFAULT CHARSET=latin1 `TABLE_TYPE`='MYSQL' `OPTION_LIST`='host=127.0.0.1,user=root,port=SLAVE_PORT' ) ENGINE=CONNECT DEFAULT CHARSET=latin1 `TABLE_TYPE`='MYSQL' `OPTION_LIST`='host=127.0.0.1,user=root,port=SLAVE_PORT'
SELECT * FROM t1; SELECT * FROM t1;
a b c d e f g h a b c d e f g h
......
Table Create Table
t1 CREATE TABLE `t1` (
`Name` varchar(256) NOT NULL,
`Description` varchar(256) NOT NULL
) ENGINE=CONNECT DEFAULT CHARSET=latin1 `TABLE_TYPE`='ODBC' `CATFUNC`='Sources'
SET NAMES utf8;
#
# Checking CATFUNC=Tables
#
# All tables in all schemas (filtered with WHERE)
CREATE TABLE t1 ENGINE=CONNECT
TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=mtr'
CATFUNC=Tables;
SELECT * FROM t1 WHERE Table_Schema='MTR' ORDER BY Table_Schema, Table_Name;
Table_Cat Table_Schema Table_Name Table_Type Remark
MTR T1 TABLE
MTR T2 TABLE
MTR V1 VIEW
DROP TABLE t1;
# All tables in all schemas (filtered with WHERE)
CREATE TABLE t1 ENGINE=CONNECT
TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=mtr'
CATFUNC=Tables TABNAME='%.%';
SELECT * FROM t1 WHERE Table_Schema='MTR' ORDER BY Table_Schema, Table_Name;
Table_Cat Table_Schema Table_Name Table_Type Remark
MTR T1 TABLE
MTR T2 TABLE
MTR V1 VIEW
DROP TABLE t1;
# All tables "T1" in all schemas (filtered with WHERE)
CREATE TABLE t1 ENGINE=CONNECT
TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=mtr'
CATFUNC=Tables TABNAME='%.T1';
SELECT * FROM t1 WHERE Table_Schema='MTR' ORDER BY Table_Schema, Table_Name;
Table_Cat Table_Schema Table_Name Table_Type Remark
MTR T1 TABLE
DROP TABLE t1;
# All tables "T1" in all schemas (filtered with WHERE)
CREATE TABLE t1 ENGINE=CONNECT
TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=mtr'
CATFUNC=Tables TABNAME='T1';
SELECT * FROM t1 WHERE Table_Schema='MTR' ORDER BY Table_Schema, Table_Name;
Table_Cat Table_Schema Table_Name Table_Type Remark
MTR T1 TABLE
DROP TABLE t1;
# Table "T1" in the schema "MTR"
CREATE TABLE t1 ENGINE=CONNECT
TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=mtr'
CATFUNC=Tables TABNAME='MTR.T1';
SELECT * FROM t1 ORDER BY Table_Schema, Table_Name;
Table_Cat Table_Schema Table_Name Table_Type Remark
MTR T1 TABLE
DROP TABLE t1;
# All tables in the schema "MTR"
CREATE TABLE t1 ENGINE=CONNECT
TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=mtr'
CATFUNC=Tables TABNAME='MTR.%';
SELECT * FROM t1 ORDER BY Table_Schema, Table_Name;
Table_Cat Table_Schema Table_Name Table_Type Remark
MTR T1 TABLE
MTR T2 TABLE
MTR V1 VIEW
DROP TABLE t1;
#
# Checking CATFUNC=Columns
#
# All columns in all schemas (limited with WHERE)
CREATE TABLE t1 ENGINE=CONNECT
TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=mtr'
CATFUNC=Columns;
SELECT * FROM t1 WHERE Table_Schema='MTR' ORDER BY Table_Schema, Table_Name;
Table_Cat Table_Schema Table_Name Column_Name Data_Type Type_Name Column_Size Buffer_Length Decimal_Digits Radix Nullable Remarks
MTR T1 A 3 DECIMAL 38 40 0 10 1
MTR T1 B 6 NUMBER 38 40 0 0 1
MTR T2 A 12 VARCHAR2 64 64 0 0 1
MTR V1 A 3 DECIMAL 38 40 0 10 1
MTR V1 B 6 NUMBER 38 40 0 0 1
DROP TABLE t1;
# All columns in all schemas (limited with WHERE)
CREATE TABLE t1 ENGINE=CONNECT
TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=mtr'
CATFUNC=Columns TABNAME='%.%';
SELECT * FROM t1 WHERE Table_Schema='MTR' ORDER BY Table_Schema, Table_Name;
Table_Cat Table_Schema Table_Name Column_Name Data_Type Type_Name Column_Size Buffer_Length Decimal_Digits Radix Nullable Remarks
MTR T1 A 3 DECIMAL 38 40 0 10 1
MTR T1 B 6 NUMBER 38 40 0 0 1
MTR T2 A 12 VARCHAR2 64 64 0 0 1
MTR V1 A 3 DECIMAL 38 40 0 10 1
MTR V1 B 6 NUMBER 38 40 0 0 1
DROP TABLE t1;
# All tables "T1" in all schemas (limited with WHERE)
CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=mtr' CATFUNC=Columns TABNAME='%.T1';
SELECT * FROM t1 WHERE Table_Schema='MTR' ORDER BY Table_Schema, Table_Name;
Table_Cat Table_Schema Table_Name Column_Name Data_Type Type_Name Column_Size Buffer_Length Decimal_Digits Radix Nullable Remarks
MTR T1 A 3 DECIMAL 38 40 0 10 1
MTR T1 B 6 NUMBER 38 40 0 0 1
DROP TABLE t1;
# Table "T1" in the schema "MTR"
CREATE TABLE t1 ENGINE=CONNECT
TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=mtr'
CATFUNC=Columns TABNAME='MTR.T1';
SELECT * FROM t1 ORDER BY Table_Schema, Table_Name;
Table_Cat Table_Schema Table_Name Column_Name Data_Type Type_Name Column_Size Buffer_Length Decimal_Digits Radix Nullable Remarks
MTR T1 A 3 DECIMAL 38 40 0 10 1
MTR T1 B 6 NUMBER 38 40 0 0 1
DROP TABLE t1;
# All tables "T1" in all schemas (filtered with WHERE)
CREATE TABLE t1 ENGINE=CONNECT
TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=mtr'
CATFUNC=Columns TABNAME='%.T1';
SELECT * FROM t1 WHERE Table_Schema='MTR' ORDER BY Table_Schema, Table_Name;
Table_Cat Table_Schema Table_Name Column_Name Data_Type Type_Name Column_Size Buffer_Length Decimal_Digits Radix Nullable Remarks
MTR T1 A 3 DECIMAL 38 40 0 10 1
MTR T1 B 6 NUMBER 38 40 0 0 1
DROP TABLE t1;
#
# Checking tables
#
# Table "T1" in the default schema ("MTR")
CREATE TABLE t1 ENGINE=CONNECT
TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=mtr'
TABNAME='T1';
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`A` decimal(38,0) DEFAULT NULL,
`B` double(40,0) DEFAULT NULL
) ENGINE=CONNECT DEFAULT CHARSET=latin1 CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=mtr' `TABLE_TYPE`='ODBC' `TABNAME`='T1'
SELECT * FROM t1 ORDER BY A;
A B
10 1000000000
20 1000000000000
30 1000000000000000
CREATE TABLE t2 AS SELECT * FROM t1;
SHOW CREATE TABLE t2;
Table Create Table
t2 CREATE TABLE `t2` (
`A` decimal(38,0) DEFAULT NULL,
`B` double(40,0) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
SELECT * FROM t2;
A B
10 1000000000
20 1000000000000
30 1000000000000000
DROP TABLE t2;
CREATE VIEW v1 AS SELECT * FROM t1;
SELECT * FROM v1;
A B
10 1000000000
20 1000000000000
30 1000000000000000
DROP VIEW v1;
DROP TABLE t1;
# Table "T1" in the schema "MTR"
CREATE TABLE t1 ENGINE=CONNECT
TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=mtr'
TABNAME='MTR.T1';
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`A` decimal(38,0) DEFAULT NULL,
`B` double(40,0) DEFAULT NULL
) ENGINE=CONNECT DEFAULT CHARSET=latin1 CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=mtr' `TABLE_TYPE`='ODBC' `TABNAME`='MTR.T1'
SELECT * FROM t1;
A B
10 1000000000
20 1000000000000
30 1000000000000000
DROP TABLE t1;
# View "V1" in the schema "MTR"
CREATE TABLE t1 ENGINE=CONNECT
TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=mtr'
TABNAME='MTR.V1';
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`A` decimal(38,0) DEFAULT NULL,
`B` double(40,0) DEFAULT NULL
) ENGINE=CONNECT DEFAULT CHARSET=latin1 CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=mtr' `TABLE_TYPE`='ODBC' `TABNAME`='MTR.V1'
SELECT * FROM t1;
A B
10 1000000000
20 1000000000000
30 1000000000000000
CREATE TABLE t2 AS SELECT * FROM t1;
SHOW CREATE TABLE t2;
Table Create Table
t2 CREATE TABLE `t2` (
`A` decimal(38,0) DEFAULT NULL,
`B` double(40,0) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
SELECT * FROM t2;
A B
10 1000000000
20 1000000000000
30 1000000000000000
DROP TABLE t2;
CREATE VIEW v1 AS SELECT * FROM t1;
SELECT * FROM v1;
A B
10 1000000000
20 1000000000000
30 1000000000000000
DROP VIEW v1;
DROP TABLE t1;
# Table "T2" in the schema "MTR"
CREATE TABLE t1 ENGINE=CONNECT
TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=mtr'
TABNAME='MTR.T2';
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`A` varchar(64) DEFAULT NULL
) ENGINE=CONNECT DEFAULT CHARSET=latin1 CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=mtr' `TABLE_TYPE`='ODBC' `TABNAME`='MTR.T2'
SELECT * FROM t1;
A
test
CREATE TABLE t2 AS SELECT * FROM t1;
SHOW CREATE TABLE t2;
Table Create Table
t2 CREATE TABLE `t2` (
`A` varchar(64) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
SELECT * FROM t2;
A
test
DROP TABLE t2;
CREATE VIEW v1 AS SELECT * FROM t1;
SELECT * FROM v1;
A
test
DROP VIEW v1;
DROP TABLE t1;
--disable_query_log
--error 0,ER_UNKNOWN_ERROR
CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CATFUNC=Sources;
if ($mysql_errno)
{
Skip No ODBC support;
}
if (!`SELECT count(*) FROM t1 WHERE Name='ConnectEngineOracle'`)
{
DROP TABLE t1;
Skip Need ODBC data source ConnectEngineOracle;
}
SHOW CREATE TABLE t1;
DROP TABLE t1;
--enable_query_log
DROP USER mtr CASCADE;
CREATE USER mtr IDENTIFIED BY mtr
DEFAULT TABLESPACE users
TEMPORARY TABLESPACE temp;
GRANT CREATE SESSION TO mtr;
GRANT CREATE TABLE TO mtr;
GRANT CREATE VIEW TO mtr;
ALTER USER mtr QUOTA UNLIMITED ON USERS;
CONNECT mtr/mtr;
CREATE TABLE t1 (a INT,b NUMBER);
INSERT INTO t1 VALUES (10,1000*1000*1000);
INSERT INTO t1 VALUES (20,1000*1000*1000*1000);
INSERT INTO t1 VALUES (30,1000*1000*1000*1000*1000);
CREATE VIEW v1 AS SELECT * FROM t1;
CREATE TABLE t2 (a VARCHAR(64));
INSERT INTO t2 VALUES ('test');
--source have_odbc_oracle.inc
#
# To configure your system to be able to run this test,
# follow through the following steps:
#
# 1. Install and configure Oracle database to start on the system startup.
#
# 2. Create user, database, schema and tables to be used by mtr:
# sqlplus system/manager < odbc_oracle.sql
#
# 3. Configure Oracle ODBC Driver for unixODBC (skip this step on Windows):
# Add these lines into /etc/odbcinst.ini:
# (the exact paths can vary)
#
#[Oracle11g]
#Description=Oracle ODBC driver for Oracle 11g
#Driver=/u01/app/oracle/product/11.2.0/xe/lib/libsqora.so.11.1
#Setup=
#FileUsage=
#CPTimeout=
#CPReuse=
#
# 4. Create a data source with the name "ConnectEngineOracle"
# - On Windows: use odbcadm.exe
# - On Linux: put these lines into /etc/odbc.ini
#
#[ConnectEngineOracle]
#Application Attributes=T
#Attributes=W
#BatchAutocommitMode=IfAllSuccessful
#CloseCursor=F
#DisableDPM=F
#DisableMTS=T
#Driver=Oracle11g
#DSN=ConnectEngineOracle
#EXECSchemaOpt=
#EXECSyntax=T
#Failover=T
#FailoverDelay=10
#FailoverRetryCount=10
#FetchBufferSize=64000
#ForceWCHAR=F
#Lobs=T
#Longs=T
#MetadataIdDefault=F
#QueryTimeout=T
#ResultSets=T
#ServerName=
#SQLGetData extensions=F
#Translation DLL=
#Translation Option=0
#UserID=
SET NAMES utf8;
#
# Oracle does not support the third (catalog) level
# in SQLTables() and SQLColumns(), e.g.: CATFUNC=Tables TABNAME='%.%.%'.
# It returns a "Driver not capable" error on attept to use non-NULL catalog.
#
# But it works fine with the second (schema) level:
# CATFUNC=Tables TABNAME='%.%'
# Note, if schema level is not specified, or schema level is '%',
# tables for *all* schemas are returned
# (not only for the schema associated with the user.
#
# Note, schema and table names must be in upper case.
#
--echo #
--echo # Checking CATFUNC=Tables
--echo #
--echo
--echo # All tables in all schemas (filtered with WHERE)
CREATE TABLE t1 ENGINE=CONNECT
TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=mtr'
CATFUNC=Tables;
SELECT * FROM t1 WHERE Table_Schema='MTR' ORDER BY Table_Schema, Table_Name;
DROP TABLE t1;
--echo # All tables in all schemas (filtered with WHERE)
CREATE TABLE t1 ENGINE=CONNECT
TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=mtr'
CATFUNC=Tables TABNAME='%.%';
SELECT * FROM t1 WHERE Table_Schema='MTR' ORDER BY Table_Schema, Table_Name;
DROP TABLE t1;
--echo # All tables "T1" in all schemas (filtered with WHERE)
CREATE TABLE t1 ENGINE=CONNECT
TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=mtr'
CATFUNC=Tables TABNAME='%.T1';
SELECT * FROM t1 WHERE Table_Schema='MTR' ORDER BY Table_Schema, Table_Name;
DROP TABLE t1;
--echo # All tables "T1" in all schemas (filtered with WHERE)
CREATE TABLE t1 ENGINE=CONNECT
TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=mtr'
CATFUNC=Tables TABNAME='T1';
SELECT * FROM t1 WHERE Table_Schema='MTR' ORDER BY Table_Schema, Table_Name;
DROP TABLE t1;
--echo # Table "T1" in the schema "MTR"
CREATE TABLE t1 ENGINE=CONNECT
TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=mtr'
CATFUNC=Tables TABNAME='MTR.T1';
SELECT * FROM t1 ORDER BY Table_Schema, Table_Name;
DROP TABLE t1;
--echo # All tables in the schema "MTR"
CREATE TABLE t1 ENGINE=CONNECT
TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=mtr'
CATFUNC=Tables TABNAME='MTR.%';
SELECT * FROM t1 ORDER BY Table_Schema, Table_Name;
DROP TABLE t1;
--echo #
--echo # Checking CATFUNC=Columns
--echo #
--echo
--echo # All columns in all schemas (limited with WHERE)
CREATE TABLE t1 ENGINE=CONNECT
TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=mtr'
CATFUNC=Columns;
# Disable warnings to avoid "Result limited to 20000 lines"
--disable_warnings
SELECT * FROM t1 WHERE Table_Schema='MTR' ORDER BY Table_Schema, Table_Name;
--enable_warnings
DROP TABLE t1;
--echo # All columns in all schemas (limited with WHERE)
CREATE TABLE t1 ENGINE=CONNECT
TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=mtr'
CATFUNC=Columns TABNAME='%.%';
# Disable warnings to avoid "Result limited to 20000 lines"
--disable_warnings
SELECT * FROM t1 WHERE Table_Schema='MTR' ORDER BY Table_Schema, Table_Name;
--enable_warnings
DROP TABLE t1;
--echo # All tables "T1" in all schemas (limited with WHERE)
CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=mtr' CATFUNC=Columns TABNAME='%.T1';
SELECT * FROM t1 WHERE Table_Schema='MTR' ORDER BY Table_Schema, Table_Name;
DROP TABLE t1;
--echo # Table "T1" in the schema "MTR"
CREATE TABLE t1 ENGINE=CONNECT
TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=mtr'
CATFUNC=Columns TABNAME='MTR.T1';
SELECT * FROM t1 ORDER BY Table_Schema, Table_Name;
DROP TABLE t1;
--echo # All tables "T1" in all schemas (filtered with WHERE)
CREATE TABLE t1 ENGINE=CONNECT
TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=mtr'
CATFUNC=Columns TABNAME='%.T1';
SELECT * FROM t1 WHERE Table_Schema='MTR' ORDER BY Table_Schema, Table_Name;
DROP TABLE t1;
--echo #
--echo # Checking tables
--echo #
--echo
--echo # Table "T1" in the default schema ("MTR")
CREATE TABLE t1 ENGINE=CONNECT
TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=mtr'
TABNAME='T1';
SHOW CREATE TABLE t1;
SELECT * FROM t1 ORDER BY A;
CREATE TABLE t2 AS SELECT * FROM t1;
SHOW CREATE TABLE t2;
SELECT * FROM t2;
DROP TABLE t2;
CREATE VIEW v1 AS SELECT * FROM t1;
SELECT * FROM v1;
DROP VIEW v1;
DROP TABLE t1;
--echo # Table "T1" in the schema "MTR"
CREATE TABLE t1 ENGINE=CONNECT
TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=mtr'
TABNAME='MTR.T1';
SHOW CREATE TABLE t1;
SELECT * FROM t1;
DROP TABLE t1;
--echo # View "V1" in the schema "MTR"
CREATE TABLE t1 ENGINE=CONNECT
TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=mtr'
TABNAME='MTR.V1';
SHOW CREATE TABLE t1;
SELECT * FROM t1;
CREATE TABLE t2 AS SELECT * FROM t1;
SHOW CREATE TABLE t2;
SELECT * FROM t2;
DROP TABLE t2;
CREATE VIEW v1 AS SELECT * FROM t1;
SELECT * FROM v1;
DROP VIEW v1;
DROP TABLE t1;
--echo # Table "T2" in the schema "MTR"
CREATE TABLE t1 ENGINE=CONNECT
TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=mtr'
TABNAME='MTR.T2';
SHOW CREATE TABLE t1;
SELECT * FROM t1;
CREATE TABLE t2 AS SELECT * FROM t1;
SHOW CREATE TABLE t2;
SELECT * FROM t2;
DROP TABLE t2;
CREATE VIEW v1 AS SELECT * FROM t1;
SELECT * FROM v1;
DROP VIEW v1;
DROP TABLE t1;
...@@ -42,9 +42,10 @@ int MYSQLtoPLG(char *typname, char *var) ...@@ -42,9 +42,10 @@ int MYSQLtoPLG(char *typname, char *var)
!stricmp(typname, "text") || !stricmp(typname, "blob")) !stricmp(typname, "text") || !stricmp(typname, "blob"))
type = TYPE_STRING; type = TYPE_STRING;
else if (!stricmp(typname, "double") || !stricmp(typname, "float") || else if (!stricmp(typname, "double") || !stricmp(typname, "float") ||
!stricmp(typname, "real") || !stricmp(typname, "real"))
!stricmp(typname, "decimal") || !stricmp(typname, "numeric")) type = TYPE_DOUBLE;
type = TYPE_FLOAT; else if (!stricmp(typname, "decimal") || !stricmp(typname, "numeric"))
type = TYPE_DECIM;
else if (!stricmp(typname, "date") || !stricmp(typname, "datetime") || else if (!stricmp(typname, "date") || !stricmp(typname, "datetime") ||
!stricmp(typname, "time") || !stricmp(typname, "timestamp") || !stricmp(typname, "time") || !stricmp(typname, "timestamp") ||
!stricmp(typname, "year")) !stricmp(typname, "year"))
...@@ -95,7 +96,7 @@ enum enum_field_types PLGtoMYSQL(int type, bool dbf, char v) ...@@ -95,7 +96,7 @@ enum enum_field_types PLGtoMYSQL(int type, bool dbf, char v)
case TYPE_SHORT: case TYPE_SHORT:
mytype = MYSQL_TYPE_SHORT; mytype = MYSQL_TYPE_SHORT;
break; break;
case TYPE_FLOAT: case TYPE_DOUBLE:
mytype = MYSQL_TYPE_DOUBLE; mytype = MYSQL_TYPE_DOUBLE;
break; break;
case TYPE_DATE: case TYPE_DATE:
...@@ -114,6 +115,13 @@ enum enum_field_types PLGtoMYSQL(int type, bool dbf, char v) ...@@ -114,6 +115,13 @@ enum enum_field_types PLGtoMYSQL(int type, bool dbf, char v)
case TYPE_TINY: case TYPE_TINY:
mytype = MYSQL_TYPE_TINY; mytype = MYSQL_TYPE_TINY;
break; break;
case TYPE_DECIM:
#if !defined(ALPHA)
mytype = MYSQL_TYPE_NEWDECIMAL;
#else // ALPHA
mytype = MYSQL_TYPE_DECIMAL;
#endif // ALPHA
break;
default: default:
mytype = MYSQL_TYPE_NULL; mytype = MYSQL_TYPE_NULL;
} // endswitch mytype } // endswitch mytype
...@@ -129,7 +137,7 @@ const char *PLGtoMYSQLtype(int type, bool dbf, char v) ...@@ -129,7 +137,7 @@ const char *PLGtoMYSQLtype(int type, bool dbf, char v)
switch (type) { switch (type) {
case TYPE_INT: return "INT"; case TYPE_INT: return "INT";
case TYPE_SHORT: return "SMALLINT"; case TYPE_SHORT: return "SMALLINT";
case TYPE_FLOAT: return "DOUBLE"; case TYPE_DOUBLE: return "DOUBLE";
case TYPE_DATE: return dbf ? "DATE" : case TYPE_DATE: return dbf ? "DATE" :
(v == 'S') ? "TIMESTAMP" : (v == 'S') ? "TIMESTAMP" :
(v == 'D') ? "DATE" : (v == 'D') ? "DATE" :
...@@ -138,6 +146,7 @@ const char *PLGtoMYSQLtype(int type, bool dbf, char v) ...@@ -138,6 +146,7 @@ const char *PLGtoMYSQLtype(int type, bool dbf, char v)
case TYPE_STRING: return v ? "VARCHAR" : "CHAR"; case TYPE_STRING: return v ? "VARCHAR" : "CHAR";
case TYPE_BIGINT: return "BIGINT"; case TYPE_BIGINT: return "BIGINT";
case TYPE_TINY: return "TINYINT"; case TYPE_TINY: return "TINYINT";
case TYPE_DECIM: return "DECIMAL";
default: return "CHAR(0)"; default: return "CHAR(0)";
} // endswitch mytype } // endswitch mytype
...@@ -170,9 +179,11 @@ int MYSQLtoPLG(int mytype, char *var) ...@@ -170,9 +179,11 @@ int MYSQLtoPLG(int mytype, char *var)
#if !defined(ALPHA) #if !defined(ALPHA)
case MYSQL_TYPE_NEWDECIMAL: case MYSQL_TYPE_NEWDECIMAL:
#endif // !ALPHA) #endif // !ALPHA)
type = TYPE_DECIM;
break;
case MYSQL_TYPE_FLOAT: case MYSQL_TYPE_FLOAT:
case MYSQL_TYPE_DOUBLE: case MYSQL_TYPE_DOUBLE:
type = TYPE_FLOAT; type = TYPE_DOUBLE;
break; break;
case MYSQL_TYPE_TIMESTAMP: case MYSQL_TYPE_TIMESTAMP:
case MYSQL_TYPE_DATE: case MYSQL_TYPE_DATE:
......
/************ Odbconn C++ Functions Source Code File (.CPP) ************/ /************ Odbconn C++ Functions Source Code File (.CPP) ************/
/* Name: ODBCONN.CPP Version 1.8 */ /* Name: ODBCONN.CPP Version 1.9 */
/* */ /* */
/* (C) Copyright to the author Olivier BERTRAND 1998-2013 */ /* (C) Copyright to the author Olivier BERTRAND 1998-2013 */
/* */ /* */
...@@ -78,8 +78,9 @@ static short GetSQLType(int type) ...@@ -78,8 +78,9 @@ static short GetSQLType(int type)
case TYPE_INT: tp = SQL_INTEGER; break; case TYPE_INT: tp = SQL_INTEGER; break;
case TYPE_DATE: tp = SQL_TIMESTAMP; break; case TYPE_DATE: tp = SQL_TIMESTAMP; break;
case TYPE_BIGINT: tp = SQL_BIGINT; break; // (-5) case TYPE_BIGINT: tp = SQL_BIGINT; break; // (-5)
case TYPE_FLOAT: tp = SQL_DOUBLE; break; case TYPE_DOUBLE: tp = SQL_DOUBLE; break;
case TYPE_TINY : tp = SQL_TINYINT; break; case TYPE_TINY: tp = SQL_TINYINT; break;
case TYPE_DECIM: tp = SQL_DECIMAL; break;
} // endswitch type } // endswitch type
return tp; return tp;
...@@ -98,8 +99,9 @@ static int GetSQLCType(int type) ...@@ -98,8 +99,9 @@ static int GetSQLCType(int type)
case TYPE_INT: tp = SQL_C_LONG; break; case TYPE_INT: tp = SQL_C_LONG; break;
case TYPE_DATE: tp = SQL_C_TIMESTAMP; break; case TYPE_DATE: tp = SQL_C_TIMESTAMP; break;
case TYPE_BIGINT: tp = SQL_C_SBIGINT; break; case TYPE_BIGINT: tp = SQL_C_SBIGINT; break;
case TYPE_FLOAT: tp = SQL_C_DOUBLE; break; case TYPE_DOUBLE: tp = SQL_C_DOUBLE; break;
case TYPE_TINY : tp = SQL_C_TINYINT; break; case TYPE_TINY : tp = SQL_C_TINYINT; break;
case TYPE_DECIM: tp = SQL_C_CHAR; break;
} // endswitch type } // endswitch type
return tp; return tp;
...@@ -125,8 +127,9 @@ int TranslateSQLType(int stp, int prec, int& len, char& v) ...@@ -125,8 +127,9 @@ int TranslateSQLType(int stp, int prec, int& len, char& v)
break; break;
case SQL_NUMERIC: // 2 case SQL_NUMERIC: // 2
case SQL_DECIMAL: // 3 case SQL_DECIMAL: // 3
type = (prec || len > 20) ? TYPE_FLOAT // type = (prec || len > 20) ? TYPE_DOUBLE
: (len > 10) ? TYPE_BIGINT : TYPE_INT; // : (len > 10) ? TYPE_BIGINT : TYPE_INT;
type = TYPE_DECIM;
break; break;
case SQL_INTEGER: // 4 case SQL_INTEGER: // 4
type = TYPE_INT; type = TYPE_INT;
...@@ -141,7 +144,7 @@ int TranslateSQLType(int stp, int prec, int& len, char& v) ...@@ -141,7 +144,7 @@ int TranslateSQLType(int stp, int prec, int& len, char& v)
case SQL_FLOAT: // 6 case SQL_FLOAT: // 6
case SQL_REAL: // 7 case SQL_REAL: // 7
case SQL_DOUBLE: // 8 case SQL_DOUBLE: // 8
type = TYPE_FLOAT; type = TYPE_DOUBLE;
break; break;
case SQL_DATETIME: // 9 case SQL_DATETIME: // 9
// case SQL_DATE: // 9 // case SQL_DATE: // 9
...@@ -312,9 +315,9 @@ PQRYRES ODBCColumns(PGLOBAL g, char *dsn, char *db, char *table, ...@@ -312,9 +315,9 @@ PQRYRES ODBCColumns(PGLOBAL g, char *dsn, char *db, char *table,
} else if (!maxres) } else if (!maxres)
maxres = 20000; maxres = 20000;
// n = ocp->GetMaxValue(SQL_MAX_QUALIFIER_NAME_LEN); // n = ocp->GetMaxValue(SQL_MAX_CATALOG_NAME_LEN);
// length[0] = (n) ? (n + 1) : 0; // length[0] = (n) ? (n + 1) : 0;
// n = ocp->GetMaxValue(SQL_MAX_USER_NAME_LEN); // n = ocp->GetMaxValue(SQL_MAX_SCHEMA_NAME_LEN);
// length[1] = (n) ? (n + 1) : 0; // length[1] = (n) ? (n + 1) : 0;
// n = ocp->GetMaxValue(SQL_MAX_TABLE_NAME_LEN); // n = ocp->GetMaxValue(SQL_MAX_TABLE_NAME_LEN);
// length[2] = (n) ? (n + 1) : 0; // length[2] = (n) ? (n + 1) : 0;
...@@ -425,7 +428,7 @@ PQRYRES MyODBCCols(PGLOBAL g, char *dsn, char *tab, bool info) ...@@ -425,7 +428,7 @@ PQRYRES MyODBCCols(PGLOBAL g, char *dsn, char *tab, bool info)
/************************************************************************/ /************************************************************************/
/* Keep only the info used by ha_connect::pre_create. */ /* Keep only the info used by ha_connect::pre_create. */
/************************************************************************/ /************************************************************************/
qrp->Colresp = qrp->Colresp->Next->Next; // Skip Owner and Table names qrp->Colresp = qrp->Colresp->Next->Next; // Skip Schema and Table names
crpt = qrp->Colresp->Next; // SQL type crpt = qrp->Colresp->Next; // SQL type
crpl = crpt->Next->Next; // Length crpl = crpt->Next->Next; // Length
...@@ -440,7 +443,7 @@ PQRYRES MyODBCCols(PGLOBAL g, char *dsn, char *tab, bool info) ...@@ -440,7 +443,7 @@ PQRYRES MyODBCCols(PGLOBAL g, char *dsn, char *tab, bool info)
crpt->Kdata->SetValue(type, i); crpt->Kdata->SetValue(type, i);
// Some data sources do not count prec in length // Some data sources do not count prec in length
if (type == TYPE_FLOAT) if (type == TYPE_DOUBLE)
len += (prec + 2); // To be safe len += (prec + 2); // To be safe
// Could have been changed for blobs or numeric // Could have been changed for blobs or numeric
...@@ -588,9 +591,9 @@ PQRYRES ODBCTables(PGLOBAL g, char *dsn, char *db, char *tabpat, ...@@ -588,9 +591,9 @@ PQRYRES ODBCTables(PGLOBAL g, char *dsn, char *db, char *tabpat,
if (!maxres) if (!maxres)
maxres = 10000; // This is completely arbitrary maxres = 10000; // This is completely arbitrary
// n = ocp->GetMaxValue(SQL_MAX_QUALIFIER_NAME_LEN); // n = ocp->GetMaxValue(SQL_MAX_CATALOG_NAME_LEN);
// length[0] = (n) ? (n + 1) : 0; // length[0] = (n) ? (n + 1) : 0;
// n = ocp->GetMaxValue(SQL_MAX_USER_NAME_LEN); // n = ocp->GetMaxValue(SQL_MAX_SCHEMA_NAME_LEN);
// length[1] = (n) ? (n + 1) : 0; // length[1] = (n) ? (n + 1) : 0;
n = ocp->GetMaxValue(SQL_MAX_TABLE_NAME_LEN); n = ocp->GetMaxValue(SQL_MAX_TABLE_NAME_LEN);
length[2] = (n) ? (n + 1) : 128; length[2] = (n) ? (n + 1) : 128;
...@@ -678,9 +681,9 @@ PQRYRES ODBCPrimaryKeys(PGLOBAL g, ODBConn *op, char *dsn, char *table) ...@@ -678,9 +681,9 @@ PQRYRES ODBCPrimaryKeys(PGLOBAL g, ODBConn *op, char *dsn, char *table)
/************************************************************************/ /************************************************************************/
n = ocp->GetMaxValue(SQL_MAX_COLUMNS_IN_TABLE); n = ocp->GetMaxValue(SQL_MAX_COLUMNS_IN_TABLE);
maxres = (n) ? (int)n : 250; maxres = (n) ? (int)n : 250;
n = ocp->GetMaxValue(SQL_MAX_QUALIFIER_NAME_LEN); n = ocp->GetMaxValue(SQL_MAX_CATALOG_NAME_LEN);
length[0] = (n) ? (n + 1) : 128; length[0] = (n) ? (n + 1) : 128;
n = ocp->GetMaxValue(SQL_MAX_USER_NAME_LEN); n = ocp->GetMaxValue(SQL_MAX_SCHEMA_NAME_LEN);
length[1] = (n) ? (n + 1) : 128; length[1] = (n) ? (n + 1) : 128;
n = ocp->GetMaxValue(SQL_MAX_TABLE_NAME_LEN); n = ocp->GetMaxValue(SQL_MAX_TABLE_NAME_LEN);
length[2] = (n) ? (n + 1) : 128; length[2] = (n) ? (n + 1) : 128;
...@@ -761,11 +764,11 @@ PQRYRES ODBCStatistics(PGLOBAL g, ODBConn *op, char *dsn, char *pat, ...@@ -761,11 +764,11 @@ PQRYRES ODBCStatistics(PGLOBAL g, ODBConn *op, char *dsn, char *pat,
/************************************************************************/ /************************************************************************/
n = 1 + ocp->GetMaxValue(SQL_MAX_COLUMNS_IN_INDEX); n = 1 + ocp->GetMaxValue(SQL_MAX_COLUMNS_IN_INDEX);
maxres = (n) ? (int)n : 32; maxres = (n) ? (int)n : 32;
n = ocp->GetMaxValue(SQL_MAX_USER_NAME_LEN); n = ocp->GetMaxValue(SQL_MAX_SCHEMA_NAME_LEN);
length[1] = (n) ? (n + 1) : 128; length[1] = (n) ? (n + 1) : 128;
n = ocp->GetMaxValue(SQL_MAX_TABLE_NAME_LEN); n = ocp->GetMaxValue(SQL_MAX_TABLE_NAME_LEN);
length[2] = length[5] = (n) ? (n + 1) : 128; length[2] = length[5] = (n) ? (n + 1) : 128;
n = ocp->GetMaxValue(SQL_MAX_QUALIFIER_NAME_LEN); n = ocp->GetMaxValue(SQL_MAX_CATALOG_NAME_LEN);
length[0] = length[4] = (n) ? (n + 1) : length[2]; length[0] = length[4] = (n) ? (n + 1) : length[2];
n = ocp->GetMaxValue(SQL_MAX_COLUMN_NAME_LEN); n = ocp->GetMaxValue(SQL_MAX_COLUMN_NAME_LEN);
length[7] = (n) ? (n + 1) : 128; length[7] = (n) ? (n + 1) : 128;
...@@ -1649,34 +1652,34 @@ int ODBConn::ExecuteSQL(void) ...@@ -1649,34 +1652,34 @@ int ODBConn::ExecuteSQL(void)
bool ODBConn::BindParam(ODBCCOL *colp) bool ODBConn::BindParam(ODBCCOL *colp)
{ {
void *buf; void *buf;
UWORD n = colp->GetRank(); int buftype = colp->GetResultType();
SWORD ct, sqlt; SQLUSMALLINT n = colp->GetRank();
UDWORD len; SQLSMALLINT ct, sqlt, dec, nul;
SQLULEN colsize;
SQLLEN len;
SQLLEN *strlen = colp->GetStrLen(); SQLLEN *strlen = colp->GetStrLen();
RETCODE rc; SQLRETURN rc;
#if 0
try { try {
SWORD dec, nul; rc = SQLDescribeParam(m_hstmt, n, &sqlt, &colsize, &dec, &nul);
rc = SQLDescribeParam(m_hstmt, n, &sqlt, &len, &dec, &nul);
if (!Check(rc)) if (!Check(rc))
ThrowDBX(rc, m_hstmt); ThrowDBX(rc, "SQLDescribeParam", m_hstmt);
} catch(DBX *x) { } catch(DBX *x) {
strcpy(m_G->Message, x->GetErrorMessage(0)); strcpy(m_G->Message, x->GetErrorMessage(0));
colsize = colp->GetPrecision();
sqlt = GetSQLType(buftype);
} // end try/catch } // end try/catch
#endif // 0
buf = colp->GetBuffer(0); buf = colp->GetBuffer(0);
len = IsTypeNum(colp->GetResultType()) ? 0 : colp->GetBuflen(); len = IsTypeChar(buftype) ? colp->GetBuflen() : 0;
ct = GetSQLCType(colp->GetResultType()); ct = GetSQLCType(buftype);
sqlt = GetSQLType(colp->GetResultType()); *strlen = IsTypeChar(buftype) ? SQL_NTS : 0;
*strlen = IsTypeNum(colp->GetResultType()) ? 0 : SQL_NTS;
try { try {
rc = SQLBindParameter(m_hstmt, n, SQL_PARAM_INPUT, ct, sqlt, rc = SQLBindParameter(m_hstmt, n, SQL_PARAM_INPUT, ct, sqlt,
len, 0, buf, 0, strlen); colsize, dec, buf, len, strlen);
if (!Check(rc)) if (!Check(rc))
ThrowDBX(rc, "SQLBindParameter", m_hstmt); ThrowDBX(rc, "SQLBindParameter", m_hstmt);
...@@ -2020,7 +2023,6 @@ bool ODBConn::GetDrivers(PQRYRES qrp) ...@@ -2020,7 +2023,6 @@ bool ODBConn::GetDrivers(PQRYRES qrp)
return rv; return rv;
} // end of GetDrivers } // end of GetDrivers
/***********************************************************************/ /***********************************************************************/
/* A helper class to split an optionally qualified table name into */ /* A helper class to split an optionally qualified table name into */
/* components. */ /* components. */
...@@ -2039,7 +2041,7 @@ class SQLQualifiedName ...@@ -2039,7 +2041,7 @@ class SQLQualifiedName
{ {
S->str= str; S->str= str;
S->length= length; S->length= length;
} // eend of lex_string_set } // end of lex_string_set
void lex_string_shorten_down(MYSQL_LEX_STRING *S, size_t offs) void lex_string_shorten_down(MYSQL_LEX_STRING *S, size_t offs)
{ {
...@@ -2228,7 +2230,7 @@ int ODBConn::GetCatInfo(CATPARM *cap) ...@@ -2228,7 +2230,7 @@ int ODBConn::GetCatInfo(CATPARM *cap)
((STRBLK*)crp->Kdata)->SetSorted(true); ((STRBLK*)crp->Kdata)->SetSorted(true);
} // endif len } // endif len
pval[n] = AllocateValue(g, crp->Type, len, 0); pval[n] = AllocateValue(g, crp->Type, len);
buffer = pval[n]->GetTo_Val(); buffer = pval[n]->GetTo_Val();
vl = vlen + n; vl = vlen + n;
......
...@@ -1523,7 +1523,7 @@ void PlugPutOut(PGLOBAL g, FILE *f, short t, void *v, uint n) ...@@ -1523,7 +1523,7 @@ void PlugPutOut(PGLOBAL g, FILE *f, short t, void *v, uint n)
fprintf(f, "%s%s\n", m, (PSZ)v); fprintf(f, "%s%s\n", m, (PSZ)v);
break; break;
case TYPE_FLOAT: case TYPE_DOUBLE:
fprintf(f, "%s%lf\n", m, *(double *)v); fprintf(f, "%s%lf\n", m, *(double *)v);
break; break;
......
...@@ -38,13 +38,13 @@ char *GetMsgid(int id) ...@@ -38,13 +38,13 @@ char *GetMsgid(int id)
case IDS_13: p = "%s: cl de connexion invalide %d"; break; case IDS_13: p = "%s: cl de connexion invalide %d"; break;
case IDS_14: p = "SafeDB: %s rc=%d"; break; case IDS_14: p = "SafeDB: %s rc=%d"; break;
case IDS_15: p = "Mauvaise Dll de communication appele par le moteur %s"; break; case IDS_15: p = "Mauvaise Dll de communication appele par le moteur %s"; break;
case IDS_TAB_01: p = "Qualificateur"; break; case IDS_TAB_01: p = "Catalogue"; break;
case IDS_TAB_02: p = "Propritaire"; break; case IDS_TAB_02: p = "Schma"; break;
case IDS_TAB_03: p = "Nom"; break; case IDS_TAB_03: p = "Nom"; break;
case IDS_TAB_04: p = "Type"; break; case IDS_TAB_04: p = "Type"; break;
case IDS_TAB_05: p = "Remarque"; break; case IDS_TAB_05: p = "Remarque"; break;
case IDS_COL_01: p = "Qualif_Table"; break; case IDS_COL_01: p = "Cat_Table"; break;
case IDS_COL_02: p = "Prop_Tabl"; break; case IDS_COL_02: p = "Schem_Table"; break;
case IDS_COL_03: p = "Nom_Table"; break; case IDS_COL_03: p = "Nom_Table"; break;
case IDS_COL_04: p = "Nom_Colonne"; break; case IDS_COL_04: p = "Nom_Colonne"; break;
case IDS_COL_05: p = "Type_Donnes"; break; case IDS_COL_05: p = "Type_Donnes"; break;
...@@ -70,18 +70,18 @@ char *GetMsgid(int id) ...@@ -70,18 +70,18 @@ char *GetMsgid(int id)
case IDS_INF_13: p = "Nom_Type_Local"; break; case IDS_INF_13: p = "Nom_Type_Local"; break;
case IDS_INF_14: p = "Echelle_Minimum"; break; case IDS_INF_14: p = "Echelle_Minimum"; break;
case IDS_INF_15: p = "Echelle_Maximum"; break; case IDS_INF_15: p = "Echelle_Maximum"; break;
case IDS_PKY_01: p = "Qualif_Table"; break; case IDS_PKY_01: p = "Cat_Table"; break;
case IDS_PKY_02: p = "Prop_Table"; break; case IDS_PKY_02: p = "Schem_Table"; break;
case IDS_PKY_03: p = "Nom_Table"; break; case IDS_PKY_03: p = "Nom_Table"; break;
case IDS_PKY_04: p = "Nom_Colonne"; break; case IDS_PKY_04: p = "Nom_Colonne"; break;
case IDS_PKY_05: p = "Numro_Cl"; break; case IDS_PKY_05: p = "Numro_Cl"; break;
case IDS_PKY_06: p = "Nom_Cl"; break; case IDS_PKY_06: p = "Nom_Cl"; break;
case IDS_FKY_01: p = "PKTable_Qualifier"; break; case IDS_FKY_01: p = "PKTable_Catalog"; break;
case IDS_FKY_02: p = "PKTable_Owner"; break; case IDS_FKY_02: p = "PKTable_Schema"; break;
case IDS_FKY_03: p = "PKTable_Name"; break; case IDS_FKY_03: p = "PKTable_Name"; break;
case IDS_FKY_04: p = "PKColumn_Name"; break; case IDS_FKY_04: p = "PKColumn_Name"; break;
case IDS_FKY_05: p = "FKTable_Qualifier"; break; case IDS_FKY_05: p = "FKTable_Catalog"; break;
case IDS_FKY_06: p = "FKTable_Owner"; break; case IDS_FKY_06: p = "FKTable_Schema"; break;
case IDS_FKY_07: p = "FKTable_Name"; break; case IDS_FKY_07: p = "FKTable_Name"; break;
case IDS_FKY_08: p = "FKColumn_Name"; break; case IDS_FKY_08: p = "FKColumn_Name"; break;
case IDS_FKY_09: p = "Key_Seq"; break; case IDS_FKY_09: p = "Key_Seq"; break;
...@@ -89,8 +89,8 @@ char *GetMsgid(int id) ...@@ -89,8 +89,8 @@ char *GetMsgid(int id)
case IDS_FKY_11: p = "Delete_Rule"; break; case IDS_FKY_11: p = "Delete_Rule"; break;
case IDS_FKY_12: p = "FK_Name"; break; case IDS_FKY_12: p = "FK_Name"; break;
case IDS_FKY_13: p = "PK_Name"; break; case IDS_FKY_13: p = "PK_Name"; break;
case IDS_STA_01: p = "Table_Qualifier"; break; case IDS_STA_01: p = "Table_Catalog"; break;
case IDS_STA_02: p = "Table_Owner"; break; case IDS_STA_02: p = "Table_Schema"; break;
case IDS_STA_03: p = "Table_Name"; break; case IDS_STA_03: p = "Table_Name"; break;
case IDS_STA_04: p = "Non_Unique"; break; case IDS_STA_04: p = "Non_Unique"; break;
case IDS_STA_05: p = "Index_Qualifier"; break; case IDS_STA_05: p = "Index_Qualifier"; break;
...@@ -162,18 +162,18 @@ char *GetMsgid(int id) ...@@ -162,18 +162,18 @@ char *GetMsgid(int id)
case IDS_INF_13: p = "Local_Type_Name"; break; case IDS_INF_13: p = "Local_Type_Name"; break;
case IDS_INF_14: p = "Minimum_Scale"; break; case IDS_INF_14: p = "Minimum_Scale"; break;
case IDS_INF_15: p = "Maximum_Scale"; break; case IDS_INF_15: p = "Maximum_Scale"; break;
case IDS_PKY_01: p = "Table_Qualifier"; break; case IDS_PKY_01: p = "Table_Catalog"; break;
case IDS_PKY_02: p = "Table_Owner"; break; case IDS_PKY_02: p = "Table_Schema"; break;
case IDS_PKY_03: p = "Table_Name"; break; case IDS_PKY_03: p = "Table_Name"; break;
case IDS_PKY_04: p = "Column_Name"; break; case IDS_PKY_04: p = "Column_Name"; break;
case IDS_PKY_05: p = "Key_Seq"; break; case IDS_PKY_05: p = "Key_Seq"; break;
case IDS_PKY_06: p = "Pk_Name"; break; case IDS_PKY_06: p = "Pk_Name"; break;
case IDS_FKY_01: p = "PKTable_Qualifier"; break; case IDS_FKY_01: p = "PKTable_Catalog"; break;
case IDS_FKY_02: p = "PKTable_Owner"; break; case IDS_FKY_02: p = "PKTable_Schema"; break;
case IDS_FKY_03: p = "PKTable_Name"; break; case IDS_FKY_03: p = "PKTable_Name"; break;
case IDS_FKY_04: p = "PKColumn_Name"; break; case IDS_FKY_04: p = "PKColumn_Name"; break;
case IDS_FKY_05: p = "FKTable_Qualifier"; break; case IDS_FKY_05: p = "FKTable_Catalog"; break;
case IDS_FKY_06: p = "FKTable_Owner"; break; case IDS_FKY_06: p = "FKTable_Schema"; break;
case IDS_FKY_07: p = "FKTable_Name"; break; case IDS_FKY_07: p = "FKTable_Name"; break;
case IDS_FKY_08: p = "FKColumn_Name"; break; case IDS_FKY_08: p = "FKColumn_Name"; break;
case IDS_FKY_09: p = "Key_Seq"; break; case IDS_FKY_09: p = "Key_Seq"; break;
...@@ -181,8 +181,8 @@ char *GetMsgid(int id) ...@@ -181,8 +181,8 @@ char *GetMsgid(int id)
case IDS_FKY_11: p = "Delete_Rule"; break; case IDS_FKY_11: p = "Delete_Rule"; break;
case IDS_FKY_12: p = "FK_Name"; break; case IDS_FKY_12: p = "FK_Name"; break;
case IDS_FKY_13: p = "PK_Name"; break; case IDS_FKY_13: p = "PK_Name"; break;
case IDS_STA_01: p = "Table_Qualifier"; break; case IDS_STA_01: p = "Table_Catalog"; break;
case IDS_STA_02: p = "Table_Owner"; break; case IDS_STA_02: p = "Table_Schema"; break;
case IDS_STA_03: p = "Table_Name"; break; case IDS_STA_03: p = "Table_Name"; break;
case IDS_STA_04: p = "Non_Unique"; break; case IDS_STA_04: p = "Non_Unique"; break;
case IDS_STA_05: p = "Index_Qualifier"; break; case IDS_STA_05: p = "Index_Qualifier"; break;
......
...@@ -73,7 +73,7 @@ RELDEF::RELDEF(void) ...@@ -73,7 +73,7 @@ RELDEF::RELDEF(void)
/***********************************************************************/ /***********************************************************************/
TABDEF::TABDEF(void) TABDEF::TABDEF(void)
{ {
Owner = NULL; Schema = NULL;
Desc = NULL; Desc = NULL;
Catfunc = FNC_NO; Catfunc = FNC_NO;
Card = 0; Card = 0;
...@@ -338,9 +338,9 @@ COLCRT::COLCRT(PSZ name) ...@@ -338,9 +338,9 @@ COLCRT::COLCRT(PSZ name)
Fmt = NULL; Fmt = NULL;
Offset = -1; Offset = -1;
Long = -1; Long = -1;
//Freq = -1; Precision = -1;
Key = -1; Key = -1;
Prec = -1; Scale = -1;
Opt = -1; Opt = -1;
DataType = '*'; DataType = '*';
} // end of COLCRT constructor for table creation } // end of COLCRT constructor for table creation
...@@ -354,9 +354,9 @@ COLCRT::COLCRT(void) ...@@ -354,9 +354,9 @@ COLCRT::COLCRT(void)
Fmt = NULL; Fmt = NULL;
Offset = 0; Offset = 0;
Long = 0; Long = 0;
//Freq = 0; Precision = 0;
Key = 0; Key = 0;
Prec = 0; Scale = 0;
Opt = 0; Opt = 0;
DataType = '*'; DataType = '*';
} // end of COLCRT constructor for table & view definition } // end of COLCRT constructor for table & view definition
...@@ -394,8 +394,10 @@ int COLDEF::Define(PGLOBAL g, void *memp, PCOLINFO cfp, int poff) ...@@ -394,8 +394,10 @@ int COLDEF::Define(PGLOBAL g, void *memp, PCOLINFO cfp, int poff)
strcpy(F.Type, GetFormatType(Buf_Type)); strcpy(F.Type, GetFormatType(Buf_Type));
F.Length = cfp->Length; F.Length = cfp->Length;
F.Prec = cfp->Prec; F.Prec = cfp->Scale;
Offset = (cfp->Offset < 0) ? poff : cfp->Offset; Offset = (cfp->Offset < 0) ? poff : cfp->Offset;
Precision = cfp->Precision;
Scale = cfp->Scale;
Long = cfp->Length; Long = cfp->Length;
Opt = cfp->Opt; Opt = cfp->Opt;
Key = cfp->Key; Key = cfp->Key;
......
...@@ -87,7 +87,7 @@ class DllExport TABDEF : public RELDEF { /* Logical table descriptor */ ...@@ -87,7 +87,7 @@ class DllExport TABDEF : public RELDEF { /* Logical table descriptor */
protected: protected:
// Members // Members
PSZ Owner; /* Table owner (for ODBC) */ PSZ Schema; /* Table schema (for ODBC) */
PSZ Desc; /* Table description */ PSZ Desc; /* Table description */
uint Catfunc; /* Catalog function ID */ uint Catfunc; /* Catalog function ID */
int Card; /* (max) number of rows in table */ int Card; /* (max) number of rows in table */
...@@ -149,6 +149,7 @@ class DllExport COLCRT : public BLOCK { /* Column description block ...@@ -149,6 +149,7 @@ class DllExport COLCRT : public BLOCK { /* Column description block
PSZ GetFmt(void) {return Fmt;} PSZ GetFmt(void) {return Fmt;}
int GetOpt(void) {return Opt;} int GetOpt(void) {return Opt;}
int GetLong(void) {return Long;} int GetLong(void) {return Long;}
int GetPrecision(void) {return Precision;}
int GetOffset(void) {return Offset;} int GetOffset(void) {return Offset;}
void SetOffset(int offset) {Offset = offset;} void SetOffset(int offset) {Offset = offset;}
...@@ -161,7 +162,8 @@ class DllExport COLCRT : public BLOCK { /* Column description block ...@@ -161,7 +162,8 @@ class DllExport COLCRT : public BLOCK { /* Column description block
int Offset; /* Offset of field within record */ int Offset; /* Offset of field within record */
int Long; /* Length of field in file record (!BIN) */ int Long; /* Length of field in file record (!BIN) */
int Key; /* Key (greater than 1 if multiple) */ int Key; /* Key (greater than 1 if multiple) */
int Prec; /* Precision for float values */ int Precision; /* Logical column length */
int Scale; /* Decimals for float/decimal values */
int Opt; /* 0:Not 1:clustered 2:sorted-asc 3:desc */ int Opt; /* 0:Not 1:clustered 2:sorted-asc 3:desc */
char DataType; /* Internal data type (C, N, F, T) */ char DataType; /* Internal data type (C, N, F, T) */
}; // end of COLCRT }; // end of COLCRT
......
...@@ -30,7 +30,7 @@ XTAB::XTAB(LPCSTR name, LPCSTR srcdef) : Name(name) ...@@ -30,7 +30,7 @@ XTAB::XTAB(LPCSTR name, LPCSTR srcdef) : Name(name)
Next = NULL; Next = NULL;
To_Tdb = NULL; To_Tdb = NULL;
Srcdef = srcdef; Srcdef = srcdef;
Creator = NULL; Schema = NULL;
Qualifier = NULL; Qualifier = NULL;
#ifdef DEBTRACE #ifdef DEBTRACE
...@@ -46,7 +46,7 @@ XTAB::XTAB(PTABLE tp) : Name(tp->Name) ...@@ -46,7 +46,7 @@ XTAB::XTAB(PTABLE tp) : Name(tp->Name)
Next = NULL; Next = NULL;
To_Tdb = NULL; To_Tdb = NULL;
Srcdef = tp->Srcdef; Srcdef = tp->Srcdef;
Creator = tp->Creator; Schema = tp->Schema;
Qualifier = tp->Qualifier; Qualifier = tp->Qualifier;
#ifdef DEBTRACE #ifdef DEBTRACE
...@@ -83,7 +83,7 @@ void XTAB::Print(PGLOBAL g, FILE *f, uint n) ...@@ -83,7 +83,7 @@ void XTAB::Print(PGLOBAL g, FILE *f, uint n)
for (PTABLE tp = this; tp; tp = tp->Next) { for (PTABLE tp = this; tp; tp = tp->Next) {
fprintf(f, "%sTABLE: %s.%s %s\n", fprintf(f, "%sTABLE: %s.%s %s\n",
m, SVP(tp->Creator), tp->Name, SVP(tp->Srcdef)); m, SVP(tp->Schema), tp->Name, SVP(tp->Srcdef));
PlugPutOut(g, f, TYPE_TDB, tp->To_Tdb, n + 2); PlugPutOut(g, f, TYPE_TDB, tp->To_Tdb, n + 2);
} /* endfor tp */ } /* endfor tp */
...@@ -101,7 +101,7 @@ void XTAB::Print(PGLOBAL g, char *ps, uint z) ...@@ -101,7 +101,7 @@ void XTAB::Print(PGLOBAL g, char *ps, uint z)
for (PTABLE tp = this; tp && n > 0; tp = tp->Next) { for (PTABLE tp = this; tp && n > 0; tp = tp->Next) {
i = sprintf(buf, "TABLE: %s.%s %s To_Tdb=%p ", i = sprintf(buf, "TABLE: %s.%s %s To_Tdb=%p ",
SVP(tp->Creator), tp->Name, SVP(tp->Srcdef), tp->To_Tdb); SVP(tp->Schema), tp->Name, SVP(tp->Srcdef), tp->To_Tdb);
strncat(ps, buf, n); strncat(ps, buf, n);
n -= i; n -= i;
} // endif tp } // endif tp
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
/***********************************************************************/ /***********************************************************************/
/* Definition of class XTAB with all its method functions. */ /* Definition of class XTAB with all its method functions. */
/***********************************************************************/ /***********************************************************************/
class DllExport XTAB: public BLOCK { // Table Name-Owner-Srcdef block. class DllExport XTAB: public BLOCK { // Table Name-Schema-Srcdef block.
friend class TDBPRX; friend class TDBPRX;
friend class TDBTBM; friend class TDBTBM;
public: public:
...@@ -28,12 +28,12 @@ class DllExport XTAB: public BLOCK { // Table Name-Owner-Srcdef block. ...@@ -28,12 +28,12 @@ class DllExport XTAB: public BLOCK { // Table Name-Owner-Srcdef block.
PTDB GetTo_Tdb(void) {return To_Tdb;} PTDB GetTo_Tdb(void) {return To_Tdb;}
LPCSTR GetName(void) {return Name;} LPCSTR GetName(void) {return Name;}
LPCSTR GetSrc(void) {return Srcdef;} LPCSTR GetSrc(void) {return Srcdef;}
LPCSTR GetCreator(void) {return Creator;} LPCSTR GetSchema(void) {return Schema;}
LPCSTR GetQualifier(void) {return Qualifier;} LPCSTR GetQualifier(void) {return Qualifier;}
void SetTo_Tdb(PTDB tdbp) {To_Tdb = tdbp;} void SetTo_Tdb(PTDB tdbp) {To_Tdb = tdbp;}
void SetName(LPCSTR name) {Name = name;} void SetName(LPCSTR name) {Name = name;}
void SetSrc(LPCSTR srcdef) {Srcdef = srcdef;} void SetSrc(LPCSTR srcdef) {Srcdef = srcdef;}
void SetCreator(LPCSTR crname) {Creator = crname;} void SetSchema(LPCSTR schname) {Schema = schname;}
void SetQualifier(LPCSTR qname) {Qualifier = qname;} void SetQualifier(LPCSTR qname) {Qualifier = qname;}
// Methods // Methods
...@@ -47,7 +47,7 @@ class DllExport XTAB: public BLOCK { // Table Name-Owner-Srcdef block. ...@@ -47,7 +47,7 @@ class DllExport XTAB: public BLOCK { // Table Name-Owner-Srcdef block.
PTDB To_Tdb; // Points to Table description Block PTDB To_Tdb; // Points to Table description Block
LPCSTR Name; // Table name LPCSTR Name; // Table name
LPCSTR Srcdef; // Table Source definition LPCSTR Srcdef; // Table Source definition
LPCSTR Creator; // Creator name LPCSTR Schema; // Schema name
LPCSTR Qualifier; // Qualifier name LPCSTR Qualifier; // Qualifier name
}; // end of class XTAB }; // end of class XTAB
...@@ -68,7 +68,7 @@ class DllExport COLUMN: public XOBJECT { // Column Name/Qualifier block. ...@@ -68,7 +68,7 @@ class DllExport COLUMN: public XOBJECT { // Column Name/Qualifier block.
virtual int GetResultType(void) {assert(false); return TYPE_VOID;} virtual int GetResultType(void) {assert(false); return TYPE_VOID;}
virtual int GetLength(void) {assert(false); return 0;} virtual int GetLength(void) {assert(false); return 0;}
virtual int GetLengthEx(void) {assert(false); return 0;} virtual int GetLengthEx(void) {assert(false); return 0;}
virtual int GetPrecision() {assert(false); return 0;}; virtual int GetScale() {assert(false); return 0;};
LPCSTR GetName(void) {return Name;} LPCSTR GetName(void) {return Name;}
LPCSTR GetQualifier(void) {return Qualifier;} LPCSTR GetQualifier(void) {return Qualifier;}
PTABLE GetTo_Table(void) {return To_Table;} PTABLE GetTo_Table(void) {return To_Table;}
......
...@@ -499,7 +499,10 @@ int TDBDOS::MakeIndex(PGLOBAL g, PIXDEF pxdf, bool add) ...@@ -499,7 +499,10 @@ int TDBDOS::MakeIndex(PGLOBAL g, PIXDEF pxdf, bool add)
if (!(colp = ColDB(g, kdp->GetName(), 0))) { if (!(colp = ColDB(g, kdp->GetName(), 0))) {
sprintf(g->Message, MSG(INDX_COL_NOTIN), kdp->GetName(), Name); sprintf(g->Message, MSG(INDX_COL_NOTIN), kdp->GetName(), Name);
goto err; goto err;
} // endif colp } else if (colp->GetResultType() == TYPE_DECIM) {
sprintf(g->Message, "Decimal columns are not indexable yet");
goto err;
} // endif Type
colp->InitValue(g); colp->InitValue(g);
n = max(n, xdp->GetNparts()); n = max(n, xdp->GetNparts());
...@@ -944,7 +947,7 @@ DOSCOL::DOSCOL(PGLOBAL g, PCOLDEF cdp, PTDB tp, PCOL cp, int i, PSZ am) ...@@ -944,7 +947,7 @@ DOSCOL::DOSCOL(PGLOBAL g, PCOLDEF cdp, PTDB tp, PCOL cp, int i, PSZ am)
} // endswitch p } // endswitch p
// Set number of decimal digits // Set number of decimal digits
Dcm = (*p) ? atoi(p) : GetPrecision(); Dcm = (*p) ? atoi(p) : GetScale();
} // endif fmt } // endif fmt
if (trace) if (trace)
...@@ -1006,10 +1009,10 @@ bool DOSCOL::SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check) ...@@ -1006,10 +1009,10 @@ bool DOSCOL::SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check)
if (GetDomain() || ((DTVAL *)value)->IsFormatted()) if (GetDomain() || ((DTVAL *)value)->IsFormatted())
goto newval; // This will make a new value; goto newval; // This will make a new value;
} else if (Buf_Type == TYPE_FLOAT) } else if (Buf_Type == TYPE_DOUBLE)
// Float values must be written with the correct (column) precision // Float values must be written with the correct (column) precision
// Note: maybe this should be forced by ShowValue instead of this ? // Note: maybe this should be forced by ShowValue instead of this ?
value->SetPrec(GetPrecision()); value->SetPrec(GetScale());
Value = value; // Directly access the external value Value = value; // Directly access the external value
} else { } else {
...@@ -1094,7 +1097,7 @@ void DOSCOL::ReadColumn(PGLOBAL g) ...@@ -1094,7 +1097,7 @@ void DOSCOL::ReadColumn(PGLOBAL g)
} // endif SetValue_char } // endif SetValue_char
break; break;
case TYPE_FLOAT: case TYPE_DOUBLE:
Value->SetValue_char(p, field); Value->SetValue_char(p, field);
dval = Value->GetFloatValue(); dval = Value->GetFloatValue();
...@@ -1207,7 +1210,7 @@ void DOSCOL::WriteColumn(PGLOBAL g) ...@@ -1207,7 +1210,7 @@ void DOSCOL::WriteColumn(PGLOBAL g)
len = sprintf(Buf, fmt, field - i, Value->GetTinyValue()); len = sprintf(Buf, fmt, field - i, Value->GetTinyValue());
break; break;
case TYPE_FLOAT: case TYPE_DOUBLE:
strcpy(fmt, (Ldz) ? "%0*.*lf" : "%*.*lf"); strcpy(fmt, (Ldz) ? "%0*.*lf" : "%*.*lf");
sprintf(Buf, fmt, field + ((Nod && Dcm) ? 1 : 0), sprintf(Buf, fmt, field + ((Nod && Dcm) ? 1 : 0),
Dcm, Value->GetFloatValue()); Dcm, Value->GetFloatValue());
......
...@@ -72,7 +72,7 @@ extern "C" int trace; ...@@ -72,7 +72,7 @@ extern "C" int trace;
/* CSVColumns: constructs the result blocks containing the description */ /* CSVColumns: constructs the result blocks containing the description */
/* of all the columns of a CSV file that will be retrieved by #GetData.*/ /* 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 */ /* Note: the algorithm to set the type is based on the internal values */
/* of types (TYPE_STRING < TYPE_FLOAT < TYPE_INT) (1 < 2 < 7). */ /* of types (TYPE_STRING < TYPE_DOUBLE < TYPE_INT) (1 < 2 < 7). */
/* If these values are changed, this will have to be revisited. */ /* If these values are changed, this will have to be revisited. */
/***********************************************************************/ /***********************************************************************/
PQRYRES CSVColumns(PGLOBAL g, const char *fn, char sep, char q, PQRYRES CSVColumns(PGLOBAL g, const char *fn, char sep, char q,
...@@ -230,9 +230,9 @@ PQRYRES CSVColumns(PGLOBAL g, const char *fn, char sep, char q, ...@@ -230,9 +230,9 @@ PQRYRES CSVColumns(PGLOBAL g, const char *fn, char sep, char q,
if (n) { if (n) {
len[i] = max(len[i], n); len[i] = max(len[i], n);
type = (digit || (dec && n == 1)) ? TYPE_STRING type = (digit || (dec && n == 1)) ? TYPE_STRING
: (dec) ? TYPE_FLOAT : TYPE_INT; : (dec) ? TYPE_DOUBLE : TYPE_INT;
typ[i] = min(type, typ[i]); typ[i] = min(type, typ[i]);
prc[i] = max((typ[i] == TYPE_FLOAT) ? (dec - 1) : 0, prc[i]); prc[i] = max((typ[i] == TYPE_DOUBLE) ? (dec - 1) : 0, prc[i]);
} // endif n } // endif n
i++; i++;
...@@ -310,9 +310,9 @@ PQRYRES CSVColumns(PGLOBAL g, const char *fn, char sep, char q, ...@@ -310,9 +310,9 @@ PQRYRES CSVColumns(PGLOBAL g, const char *fn, char sep, char q,
if (n) { if (n) {
len[i] = max(len[i], n); len[i] = max(len[i], n);
type = (digit || n == 0 || (dec && n == 1)) ? TYPE_STRING type = (digit || n == 0 || (dec && n == 1)) ? TYPE_STRING
: (dec) ? TYPE_FLOAT : TYPE_INT; : (dec) ? TYPE_DOUBLE : TYPE_INT;
typ[i] = min(type, typ[i]); typ[i] = min(type, typ[i]);
prc[i] = max((typ[i] == TYPE_FLOAT) ? (dec - 1) : 0, prc[i]); prc[i] = max((typ[i] == TYPE_DOUBLE) ? (dec - 1) : 0, prc[i]);
} // endif n } // endif n
imax = max(imax, i+1); imax = max(imax, i+1);
......
...@@ -1117,7 +1117,7 @@ MYSQLCOL::MYSQLCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am) ...@@ -1117,7 +1117,7 @@ MYSQLCOL::MYSQLCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am)
} // endif cprec } // endif cprec
// Set additional MySQL access method information for column. // Set additional MySQL access method information for column.
Long = cdp->GetLong(); Precision = Long = cdp->GetLong();
Bind = NULL; Bind = NULL;
To_Val = NULL; To_Val = NULL;
Slen = 0; Slen = 0;
...@@ -1136,7 +1136,7 @@ MYSQLCOL::MYSQLCOL(MYSQL_FIELD *fld, PTDB tdbp, int i, PSZ am) ...@@ -1136,7 +1136,7 @@ MYSQLCOL::MYSQLCOL(MYSQL_FIELD *fld, PTDB tdbp, int i, PSZ am)
{ {
Name = fld->name; Name = fld->name;
Opt = 0; Opt = 0;
Long = fld->length; Precision = Long = fld->length;
Buf_Type = MYSQLtoPLG(fld->type); Buf_Type = MYSQLtoPLG(fld->type);
strcpy(Format.Type, GetFormatType(Buf_Type)); strcpy(Format.Type, GetFormatType(Buf_Type));
Format.Length = Long; Format.Length = Long;
...@@ -1144,6 +1144,9 @@ MYSQLCOL::MYSQLCOL(MYSQL_FIELD *fld, PTDB tdbp, int i, PSZ am) ...@@ -1144,6 +1144,9 @@ MYSQLCOL::MYSQLCOL(MYSQL_FIELD *fld, PTDB tdbp, int i, PSZ am)
ColUse = U_P; ColUse = U_P;
Nullable = !IS_NOT_NULL(fld->flags); Nullable = !IS_NOT_NULL(fld->flags);
if (Buf_Type == TYPE_DECIM)
Precision = ((Field_new_decimal*)fld)->precision;
// Set additional MySQL access method information for column. // Set additional MySQL access method information for column.
Bind = NULL; Bind = NULL;
To_Val = NULL; To_Val = NULL;
...@@ -1202,10 +1205,10 @@ bool MYSQLCOL::SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check) ...@@ -1202,10 +1205,10 @@ bool MYSQLCOL::SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check)
if (GetDomain() || ((DTVAL *)value)->IsFormatted()) if (GetDomain() || ((DTVAL *)value)->IsFormatted())
goto newval; // This will make a new value; goto newval; // This will make a new value;
} else if (Buf_Type == TYPE_FLOAT) } else if (Buf_Type == TYPE_DOUBLE)
// Float values must be written with the correct (column) precision // Float values must be written with the correct (column) precision
// Note: maybe this should be forced by ShowValue instead of this ? // Note: maybe this should be forced by ShowValue instead of this ?
value->SetPrec(GetPrecision()); value->SetPrec(GetScale());
Value = value; // Directly access the external value Value = value; // Directly access the external value
} else { } else {
......
...@@ -90,7 +90,7 @@ extern int num_read, num_there, num_eq[2]; // Statistics ...@@ -90,7 +90,7 @@ extern int num_read, num_there, num_eq[2]; // Statistics
/***********************************************************************/ /***********************************************************************/
ODBCDEF::ODBCDEF(void) ODBCDEF::ODBCDEF(void)
{ {
Connect = Tabname = Tabowner = Tabqual = Srcdef = Qchar = Qrystr = NULL; Connect= Tabname= Tabschema= Tabcat= Srcdef= Qchar= Qrystr= Sep= NULL;
Catver = Options = Quoted = Maxerr = Maxres = 0; Catver = Options = Quoted = Maxerr = Maxres = 0;
Xsrc = false; Xsrc = false;
} // end of ODBCDEF constructor } // end of ODBCDEF constructor
...@@ -104,11 +104,13 @@ bool ODBCDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff) ...@@ -104,11 +104,13 @@ bool ODBCDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
Tabname = Cat->GetStringCatInfo(g, "Name", Tabname = Cat->GetStringCatInfo(g, "Name",
(Catfunc & (FNC_TABLE | FNC_COL)) ? NULL : Name); (Catfunc & (FNC_TABLE | FNC_COL)) ? NULL : Name);
Tabname = Cat->GetStringCatInfo(g, "Tabname", Tabname); Tabname = Cat->GetStringCatInfo(g, "Tabname", Tabname);
//Tabowner = Cat->GetStringCatInfo(g, "Owner", NULL); Tabschema = Cat->GetStringCatInfo(g, "Dbname", NULL);
Tabowner = Cat->GetStringCatInfo(g, "Dbname", NULL); Tabschema = Cat->GetStringCatInfo(g, "Schema", Tabschema);
Tabqual = Cat->GetStringCatInfo(g, "Qualifier", NULL); Tabcat = Cat->GetStringCatInfo(g, "Qualifier", NULL);
Tabcat = Cat->GetStringCatInfo(g, "Catalog", Tabcat);
Srcdef = Cat->GetStringCatInfo(g, "Srcdef", NULL); Srcdef = Cat->GetStringCatInfo(g, "Srcdef", NULL);
Qrystr = Cat->GetStringCatInfo(g, "Query_String", "?"); Qrystr = Cat->GetStringCatInfo(g, "Query_String", "?");
Sep = Cat->GetStringCatInfo(g, "Separator", NULL);
Catver = Cat->GetIntCatInfo("Catver", 2); Catver = Cat->GetIntCatInfo("Catver", 2);
Xsrc = Cat->GetBoolCatInfo("Execsrc", FALSE); Xsrc = Cat->GetBoolCatInfo("Execsrc", FALSE);
Maxerr = Cat->GetIntCatInfo("Maxerr", 0); Maxerr = Cat->GetIntCatInfo("Maxerr", 0);
...@@ -170,10 +172,11 @@ TDBODBC::TDBODBC(PODEF tdp) : TDBASE(tdp) ...@@ -170,10 +172,11 @@ TDBODBC::TDBODBC(PODEF tdp) : TDBASE(tdp)
if (tdp) { if (tdp) {
Connect = tdp->Connect; Connect = tdp->Connect;
TableName = tdp->Tabname; TableName = tdp->Tabname;
Owner = tdp->Tabowner; Schema = tdp->Tabschema;
Qualifier = tdp->Tabqual; Catalog = tdp->Tabcat;
Srcdef = tdp->Srcdef; Srcdef = tdp->Srcdef;
Qrystr = tdp->Qrystr; Qrystr = tdp->Qrystr;
Sep = tdp->GetSep();
Options = tdp->Options; Options = tdp->Options;
Quoted = max(0, tdp->GetQuoted()); Quoted = max(0, tdp->GetQuoted());
Rows = tdp->GetElemt(); Rows = tdp->GetElemt();
...@@ -181,10 +184,11 @@ TDBODBC::TDBODBC(PODEF tdp) : TDBASE(tdp) ...@@ -181,10 +184,11 @@ TDBODBC::TDBODBC(PODEF tdp) : TDBASE(tdp)
} else { } else {
Connect = NULL; Connect = NULL;
TableName = NULL; TableName = NULL;
Owner = NULL; Schema = NULL;
Qualifier = NULL; Catalog = NULL;
Srcdef = NULL; Srcdef = NULL;
Qrystr = NULL; Qrystr = NULL;
Sep = 0;
Options = 0; Options = 0;
Quoted = 0; Quoted = 0;
Rows = 0; Rows = 0;
...@@ -211,8 +215,8 @@ TDBODBC::TDBODBC(PTDBODBC tdbp) : TDBASE(tdbp) ...@@ -211,8 +215,8 @@ TDBODBC::TDBODBC(PTDBODBC tdbp) : TDBASE(tdbp)
Cnp = tdbp->Cnp; Cnp = tdbp->Cnp;
Connect = tdbp->Connect; Connect = tdbp->Connect;
TableName = tdbp->TableName; TableName = tdbp->TableName;
Owner = tdbp->Owner; Schema = tdbp->Schema;
Qualifier = tdbp->Qualifier; Catalog = tdbp->Catalog;
Srcdef = tdbp->Srcdef; Srcdef = tdbp->Srcdef;
Qrystr = tdbp->Qrystr; Qrystr = tdbp->Qrystr;
Quote = tdbp->Quote; Quote = tdbp->Quote;
...@@ -336,7 +340,7 @@ int TDBODBC::Decode(char *txt, char *buf, size_t n) ...@@ -336,7 +340,7 @@ int TDBODBC::Decode(char *txt, char *buf, size_t n)
char *TDBODBC::MakeSQL(PGLOBAL g, bool cnt) char *TDBODBC::MakeSQL(PGLOBAL g, bool cnt)
{ {
char *colist, *tabname, *sql, buf[64]; char *colist, *tabname, *sql, buf[64];
LPCSTR ownp = NULL, qualp = NULL; LPCSTR schmp = NULL, catp = NULL;
int len, ncol = 0; int len, ncol = 0;
bool first = true; bool first = true;
PTABLE tablep = To_Table; PTABLE tablep = To_Table;
...@@ -406,37 +410,34 @@ char *TDBODBC::MakeSQL(PGLOBAL g, bool cnt) ...@@ -406,37 +410,34 @@ char *TDBODBC::MakeSQL(PGLOBAL g, bool cnt)
len = (strlen(colist) + strlen(buf) + 14); len = (strlen(colist) + strlen(buf) + 14);
len += (To_Filter ? strlen(To_Filter->Body) + 7 : 0); len += (To_Filter ? strlen(To_Filter->Body) + 7 : 0);
// if (tablep->GetQualifier()) This is used when using a table if (Catalog && *Catalog)
// qualp = tablep->GetQualifier(); from anotherPlugDB database but catp = Catalog;
// else makes no sense for ODBC.
if (Qualifier && *Qualifier)
qualp = Qualifier;
if (qualp) if (catp)
len += (strlen(qualp) + 2); len += (strlen(catp) + 2);
if (tablep->GetCreator()) if (tablep->GetSchema())
ownp = tablep->GetCreator(); schmp = tablep->GetSchema();
else if (Owner && *Owner) else if (Schema && *Schema)
ownp = Owner; schmp = Schema;
if (ownp) if (schmp)
len += (strlen(ownp) + 1); len += (strlen(schmp) + 1);
sql = (char*)PlugSubAlloc(g, NULL, len); sql = (char*)PlugSubAlloc(g, NULL, len);
strcat(strcat(strcpy(sql, "SELECT "), colist), " FROM "); strcat(strcat(strcpy(sql, "SELECT "), colist), " FROM ");
if (qualp) { if (catp) {
strcat(sql, qualp); strcat(sql, catp);
if (ownp) if (schmp)
strcat(strcat(sql, "."), ownp); strcat(strcat(sql, "."), schmp);
else else
strcat(sql, "."); strcat(sql, ".");
strcat(sql, "."); strcat(sql, ".");
} else if (ownp) } else if (schmp)
strcat(strcat(sql, ownp), "."); strcat(strcat(sql, schmp), ".");
strcat(sql, tabname); strcat(sql, tabname);
...@@ -921,7 +922,8 @@ ODBCCOL::ODBCCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am) ...@@ -921,7 +922,8 @@ ODBCCOL::ODBCCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am)
} // endif cprec } // endif cprec
// Set additional ODBC access method information for column. // Set additional ODBC access method information for column.
Long = cdp->GetLong(); //Long = cdp->GetLong();
Long = Precision;
//strcpy(F_Date, cdp->F_Date); //strcpy(F_Date, cdp->F_Date);
To_Val = NULL; To_Val = NULL;
Slen = 0; Slen = 0;
...@@ -986,10 +988,10 @@ bool ODBCCOL::SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check) ...@@ -986,10 +988,10 @@ bool ODBCCOL::SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check)
if (GetDomain() || ((DTVAL *)value)->IsFormatted()) if (GetDomain() || ((DTVAL *)value)->IsFormatted())
goto newval; // This will make a new value; goto newval; // This will make a new value;
} else if (Buf_Type == TYPE_FLOAT) } else if (Buf_Type == TYPE_DOUBLE)
// Float values must be written with the correct (column) precision // Float values must be written with the correct (column) precision
// Note: maybe this should be forced by ShowValue instead of this ? // Note: maybe this should be forced by ShowValue instead of this ?
value->SetPrec(GetPrecision()); value->SetPrec(GetScale());
Value = value; // Directly access the external value Value = value; // Directly access the external value
} else { } else {
...@@ -1036,12 +1038,14 @@ void ODBCCOL::ReadColumn(PGLOBAL g) ...@@ -1036,12 +1038,14 @@ void ODBCCOL::ReadColumn(PGLOBAL g)
} else } else
Value->SetNull(false); Value->SetNull(false);
if (Bufp && tdbp->Rows) if (Bufp && tdbp->Rows) {
if (Buf_Type == TYPE_DATE) if (Buf_Type == TYPE_DATE)
*Sqlbuf = ((TIMESTAMP_STRUCT*)Bufp)[n]; *Sqlbuf = ((TIMESTAMP_STRUCT*)Bufp)[n];
else else
Value->SetValue_pvblk(Blkp, n); Value->SetValue_pvblk(Blkp, n);
} // endif Bufp
if (Buf_Type == TYPE_DATE) { if (Buf_Type == TYPE_DATE) {
struct tm dbtime = {0,0,0,0,0,0,0,0,0}; struct tm dbtime = {0,0,0,0,0,0,0,0,0};
...@@ -1052,6 +1056,13 @@ void ODBCCOL::ReadColumn(PGLOBAL g) ...@@ -1052,6 +1056,13 @@ void ODBCCOL::ReadColumn(PGLOBAL g)
dbtime.tm_mon = (int)Sqlbuf->month - 1; dbtime.tm_mon = (int)Sqlbuf->month - 1;
dbtime.tm_year = (int)Sqlbuf->year - 1900; dbtime.tm_year = (int)Sqlbuf->year - 1900;
((DTVAL*)Value)->MakeTime(&dbtime); ((DTVAL*)Value)->MakeTime(&dbtime);
} else if (Buf_Type == TYPE_DECIM && tdbp->Sep) {
// Be sure to use decimal point
char *p = strchr(Value->GetCharValue(), tdbp->Sep);
if (p)
*p = '.';
} // endif Buf_Type } // endif Buf_Type
if (g->Trace) { if (g->Trace) {
...@@ -1080,7 +1091,8 @@ void ODBCCOL::AllocateBuffers(PGLOBAL g, int rows) ...@@ -1080,7 +1091,8 @@ void ODBCCOL::AllocateBuffers(PGLOBAL g, int rows)
if (Buf_Type == TYPE_DATE) if (Buf_Type == TYPE_DATE)
Bufp = PlugSubAlloc(g, NULL, rows * sizeof(TIMESTAMP_STRUCT)); Bufp = PlugSubAlloc(g, NULL, rows * sizeof(TIMESTAMP_STRUCT));
else { else {
Blkp = AllocValBlock(g, NULL, Buf_Type, rows, Long+1, 0, true, false, false); Blkp = AllocValBlock(g, NULL, Buf_Type, rows, GetBuflen(),
GetScale(), true, false, false);
Bufp = Blkp->GetValPointer(); Bufp = Blkp->GetValPointer();
} // endelse } // endelse
...@@ -1107,13 +1119,21 @@ void *ODBCCOL::GetBuffer(DWORD rows) ...@@ -1107,13 +1119,21 @@ void *ODBCCOL::GetBuffer(DWORD rows)
/***********************************************************************/ /***********************************************************************/
SWORD ODBCCOL::GetBuflen(void) SWORD ODBCCOL::GetBuflen(void)
{ {
if (Buf_Type == TYPE_DATE) SWORD flen;
return (SWORD)sizeof(TIMESTAMP_STRUCT);
else if (Buf_Type == TYPE_STRING)
return (SWORD)Value->GetClen() + 1;
else
return (SWORD)Value->GetClen();
switch (Buf_Type) {
case TYPE_DATE:
flen = (SWORD)sizeof(TIMESTAMP_STRUCT);
break;
case TYPE_STRING:
case TYPE_DECIM:
flen = (SWORD)Value->GetClen() + 1;
break;
default:
flen = (SWORD)Value->GetClen();
} // endswitch Buf_Type
return flen;
} // end of GetBuflen } // end of GetBuflen
/***********************************************************************/ /***********************************************************************/
...@@ -1137,11 +1157,18 @@ void ODBCCOL::WriteColumn(PGLOBAL g) ...@@ -1137,11 +1157,18 @@ void ODBCCOL::WriteColumn(PGLOBAL g)
Sqlbuf->month = dbtime->tm_mon + 1; Sqlbuf->month = dbtime->tm_mon + 1;
Sqlbuf->year = dbtime->tm_year + 1900; Sqlbuf->year = dbtime->tm_year + 1900;
Sqlbuf->fraction = 0; Sqlbuf->fraction = 0;
} else if (Buf_Type == TYPE_DECIM) {
// Some data sources require local decimal separator
char *p, sep = ((PTDBODBC)To_Tdb)->Sep;
if (sep && (p = strchr(Value->GetCharValue(), '.')))
*p = sep;
} // endif Buf_Type } // endif Buf_Type
if (Nullable) if (Nullable)
*StrLen = (Value->IsNull()) ? SQL_NULL_DATA : *StrLen = (Value->IsNull()) ? SQL_NULL_DATA :
(IsTypeNum(Buf_Type)) ? 0 : SQL_NTS; (IsTypeChar(Buf_Type)) ? SQL_NTS : 0;
} // end of WriteColumn } // end of WriteColumn
...@@ -1415,7 +1442,7 @@ PQRYRES TDBSRC::GetResult(PGLOBAL g) ...@@ -1415,7 +1442,7 @@ PQRYRES TDBSRC::GetResult(PGLOBAL g)
TDBOTB::TDBOTB(PODEF tdp) : TDBDRV(tdp) TDBOTB::TDBOTB(PODEF tdp) : TDBDRV(tdp)
{ {
Dsn = tdp->GetConnect(); Dsn = tdp->GetConnect();
Schema = tdp->GetTabowner(); Schema = tdp->GetTabschema();
Tab = tdp->GetTabname(); Tab = tdp->GetTabname();
} // end of TDBOTB constructor } // end of TDBOTB constructor
......
...@@ -32,9 +32,10 @@ class DllExport ODBCDEF : public TABDEF { /* Logical table description */ ...@@ -32,9 +32,10 @@ class DllExport ODBCDEF : public TABDEF { /* Logical table description */
virtual const char *GetType(void) {return "ODBC";} virtual const char *GetType(void) {return "ODBC";}
PSZ GetConnect(void) {return Connect;} PSZ GetConnect(void) {return Connect;}
PSZ GetTabname(void) {return Tabname;} PSZ GetTabname(void) {return Tabname;}
PSZ GetTabowner(void) {return Tabowner;} PSZ GetTabschema(void) {return Tabschema;}
PSZ GetTabqual(void) {return Tabqual;} PSZ GetTabcat(void) {return Tabcat;}
PSZ GetSrcdef(void) {return Srcdef;} PSZ GetSrcdef(void) {return Srcdef;}
char GetSep(void) {return (Sep) ? *Sep : 0;}
int GetQuoted(void) {return Quoted;} int GetQuoted(void) {return Quoted;}
int GetCatver(void) {return Catver;} int GetCatver(void) {return Catver;}
int GetOptions(void) {return Options;} int GetOptions(void) {return Options;}
...@@ -47,11 +48,12 @@ class DllExport ODBCDEF : public TABDEF { /* Logical table description */ ...@@ -47,11 +48,12 @@ class DllExport ODBCDEF : public TABDEF { /* Logical table description */
// Members // Members
PSZ Connect; /* ODBC connection string */ PSZ Connect; /* ODBC connection string */
PSZ Tabname; /* External table name */ PSZ Tabname; /* External table name */
PSZ Tabowner; /* External table owner */ PSZ Tabschema; /* External table schema */
PSZ Tabqual; /* External table qualifier */ PSZ Tabcat; /* External table catalog */
PSZ Srcdef; /* The source table SQL definition */ PSZ Srcdef; /* The source table SQL definition */
PSZ Qchar; /* Identifier quoting character */ PSZ Qchar; /* Identifier quoting character */
PSZ Qrystr; /* The original query */ PSZ Qrystr; /* The original query */
PSZ Sep; /* Decimal separator */
int Catver; /* ODBC version for catalog functions */ int Catver; /* ODBC version for catalog functions */
int Options; /* Open connection options */ int Options; /* Open connection options */
int Quoted; /* Identifier quoting level */ int Quoted; /* Identifier quoting level */
...@@ -115,8 +117,8 @@ class TDBODBC : public TDBASE { ...@@ -115,8 +117,8 @@ class TDBODBC : public TDBASE {
ODBCCOL *Cnp; // Points to count(*) column ODBCCOL *Cnp; // Points to count(*) column
char *Connect; // Points to connection string char *Connect; // Points to connection string
char *TableName; // Points to ODBC table name char *TableName; // Points to ODBC table name
char *Owner; // Points to ODBC table Owner char *Schema; // Points to ODBC table Schema
char *Qualifier; // Points to ODBC table Qualifier char *Catalog; // Points to ODBC table Catalog
char *Srcdef; // The source table SQL definition char *Srcdef; // The source table SQL definition
char *Query; // Points to SQL statement char *Query; // Points to SQL statement
char *Count; // Points to count(*) SQL statement char *Count; // Points to count(*) SQL statement
...@@ -125,6 +127,7 @@ class TDBODBC : public TDBASE { ...@@ -125,6 +127,7 @@ class TDBODBC : public TDBASE {
char *MulConn; // Used for multiple ODBC tables char *MulConn; // Used for multiple ODBC tables
char *DBQ; // The address part of Connect string char *DBQ; // The address part of Connect string
char *Qrystr; // The original query char *Qrystr; // The original query
char Sep; // The decimal separator
int Options; // Connect options int Options; // Connect options
int Quoted; // The identifier quoting level int Quoted; // The identifier quoting level
int Fpos; // Position of last read record int Fpos; // Position of last read record
......
...@@ -416,10 +416,10 @@ bool INICOL::SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check) ...@@ -416,10 +416,10 @@ bool INICOL::SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check)
if (GetDomain() || ((DTVAL *)value)->IsFormatted()) if (GetDomain() || ((DTVAL *)value)->IsFormatted())
goto newval; // This will make a new value; goto newval; // This will make a new value;
} else if (Buf_Type == TYPE_FLOAT) } else if (Buf_Type == TYPE_DOUBLE || Buf_Type == TYPE_DECIM)
// Float values must be written with the correct (column) precision // Float values must be written with the correct (column) precision
// Note: maybe this should be forced by ShowValue instead of this ? // Note: maybe this should be forced by ShowValue instead of this ?
value->SetPrec(GetPrecision()); value->SetPrec(GetScale());
Value = value; // Directly access the external value Value = value; // Directly access the external value
} else { } else {
......
...@@ -122,16 +122,16 @@ TABLE_SHARE *GetTableShare(PGLOBAL g, THD *thd, const char *db, ...@@ -122,16 +122,16 @@ TABLE_SHARE *GetTableShare(PGLOBAL g, THD *thd, const char *db,
PQRYRES TabColumns(PGLOBAL g, THD *thd, const char *db, PQRYRES TabColumns(PGLOBAL g, THD *thd, const char *db,
const char *name, bool& info) const char *name, bool& info)
{ {
static int buftyp[] = {TYPE_STRING, TYPE_SHORT, TYPE_STRING, TYPE_INT, int buftyp[] = {TYPE_STRING, TYPE_SHORT, TYPE_STRING, TYPE_INT,
TYPE_INT, TYPE_SHORT, TYPE_SHORT, TYPE_SHORT, TYPE_INT, TYPE_SHORT, TYPE_SHORT, TYPE_SHORT,
TYPE_STRING, TYPE_STRING, TYPE_STRING}; TYPE_STRING, TYPE_STRING, TYPE_STRING};
static XFLD fldtyp[] = {FLD_NAME, FLD_TYPE, FLD_TYPENAME, FLD_PREC, XFLD fldtyp[] = {FLD_NAME, FLD_TYPE, FLD_TYPENAME, FLD_PREC,
FLD_LENGTH, FLD_SCALE, FLD_RADIX, FLD_NULL, FLD_LENGTH, FLD_SCALE, FLD_RADIX, FLD_NULL,
FLD_REM, FLD_NO, FLD_CHARSET}; FLD_REM, FLD_NO, FLD_CHARSET};
static unsigned int length[] = {0, 4, 16, 4, 4, 4, 4, 4, 0, 32, 32}; unsigned int length[] = {0, 4, 16, 4, 4, 4, 4, 4, 0, 32, 32};
char *fld, *fmt, v; char *fld, *fmt, v;
int i, n, ncol = sizeof(buftyp) / sizeof(int); int i, n, ncol = sizeof(buftyp) / sizeof(int);
int len, type, prec; int prec, len, type, scale;
bool mysql; bool mysql;
TABLE_SHARE *s = NULL; TABLE_SHARE *s = NULL;
Field* *field; Field* *field;
...@@ -208,27 +208,33 @@ PQRYRES TabColumns(PGLOBAL g, THD *thd, const char *db, ...@@ -208,27 +208,33 @@ PQRYRES TabColumns(PGLOBAL g, THD *thd, const char *db,
// When creating tables we do need info about date columns // When creating tables we do need info about date columns
if (mysql) { if (mysql) {
fmt = MyDateFmt(fp->type()); fmt = MyDateFmt(fp->type());
len = strlen(fmt); prec = len = strlen(fmt);
} else { } else {
fmt = (char*)fp->option_struct->dateformat; fmt = (char*)fp->option_struct->dateformat;
len = fp->field_length; prec = len = fp->field_length;
} // endif mysql } // endif mysql
} else { } else {
fmt = NULL; if (type == TYPE_DECIM)
prec = ((Field_new_decimal*)fp)->precision;
else
prec = fp->field_length;
// prec = (prec(???) == NOT_FIXED_DEC) ? 0 : fp->field_length;
len = fp->char_length(); len = fp->char_length();
fmt = NULL;
} // endif type } // endif type
crp = crp->Next; // Precision crp = crp->Next; // Precision
crp->Kdata->SetValue(len, i); crp->Kdata->SetValue(prec, i);
crp = crp->Next; // Length crp = crp->Next; // Length
prec = (type == TYPE_FLOAT) ? fp->decimals() : 0;
len = (prec == 31) ? 0 : fp->field_length;
crp->Kdata->SetValue(len, i); crp->Kdata->SetValue(len, i);
crp = crp->Next; // Scale crp = crp->Next; // Scale
crp->Kdata->SetValue(prec, i); scale = (type == TYPE_DOUBLE || type == TYPE_DECIM) ? fp->decimals()
: 0;
crp->Kdata->SetValue(scale, i);
crp = crp->Next; // Radix crp = crp->Next; // Radix
crp->Kdata->SetValue(0, i); crp->Kdata->SetValue(0, i);
......
...@@ -269,7 +269,7 @@ PQRYRES WMIColumns(PGLOBAL g, char *nsp, char *cls, bool info) ...@@ -269,7 +269,7 @@ PQRYRES WMIColumns(PGLOBAL g, char *nsp, char *cls, bool info)
case CIM_REAL64: case CIM_REAL64:
case CIM_REAL32: case CIM_REAL32:
prec = 2; prec = 2;
typ = TYPE_FLOAT; typ = TYPE_DOUBLE;
lng = 15; lng = 15;
break; break;
case CIM_SINT64: case CIM_SINT64:
......
...@@ -1168,10 +1168,10 @@ bool XMLCOL::SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check) ...@@ -1168,10 +1168,10 @@ bool XMLCOL::SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check)
if (GetDomain() || ((DTVAL *)value)->IsFormatted()) if (GetDomain() || ((DTVAL *)value)->IsFormatted())
goto newval; // This will make a new value; goto newval; // This will make a new value;
} else if (Buf_Type == TYPE_FLOAT) } else if (Buf_Type == TYPE_DOUBLE)
// Float values must be written with the correct (column) precision // Float values must be written with the correct (column) precision
// Note: maybe this should be forced by ShowValue instead of this ? // Note: maybe this should be forced by ShowValue instead of this ?
value->SetPrec(GetPrecision()); value->SetPrec(GetScale());
Value = value; // Directly access the external value Value = value; // Directly access the external value
} else { } else {
......
...@@ -57,6 +57,7 @@ PVBLK AllocValBlock(PGLOBAL g, void *mp, int type, int nval, int len, ...@@ -57,6 +57,7 @@ PVBLK AllocValBlock(PGLOBAL g, void *mp, int type, int nval, int len,
switch (type) { switch (type) {
case TYPE_STRING: case TYPE_STRING:
case TYPE_DECIM:
if (len) if (len)
blkp = new(g) CHRBLK(mp, nval, len, prec, blank); blkp = new(g) CHRBLK(mp, nval, len, prec, blank);
else else
...@@ -87,7 +88,7 @@ PVBLK AllocValBlock(PGLOBAL g, void *mp, int type, int nval, int len, ...@@ -87,7 +88,7 @@ PVBLK AllocValBlock(PGLOBAL g, void *mp, int type, int nval, int len,
blkp = new(g) TYPBLK<longlong>(mp, nval, type); blkp = new(g) TYPBLK<longlong>(mp, nval, type);
break; break;
case TYPE_FLOAT: case TYPE_DOUBLE:
blkp = new(g) TYPBLK<double>(mp, nval, type, prec); blkp = new(g) TYPBLK<double>(mp, nval, type, prec);
break; break;
case TYPE_TINY: case TYPE_TINY:
...@@ -343,6 +344,21 @@ ulonglong TYPBLK<longlong>::MaxVal(void) {return INT_MAX64;} ...@@ -343,6 +344,21 @@ ulonglong TYPBLK<longlong>::MaxVal(void) {return INT_MAX64;}
template <> template <>
ulonglong TYPBLK<ulonglong>::MaxVal(void) {return ULONGLONG_MAX;} ulonglong TYPBLK<ulonglong>::MaxVal(void) {return ULONGLONG_MAX;}
template <>
void TYPBLK<double>::SetValue(PSZ p, int n)
{
ChkIndx(n);
if (Check) {
PGLOBAL& g = Global;
strcpy(g->Message, MSG(BAD_SET_STRING));
longjmp(g->jumper[g->jump_level], Type);
} // endif Check
Typp[n] = atof(p);
SetNull(n, false);
} // end of SetValue
/***********************************************************************/ /***********************************************************************/
/* Set one value in a block from an array of characters. */ /* Set one value in a block from an array of characters. */
/***********************************************************************/ /***********************************************************************/
...@@ -1163,7 +1179,7 @@ DATBLK::DATBLK(void *mp, int nval) : TYPBLK<int>(mp, nval, TYPE_INT) ...@@ -1163,7 +1179,7 @@ DATBLK::DATBLK(void *mp, int nval) : TYPBLK<int>(mp, nval, TYPE_INT)
/***********************************************************************/ /***********************************************************************/
bool DATBLK::SetFormat(PGLOBAL g, PSZ fmt, int len, int year) bool DATBLK::SetFormat(PGLOBAL g, PSZ fmt, int len, int year)
{ {
if (!(Dvalp = AllocateValue(g, TYPE_DATE, len, year, fmt))) if (!(Dvalp = AllocateValue(g, TYPE_DATE, len, year, false, fmt)))
return true; return true;
return false; return false;
......
...@@ -153,8 +153,9 @@ PSZ GetTypeName(int type) ...@@ -153,8 +153,9 @@ PSZ GetTypeName(int type)
case TYPE_INT: name = "INTEGER"; break; case TYPE_INT: name = "INTEGER"; break;
case TYPE_BIGINT: name = "BIGINT"; break; case TYPE_BIGINT: name = "BIGINT"; break;
case TYPE_DATE: name = "DATE"; break; case TYPE_DATE: name = "DATE"; break;
case TYPE_FLOAT: name = "FLOAT"; break; case TYPE_DOUBLE: name = "DOUBLE"; break;
case TYPE_TINY: name = "TINY"; break; case TYPE_TINY: name = "TINY"; break;
case TYPE_DECIM: name = "DECIMAL"; break;
default: name = "UNKNOWN"; break; default: name = "UNKNOWN"; break;
} // endswitch type } // endswitch type
...@@ -167,12 +168,13 @@ PSZ GetTypeName(int type) ...@@ -167,12 +168,13 @@ PSZ GetTypeName(int type)
int GetTypeSize(int type, int len) int GetTypeSize(int type, int len)
{ {
switch (type) { switch (type) {
case TYPE_DECIM:
case TYPE_STRING: len = len * sizeof(char); break; case TYPE_STRING: len = len * sizeof(char); break;
case TYPE_SHORT: len = sizeof(short); break; case TYPE_SHORT: len = sizeof(short); break;
case TYPE_INT: len = sizeof(int); break; case TYPE_INT: len = sizeof(int); break;
case TYPE_BIGINT: len = sizeof(longlong); break; case TYPE_BIGINT: len = sizeof(longlong); break;
case TYPE_DATE: len = sizeof(int); break; case TYPE_DATE: len = sizeof(int); break;
case TYPE_FLOAT: len = sizeof(double); break; case TYPE_DOUBLE: len = sizeof(double); break;
case TYPE_TINY: len = sizeof(char); break; case TYPE_TINY: len = sizeof(char); break;
default: len = 0; default: len = 0;
} // endswitch type } // endswitch type
...@@ -192,9 +194,10 @@ char *GetFormatType(int type) ...@@ -192,9 +194,10 @@ char *GetFormatType(int type)
case TYPE_SHORT: c = "S"; break; case TYPE_SHORT: c = "S"; break;
case TYPE_INT: c = "N"; break; case TYPE_INT: c = "N"; break;
case TYPE_BIGINT: c = "L"; break; case TYPE_BIGINT: c = "L"; break;
case TYPE_FLOAT: c = "F"; break; case TYPE_DOUBLE: c = "F"; break;
case TYPE_DATE: c = "D"; break; case TYPE_DATE: c = "D"; break;
case TYPE_TINY: c = "T"; break; case TYPE_TINY: c = "T"; break;
case TYPE_DECIM: c = "M"; break;
} // endswitch type } // endswitch type
return c; return c;
...@@ -212,15 +215,15 @@ int GetFormatType(char c) ...@@ -212,15 +215,15 @@ int GetFormatType(char c)
case 'S': type = TYPE_SHORT; break; case 'S': type = TYPE_SHORT; break;
case 'N': type = TYPE_INT; break; case 'N': type = TYPE_INT; break;
case 'L': type = TYPE_BIGINT; break; case 'L': type = TYPE_BIGINT; break;
case 'F': type = TYPE_FLOAT; break; case 'F': type = TYPE_DOUBLE; break;
case 'D': type = TYPE_DATE; break; case 'D': type = TYPE_DATE; break;
case 'T': type = TYPE_TINY; break; case 'T': type = TYPE_TINY; break;
case 'M': type = TYPE_DECIM; break;
} // endswitch type } // endswitch type
return type; return type;
} // end of GetFormatType } // end of GetFormatType
/***********************************************************************/ /***********************************************************************/
/* IsTypeChar: returns true for character type(s). */ /* IsTypeChar: returns true for character type(s). */
/***********************************************************************/ /***********************************************************************/
...@@ -228,6 +231,7 @@ bool IsTypeChar(int type) ...@@ -228,6 +231,7 @@ bool IsTypeChar(int type)
{ {
switch (type) { switch (type) {
case TYPE_STRING: case TYPE_STRING:
case TYPE_DECIM:
return true; return true;
} // endswitch type } // endswitch type
...@@ -243,10 +247,11 @@ bool IsTypeNum(int type) ...@@ -243,10 +247,11 @@ bool IsTypeNum(int type)
case TYPE_INT: case TYPE_INT:
case TYPE_BIGINT: case TYPE_BIGINT:
case TYPE_DATE: case TYPE_DATE:
case TYPE_FLOAT: case TYPE_DOUBLE:
case TYPE_SHORT: case TYPE_SHORT:
case TYPE_NUM: case TYPE_NUM:
case TYPE_TINY: case TYPE_TINY:
case TYPE_DECIM:
return true; return true;
} // endswitch type } // endswitch type
...@@ -261,10 +266,11 @@ const char *GetFmt(int type, bool un) ...@@ -261,10 +266,11 @@ const char *GetFmt(int type, bool un)
const char *fmt; const char *fmt;
switch (type) { switch (type) {
case TYPE_DECIM:
case TYPE_STRING: fmt = "%s"; break; case TYPE_STRING: fmt = "%s"; break;
case TYPE_SHORT: fmt = (un) ? "%hu" : "%hd"; break; case TYPE_SHORT: fmt = (un) ? "%hu" : "%hd"; break;
case TYPE_BIGINT: fmt = (un) ? "%llu" : "%lld"; break; case TYPE_BIGINT: fmt = (un) ? "%llu" : "%lld"; break;
case TYPE_FLOAT: fmt = "%.*lf"; break; case TYPE_DOUBLE: fmt = "%.*lf"; break;
default: fmt = (un) ? "%u" : "%d"; break; default: fmt = (un) ? "%u" : "%d"; break;
} // endswitch Type } // endswitch Type
...@@ -293,7 +299,7 @@ int ConvertType(int target, int type, CONV kind, bool match) ...@@ -293,7 +299,7 @@ int ConvertType(int target, int type, CONV kind, bool match)
if (match && (!IsTypeNum(target) || !IsTypeNum(type))) if (match && (!IsTypeNum(target) || !IsTypeNum(type)))
return TYPE_ERROR; return TYPE_ERROR;
return (target == TYPE_FLOAT || type == TYPE_FLOAT) ? TYPE_FLOAT return (target == TYPE_DOUBLE || type == TYPE_DOUBLE) ? TYPE_DOUBLE
: (target == TYPE_DATE || type == TYPE_DATE) ? TYPE_DATE : (target == TYPE_DATE || type == TYPE_DATE) ? TYPE_DATE
: (target == TYPE_BIGINT || type == TYPE_BIGINT) ? TYPE_BIGINT : (target == TYPE_BIGINT || type == TYPE_BIGINT) ? TYPE_BIGINT
: (target == TYPE_INT || type == TYPE_INT) ? TYPE_INT : (target == TYPE_INT || type == TYPE_INT) ? TYPE_INT
...@@ -307,7 +313,7 @@ int ConvertType(int target, int type, CONV kind, bool match) ...@@ -307,7 +313,7 @@ int ConvertType(int target, int type, CONV kind, bool match)
(IsTypeNum(target) && !IsTypeNum(type)))) (IsTypeNum(target) && !IsTypeNum(type))))
return TYPE_ERROR; return TYPE_ERROR;
return (target == TYPE_FLOAT || type == TYPE_FLOAT) ? TYPE_FLOAT return (target == TYPE_DOUBLE || type == TYPE_DOUBLE) ? TYPE_DOUBLE
: (target == TYPE_DATE || type == TYPE_DATE) ? TYPE_DATE : (target == TYPE_DATE || type == TYPE_DATE) ? TYPE_DATE
: (target == TYPE_BIGINT || type == TYPE_BIGINT) ? TYPE_BIGINT : (target == TYPE_BIGINT || type == TYPE_BIGINT) ? TYPE_BIGINT
: (target == TYPE_INT || type == TYPE_INT) ? TYPE_INT : (target == TYPE_INT || type == TYPE_INT) ? TYPE_INT
...@@ -343,8 +349,8 @@ PVAL AllocateValue(PGLOBAL g, void *value, short type) ...@@ -343,8 +349,8 @@ PVAL AllocateValue(PGLOBAL g, void *value, short type)
case TYPE_BIGINT: case TYPE_BIGINT:
valp = new(g) TYPVAL<longlong>(*(longlong*)value, TYPE_BIGINT); valp = new(g) TYPVAL<longlong>(*(longlong*)value, TYPE_BIGINT);
break; break;
case TYPE_FLOAT: case TYPE_DOUBLE:
valp = new(g) TYPVAL<double>(*(double *)value, TYPE_FLOAT, 2); valp = new(g) TYPVAL<double>(*(double *)value, TYPE_DOUBLE, 2);
break; break;
case TYPE_TINY: case TYPE_TINY:
valp = new(g) TYPVAL<char>(*(char *)value, TYPE_TINY); valp = new(g) TYPVAL<char>(*(char *)value, TYPE_TINY);
...@@ -361,7 +367,8 @@ PVAL AllocateValue(PGLOBAL g, void *value, short type) ...@@ -361,7 +367,8 @@ PVAL AllocateValue(PGLOBAL g, void *value, short type)
/***********************************************************************/ /***********************************************************************/
/* Allocate a variable Value according to type, length and precision. */ /* Allocate a variable Value according to type, length and precision. */
/***********************************************************************/ /***********************************************************************/
PVAL AllocateValue(PGLOBAL g, int type, int len, int prec, PSZ fmt) PVAL AllocateValue(PGLOBAL g, int type, int len, int prec,
bool uns, PSZ fmt)
{ {
PVAL valp; PVAL valp;
...@@ -373,35 +380,38 @@ PVAL AllocateValue(PGLOBAL g, int type, int len, int prec, PSZ fmt) ...@@ -373,35 +380,38 @@ PVAL AllocateValue(PGLOBAL g, int type, int len, int prec, PSZ fmt)
valp = new(g) DTVAL(g, len, prec, fmt); valp = new(g) DTVAL(g, len, prec, fmt);
break; break;
case TYPE_INT: case TYPE_INT:
if (prec) if (uns)
valp = new(g) TYPVAL<uint>((uint)0, TYPE_INT, 0, true); valp = new(g) TYPVAL<uint>((uint)0, TYPE_INT, 0, true);
else else
valp = new(g) TYPVAL<int>((int)0, TYPE_INT); valp = new(g) TYPVAL<int>((int)0, TYPE_INT);
break; break;
case TYPE_BIGINT: case TYPE_BIGINT:
if (prec) if (uns)
valp = new(g) TYPVAL<ulonglong>((ulonglong)0, TYPE_BIGINT, 0, true); valp = new(g) TYPVAL<ulonglong>((ulonglong)0, TYPE_BIGINT, 0, true);
else else
valp = new(g) TYPVAL<longlong>((longlong)0, TYPE_BIGINT); valp = new(g) TYPVAL<longlong>((longlong)0, TYPE_BIGINT);
break; break;
case TYPE_SHORT: case TYPE_SHORT:
if (prec) if (uns)
valp = new(g) TYPVAL<ushort>((ushort)0, TYPE_SHORT, 0, true); valp = new(g) TYPVAL<ushort>((ushort)0, TYPE_SHORT, 0, true);
else else
valp = new(g) TYPVAL<short>((short)0, TYPE_SHORT); valp = new(g) TYPVAL<short>((short)0, TYPE_SHORT);
break; break;
case TYPE_FLOAT: case TYPE_DOUBLE:
valp = new(g) TYPVAL<double>(0.0, TYPE_FLOAT, prec); valp = new(g) TYPVAL<double>(0.0, TYPE_DOUBLE, prec);
break; break;
case TYPE_TINY: case TYPE_TINY:
if (prec) if (uns)
valp = new(g) TYPVAL<uchar>((uchar)0, TYPE_TINY, 0, true); valp = new(g) TYPVAL<uchar>((uchar)0, TYPE_TINY, 0, true);
else else
valp = new(g) TYPVAL<char>((char)0, TYPE_TINY); valp = new(g) TYPVAL<char>((char)0, TYPE_TINY);
break;
case TYPE_DECIM:
valp = new(g) DECVAL(g, (PSZ)NULL, len, prec, uns);
break; break;
default: default:
sprintf(g->Message, MSG(BAD_VALUE_TYPE), type); sprintf(g->Message, MSG(BAD_VALUE_TYPE), type);
...@@ -412,6 +422,7 @@ PVAL AllocateValue(PGLOBAL g, int type, int len, int prec, PSZ fmt) ...@@ -412,6 +422,7 @@ PVAL AllocateValue(PGLOBAL g, int type, int len, int prec, PSZ fmt)
return valp; return valp;
} // end of AllocateValue } // end of AllocateValue
#if 0
/***********************************************************************/ /***********************************************************************/
/* Allocate a constant Value converted to newtype. */ /* Allocate a constant Value converted to newtype. */
/* Can also be used to copy a Value eventually converted. */ /* Can also be used to copy a Value eventually converted. */
...@@ -459,8 +470,8 @@ PVAL AllocateValue(PGLOBAL g, PVAL valp, int newtype, int uns) ...@@ -459,8 +470,8 @@ PVAL AllocateValue(PGLOBAL g, PVAL valp, int newtype, int uns)
case TYPE_DATE: case TYPE_DATE:
valp = new(g) DTVAL(g, valp->GetIntValue()); valp = new(g) DTVAL(g, valp->GetIntValue());
break; break;
case TYPE_FLOAT: case TYPE_DOUBLE:
valp = new(g) TYPVAL<double>(valp->GetFloatValue(), TYPE_FLOAT, valp = new(g) TYPVAL<double>(valp->GetFloatValue(), TYPE_DOUBLE,
valp->GetValPrec()); valp->GetValPrec());
break; break;
case TYPE_TINY: case TYPE_TINY:
...@@ -479,7 +490,7 @@ PVAL AllocateValue(PGLOBAL g, PVAL valp, int newtype, int uns) ...@@ -479,7 +490,7 @@ PVAL AllocateValue(PGLOBAL g, PVAL valp, int newtype, int uns)
valp->SetGlobal(g); valp->SetGlobal(g);
return valp; return valp;
} // end of AllocateValue } // end of AllocateValue
#endif // 0
/* -------------------------- Class VALUE ---------------------------- */ /* -------------------------- Class VALUE ---------------------------- */
...@@ -505,10 +516,11 @@ const char *VALUE::GetXfmt(void) ...@@ -505,10 +516,11 @@ const char *VALUE::GetXfmt(void)
const char *fmt; const char *fmt;
switch (Type) { switch (Type) {
case TYPE_DECIM:
case TYPE_STRING: fmt = "%*s"; break; case TYPE_STRING: fmt = "%*s"; break;
case TYPE_SHORT: fmt = (Unsigned) ? "%*hu" : "%*hd"; break; case TYPE_SHORT: fmt = (Unsigned) ? "%*hu" : "%*hd"; break;
case TYPE_BIGINT: fmt = (Unsigned) ? "%*llu" : "%*lld"; break; case TYPE_BIGINT: fmt = (Unsigned) ? "%*llu" : "%*lld"; break;
case TYPE_FLOAT: fmt = "%*.*lf"; break; case TYPE_DOUBLE: fmt = "%*.*lf"; break;
default: fmt = (Unsigned) ? "%*u" : "%*d"; break; default: fmt = (Unsigned) ? "%*u" : "%*d"; break;
} // endswitch Type } // endswitch Type
...@@ -1355,6 +1367,234 @@ bool TYPVAL<PSZ>::SetConstFormat(PGLOBAL g, FORMAT& fmt) ...@@ -1355,6 +1367,234 @@ bool TYPVAL<PSZ>::SetConstFormat(PGLOBAL g, FORMAT& fmt)
return false; return false;
} // end of SetConstFormat } // end of SetConstFormat
/* -------------------------- Class DECIMAL -------------------------- */
/***********************************************************************/
/* DECIMAL public constructor from a constant string. */
/***********************************************************************/
DECVAL::DECVAL(PSZ s) : TYPVAL<PSZ>(s)
{
if (s) {
char *p = strchr(Strp, '.');
Prec = (p) ? Len - (p - Strp) : 0;
} // endif s
Type = TYPE_DECIM;
} // end of DECVAL constructor
/***********************************************************************/
/* DECIMAL public constructor from char. */
/***********************************************************************/
DECVAL::DECVAL(PGLOBAL g, PSZ s, int n, int prec, bool uns)
: TYPVAL<PSZ>(g, s, n + (prec ? 1 : 0) + (uns ? 0 : 1), 0)
{
Prec = prec;
Unsigned = uns;
Type = TYPE_DECIM;
} // end of DECVAL constructor
/***********************************************************************/
/* DECIMAL: Check whether the numerica value is equal to 0. */
/***********************************************************************/
bool DECVAL::IsZero(void)
{
for (int i = 0; Strp[i]; i++)
if (!strchr("0 +-.", Strp[i]))
return false;
return true;
} // end of IsZero
/***********************************************************************/
/* DECIMAL: Reset value to zero. */
/***********************************************************************/
void DECVAL::Reset(void)
{
int i = 0;
Strp[i++] = '0';
if (Prec) {
Strp[i++] = '.';
do {
Strp[i++] = '0';
} while (i < Prec + 2);
} // endif Prec
Strp[i] = 0;
} // end of Reset
/***********************************************************************/
/* DECIMAL ShowValue: get string representation right justified. */
/***********************************************************************/
char *DECVAL::ShowValue(char *buf, int len)
{
sprintf(buf, Xfmt, len, Strp);
return buf;
} // end of ShowValue
/***********************************************************************/
/* GetBinValue: fill a buffer with the internal binary value. */
/* This function checks whether the buffer length is enough and */
/* returns true if not. Actual filling occurs only if go is true. */
/* Currently used by WriteColumn of binary files. */
/***********************************************************************/
bool DECVAL::GetBinValue(void *buf, int buflen, bool go)
{
int len = (Null) ? 0 : strlen(Strp);
if (len > buflen)
return true;
else if (go) {
memset(buf, ' ', buflen - len);
memcpy((char*)buf + buflen - len, Strp, len);
} // endif go
return false;
} // end of GetBinValue
#if 0
/***********************************************************************/
/* DECIMAL SetValue: copy the value of another Value object. */
/***********************************************************************/
bool DECVAL::SetValue_pval(PVAL valp, bool chktype)
{
if (chktype && (valp->GetType() != Type || valp->GetSize() > Len))
return true;
char buf[32];
if (!(Null = valp->IsNull() && Nullable))
strncpy(Strp, valp->GetCharString(buf), Len);
else
Reset();
return false;
} // end of SetValue_pval
/***********************************************************************/
/* DECIMAL SetValue: fill string with chars extracted from a line. */
/***********************************************************************/
bool DECVAL::SetValue_char(char *p, int n)
{
bool rc;
if (p) {
rc = n > Len;
if ((n = min(n, Len))) {
strncpy(Strp, p, n);
// for (p = Strp + n - 1; p >= Strp && (*p == ' ' || *p == '\0'); p--) ;
for (p = Strp + n - 1; p >= Strp; p--)
if (*p && *p != ' ')
break;
*(++p) = '\0';
if (trace > 1)
htrc(" Setting string to: '%s'\n", Strp);
} else
Reset();
Null = false;
} else {
rc = false;
Reset();
Null = Nullable;
} // endif p
return rc;
} // end of SetValue_char
/***********************************************************************/
/* DECIMAL SetValue: fill string with another string. */
/***********************************************************************/
void DECVAL::SetValue_psz(PSZ s)
{
if (s) {
strncpy(Strp, s, Len);
Null = false;
} else {
Reset();
Null = Nullable;
} // endif s
} // end of SetValue_psz
/***********************************************************************/
/* DECIMAL SetValue: fill string with a string extracted from a block.*/
/***********************************************************************/
void DECVAL::SetValue_pvblk(PVBLK blk, int n)
{
// STRBLK's can return a NULL pointer
SetValue_psz(blk->GetCharValue(n));
} // end of SetValue_pvblk
/***********************************************************************/
/* DECIMAL SetBinValue: fill string with chars extracted from a line. */
/***********************************************************************/
void DECVAL::SetBinValue(void *p)
{
SetValue_char((char *)p, Len);
} // end of SetBinValue
/***********************************************************************/
/* DECIMAL GetCharString: get string representation of a char value. */
/***********************************************************************/
char *DECVAL::GetCharString(char *p)
{
return Strp;
} // end of GetCharString
#endif // 0
/***********************************************************************/
/* DECIMAL compare value with another Value. */
/***********************************************************************/
bool DECVAL::IsEqual(PVAL vp, bool chktype)
{
if (this == vp)
return true;
else if (chktype && Type != vp->GetType())
return false;
else if (Null || vp->IsNull())
return false;
char buf[32];
return !strcmp(Strp, vp->GetCharString(buf));
} // end of IsEqual
#if 0
/***********************************************************************/
/* FormatValue: This function set vp (a STRING value) to the string */
/* constructed from its own value formated using the fmt format. */
/* This function assumes that the format matches the value type. */
/***********************************************************************/
bool DECVAL::FormatValue(PVAL vp, char *fmt)
{
char *buf = (char*)vp->GetTo_Val(); // Should be big enough
int n = sprintf(buf, fmt, Strp);
return (n > vp->GetValLen());
} // end of FormatValue
/***********************************************************************/
/* DECIMAL SetFormat function (used to set SELECT output format). */
/***********************************************************************/
bool DECVAL::SetConstFormat(PGLOBAL g, FORMAT& fmt)
{
fmt.Type[0] = 'C';
fmt.Length = Len;
fmt.Prec = 0;
return false;
} // end of SetConstFormat
#endif // 0
/* -------------------------- Class DTVAL ---------------------------- */ /* -------------------------- Class DTVAL ---------------------------- */
/***********************************************************************/ /***********************************************************************/
......
...@@ -47,9 +47,9 @@ DllExport int GetFormatType(char); ...@@ -47,9 +47,9 @@ DllExport int GetFormatType(char);
DllExport bool IsTypeChar(int type); DllExport bool IsTypeChar(int type);
DllExport bool IsTypeNum(int type); DllExport bool IsTypeNum(int type);
//lExport int ConvertType(int, int, CONV, bool match = false); //lExport int ConvertType(int, int, CONV, bool match = false);
DllExport PVAL AllocateValue(PGLOBAL, PVAL, int = TYPE_VOID, int = 0); //lExport PVAL AllocateValue(PGLOBAL, PVAL, int = TYPE_VOID, int = 0);
DllExport PVAL AllocateValue(PGLOBAL, int, int len = 0, int prec = 0, DllExport PVAL AllocateValue(PGLOBAL, int, int len = 0, int prec = 0,
PSZ fmt = NULL); bool uns = false, PSZ fmt = NULL);
DllExport ulonglong CharToNumber(char *, int, ulonglong, bool, DllExport ulonglong CharToNumber(char *, int, ulonglong, bool,
bool *minus = NULL, bool *rc = NULL); bool *minus = NULL, bool *rc = NULL);
...@@ -255,6 +255,37 @@ class DllExport TYPVAL<PSZ>: public VALUE { ...@@ -255,6 +255,37 @@ class DllExport TYPVAL<PSZ>: public VALUE {
int Len; int Len;
}; // end of class TYPVAL<PSZ> }; // end of class TYPVAL<PSZ>
/***********************************************************************/
/* Specific DECIMAL class. */
/***********************************************************************/
class DllExport DECVAL: public TYPVAL<PSZ> {
public:
// Constructors
DECVAL(PSZ s);
DECVAL(PGLOBAL g, PSZ s, int n, int prec, bool uns);
// Implementation
virtual bool IsTypeNum(void) {return true;}
virtual bool IsZero(void);
virtual void Reset(void);
virtual int GetValPrec() {return Prec;}
// Methods
//virtual bool SetValue_pval(PVAL valp, bool chktype);
//virtual bool SetValue_char(char *p, int n);
//virtual void SetValue_psz(PSZ s);
//virtual void SetValue_pvblk(PVBLK blk, int n);
//virtual void SetBinValue(void *p);
virtual bool GetBinValue(void *buf, int buflen, bool go);
virtual char *ShowValue(char *buf, int);
//virtual char *GetCharString(char *p);
virtual bool IsEqual(PVAL vp, bool chktype);
//virtual bool FormatValue(PVAL vp, char *fmt);
//virtual bool SetConstFormat(PGLOBAL, FORMAT&);
// Members
}; // end of class DECVAL
/***********************************************************************/ /***********************************************************************/
/* Class DTVAL: represents a time stamp value. */ /* Class DTVAL: represents a time stamp value. */
/***********************************************************************/ /***********************************************************************/
......
...@@ -2753,7 +2753,7 @@ KXYCOL::KXYCOL(PKXBASE kp) : To_Keys(Keys.Memp), ...@@ -2753,7 +2753,7 @@ KXYCOL::KXYCOL(PKXBASE kp) : To_Keys(Keys.Memp),
/***********************************************************************/ /***********************************************************************/
bool KXYCOL::Init(PGLOBAL g, PCOL colp, int n, bool sm, int kln) bool KXYCOL::Init(PGLOBAL g, PCOL colp, int n, bool sm, int kln)
{ {
int len = colp->GetLength(), prec = colp->GetPrecision(); int len = colp->GetLength(), prec = colp->GetScale();
// Currently no indexing on NULL columns // Currently no indexing on NULL columns
if (colp->IsNullable()) { if (colp->IsNullable()) {
...@@ -2774,7 +2774,8 @@ bool KXYCOL::Init(PGLOBAL g, PCOL colp, int n, bool sm, int kln) ...@@ -2774,7 +2774,8 @@ bool KXYCOL::Init(PGLOBAL g, PCOL colp, int n, bool sm, int kln)
// Allocate the Value object used when moving items // Allocate the Value object used when moving items
Type = colp->GetResultType(); Type = colp->GetResultType();
if (!(Valp = AllocateValue(g, Type, len, colp->GetPrecision()))) if (!(Valp = AllocateValue(g, Type, len, colp->GetScale(),
colp->IsUnsigned())))
return true; return true;
Klen = Valp->GetClen(); Klen = Valp->GetClen();
...@@ -2825,7 +2826,7 @@ BYTE* KXYCOL::MapInit(PGLOBAL g, PCOL colp, int *n, BYTE *m) ...@@ -2825,7 +2826,7 @@ BYTE* KXYCOL::MapInit(PGLOBAL g, PCOL colp, int *n, BYTE *m)
#endif #endif
// Allocate the Value object used when moving items // Allocate the Value object used when moving items
Valp = AllocateValue(g, Type, len, prec, NULL); Valp = AllocateValue(g, Type, len, prec, false, NULL);
Klen = Valp->GetClen(); Klen = Valp->GetClen();
if (n[2]) { if (n[2]) {
......
...@@ -109,6 +109,7 @@ int CONSTANT::GetLengthEx(void) ...@@ -109,6 +109,7 @@ int CONSTANT::GetLengthEx(void)
return Value->GetValLen(); return Value->GetValLen();
} // end of GetLengthEx } // end of GetLengthEx
#if 0
/***********************************************************************/ /***********************************************************************/
/* Convert a constant to the given type. */ /* Convert a constant to the given type. */
/***********************************************************************/ /***********************************************************************/
...@@ -119,6 +120,7 @@ void CONSTANT::Convert(PGLOBAL g, int newtype) ...@@ -119,6 +120,7 @@ void CONSTANT::Convert(PGLOBAL g, int newtype)
longjmp(g->jumper[g->jump_level], TYPE_CONST); longjmp(g->jumper[g->jump_level], TYPE_CONST);
} // end of Convert } // end of Convert
#endif // 0
/***********************************************************************/ /***********************************************************************/
/* Compare: returns true if this object is equivalent to xp. */ /* Compare: returns true if this object is equivalent to xp. */
...@@ -151,7 +153,7 @@ bool CONSTANT::Rephrase(PGLOBAL g, PSZ work) ...@@ -151,7 +153,7 @@ bool CONSTANT::Rephrase(PGLOBAL g, PSZ work)
case TYPE_DATE: case TYPE_DATE:
sprintf(work + strlen(work), "%d", Value->GetIntValue()); sprintf(work + strlen(work), "%d", Value->GetIntValue());
break; break;
case TYPE_FLOAT: case TYPE_DOUBLE:
sprintf(work + strlen(work), "%lf", Value->GetFloatValue()); sprintf(work + strlen(work), "%lf", Value->GetFloatValue());
break; break;
case TYPE_BIGINT: case TYPE_BIGINT:
......
...@@ -52,7 +52,7 @@ class DllExport XOBJECT : public BLOCK { ...@@ -52,7 +52,7 @@ class DllExport XOBJECT : public BLOCK {
virtual short GetShortValue(void); virtual short GetShortValue(void);
virtual int GetIntValue(void); virtual int GetIntValue(void);
virtual double GetFloatValue(void); virtual double GetFloatValue(void);
virtual int GetPrecision(void) = 0; virtual int GetScale(void) = 0;
// Methods // Methods
virtual void Reset(void) {} virtual void Reset(void) {}
...@@ -92,7 +92,7 @@ class DllExport XVOID : public XOBJECT { ...@@ -92,7 +92,7 @@ class DllExport XVOID : public XOBJECT {
virtual PSZ GetCharValue(void) {return NULL;} virtual PSZ GetCharValue(void) {return NULL;}
virtual int GetIntValue(void) {return 0;} virtual int GetIntValue(void) {return 0;}
virtual double GetFloatValue(void) {return 0.0;} virtual double GetFloatValue(void) {return 0.0;}
virtual int GetPrecision() {return 0;} virtual int GetScale() {return 0;}
// Methods // Methods
virtual bool Compare(PXOB xp) {return xp->GetType() == TYPE_VOID;} virtual bool Compare(PXOB xp) {return xp->GetType() == TYPE_VOID;}
...@@ -115,7 +115,7 @@ class DllExport CONSTANT : public XOBJECT { ...@@ -115,7 +115,7 @@ class DllExport CONSTANT : public XOBJECT {
virtual int GetType(void) {return TYPE_CONST;} virtual int GetType(void) {return TYPE_CONST;}
virtual int GetResultType(void) {return Value->Type;} virtual int GetResultType(void) {return Value->Type;}
virtual int GetLength(void) {return Value->GetValLen();} virtual int GetLength(void) {return Value->GetValLen();}
virtual int GetPrecision() {return Value->GetValPrec();} virtual int GetScale() {return Value->GetValPrec();}
virtual int GetLengthEx(void); virtual int GetLengthEx(void);
// Methods // Methods
...@@ -123,7 +123,7 @@ class DllExport CONSTANT : public XOBJECT { ...@@ -123,7 +123,7 @@ class DllExport CONSTANT : public XOBJECT {
virtual bool SetFormat(PGLOBAL g, FORMAT& fmt) virtual bool SetFormat(PGLOBAL g, FORMAT& fmt)
{return Value->SetConstFormat(g, fmt);} {return Value->SetConstFormat(g, fmt);}
virtual int CheckSpcCol(PTDB, int) {return 1;} virtual int CheckSpcCol(PTDB, int) {return 1;}
void Convert(PGLOBAL g, int newtype); // void Convert(PGLOBAL g, int newtype);
// bool Rephrase(PGLOBAL g, PSZ work); // bool Rephrase(PGLOBAL g, PSZ work);
void SetValue(PVAL vp) {Value = vp;} void SetValue(PVAL vp) {Value = vp;}
virtual bool VerifyColumn(PTBX txp) {return true;} virtual bool VerifyColumn(PTBX txp) {return true;}
......
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