Commit c055e5e0 authored by Olivier Bertrand's avatar Olivier Bertrand

- Add the DECIMAL data type (TYPE_DECIM)

  Change the variable name of the DOUBLE type from TYPE_FLOAT to TYPE_DOUBLE
  Change some names to reflect ODBC version 3. This affects some variable
  names, function names and catalog table column names.
  Qualifier -> Catalog
  Owner (Creator) -> Schema
  Length -> Precision
  Prec -> Scale

modified:
  storage/connect/catalog.h
  storage/connect/colblk.cpp
  storage/connect/colblk.h
  storage/connect/filamdbf.cpp
  storage/connect/global.h
  storage/connect/ha_connect.cc
  storage/connect/myconn.cpp
  storage/connect/mysql-test/connect/r/mysql_new.result
  storage/connect/mysql-test/connect/r/odbc_oracle.result
  storage/connect/myutil.cpp
  storage/connect/odbconn.cpp
  storage/connect/plgdbutl.cpp
  storage/connect/rcmsg.c
  storage/connect/reldef.cpp
  storage/connect/reldef.h
  storage/connect/tabcol.cpp
  storage/connect/tabcol.h
  storage/connect/tabdos.cpp
  storage/connect/tabfmt.cpp
  storage/connect/tabmysql.cpp
  storage/connect/tabodbc.cpp
  storage/connect/tabodbc.h
  storage/connect/tabsys.cpp
  storage/connect/tabutil.cpp
  storage/connect/tabwmi.cpp
  storage/connect/tabxml.cpp
  storage/connect/valblk.cpp
  storage/connect/value.cpp
  storage/connect/value.h
  storage/connect/xindex.cpp
  storage/connect/xobject.cpp
  storage/connect/xobject.h

- Fix crash when GetTDB returned NULL in Open_Table

modified:
  storage/connect/ha_connect.cc

- Fix assert error setting double values from PSZ

modified:
  storage/connect/valblk.cpp
parent 889b08b0
......@@ -41,7 +41,8 @@ typedef struct _colinfo {
int Offset;
int Length;
int Key;
int Prec;
int Precision;
int Scale;
int Opt;
char *Remark;
char *Datefmt;
......
......@@ -38,6 +38,7 @@ COLBLK::COLBLK(PCOLDEF cdp, PTDB tdbp, int i)
Format = cdp->F;
Opt = cdp->Opt;
Long = cdp->Long;
Precision = cdp->Precision;
Buf_Type = cdp->Buf_Type;
ColUse |= cdp->Flags; // Used by CONNECT
Nullable = !!(cdp->Flags & U_NULLS);
......@@ -47,6 +48,7 @@ COLBLK::COLBLK(PCOLDEF cdp, PTDB tdbp, int i)
memset(&Format, 0, sizeof(FORMAT));
Opt = 0;
Long = 0;
Precision = 0;
Buf_Type = TYPE_ERROR;
Nullable = false;
Unsigned = false;
......@@ -165,7 +167,7 @@ bool COLBLK::CheckSort(PTDB tdbp)
/* InitValue: prepare a column block for read operation. */
/* Now we use Format.Length for the len parameter to avoid strings */
/* 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. */
/***********************************************************************/
bool COLBLK::InitValue(PGLOBAL g)
......@@ -173,12 +175,9 @@ bool COLBLK::InitValue(PGLOBAL g)
if (Value)
return false; // Already done
// Unsigned can be set only for valid value types
int prec = (Unsigned) ? 1 : GetPrecision();
// Allocate a Value object
if (!(Value = AllocateValue(g, Buf_Type, Format.Length,
prec, GetDomain())))
if (!(Value = AllocateValue(g, Buf_Type, Precision,
GetScale(), Unsigned, GetDomain())))
return true;
AddStatus(BUF_READY);
......@@ -270,7 +269,7 @@ SPCBLK::SPCBLK(PCOLUMN cp)
: COLBLK((PCOLDEF)NULL, cp->GetTo_Table()->GetTo_Tdb(), 0)
{
Name = (char*)cp->GetName();
Long = 0;
Precision = Long = 0;
Buf_Type = TYPE_ERROR;
} // end of SPCBLK constructor
......@@ -290,7 +289,7 @@ void SPCBLK::WriteColumn(PGLOBAL g)
/***********************************************************************/
RIDBLK::RIDBLK(PCOLUMN cp, bool rnm) : SPCBLK(cp)
{
Long = 10;
Precision = Long = 10;
Buf_Type = TYPE_INT;
Rnm = rnm;
*Format.Type = 'N';
......@@ -313,7 +312,7 @@ void RIDBLK::ReadColumn(PGLOBAL g)
FIDBLK::FIDBLK(PCOLUMN cp) : SPCBLK(cp)
{
//Is_Key = 2; for when the MUL table indexed reading will be implemented.
Long = _MAX_PATH;
Precision = Long = _MAX_PATH;
Buf_Type = TYPE_STRING;
*Format.Type = 'C';
Format.Length = Long;
......@@ -348,7 +347,7 @@ void FIDBLK::ReadColumn(PGLOBAL g)
TIDBLK::TIDBLK(PCOLUMN cp) : SPCBLK(cp)
{
//Is_Key = 2; for when the MUL table indexed reading will be implemented.
Long = 64;
Precision = Long = 64;
Buf_Type = TYPE_STRING;
*Format.Type = 'C';
Format.Length = Long;
......@@ -375,7 +374,7 @@ void TIDBLK::ReadColumn(PGLOBAL g)
SIDBLK::SIDBLK(PCOLUMN cp) : SPCBLK(cp)
{
//Is_Key = 2; for when the MUL table indexed reading will be implemented.
Long = 64;
Precision = Long = 64;
Buf_Type = TYPE_STRING;
*Format.Type = 'C';
Format.Length = Long;
......
......@@ -29,7 +29,8 @@ class DllExport COLBLK : public XOBJECT {
// Implementation
virtual int GetType(void) {return TYPE_COLBLK;}
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 GetLengthEx(void);
virtual int GetAmType() {return TYPE_AM_ERROR;}
......@@ -53,6 +54,7 @@ class DllExport COLBLK : public XOBJECT {
PSZ GetDomain(void) {return (Cdp) ? Cdp->Decode : NULL;}
PSZ GetDesc(void) {return (Cdp) ? Cdp->Desc : NULL;}
PSZ GetFmt(void) {return (Cdp) ? Cdp->Fmt : NULL;}
bool IsUnsigned(void) {return Unsigned;}
bool IsNullable(void) {return Nullable;}
void SetNullable(bool b) {Nullable = b;}
......@@ -88,6 +90,7 @@ class DllExport COLBLK : public XOBJECT {
int Opt; // Cluster/sort information
int Buf_Type; // Data type
int Long; // Internal length in table
int Precision; // Column length (as for ODBC)
FORMAT Format; // Output format
ushort ColUse; // Column usage
ushort Status; // Column read status
......
......@@ -271,11 +271,11 @@ PQRYRES DBFColumns(PGLOBAL g, const char *fn, BOOL info)
type = TYPE_STRING;
break;
case 'N':
type = (thisfield.Decimals) ? TYPE_FLOAT
type = (thisfield.Decimals) ? TYPE_DOUBLE
: (len > 10) ? TYPE_BIGINT : TYPE_INT;
break;
case 'F':
type = TYPE_FLOAT;
type = TYPE_DOUBLE;
break;
case 'D':
type = TYPE_DATE; // Is this correct ???
......
......@@ -77,12 +77,13 @@
#define TYPE_SEMX 0 /* Initial semantic function type? */
#define TYPE_ERROR 0
#define TYPE_STRING 1
#define TYPE_FLOAT 2
#define TYPE_DOUBLE 2
#define TYPE_SHORT 3
#define TYPE_TINY 4
#define TYPE_BIGINT 5
#define TYPE_LIST 6
#define TYPE_INT 7
#define TYPE_DECIM 9
#if defined(OS32)
#define SYS_STAMP "OS32"
......
......@@ -862,12 +862,14 @@ void *ha_connect::GetColumnOption(PGLOBAL g, void *field, PCOLINFO pcf)
return fldp;
} // endif special
pcf->Prec= 0;
pcf->Scale= 0;
pcf->Opt= (fop) ? (int)fop->opt : 0;
if ((pcf->Length= fp->field_length) < 0)
pcf->Length= 256; // BLOB?
pcf->Precision= pcf->Length;
if (fop) {
pcf->Offset= (int)fop->offset;
// pcf->Freq= fop->freq;
......@@ -898,13 +900,17 @@ void *ha_connect::GetColumnOption(PGLOBAL g, void *field, PCOLINFO pcf)
// Find if collation name ends by _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
} // endif ci
break;
case TYPE_FLOAT:
pcf->Prec= max(min(fp->decimals(), ((unsigned)pcf->Length - 2)), 0);
case TYPE_DOUBLE:
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;
case TYPE_DATE:
// Field_length is only used for DATE columns
......@@ -1109,12 +1115,12 @@ PTDB ha_connect::GetTDB(PGLOBAL g)
|| tdbp->GetAmType() == TYPE_AM_XML)) {
tp= tdbp;
// 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;
else
tp->SetMode(xmod);
} else
printf("GetTDB: %s\n", g->Message);
tp->SetMode(xmod);
return tp;
} // end of GetTDB
......@@ -1326,7 +1332,7 @@ int ha_connect::MakeRecord(char *buf)
value->FormatValue(sdvalout, fmt);
p= sdvalout->GetCharValue();
break;
case TYPE_FLOAT:
case TYPE_DOUBLE:
p= NULL;
break;
case TYPE_STRING:
......@@ -1422,7 +1428,7 @@ int ha_connect::ScanRecord(PGLOBAL g, uchar *buf)
value->Reset();
} else switch (value->GetType()) {
case TYPE_FLOAT:
case TYPE_DOUBLE:
value->SetValue(fp->val_real());
break;
case TYPE_DATE:
......@@ -3129,7 +3135,17 @@ int ha_connect::external_lock(THD *thd, int lock_type)
if (adp)
// 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
......@@ -3508,7 +3524,7 @@ static bool add_fields(PGLOBAL g,
length= (char*)PlugSubAlloc(g, NULL, 8);
sprintf(length, "%d", len);
if (typ == TYPE_FLOAT) {
if (typ == TYPE_DOUBLE) {
decimals= (char*)PlugSubAlloc(g, NULL, 8);
sprintf(decimals, "%d", min(dec, (min(len, 31) - 1)));
} // endif dec
......@@ -3574,6 +3590,10 @@ static bool add_field(String *sql, const char *field_name, int typ,
error|= sql->append(',');
// dec must be < len and < 31
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
error|= sql->append(')');
......@@ -3590,7 +3610,7 @@ static bool add_field(String *sql, const char *field_name, int typ,
if (dft && *dft) {
error|= sql->append(" DEFAULT ");
if (IsTypeChar(typ)) {
if (!IsTypeNum(typ)) {
error|= sql->append("'");
error|= sql->append_for_single_quote(dft, strlen(dft));
error|= sql->append("'");
......@@ -4086,7 +4106,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
case TAB_TBL:
case TAB_XCL:
case TAB_OCCUR:
if (!stricmp(tab, create_info->alias) &&
if (!src && !stricmp(tab, create_info->alias) &&
(!db || !stricmp(db, table_s->db.str)))
sprintf(g->Message, "A %s table cannot refer to itself", topt->type);
else
......@@ -4295,11 +4315,15 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
} else
typ= plgtyp;
switch (typ) {
case TYPE_DOUBLE:
// Some data sources do not count dec in length (prec)
if (typ == TYPE_FLOAT)
prec += (dec + 2); // To be safe
else
case TYPE_DECIM:
break;
default:
dec= 0;
} // endswitch typ
} // endif ttp
#endif // ODBC_SUPPORT
......@@ -4307,7 +4331,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
// Make the arguments as required by add_fields
if (typ == TYPE_DATE)
prec= 0;
else if (typ == TYPE_FLOAT)
else if (typ == TYPE_DOUBLE)
prec= len;
// Now add the field
......
......@@ -723,7 +723,8 @@ PQRYRES MYSQLC::GetResult(PGLOBAL g, bool pdb)
// For direct MySQL connection, display the MySQL date 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->Clen = GetTypeSize(crp->Type, crp->Length);
uns = (fld->flags & (UNSIGNED_FLAG | ZEROFILL_FLAG)) ? true : false;
......
......@@ -141,7 +141,7 @@ t1 CREATE TABLE `t1` (
`e` bigint(20) DEFAULT NULL,
`f` 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'
SELECT * FROM t1;
a b c d e f g h
......
......@@ -126,7 +126,7 @@ TABNAME='T1';
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`A` double(40,0) DEFAULT NULL,
`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;
......@@ -138,7 +138,7 @@ CREATE TABLE t2 AS SELECT * FROM t1;
SHOW CREATE TABLE t2;
Table Create Table
t2 CREATE TABLE `t2` (
`A` double(40,0) DEFAULT NULL,
`A` decimal(38,0) DEFAULT NULL,
`B` double(40,0) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
SELECT * FROM t2;
......@@ -162,7 +162,7 @@ TABNAME='MTR.T1';
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`A` double(40,0) DEFAULT NULL,
`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;
......@@ -178,7 +178,7 @@ TABNAME='MTR.V1';
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`A` double(40,0) DEFAULT NULL,
`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;
......@@ -190,7 +190,7 @@ CREATE TABLE t2 AS SELECT * FROM t1;
SHOW CREATE TABLE t2;
Table Create Table
t2 CREATE TABLE `t2` (
`A` double(40,0) DEFAULT NULL,
`A` decimal(38,0) DEFAULT NULL,
`B` double(40,0) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
SELECT * FROM t2;
......
......@@ -42,9 +42,10 @@ int MYSQLtoPLG(char *typname, char *var)
!stricmp(typname, "text") || !stricmp(typname, "blob"))
type = TYPE_STRING;
else if (!stricmp(typname, "double") || !stricmp(typname, "float") ||
!stricmp(typname, "real") ||
!stricmp(typname, "decimal") || !stricmp(typname, "numeric"))
type = TYPE_FLOAT;
!stricmp(typname, "real"))
type = TYPE_DOUBLE;
else if (!stricmp(typname, "decimal") || !stricmp(typname, "numeric"))
type = TYPE_DECIM;
else if (!stricmp(typname, "date") || !stricmp(typname, "datetime") ||
!stricmp(typname, "time") || !stricmp(typname, "timestamp") ||
!stricmp(typname, "year"))
......@@ -95,7 +96,7 @@ enum enum_field_types PLGtoMYSQL(int type, bool dbf, char v)
case TYPE_SHORT:
mytype = MYSQL_TYPE_SHORT;
break;
case TYPE_FLOAT:
case TYPE_DOUBLE:
mytype = MYSQL_TYPE_DOUBLE;
break;
case TYPE_DATE:
......@@ -114,6 +115,13 @@ enum enum_field_types PLGtoMYSQL(int type, bool dbf, char v)
case TYPE_TINY:
mytype = MYSQL_TYPE_TINY;
break;
case TYPE_DECIM:
#if !defined(ALPHA)
mytype = MYSQL_TYPE_NEWDECIMAL;
#else // ALPHA
mytype = MYSQL_TYPE_DECIMAL;
#endif // ALPHA
break;
default:
mytype = MYSQL_TYPE_NULL;
} // endswitch mytype
......@@ -129,7 +137,7 @@ const char *PLGtoMYSQLtype(int type, bool dbf, char v)
switch (type) {
case TYPE_INT: return "INT";
case TYPE_SHORT: return "SMALLINT";
case TYPE_FLOAT: return "DOUBLE";
case TYPE_DOUBLE: return "DOUBLE";
case TYPE_DATE: return dbf ? "DATE" :
(v == 'S') ? "TIMESTAMP" :
(v == 'D') ? "DATE" :
......@@ -138,6 +146,7 @@ const char *PLGtoMYSQLtype(int type, bool dbf, char v)
case TYPE_STRING: return v ? "VARCHAR" : "CHAR";
case TYPE_BIGINT: return "BIGINT";
case TYPE_TINY: return "TINYINT";
case TYPE_DECIM: return "DECIMAL";
default: return "CHAR(0)";
} // endswitch mytype
......@@ -170,9 +179,11 @@ int MYSQLtoPLG(int mytype, char *var)
#if !defined(ALPHA)
case MYSQL_TYPE_NEWDECIMAL:
#endif // !ALPHA)
type = TYPE_DECIM;
break;
case MYSQL_TYPE_FLOAT:
case MYSQL_TYPE_DOUBLE:
type = TYPE_FLOAT;
type = TYPE_DOUBLE;
break;
case MYSQL_TYPE_TIMESTAMP:
case MYSQL_TYPE_DATE:
......
/************ 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 */
/* */
......@@ -78,8 +78,9 @@ static short GetSQLType(int type)
case TYPE_INT: tp = SQL_INTEGER; break;
case TYPE_DATE: tp = SQL_TIMESTAMP; break;
case TYPE_BIGINT: tp = SQL_BIGINT; break; // (-5)
case TYPE_FLOAT: tp = SQL_DOUBLE; break;
case TYPE_TINY : tp = SQL_TINYINT; break;
case TYPE_DOUBLE: tp = SQL_DOUBLE; break;
case TYPE_TINY: tp = SQL_TINYINT; break;
case TYPE_DECIM: tp = SQL_DECIMAL; break;
} // endswitch type
return tp;
......@@ -98,8 +99,9 @@ static int GetSQLCType(int type)
case TYPE_INT: tp = SQL_C_LONG; break;
case TYPE_DATE: tp = SQL_C_TIMESTAMP; 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_DECIM: tp = SQL_C_CHAR; break;
} // endswitch type
return tp;
......@@ -125,8 +127,9 @@ int TranslateSQLType(int stp, int prec, int& len, char& v)
break;
case SQL_NUMERIC: // 2
case SQL_DECIMAL: // 3
type = (prec || len > 20) ? TYPE_FLOAT
: (len > 10) ? TYPE_BIGINT : TYPE_INT;
// type = (prec || len > 20) ? TYPE_DOUBLE
// : (len > 10) ? TYPE_BIGINT : TYPE_INT;
type = TYPE_DECIM;
break;
case SQL_INTEGER: // 4
type = TYPE_INT;
......@@ -141,7 +144,7 @@ int TranslateSQLType(int stp, int prec, int& len, char& v)
case SQL_FLOAT: // 6
case SQL_REAL: // 7
case SQL_DOUBLE: // 8
type = TYPE_FLOAT;
type = TYPE_DOUBLE;
break;
case SQL_DATETIME: // 9
// case SQL_DATE: // 9
......@@ -312,9 +315,9 @@ PQRYRES ODBCColumns(PGLOBAL g, char *dsn, char *db, char *table,
} else if (!maxres)
maxres = 20000;
// n = ocp->GetMaxValue(SQL_MAX_QUALIFIER_NAME_LEN);
// n = ocp->GetMaxValue(SQL_MAX_CATALOG_NAME_LEN);
// 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;
// n = ocp->GetMaxValue(SQL_MAX_TABLE_NAME_LEN);
// length[2] = (n) ? (n + 1) : 0;
......@@ -425,7 +428,7 @@ PQRYRES MyODBCCols(PGLOBAL g, char *dsn, char *tab, bool info)
/************************************************************************/
/* 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
crpl = crpt->Next->Next; // Length
......@@ -440,7 +443,7 @@ PQRYRES MyODBCCols(PGLOBAL g, char *dsn, char *tab, bool info)
crpt->Kdata->SetValue(type, i);
// Some data sources do not count prec in length
if (type == TYPE_FLOAT)
if (type == TYPE_DOUBLE)
len += (prec + 2); // To be safe
// Could have been changed for blobs or numeric
......@@ -588,9 +591,9 @@ PQRYRES ODBCTables(PGLOBAL g, char *dsn, char *db, char *tabpat,
if (!maxres)
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;
// n = ocp->GetMaxValue(SQL_MAX_USER_NAME_LEN);
// n = ocp->GetMaxValue(SQL_MAX_SCHEMA_NAME_LEN);
// length[1] = (n) ? (n + 1) : 0;
n = ocp->GetMaxValue(SQL_MAX_TABLE_NAME_LEN);
length[2] = (n) ? (n + 1) : 128;
......@@ -678,9 +681,9 @@ PQRYRES ODBCPrimaryKeys(PGLOBAL g, ODBConn *op, char *dsn, char *table)
/************************************************************************/
n = ocp->GetMaxValue(SQL_MAX_COLUMNS_IN_TABLE);
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;
n = ocp->GetMaxValue(SQL_MAX_USER_NAME_LEN);
n = ocp->GetMaxValue(SQL_MAX_SCHEMA_NAME_LEN);
length[1] = (n) ? (n + 1) : 128;
n = ocp->GetMaxValue(SQL_MAX_TABLE_NAME_LEN);
length[2] = (n) ? (n + 1) : 128;
......@@ -761,11 +764,11 @@ PQRYRES ODBCStatistics(PGLOBAL g, ODBConn *op, char *dsn, char *pat,
/************************************************************************/
n = 1 + ocp->GetMaxValue(SQL_MAX_COLUMNS_IN_INDEX);
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;
n = ocp->GetMaxValue(SQL_MAX_TABLE_NAME_LEN);
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];
n = ocp->GetMaxValue(SQL_MAX_COLUMN_NAME_LEN);
length[7] = (n) ? (n + 1) : 128;
......@@ -1649,34 +1652,34 @@ int ODBConn::ExecuteSQL(void)
bool ODBConn::BindParam(ODBCCOL *colp)
{
void *buf;
UWORD n = colp->GetRank();
SWORD ct, sqlt;
UDWORD len;
int buftype = colp->GetResultType();
SQLUSMALLINT n = colp->GetRank();
SQLSMALLINT ct, sqlt, dec, nul;
SQLULEN colsize;
SQLLEN len;
SQLLEN *strlen = colp->GetStrLen();
RETCODE rc;
SQLRETURN rc;
#if 0
try {
SWORD dec, nul;
rc = SQLDescribeParam(m_hstmt, n, &sqlt, &len, &dec, &nul);
rc = SQLDescribeParam(m_hstmt, n, &sqlt, &colsize, &dec, &nul);
if (!Check(rc))
ThrowDBX(rc, m_hstmt);
ThrowDBX(rc, "SQLDescribeParam", m_hstmt);
} catch(DBX *x) {
strcpy(m_G->Message, x->GetErrorMessage(0));
colsize = colp->GetPrecision();
sqlt = GetSQLType(buftype);
} // end try/catch
#endif // 0
buf = colp->GetBuffer(0);
len = IsTypeNum(colp->GetResultType()) ? 0 : colp->GetBuflen();
ct = GetSQLCType(colp->GetResultType());
sqlt = GetSQLType(colp->GetResultType());
*strlen = IsTypeNum(colp->GetResultType()) ? 0 : SQL_NTS;
len = IsTypeChar(buftype) ? colp->GetBuflen() : 0;
ct = GetSQLCType(buftype);
*strlen = IsTypeChar(buftype) ? SQL_NTS : 0;
try {
rc = SQLBindParameter(m_hstmt, n, SQL_PARAM_INPUT, ct, sqlt,
len, 0, buf, 0, strlen);
colsize, dec, buf, len, strlen);
if (!Check(rc))
ThrowDBX(rc, "SQLBindParameter", m_hstmt);
......@@ -2228,7 +2231,7 @@ int ODBConn::GetCatInfo(CATPARM *cap)
((STRBLK*)crp->Kdata)->SetSorted(true);
} // endif len
pval[n] = AllocateValue(g, crp->Type, len, 0);
pval[n] = AllocateValue(g, crp->Type, len);
buffer = pval[n]->GetTo_Val();
vl = vlen + 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);
break;
case TYPE_FLOAT:
case TYPE_DOUBLE:
fprintf(f, "%s%lf\n", m, *(double *)v);
break;
......
......@@ -38,13 +38,13 @@ char *GetMsgid(int id)
case IDS_13: p = "%s: cl de connexion invalide %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_TAB_01: p = "Qualificateur"; break;
case IDS_TAB_02: p = "Propritaire"; break;
case IDS_TAB_01: p = "Catalogue"; break;
case IDS_TAB_02: p = "Schma"; break;
case IDS_TAB_03: p = "Nom"; break;
case IDS_TAB_04: p = "Type"; break;
case IDS_TAB_05: p = "Remarque"; break;
case IDS_COL_01: p = "Qualif_Table"; break;
case IDS_COL_02: p = "Prop_Tabl"; break;
case IDS_COL_01: p = "Cat_Table"; break;
case IDS_COL_02: p = "Schem_Table"; break;
case IDS_COL_03: p = "Nom_Table"; break;
case IDS_COL_04: p = "Nom_Colonne"; break;
case IDS_COL_05: p = "Type_Donnes"; break;
......@@ -70,18 +70,18 @@ char *GetMsgid(int id)
case IDS_INF_13: p = "Nom_Type_Local"; break;
case IDS_INF_14: p = "Echelle_Minimum"; break;
case IDS_INF_15: p = "Echelle_Maximum"; break;
case IDS_PKY_01: p = "Qualif_Table"; break;
case IDS_PKY_02: p = "Prop_Table"; break;
case IDS_PKY_01: p = "Cat_Table"; break;
case IDS_PKY_02: p = "Schem_Table"; break;
case IDS_PKY_03: p = "Nom_Table"; break;
case IDS_PKY_04: p = "Nom_Colonne"; break;
case IDS_PKY_05: p = "Numro_Cl"; break;
case IDS_PKY_06: p = "Nom_Cl"; break;
case IDS_FKY_01: p = "PKTable_Qualifier"; break;
case IDS_FKY_02: p = "PKTable_Owner"; break;
case IDS_FKY_01: p = "PKTable_Catalog"; break;
case IDS_FKY_02: p = "PKTable_Schema"; break;
case IDS_FKY_03: p = "PKTable_Name"; break;
case IDS_FKY_04: p = "PKColumn_Name"; break;
case IDS_FKY_05: p = "FKTable_Qualifier"; break;
case IDS_FKY_06: p = "FKTable_Owner"; break;
case IDS_FKY_05: p = "FKTable_Catalog"; break;
case IDS_FKY_06: p = "FKTable_Schema"; break;
case IDS_FKY_07: p = "FKTable_Name"; break;
case IDS_FKY_08: p = "FKColumn_Name"; break;
case IDS_FKY_09: p = "Key_Seq"; break;
......@@ -89,8 +89,8 @@ char *GetMsgid(int id)
case IDS_FKY_11: p = "Delete_Rule"; break;
case IDS_FKY_12: p = "FK_Name"; break;
case IDS_FKY_13: p = "PK_Name"; break;
case IDS_STA_01: p = "Table_Qualifier"; break;
case IDS_STA_02: p = "Table_Owner"; break;
case IDS_STA_01: p = "Table_Catalog"; break;
case IDS_STA_02: p = "Table_Schema"; break;
case IDS_STA_03: p = "Table_Name"; break;
case IDS_STA_04: p = "Non_Unique"; break;
case IDS_STA_05: p = "Index_Qualifier"; break;
......@@ -162,18 +162,18 @@ char *GetMsgid(int id)
case IDS_INF_13: p = "Local_Type_Name"; break;
case IDS_INF_14: p = "Minimum_Scale"; break;
case IDS_INF_15: p = "Maximum_Scale"; break;
case IDS_PKY_01: p = "Table_Qualifier"; break;
case IDS_PKY_02: p = "Table_Owner"; break;
case IDS_PKY_01: p = "Table_Catalog"; break;
case IDS_PKY_02: p = "Table_Schema"; break;
case IDS_PKY_03: p = "Table_Name"; break;
case IDS_PKY_04: p = "Column_Name"; break;
case IDS_PKY_05: p = "Key_Seq"; break;
case IDS_PKY_06: p = "Pk_Name"; break;
case IDS_FKY_01: p = "PKTable_Qualifier"; break;
case IDS_FKY_02: p = "PKTable_Owner"; break;
case IDS_FKY_01: p = "PKTable_Catalog"; break;
case IDS_FKY_02: p = "PKTable_Schema"; break;
case IDS_FKY_03: p = "PKTable_Name"; break;
case IDS_FKY_04: p = "PKColumn_Name"; break;
case IDS_FKY_05: p = "FKTable_Qualifier"; break;
case IDS_FKY_06: p = "FKTable_Owner"; break;
case IDS_FKY_05: p = "FKTable_Catalog"; break;
case IDS_FKY_06: p = "FKTable_Schema"; break;
case IDS_FKY_07: p = "FKTable_Name"; break;
case IDS_FKY_08: p = "FKColumn_Name"; break;
case IDS_FKY_09: p = "Key_Seq"; break;
......@@ -181,8 +181,8 @@ char *GetMsgid(int id)
case IDS_FKY_11: p = "Delete_Rule"; break;
case IDS_FKY_12: p = "FK_Name"; break;
case IDS_FKY_13: p = "PK_Name"; break;
case IDS_STA_01: p = "Table_Qualifier"; break;
case IDS_STA_02: p = "Table_Owner"; break;
case IDS_STA_01: p = "Table_Catalog"; break;
case IDS_STA_02: p = "Table_Schema"; break;
case IDS_STA_03: p = "Table_Name"; break;
case IDS_STA_04: p = "Non_Unique"; break;
case IDS_STA_05: p = "Index_Qualifier"; break;
......
......@@ -73,7 +73,7 @@ RELDEF::RELDEF(void)
/***********************************************************************/
TABDEF::TABDEF(void)
{
Owner = NULL;
Schema = NULL;
Desc = NULL;
Catfunc = FNC_NO;
Card = 0;
......@@ -338,9 +338,9 @@ COLCRT::COLCRT(PSZ name)
Fmt = NULL;
Offset = -1;
Long = -1;
//Freq = -1;
Precision = -1;
Key = -1;
Prec = -1;
Scale = -1;
Opt = -1;
DataType = '*';
} // end of COLCRT constructor for table creation
......@@ -354,9 +354,9 @@ COLCRT::COLCRT(void)
Fmt = NULL;
Offset = 0;
Long = 0;
//Freq = 0;
Precision = 0;
Key = 0;
Prec = 0;
Scale = 0;
Opt = 0;
DataType = '*';
} // end of COLCRT constructor for table & view definition
......@@ -394,8 +394,10 @@ int COLDEF::Define(PGLOBAL g, void *memp, PCOLINFO cfp, int poff)
strcpy(F.Type, GetFormatType(Buf_Type));
F.Length = cfp->Length;
F.Prec = cfp->Prec;
F.Prec = cfp->Scale;
Offset = (cfp->Offset < 0) ? poff : cfp->Offset;
Precision = cfp->Precision;
Scale = cfp->Scale;
Long = cfp->Length;
Opt = cfp->Opt;
Key = cfp->Key;
......
......@@ -87,7 +87,7 @@ class DllExport TABDEF : public RELDEF { /* Logical table descriptor */
protected:
// Members
PSZ Owner; /* Table owner (for ODBC) */
PSZ Schema; /* Table schema (for ODBC) */
PSZ Desc; /* Table description */
uint Catfunc; /* Catalog function ID */
int Card; /* (max) number of rows in table */
......@@ -149,6 +149,7 @@ class DllExport COLCRT : public BLOCK { /* Column description block
PSZ GetFmt(void) {return Fmt;}
int GetOpt(void) {return Opt;}
int GetLong(void) {return Long;}
int GetPrecision(void) {return Precision;}
int GetOffset(void) {return Offset;}
void SetOffset(int offset) {Offset = offset;}
......@@ -161,7 +162,8 @@ class DllExport COLCRT : public BLOCK { /* Column description block
int Offset; /* Offset of field within record */
int Long; /* Length of field in file record (!BIN) */
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 */
char DataType; /* Internal data type (C, N, F, T) */
}; // end of COLCRT
......
......@@ -30,7 +30,7 @@ XTAB::XTAB(LPCSTR name, LPCSTR srcdef) : Name(name)
Next = NULL;
To_Tdb = NULL;
Srcdef = srcdef;
Creator = NULL;
Schema = NULL;
Qualifier = NULL;
#ifdef DEBTRACE
......@@ -46,7 +46,7 @@ XTAB::XTAB(PTABLE tp) : Name(tp->Name)
Next = NULL;
To_Tdb = NULL;
Srcdef = tp->Srcdef;
Creator = tp->Creator;
Schema = tp->Schema;
Qualifier = tp->Qualifier;
#ifdef DEBTRACE
......@@ -83,7 +83,7 @@ void XTAB::Print(PGLOBAL g, FILE *f, uint n)
for (PTABLE tp = this; tp; tp = tp->Next) {
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);
} /* endfor tp */
......@@ -101,7 +101,7 @@ void XTAB::Print(PGLOBAL g, char *ps, uint z)
for (PTABLE tp = this; tp && n > 0; tp = tp->Next) {
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);
n -= i;
} // endif tp
......
......@@ -15,7 +15,7 @@
/***********************************************************************/
/* 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 TDBTBM;
public:
......@@ -28,12 +28,12 @@ class DllExport XTAB: public BLOCK { // Table Name-Owner-Srcdef block.
PTDB GetTo_Tdb(void) {return To_Tdb;}
LPCSTR GetName(void) {return Name;}
LPCSTR GetSrc(void) {return Srcdef;}
LPCSTR GetCreator(void) {return Creator;}
LPCSTR GetSchema(void) {return Schema;}
LPCSTR GetQualifier(void) {return Qualifier;}
void SetTo_Tdb(PTDB tdbp) {To_Tdb = tdbp;}
void SetName(LPCSTR name) {Name = name;}
void SetSrc(LPCSTR srcdef) {Srcdef = srcdef;}
void SetCreator(LPCSTR crname) {Creator = crname;}
void SetSchema(LPCSTR schname) {Schema = schname;}
void SetQualifier(LPCSTR qname) {Qualifier = qname;}
// Methods
......@@ -47,7 +47,7 @@ class DllExport XTAB: public BLOCK { // Table Name-Owner-Srcdef block.
PTDB To_Tdb; // Points to Table description Block
LPCSTR Name; // Table name
LPCSTR Srcdef; // Table Source definition
LPCSTR Creator; // Creator name
LPCSTR Schema; // Schema name
LPCSTR Qualifier; // Qualifier name
}; // end of class XTAB
......@@ -68,7 +68,7 @@ class DllExport COLUMN: public XOBJECT { // Column Name/Qualifier block.
virtual int GetResultType(void) {assert(false); return TYPE_VOID;}
virtual int GetLength(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 GetQualifier(void) {return Qualifier;}
PTABLE GetTo_Table(void) {return To_Table;}
......
......@@ -499,7 +499,10 @@ int TDBDOS::MakeIndex(PGLOBAL g, PIXDEF pxdf, bool add)
if (!(colp = ColDB(g, kdp->GetName(), 0))) {
sprintf(g->Message, MSG(INDX_COL_NOTIN), kdp->GetName(), Name);
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);
n = max(n, xdp->GetNparts());
......@@ -944,7 +947,7 @@ DOSCOL::DOSCOL(PGLOBAL g, PCOLDEF cdp, PTDB tp, PCOL cp, int i, PSZ am)
} // endswitch p
// Set number of decimal digits
Dcm = (*p) ? atoi(p) : GetPrecision();
Dcm = (*p) ? atoi(p) : GetScale();
} // endif fmt
if (trace)
......@@ -1006,10 +1009,10 @@ bool DOSCOL::SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check)
if (GetDomain() || ((DTVAL *)value)->IsFormatted())
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
// Note: maybe this should be forced by ShowValue instead of this ?
value->SetPrec(GetPrecision());
value->SetPrec(GetScale());
Value = value; // Directly access the external value
} else {
......@@ -1094,7 +1097,7 @@ void DOSCOL::ReadColumn(PGLOBAL g)
} // endif SetValue_char
break;
case TYPE_FLOAT:
case TYPE_DOUBLE:
Value->SetValue_char(p, field);
dval = Value->GetFloatValue();
......@@ -1207,7 +1210,7 @@ void DOSCOL::WriteColumn(PGLOBAL g)
len = sprintf(Buf, fmt, field - i, Value->GetTinyValue());
break;
case TYPE_FLOAT:
case TYPE_DOUBLE:
strcpy(fmt, (Ldz) ? "%0*.*lf" : "%*.*lf");
sprintf(Buf, fmt, field + ((Nod && Dcm) ? 1 : 0),
Dcm, Value->GetFloatValue());
......
......@@ -72,7 +72,7 @@ extern "C" int trace;
/* CSVColumns: constructs the result blocks containing the description */
/* of all the columns of a CSV file that will be retrieved by #GetData.*/
/* Note: the algorithm to set the type is based on the internal values */
/* of types (TYPE_STRING < TYPE_FLOAT < TYPE_INT) (1 < 2 < 7). */
/* of types (TYPE_STRING < TYPE_DOUBLE < TYPE_INT) (1 < 2 < 7). */
/* If these values are changed, this will have to be revisited. */
/***********************************************************************/
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) {
len[i] = max(len[i], n);
type = (digit || (dec && n == 1)) ? TYPE_STRING
: (dec) ? TYPE_FLOAT : TYPE_INT;
: (dec) ? TYPE_DOUBLE : TYPE_INT;
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
i++;
......@@ -310,9 +310,9 @@ PQRYRES CSVColumns(PGLOBAL g, const char *fn, char sep, char q,
if (n) {
len[i] = max(len[i], n);
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]);
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
imax = max(imax, i+1);
......
......@@ -1117,7 +1117,7 @@ MYSQLCOL::MYSQLCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am)
} // endif cprec
// Set additional MySQL access method information for column.
Long = cdp->GetLong();
Precision = Long = cdp->GetLong();
Bind = NULL;
To_Val = NULL;
Slen = 0;
......@@ -1136,7 +1136,7 @@ MYSQLCOL::MYSQLCOL(MYSQL_FIELD *fld, PTDB tdbp, int i, PSZ am)
{
Name = fld->name;
Opt = 0;
Long = fld->length;
Precision = Long = fld->length;
Buf_Type = MYSQLtoPLG(fld->type);
strcpy(Format.Type, GetFormatType(Buf_Type));
Format.Length = Long;
......@@ -1144,6 +1144,9 @@ MYSQLCOL::MYSQLCOL(MYSQL_FIELD *fld, PTDB tdbp, int i, PSZ am)
ColUse = U_P;
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.
Bind = NULL;
To_Val = NULL;
......@@ -1202,10 +1205,10 @@ bool MYSQLCOL::SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check)
if (GetDomain() || ((DTVAL *)value)->IsFormatted())
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
// Note: maybe this should be forced by ShowValue instead of this ?
value->SetPrec(GetPrecision());
value->SetPrec(GetScale());
Value = value; // Directly access the external value
} else {
......
......@@ -90,7 +90,7 @@ extern int num_read, num_there, num_eq[2]; // Statistics
/***********************************************************************/
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;
Xsrc = false;
} // end of ODBCDEF constructor
......@@ -104,11 +104,13 @@ bool ODBCDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
Tabname = Cat->GetStringCatInfo(g, "Name",
(Catfunc & (FNC_TABLE | FNC_COL)) ? NULL : Name);
Tabname = Cat->GetStringCatInfo(g, "Tabname", Tabname);
//Tabowner = Cat->GetStringCatInfo(g, "Owner", NULL);
Tabowner = Cat->GetStringCatInfo(g, "Dbname", NULL);
Tabqual = Cat->GetStringCatInfo(g, "Qualifier", NULL);
Tabschema = Cat->GetStringCatInfo(g, "Dbname", NULL);
Tabschema = Cat->GetStringCatInfo(g, "Schema", Tabschema);
Tabcat = Cat->GetStringCatInfo(g, "Qualifier", NULL);
Tabcat = Cat->GetStringCatInfo(g, "Catalog", Tabcat);
Srcdef = Cat->GetStringCatInfo(g, "Srcdef", NULL);
Qrystr = Cat->GetStringCatInfo(g, "Query_String", "?");
Sep = Cat->GetStringCatInfo(g, "Separator", NULL);
Catver = Cat->GetIntCatInfo("Catver", 2);
Xsrc = Cat->GetBoolCatInfo("Execsrc", FALSE);
Maxerr = Cat->GetIntCatInfo("Maxerr", 0);
......@@ -170,10 +172,11 @@ TDBODBC::TDBODBC(PODEF tdp) : TDBASE(tdp)
if (tdp) {
Connect = tdp->Connect;
TableName = tdp->Tabname;
Owner = tdp->Tabowner;
Qualifier = tdp->Tabqual;
Schema = tdp->Tabschema;
Catalog = tdp->Tabcat;
Srcdef = tdp->Srcdef;
Qrystr = tdp->Qrystr;
Sep = tdp->GetSep();
Options = tdp->Options;
Quoted = max(0, tdp->GetQuoted());
Rows = tdp->GetElemt();
......@@ -181,10 +184,11 @@ TDBODBC::TDBODBC(PODEF tdp) : TDBASE(tdp)
} else {
Connect = NULL;
TableName = NULL;
Owner = NULL;
Qualifier = NULL;
Schema = NULL;
Catalog = NULL;
Srcdef = NULL;
Qrystr = NULL;
Sep = 0;
Options = 0;
Quoted = 0;
Rows = 0;
......@@ -211,8 +215,8 @@ TDBODBC::TDBODBC(PTDBODBC tdbp) : TDBASE(tdbp)
Cnp = tdbp->Cnp;
Connect = tdbp->Connect;
TableName = tdbp->TableName;
Owner = tdbp->Owner;
Qualifier = tdbp->Qualifier;
Schema = tdbp->Schema;
Catalog = tdbp->Catalog;
Srcdef = tdbp->Srcdef;
Qrystr = tdbp->Qrystr;
Quote = tdbp->Quote;
......@@ -336,7 +340,7 @@ int TDBODBC::Decode(char *txt, char *buf, size_t n)
char *TDBODBC::MakeSQL(PGLOBAL g, bool cnt)
{
char *colist, *tabname, *sql, buf[64];
LPCSTR ownp = NULL, qualp = NULL;
LPCSTR schmp = NULL, catp = NULL;
int len, ncol = 0;
bool first = true;
PTABLE tablep = To_Table;
......@@ -406,37 +410,34 @@ char *TDBODBC::MakeSQL(PGLOBAL g, bool cnt)
len = (strlen(colist) + strlen(buf) + 14);
len += (To_Filter ? strlen(To_Filter->Body) + 7 : 0);
// if (tablep->GetQualifier()) This is used when using a table
// qualp = tablep->GetQualifier(); from anotherPlugDB database but
// else makes no sense for ODBC.
if (Qualifier && *Qualifier)
qualp = Qualifier;
if (Catalog && *Catalog)
catp = Catalog;
if (qualp)
len += (strlen(qualp) + 2);
if (catp)
len += (strlen(catp) + 2);
if (tablep->GetCreator())
ownp = tablep->GetCreator();
else if (Owner && *Owner)
ownp = Owner;
if (tablep->GetSchema())
schmp = tablep->GetSchema();
else if (Schema && *Schema)
schmp = Schema;
if (ownp)
len += (strlen(ownp) + 1);
if (schmp)
len += (strlen(schmp) + 1);
sql = (char*)PlugSubAlloc(g, NULL, len);
strcat(strcat(strcpy(sql, "SELECT "), colist), " FROM ");
if (qualp) {
strcat(sql, qualp);
if (catp) {
strcat(sql, catp);
if (ownp)
strcat(strcat(sql, "."), ownp);
if (schmp)
strcat(strcat(sql, "."), schmp);
else
strcat(sql, ".");
strcat(sql, ".");
} else if (ownp)
strcat(strcat(sql, ownp), ".");
} else if (schmp)
strcat(strcat(sql, schmp), ".");
strcat(sql, tabname);
......@@ -921,7 +922,8 @@ ODBCCOL::ODBCCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am)
} // endif cprec
// Set additional ODBC access method information for column.
Long = cdp->GetLong();
//Long = cdp->GetLong();
Long = Precision;
//strcpy(F_Date, cdp->F_Date);
To_Val = NULL;
Slen = 0;
......@@ -986,10 +988,10 @@ bool ODBCCOL::SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check)
if (GetDomain() || ((DTVAL *)value)->IsFormatted())
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
// Note: maybe this should be forced by ShowValue instead of this ?
value->SetPrec(GetPrecision());
value->SetPrec(GetScale());
Value = value; // Directly access the external value
} else {
......@@ -1036,12 +1038,14 @@ void ODBCCOL::ReadColumn(PGLOBAL g)
} else
Value->SetNull(false);
if (Bufp && tdbp->Rows)
if (Bufp && tdbp->Rows) {
if (Buf_Type == TYPE_DATE)
*Sqlbuf = ((TIMESTAMP_STRUCT*)Bufp)[n];
else
Value->SetValue_pvblk(Blkp, n);
} // endif Bufp
if (Buf_Type == TYPE_DATE) {
struct tm dbtime = {0,0,0,0,0,0,0,0,0};
......@@ -1052,6 +1056,13 @@ void ODBCCOL::ReadColumn(PGLOBAL g)
dbtime.tm_mon = (int)Sqlbuf->month - 1;
dbtime.tm_year = (int)Sqlbuf->year - 1900;
((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
if (g->Trace) {
......@@ -1080,7 +1091,8 @@ void ODBCCOL::AllocateBuffers(PGLOBAL g, int rows)
if (Buf_Type == TYPE_DATE)
Bufp = PlugSubAlloc(g, NULL, rows * sizeof(TIMESTAMP_STRUCT));
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();
} // endelse
......@@ -1107,13 +1119,21 @@ void *ODBCCOL::GetBuffer(DWORD rows)
/***********************************************************************/
SWORD ODBCCOL::GetBuflen(void)
{
if (Buf_Type == TYPE_DATE)
return (SWORD)sizeof(TIMESTAMP_STRUCT);
else if (Buf_Type == TYPE_STRING)
return (SWORD)Value->GetClen() + 1;
else
return (SWORD)Value->GetClen();
SWORD flen;
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
/***********************************************************************/
......@@ -1137,11 +1157,18 @@ void ODBCCOL::WriteColumn(PGLOBAL g)
Sqlbuf->month = dbtime->tm_mon + 1;
Sqlbuf->year = dbtime->tm_year + 1900;
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
if (Nullable)
*StrLen = (Value->IsNull()) ? SQL_NULL_DATA :
(IsTypeNum(Buf_Type)) ? 0 : SQL_NTS;
(IsTypeChar(Buf_Type)) ? SQL_NTS : 0;
} // end of WriteColumn
......@@ -1415,7 +1442,7 @@ PQRYRES TDBSRC::GetResult(PGLOBAL g)
TDBOTB::TDBOTB(PODEF tdp) : TDBDRV(tdp)
{
Dsn = tdp->GetConnect();
Schema = tdp->GetTabowner();
Schema = tdp->GetTabschema();
Tab = tdp->GetTabname();
} // end of TDBOTB constructor
......
......@@ -32,9 +32,10 @@ class DllExport ODBCDEF : public TABDEF { /* Logical table description */
virtual const char *GetType(void) {return "ODBC";}
PSZ GetConnect(void) {return Connect;}
PSZ GetTabname(void) {return Tabname;}
PSZ GetTabowner(void) {return Tabowner;}
PSZ GetTabqual(void) {return Tabqual;}
PSZ GetTabschema(void) {return Tabschema;}
PSZ GetTabcat(void) {return Tabcat;}
PSZ GetSrcdef(void) {return Srcdef;}
char GetSep(void) {return (Sep) ? *Sep : 0;}
int GetQuoted(void) {return Quoted;}
int GetCatver(void) {return Catver;}
int GetOptions(void) {return Options;}
......@@ -47,11 +48,12 @@ class DllExport ODBCDEF : public TABDEF { /* Logical table description */
// Members
PSZ Connect; /* ODBC connection string */
PSZ Tabname; /* External table name */
PSZ Tabowner; /* External table owner */
PSZ Tabqual; /* External table qualifier */
PSZ Tabschema; /* External table schema */
PSZ Tabcat; /* External table catalog */
PSZ Srcdef; /* The source table SQL definition */
PSZ Qchar; /* Identifier quoting character */
PSZ Qrystr; /* The original query */
PSZ Sep; /* Decimal separator */
int Catver; /* ODBC version for catalog functions */
int Options; /* Open connection options */
int Quoted; /* Identifier quoting level */
......@@ -115,8 +117,8 @@ class TDBODBC : public TDBASE {
ODBCCOL *Cnp; // Points to count(*) column
char *Connect; // Points to connection string
char *TableName; // Points to ODBC table name
char *Owner; // Points to ODBC table Owner
char *Qualifier; // Points to ODBC table Qualifier
char *Schema; // Points to ODBC table Schema
char *Catalog; // Points to ODBC table Catalog
char *Srcdef; // The source table SQL definition
char *Query; // Points to SQL statement
char *Count; // Points to count(*) SQL statement
......@@ -125,6 +127,7 @@ class TDBODBC : public TDBASE {
char *MulConn; // Used for multiple ODBC tables
char *DBQ; // The address part of Connect string
char *Qrystr; // The original query
char Sep; // The decimal separator
int Options; // Connect options
int Quoted; // The identifier quoting level
int Fpos; // Position of last read record
......
......@@ -416,10 +416,10 @@ bool INICOL::SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check)
if (GetDomain() || ((DTVAL *)value)->IsFormatted())
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
// Note: maybe this should be forced by ShowValue instead of this ?
value->SetPrec(GetPrecision());
value->SetPrec(GetScale());
Value = value; // Directly access the external value
} else {
......
......@@ -122,16 +122,16 @@ TABLE_SHARE *GetTableShare(PGLOBAL g, THD *thd, const char *db,
PQRYRES TabColumns(PGLOBAL g, THD *thd, const char *db,
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_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_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;
int i, n, ncol = sizeof(buftyp) / sizeof(int);
int len, type, prec;
int prec, len, type, scale;
bool mysql;
TABLE_SHARE *s = NULL;
Field* *field;
......@@ -208,27 +208,32 @@ PQRYRES TabColumns(PGLOBAL g, THD *thd, const char *db,
// When creating tables we do need info about date columns
if (mysql) {
fmt = MyDateFmt(fp->type());
len = strlen(fmt);
prec = len = strlen(fmt);
} else {
fmt = (char*)fp->option_struct->dateformat;
len = fp->field_length;
prec = len = fp->field_length;
} // endif mysql
} else {
fmt = NULL;
if (type == TYPE_DECIM)
prec = ((Field_new_decimal*)fp)->precision;
else
prec = (prec == NOT_FIXED_DEC) ? 0 : fp->field_length;
len = fp->char_length();
fmt = NULL;
} // endif type
crp = crp->Next; // Precision
crp->Kdata->SetValue(len, i);
crp->Kdata->SetValue(prec, i);
crp = crp->Next; // Length
prec = (type == TYPE_FLOAT) ? fp->decimals() : 0;
len = (prec == 31) ? 0 : fp->field_length;
crp->Kdata->SetValue(len, i);
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->Kdata->SetValue(0, i);
......
......@@ -269,7 +269,7 @@ PQRYRES WMIColumns(PGLOBAL g, char *nsp, char *cls, bool info)
case CIM_REAL64:
case CIM_REAL32:
prec = 2;
typ = TYPE_FLOAT;
typ = TYPE_DOUBLE;
lng = 15;
break;
case CIM_SINT64:
......
......@@ -1168,10 +1168,10 @@ bool XMLCOL::SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check)
if (GetDomain() || ((DTVAL *)value)->IsFormatted())
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
// Note: maybe this should be forced by ShowValue instead of this ?
value->SetPrec(GetPrecision());
value->SetPrec(GetScale());
Value = value; // Directly access the external value
} else {
......
......@@ -57,6 +57,7 @@ PVBLK AllocValBlock(PGLOBAL g, void *mp, int type, int nval, int len,
switch (type) {
case TYPE_STRING:
case TYPE_DECIM:
if (len)
blkp = new(g) CHRBLK(mp, nval, len, prec, blank);
else
......@@ -87,7 +88,7 @@ PVBLK AllocValBlock(PGLOBAL g, void *mp, int type, int nval, int len,
blkp = new(g) TYPBLK<longlong>(mp, nval, type);
break;
case TYPE_FLOAT:
case TYPE_DOUBLE:
blkp = new(g) TYPBLK<double>(mp, nval, type, prec);
break;
case TYPE_TINY:
......@@ -343,6 +344,21 @@ ulonglong TYPBLK<longlong>::MaxVal(void) {return INT_MAX64;}
template <>
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. */
/***********************************************************************/
......@@ -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)
{
if (!(Dvalp = AllocateValue(g, TYPE_DATE, len, year, fmt)))
if (!(Dvalp = AllocateValue(g, TYPE_DATE, len, year, false, fmt)))
return true;
return false;
......
......@@ -153,8 +153,9 @@ PSZ GetTypeName(int type)
case TYPE_INT: name = "INTEGER"; break;
case TYPE_BIGINT: name = "BIGINT"; 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_DECIM: name = "DECIMAL"; break;
default: name = "UNKNOWN"; break;
} // endswitch type
......@@ -167,12 +168,13 @@ PSZ GetTypeName(int type)
int GetTypeSize(int type, int len)
{
switch (type) {
case TYPE_DECIM:
case TYPE_STRING: len = len * sizeof(char); break;
case TYPE_SHORT: len = sizeof(short); break;
case TYPE_INT: len = sizeof(int); break;
case TYPE_BIGINT: len = sizeof(longlong); 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;
default: len = 0;
} // endswitch type
......@@ -192,9 +194,10 @@ char *GetFormatType(int type)
case TYPE_SHORT: c = "S"; break;
case TYPE_INT: c = "N"; 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_TINY: c = "T"; break;
case TYPE_DECIM: c = "M"; break;
} // endswitch type
return c;
......@@ -212,15 +215,15 @@ int GetFormatType(char c)
case 'S': type = TYPE_SHORT; break;
case 'N': type = TYPE_INT; 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 'T': type = TYPE_TINY; break;
case 'M': type = TYPE_DECIM; break;
} // endswitch type
return type;
} // end of GetFormatType
/***********************************************************************/
/* IsTypeChar: returns true for character type(s). */
/***********************************************************************/
......@@ -228,6 +231,7 @@ bool IsTypeChar(int type)
{
switch (type) {
case TYPE_STRING:
case TYPE_DECIM:
return true;
} // endswitch type
......@@ -243,10 +247,11 @@ bool IsTypeNum(int type)
case TYPE_INT:
case TYPE_BIGINT:
case TYPE_DATE:
case TYPE_FLOAT:
case TYPE_DOUBLE:
case TYPE_SHORT:
case TYPE_NUM:
case TYPE_TINY:
case TYPE_DECIM:
return true;
} // endswitch type
......@@ -261,10 +266,11 @@ const char *GetFmt(int type, bool un)
const char *fmt;
switch (type) {
case TYPE_DECIM:
case TYPE_STRING: fmt = "%s"; break;
case TYPE_SHORT: fmt = (un) ? "%hu" : "%hd"; 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;
} // endswitch Type
......@@ -293,7 +299,7 @@ int ConvertType(int target, int type, CONV kind, bool match)
if (match && (!IsTypeNum(target) || !IsTypeNum(type)))
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_BIGINT || type == TYPE_BIGINT) ? TYPE_BIGINT
: (target == TYPE_INT || type == TYPE_INT) ? TYPE_INT
......@@ -307,7 +313,7 @@ int ConvertType(int target, int type, CONV kind, bool match)
(IsTypeNum(target) && !IsTypeNum(type))))
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_BIGINT || type == TYPE_BIGINT) ? TYPE_BIGINT
: (target == TYPE_INT || type == TYPE_INT) ? TYPE_INT
......@@ -343,8 +349,8 @@ PVAL AllocateValue(PGLOBAL g, void *value, short type)
case TYPE_BIGINT:
valp = new(g) TYPVAL<longlong>(*(longlong*)value, TYPE_BIGINT);
break;
case TYPE_FLOAT:
valp = new(g) TYPVAL<double>(*(double *)value, TYPE_FLOAT, 2);
case TYPE_DOUBLE:
valp = new(g) TYPVAL<double>(*(double *)value, TYPE_DOUBLE, 2);
break;
case TYPE_TINY:
valp = new(g) TYPVAL<char>(*(char *)value, TYPE_TINY);
......@@ -361,7 +367,8 @@ PVAL AllocateValue(PGLOBAL g, void *value, short type)
/***********************************************************************/
/* 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;
......@@ -373,35 +380,38 @@ PVAL AllocateValue(PGLOBAL g, int type, int len, int prec, PSZ fmt)
valp = new(g) DTVAL(g, len, prec, fmt);
break;
case TYPE_INT:
if (prec)
if (uns)
valp = new(g) TYPVAL<uint>((uint)0, TYPE_INT, 0, true);
else
valp = new(g) TYPVAL<int>((int)0, TYPE_INT);
break;
case TYPE_BIGINT:
if (prec)
if (uns)
valp = new(g) TYPVAL<ulonglong>((ulonglong)0, TYPE_BIGINT, 0, true);
else
valp = new(g) TYPVAL<longlong>((longlong)0, TYPE_BIGINT);
break;
case TYPE_SHORT:
if (prec)
if (uns)
valp = new(g) TYPVAL<ushort>((ushort)0, TYPE_SHORT, 0, true);
else
valp = new(g) TYPVAL<short>((short)0, TYPE_SHORT);
break;
case TYPE_FLOAT:
valp = new(g) TYPVAL<double>(0.0, TYPE_FLOAT, prec);
case TYPE_DOUBLE:
valp = new(g) TYPVAL<double>(0.0, TYPE_DOUBLE, prec);
break;
case TYPE_TINY:
if (prec)
if (uns)
valp = new(g) TYPVAL<uchar>((uchar)0, TYPE_TINY, 0, true);
else
valp = new(g) TYPVAL<char>((char)0, TYPE_TINY);
break;
case TYPE_DECIM:
valp = new(g) DECVAL(g, (PSZ)NULL, len, prec, uns);
break;
default:
sprintf(g->Message, MSG(BAD_VALUE_TYPE), type);
......@@ -412,6 +422,7 @@ PVAL AllocateValue(PGLOBAL g, int type, int len, int prec, PSZ fmt)
return valp;
} // end of AllocateValue
#if 0
/***********************************************************************/
/* Allocate a constant Value converted to newtype. */
/* Can also be used to copy a Value eventually converted. */
......@@ -459,8 +470,8 @@ PVAL AllocateValue(PGLOBAL g, PVAL valp, int newtype, int uns)
case TYPE_DATE:
valp = new(g) DTVAL(g, valp->GetIntValue());
break;
case TYPE_FLOAT:
valp = new(g) TYPVAL<double>(valp->GetFloatValue(), TYPE_FLOAT,
case TYPE_DOUBLE:
valp = new(g) TYPVAL<double>(valp->GetFloatValue(), TYPE_DOUBLE,
valp->GetValPrec());
break;
case TYPE_TINY:
......@@ -479,7 +490,7 @@ PVAL AllocateValue(PGLOBAL g, PVAL valp, int newtype, int uns)
valp->SetGlobal(g);
return valp;
} // end of AllocateValue
#endif // 0
/* -------------------------- Class VALUE ---------------------------- */
......@@ -505,10 +516,11 @@ const char *VALUE::GetXfmt(void)
const char *fmt;
switch (Type) {
case TYPE_DECIM:
case TYPE_STRING: fmt = "%*s"; break;
case TYPE_SHORT: fmt = (Unsigned) ? "%*hu" : "%*hd"; 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;
} // endswitch Type
......@@ -1355,6 +1367,234 @@ bool TYPVAL<PSZ>::SetConstFormat(PGLOBAL g, FORMAT& fmt)
return false;
} // 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 ---------------------------- */
/***********************************************************************/
......
......@@ -47,9 +47,9 @@ DllExport int GetFormatType(char);
DllExport bool IsTypeChar(int type);
DllExport bool IsTypeNum(int type);
//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,
PSZ fmt = NULL);
bool uns = false, PSZ fmt = NULL);
DllExport ulonglong CharToNumber(char *, int, ulonglong, bool,
bool *minus = NULL, bool *rc = NULL);
......@@ -255,6 +255,37 @@ class DllExport TYPVAL<PSZ>: public VALUE {
int Len;
}; // 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. */
/***********************************************************************/
......
......@@ -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)
{
int len = colp->GetLength(), prec = colp->GetPrecision();
int len = colp->GetLength(), prec = colp->GetScale();
// Currently no indexing on NULL columns
if (colp->IsNullable()) {
......@@ -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
Type = colp->GetResultType();
if (!(Valp = AllocateValue(g, Type, len, colp->GetPrecision())))
if (!(Valp = AllocateValue(g, Type, len, colp->GetScale(),
colp->IsUnsigned())))
return true;
Klen = Valp->GetClen();
......@@ -2825,7 +2826,7 @@ BYTE* KXYCOL::MapInit(PGLOBAL g, PCOL colp, int *n, BYTE *m)
#endif
// 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();
if (n[2]) {
......
......@@ -109,6 +109,7 @@ int CONSTANT::GetLengthEx(void)
return Value->GetValLen();
} // end of GetLengthEx
#if 0
/***********************************************************************/
/* Convert a constant to the given type. */
/***********************************************************************/
......@@ -119,6 +120,7 @@ void CONSTANT::Convert(PGLOBAL g, int newtype)
longjmp(g->jumper[g->jump_level], TYPE_CONST);
} // end of Convert
#endif // 0
/***********************************************************************/
/* Compare: returns true if this object is equivalent to xp. */
......@@ -151,7 +153,7 @@ bool CONSTANT::Rephrase(PGLOBAL g, PSZ work)
case TYPE_DATE:
sprintf(work + strlen(work), "%d", Value->GetIntValue());
break;
case TYPE_FLOAT:
case TYPE_DOUBLE:
sprintf(work + strlen(work), "%lf", Value->GetFloatValue());
break;
case TYPE_BIGINT:
......
......@@ -52,7 +52,7 @@ class DllExport XOBJECT : public BLOCK {
virtual short GetShortValue(void);
virtual int GetIntValue(void);
virtual double GetFloatValue(void);
virtual int GetPrecision(void) = 0;
virtual int GetScale(void) = 0;
// Methods
virtual void Reset(void) {}
......@@ -92,7 +92,7 @@ class DllExport XVOID : public XOBJECT {
virtual PSZ GetCharValue(void) {return NULL;}
virtual int GetIntValue(void) {return 0;}
virtual double GetFloatValue(void) {return 0.0;}
virtual int GetPrecision() {return 0;}
virtual int GetScale() {return 0;}
// Methods
virtual bool Compare(PXOB xp) {return xp->GetType() == TYPE_VOID;}
......@@ -115,7 +115,7 @@ class DllExport CONSTANT : public XOBJECT {
virtual int GetType(void) {return TYPE_CONST;}
virtual int GetResultType(void) {return Value->Type;}
virtual int GetLength(void) {return Value->GetValLen();}
virtual int GetPrecision() {return Value->GetValPrec();}
virtual int GetScale() {return Value->GetValPrec();}
virtual int GetLengthEx(void);
// Methods
......@@ -123,7 +123,7 @@ class DllExport CONSTANT : public XOBJECT {
virtual bool SetFormat(PGLOBAL g, FORMAT& fmt)
{return Value->SetConstFormat(g, fmt);}
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);
void SetValue(PVAL vp) {Value = vp;}
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