diff options
author | Olivier Bertrand <bertrandop@gmail.com> | 2013-12-28 15:46:49 +0100 |
---|---|---|
committer | Olivier Bertrand <bertrandop@gmail.com> | 2013-12-28 15:46:49 +0100 |
commit | c055e5e0efcdd3750550230a483cdf8847b3d414 (patch) | |
tree | 77384e1d1f2f168c3d1df7a58d72a620f3416e46 /storage | |
parent | 889b08b050a1d7e8a5bb842e5d72b4b18be139e4 (diff) | |
download | mariadb-git-c055e5e0efcdd3750550230a483cdf8847b3d414.tar.gz |
- 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
Diffstat (limited to 'storage')
32 files changed, 619 insertions, 241 deletions
diff --git a/storage/connect/catalog.h b/storage/connect/catalog.h index 3a06aea7a30..a61b1a53653 100644 --- a/storage/connect/catalog.h +++ b/storage/connect/catalog.h @@ -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; diff --git a/storage/connect/colblk.cpp b/storage/connect/colblk.cpp index 6b2921e1737..bce26e25387 100644 --- a/storage/connect/colblk.cpp +++ b/storage/connect/colblk.cpp @@ -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; diff --git a/storage/connect/colblk.h b/storage/connect/colblk.h index 7b5fe0cad0f..320350f1923 100644 --- a/storage/connect/colblk.h +++ b/storage/connect/colblk.h @@ -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 diff --git a/storage/connect/filamdbf.cpp b/storage/connect/filamdbf.cpp index c7f389b3ac5..c7ffe74c760 100644 --- a/storage/connect/filamdbf.cpp +++ b/storage/connect/filamdbf.cpp @@ -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 ??? diff --git a/storage/connect/global.h b/storage/connect/global.h index 3702f050501..4c0bc993123 100644 --- a/storage/connect/global.h +++ b/storage/connect/global.h @@ -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" diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc index 706f29175d6..8b0e3a2b036 100644 --- a/storage/connect/ha_connect.cc +++ b/storage/connect/ha_connect.cc @@ -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,7 +3590,11 @@ 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))); - } // endif dec + } 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(')'); } // endif len @@ -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; - // Some data sources do not count dec in length (prec) - if (typ == TYPE_FLOAT) - prec += (dec + 2); // To be safe - else - dec= 0; + switch (typ) { + case TYPE_DOUBLE: + // Some data sources do not count dec in length (prec) + prec += (dec + 2); // To be safe + 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 diff --git a/storage/connect/myconn.cpp b/storage/connect/myconn.cpp index 08410793792..769aa5a581c 100644 --- a/storage/connect/myconn.cpp +++ b/storage/connect/myconn.cpp @@ -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; diff --git a/storage/connect/mysql-test/connect/r/mysql_new.result b/storage/connect/mysql-test/connect/r/mysql_new.result index 152d963efa7..327afa34446 100644 --- a/storage/connect/mysql-test/connect/r/mysql_new.result +++ b/storage/connect/mysql-test/connect/r/mysql_new.result @@ -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 diff --git a/storage/connect/mysql-test/connect/r/odbc_oracle.result b/storage/connect/mysql-test/connect/r/odbc_oracle.result index 7f9bfd8a30e..fff2f192184 100644 --- a/storage/connect/mysql-test/connect/r/odbc_oracle.result +++ b/storage/connect/mysql-test/connect/r/odbc_oracle.result @@ -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; diff --git a/storage/connect/myutil.cpp b/storage/connect/myutil.cpp index 4bfdc1a03ec..1594afb1b3d 100644 --- a/storage/connect/myutil.cpp +++ b/storage/connect/myutil.cpp @@ -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: diff --git a/storage/connect/odbconn.cpp b/storage/connect/odbconn.cpp index 846d8963502..a8a393d0ab7 100644 --- a/storage/connect/odbconn.cpp +++ b/storage/connect/odbconn.cpp @@ -1,5 +1,5 @@ /************ 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; @@ -1648,35 +1651,35 @@ int ODBConn::ExecuteSQL(void) /***********************************************************************/ bool ODBConn::BindParam(ODBCCOL *colp) { - void *buf; - UWORD n = colp->GetRank(); - SWORD ct, sqlt; - UDWORD len; - SQLLEN *strlen = colp->GetStrLen(); - RETCODE rc; + void *buf; + int buftype = colp->GetResultType(); + SQLUSMALLINT n = colp->GetRank(); + SQLSMALLINT ct, sqlt, dec, nul; + SQLULEN colsize; + SQLLEN len; + SQLLEN *strlen = colp->GetStrLen(); + 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; diff --git a/storage/connect/plgdbutl.cpp b/storage/connect/plgdbutl.cpp index 26aa4681878..b5c4239c992 100644 --- a/storage/connect/plgdbutl.cpp +++ b/storage/connect/plgdbutl.cpp @@ -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; diff --git a/storage/connect/rcmsg.c b/storage/connect/rcmsg.c index 25dd4df7a92..bac420e696f 100644 --- a/storage/connect/rcmsg.c +++ b/storage/connect/rcmsg.c @@ -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 appelée par le moteur %s"; break; - case IDS_TAB_01: p = "Qualificateur"; break; - case IDS_TAB_02: p = "Propriétaire"; break; + case IDS_TAB_01: p = "Catalogue"; break; + case IDS_TAB_02: p = "Schéma"; 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_Données"; 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 = "Numéro_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; diff --git a/storage/connect/reldef.cpp b/storage/connect/reldef.cpp index 93d15747911..81c9bf9faca 100644 --- a/storage/connect/reldef.cpp +++ b/storage/connect/reldef.cpp @@ -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; diff --git a/storage/connect/reldef.h b/storage/connect/reldef.h index e443374b676..a877c8ee915 100644 --- a/storage/connect/reldef.h +++ b/storage/connect/reldef.h @@ -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 diff --git a/storage/connect/tabcol.cpp b/storage/connect/tabcol.cpp index 9af52043f0c..efd863a88cf 100644 --- a/storage/connect/tabcol.cpp +++ b/storage/connect/tabcol.cpp @@ -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 diff --git a/storage/connect/tabcol.h b/storage/connect/tabcol.h index c5ebfdbb10d..fe643e075c3 100644 --- a/storage/connect/tabcol.h +++ b/storage/connect/tabcol.h @@ -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;} diff --git a/storage/connect/tabdos.cpp b/storage/connect/tabdos.cpp index 2baf9de155f..15215dc0f01 100644 --- a/storage/connect/tabdos.cpp +++ b/storage/connect/tabdos.cpp @@ -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()); diff --git a/storage/connect/tabfmt.cpp b/storage/connect/tabfmt.cpp index 95ea232d798..9a121b9ab9a 100644 --- a/storage/connect/tabfmt.cpp +++ b/storage/connect/tabfmt.cpp @@ -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); diff --git a/storage/connect/tabmysql.cpp b/storage/connect/tabmysql.cpp index 12b206a911a..fcf083bcbce 100644 --- a/storage/connect/tabmysql.cpp +++ b/storage/connect/tabmysql.cpp @@ -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 { diff --git a/storage/connect/tabodbc.cpp b/storage/connect/tabodbc.cpp index 9d705d7e757..1fb71e33646 100644 --- a/storage/connect/tabodbc.cpp +++ b/storage/connect/tabodbc.cpp @@ -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,7 +1056,14 @@ void ODBCCOL::ReadColumn(PGLOBAL g) dbtime.tm_mon = (int)Sqlbuf->month - 1; dbtime.tm_year = (int)Sqlbuf->year - 1900; ((DTVAL*)Value)->MakeTime(&dbtime); - } // endif Buf_Type + } 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) { char buf[32]; @@ -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; - } // endif Buf_Type + } 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 diff --git a/storage/connect/tabodbc.h b/storage/connect/tabodbc.h index a55e0c1f5b2..35864bab5ef 100644 --- a/storage/connect/tabodbc.h +++ b/storage/connect/tabodbc.h @@ -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 diff --git a/storage/connect/tabsys.cpp b/storage/connect/tabsys.cpp index a7fc9346d1f..2bb5532cea0 100644 --- a/storage/connect/tabsys.cpp +++ b/storage/connect/tabsys.cpp @@ -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 { diff --git a/storage/connect/tabutil.cpp b/storage/connect/tabutil.cpp index 48b6d008a31..de5f4a1004b 100644 --- a/storage/connect/tabutil.cpp +++ b/storage/connect/tabutil.cpp @@ -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, - 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, - 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}; + int buftyp[] = {TYPE_STRING, TYPE_SHORT, TYPE_STRING, TYPE_INT, + TYPE_INT, TYPE_SHORT, TYPE_SHORT, TYPE_SHORT, + TYPE_STRING, TYPE_STRING, TYPE_STRING}; + XFLD fldtyp[] = {FLD_NAME, FLD_TYPE, FLD_TYPENAME, FLD_PREC, + FLD_LENGTH, FLD_SCALE, FLD_RADIX, FLD_NULL, + FLD_REM, FLD_NO, FLD_CHARSET}; + 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); diff --git a/storage/connect/tabwmi.cpp b/storage/connect/tabwmi.cpp index 6d3d1609430..8f91d9b3ed8 100644 --- a/storage/connect/tabwmi.cpp +++ b/storage/connect/tabwmi.cpp @@ -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: diff --git a/storage/connect/tabxml.cpp b/storage/connect/tabxml.cpp index 3feba14ca5e..5fef4fd9ef0 100644 --- a/storage/connect/tabxml.cpp +++ b/storage/connect/tabxml.cpp @@ -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 { diff --git a/storage/connect/valblk.cpp b/storage/connect/valblk.cpp index b041760e1c4..bef5d6ef716 100644 --- a/storage/connect/valblk.cpp +++ b/storage/connect/valblk.cpp @@ -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; diff --git a/storage/connect/value.cpp b/storage/connect/value.cpp index 8857608015e..65a08ba277e 100644 --- a/storage/connect/value.cpp +++ b/storage/connect/value.cpp @@ -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,36 +380,39 @@ 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); return NULL; @@ -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 ---------------------------- */ /***********************************************************************/ diff --git a/storage/connect/value.h b/storage/connect/value.h index 185234b42b9..f8e89ba55fd 100644 --- a/storage/connect/value.h +++ b/storage/connect/value.h @@ -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); @@ -256,6 +256,37 @@ class DllExport TYPVAL<PSZ>: public VALUE { }; // 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 DllExport DTVAL : public TYPVAL<int> { diff --git a/storage/connect/xindex.cpp b/storage/connect/xindex.cpp index 46ddba52332..601374ef5d7 100755 --- a/storage/connect/xindex.cpp +++ b/storage/connect/xindex.cpp @@ -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]) { diff --git a/storage/connect/xobject.cpp b/storage/connect/xobject.cpp index 3da78426e95..aa87517bd2e 100644 --- a/storage/connect/xobject.cpp +++ b/storage/connect/xobject.cpp @@ -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: diff --git a/storage/connect/xobject.h b/storage/connect/xobject.h index 74d571a6e60..b7869be96b2 100644 --- a/storage/connect/xobject.h +++ b/storage/connect/xobject.h @@ -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;} |