summaryrefslogtreecommitdiff
path: root/storage
diff options
context:
space:
mode:
authorOlivier Bertrand <bertrandop@gmail.com>2013-12-03 22:59:40 +0100
committerOlivier Bertrand <bertrandop@gmail.com>2013-12-03 22:59:40 +0100
commitee2f04450b45515c507e4511c26e48e2b846aa73 (patch)
tree2c1d9bec56e1268c8c41629ae1dd4f1d8253f471 /storage
parentd240a0418cf6d59fba711f0677f164d9ee881b7e (diff)
downloadmariadb-git-ee2f04450b45515c507e4511c26e48e2b846aa73.tar.gz
- Add support for unsigned numeric types
added: storage/connect/mysql-test/connect/r/unsigned.result storage/connect/mysql-test/connect/t/unsigned.test modified: storage/connect/colblk.cpp storage/connect/colblk.h storage/connect/connect.cc storage/connect/ha_connect.cc storage/connect/myconn.cpp storage/connect/mysql-test/connect/r/mysql_discovery.result storage/connect/mysql-test/connect/r/xml.result storage/connect/myutil.cpp storage/connect/myutil.h storage/connect/plgdbsem.h storage/connect/tabdos.cpp storage/connect/tabfix.cpp storage/connect/tabmysql.cpp storage/connect/tabutil.cpp storage/connect/valblk.cpp storage/connect/valblk.h storage/connect/value.cpp storage/connect/value.h storage/connect/xobject.cpp storage/connect/xobject.h
Diffstat (limited to 'storage')
-rw-r--r--storage/connect/colblk.cpp7
-rw-r--r--storage/connect/colblk.h1
-rw-r--r--storage/connect/connect.cc34
-rw-r--r--storage/connect/ha_connect.cc67
-rw-r--r--storage/connect/myconn.cpp74
-rw-r--r--storage/connect/mysql-test/connect/r/mysql_discovery.result2
-rw-r--r--storage/connect/mysql-test/connect/r/unsigned.result73
-rw-r--r--storage/connect/mysql-test/connect/r/xml.result2
-rw-r--r--storage/connect/mysql-test/connect/t/unsigned.test34
-rw-r--r--storage/connect/myutil.cpp5
-rw-r--r--storage/connect/myutil.h2
-rw-r--r--storage/connect/plgdbsem.h4
-rw-r--r--storage/connect/tabdos.cpp13
-rw-r--r--storage/connect/tabfix.cpp7
-rw-r--r--storage/connect/tabmysql.cpp9
-rw-r--r--storage/connect/tabutil.cpp26
-rw-r--r--storage/connect/valblk.cpp184
-rw-r--r--storage/connect/valblk.h31
-rw-r--r--storage/connect/value.cpp3642
-rw-r--r--storage/connect/value.h67
-rw-r--r--storage/connect/xobject.cpp2
-rw-r--r--storage/connect/xobject.h2
22 files changed, 2344 insertions, 1944 deletions
diff --git a/storage/connect/colblk.cpp b/storage/connect/colblk.cpp
index 2953fa29493..6b2921e1737 100644
--- a/storage/connect/colblk.cpp
+++ b/storage/connect/colblk.cpp
@@ -41,6 +41,7 @@ COLBLK::COLBLK(PCOLDEF cdp, PTDB tdbp, int i)
Buf_Type = cdp->Buf_Type;
ColUse |= cdp->Flags; // Used by CONNECT
Nullable = !!(cdp->Flags & U_NULLS);
+ Unsigned = !!(cdp->Flags & U_UNSIGNED);
} else {
Name = NULL;
memset(&Format, 0, sizeof(FORMAT));
@@ -48,6 +49,7 @@ COLBLK::COLBLK(PCOLDEF cdp, PTDB tdbp, int i)
Long = 0;
Buf_Type = TYPE_ERROR;
Nullable = false;
+ Unsigned = false;
} // endif cdp
To_Tdb = tdbp;
@@ -171,9 +173,12 @@ 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,
- GetPrecision(), GetDomain())))
+ prec, GetDomain())))
return true;
AddStatus(BUF_READY);
diff --git a/storage/connect/colblk.h b/storage/connect/colblk.h
index a5771ccc6fa..7b5fe0cad0f 100644
--- a/storage/connect/colblk.h
+++ b/storage/connect/colblk.h
@@ -83,6 +83,7 @@ class DllExport COLBLK : public XOBJECT {
PTDB To_Tdb; // Points to Table Descriptor Block
PXCOL To_Kcol; // Points to Xindex matching column
bool Nullable; // True if nullable
+ bool Unsigned; // True if unsigned
int Index; // Column number in table
int Opt; // Cluster/sort information
int Buf_Type; // Data type
diff --git a/storage/connect/connect.cc b/storage/connect/connect.cc
index fd5f6fe6d5d..688e7c092c1 100644
--- a/storage/connect/connect.cc
+++ b/storage/connect/connect.cc
@@ -685,6 +685,7 @@ RCODE CntIndexRead(PGLOBAL g, PTDB ptdb, OPVAL op,
char *kp= (char*)key;
int n;
short lg;
+ bool rcb;
RCODE rc;
PVAL valp;
PCOL colp;
@@ -719,9 +720,20 @@ RCODE CntIndexRead(PGLOBAL g, PTDB ptdb, OPVAL op,
if (colp->GetColUse(U_VAR)) {
lg= *(short*)kp;
kp+= sizeof(short);
- valp->SetValue_char(kp, (int)lg);
+ rcb= valp->SetValue_char(kp, (int)lg);
} else
- valp->SetValue_char(kp, valp->GetClen());
+ rcb= valp->SetValue_char(kp, valp->GetClen());
+
+ if (rcb) {
+ if (tdbp->RowNumber(g))
+ sprintf(g->Message, "Out of range value for column %s at row %d",
+ colp->GetName(), tdbp->RowNumber(g));
+ else
+ sprintf(g->Message, "Out of range value for column %s",
+ colp->GetName());
+
+ PushWarning(g, tdbp);
+ } // endif b
} else
valp->SetBinValue((void*)kp);
@@ -759,7 +771,7 @@ int CntIndexRange(PGLOBAL g, PTDB ptdb, const uchar* *key, uint *len,
const uchar *p, *kp;
int i, n, k[2];
short lg;
- bool b;
+ bool b, rcb;
PVAL valp;
PCOL colp;
PTDBDOX tdbp;
@@ -802,9 +814,21 @@ int CntIndexRange(PGLOBAL g, PTDB ptdb, const uchar* *key, uint *len,
if (colp->GetColUse(U_VAR)) {
lg= *(short*)p;
p+= sizeof(short);
- valp->SetValue_char((char*)p, (int)lg);
+ rcb= valp->SetValue_char((char*)p, (int)lg);
} else
- valp->SetValue_char((char*)p, valp->GetClen());
+ rcb= valp->SetValue_char((char*)p, valp->GetClen());
+
+ if (rcb) {
+ if (tdbp->RowNumber(g))
+ sprintf(g->Message,
+ "Out of range value for column %s at row %d",
+ colp->GetName(), tdbp->RowNumber(g));
+ else
+ sprintf(g->Message, "Out of range value for column %s",
+ colp->GetName());
+
+ PushWarning(g, tdbp);
+ } // endif b
} else
valp->SetBinValue((void*)p);
diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc
index 038fb05839a..f9a9fac11cc 100644
--- a/storage/connect/ha_connect.cc
+++ b/storage/connect/ha_connect.cc
@@ -165,7 +165,7 @@ extern "C" char nmfile[];
extern "C" char pdebug[];
extern "C" {
- char version[]= "Version 1.01.0009 October 29, 2013";
+ char version[]= "Version 1.01.0010 November 30, 2013";
#if defined(XMSG)
char msglang[]; // Default message language
@@ -777,7 +777,7 @@ int ha_connect::GetIntegerOption(char *opname)
if (opval == (ulonglong)NO_IVAL && options && options->oplist)
if ((pv= GetListOption(xp->g, opname, options->oplist)))
- opval= (unsigned)atoll(pv);
+ opval= CharToNumber(pv, strlen(pv), ULONGLONG_MAX, true);
return (int)opval;
} // end of GetIntegerOption
@@ -936,6 +936,12 @@ void *ha_connect::GetColumnOption(PGLOBAL g, void *field, PCOLINFO pcf)
break;
} // endswitch type
+ if (fp->flags & UNSIGNED_FLAG)
+ pcf->Flags |= U_UNSIGNED;
+
+ if (fp->flags & ZEROFILL_FLAG)
+ pcf->Flags |= U_ZEROFILL;
+
// This is used to skip null bit
if (fp->real_maybe_null())
pcf->Flags |= U_NULLS;
@@ -1341,7 +1347,15 @@ int ha_connect::MakeRecord(char *buf)
} else
if (fp->store(value->GetFloatValue())) {
- rc= HA_ERR_WRONG_IN_RECORD;
+// rc= HA_ERR_WRONG_IN_RECORD; a Warning was ignored
+ char buf[128];
+ THD *thd= ha_thd();
+
+ sprintf(buf, "Out of range value for column '%s' at row %ld",
+ fp->field_name,
+ thd->get_stmt_da()->current_row_for_warning());
+
+ push_warning(thd, Sql_condition::WARN_LEVEL_WARN, 0, buf);
DBUG_PRINT("MakeRecord", ("%s", value->GetCharString(val)));
} // endif store
@@ -3511,7 +3525,7 @@ static bool add_fields(PGLOBAL g,
#else // !NEW_WAY
static bool add_field(String *sql, const char *field_name, int typ,
int len, int dec, uint tm, const char *rem,
- int flag, bool dbf, char v)
+ char *dft, int flag, bool dbf, char v)
{
char var = (len > 255) ? 'V' : v;
bool error= false;
@@ -3535,9 +3549,26 @@ static bool add_field(String *sql, const char *field_name, int typ,
error|= sql->append(')');
} // endif len
+ if (v == 'U')
+ error|= sql->append(" UNSIGNED");
+ else if (v == 'Z')
+ error|= sql->append(" ZEROFILL");
+
if (tm)
error|= sql->append(STRING_WITH_LEN(" NOT NULL"), system_charset_info);
+ if (dft && *dft) {
+ error|= sql->append(" DEFAULT ");
+
+ if (IsTypeChar(typ)) {
+ error|= sql->append("'");
+ error|= sql->append_for_single_quote(dft, strlen(dft));
+ error|= sql->append("'");
+ } else
+ error|= sql->append(dft);
+
+ } // endif rem
+
if (rem && *rem) {
error|= sql->append(" COMMENT '");
error|= sql->append_for_single_quote(rem, strlen(rem));
@@ -4044,8 +4075,8 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
} // endif src
if (ok) {
- char *cnm, *rem;
- int i, len, dec, typ, flg;
+ char *cnm, *rem, *dft;
+ int i, len, prec, dec, typ, flg;
PDBUSER dup= PlgGetUser(g);
PCATLG cat= (dup) ? dup->Catalog : NULL;
@@ -4154,16 +4185,17 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
NOT_NULL_FLAG, "", flg, dbf);
#else // !NEW_WAY
// Now add the field
- if (add_field(&sql, cnm, typ, len, dec, NOT_NULL_FLAG, 0, flg, dbf, 0))
+ if (add_field(&sql, cnm, typ, len, dec, NOT_NULL_FLAG, 0, NULL, flg, dbf, 0))
rc= HA_ERR_OUT_OF_MEM;
#endif // !NEW_WAY
} // endfor crp
} else // Not a catalog table
for (i= 0; !rc && i < qrp->Nblin; i++) {
- typ= len= dec= 0;
+ typ= len= prec= dec= 0;
tm= NOT_NULL_FLAG;
cnm= (char*)"noname";
+ dft= NULL;
#if defined(NEW_WAY)
rem= "";
// cs= NULL;
@@ -4181,6 +4213,10 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
v = (crp->Nulls) ? crp->Nulls[i] : 0;
break;
case FLD_PREC:
+ // PREC must be always before LENGTH
+ len= prec= crp->Kdata->GetIntValue(i);
+ break;
+ case FLD_LENGTH:
len= crp->Kdata->GetIntValue(i);
break;
case FLD_SCALE:
@@ -4200,6 +4236,9 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
// cs= get_charset_by_name(csn, 0);
// break;
+ case FLD_DEFAULT:
+ dft= crp->Kdata->GetCharValue(i);
+ break;
default:
break; // Ignore
} // endswitch Fld
@@ -4209,16 +4248,16 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
int plgtyp;
// typ must be PLG type, not SQL type
- if (!(plgtyp= TranslateSQLType(typ, dec, len, v))) {
+ if (!(plgtyp= TranslateSQLType(typ, dec, prec, v))) {
sprintf(g->Message, "Unsupported SQL type %d", typ);
my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0));
return HA_ERR_INTERNAL_ERROR;
} else
typ= plgtyp;
- // Some data sources do not count dec in length
+ // Some data sources do not count dec in length (prec)
if (typ == TYPE_FLOAT)
- len += (dec + 2); // To be safe
+ prec += (dec + 2); // To be safe
else
dec= 0;
@@ -4227,14 +4266,16 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
// Make the arguments as required by add_fields
if (typ == TYPE_DATE)
- len= 0;
+ prec= 0;
+ else if (typ == TYPE_FLOAT)
+ prec= len;
// Now add the field
#if defined(NEW_WAY)
rc= add_fields(g, thd, &alter_info, cnm, typ, len, dec,
tm, rem, 0, true);
#else // !NEW_WAY
- if (add_field(&sql, cnm, typ, len, dec, tm, rem, 0, dbf, v))
+ if (add_field(&sql, cnm, typ, prec, dec, tm, rem, dft, 0, dbf, v))
rc= HA_ERR_OUT_OF_MEM;
#endif // !NEW_WAY
} // endfor i
diff --git a/storage/connect/myconn.cpp b/storage/connect/myconn.cpp
index f9763f0eb2f..d2a130e103f 100644
--- a/storage/connect/myconn.cpp
+++ b/storage/connect/myconn.cpp
@@ -46,21 +46,6 @@
#define DLL_EXPORT // Items are exported from this DLL
#include "myconn.h"
-#if defined(EMBEDDED)
-static char *server_args[] = {
- "this_program", /* this string is not used */
- "--skip-bdb",
- "--skip-innodb"
- };
-
-static char *server_groups[] = {
- "PlugDB_SERVER",
- "embedded",
- "server",
- (char *)NULL
- };
-#endif // EMBEDDED
-
extern "C" int trace;
extern MYSQL_PLUGIN_IMPORT uint mysqld_port;
@@ -82,12 +67,12 @@ PQRYRES MyColumns(PGLOBAL g, const char *host, const char *db,
{
static int buftyp[] = {TYPE_STRING, TYPE_SHORT, TYPE_STRING, TYPE_INT,
TYPE_STRING, TYPE_SHORT, TYPE_SHORT, TYPE_SHORT,
- TYPE_STRING, TYPE_STRING, TYPE_STRING};
+ TYPE_STRING, TYPE_STRING, TYPE_STRING, TYPE_STRING};
static XFLD fldtyp[] = {FLD_NAME, FLD_TYPE, FLD_TYPENAME, FLD_PREC,
FLD_KEY, FLD_SCALE, FLD_RADIX, FLD_NULL,
- FLD_REM, FLD_NO, FLD_CHARSET};
- static unsigned int length[] = {0, 4, 16, 4, 4, 4, 4, 4, 256, 32, 32};
- char *fld, *fmt, v, cmd[128];
+ FLD_REM, FLD_NO, FLD_DEFAULT, FLD_CHARSET};
+ static unsigned int length[] = {0, 4, 16, 4, 4, 4, 4, 4, 0, 32, 0, 32};
+ char *fld, *fmt, v, cmd[128], uns[16], zero[16];
int i, n, nf, ncol = sizeof(buftyp) / sizeof(int);
int len, type, prec, rc, k = 0;
PQRYRES qrp;
@@ -122,9 +107,10 @@ PQRYRES MyColumns(PGLOBAL g, const char *host, const char *db,
} // endif n
/********************************************************************/
- /* Get the size of the name columns. */
+ /* Get the size of the name and default columns. */
/********************************************************************/
length[0] = myc.GetFieldLength(0);
+ length[10] = myc.GetFieldLength(5);
} else {
n = 0;
length[0] = 128;
@@ -164,18 +150,29 @@ PQRYRES MyColumns(PGLOBAL g, const char *host, const char *db,
crp = qrp->Colresp; // Column_Name
crp->Kdata->SetValue(fld, i);
- // Get type, type name, and precision
+ // Get type, type name, precision, unsigned and zerofill
fld = myc.GetCharField(1);
prec = 0;
len = 0;
v = 0;
-
- if ((nf = sscanf(fld, "%[^(](%d,%d", cmd, &len, &prec)) < 1) {
- sprintf(g->Message, MSG(BAD_FIELD_TYPE), fld);
- myc.Close();
- return NULL;
- } else
- qrp->Nblin++;
+ *uns = 0;
+ *zero = 0;
+
+ switch ((nf = sscanf(fld, "%[^(](%d,%d", cmd, &len, &prec))) {
+ case 3:
+ nf = sscanf(fld, "%[^(](%d,%d) %s %s", cmd, &len, &prec, uns, zero);
+ break;
+ case 2:
+ nf = sscanf(fld, "%[^(](%d) %s %s", cmd, &len, uns, zero) + 1;
+ break;
+ case 1:
+ nf = sscanf(fld, "%s %s %s", cmd, uns, zero) + 2;
+ break;
+ default:
+ sprintf(g->Message, MSG(BAD_FIELD_TYPE), fld);
+ myc.Close();
+ return NULL;
+ } // endswitch nf
if ((type = MYSQLtoPLG(cmd, &v)) == TYPE_ERROR) {
sprintf(g->Message, "Unsupported column type %s", cmd);
@@ -184,9 +181,16 @@ PQRYRES MyColumns(PGLOBAL g, const char *host, const char *db,
} else if (type == TYPE_STRING)
len = min(len, 4096);
+ qrp->Nblin++;
crp = crp->Next; // Data_Type
crp->Kdata->SetValue(type, i);
- crp->Nulls[i] = v;
+
+ switch (nf) {
+ case 5: crp->Nulls[i] = 'Z'; break;
+ case 4: crp->Nulls[i] = 'U'; break;
+ default: crp->Nulls[i] = v; break;
+ } // endswitch nf
+
crp = crp->Next; // Type_Name
crp->Kdata->SetValue(cmd, i);
@@ -200,7 +204,7 @@ PQRYRES MyColumns(PGLOBAL g, const char *host, const char *db,
crp = crp->Next; // Precision
crp->Kdata->SetValue(len, i);
- crp = crp->Next; // was Length
+ crp = crp->Next; // key (was Length)
fld = myc.GetCharField(4);
crp->Kdata->SetValue(fld, i);
@@ -218,9 +222,13 @@ PQRYRES MyColumns(PGLOBAL g, const char *host, const char *db,
fld = myc.GetCharField(8);
crp->Kdata->SetValue(fld, i);
- crp = crp->Next; // New
+ crp = crp->Next; // Date format
crp->Kdata->SetValue((fmt) ? fmt : (char*) "", i);
+ crp = crp->Next; // New (default)
+ fld = myc.GetCharField(5);
+ crp->Kdata->SetValue(fld, i);
+
crp = crp->Next; // New (charset)
fld = myc.GetCharField(2);
crp->Kdata->SetValue(fld, i);
@@ -657,6 +665,7 @@ PQRYRES MYSQLC::GetResult(PGLOBAL g, bool pdb)
{
char *fmt;
int n;
+ bool uns;
PCOLRES *pcrp, crp;
PQRYRES qrp;
MYSQL_FIELD *fld;
@@ -707,9 +716,10 @@ PQRYRES MYSQLC::GetResult(PGLOBAL g, bool pdb)
crp->Prec = (crp->Type == TYPE_FLOAT) ? fld->decimals : 0;
crp->Length = fld->max_length;
crp->Clen = GetTypeSize(crp->Type, crp->Length);
+ uns = (fld->flags & (UNSIGNED_FLAG | ZEROFILL_FLAG)) ? true : false;
if (!(crp->Kdata = AllocValBlock(g, NULL, crp->Type, m_Rows,
- crp->Clen, 0, FALSE, TRUE, FALSE))) {
+ crp->Clen, 0, FALSE, TRUE, uns))) {
sprintf(g->Message, MSG(INV_RESULT_TYPE),
GetFormatType(crp->Type));
return NULL;
diff --git a/storage/connect/mysql-test/connect/r/mysql_discovery.result b/storage/connect/mysql-test/connect/r/mysql_discovery.result
index 2fc2039e53e..04c902d983a 100644
--- a/storage/connect/mysql-test/connect/r/mysql_discovery.result
+++ b/storage/connect/mysql-test/connect/r/mysql_discovery.result
@@ -15,7 +15,7 @@ t1 CREATE TABLE `t1` (
`id` int(20) NOT NULL,
`group` int(11) NOT NULL,
`a\\b` int(11) NOT NULL,
- `a\\` int(10) DEFAULT NULL,
+ `a\\` int(10) unsigned DEFAULT NULL,
`name` varchar(32) DEFAULT NULL
) ENGINE=CONNECT DEFAULT CHARSET=latin1 CONNECTION='mysql://root@127.0.0.1:SLAVE_PORT/test/t1' `TABLE_TYPE`='MYSQL'
INSERT INTO t1 (id, name) VALUES (1, 'foo');
diff --git a/storage/connect/mysql-test/connect/r/unsigned.result b/storage/connect/mysql-test/connect/r/unsigned.result
new file mode 100644
index 00000000000..9f4a4470721
--- /dev/null
+++ b/storage/connect/mysql-test/connect/r/unsigned.result
@@ -0,0 +1,73 @@
+#
+# Testing unsigned types
+#
+DROP TABLE IF EXISTS t1;
+Warnings:
+Note 1051 Unknown table 'test.t1'
+CREATE TABLE t1 (
+a TINYINT UNSIGNED NOT NULL,
+b SMALLINT ZEROFILL NOT NULL,
+c INT UNSIGNED NOT NULL,
+d BIGINT UNSIGNED NOT NULL,
+e CHAR(32) NOT NULL DEFAULT '???') ENGINE=CONNECT TABLE_TYPE=FIX;
+Warnings:
+Warning 1105 No file name. Table will use t1.fix
+DESCRIBE t1;
+Field Type Null Key Default Extra
+a tinyint(3) unsigned NO NULL
+b smallint(5) unsigned zerofill NO NULL
+c int(10) unsigned NO NULL
+d bigint(20) unsigned NO NULL
+e char(32) NO ???
+INSERT INTO t1(a,b,c,d) VALUES(255,65535,4294967295,18446744073709551615);
+SELECT * FROM t1;
+a b c d e
+255 65535 4294967295 18446744073709551615 ???
+UPDATE t1 SET e = d;
+SELECT * FROM t1;
+a b c d e
+255 65535 4294967295 18446744073709551615 18446744073709551615
+UPDATE t1 SET c = d;
+Warnings:
+Warning 1264 Out of range value for column 'c' at row 1
+SELECT * FROM t1;
+a b c d e
+255 65535 4294967295 18446744073709551615 18446744073709551615
+UPDATE t1 SET c = e;
+Warnings:
+Warning 1264 Out of range value for column 'c' at row 1
+SELECT * FROM t1;
+a b c d e
+255 65535 4294967295 18446744073709551615 18446744073709551615
+UPDATE t1 SET d = e;
+SELECT * FROM t1;
+a b c d e
+255 65535 4294967295 18446744073709551615 18446744073709551615
+DROP TABLE IF EXISTS t2;
+Warnings:
+Note 1051 Unknown table 'test.t2'
+CREATE TABLE t2 ENGINE=CONNECT TABLE_TYPE=PROXY TABNAME=t1;
+DESCRIBE t2;
+Field Type Null Key Default Extra
+a tinyint(3) unsigned NO NULL
+b smallint(5) unsigned zerofill NO NULL
+c int(10) unsigned NO NULL
+d bigint(20) unsigned NO NULL
+e char(32) NO NULL
+SELECT * FROM t2;
+a b c d e
+255 65535 4294967295 18446744073709551615 18446744073709551615
+DROP TABLE t2;
+CREATE TABLE t2 ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME=t1;
+DESCRIBE t2;
+Field Type Null Key Default Extra
+a tinyint(3) unsigned NO NULL
+b smallint(5) unsigned zerofill NO NULL
+c int(10) unsigned NO NULL
+d bigint(20) unsigned NO NULL
+e char(32) NO ???
+SELECT * FROM t2;
+a b c d e
+255 65535 4294967295 18446744073709551615 18446744073709551615
+DROP TABLE t2;
+DROP TABLE t1;
diff --git a/storage/connect/mysql-test/connect/r/xml.result b/storage/connect/mysql-test/connect/r/xml.result
index a8d2ded7bcf..e952cc3a635 100644
--- a/storage/connect/mysql-test/connect/r/xml.result
+++ b/storage/connect/mysql-test/connect/r/xml.result
@@ -413,7 +413,7 @@ DROP TABLE t1;
SET @a=LOAD_FILE('MYSQLD_DATADIR/test/t1.xml');
SELECT CAST(@a AS CHAR CHARACTER SET latin1);
CAST(@a AS CHAR CHARACTER SET latin1) <?xml version="1.0" encoding="iso-8859-1"?>
-<!-- Created by CONNECT Version 1.01.0009 October 29, 2013 -->
+<!-- Created by CONNECT Version 1.01.0010 November 30, 2013 -->
<t1>
<line>
<node>ÀÃÂÃ</node>
diff --git a/storage/connect/mysql-test/connect/t/unsigned.test b/storage/connect/mysql-test/connect/t/unsigned.test
new file mode 100644
index 00000000000..5119142ba52
--- /dev/null
+++ b/storage/connect/mysql-test/connect/t/unsigned.test
@@ -0,0 +1,34 @@
+--echo #
+--echo # Testing unsigned types
+--echo #
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (
+a TINYINT UNSIGNED NOT NULL,
+b SMALLINT ZEROFILL NOT NULL,
+c INT UNSIGNED NOT NULL,
+d BIGINT UNSIGNED NOT NULL,
+e CHAR(32) NOT NULL DEFAULT '???') ENGINE=CONNECT TABLE_TYPE=FIX;
+DESCRIBE t1;
+INSERT INTO t1(a,b,c,d) VALUES(255,65535,4294967295,18446744073709551615);
+SELECT * FROM t1;
+UPDATE t1 SET e = d;
+SELECT * FROM t1;
+UPDATE t1 SET c = d;
+SELECT * FROM t1;
+UPDATE t1 SET c = e;
+SELECT * FROM t1;
+UPDATE t1 SET d = e;
+SELECT * FROM t1;
+
+DROP TABLE IF EXISTS t2;
+CREATE TABLE t2 ENGINE=CONNECT TABLE_TYPE=PROXY TABNAME=t1;
+DESCRIBE t2;
+SELECT * FROM t2;
+
+DROP TABLE t2;
+CREATE TABLE t2 ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME=t1;
+DESCRIBE t2;
+SELECT * FROM t2;
+
+DROP TABLE t2;
+DROP TABLE t1;
diff --git a/storage/connect/myutil.cpp b/storage/connect/myutil.cpp
index 1b6cbaa84c7..9588a45ee8a 100644
--- a/storage/connect/myutil.cpp
+++ b/storage/connect/myutil.cpp
@@ -143,7 +143,7 @@ const char *PLGtoMYSQLtype(int type, bool dbf, char v)
/************************************************************************/
/* Convert from MySQL type to PlugDB type number */
/************************************************************************/
-int MYSQLtoPLG(int mytype)
+int MYSQLtoPLG(int mytype, char *var)
{
int type;
@@ -177,7 +177,6 @@ int MYSQLtoPLG(int mytype)
case MYSQL_TYPE_TIME:
type = TYPE_DATE;
break;
- case MYSQL_TYPE_STRING:
case MYSQL_TYPE_VAR_STRING:
#if !defined(ALPHA)
case MYSQL_TYPE_VARCHAR:
@@ -186,6 +185,8 @@ int MYSQLtoPLG(int mytype)
case MYSQL_TYPE_TINY_BLOB:
case MYSQL_TYPE_MEDIUM_BLOB:
case MYSQL_TYPE_LONG_BLOB:
+ if (var) *var = 'V';
+ case MYSQL_TYPE_STRING:
type = TYPE_STRING;
break;
default:
diff --git a/storage/connect/myutil.h b/storage/connect/myutil.h
index 46f060e3e17..f5faeec1127 100644
--- a/storage/connect/myutil.h
+++ b/storage/connect/myutil.h
@@ -7,7 +7,7 @@
enum enum_field_types PLGtoMYSQL(int type, bool dbf);
const char *PLGtoMYSQLtype(int type, bool dbf, char var = NULL);
int MYSQLtoPLG(char *typname, char *var = NULL);
-int MYSQLtoPLG(int mytype);
+int MYSQLtoPLG(int mytype, char *var = NULL);
char *MyDateFmt(int mytype);
char *MyDateFmt(char *typname);
diff --git a/storage/connect/plgdbsem.h b/storage/connect/plgdbsem.h
index d8f27603f6c..9e9d84d4a28 100644
--- a/storage/connect/plgdbsem.h
+++ b/storage/connect/plgdbsem.h
@@ -330,7 +330,9 @@ enum COLUSE {U_P = 0x01, /* the projection list. */
U_VIRTUAL = 0x20, /* a VIRTUAL column */
U_NULLS = 0x40, /* The column may have nulls */
U_IS_NULL = 0x80, /* The column has a null value */
- U_SPECIAL = 0x100}; /* The column is special */
+ U_SPECIAL = 0x100, /* The column is special */
+ U_UNSIGNED = 0x200, /* The column type is unsigned */
+ U_ZEROFILL = 0x400}; /* The column is zero filled */
/***********************************************************************/
/* DB description class and block pointer definitions. */
diff --git a/storage/connect/tabdos.cpp b/storage/connect/tabdos.cpp
index 72b3a27b057..2baf9de155f 100644
--- a/storage/connect/tabdos.cpp
+++ b/storage/connect/tabdos.cpp
@@ -1087,7 +1087,12 @@ void DOSCOL::ReadColumn(PGLOBAL g)
case TYPE_SHORT:
case TYPE_TINY:
case TYPE_BIGINT:
- Value->SetValue_char(p, field - Dcm);
+ if (Value->SetValue_char(p, field - Dcm)) {
+ sprintf(g->Message, "Out of range value for column %s at row %d",
+ Name, tdbp->RowNumber(g));
+ PushWarning(g, tdbp);
+ } // endif SetValue_char
+
break;
case TYPE_FLOAT:
Value->SetValue_char(p, field);
@@ -1104,7 +1109,11 @@ void DOSCOL::ReadColumn(PGLOBAL g)
} // endswitch Buf_Type
else
- Value->SetValue_char(p, field);
+ if (Value->SetValue_char(p, field)) {
+ sprintf(g->Message, "Out of range value for column %s at row %d",
+ Name, tdbp->RowNumber(g));
+ PushWarning(g, tdbp);
+ } // endif SetValue_char
break;
default:
diff --git a/storage/connect/tabfix.cpp b/storage/connect/tabfix.cpp
index 4cad405452e..2358dc07638 100644
--- a/storage/connect/tabfix.cpp
+++ b/storage/connect/tabfix.cpp
@@ -375,7 +375,12 @@ void BINCOL::ReadColumn(PGLOBAL g)
Value->SetValue(*(double*)p);
break;
case 'C': // Text
- Value->SetValue_char(p, Long);
+ if (Value->SetValue_char(p, Long)) {
+ sprintf(g->Message, "Out of range value for column %s at row %d",
+ Name, tdbp->RowNumber(g));
+ PushWarning(g, tdbp);
+ } // endif SetValue_char
+
break;
default:
sprintf(g->Message, MSG(BAD_BIN_FMT), Fmt, Name);
diff --git a/storage/connect/tabmysql.cpp b/storage/connect/tabmysql.cpp
index 7db44658058..12b206a911a 100644
--- a/storage/connect/tabmysql.cpp
+++ b/storage/connect/tabmysql.cpp
@@ -1284,13 +1284,18 @@ void MYSQLCOL::ReadColumn(PGLOBAL g)
htrc("MySQL ReadColumn: name=%s buf=%s\n", Name, buf);
// TODO: have a true way to differenciate temporal values
- if (strlen(buf) == 8)
+ if (Buf_Type == TYPE_DATE && strlen(buf) == 8)
// This is a TIME value
p = strcat(strcpy(tim, "1970-01-01 "), buf);
else
p = buf;
- Value->SetValue_char(p, strlen(p));
+ if (Value->SetValue_char(p, strlen(p))) {
+ sprintf(g->Message, "Out of range value for column %s at row %d",
+ Name, tdbp->RowNumber(g));
+ PushWarning(g, tdbp);
+ } // endif SetValue_char
+
} else {
if (Nullable)
Value->SetNull(true);
diff --git a/storage/connect/tabutil.cpp b/storage/connect/tabutil.cpp
index fa4c8667a70..8b1b8555f53 100644
--- a/storage/connect/tabutil.cpp
+++ b/storage/connect/tabutil.cpp
@@ -117,7 +117,7 @@ TABLE_SHARE *GetTableShare(PGLOBAL g, THD *thd, const char *db,
/************************************************************************/
/* TabColumns: constructs the result blocks containing all the columns */
-/* of the object table that will be retrieved by GetData commands. */
+/* description of the object table that will be retrieved by discovery.*/
/************************************************************************/
PQRYRES TabColumns(PGLOBAL g, THD *thd, const char *db,
const char *name, bool& info)
@@ -128,8 +128,8 @@ PQRYRES TabColumns(PGLOBAL g, THD *thd, const char *db,
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, 256, 32, 32};
- char *fld, *fmt;
+ static 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;
bool mysql;
@@ -164,6 +164,7 @@ PQRYRES TabColumns(PGLOBAL g, THD *thd, const char *db,
// Some columns must be renamed
for (i = 0, crp = qrp->Colresp; crp; crp = crp->Next)
switch (++i) {
+ case 2: crp->Nulls = (char*)PlugSubAlloc(g, NULL, n); break;
case 10: crp->Name = "Date_fmt"; break;
case 11: crp->Name = "Collation"; break;
} // endswitch i
@@ -181,8 +182,9 @@ PQRYRES TabColumns(PGLOBAL g, THD *thd, const char *db,
crp = qrp->Colresp; // Column_Name
fld = (char *)fp->field_name;
crp->Kdata->SetValue(fld, i);
+ v = 0;
- if ((type = MYSQLtoPLG(fp->type())) == TYPE_ERROR) {
+ if ((type = MYSQLtoPLG(fp->type(), &v)) == TYPE_ERROR) {
sprintf(g->Message, "Unsupported column type %s", GetTypeName(type));
qrp = NULL;
break;
@@ -190,6 +192,14 @@ PQRYRES TabColumns(PGLOBAL g, THD *thd, const char *db,
crp = crp->Next; // Data_Type
crp->Kdata->SetValue(type, i);
+
+ if (fp->flags & ZEROFILL_FLAG)
+ crp->Nulls[i] = 'Z';
+ else if (fp->flags & UNSIGNED_FLAG)
+ crp->Nulls[i] = 'U';
+ else
+ crp->Nulls[i] = v;
+
crp = crp->Next; // Type_Name
crp->Kdata->SetValue(GetTypeName(type), i);
@@ -200,7 +210,7 @@ PQRYRES TabColumns(PGLOBAL g, THD *thd, const char *db,
len = strlen(fmt);
} else {
fmt = (char*)fp->option_struct->dateformat;
- len = fp->field_length;
+ fp->field_length;
} // endif mysql
} else {
@@ -212,10 +222,10 @@ PQRYRES TabColumns(PGLOBAL g, THD *thd, const char *db,
crp->Kdata->SetValue(len, i);
crp = crp->Next; // Length
- len = fp->field_length;
+ prec = (type == TYPE_FLOAT) ? fp->decimals() : 0;
+ len = (prec == 31) ? 0 : fp->field_length;
crp->Kdata->SetValue(len, i);
- prec = (type == TYPE_FLOAT) ? fp->decimals() : 0;
crp = crp->Next; // Scale
crp->Kdata->SetValue(prec, i);
@@ -233,7 +243,7 @@ PQRYRES TabColumns(PGLOBAL g, THD *thd, const char *db,
else
crp->Kdata->Reset(i);
- crp = crp->Next; // New
+ crp = crp->Next; // New (date format)
crp->Kdata->SetValue((fmt) ? fmt : (char*) "", i);
crp = crp->Next; // New (charset)
diff --git a/storage/connect/valblk.cpp b/storage/connect/valblk.cpp
index 7fabad88794..afaff491249 100644
--- a/storage/connect/valblk.cpp
+++ b/storage/connect/valblk.cpp
@@ -191,7 +191,7 @@ void VALBLK::ChkIndx(int n)
void VALBLK::ChkTyp(PVAL v)
{
- if (Check && Type != v->GetType()) {
+ if (Check && (Type != v->GetType() || Unsigned != v->IsUnsigned())) {
PGLOBAL& g = Global;
strcpy(g->Message, MSG(VALTYPE_NOMATCH));
longjmp(g->jumper[g->jump_level], Type);
@@ -201,7 +201,7 @@ void VALBLK::ChkTyp(PVAL v)
void VALBLK::ChkTyp(PVBLK vb)
{
- if (Check && Type != vb->GetType()) {
+ if (Check && (Type != vb->GetType() || Unsigned != vb->IsUnsigned())) {
PGLOBAL& g = Global;
strcpy(g->Message, MSG(VALTYPE_NOMATCH));
longjmp(g->jumper[g->jump_level], Type);
@@ -304,28 +304,44 @@ void TYPBLK<TYPE>::SetValue(PSZ p, int n)
longjmp(g->jumper[g->jump_level], Type);
} // endif Check
- Typp[n] = GetTypedValue(p);
+ bool minus;
+ ulonglong maxval = MaxVal();
+ ulonglong val = CharToNumber(p, strlen(p), maxval, Unsigned, &minus);
+
+ if (minus && val < maxval)
+ Typp[n] = (TYPE)(-(signed)val);
+ else
+ Typp[n] = (TYPE)val;
+
SetNull(n, false);
} // end of SetValue
+template <class TYPE>
+ulonglong TYPBLK<TYPE>::MaxVal(void) {DBUG_ASSERT(false); return 0;}
+
template <>
-int TYPBLK<int>::GetTypedValue(PSZ p) {return atol(p);}
-template <>
-uint TYPBLK<uint>::GetTypedValue(PSZ p) {return (unsigned)atol(p);}
+ulonglong TYPBLK<short>::MaxVal(void) {return INT_MAX16;}
+
template <>
-short TYPBLK<short>::GetTypedValue(PSZ p) {return (short)atoi(p);}
+ulonglong TYPBLK<ushort>::MaxVal(void) {return UINT_MAX16;}
+
template <>
-ushort TYPBLK<ushort>::GetTypedValue(PSZ p) {return (ushort)atoi(p);}
+ulonglong TYPBLK<int>::MaxVal(void) {return INT_MAX32;}
+
template <>
-longlong TYPBLK<longlong>::GetTypedValue(PSZ p) {return atoll(p);}
+ulonglong TYPBLK<uint>::MaxVal(void) {return UINT_MAX32;}
+
template <>
-ulonglong TYPBLK<ulonglong>::GetTypedValue(PSZ p) {return (unsigned)atoll(p);}
+ulonglong TYPBLK<char>::MaxVal(void) {return INT_MAX8;}
+
template <>
-double TYPBLK<double>::GetTypedValue(PSZ p) {return atof(p);}
+ulonglong TYPBLK<uchar>::MaxVal(void) {return UINT_MAX8;}
+
template <>
-char TYPBLK<char>::GetTypedValue(PSZ p) {return (char)atoi(p);}
+ulonglong TYPBLK<longlong>::MaxVal(void) {return INT_MAX64;}
+
template <>
-uchar TYPBLK<uchar>::GetTypedValue(PSZ p) {return (uchar)atoi(p);}
+ulonglong TYPBLK<ulonglong>::MaxVal(void) {return ULONGLONG_MAX;}
/***********************************************************************/
/* Set one value in a block from an array of characters. */
@@ -558,11 +574,35 @@ char *CHRBLK::GetCharValue(int n)
} // end of GetCharValue
/***********************************************************************/
+/* Return the value of the nth element converted to tiny int. */
+/***********************************************************************/
+char CHRBLK::GetTinyValue(int n)
+ {
+ bool m;
+ ulonglong val = CharToNumber((char*)GetValPtr(n), Long, INT_MAX8,
+ false, &m);
+
+ return (m && val < INT_MAX8) ? (char)(-(signed)val) : (char)val;
+ } // end of GetTinyValue
+
+/***********************************************************************/
+/* Return the value of the nth element converted to unsigned tiny int.*/
+/***********************************************************************/
+uchar CHRBLK::GetUTinyValue(int n)
+ {
+ return (uchar)CharToNumber((char*)GetValPtr(n), Long, UINT_MAX8, true);
+ } // end of GetTinyValue
+
+/***********************************************************************/
/* Return the value of the nth element converted to short. */
/***********************************************************************/
short CHRBLK::GetShortValue(int n)
{
- return (short)atoi((char *)GetValPtrEx(n));
+ bool m;
+ ulonglong val = CharToNumber((char*)GetValPtr(n), Long, INT_MAX16,
+ false, &m);
+
+ return (m && val < INT_MAX16) ? (short)(-(signed)val) : (short)val;
} // end of GetShortValue
/***********************************************************************/
@@ -570,7 +610,7 @@ short CHRBLK::GetShortValue(int n)
/***********************************************************************/
ushort CHRBLK::GetUShortValue(int n)
{
- return (ushort)atoi((char *)GetValPtrEx(n));
+ return (ushort)CharToNumber((char*)GetValPtr(n), Long, UINT_MAX16, true);
} // end of GetShortValue
/***********************************************************************/
@@ -578,7 +618,11 @@ ushort CHRBLK::GetUShortValue(int n)
/***********************************************************************/
int CHRBLK::GetIntValue(int n)
{
- return atol((char *)GetValPtrEx(n));
+ bool m;
+ ulonglong val = CharToNumber((char*)GetValPtr(n), Long, INT_MAX32,
+ false, &m);
+
+ return (m && val < INT_MAX32) ? (int)(-(signed)val) : (int)val;
} // end of GetIntValue
/***********************************************************************/
@@ -586,7 +630,7 @@ int CHRBLK::GetIntValue(int n)
/***********************************************************************/
uint CHRBLK::GetUIntValue(int n)
{
- return (unsigned)atol((char *)GetValPtrEx(n));
+ return (uint)CharToNumber((char*)GetValPtr(n), Long, UINT_MAX32, true);
} // end of GetIntValue
/***********************************************************************/
@@ -594,7 +638,11 @@ uint CHRBLK::GetUIntValue(int n)
/***********************************************************************/
longlong CHRBLK::GetBigintValue(int n)
{
- return atoll((char *)GetValPtrEx(n));
+ bool m;
+ ulonglong val = CharToNumber((char*)GetValPtr(n), Long, INT_MAX64,
+ false, &m);
+
+ return (m && val < INT_MAX64) ? (longlong)(-(signed)val) : (longlong)val;
} // end of GetBigintValue
/***********************************************************************/
@@ -602,8 +650,8 @@ longlong CHRBLK::GetBigintValue(int n)
/***********************************************************************/
ulonglong CHRBLK::GetUBigintValue(int n)
{
- return (unsigned)atoll((char *)GetValPtrEx(n));
- } // end of GetBigintValue
+ return CharToNumber((char*)GetValPtr(n), Long, ULONGLONG_MAX, true);
+ } // end of GetUBigintValue
/***********************************************************************/
/* Return the value of the nth element converted to double. */
@@ -614,22 +662,6 @@ double CHRBLK::GetFloatValue(int n)
} // end of GetFloatValue
/***********************************************************************/
-/* Return the value of the nth element converted to tiny int. */
-/***********************************************************************/
-char CHRBLK::GetTinyValue(int n)
- {
- return (char)atoi((char *)GetValPtrEx(n));
- } // end of GetTinyValue
-
-/***********************************************************************/
-/* Return the value of the nth element converted to unsigned tiny int.*/
-/***********************************************************************/
-uchar CHRBLK::GetUTinyValue(int n)
- {
- return (uchar)atoi((char *)GetValPtrEx(n));
- } // end of GetTinyValue
-
-/***********************************************************************/
/* Set one value in a block. */
/***********************************************************************/
void CHRBLK::SetValue(PVAL valp, int n)
@@ -870,6 +902,86 @@ void STRBLK::Init(PGLOBAL g, bool check)
} // end of Init
/***********************************************************************/
+/* Get the tiny value represented by the Strp string. */
+/***********************************************************************/
+char STRBLK::GetTinyValue(int n)
+ {
+ bool m;
+ ulonglong val = CharToNumber(Strp[n], strlen(Strp[n]), INT_MAX8,
+ false, &m);
+
+ return (m && val < INT_MAX8) ? (char)(-(signed)val) : (char)val;
+ } // end of GetTinyValue
+
+/***********************************************************************/
+/* Get the unsigned tiny value represented by the Strp string. */
+/***********************************************************************/
+uchar STRBLK::GetUTinyValue(int n)
+ {
+ return (uchar)CharToNumber(Strp[n], strlen(Strp[n]), UINT_MAX8, true);
+ } // end of GetUTinyValue
+
+/***********************************************************************/
+/* Get the short value represented by the Strp string. */
+/***********************************************************************/
+short STRBLK::GetShortValue(int n)
+ {
+ bool m;
+ ulonglong val = CharToNumber(Strp[n], strlen(Strp[n]), INT_MAX16,
+ false, &m);
+
+ return (m && val < INT_MAX16) ? (short)(-(signed)val) : (short)val;
+ } // end of GetShortValue
+
+/***********************************************************************/
+/* Get the unsigned short value represented by the Strp string. */
+/***********************************************************************/
+ushort STRBLK::GetUShortValue(int n)
+ {
+ return (ushort)CharToNumber(Strp[n], strlen(Strp[n]), UINT_MAX16, true);
+ } // end of GetUshortValue
+
+/***********************************************************************/
+/* Get the integer value represented by the Strp string. */
+/***********************************************************************/
+int STRBLK::GetIntValue(int n)
+ {
+ bool m;
+ ulonglong val = CharToNumber(Strp[n], strlen(Strp[n]), INT_MAX32,
+ false, &m);
+
+ return (m && val < INT_MAX32) ? (int)(-(signed)val) : (int)val;
+ } // end of GetIntValue
+
+/***********************************************************************/
+/* Get the unsigned integer value represented by the Strp string. */
+/***********************************************************************/
+uint STRBLK::GetUIntValue(int n)
+ {
+ return (uint)CharToNumber(Strp[n], strlen(Strp[n]), UINT_MAX32, true);
+ } // end of GetUintValue
+
+/***********************************************************************/
+/* Get the big integer value represented by the Strp string. */
+/***********************************************************************/
+longlong STRBLK::GetBigintValue(int n)
+ {
+ bool m;
+ ulonglong val = CharToNumber(Strp[n], strlen(Strp[n]), INT_MAX64,
+ false, &m);
+
+ return (m && val < INT_MAX64) ? (-(signed)val) : (longlong)val;
+ } // end of GetBigintValue
+
+/***********************************************************************/
+/* Get the unsigned big integer value represented by the Strp string. */
+/***********************************************************************/
+ulonglong STRBLK::GetUBigintValue(int n)
+ {
+ return CharToNumber(Strp[n], strlen(Strp[n]), ULONGLONG_MAX, true);
+ } // end of GetUBigintValue
+
+/***********************************************************************/
/* Set one value in a block from a value in another block. */
/***********************************************************************/
void STRBLK::SetValue(PVBLK pv, int n1, int n2)
diff --git a/storage/connect/valblk.h b/storage/connect/valblk.h
index fb3b0b7e72b..a3669cabd37 100644
--- a/storage/connect/valblk.h
+++ b/storage/connect/valblk.h
@@ -45,9 +45,12 @@ class VALBLK : public BLOCK {
{if (To_Nulls) {To_Nulls[n] = (b) ? '*' : 0;}}
virtual bool IsNull(int n) {return To_Nulls && To_Nulls[n];}
virtual void SetNullable(bool b);
+ virtual bool IsUnsigned(void) {return Unsigned;}
virtual void Init(PGLOBAL g, bool check) = 0;
virtual int GetVlen(void) = 0;
virtual PSZ GetCharValue(int n);
+ virtual char GetTinyValue(int n) = 0;
+ virtual uchar GetUTinyValue(int n) = 0;
virtual short GetShortValue(int n) = 0;
virtual ushort GetUShortValue(int n) = 0;
virtual int GetIntValue(int n) = 0;
@@ -55,8 +58,6 @@ class VALBLK : public BLOCK {
virtual longlong GetBigintValue(int n) = 0;
virtual ulonglong GetUBigintValue(int n) = 0;
virtual double GetFloatValue(int n) = 0;
- virtual char GetTinyValue(int n) = 0;
- virtual uchar GetUTinyValue(int n) = 0;
virtual void ReAlloc(void *mp, int n) {Blkp = mp; Nval = n;}
virtual void Reset(int n) = 0;
virtual bool SetFormat(PGLOBAL g, PSZ fmt, int len, int year = 0);
@@ -123,6 +124,8 @@ class TYPBLK : public VALBLK {
virtual void Init(PGLOBAL g, bool check);
virtual int GetVlen(void) {return sizeof(TYPE);}
//virtual PSZ GetCharValue(int n);
+ virtual char GetTinyValue(int n) {return (char)Typp[n];}
+ virtual uchar GetUTinyValue(int n) {return (uchar)Typp[n];}
virtual short GetShortValue(int n) {return (short)Typp[n];}
virtual ushort GetUShortValue(int n) {return (ushort)Typp[n];}
virtual int GetIntValue(int n) {return (int)Typp[n];}
@@ -130,8 +133,6 @@ class TYPBLK : public VALBLK {
virtual longlong GetBigintValue(int n) {return (longlong)Typp[n];}
virtual ulonglong GetUBigintValue(int n) {return (ulonglong)Typp[n];}
virtual double GetFloatValue(int n) {return (double)Typp[n];}
- virtual char GetTinyValue(int n) {return (char)Typp[n];}
- virtual uchar GetUTinyValue(int n) {return (uchar)Typp[n];}
virtual void Reset(int n) {Typp[n] = 0;}
// Methods
@@ -168,9 +169,9 @@ class TYPBLK : public VALBLK {
protected:
// Specialized functions
+ static ulonglong MaxVal(void);
TYPE GetTypedValue(PVAL vp);
TYPE GetTypedValue(PVBLK blk, int n);
- TYPE GetTypedValue(PSZ s);
// Members
TYPE* const &Typp;
@@ -189,6 +190,8 @@ class CHRBLK : public VALBLK {
virtual void Init(PGLOBAL g, bool check);
virtual int GetVlen(void) {return Long;}
virtual PSZ GetCharValue(int n);
+ virtual char GetTinyValue(int n);
+ virtual uchar GetUTinyValue(int n);
virtual short GetShortValue(int n);
virtual ushort GetUShortValue(int n);
virtual int GetIntValue(int n);
@@ -196,8 +199,6 @@ class CHRBLK : public VALBLK {
virtual longlong GetBigintValue(int n);
virtual ulonglong GetUBigintValue(int n);
virtual double GetFloatValue(int n);
- virtual char GetTinyValue(int n);
- virtual uchar GetUTinyValue(int n);
virtual void Reset(int n);
virtual void SetPrec(int p) {Ci = (p != 0);}
virtual bool IsCi(void) {return Ci;}
@@ -242,15 +243,15 @@ class STRBLK : public VALBLK {
virtual void Init(PGLOBAL g, bool check);
virtual int GetVlen(void) {return sizeof(PSZ);}
virtual PSZ GetCharValue(int n) {return Strp[n];}
- virtual short GetShortValue(int n) {return (short)atoi(Strp[n]);}
- virtual ushort GetUShortValue(int n) {return (ushort)atoi(Strp[n]);}
- virtual int GetIntValue(int n) {return atol(Strp[n]);}
- virtual uint GetUIntValue(int n) {return (unsigned)atol(Strp[n]);}
- virtual longlong GetBigintValue(int n) {return atoll(Strp[n]);}
- virtual ulonglong GetUBigintValue(int n) {return (unsigned)atoll(Strp[n]);}
+ virtual char GetTinyValue(int n);
+ virtual uchar GetUTinyValue(int n);
+ virtual short GetShortValue(int n);
+ virtual ushort GetUShortValue(int n);
+ virtual int GetIntValue(int n);
+ virtual uint GetUIntValue(int n);
+ virtual longlong GetBigintValue(int n);
+ virtual ulonglong GetUBigintValue(int n);
virtual double GetFloatValue(int n) {return atof(Strp[n]);}
- virtual char GetTinyValue(int n) {return (char)atoi(Strp[n]);}
- virtual uchar GetUTinyValue(int n) {return (uchar)atoi(Strp[n]);}
virtual void Reset(int n) {Strp[n] = NULL;}
// Methods
diff --git a/storage/connect/value.cpp b/storage/connect/value.cpp
index 077df346459..b41fafe6ecb 100644
--- a/storage/connect/value.cpp
+++ b/storage/connect/value.cpp
@@ -1,1776 +1,1866 @@
-/************* Value C++ Functions Source Code File (.CPP) *************/
-/* Name: VALUE.CPP Version 2.3 */
-/* */
-/* (C) Copyright to the author Olivier BERTRAND 2001-2013 */
-/* */
-/* This file contains the VALUE and derived classes family functions. */
-/* These classes contain values of different types. They are used so */
-/* new object types can be defined and added to the processing simply */
-/* (hopefully) adding their specific functions in this file. */
-/* First family is VALUE that represent single typed objects. It is */
-/* used by columns (COLBLK), SELECT and FILTER (derived) objects. */
-/* Second family is VALBLK, representing simple suballocated arrays */
-/* of values treated sequentially by FIX, BIN and VCT tables and */
-/* columns, as well for min/max blocks as for VCT column blocks. */
-/* Q&A: why not using only one family ? Simple values are arrays that */
-/* have only one element and arrays could have functions for all kind */
-/* of processing. The answer is a-because historically it was simpler */
-/* to do that way, b-because of performance on single values, and c- */
-/* to avoid too complicated classes and unuseful duplication of many */
-/* functions used on one family only. The drawback is that for new */
-/* types of objects, we shall have more classes to update. */
-/* Currently the only implemented types are STRING, INT, SHORT, TINY, */
-/* DATE and LONGLONG. Recently we added some UNSIGNED types. */
-/***********************************************************************/
-
-/***********************************************************************/
-/* Include relevant MariaDB header file. */
-/***********************************************************************/
-#include "my_global.h"
-#include "sql_class.h"
-#include "sql_time.h"
-
-#if defined(WIN32)
-//#include <windows.h>
-#else // !WIN32
-#include <string.h>
-#endif // !WIN32
-
-#include <math.h>
-
-#undef DOMAIN // Was defined in math.h
-
-/***********************************************************************/
-/* Include required application header files */
-/* global.h is header containing all global Plug declarations. */
-/* plgdbsem.h is header containing the DB applic. declarations. */
-/***********************************************************************/
-#include "global.h"
-#include "plgdbsem.h"
-#include "preparse.h" // For DATPAR
-//#include "value.h"
-#include "valblk.h"
-#define NO_FUNC // Already defined in ODBConn
-#include "plgcnx.h" // For DB types
-#include "osutil.h"
-
-/***********************************************************************/
-/* Check macro's. */
-/***********************************************************************/
-#if defined(_DEBUG)
-#define CheckType(V) if (Type != V->GetType()) { \
- PGLOBAL& g = Global; \
- strcpy(g->Message, MSG(VALTYPE_NOMATCH)); \
- longjmp(g->jumper[g->jump_level], Type); }
-#else
-#define CheckType(V)
-#endif
-
-#define FOURYEARS 126230400 // Four years in seconds (1 leap)
-
-/***********************************************************************/
-/* Static variables. */
-/***********************************************************************/
-static char *list =
- " ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789/.*-‘abcdefghijklmnopqrstuv"; //wxyzñ'
-//" ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz.";
-extern "C" int trace;
-
-/***********************************************************************/
-/* Initialize the DTVAL static member. */
-/***********************************************************************/
-int DTVAL::Shift = 0;
-
-/***********************************************************************/
-/* Routines called externally. */
-/***********************************************************************/
-bool PlugEvalLike(PGLOBAL, LPCSTR, LPCSTR, bool);
-#if !defined(WIN32)
-extern "C" {
-PSZ strupr(PSZ s);
-PSZ strlwr(PSZ s);
-}
-#endif // !WIN32
-
-/***********************************************************************/
-/* GetTypeName: returns the PlugDB internal type name. */
-/***********************************************************************/
-PSZ GetTypeName(int type)
- {
- PSZ name;
-
- switch (type) {
- case TYPE_STRING: name = "CHAR"; break;
- case TYPE_SHORT: name = "SMALLINT"; break;
- 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_TINY: name = "TINY"; break;
- default: name = "UNKNOWN"; break;
- } // endswitch type
-
- return name;
- } // end of GetTypeName
-
-/***********************************************************************/
-/* GetTypeSize: returns the PlugDB internal type size. */
-/***********************************************************************/
-int GetTypeSize(int type, int len)
- {
- switch (type) {
- 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_TINY: len = sizeof(char); break;
- default: len = 0;
- } // endswitch type
-
- return len;
- } // end of GetTypeSize
-
-/***********************************************************************/
-/* GetFormatType: returns the FORMAT character(s) according to type. */
-/***********************************************************************/
-char *GetFormatType(int type)
- {
- char *c = "X";
-
- switch (type) {
- case TYPE_STRING: c = "C"; break;
- 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_DATE: c = "D"; break;
- case TYPE_TINY: c = "T"; break;
- } // endswitch type
-
- return c;
- } // end of GetFormatType
-
-/***********************************************************************/
-/* GetFormatType: returns the FORMAT type according to character. */
-/***********************************************************************/
-int GetFormatType(char c)
- {
- int type = TYPE_ERROR;
-
- switch (c) {
- case 'C': type = TYPE_STRING; break;
- 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 'D': type = TYPE_DATE; break;
- case 'T': type = TYPE_TINY; break;
- } // endswitch type
-
- return type;
- } // end of GetFormatType
-
-
-/***********************************************************************/
-/* IsTypeChar: returns true for character type(s). */
-/***********************************************************************/
-bool IsTypeChar(int type)
- {
- switch (type) {
- case TYPE_STRING:
- return true;
- } // endswitch type
-
- return false;
- } // end of IsTypeChar
-
-/***********************************************************************/
-/* IsTypeNum: returns true for numeric types. */
-/***********************************************************************/
-bool IsTypeNum(int type)
- {
- switch (type) {
- case TYPE_INT:
- case TYPE_BIGINT:
- case TYPE_DATE:
- case TYPE_FLOAT:
- case TYPE_SHORT:
- case TYPE_NUM:
- case TYPE_TINY:
- return true;
- } // endswitch type
-
- return false;
- } // end of IsTypeNum
-
-/***********************************************************************/
-/* GetFmt: returns the format to use with a typed value. */
-/***********************************************************************/
-const char *GetFmt(int type, bool un)
- {
- const char *fmt;
-
- switch (type) {
- 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;
- default: fmt = (un) ? "%u" : "%d"; break;
- } // endswitch Type
-
- return fmt;
- } // end of GetFmt
-
-#if 0
-/***********************************************************************/
-/* ConvertType: what this function does is to determine the type to */
-/* which should be converted a value so no precision would be lost. */
-/* This can be a numeric type if num is true or non numeric if false. */
-/* Note: this is an ultra simplified version of this function that */
-/* should become more and more complex as new types are added. */
-/* Not evaluated types (TYPE_VOID or TYPE_UNDEF) return false from */
-/* IsType... functions so match does not prevent correct setting. */
-/***********************************************************************/
-int ConvertType(int target, int type, CONV kind, bool match)
- {
- switch (kind) {
- case CNV_CHAR:
- if (match && (!IsTypeChar(target) || !IsTypeChar(type)))
- return TYPE_ERROR;
-
- return TYPE_STRING;
- case CNV_NUM:
- if (match && (!IsTypeNum(target) || !IsTypeNum(type)))
- return TYPE_ERROR;
-
- return (target == TYPE_FLOAT || type == TYPE_FLOAT) ? TYPE_FLOAT
- : (target == TYPE_DATE || type == TYPE_DATE) ? TYPE_DATE
- : (target == TYPE_BIGINT || type == TYPE_BIGINT) ? TYPE_BIGINT
- : (target == TYPE_INT || type == TYPE_INT) ? TYPE_INT
- : (target == TYPE_SHORT || type == TYPE_SHORT) ? TYPE_SHORT
- : TYPE_TINY;
- default:
- if (target == TYPE_ERROR || target == type)
- return type;
-
- if (match && ((IsTypeChar(target) && !IsTypeChar(type)) ||
- (IsTypeNum(target) && !IsTypeNum(type))))
- return TYPE_ERROR;
-
- return (target == TYPE_FLOAT || type == TYPE_FLOAT) ? TYPE_FLOAT
- : (target == TYPE_DATE || type == TYPE_DATE) ? TYPE_DATE
- : (target == TYPE_BIGINT || type == TYPE_BIGINT) ? TYPE_BIGINT
- : (target == TYPE_INT || type == TYPE_INT) ? TYPE_INT
- : (target == TYPE_SHORT || type == TYPE_SHORT) ? TYPE_SHORT
- : (target == TYPE_STRING || type == TYPE_STRING) ? TYPE_STRING
- : (target == TYPE_TINY || type == TYPE_TINY) ? TYPE_TINY
- : TYPE_ERROR;
- } // endswitch kind
-
- } // end of ConvertType
-#endif // 0
-
-/***********************************************************************/
-/* AllocateConstant: allocates a constant Value. */
-/***********************************************************************/
-PVAL AllocateValue(PGLOBAL g, void *value, short type)
- {
- PVAL valp;
-
- if (trace)
- htrc("AllocateConstant: value=%p type=%hd\n", value, type);
-
- switch (type) {
- case TYPE_STRING:
- valp = new(g) TYPVAL<PSZ>((PSZ)value);
- break;
- case TYPE_SHORT:
- valp = new(g) TYPVAL<short>(*(short*)value, TYPE_SHORT);
- break;
- case TYPE_INT:
- valp = new(g) TYPVAL<int>(*(int*)value, TYPE_INT);
- break;
- 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);
- break;
- case TYPE_TINY:
- valp = new(g) TYPVAL<char>(*(char *)value, TYPE_TINY);
- break;
- default:
- sprintf(g->Message, MSG(BAD_VALUE_TYPE), type);
- return NULL;
- } // endswitch Type
-
- valp->SetGlobal(g);
- return valp;
- } // end of AllocateValue
-
-/***********************************************************************/
-/* Allocate a variable Value according to type, length and precision. */
-/***********************************************************************/
-PVAL AllocateValue(PGLOBAL g, int type, int len, int prec, PSZ fmt)
- {
- PVAL valp;
-
- switch (type) {
- case TYPE_STRING:
- valp = new(g) TYPVAL<PSZ>(g, (PSZ)NULL, len, prec);
- break;
- case TYPE_DATE:
- valp = new(g) DTVAL(g, len, prec, fmt);
- break;
- case TYPE_INT:
- if (prec)
- 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)
- 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)
- 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);
- break;
- case TYPE_TINY:
- if (prec)
- valp = new(g) TYPVAL<uchar>((uchar)0, TYPE_TINY, 0, true);
- else
- valp = new(g) TYPVAL<char>((char)0, TYPE_TINY);
-
- break;
- default:
- sprintf(g->Message, MSG(BAD_VALUE_TYPE), type);
- return NULL;
- } // endswitch type
-
- valp->SetGlobal(g);
- return valp;
- } // end of AllocateValue
-
-/***********************************************************************/
-/* Allocate a constant Value converted to newtype. */
-/* Can also be used to copy a Value eventually converted. */
-/***********************************************************************/
-PVAL AllocateValue(PGLOBAL g, PVAL valp, int newtype, int uns)
- {
- PSZ p, sp;
- bool un = (uns < 0) ? false : (uns > 0) ? true : valp->IsUnsigned();
-
- if (newtype == TYPE_VOID) // Means allocate a value of the same type
- newtype = valp->GetType();
-
- switch (newtype) {
- case TYPE_STRING:
- p = (PSZ)PlugSubAlloc(g, NULL, 1 + valp->GetValLen());
-
- if ((sp = valp->GetCharString(p)) != p)
- strcpy (p, sp);
-
- valp = new(g) TYPVAL<PSZ>(g, p, valp->GetValLen(), valp->GetValPrec());
- break;
- case TYPE_SHORT:
- if (un)
- valp = new(g) TYPVAL<ushort>(valp->GetUShortValue(),
- TYPE_SHORT, 0, true);
- else
- valp = new(g) TYPVAL<short>(valp->GetShortValue(), TYPE_SHORT);
-
- break;
- case TYPE_INT:
- if (un)
- valp = new(g) TYPVAL<uint>(valp->GetUIntValue(), TYPE_INT, 0, true);
- else
- valp = new(g) TYPVAL<int>(valp->GetIntValue(), TYPE_INT);
-
- break;
- case TYPE_BIGINT:
- if (un)
- valp = new(g) TYPVAL<ulonglong>(valp->GetUBigintValue(),
- TYPE_BIGINT, 0, true);
- else
- valp = new(g) TYPVAL<longlong>(valp->GetBigintValue(), TYPE_BIGINT);
-
- break;
- case TYPE_DATE:
- valp = new(g) DTVAL(g, valp->GetIntValue());
- break;
- case TYPE_FLOAT:
- valp = new(g) TYPVAL<double>(valp->GetFloatValue(), TYPE_FLOAT,
- valp->GetValPrec());
- break;
- case TYPE_TINY:
- if (un)
- valp = new(g) TYPVAL<uchar>(valp->GetUTinyValue(),
- TYPE_TINY, 0, true);
- else
- valp = new(g) TYPVAL<char>(valp->GetTinyValue(), TYPE_TINY);
-
- break;
- default:
- sprintf(g->Message, MSG(BAD_VALUE_TYPE), newtype);
- return NULL;
- } // endswitch type
-
- valp->SetGlobal(g);
- return valp;
- } // end of AllocateValue
-
-
-/* -------------------------- Class VALUE ---------------------------- */
-
-/***********************************************************************/
-/* Class VALUE protected constructor. */
-/***********************************************************************/
-VALUE::VALUE(int type, bool un) : Type(type)
- {
- Null = false;
- Nullable = false;
- Unsigned = un;
- Clen = 0;
- Prec = 0;
- Fmt = GetFmt(Type, Unsigned);
- Xfmt = GetXfmt();
- } // end of VALUE constructor
-
-/***********************************************************************/
-/* VALUE GetXfmt: returns the extended format to use with typed value. */
-/***********************************************************************/
-const char *VALUE::GetXfmt(void)
- {
- const char *fmt;
-
- switch (Type) {
- 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;
- default: fmt = (Unsigned) ? "%*u" : "%*d"; break;
- } // endswitch Type
-
- return fmt;
- } // end of GetFmt
-
-/* -------------------------- Class TYPVAL ---------------------------- */
-
-/***********************************************************************/
-/* TYPVAL public constructor from a constant typed value. */
-/***********************************************************************/
-template <class TYPE>
-TYPVAL<TYPE>::TYPVAL(TYPE n, int type, int prec, bool un)
- : VALUE(type, un)
- {
- Tval = n;
- Clen = sizeof(TYPE);
- Prec = prec;
- } // end of TYPVAL constructor
-
-/***********************************************************************/
-/* TYPVAL GetValLen: returns the print length of the typed object. */
-/***********************************************************************/
-template <class TYPE>
-int TYPVAL<TYPE>::GetValLen(void)
- {
- char c[32];
-
- return sprintf(c, Fmt, Tval);
- } // end of GetValLen
-
-template <>
-int TYPVAL<double>::GetValLen(void)
- {
- char c[32];
-
- return sprintf(c, Fmt, Prec, Tval);
- } // end of GetValLen
-
-/***********************************************************************/
-/* TYPVAL SetValue: copy the value of another Value object. */
-/* This function allows conversion if chktype is false. */
-/***********************************************************************/
-template <class TYPE>
-bool TYPVAL<TYPE>::SetValue_pval(PVAL valp, bool chktype)
- {
- if (chktype && Type != valp->GetType())
- return true;
-
- if (!(Null = valp->IsNull() && Nullable))
- Tval = GetTypedValue(valp);
- else
- Reset();
-
- return false;
- } // end of SetValue
-
-template <>
-short TYPVAL<short>::GetTypedValue(PVAL valp)
- {return valp->GetShortValue();}
-
-template <>
-ushort TYPVAL<ushort>::GetTypedValue(PVAL valp)
- {return valp->GetUShortValue();}
-
-template <>
-int TYPVAL<int>::GetTypedValue(PVAL valp)
- {return valp->GetIntValue();}
-
-template <>
-uint TYPVAL<uint>::GetTypedValue(PVAL valp)
- {return valp->GetUIntValue();}
-
-template <>
-longlong TYPVAL<longlong>::GetTypedValue(PVAL valp)
- {return valp->GetBigintValue();}
-
-template <>
-ulonglong TYPVAL<ulonglong>::GetTypedValue(PVAL valp)
- {return valp->GetUBigintValue();}
-
-template <>
-double TYPVAL<double>::GetTypedValue(PVAL valp)
- {return valp->GetFloatValue();}
-
-template <>
-char TYPVAL<char>::GetTypedValue(PVAL valp)
- {return valp->GetTinyValue();}
-
-template <>
-uchar TYPVAL<uchar>::GetTypedValue(PVAL valp)
- {return valp->GetUTinyValue();}
-
-/***********************************************************************/
-/* TYPVAL SetValue: convert chars extracted from a line to TYPE value.*/
-/***********************************************************************/
-template <class TYPE>
-void TYPVAL<TYPE>::SetValue_char(char *p, int n)
- {
- char *p2, buf[32];
- bool minus = false;
-
- for (p2 = p + n; p < p2 && *p == ' '; p++) ;
-
- for (Tval = 0, minus = false; p < p2; p++)
- switch (*p) {
- case '-':
- minus = true;
- case '+':
- break;
- case '0': Tval = Tval * 10; break;
- case '1': Tval = Tval * 10 + 1; break;
- case '2': Tval = Tval * 10 + 2; break;
- case '3': Tval = Tval * 10 + 3; break;
- case '4': Tval = Tval * 10 + 4; break;
- case '5': Tval = Tval * 10 + 5; break;
- case '6': Tval = Tval * 10 + 6; break;
- case '7': Tval = Tval * 10 + 7; break;
- case '8': Tval = Tval * 10 + 8; break;
- case '9': Tval = Tval * 10 + 9; break;
- default:
- p = p2;
- } // endswitch *p
-
- if (minus && Tval)
- Tval = (-(signed)Tval) ? -(signed)Tval : Tval;
-
- if (trace > 1)
- htrc(strcat(strcat(strcpy(buf, " setting %s to: "), Fmt), "\n"),
- GetTypeName(Type), Tval);
-
- Null = false;
- } // end of SetValue
-
-template <>
-void TYPVAL<double>::SetValue_char(char *p, int n)
- {
- if (p) {
- char buf[32];
-
- for (; n > 0 && *p == ' '; p++)
- n--;
-
- memcpy(buf, p, min(n, 31));
- buf[n] = '\0';
- Tval = atof(buf);
-
- if (trace > 1)
- htrc(" setting double: '%s' -> %lf\n", buf, Tval);
-
- Null = false;
- } else {
- Reset();
- Null = Nullable;
- } // endif p
-
- } // end of SetValue
-
-/***********************************************************************/
-/* TYPVAL SetValue: fill a typed value from a string. */
-/***********************************************************************/
-template <class TYPE>
-void TYPVAL<TYPE>::SetValue_psz(PSZ s)
- {
- if (s) {
- Tval = GetTypedValue(s);
- Null = false;
- } else {
- Reset();
- Null = Nullable;
- } // endif p
-
- } // end of SetValue
-
-template <>
-int TYPVAL<int>::GetTypedValue(PSZ s) {return atol(s);}
-template <>
-uint TYPVAL<uint>::GetTypedValue(PSZ s) {return (unsigned)atol(s);}
-template <>
-short TYPVAL<short>::GetTypedValue(PSZ s) {return (short)atoi(s);}
-template <>
-ushort TYPVAL<ushort>::GetTypedValue(PSZ s) {return (ushort)atoi(s);}
-template <>
-longlong TYPVAL<longlong>::GetTypedValue(PSZ s) {return atoll(s);}
-template <>
-ulonglong TYPVAL<ulonglong>::GetTypedValue(PSZ s) {return (unsigned)atoll(s);}
-template <>
-double TYPVAL<double>::GetTypedValue(PSZ s) {return atof(s);}
-template <>
-char TYPVAL<char>::GetTypedValue(PSZ s) {return (char)atoi(s);}
-template <>
-uchar TYPVAL<uchar>::GetTypedValue(PSZ s) {return (uchar)atoi(s);}
-
-/***********************************************************************/
-/* TYPVAL SetValue: set value with a TYPE extracted from a block. */
-/***********************************************************************/
-template <class TYPE>
-void TYPVAL<TYPE>::SetValue_pvblk(PVBLK blk, int n)
- {
- Tval = GetTypedValue(blk, n);
- Null = false;
- } // end of SetValue
-
-template <>
-int TYPVAL<int>::GetTypedValue(PVBLK blk, int n)
- {return blk->GetIntValue(n);}
-
-template <>
-uint TYPVAL<uint>::GetTypedValue(PVBLK blk, int n)
- {return (unsigned)blk->GetIntValue(n);}
-
-template <>
-short TYPVAL<short>::GetTypedValue(PVBLK blk, int n)
- {return blk->GetShortValue(n);}
-
-template <>
-ushort TYPVAL<ushort>::GetTypedValue(PVBLK blk, int n)
- {return (unsigned)blk->GetShortValue(n);}
-
-template <>
-longlong TYPVAL<longlong>::GetTypedValue(PVBLK blk, int n)
- {return blk->GetBigintValue(n);}
-
-template <>
-ulonglong TYPVAL<ulonglong>::GetTypedValue(PVBLK blk, int n)
- {return (unsigned)blk->GetBigintValue(n);}
-
-template <>
-double TYPVAL<double>::GetTypedValue(PVBLK blk, int n)
- {return blk->GetFloatValue(n);}
-
-template <>
-char TYPVAL<char>::GetTypedValue(PVBLK blk, int n)
- {return blk->GetTinyValue(n);}
-
-template <>
-uchar TYPVAL<uchar>::GetTypedValue(PVBLK blk, int n)
- {return (unsigned)blk->GetTinyValue(n);}
-
-/***********************************************************************/
-/* TYPVAL SetBinValue: with bytes extracted from a line. */
-/***********************************************************************/
-template <class TYPE>
-void TYPVAL<TYPE>::SetBinValue(void *p)
- {
- Tval = *(TYPE *)p;
- Null = false;
- } // end of SetBinValue
-
-/***********************************************************************/
-/* 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. */
-/***********************************************************************/
-template <class TYPE>
-bool TYPVAL<TYPE>::GetBinValue(void *buf, int buflen, bool go)
- {
- // Test on length was removed here until a variable in column give the
- // real field length. For BIN files the field length logically cannot
- // be different from the variable length because no conversion is done.
- // Therefore this test is useless anyway.
-//#if defined(_DEBUG)
-// if (sizeof(TYPE) > buflen)
-// return true;
-//#endif
-
- if (go)
- *(TYPE *)buf = Tval;
-
- Null = false;
- return false;
- } // end of GetBinValue
-
-/***********************************************************************/
-/* TYPVAL ShowValue: get string representation of a typed value. */
-/***********************************************************************/
-template <class TYPE>
-char *TYPVAL<TYPE>::ShowValue(char *buf, int len)
- {
- sprintf(buf, Xfmt, len, Tval);
- return buf;
- } // end of ShowValue
-
-template <>
-char *TYPVAL<double>::ShowValue(char *buf, int len)
- {
- // TODO: use snprintf to avoid possible overflow
- sprintf(buf, Xfmt, len, Prec, Tval);
- return buf;
- } // end of ShowValue
-
-/***********************************************************************/
-/* TYPVAL GetCharString: get string representation of a typed value. */
-/***********************************************************************/
-template <class TYPE>
-char *TYPVAL<TYPE>::GetCharString(char *p)
- {
- sprintf(p, Fmt, Tval);
- return p;
- } // end of GetCharString
-
-template <>
-char *TYPVAL<double>::GetCharString(char *p)
- {
- sprintf(p, Fmt, Prec, Tval);
- return p;
- } // end of GetCharString
-
-#if 0
-/***********************************************************************/
-/* TYPVAL GetShortString: get short representation of a typed value. */
-/***********************************************************************/
-template <class TYPE>
-char *TYPVAL<TYPE>::GetShortString(char *p, int n)
- {
- sprintf(p, "%*hd", n, (short)Tval);
- return p;
- } // end of GetShortString
-
-/***********************************************************************/
-/* TYPVAL GetIntString: get int representation of a typed value. */
-/***********************************************************************/
-template <class TYPE>
-char *TYPVAL<TYPE>::GetIntString(char *p, int n)
- {
- sprintf(p, "%*d", n, (int)Tval);
- return p;
- } // end of GetIntString
-
-/***********************************************************************/
-/* TYPVAL GetBigintString: get big int representation of a TYPE value.*/
-/***********************************************************************/
-template <class TYPE>
-char *TYPVAL<TYPE>::GetBigintString(char *p, int n)
- {
- sprintf(p, "%*lld", n, (longlong)Tval);
- return p;
- } // end of GetBigintString
-
-/***********************************************************************/
-/* TYPVAL GetFloatString: get double representation of a typed value. */
-/***********************************************************************/
-template <class TYPE>
-char *TYPVAL<TYPE>::GetFloatString(char *p, int n, int prec)
- {
- sprintf(p, "%*.*lf", n, (prec < 0) ? 2 : prec, (double)Tval);
- return p;
- } // end of GetFloatString
-
-/***********************************************************************/
-/* TYPVAL GetTinyString: get char representation of a typed value. */
-/***********************************************************************/
-template <class TYPE>
-char *TYPVAL<TYPE>::GetTinyString(char *p, int n)
- {
- sprintf(p, "%*d", n, (int)(char)Tval);
- return p;
- } // end of GetIntString
-#endif // 0
-
-/***********************************************************************/
-/* TYPVAL compare value with another Value. */
-/***********************************************************************/
-template <class TYPE>
-bool TYPVAL<TYPE>::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;
- else
- return (Tval == GetTypedValue(vp));
-
- } // end of IsEqual
-
-/***********************************************************************/
-/* 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. */
-/***********************************************************************/
-template <class TYPE>
-bool TYPVAL<TYPE>::FormatValue(PVAL vp, char *fmt)
- {
- char *buf = (char*)vp->GetTo_Val(); // Should be big enough
- int n = sprintf(buf, fmt, Tval);
-
- return (n > vp->GetValLen());
- } // end of FormatValue
-
-/***********************************************************************/
-/* TYPVAL SetFormat function (used to set SELECT output format). */
-/***********************************************************************/
-template <class TYPE>
-bool TYPVAL<TYPE>::SetConstFormat(PGLOBAL g, FORMAT& fmt)
- {
- char c[32];
-
- fmt.Type[0] = *GetFormatType(Type);
- fmt.Length = sprintf(c, Fmt, Tval);
- fmt.Prec = Prec;
- return false;
- } // end of SetConstFormat
-
-/***********************************************************************/
-/* Make file output of a typed object. */
-/***********************************************************************/
-template <class TYPE>
-void TYPVAL<TYPE>::Print(PGLOBAL g, FILE *f, uint n)
- {
- char m[64], buf[12];
-
- memset(m, ' ', n); /* Make margin string */
- m[n] = '\0';
-
- if (Null)
- fprintf(f, "%s<null>\n", m);
- else
- fprintf(f, strcat(strcat(strcpy(buf, "%s"), Fmt), "\n"), m, Tval);
-
- } /* end of Print */
-
-/***********************************************************************/
-/* Make string output of a int object. */
-/***********************************************************************/
-template <class TYPE>
-void TYPVAL<TYPE>::Print(PGLOBAL g, char *ps, uint z)
- {
- if (Null)
- strcpy(ps, "<null>");
- else
- sprintf(ps, Fmt, Tval);
-
- } /* end of Print */
-
-/* -------------------------- Class STRING --------------------------- */
-
-/***********************************************************************/
-/* STRING public constructor from a constant string. */
-/***********************************************************************/
-TYPVAL<PSZ>::TYPVAL(PSZ s) : VALUE(TYPE_STRING)
- {
- Strp = s;
- Len = strlen(s);
- Clen = Len;
- Ci = false;
- } // end of STRING constructor
-
-/***********************************************************************/
-/* STRING public constructor from char. */
-/***********************************************************************/
-TYPVAL<PSZ>::TYPVAL(PGLOBAL g, PSZ s, int n, int c)
- : VALUE(TYPE_STRING)
- {
- Len = (g) ? n : strlen(s);
-
- if (!s) {
- if (g) {
- Strp = (char *)PlugSubAlloc(g, NULL, Len + 1);
- Strp[Len] = '\0';
- } else
- assert(false);
-
- } else
- Strp = s;
-
- Clen = Len;
- Ci = (c != 0);
- } // end of STRING constructor
-
-/***********************************************************************/
-/* STRING SetValue: copy the value of another Value object. */
-/***********************************************************************/
-bool TYPVAL<PSZ>::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
-
-/***********************************************************************/
-/* STRING SetValue: fill string with chars extracted from a line. */
-/***********************************************************************/
-void TYPVAL<PSZ>::SetValue_char(char *p, int n)
- {
- if (p) {
- 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 {
- Reset();
- Null = Nullable;
- } // endif p
-
- } // end of SetValue_char
-
-/***********************************************************************/
-/* STRING SetValue: fill string with another string. */
-/***********************************************************************/
-void TYPVAL<PSZ>::SetValue_psz(PSZ s)
- {
- if (s) {
- strncpy(Strp, s, Len);
- Null = false;
- } else {
- Reset();
- Null = Nullable;
- } // endif s
-
- } // end of SetValue_psz
-
-/***********************************************************************/
-/* STRING SetValue: fill string with a string extracted from a block. */
-/***********************************************************************/
-void TYPVAL<PSZ>::SetValue_pvblk(PVBLK blk, int n)
- {
- strncpy(Strp, blk->GetCharValue(n), Len);
- } // end of SetValue_pvblk
-
-/***********************************************************************/
-/* STRING SetValue: get the character representation of an integer. */
-/***********************************************************************/
-void TYPVAL<PSZ>::SetValue(int n)
- {
- char buf[16];
- PGLOBAL& g = Global;
- int k = sprintf(buf, "%d", n);
-
- if (k > Len) {
- sprintf(g->Message, MSG(VALSTR_TOO_LONG), buf, Len);
- longjmp(g->jumper[g->jump_level], 138);
- } else
- SetValue_psz(buf);
-
- Null = false;
- } // end of SetValue
-
-/***********************************************************************/
-/* STRING SetValue: get the character representation of an uint. */
-/***********************************************************************/
-void TYPVAL<PSZ>::SetValue(uint n)
- {
- char buf[16];
- PGLOBAL& g = Global;
- int k = sprintf(buf, "%u", n);
-
- if (k > Len) {
- sprintf(g->Message, MSG(VALSTR_TOO_LONG), buf, Len);
- longjmp(g->jumper[g->jump_level], 138);
- } else
- SetValue_psz(buf);
-
- Null = false;
- } // end of SetValue
-
-/***********************************************************************/
-/* STRING SetValue: get the character representation of a short int. */
-/***********************************************************************/
-void TYPVAL<PSZ>::SetValue(short i)
- {
- SetValue((int)i);
- Null = false;
- } // end of SetValue
-
-/***********************************************************************/
-/* STRING SetValue: get the character representation of a ushort int. */
-/***********************************************************************/
-void TYPVAL<PSZ>::SetValue(ushort i)
- {
- SetValue((uint)i);
- Null = false;
- } // end of SetValue
-
-/***********************************************************************/
-/* STRING SetValue: get the character representation of a big integer.*/
-/***********************************************************************/
-void TYPVAL<PSZ>::SetValue(longlong n)
- {
- char buf[24];
- PGLOBAL& g = Global;
- int k = sprintf(buf, "%lld", n);
-
- if (k > Len) {
- sprintf(g->Message, MSG(VALSTR_TOO_LONG), buf, Len);
- longjmp(g->jumper[g->jump_level], 138);
- } else
- SetValue_psz(buf);
-
- Null = false;
- } // end of SetValue
-
-/***********************************************************************/
-/* STRING SetValue: get the character representation of a big integer.*/
-/***********************************************************************/
-void TYPVAL<PSZ>::SetValue(ulonglong n)
- {
- char buf[24];
- PGLOBAL& g = Global;
- int k = sprintf(buf, "%llu", n);
-
- if (k > Len) {
- sprintf(g->Message, MSG(VALSTR_TOO_LONG), buf, Len);
- longjmp(g->jumper[g->jump_level], 138);
- } else
- SetValue_psz(buf);
-
- Null = false;
- } // end of SetValue
-
-/***********************************************************************/
-/* STRING SetValue: get the character representation of a double. */
-/***********************************************************************/
-void TYPVAL<PSZ>::SetValue(double f)
- {
- char *p, buf[32];
- PGLOBAL& g = Global;
- int k = sprintf(buf, "%lf", f);
-
- for (p = buf + k - 1; p >= buf; p--)
- if (*p == '0') {
- *p = 0;
- k--;
- } else
- break;
-
- if (k > Len) {
- sprintf(g->Message, MSG(VALSTR_TOO_LONG), buf, Len);
- longjmp(g->jumper[g->jump_level], 138);
- } else
- SetValue_psz(buf);
-
- Null = false;
- } // end of SetValue
-
-/***********************************************************************/
-/* STRING SetValue: get the character representation of a tiny int. */
-/***********************************************************************/
-void TYPVAL<PSZ>::SetValue(char c)
- {
- SetValue((int)c);
- Null = false;
- } // end of SetValue
-
-/***********************************************************************/
-/* STRING SetValue: get the character representation of a tiny int. */
-/***********************************************************************/
-void TYPVAL<PSZ>::SetValue(uchar c)
- {
- SetValue((uint)c);
- Null = false;
- } // end of SetValue
-
-/***********************************************************************/
-/* STRING SetBinValue: fill string with chars extracted from a line. */
-/***********************************************************************/
-void TYPVAL<PSZ>::SetBinValue(void *p)
- {
- SetValue_char((char *)p, Len);
- } // end of SetBinValue
-
-/***********************************************************************/
-/* 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 TYPVAL<PSZ>::GetBinValue(void *buf, int buflen, bool go)
- {
- int len = (Null) ? 0 : strlen(Strp);
-
- if (len > buflen)
- return true;
- else if (go) {
- memset(buf, ' ', buflen);
- memcpy(buf, Strp, len);
- } // endif go
-
- return false;
- } // end of GetBinValue
-
-/***********************************************************************/
-/* STRING ShowValue: get string representation of a char value. */
-/***********************************************************************/
-char *TYPVAL<PSZ>::ShowValue(char *buf, int len)
- {
- return Strp;
- } // end of ShowValue
-
-/***********************************************************************/
-/* STRING GetCharString: get string representation of a char value. */
-/***********************************************************************/
-char *TYPVAL<PSZ>::GetCharString(char *p)
- {
- return Strp;
- } // end of GetCharString
-
-#if 0
-/***********************************************************************/
-/* STRING GetShortString: get short representation of a char value. */
-/***********************************************************************/
-char *TYPVAL<PSZ>::GetShortString(char *p, int n)
- {
- sprintf(p, "%*hd", n, (short)(Null ? 0 : atoi(Strp)));
- return p;
- } // end of GetShortString
-
-/***********************************************************************/
-/* STRING GetIntString: get int representation of a char value. */
-/***********************************************************************/
-char *TYPVAL<PSZ>::GetIntString(char *p, int n)
- {
- sprintf(p, "%*ld", n, (Null) ? 0 : atol(Strp));
- return p;
- } // end of GetIntString
-
-/***********************************************************************/
-/* STRING GetBigintString: get big int representation of a char value.*/
-/***********************************************************************/
-char *TYPVAL<PSZ>::GetBigintString(char *p, int n)
- {
- sprintf(p, "%*lld", n, (Null) ? 0 : atoll(Strp));
- return p;
- } // end of GetBigintString
-
-/***********************************************************************/
-/* STRING GetFloatString: get double representation of a char value. */
-/***********************************************************************/
-char *TYPVAL<PSZ>::GetFloatString(char *p, int n, int prec)
- {
- sprintf(p, "%*.*lf", n, (prec < 0) ? 2 : prec, Null ? 0 : atof(Strp));
- return p;
- } // end of GetFloatString
-
-/***********************************************************************/
-/* STRING GetTinyString: get tiny int representation of a char value. */
-/***********************************************************************/
-char *TYPVAL<PSZ>::GetTinyString(char *p, int n)
- {
- sprintf(p, "%*d", n, (Null) ? 0 : (char)atoi(Strp));
- return p;
- } // end of GetIntString
-#endif // 0
-
-/***********************************************************************/
-/* STRING compare value with another Value. */
-/***********************************************************************/
-bool TYPVAL<PSZ>::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];
-
- if (Ci || vp->IsCi())
- return !stricmp(Strp, vp->GetCharString(buf));
- else // (!Ci)
- return !strcmp(Strp, vp->GetCharString(buf));
-
- } // end of IsEqual
-
-/***********************************************************************/
-/* 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 TYPVAL<PSZ>::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
-
-/***********************************************************************/
-/* STRING SetFormat function (used to set SELECT output format). */
-/***********************************************************************/
-bool TYPVAL<PSZ>::SetConstFormat(PGLOBAL g, FORMAT& fmt)
- {
- fmt.Type[0] = 'C';
- fmt.Length = Len;
- fmt.Prec = 0;
- return false;
- } // end of SetConstFormat
-
-/* -------------------------- Class DTVAL ---------------------------- */
-
-/***********************************************************************/
-/* DTVAL public constructor for new void values. */
-/***********************************************************************/
-DTVAL::DTVAL(PGLOBAL g, int n, int prec, PSZ fmt)
- : TYPVAL<int>((int)0, TYPE_DATE)
- {
- if (!fmt) {
- Pdtp = NULL;
- Sdate = NULL;
- DefYear = 0;
- Len = n;
- } else
- SetFormat(g, fmt, n, prec);
-
-//Type = TYPE_DATE;
- } // end of DTVAL constructor
-
-/***********************************************************************/
-/* DTVAL public constructor from int. */
-/***********************************************************************/
-DTVAL::DTVAL(PGLOBAL g, int n) : TYPVAL<int>(n, TYPE_DATE)
- {
- Pdtp = NULL;
- Len = 19;
-//Type = TYPE_DATE;
- Sdate = NULL;
- DefYear = 0;
- } // end of DTVAL constructor
-
-/***********************************************************************/
-/* Set format so formatted dates can be converted on input/output. */
-/***********************************************************************/
-bool DTVAL::SetFormat(PGLOBAL g, PSZ fmt, int len, int year)
- {
- Pdtp = MakeDateFormat(g, fmt, true, true, (year > 9999) ? 1 : 0);
- Sdate = (char*)PlugSubAlloc(g, NULL, len + 1);
- DefYear = (int)((year > 9999) ? (year - 10000) : year);
- Len = len;
- return false;
- } // end of SetFormat
-
-/***********************************************************************/
-/* Set format from the format of another date value. */
-/***********************************************************************/
-bool DTVAL::SetFormat(PGLOBAL g, PVAL valp)
- {
- DTVAL *vp;
-
- if (valp->GetType() != TYPE_DATE) {
- sprintf(g->Message, MSG(NO_FORMAT_TYPE), valp->GetType());
- return true;
- } else
- vp = (DTVAL*)valp;
-
- Len = vp->Len;
- Pdtp = vp->Pdtp;
- Sdate = (char*)PlugSubAlloc(g, NULL, Len + 1);
- DefYear = vp->DefYear;
- return false;
- } // end of SetFormat
-
-/***********************************************************************/
-/* We need TimeShift because the mktime C function does a correction */
-/* for local time zone that we want to override for DB operations. */
-/***********************************************************************/
-void DTVAL::SetTimeShift(void)
- {
- struct tm dtm;
- memset(&dtm, 0, sizeof(dtm));
- dtm.tm_mday=2;
- dtm.tm_mon=0;
- dtm.tm_year=70;
-
- Shift = (int)mktime(&dtm) - 86400;
-
- if (trace)
- htrc("DTVAL Shift=%d\n", Shift);
-
- } // end of SetTimeShift
-
-/***********************************************************************/
-/* GetGmTime: returns a pointer to a static tm structure obtained */
-/* though the gmtime C function. The purpose of this function is to */
-/* extend the range of valid dates by accepting negative time values. */
-/***********************************************************************/
-static void TIME_to_localtime(struct tm *tm, const MYSQL_TIME *ltime)
-{
- bzero(tm, sizeof(*tm));
- tm->tm_year= ltime->year - 1900;
- tm->tm_mon= ltime->month - 1;
- tm->tm_mday= ltime->day;
- tm->tm_hour= ltime->hour;
- tm->tm_min= ltime->minute;
- tm->tm_sec= ltime->second;
-}
-
-
-static struct tm *gmtime_mysql(const time_t *timep, struct tm *tm)
-{
- MYSQL_TIME ltime;
- thd_gmt_sec_to_TIME(current_thd, &ltime, (my_time_t) *timep);
- TIME_to_localtime(tm, &ltime);
- return tm;
-}
-
-
-struct tm *DTVAL::GetGmTime(struct tm *tm_buffer)
- {
- struct tm *datm;
- time_t t = (time_t)Tval;
-
- if (Tval < 0) {
- int n;
-
- for (n = 0; t < 0; n += 4)
- t += FOURYEARS;
-
- datm = gmtime_mysql(&t, tm_buffer);
-
- if (datm)
- datm->tm_year -= n;
-
- } else
- datm = gmtime_mysql(&t, tm_buffer);
-
- return datm;
- } // end of GetGmTime
-
-/***********************************************************************/
-/* MakeTime: calculates a date value from a tm structures using the */
-/* mktime C function. The purpose of this function is to extend the */
-/* range of valid dates by accepting to set negative time values. */
-/***********************************************************************/
-
-static time_t mktime_mysql(struct tm *ptm)
-{
- MYSQL_TIME ltime;
- localtime_to_TIME(&ltime, ptm);
- ltime.time_type= MYSQL_TIMESTAMP_DATETIME;
- uint error_code;
- time_t t= TIME_to_timestamp(current_thd, &ltime, &error_code);
- return error_code ? (time_t) -1 : t;
-}
-
-bool DTVAL::MakeTime(struct tm *ptm)
- {
- int n, y = ptm->tm_year;
- time_t t = mktime_mysql(ptm);
-
- if (trace > 1)
- htrc("MakeTime from (%d,%d,%d,%d,%d,%d)\n",
- ptm->tm_year, ptm->tm_mon, ptm->tm_mday,
- ptm->tm_hour, ptm->tm_min, ptm->tm_sec);
-
- if (t == -1) {
- if (y < 1 || y > 71)
- return true;
-
- for (n = 0; t == -1 && n < 20; n++) {
- ptm->tm_year += 4;
- t = mktime_mysql(ptm);
- } // endfor t
-
- if (t == -1)
- return true;
-
- if ((t -= (n * FOURYEARS)) > 2000000000)
- return true;
-
- }
- Tval= (int) t;
-
- if (trace > 1)
- htrc("MakeTime Ival=%d\n", Tval);
-
- return false;
- } // end of MakeTime
-
-/***********************************************************************/
-/* Make a time_t datetime from its components (YY, MM, DD, hh, mm, ss) */
-/***********************************************************************/
-bool DTVAL::MakeDate(PGLOBAL g, int *val, int nval)
- {
- int i, m;
- int n;
- bool rc = false;
- struct tm datm;
- bzero(&datm, sizeof(datm));
- datm.tm_mday=1;
- datm.tm_mon=0;
- datm.tm_year=70;
-
- if (trace > 1)
- htrc("MakeDate from(%d,%d,%d,%d,%d,%d) nval=%d\n",
- val[0], val[1], val[2], val[3], val[4], val[5], nval);
-
- for (i = 0; i < nval; i++) {
- n = val[i];
-
-// if (trace > 1)
-// htrc("i=%d n=%d\n", i, n);
-
- switch (i) {
- case 0:
- if (n >= 1900)
- n -= 1900;
-
- datm.tm_year = n;
-
-// if (trace > 1)
-// htrc("n=%d tm_year=%d\n", n, datm.tm_year);
-
- break;
- case 1:
- // If mktime handles apparently correctly large or negative
- // day values, it is not the same for months. Therefore we
- // do the ajustment here, thus mktime has not to do it.
- if (n > 0) {
- m = (n - 1) % 12;
- n = (n - 1) / 12;
- } else {
- m = 11 + n % 12;
- n = n / 12 - 1;
- } // endfi n
-
- datm.tm_mon = m;
- datm.tm_year += n;
-
-// if (trace > 1)
-// htrc("n=%d m=%d tm_year=%d tm_mon=%d\n", n, m, datm.tm_year, datm.tm_mon);
-
- break;
- case 2:
- // For days, big or negative values may also cause problems
- m = n % 1461;
- n = 4 * (n / 1461);
-
- if (m < 0) {
- m += 1461;
- n -= 4;
- } // endif m
-
- datm.tm_mday = m;
- datm.tm_year += n;
-
-// if (trace > 1)
-// htrc("n=%d m=%d tm_year=%d tm_mon=%d\n", n, m, datm.tm_year, datm.tm_mon);
-
- break;
- case 3: datm.tm_hour = n; break;
- case 4: datm.tm_min = n; break;
- case 5: datm.tm_sec = n; break;
- } // endswitch i
-
- } // endfor i
-
- if (trace > 1)
- htrc("MakeDate datm=(%d,%d,%d,%d,%d,%d)\n",
- datm.tm_year, datm.tm_mon, datm.tm_mday,
- datm.tm_hour, datm.tm_min, datm.tm_sec);
-
- // Pass g to have an error return or NULL to set invalid dates to 0
- if (MakeTime(&datm))
- if (g) {
- strcpy(g->Message, MSG(BAD_DATETIME));
- rc = true;
- } else
- Tval = 0;
-
- return rc;
- } // end of MakeDate
-
-/***********************************************************************/
-/* DTVAL SetValue: copy the value of another Value object. */
-/* This function allows conversion if chktype is false. */
-/***********************************************************************/
-bool DTVAL::SetValue_pval(PVAL valp, bool chktype)
- {
- if (chktype && Type != valp->GetType())
- return true;
-
- if (!(Null = valp->IsNull() && Nullable)) {
- if (Pdtp && !valp->IsTypeNum()) {
- int ndv;
- int dval[6];
-
- ndv = ExtractDate(valp->GetCharValue(), Pdtp, DefYear, dval);
- MakeDate(NULL, dval, ndv);
- } else
- Tval = valp->GetIntValue();
-
- } else
- Reset();
-
- return false;
- } // end of SetValue
-
-/***********************************************************************/
-/* SetValue: convert chars extracted from a line to date value. */
-/***********************************************************************/
-void DTVAL::SetValue_char(char *p, int n)
- {
- if (Pdtp) {
- char *p2;
- int ndv;
- int dval[6];
-
- // Trim trailing blanks
- for (p2 = p + n -1; p < p2 && *p2 == ' '; p2--) ;
-
- n = min(p2 - p + 1, Len);
- memcpy(Sdate, p, n);
- Sdate[n] = '\0';
-
- ndv = ExtractDate(Sdate, Pdtp, DefYear, dval);
- MakeDate(NULL, dval, ndv);
-
- if (trace > 1)
- htrc(" setting date: '%s' -> %d\n", Sdate, Tval);
-
- Null = false;
- } else
- TYPVAL<int>::SetValue_char(p, n);
-
- } // end of SetValue
-
-/***********************************************************************/
-/* SetValue: convert a char string to date value. */
-/***********************************************************************/
-void DTVAL::SetValue_psz(PSZ p)
- {
- if (Pdtp) {
- int ndv;
- int dval[6];
-
- strncpy(Sdate, p, Len);
- Sdate[Len] = '\0';
-
- ndv = ExtractDate(Sdate, Pdtp, DefYear, dval);
- MakeDate(NULL, dval, ndv);
-
- if (trace > 1)
- htrc(" setting date: '%s' -> %d\n", Sdate, Tval);
-
- Null = false;
- } else
- TYPVAL<int>::SetValue_psz(p);
-
- } // end of SetValue
-
-/***********************************************************************/
-/* DTVAL SetValue: set value with a value extracted from a block. */
-/***********************************************************************/
-void DTVAL::SetValue_pvblk(PVBLK blk, int n)
- {
- if (Pdtp && !::IsTypeNum(blk->GetType())) {
- int ndv;
- int dval[6];
-
- ndv = ExtractDate(blk->GetCharValue(n), Pdtp, DefYear, dval);
- MakeDate(NULL, dval, ndv);
- } else
- Tval = blk->GetIntValue(n);
-
- } // end of SetValue
-
-/***********************************************************************/
-/* DTVAL GetCharString: get string representation of a date value. */
-/***********************************************************************/
-char *DTVAL::GetCharString(char *p)
- {
- if (Pdtp) {
- size_t n = 0;
- struct tm tm, *ptm= GetGmTime(&tm);
-
- if (ptm)
- n = strftime(Sdate, Len + 1, Pdtp->OutFmt, ptm);
-
- if (!n) {
- *Sdate = '\0';
- strncat(Sdate, "Error", Len + 1);
- } // endif n
-
- return Sdate;
- } else
- sprintf(p, "%d", Tval);
-
- Null = false;
- return p;
- } // end of GetCharString
-
-/***********************************************************************/
-/* DTVAL ShowValue: get string representation of a date value. */
-/***********************************************************************/
-char *DTVAL::ShowValue(char *buf, int len)
- {
- if (Pdtp) {
- char *p;
- size_t m, n = 0;
- struct tm tm, *ptm = GetGmTime(&tm);
-
- if (Len < len) {
- p = buf;
- m = len;
- } else {
- p = Sdate;
- m = Len + 1;
- } // endif Len
-
- if (ptm)
- n = strftime(p, m, Pdtp->OutFmt, ptm);
-
- if (!n) {
- *p = '\0';
- strncat(p, "Error", m);
- } // endif n
-
- return p;
- } else
- return TYPVAL<int>::ShowValue(buf, len);
-
- } // end of ShowValue
-
-/***********************************************************************/
-/* Returns a member of the struct tm representation of the date. */
-/***********************************************************************/
-bool DTVAL::GetTmMember(OPVAL op, int& mval)
- {
- bool rc = false;
- struct tm tm, *ptm = GetGmTime(&tm);
-
- switch (op) {
- case OP_MDAY: mval = ptm->tm_mday; break;
- case OP_MONTH: mval = ptm->tm_mon + 1; break;
- case OP_YEAR: mval = ptm->tm_year + 1900; break;
- case OP_WDAY: mval = ptm->tm_wday + 1; break;
- case OP_YDAY: mval = ptm->tm_yday + 1; break;
- case OP_QUART: mval = ptm->tm_mon / 3 + 1; break;
- default:
- rc = true;
- } // endswitch op
-
- return rc;
- } // end of GetTmMember
-
-/***********************************************************************/
-/* Calculates the week number of the year for the internal date value.*/
-/* The International Standard ISO 8601 has decreed that Monday shall */
-/* be the first day of the week. A week that lies partly in one year */
-/* and partly in another is assigned a number in the year in which */
-/* most of its days lie. That means that week number 1 of any year is */
-/* the week that contains the January 4th. */
-/***********************************************************************/
-bool DTVAL::WeekNum(PGLOBAL g, int& nval)
- {
- // w is the start of the week SUN=0, MON=1, etc.
- int m, n, w = nval % 7;
- struct tm tm, *ptm = GetGmTime(&tm);
-
- // Which day is January 4th of this year?
- m = (367 + ptm->tm_wday - ptm->tm_yday) % 7;
-
- // When does the first week begins?
- n = 3 - (7 + m - w) % 7;
-
- // Now calculate the week number
- if (!(nval = (7 + ptm->tm_yday - n) / 7))
- nval = 52;
-
- // Everything should be Ok
- return false;
- } // end of WeekNum
-
-/***********************************************************************/
-/* 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 DTVAL::FormatValue(PVAL vp, char *fmt)
- {
- char *buf = (char*)vp->GetTo_Val(); // Should be big enough
- struct tm tm, *ptm = GetGmTime(&tm);
-
- if (trace)
- htrc("FormatValue: ptm=%p len=%d\n", ptm, vp->GetValLen());
-
- if (ptm) {
- size_t n = strftime(buf, vp->GetValLen(), fmt, ptm);
-
- if (trace)
- htrc("strftime: n=%d buf=%s\n", n, (n) ? buf : "???");
-
- return (n == 0);
- } else
- return true;
-
- } // end of FormatValue
-
-/* -------------------------- End of Value --------------------------- */
+/************* Value C++ Functions Source Code File (.CPP) *************/
+/* Name: VALUE.CPP Version 2.3 */
+/* */
+/* (C) Copyright to the author Olivier BERTRAND 2001-2013 */
+/* */
+/* This file contains the VALUE and derived classes family functions. */
+/* These classes contain values of different types. They are used so */
+/* new object types can be defined and added to the processing simply */
+/* (hopefully) adding their specific functions in this file. */
+/* First family is VALUE that represent single typed objects. It is */
+/* used by columns (COLBLK), SELECT and FILTER (derived) objects. */
+/* Second family is VALBLK, representing simple suballocated arrays */
+/* of values treated sequentially by FIX, BIN and VCT tables and */
+/* columns, as well for min/max blocks as for VCT column blocks. */
+/* Q&A: why not using only one family ? Simple values are arrays that */
+/* have only one element and arrays could have functions for all kind */
+/* of processing. The answer is a-because historically it was simpler */
+/* to do that way, b-because of performance on single values, and c- */
+/* to avoid too complicated classes and unuseful duplication of many */
+/* functions used on one family only. The drawback is that for new */
+/* types of objects, we shall have more classes to update. */
+/* Currently the only implemented types are STRING, INT, SHORT, TINY, */
+/* DATE and LONGLONG. Recently we added some UNSIGNED types. */
+/***********************************************************************/
+
+/***********************************************************************/
+/* Include relevant MariaDB header file. */
+/***********************************************************************/
+#include "my_global.h"
+#include "sql_class.h"
+#include "sql_time.h"
+
+#if defined(WIN32)
+//#include <windows.h>
+#else // !WIN32
+#include <string.h>
+#endif // !WIN32
+
+#include <math.h>
+
+#undef DOMAIN // Was defined in math.h
+
+/***********************************************************************/
+/* Include required application header files */
+/* global.h is header containing all global Plug declarations. */
+/* plgdbsem.h is header containing the DB applic. declarations. */
+/***********************************************************************/
+#include "global.h"
+#include "plgdbsem.h"
+#include "preparse.h" // For DATPAR
+//#include "value.h"
+#include "valblk.h"
+#define NO_FUNC // Already defined in ODBConn
+#include "plgcnx.h" // For DB types
+#include "osutil.h"
+
+/***********************************************************************/
+/* Check macro's. */
+/***********************************************************************/
+#if defined(_DEBUG)
+#define CheckType(V) if (Type != V->GetType()) { \
+ PGLOBAL& g = Global; \
+ strcpy(g->Message, MSG(VALTYPE_NOMATCH)); \
+ longjmp(g->jumper[g->jump_level], Type); }
+#else
+#define CheckType(V)
+#endif
+
+#define FOURYEARS 126230400 // Four years in seconds (1 leap)
+
+/***********************************************************************/
+/* Static variables. */
+/***********************************************************************/
+static char *list =
+ " ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789/.*-‘abcdefghijklmnopqrstuv"; //wxyzñ'
+//" ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz.";
+extern "C" int trace;
+
+/***********************************************************************/
+/* Initialize the DTVAL static member. */
+/***********************************************************************/
+int DTVAL::Shift = 0;
+
+/***********************************************************************/
+/* Routines called externally. */
+/***********************************************************************/
+bool PlugEvalLike(PGLOBAL, LPCSTR, LPCSTR, bool);
+#if !defined(WIN32)
+extern "C" {
+PSZ strupr(PSZ s);
+PSZ strlwr(PSZ s);
+}
+#endif // !WIN32
+
+/***********************************************************************/
+/* Get a long long number from its character representation. */
+/* IN p: Pointer to the numeric string */
+/* IN n: The string length */
+/* IN maxval: The number max value */
+/* IN un: True if the number must be unsigned */
+/* OUT rc: Set to TRUE for out of range value */
+/* OUT minus: Set to true if the number is negative */
+/* Returned val: The resulting number */
+/***********************************************************************/
+ulonglong CharToNumber(char *p, int n, ulonglong maxval,
+ bool un, bool *minus, bool *rc)
+{
+ char *p2;
+ uchar c;
+ ulonglong val;
+
+ if (minus) *minus = false;
+ if (rc) *rc = false;
+
+ // Eliminate leading blanks or 0
+ for (p2 = p + n; p < p2 && (*p == ' ' || *p == '0'); p++) ;
+
+ // Get an eventual sign character
+ switch (*p) {
+ case '-':
+ if (un) {
+ if (rc) *rc = true;
+ return 0;
+ } else {
+ maxval++;
+ if (minus) *minus = true;
+ } // endif Unsigned
+
+ case '+':
+ p++;
+ break;
+ } // endswitch *p
+
+ for (val = 0; p < p2 && (c = (uchar)(*p - '0')) < 10; p++)
+ if (val > (maxval - c) / 10) {
+ val = maxval;
+ if (rc) *rc = true;
+ break;
+ } else
+ val = val * 10 + c;
+
+ return val;
+} // end of CharToNumber
+
+/***********************************************************************/
+/* GetTypeName: returns the PlugDB internal type name. */
+/***********************************************************************/
+PSZ GetTypeName(int type)
+ {
+ PSZ name;
+
+ switch (type) {
+ case TYPE_STRING: name = "CHAR"; break;
+ case TYPE_SHORT: name = "SMALLINT"; break;
+ 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_TINY: name = "TINY"; break;
+ default: name = "UNKNOWN"; break;
+ } // endswitch type
+
+ return name;
+ } // end of GetTypeName
+
+/***********************************************************************/
+/* GetTypeSize: returns the PlugDB internal type size. */
+/***********************************************************************/
+int GetTypeSize(int type, int len)
+ {
+ switch (type) {
+ 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_TINY: len = sizeof(char); break;
+ default: len = 0;
+ } // endswitch type
+
+ return len;
+ } // end of GetTypeSize
+
+/***********************************************************************/
+/* GetFormatType: returns the FORMAT character(s) according to type. */
+/***********************************************************************/
+char *GetFormatType(int type)
+ {
+ char *c = "X";
+
+ switch (type) {
+ case TYPE_STRING: c = "C"; break;
+ 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_DATE: c = "D"; break;
+ case TYPE_TINY: c = "T"; break;
+ } // endswitch type
+
+ return c;
+ } // end of GetFormatType
+
+/***********************************************************************/
+/* GetFormatType: returns the FORMAT type according to character. */
+/***********************************************************************/
+int GetFormatType(char c)
+ {
+ int type = TYPE_ERROR;
+
+ switch (c) {
+ case 'C': type = TYPE_STRING; break;
+ 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 'D': type = TYPE_DATE; break;
+ case 'T': type = TYPE_TINY; break;
+ } // endswitch type
+
+ return type;
+ } // end of GetFormatType
+
+
+/***********************************************************************/
+/* IsTypeChar: returns true for character type(s). */
+/***********************************************************************/
+bool IsTypeChar(int type)
+ {
+ switch (type) {
+ case TYPE_STRING:
+ return true;
+ } // endswitch type
+
+ return false;
+ } // end of IsTypeChar
+
+/***********************************************************************/
+/* IsTypeNum: returns true for numeric types. */
+/***********************************************************************/
+bool IsTypeNum(int type)
+ {
+ switch (type) {
+ case TYPE_INT:
+ case TYPE_BIGINT:
+ case TYPE_DATE:
+ case TYPE_FLOAT:
+ case TYPE_SHORT:
+ case TYPE_NUM:
+ case TYPE_TINY:
+ return true;
+ } // endswitch type
+
+ return false;
+ } // end of IsTypeNum
+
+/***********************************************************************/
+/* GetFmt: returns the format to use with a typed value. */
+/***********************************************************************/
+const char *GetFmt(int type, bool un)
+ {
+ const char *fmt;
+
+ switch (type) {
+ 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;
+ default: fmt = (un) ? "%u" : "%d"; break;
+ } // endswitch Type
+
+ return fmt;
+ } // end of GetFmt
+
+#if 0
+/***********************************************************************/
+/* ConvertType: what this function does is to determine the type to */
+/* which should be converted a value so no precision would be lost. */
+/* This can be a numeric type if num is true or non numeric if false. */
+/* Note: this is an ultra simplified version of this function that */
+/* should become more and more complex as new types are added. */
+/* Not evaluated types (TYPE_VOID or TYPE_UNDEF) return false from */
+/* IsType... functions so match does not prevent correct setting. */
+/***********************************************************************/
+int ConvertType(int target, int type, CONV kind, bool match)
+ {
+ switch (kind) {
+ case CNV_CHAR:
+ if (match && (!IsTypeChar(target) || !IsTypeChar(type)))
+ return TYPE_ERROR;
+
+ return TYPE_STRING;
+ case CNV_NUM:
+ if (match && (!IsTypeNum(target) || !IsTypeNum(type)))
+ return TYPE_ERROR;
+
+ return (target == TYPE_FLOAT || type == TYPE_FLOAT) ? TYPE_FLOAT
+ : (target == TYPE_DATE || type == TYPE_DATE) ? TYPE_DATE
+ : (target == TYPE_BIGINT || type == TYPE_BIGINT) ? TYPE_BIGINT
+ : (target == TYPE_INT || type == TYPE_INT) ? TYPE_INT
+ : (target == TYPE_SHORT || type == TYPE_SHORT) ? TYPE_SHORT
+ : TYPE_TINY;
+ default:
+ if (target == TYPE_ERROR || target == type)
+ return type;
+
+ if (match && ((IsTypeChar(target) && !IsTypeChar(type)) ||
+ (IsTypeNum(target) && !IsTypeNum(type))))
+ return TYPE_ERROR;
+
+ return (target == TYPE_FLOAT || type == TYPE_FLOAT) ? TYPE_FLOAT
+ : (target == TYPE_DATE || type == TYPE_DATE) ? TYPE_DATE
+ : (target == TYPE_BIGINT || type == TYPE_BIGINT) ? TYPE_BIGINT
+ : (target == TYPE_INT || type == TYPE_INT) ? TYPE_INT
+ : (target == TYPE_SHORT || type == TYPE_SHORT) ? TYPE_SHORT
+ : (target == TYPE_STRING || type == TYPE_STRING) ? TYPE_STRING
+ : (target == TYPE_TINY || type == TYPE_TINY) ? TYPE_TINY
+ : TYPE_ERROR;
+ } // endswitch kind
+
+ } // end of ConvertType
+#endif // 0
+
+/***********************************************************************/
+/* AllocateConstant: allocates a constant Value. */
+/***********************************************************************/
+PVAL AllocateValue(PGLOBAL g, void *value, short type)
+ {
+ PVAL valp;
+
+ if (trace)
+ htrc("AllocateConstant: value=%p type=%hd\n", value, type);
+
+ switch (type) {
+ case TYPE_STRING:
+ valp = new(g) TYPVAL<PSZ>((PSZ)value);
+ break;
+ case TYPE_SHORT:
+ valp = new(g) TYPVAL<short>(*(short*)value, TYPE_SHORT);
+ break;
+ case TYPE_INT:
+ valp = new(g) TYPVAL<int>(*(int*)value, TYPE_INT);
+ break;
+ 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);
+ break;
+ case TYPE_TINY:
+ valp = new(g) TYPVAL<char>(*(char *)value, TYPE_TINY);
+ break;
+ default:
+ sprintf(g->Message, MSG(BAD_VALUE_TYPE), type);
+ return NULL;
+ } // endswitch Type
+
+ valp->SetGlobal(g);
+ return valp;
+ } // end of AllocateValue
+
+/***********************************************************************/
+/* Allocate a variable Value according to type, length and precision. */
+/***********************************************************************/
+PVAL AllocateValue(PGLOBAL g, int type, int len, int prec, PSZ fmt)
+ {
+ PVAL valp;
+
+ switch (type) {
+ case TYPE_STRING:
+ valp = new(g) TYPVAL<PSZ>(g, (PSZ)NULL, len, prec);
+ break;
+ case TYPE_DATE:
+ valp = new(g) DTVAL(g, len, prec, fmt);
+ break;
+ case TYPE_INT:
+ if (prec)
+ 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)
+ 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)
+ 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);
+ break;
+ case TYPE_TINY:
+ if (prec)
+ valp = new(g) TYPVAL<uchar>((uchar)0, TYPE_TINY, 0, true);
+ else
+ valp = new(g) TYPVAL<char>((char)0, TYPE_TINY);
+
+ break;
+ default:
+ sprintf(g->Message, MSG(BAD_VALUE_TYPE), type);
+ return NULL;
+ } // endswitch type
+
+ valp->SetGlobal(g);
+ return valp;
+ } // end of AllocateValue
+
+/***********************************************************************/
+/* Allocate a constant Value converted to newtype. */
+/* Can also be used to copy a Value eventually converted. */
+/***********************************************************************/
+PVAL AllocateValue(PGLOBAL g, PVAL valp, int newtype, int uns)
+ {
+ PSZ p, sp;
+ bool un = (uns < 0) ? false : (uns > 0) ? true : valp->IsUnsigned();
+
+ if (newtype == TYPE_VOID) // Means allocate a value of the same type
+ newtype = valp->GetType();
+
+ switch (newtype) {
+ case TYPE_STRING:
+ p = (PSZ)PlugSubAlloc(g, NULL, 1 + valp->GetValLen());
+
+ if ((sp = valp->GetCharString(p)) != p)
+ strcpy (p, sp);
+
+ valp = new(g) TYPVAL<PSZ>(g, p, valp->GetValLen(), valp->GetValPrec());
+ break;
+ case TYPE_SHORT:
+ if (un)
+ valp = new(g) TYPVAL<ushort>(valp->GetUShortValue(),
+ TYPE_SHORT, 0, true);
+ else
+ valp = new(g) TYPVAL<short>(valp->GetShortValue(), TYPE_SHORT);
+
+ break;
+ case TYPE_INT:
+ if (un)
+ valp = new(g) TYPVAL<uint>(valp->GetUIntValue(), TYPE_INT, 0, true);
+ else
+ valp = new(g) TYPVAL<int>(valp->GetIntValue(), TYPE_INT);
+
+ break;
+ case TYPE_BIGINT:
+ if (un)
+ valp = new(g) TYPVAL<ulonglong>(valp->GetUBigintValue(),
+ TYPE_BIGINT, 0, true);
+ else
+ valp = new(g) TYPVAL<longlong>(valp->GetBigintValue(), TYPE_BIGINT);
+
+ break;
+ case TYPE_DATE:
+ valp = new(g) DTVAL(g, valp->GetIntValue());
+ break;
+ case TYPE_FLOAT:
+ valp = new(g) TYPVAL<double>(valp->GetFloatValue(), TYPE_FLOAT,
+ valp->GetValPrec());
+ break;
+ case TYPE_TINY:
+ if (un)
+ valp = new(g) TYPVAL<uchar>(valp->GetUTinyValue(),
+ TYPE_TINY, 0, true);
+ else
+ valp = new(g) TYPVAL<char>(valp->GetTinyValue(), TYPE_TINY);
+
+ break;
+ default:
+ sprintf(g->Message, MSG(BAD_VALUE_TYPE), newtype);
+ return NULL;
+ } // endswitch type
+
+ valp->SetGlobal(g);
+ return valp;
+ } // end of AllocateValue
+
+
+/* -------------------------- Class VALUE ---------------------------- */
+
+/***********************************************************************/
+/* Class VALUE protected constructor. */
+/***********************************************************************/
+VALUE::VALUE(int type, bool un) : Type(type)
+ {
+ Null = false;
+ Nullable = false;
+ Unsigned = un;
+ Clen = 0;
+ Prec = 0;
+ Fmt = GetFmt(Type, Unsigned);
+ Xfmt = GetXfmt();
+ } // end of VALUE constructor
+
+/***********************************************************************/
+/* VALUE GetXfmt: returns the extended format to use with typed value. */
+/***********************************************************************/
+const char *VALUE::GetXfmt(void)
+ {
+ const char *fmt;
+
+ switch (Type) {
+ 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;
+ default: fmt = (Unsigned) ? "%*u" : "%*d"; break;
+ } // endswitch Type
+
+ return fmt;
+ } // end of GetFmt
+
+/* -------------------------- Class TYPVAL ---------------------------- */
+
+/***********************************************************************/
+/* TYPVAL public constructor from a constant typed value. */
+/***********************************************************************/
+template <class TYPE>
+TYPVAL<TYPE>::TYPVAL(TYPE n, int type, int prec, bool un)
+ : VALUE(type, un)
+ {
+ Tval = n;
+ Clen = sizeof(TYPE);
+ Prec = prec;
+ } // end of TYPVAL constructor
+
+/***********************************************************************/
+/* Return unsigned max value for the type. */
+/***********************************************************************/
+template <class TYPE>
+ulonglong TYPVAL<TYPE>::MaxVal(void) {DBUG_ASSERT(false); return 0;}
+
+template <>
+ulonglong TYPVAL<short>::MaxVal(void) {return INT_MAX16;}
+
+template <>
+ulonglong TYPVAL<ushort>::MaxVal(void) {return UINT_MAX16;}
+
+template <>
+ulonglong TYPVAL<int>::MaxVal(void) {return INT_MAX32;}
+
+template <>
+ulonglong TYPVAL<uint>::MaxVal(void) {return UINT_MAX32;}
+
+template <>
+ulonglong TYPVAL<char>::MaxVal(void) {return INT_MAX8;}
+
+template <>
+ulonglong TYPVAL<uchar>::MaxVal(void) {return UINT_MAX8;}
+
+template <>
+ulonglong TYPVAL<longlong>::MaxVal(void) {return INT_MAX64;}
+
+template <>
+ulonglong TYPVAL<ulonglong>::MaxVal(void) {return ULONGLONG_MAX;}
+
+/***********************************************************************/
+/* TYPVAL GetValLen: returns the print length of the typed object. */
+/***********************************************************************/
+template <class TYPE>
+int TYPVAL<TYPE>::GetValLen(void)
+ {
+ char c[32];
+
+ return sprintf(c, Fmt, Tval);
+ } // end of GetValLen
+
+template <>
+int TYPVAL<double>::GetValLen(void)
+ {
+ char c[32];
+
+ return sprintf(c, Fmt, Prec, Tval);
+ } // end of GetValLen
+
+/***********************************************************************/
+/* TYPVAL SetValue: copy the value of another Value object. */
+/* This function allows conversion if chktype is false. */
+/***********************************************************************/
+template <class TYPE>
+bool TYPVAL<TYPE>::SetValue_pval(PVAL valp, bool chktype)
+ {
+ if (chktype && Type != valp->GetType())
+ return true;
+
+ if (!(Null = valp->IsNull() && Nullable))
+ Tval = GetTypedValue(valp);
+ else
+ Reset();
+
+ return false;
+ } // end of SetValue
+
+template <>
+short TYPVAL<short>::GetTypedValue(PVAL valp)
+ {return valp->GetShortValue();}
+
+template <>
+ushort TYPVAL<ushort>::GetTypedValue(PVAL valp)
+ {return valp->GetUShortValue();}
+
+template <>
+int TYPVAL<int>::GetTypedValue(PVAL valp)
+ {return valp->GetIntValue();}
+
+template <>
+uint TYPVAL<uint>::GetTypedValue(PVAL valp)
+ {return valp->GetUIntValue();}
+
+template <>
+longlong TYPVAL<longlong>::GetTypedValue(PVAL valp)
+ {return valp->GetBigintValue();}
+
+template <>
+ulonglong TYPVAL<ulonglong>::GetTypedValue(PVAL valp)
+ {return valp->GetUBigintValue();}
+
+template <>
+double TYPVAL<double>::GetTypedValue(PVAL valp)
+ {return valp->GetFloatValue();}
+
+template <>
+char TYPVAL<char>::GetTypedValue(PVAL valp)
+ {return valp->GetTinyValue();}
+
+template <>
+uchar TYPVAL<uchar>::GetTypedValue(PVAL valp)
+ {return valp->GetUTinyValue();}
+
+/***********************************************************************/
+/* TYPVAL SetValue: convert chars extracted from a line to TYPE value.*/
+/***********************************************************************/
+template <class TYPE>
+bool TYPVAL<TYPE>::SetValue_char(char *p, int n)
+ {
+ bool rc, minus;
+ ulonglong maxval = MaxVal();
+ ulonglong val = CharToNumber(p, n, maxval, Unsigned, &minus, &rc);
+
+ if (minus && val < maxval)
+ Tval = (TYPE)(-(signed)val);
+ else
+ Tval = (TYPE)val;
+
+ if (trace > 1) {
+ char buf[64];
+ htrc(strcat(strcat(strcpy(buf, " setting %s to: "), Fmt), "\n"),
+ GetTypeName(Type), Tval);
+ } // endif trace
+
+ Null = false;
+ return rc;
+ } // end of SetValue
+
+template <>
+bool TYPVAL<double>::SetValue_char(char *p, int n)
+ {
+ if (p) {
+ char buf[32];
+
+ for (; n > 0 && *p == ' '; p++)
+ n--;
+
+ memcpy(buf, p, min(n, 31));
+ buf[n] = '\0';
+ Tval = atof(buf);
+
+ if (trace > 1)
+ htrc(" setting double: '%s' -> %lf\n", buf, Tval);
+
+ Null = false;
+ } else {
+ Reset();
+ Null = Nullable;
+ } // endif p
+
+ return false;
+ } // end of SetValue
+
+/***********************************************************************/
+/* TYPVAL SetValue: fill a typed value from a string. */
+/***********************************************************************/
+template <class TYPE>
+void TYPVAL<TYPE>::SetValue_psz(PSZ s)
+ {
+ if (s) {
+ SetValue_char(s, (int)strlen(s));
+ Null = false;
+ } else {
+ Reset();
+ Null = Nullable;
+ } // endif p
+
+ } // end of SetValue
+
+/***********************************************************************/
+/* TYPVAL SetValue: set value with a TYPE extracted from a block. */
+/***********************************************************************/
+template <class TYPE>
+void TYPVAL<TYPE>::SetValue_pvblk(PVBLK blk, int n)
+ {
+ Tval = GetTypedValue(blk, n);
+ Null = false;
+ } // end of SetValue
+
+template <>
+int TYPVAL<int>::GetTypedValue(PVBLK blk, int n)
+ {return blk->GetIntValue(n);}
+
+template <>
+uint TYPVAL<uint>::GetTypedValue(PVBLK blk, int n)
+ {return blk->GetUIntValue(n);}
+
+template <>
+short TYPVAL<short>::GetTypedValue(PVBLK blk, int n)
+ {return blk->GetShortValue(n);}
+
+template <>
+ushort TYPVAL<ushort>::GetTypedValue(PVBLK blk, int n)
+ {return blk->GetUShortValue(n);}
+
+template <>
+longlong TYPVAL<longlong>::GetTypedValue(PVBLK blk, int n)
+ {return blk->GetBigintValue(n);}
+
+template <>
+ulonglong TYPVAL<ulonglong>::GetTypedValue(PVBLK blk, int n)
+ {return blk->GetUBigintValue(n);}
+
+template <>
+double TYPVAL<double>::GetTypedValue(PVBLK blk, int n)
+ {return blk->GetFloatValue(n);}
+
+template <>
+char TYPVAL<char>::GetTypedValue(PVBLK blk, int n)
+ {return blk->GetTinyValue(n);}
+
+template <>
+uchar TYPVAL<uchar>::GetTypedValue(PVBLK blk, int n)
+ {return blk->GetUTinyValue(n);}
+
+/***********************************************************************/
+/* TYPVAL SetBinValue: with bytes extracted from a line. */
+/***********************************************************************/
+template <class TYPE>
+void TYPVAL<TYPE>::SetBinValue(void *p)
+ {
+ Tval = *(TYPE *)p;
+ Null = false;
+ } // end of SetBinValue
+
+/***********************************************************************/
+/* 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. */
+/***********************************************************************/
+template <class TYPE>
+bool TYPVAL<TYPE>::GetBinValue(void *buf, int buflen, bool go)
+ {
+ // Test on length was removed here until a variable in column give the
+ // real field length. For BIN files the field length logically cannot
+ // be different from the variable length because no conversion is done.
+ // Therefore this test is useless anyway.
+//#if defined(_DEBUG)
+// if (sizeof(TYPE) > buflen)
+// return true;
+//#endif
+
+ if (go)
+ *(TYPE *)buf = Tval;
+
+ Null = false;
+ return false;
+ } // end of GetBinValue
+
+/***********************************************************************/
+/* TYPVAL ShowValue: get string representation of a typed value. */
+/***********************************************************************/
+template <class TYPE>
+char *TYPVAL<TYPE>::ShowValue(char *buf, int len)
+ {
+ sprintf(buf, Xfmt, len, Tval);
+ return buf;
+ } // end of ShowValue
+
+template <>
+char *TYPVAL<double>::ShowValue(char *buf, int len)
+ {
+ // TODO: use snprintf to avoid possible overflow
+ sprintf(buf, Xfmt, len, Prec, Tval);
+ return buf;
+ } // end of ShowValue
+
+/***********************************************************************/
+/* TYPVAL GetCharString: get string representation of a typed value. */
+/***********************************************************************/
+template <class TYPE>
+char *TYPVAL<TYPE>::GetCharString(char *p)
+ {
+ sprintf(p, Fmt, Tval);
+ return p;
+ } // end of GetCharString
+
+template <>
+char *TYPVAL<double>::GetCharString(char *p)
+ {
+ sprintf(p, Fmt, Prec, Tval);
+ return p;
+ } // end of GetCharString
+
+#if 0
+/***********************************************************************/
+/* TYPVAL GetShortString: get short representation of a typed value. */
+/***********************************************************************/
+template <class TYPE>
+char *TYPVAL<TYPE>::GetShortString(char *p, int n)
+ {
+ sprintf(p, "%*hd", n, (short)Tval);
+ return p;
+ } // end of GetShortString
+
+/***********************************************************************/
+/* TYPVAL GetIntString: get int representation of a typed value. */
+/***********************************************************************/
+template <class TYPE>
+char *TYPVAL<TYPE>::GetIntString(char *p, int n)
+ {
+ sprintf(p, "%*d", n, (int)Tval);
+ return p;
+ } // end of GetIntString
+
+/***********************************************************************/
+/* TYPVAL GetBigintString: get big int representation of a TYPE value.*/
+/***********************************************************************/
+template <class TYPE>
+char *TYPVAL<TYPE>::GetBigintString(char *p, int n)
+ {
+ sprintf(p, "%*lld", n, (longlong)Tval);
+ return p;
+ } // end of GetBigintString
+
+/***********************************************************************/
+/* TYPVAL GetFloatString: get double representation of a typed value. */
+/***********************************************************************/
+template <class TYPE>
+char *TYPVAL<TYPE>::GetFloatString(char *p, int n, int prec)
+ {
+ sprintf(p, "%*.*lf", n, (prec < 0) ? 2 : prec, (double)Tval);
+ return p;
+ } // end of GetFloatString
+
+/***********************************************************************/
+/* TYPVAL GetTinyString: get char representation of a typed value. */
+/***********************************************************************/
+template <class TYPE>
+char *TYPVAL<TYPE>::GetTinyString(char *p, int n)
+ {
+ sprintf(p, "%*d", n, (int)(char)Tval);
+ return p;
+ } // end of GetIntString
+#endif // 0
+
+/***********************************************************************/
+/* TYPVAL compare value with another Value. */
+/***********************************************************************/
+template <class TYPE>
+bool TYPVAL<TYPE>::IsEqual(PVAL vp, bool chktype)
+ {
+ if (this == vp)
+ return true;
+ else if (chktype && Type != vp->GetType())
+ return false;
+ else if (chktype && Unsigned != vp->IsUnsigned())
+ return false;
+ else if (Null || vp->IsNull())
+ return false;
+ else
+ return (Tval == GetTypedValue(vp));
+
+ } // end of IsEqual
+
+/***********************************************************************/
+/* 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. */
+/***********************************************************************/
+template <class TYPE>
+bool TYPVAL<TYPE>::FormatValue(PVAL vp, char *fmt)
+ {
+ char *buf = (char*)vp->GetTo_Val(); // Should be big enough
+ int n = sprintf(buf, fmt, Tval);
+
+ return (n > vp->GetValLen());
+ } // end of FormatValue
+
+/***********************************************************************/
+/* TYPVAL SetFormat function (used to set SELECT output format). */
+/***********************************************************************/
+template <class TYPE>
+bool TYPVAL<TYPE>::SetConstFormat(PGLOBAL g, FORMAT& fmt)
+ {
+ char c[32];
+
+ fmt.Type[0] = *GetFormatType(Type);
+ fmt.Length = sprintf(c, Fmt, Tval);
+ fmt.Prec = Prec;
+ return false;
+ } // end of SetConstFormat
+
+/***********************************************************************/
+/* Make file output of a typed object. */
+/***********************************************************************/
+template <class TYPE>
+void TYPVAL<TYPE>::Print(PGLOBAL g, FILE *f, uint n)
+ {
+ char m[64], buf[12];
+
+ memset(m, ' ', n); /* Make margin string */
+ m[n] = '\0';
+
+ if (Null)
+ fprintf(f, "%s<null>\n", m);
+ else
+ fprintf(f, strcat(strcat(strcpy(buf, "%s"), Fmt), "\n"), m, Tval);
+
+ } /* end of Print */
+
+/***********************************************************************/
+/* Make string output of a int object. */
+/***********************************************************************/
+template <class TYPE>
+void TYPVAL<TYPE>::Print(PGLOBAL g, char *ps, uint z)
+ {
+ if (Null)
+ strcpy(ps, "<null>");
+ else
+ sprintf(ps, Fmt, Tval);
+
+ } /* end of Print */
+
+/* -------------------------- Class STRING --------------------------- */
+
+/***********************************************************************/
+/* STRING public constructor from a constant string. */
+/***********************************************************************/
+TYPVAL<PSZ>::TYPVAL(PSZ s) : VALUE(TYPE_STRING)
+ {
+ Strp = s;
+ Len = strlen(s);
+ Clen = Len;
+ Ci = false;
+ } // end of STRING constructor
+
+/***********************************************************************/
+/* STRING public constructor from char. */
+/***********************************************************************/
+TYPVAL<PSZ>::TYPVAL(PGLOBAL g, PSZ s, int n, int c)
+ : VALUE(TYPE_STRING)
+ {
+ Len = (g) ? n : strlen(s);
+
+ if (!s) {
+ if (g) {
+ Strp = (char *)PlugSubAlloc(g, NULL, Len + 1);
+ Strp[Len] = '\0';
+ } else
+ assert(false);
+
+ } else
+ Strp = s;
+
+ Clen = Len;
+ Ci = (c != 0);
+ } // end of STRING constructor
+
+/***********************************************************************/
+/* Get the tiny value represented by the Strp string. */
+/***********************************************************************/
+char TYPVAL<PSZ>::GetTinyValue(void)
+ {
+ bool m;
+ ulonglong val = CharToNumber(Strp, strlen(Strp), INT_MAX8, false, &m);
+
+ return (m && val < INT_MAX8) ? (char)(-(signed)val) : (char)val;
+ } // end of GetTinyValue
+
+/***********************************************************************/
+/* Get the unsigned tiny value represented by the Strp string. */
+/***********************************************************************/
+uchar TYPVAL<PSZ>::GetUTinyValue(void)
+ {
+ return (uchar)CharToNumber(Strp, strlen(Strp), UINT_MAX8, true);
+ } // end of GetUTinyValue
+
+/***********************************************************************/
+/* Get the short value represented by the Strp string. */
+/***********************************************************************/
+short TYPVAL<PSZ>::GetShortValue(void)
+ {
+ bool m;
+ ulonglong val = CharToNumber(Strp, strlen(Strp), INT_MAX16, false, &m);
+
+ return (m && val < INT_MAX16) ? (short)(-(signed)val) : (short)val;
+ } // end of GetShortValue
+
+/***********************************************************************/
+/* Get the unsigned short value represented by the Strp string. */
+/***********************************************************************/
+ushort TYPVAL<PSZ>::GetUShortValue(void)
+ {
+ return (ushort)CharToNumber(Strp, strlen(Strp), UINT_MAX16, true);
+ } // end of GetUshortValue
+
+/***********************************************************************/
+/* Get the integer value represented by the Strp string. */
+/***********************************************************************/
+int TYPVAL<PSZ>::GetIntValue(void)
+ {
+ bool m;
+ ulonglong val = CharToNumber(Strp, strlen(Strp), INT_MAX32, false, &m);
+
+ return (m && val < INT_MAX32) ? (int)(-(signed)val) : (int)val;
+ } // end of GetIntValue
+
+/***********************************************************************/
+/* Get the unsigned integer value represented by the Strp string. */
+/***********************************************************************/
+uint TYPVAL<PSZ>::GetUIntValue(void)
+ {
+ return (uint)CharToNumber(Strp, strlen(Strp), UINT_MAX32, true);
+ } // end of GetUintValue
+
+/***********************************************************************/
+/* Get the big integer value represented by the Strp string. */
+/***********************************************************************/
+longlong TYPVAL<PSZ>::GetBigintValue(void)
+ {
+ bool m;
+ ulonglong val = CharToNumber(Strp, strlen(Strp), INT_MAX64, false, &m);
+
+ return (m && val < INT_MAX64) ? (-(signed)val) : (longlong)val;
+ } // end of GetBigintValue
+
+/***********************************************************************/
+/* Get the unsigned big integer value represented by the Strp string. */
+/***********************************************************************/
+ulonglong TYPVAL<PSZ>::GetUBigintValue(void)
+ {
+ return CharToNumber(Strp, strlen(Strp), ULONGLONG_MAX, true);
+ } // end of GetUBigintValue
+
+/***********************************************************************/
+/* STRING SetValue: copy the value of another Value object. */
+/***********************************************************************/
+bool TYPVAL<PSZ>::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
+
+/***********************************************************************/
+/* STRING SetValue: fill string with chars extracted from a line. */
+/***********************************************************************/
+bool TYPVAL<PSZ>::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
+
+/***********************************************************************/
+/* STRING SetValue: fill string with another string. */
+/***********************************************************************/
+void TYPVAL<PSZ>::SetValue_psz(PSZ s)
+ {
+ if (s) {
+ strncpy(Strp, s, Len);
+ Null = false;
+ } else {
+ Reset();
+ Null = Nullable;
+ } // endif s
+
+ } // end of SetValue_psz
+
+/***********************************************************************/
+/* STRING SetValue: fill string with a string extracted from a block. */
+/***********************************************************************/
+void TYPVAL<PSZ>::SetValue_pvblk(PVBLK blk, int n)
+ {
+ strncpy(Strp, blk->GetCharValue(n), Len);
+ } // end of SetValue_pvblk
+
+/***********************************************************************/
+/* STRING SetValue: get the character representation of an integer. */
+/***********************************************************************/
+void TYPVAL<PSZ>::SetValue(int n)
+ {
+ char buf[16];
+ PGLOBAL& g = Global;
+ int k = sprintf(buf, "%d", n);
+
+ if (k > Len) {
+ sprintf(g->Message, MSG(VALSTR_TOO_LONG), buf, Len);
+ longjmp(g->jumper[g->jump_level], 138);
+ } else
+ SetValue_psz(buf);
+
+ Null = false;
+ } // end of SetValue
+
+/***********************************************************************/
+/* STRING SetValue: get the character representation of an uint. */
+/***********************************************************************/
+void TYPVAL<PSZ>::SetValue(uint n)
+ {
+ char buf[16];
+ PGLOBAL& g = Global;
+ int k = sprintf(buf, "%u", n);
+
+ if (k > Len) {
+ sprintf(g->Message, MSG(VALSTR_TOO_LONG), buf, Len);
+ longjmp(g->jumper[g->jump_level], 138);
+ } else
+ SetValue_psz(buf);
+
+ Null = false;
+ } // end of SetValue
+
+/***********************************************************************/
+/* STRING SetValue: get the character representation of a short int. */
+/***********************************************************************/
+void TYPVAL<PSZ>::SetValue(short i)
+ {
+ SetValue((int)i);
+ Null = false;
+ } // end of SetValue
+
+/***********************************************************************/
+/* STRING SetValue: get the character representation of a ushort int. */
+/***********************************************************************/
+void TYPVAL<PSZ>::SetValue(ushort i)
+ {
+ SetValue((uint)i);
+ Null = false;
+ } // end of SetValue
+
+/***********************************************************************/
+/* STRING SetValue: get the character representation of a big integer.*/
+/***********************************************************************/
+void TYPVAL<PSZ>::SetValue(longlong n)
+ {
+ char buf[24];
+ PGLOBAL& g = Global;
+ int k = sprintf(buf, "%lld", n);
+
+ if (k > Len) {
+ sprintf(g->Message, MSG(VALSTR_TOO_LONG), buf, Len);
+ longjmp(g->jumper[g->jump_level], 138);
+ } else
+ SetValue_psz(buf);
+
+ Null = false;
+ } // end of SetValue
+
+/***********************************************************************/
+/* STRING SetValue: get the character representation of a big integer.*/
+/***********************************************************************/
+void TYPVAL<PSZ>::SetValue(ulonglong n)
+ {
+ char buf[24];
+ PGLOBAL& g = Global;
+ int k = sprintf(buf, "%llu", n);
+
+ if (k > Len) {
+ sprintf(g->Message, MSG(VALSTR_TOO_LONG), buf, Len);
+ longjmp(g->jumper[g->jump_level], 138);
+ } else
+ SetValue_psz(buf);
+
+ Null = false;
+ } // end of SetValue
+
+/***********************************************************************/
+/* STRING SetValue: get the character representation of a double. */
+/***********************************************************************/
+void TYPVAL<PSZ>::SetValue(double f)
+ {
+ char *p, buf[32];
+ PGLOBAL& g = Global;
+ int k = sprintf(buf, "%lf", f);
+
+ for (p = buf + k - 1; p >= buf; p--)
+ if (*p == '0') {
+ *p = 0;
+ k--;
+ } else
+ break;
+
+ if (k > Len) {
+ sprintf(g->Message, MSG(VALSTR_TOO_LONG), buf, Len);
+ longjmp(g->jumper[g->jump_level], 138);
+ } else
+ SetValue_psz(buf);
+
+ Null = false;
+ } // end of SetValue
+
+/***********************************************************************/
+/* STRING SetValue: get the character representation of a tiny int. */
+/***********************************************************************/
+void TYPVAL<PSZ>::SetValue(char c)
+ {
+ SetValue((int)c);
+ Null = false;
+ } // end of SetValue
+
+/***********************************************************************/
+/* STRING SetValue: get the character representation of a tiny int. */
+/***********************************************************************/
+void TYPVAL<PSZ>::SetValue(uchar c)
+ {
+ SetValue((uint)c);
+ Null = false;
+ } // end of SetValue
+
+/***********************************************************************/
+/* STRING SetBinValue: fill string with chars extracted from a line. */
+/***********************************************************************/
+void TYPVAL<PSZ>::SetBinValue(void *p)
+ {
+ SetValue_char((char *)p, Len);
+ } // end of SetBinValue
+
+/***********************************************************************/
+/* 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 TYPVAL<PSZ>::GetBinValue(void *buf, int buflen, bool go)
+ {
+ int len = (Null) ? 0 : strlen(Strp);
+
+ if (len > buflen)
+ return true;
+ else if (go) {
+ memset(buf, ' ', buflen);
+ memcpy(buf, Strp, len);
+ } // endif go
+
+ return false;
+ } // end of GetBinValue
+
+/***********************************************************************/
+/* STRING ShowValue: get string representation of a char value. */
+/***********************************************************************/
+char *TYPVAL<PSZ>::ShowValue(char *buf, int len)
+ {
+ return Strp;
+ } // end of ShowValue
+
+/***********************************************************************/
+/* STRING GetCharString: get string representation of a char value. */
+/***********************************************************************/
+char *TYPVAL<PSZ>::GetCharString(char *p)
+ {
+ return Strp;
+ } // end of GetCharString
+
+/***********************************************************************/
+/* STRING compare value with another Value. */
+/***********************************************************************/
+bool TYPVAL<PSZ>::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];
+
+ if (Ci || vp->IsCi())
+ return !stricmp(Strp, vp->GetCharString(buf));
+ else // (!Ci)
+ return !strcmp(Strp, vp->GetCharString(buf));
+
+ } // end of IsEqual
+
+/***********************************************************************/
+/* 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 TYPVAL<PSZ>::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
+
+/***********************************************************************/
+/* STRING SetFormat function (used to set SELECT output format). */
+/***********************************************************************/
+bool TYPVAL<PSZ>::SetConstFormat(PGLOBAL g, FORMAT& fmt)
+ {
+ fmt.Type[0] = 'C';
+ fmt.Length = Len;
+ fmt.Prec = 0;
+ return false;
+ } // end of SetConstFormat
+
+/* -------------------------- Class DTVAL ---------------------------- */
+
+/***********************************************************************/
+/* DTVAL public constructor for new void values. */
+/***********************************************************************/
+DTVAL::DTVAL(PGLOBAL g, int n, int prec, PSZ fmt)
+ : TYPVAL<int>((int)0, TYPE_DATE)
+ {
+ if (!fmt) {
+ Pdtp = NULL;
+ Sdate = NULL;
+ DefYear = 0;
+ Len = n;
+ } else
+ SetFormat(g, fmt, n, prec);
+
+//Type = TYPE_DATE;
+ } // end of DTVAL constructor
+
+/***********************************************************************/
+/* DTVAL public constructor from int. */
+/***********************************************************************/
+DTVAL::DTVAL(PGLOBAL g, int n) : TYPVAL<int>(n, TYPE_DATE)
+ {
+ Pdtp = NULL;
+ Len = 19;
+//Type = TYPE_DATE;
+ Sdate = NULL;
+ DefYear = 0;
+ } // end of DTVAL constructor
+
+/***********************************************************************/
+/* Set format so formatted dates can be converted on input/output. */
+/***********************************************************************/
+bool DTVAL::SetFormat(PGLOBAL g, PSZ fmt, int len, int year)
+ {
+ Pdtp = MakeDateFormat(g, fmt, true, true, (year > 9999) ? 1 : 0);
+ Sdate = (char*)PlugSubAlloc(g, NULL, len + 1);
+ DefYear = (int)((year > 9999) ? (year - 10000) : year);
+ Len = len;
+ return false;
+ } // end of SetFormat
+
+/***********************************************************************/
+/* Set format from the format of another date value. */
+/***********************************************************************/
+bool DTVAL::SetFormat(PGLOBAL g, PVAL valp)
+ {
+ DTVAL *vp;
+
+ if (valp->GetType() != TYPE_DATE) {
+ sprintf(g->Message, MSG(NO_FORMAT_TYPE), valp->GetType());
+ return true;
+ } else
+ vp = (DTVAL*)valp;
+
+ Len = vp->Len;
+ Pdtp = vp->Pdtp;
+ Sdate = (char*)PlugSubAlloc(g, NULL, Len + 1);
+ DefYear = vp->DefYear;
+ return false;
+ } // end of SetFormat
+
+/***********************************************************************/
+/* We need TimeShift because the mktime C function does a correction */
+/* for local time zone that we want to override for DB operations. */
+/***********************************************************************/
+void DTVAL::SetTimeShift(void)
+ {
+ struct tm dtm;
+ memset(&dtm, 0, sizeof(dtm));
+ dtm.tm_mday=2;
+ dtm.tm_mon=0;
+ dtm.tm_year=70;
+
+ Shift = (int)mktime(&dtm) - 86400;
+
+ if (trace)
+ htrc("DTVAL Shift=%d\n", Shift);
+
+ } // end of SetTimeShift
+
+// Added by Alexander Barkov
+static void TIME_to_localtime(struct tm *tm, const MYSQL_TIME *ltime)
+{
+ bzero(tm, sizeof(*tm));
+ tm->tm_year= ltime->year - 1900;
+ tm->tm_mon= ltime->month - 1;
+ tm->tm_mday= ltime->day;
+ tm->tm_hour= ltime->hour;
+ tm->tm_min= ltime->minute;
+ tm->tm_sec= ltime->second;
+}
+
+// Added by Alexander Barkov
+static struct tm *gmtime_mysql(const time_t *timep, struct tm *tm)
+{
+ MYSQL_TIME ltime;
+ thd_gmt_sec_to_TIME(current_thd, &ltime, (my_time_t) *timep);
+ TIME_to_localtime(tm, &ltime);
+ return tm;
+}
+
+/***********************************************************************/
+/* GetGmTime: returns a pointer to a static tm structure obtained */
+/* though the gmtime C function. The purpose of this function is to */
+/* extend the range of valid dates by accepting negative time values. */
+/***********************************************************************/
+struct tm *DTVAL::GetGmTime(struct tm *tm_buffer)
+ {
+ struct tm *datm;
+ time_t t = (time_t)Tval;
+
+ if (Tval < 0) {
+ int n;
+
+ for (n = 0; t < 0; n += 4)
+ t += FOURYEARS;
+
+ datm = gmtime_mysql(&t, tm_buffer);
+
+ if (datm)
+ datm->tm_year -= n;
+
+ } else
+ datm = gmtime_mysql(&t, tm_buffer);
+
+ return datm;
+ } // end of GetGmTime
+
+// Added by Alexander Barkov
+static time_t mktime_mysql(struct tm *ptm)
+{
+ MYSQL_TIME ltime;
+ localtime_to_TIME(&ltime, ptm);
+ ltime.time_type= MYSQL_TIMESTAMP_DATETIME;
+ uint error_code;
+ time_t t= TIME_to_timestamp(current_thd, &ltime, &error_code);
+ return error_code ? (time_t) -1 : t;
+}
+
+/***********************************************************************/
+/* MakeTime: calculates a date value from a tm structures using the */
+/* mktime C function. The purpose of this function is to extend the */
+/* range of valid dates by accepting to set negative time values. */
+/***********************************************************************/
+bool DTVAL::MakeTime(struct tm *ptm)
+ {
+ int n, y = ptm->tm_year;
+ time_t t = mktime_mysql(ptm);
+
+ if (trace > 1)
+ htrc("MakeTime from (%d,%d,%d,%d,%d,%d)\n",
+ ptm->tm_year, ptm->tm_mon, ptm->tm_mday,
+ ptm->tm_hour, ptm->tm_min, ptm->tm_sec);
+
+ if (t == -1) {
+ if (y < 1 || y > 71)
+ return true;
+
+ for (n = 0; t == -1 && n < 20; n++) {
+ ptm->tm_year += 4;
+ t = mktime_mysql(ptm);
+ } // endfor t
+
+ if (t == -1)
+ return true;
+
+ if ((t -= (n * FOURYEARS)) > 2000000000)
+ return true;
+
+ }
+ Tval= (int) t;
+
+ if (trace > 1)
+ htrc("MakeTime Ival=%d\n", Tval);
+
+ return false;
+ } // end of MakeTime
+
+/***********************************************************************/
+/* Make a time_t datetime from its components (YY, MM, DD, hh, mm, ss) */
+/***********************************************************************/
+bool DTVAL::MakeDate(PGLOBAL g, int *val, int nval)
+ {
+ int i, m;
+ int n;
+ bool rc = false;
+ struct tm datm;
+ bzero(&datm, sizeof(datm));
+ datm.tm_mday=1;
+ datm.tm_mon=0;
+ datm.tm_year=70;
+
+ if (trace > 1)
+ htrc("MakeDate from(%d,%d,%d,%d,%d,%d) nval=%d\n",
+ val[0], val[1], val[2], val[3], val[4], val[5], nval);
+
+ for (i = 0; i < nval; i++) {
+ n = val[i];
+
+// if (trace > 1)
+// htrc("i=%d n=%d\n", i, n);
+
+ switch (i) {
+ case 0:
+ if (n >= 1900)
+ n -= 1900;
+
+ datm.tm_year = n;
+
+// if (trace > 1)
+// htrc("n=%d tm_year=%d\n", n, datm.tm_year);
+
+ break;
+ case 1:
+ // If mktime handles apparently correctly large or negative
+ // day values, it is not the same for months. Therefore we
+ // do the ajustment here, thus mktime has not to do it.
+ if (n > 0) {
+ m = (n - 1) % 12;
+ n = (n - 1) / 12;
+ } else {
+ m = 11 + n % 12;
+ n = n / 12 - 1;
+ } // endfi n
+
+ datm.tm_mon = m;
+ datm.tm_year += n;
+
+// if (trace > 1)
+// htrc("n=%d m=%d tm_year=%d tm_mon=%d\n", n, m, datm.tm_year, datm.tm_mon);
+
+ break;
+ case 2:
+ // For days, big or negative values may also cause problems
+ m = n % 1461;
+ n = 4 * (n / 1461);
+
+ if (m < 0) {
+ m += 1461;
+ n -= 4;
+ } // endif m
+
+ datm.tm_mday = m;
+ datm.tm_year += n;
+
+// if (trace > 1)
+// htrc("n=%d m=%d tm_year=%d tm_mon=%d\n", n, m, datm.tm_year, datm.tm_mon);
+
+ break;
+ case 3: datm.tm_hour = n; break;
+ case 4: datm.tm_min = n; break;
+ case 5: datm.tm_sec = n; break;
+ } // endswitch i
+
+ } // endfor i
+
+ if (trace > 1)
+ htrc("MakeDate datm=(%d,%d,%d,%d,%d,%d)\n",
+ datm.tm_year, datm.tm_mon, datm.tm_mday,
+ datm.tm_hour, datm.tm_min, datm.tm_sec);
+
+ // Pass g to have an error return or NULL to set invalid dates to 0
+ if (MakeTime(&datm))
+ if (g) {
+ strcpy(g->Message, MSG(BAD_DATETIME));
+ rc = true;
+ } else
+ Tval = 0;
+
+ return rc;
+ } // end of MakeDate
+
+/***********************************************************************/
+/* DTVAL SetValue: copy the value of another Value object. */
+/* This function allows conversion if chktype is false. */
+/***********************************************************************/
+bool DTVAL::SetValue_pval(PVAL valp, bool chktype)
+ {
+ if (chktype && Type != valp->GetType())
+ return true;
+
+ if (!(Null = valp->IsNull() && Nullable)) {
+ if (Pdtp && !valp->IsTypeNum()) {
+ int ndv;
+ int dval[6];
+
+ ndv = ExtractDate(valp->GetCharValue(), Pdtp, DefYear, dval);
+ MakeDate(NULL, dval, ndv);
+ } else
+ Tval = valp->GetIntValue();
+
+ } else
+ Reset();
+
+ return false;
+ } // end of SetValue
+
+/***********************************************************************/
+/* SetValue: convert chars extracted from a line to date value. */
+/***********************************************************************/
+bool DTVAL::SetValue_char(char *p, int n)
+ {
+ bool rc;
+
+ if (Pdtp) {
+ char *p2;
+ int ndv;
+ int dval[6];
+
+ // Trim trailing blanks
+ for (p2 = p + n -1; p < p2 && *p2 == ' '; p2--) ;
+
+ if ((rc = (n = p2 - p + 1) > Len))
+ n = Len;
+
+ memcpy(Sdate, p, n);
+ Sdate[n] = '\0';
+
+ ndv = ExtractDate(Sdate, Pdtp, DefYear, dval);
+ MakeDate(NULL, dval, ndv);
+
+ if (trace > 1)
+ htrc(" setting date: '%s' -> %d\n", Sdate, Tval);
+
+ Null = false;
+ } else
+ rc = TYPVAL<int>::SetValue_char(p, n);
+
+ return rc;
+ } // end of SetValue
+
+/***********************************************************************/
+/* SetValue: convert a char string to date value. */
+/***********************************************************************/
+void DTVAL::SetValue_psz(PSZ p)
+ {
+ if (Pdtp) {
+ int ndv;
+ int dval[6];
+
+ strncpy(Sdate, p, Len);
+ Sdate[Len] = '\0';
+
+ ndv = ExtractDate(Sdate, Pdtp, DefYear, dval);
+ MakeDate(NULL, dval, ndv);
+
+ if (trace > 1)
+ htrc(" setting date: '%s' -> %d\n", Sdate, Tval);
+
+ Null = false;
+ } else
+ TYPVAL<int>::SetValue_psz(p);
+
+ } // end of SetValue
+
+/***********************************************************************/
+/* DTVAL SetValue: set value with a value extracted from a block. */
+/***********************************************************************/
+void DTVAL::SetValue_pvblk(PVBLK blk, int n)
+ {
+ if (Pdtp && !::IsTypeNum(blk->GetType())) {
+ int ndv;
+ int dval[6];
+
+ ndv = ExtractDate(blk->GetCharValue(n), Pdtp, DefYear, dval);
+ MakeDate(NULL, dval, ndv);
+ } else
+ Tval = blk->GetIntValue(n);
+
+ } // end of SetValue
+
+/***********************************************************************/
+/* DTVAL GetCharString: get string representation of a date value. */
+/***********************************************************************/
+char *DTVAL::GetCharString(char *p)
+ {
+ if (Pdtp) {
+ size_t n = 0;
+ struct tm tm, *ptm= GetGmTime(&tm);
+
+ if (ptm)
+ n = strftime(Sdate, Len + 1, Pdtp->OutFmt, ptm);
+
+ if (!n) {
+ *Sdate = '\0';
+ strncat(Sdate, "Error", Len + 1);
+ } // endif n
+
+ return Sdate;
+ } else
+ sprintf(p, "%d", Tval);
+
+ Null = false;
+ return p;
+ } // end of GetCharString
+
+/***********************************************************************/
+/* DTVAL ShowValue: get string representation of a date value. */
+/***********************************************************************/
+char *DTVAL::ShowValue(char *buf, int len)
+ {
+ if (Pdtp) {
+ char *p;
+ size_t m, n = 0;
+ struct tm tm, *ptm = GetGmTime(&tm);
+
+ if (Len < len) {
+ p = buf;
+ m = len;
+ } else {
+ p = Sdate;
+ m = Len + 1;
+ } // endif Len
+
+ if (ptm)
+ n = strftime(p, m, Pdtp->OutFmt, ptm);
+
+ if (!n) {
+ *p = '\0';
+ strncat(p, "Error", m);
+ } // endif n
+
+ return p;
+ } else
+ return TYPVAL<int>::ShowValue(buf, len);
+
+ } // end of ShowValue
+
+#if 0 // Not used by CONNECT
+/***********************************************************************/
+/* Returns a member of the struct tm representation of the date. */
+/***********************************************************************/
+bool DTVAL::GetTmMember(OPVAL op, int& mval)
+ {
+ bool rc = false;
+ struct tm tm, *ptm = GetGmTime(&tm);
+
+ switch (op) {
+ case OP_MDAY: mval = ptm->tm_mday; break;
+ case OP_MONTH: mval = ptm->tm_mon + 1; break;
+ case OP_YEAR: mval = ptm->tm_year + 1900; break;
+ case OP_WDAY: mval = ptm->tm_wday + 1; break;
+ case OP_YDAY: mval = ptm->tm_yday + 1; break;
+ case OP_QUART: mval = ptm->tm_mon / 3 + 1; break;
+ default:
+ rc = true;
+ } // endswitch op
+
+ return rc;
+ } // end of GetTmMember
+
+/***********************************************************************/
+/* Calculates the week number of the year for the internal date value.*/
+/* The International Standard ISO 8601 has decreed that Monday shall */
+/* be the first day of the week. A week that lies partly in one year */
+/* and partly in another is assigned a number in the year in which */
+/* most of its days lie. That means that week number 1 of any year is */
+/* the week that contains the January 4th. */
+/***********************************************************************/
+bool DTVAL::WeekNum(PGLOBAL g, int& nval)
+ {
+ // w is the start of the week SUN=0, MON=1, etc.
+ int m, n, w = nval % 7;
+ struct tm tm, *ptm = GetGmTime(&tm);
+
+ // Which day is January 4th of this year?
+ m = (367 + ptm->tm_wday - ptm->tm_yday) % 7;
+
+ // When does the first week begins?
+ n = 3 - (7 + m - w) % 7;
+
+ // Now calculate the week number
+ if (!(nval = (7 + ptm->tm_yday - n) / 7))
+ nval = 52;
+
+ // Everything should be Ok
+ return false;
+ } // end of WeekNum
+#endif // 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 DTVAL::FormatValue(PVAL vp, char *fmt)
+ {
+ char *buf = (char*)vp->GetTo_Val(); // Should be big enough
+ struct tm tm, *ptm = GetGmTime(&tm);
+
+ if (trace)
+ htrc("FormatValue: ptm=%p len=%d\n", ptm, vp->GetValLen());
+
+ if (ptm) {
+ size_t n = strftime(buf, vp->GetValLen(), fmt, ptm);
+
+ if (trace)
+ htrc("strftime: n=%d buf=%s\n", n, (n) ? buf : "???");
+
+ return (n == 0);
+ } else
+ return true;
+
+ } // end of FormatValue
+
+/* -------------------------- End of Value --------------------------- */
diff --git a/storage/connect/value.h b/storage/connect/value.h
index 5dc4ef98d51..185234b42b9 100644
--- a/storage/connect/value.h
+++ b/storage/connect/value.h
@@ -16,11 +16,6 @@
#include "assert.h"
#include "block.h"
-#if defined(WIN32)
-#define strtoll _strtoi64
-#define atoll(S) strtoll(S, NULL, 10)
-#endif // WIN32
-
/***********************************************************************/
/* Types used in some class definitions. */
/***********************************************************************/
@@ -55,6 +50,8 @@ DllExport bool IsTypeNum(int type);
DllExport PVAL AllocateValue(PGLOBAL, PVAL, int = TYPE_VOID, int = 0);
DllExport PVAL AllocateValue(PGLOBAL, int, int len = 0, int prec = 0,
PSZ fmt = NULL);
+DllExport ulonglong CharToNumber(char *, int, ulonglong, bool,
+ bool *minus = NULL, bool *rc = NULL);
/***********************************************************************/
/* Class VALUE represents a constant or variable of any valid type. */
@@ -96,7 +93,7 @@ class DllExport VALUE : public BLOCK {
// Methods
virtual bool SetValue_pval(PVAL valp, bool chktype = false) = 0;
- virtual void SetValue_char(char *p, int n) = 0;
+ virtual bool SetValue_char(char *p, int n) = 0;
virtual void SetValue_psz(PSZ s) = 0;
virtual void SetValue(char c) {assert(false);}
virtual void SetValue(uchar c) {assert(false);}
@@ -112,11 +109,6 @@ class DllExport VALUE : public BLOCK {
virtual bool GetBinValue(void *buf, int buflen, bool go) = 0;
virtual char *ShowValue(char *buf, int len = 0) = 0;
virtual char *GetCharString(char *p) = 0;
-//virtual char *GetShortString(char *p, int n) {return "#####";}
-//virtual char *GetIntString(char *p, int n) = 0;
-//virtual char *GetBigintString(char *p, int n) = 0;
-//virtual char *GetFloatString(char *p, int n, int prec) = 0;
-//virtual char *GetTinyString(char *p, int n) {return "?";}
virtual bool IsEqual(PVAL vp, bool chktype) = 0;
virtual bool FormatValue(PVAL vp, char *fmt) = 0;
@@ -169,7 +161,7 @@ class DllExport TYPVAL : public VALUE {
// Methods
virtual bool SetValue_pval(PVAL valp, bool chktype);
- virtual void SetValue_char(char *p, int n);
+ virtual bool SetValue_char(char *p, int n);
virtual void SetValue_psz(PSZ s);
virtual void SetValue(char c) {Tval = (TYPE)c; Null = false;}
virtual void SetValue(uchar c) {Tval = (TYPE)c; Null = false;}
@@ -185,11 +177,6 @@ class DllExport TYPVAL : public VALUE {
virtual bool GetBinValue(void *buf, int buflen, bool go);
virtual char *ShowValue(char *buf, int);
virtual char *GetCharString(char *p);
-//virtual char *GetShortString(char *p, int n);
-//virtual char *GetIntString(char *p, int n);
-//virtual char *GetBigintString(char *p, int n);
-//virtual char *GetFloatString(char *p, int n, int prec = -1);
-//virtual char *GetTinyString(char *p, int n);
virtual bool IsEqual(PVAL vp, bool chktype);
virtual bool SetConstFormat(PGLOBAL, FORMAT&);
virtual bool FormatValue(PVAL vp, char *fmt);
@@ -201,9 +188,10 @@ class DllExport TYPVAL : public VALUE {
TYPVAL(void) : VALUE(TYPE_ERROR) {}
// Specialized functions
- TYPE GetTypedValue(PVAL vp);
- TYPE GetTypedValue(PVBLK blk, int n);
- TYPE GetTypedValue(PSZ s);
+ static ulonglong MaxVal(void);
+ TYPE GetTypedValue(PVAL vp);
+ TYPE GetTypedValue(PVBLK blk, int n);
+// TYPE GetTypedValue(PSZ s);
// Members
TYPE Tval;
@@ -227,21 +215,21 @@ class DllExport TYPVAL<PSZ>: public VALUE {
virtual int GetValPrec() {return (Ci) ? 1 : 0;}
virtual int GetSize(void) {return (Strp) ? strlen(Strp) : 0;}
virtual PSZ GetCharValue(void) {return Strp;}
- virtual char GetTinyValue(void) {return (char)atoi(Strp);}
- virtual uchar GetUTinyValue(void) {return (uchar)atoi(Strp);}
- virtual short GetShortValue(void) {return (short)atoi(Strp);}
- virtual ushort GetUShortValue(void) {return (ushort)atoi(Strp);}
- virtual int GetIntValue(void) {return atol(Strp);}
- virtual uint GetUIntValue(void) {return (uint)atol(Strp);}
- virtual longlong GetBigintValue(void) {return atoll(Strp);}
- virtual ulonglong GetUBigintValue(void) {return (ulonglong)atoll(Strp);}
+ virtual char GetTinyValue(void);
+ virtual uchar GetUTinyValue(void);
+ virtual short GetShortValue(void);
+ virtual ushort GetUShortValue(void);
+ virtual int GetIntValue(void);
+ virtual uint GetUIntValue(void);
+ virtual longlong GetBigintValue(void);
+ virtual ulonglong GetUBigintValue(void);
virtual double GetFloatValue(void) {return atof(Strp);}
virtual void *GetTo_Val(void) {return Strp;}
virtual void SetPrec(int prec) {Ci = prec != 0;}
// Methods
virtual bool SetValue_pval(PVAL valp, bool chktype);
- virtual void SetValue_char(char *p, int n);
+ virtual bool SetValue_char(char *p, int n);
virtual void SetValue_psz(PSZ s);
virtual void SetValue_pvblk(PVBLK blk, int n);
virtual void SetValue(char c);
@@ -257,23 +245,10 @@ class DllExport TYPVAL<PSZ>: public VALUE {
virtual bool GetBinValue(void *buf, int buflen, bool go);
virtual char *ShowValue(char *buf, int);
virtual char *GetCharString(char *p);
-//virtual char *GetShortString(char *p, int n);
-//virtual char *GetIntString(char *p, int n);
-//virtual char *GetBigintString(char *p, int n);
-//virtual char *GetFloatString(char *p, int n, int prec = -1);
-//virtual char *GetTinyString(char *p, int n);
virtual bool IsEqual(PVAL vp, bool chktype);
virtual bool FormatValue(PVAL vp, char *fmt);
virtual bool SetConstFormat(PGLOBAL, FORMAT&);
- // Specialized functions
-//template <class T>
-//T GetValue_as(T type) {return Strp;}
-//int GetValue_as(int type) {return atol(Strp);}
-//short GetValue_as(short type) {return (short)atoi(Strp);}
-//longlong GetValue_as(longlong type) {return atoll(Strp);}
-//double GetValue_as(double type) {return atof(Strp);}
-
// Members
PSZ Strp;
bool Ci; // true if case insensitive
@@ -295,7 +270,7 @@ class DllExport DTVAL : public TYPVAL<int> {
// Implementation
virtual bool SetValue_pval(PVAL valp, bool chktype);
- virtual void SetValue_char(char *p, int n);
+ virtual bool SetValue_char(char *p, int n);
virtual void SetValue_psz(PSZ s);
virtual void SetValue_pvblk(PVBLK blk, int n);
virtual char *GetCharString(char *p);
@@ -304,15 +279,15 @@ class DllExport DTVAL : public TYPVAL<int> {
bool SetFormat(PGLOBAL g, PSZ fmt, int len, int year = 0);
bool SetFormat(PGLOBAL g, PVAL valp);
bool IsFormatted(void) {return Pdtp != NULL;}
- bool GetTmMember(OPVAL op, int& mval);
- bool DateDiff(DTVAL *dtp, OPVAL op, int& tdif);
+// bool GetTmMember(OPVAL op, int& mval);
+// bool DateDiff(DTVAL *dtp, OPVAL op, int& tdif);
bool MakeTime(struct tm *ptm);
static void SetTimeShift(void);
static int GetShift(void) {return Shift;}
// Methods
bool MakeDate(PGLOBAL g, int *val, int nval);
- bool WeekNum(PGLOBAL g, int& nval);
+// bool WeekNum(PGLOBAL g, int& nval);
struct tm *GetGmTime(struct tm *);
diff --git a/storage/connect/xobject.cpp b/storage/connect/xobject.cpp
index cd8af248005..3da78426e95 100644
--- a/storage/connect/xobject.cpp
+++ b/storage/connect/xobject.cpp
@@ -134,6 +134,7 @@ bool CONSTANT::Compare(PXOB xp)
} // end of Compare
+#if 0
/***********************************************************************/
/* Rephrase: temporary implementation used by PlugRephraseSQL. */
/***********************************************************************/
@@ -166,6 +167,7 @@ bool CONSTANT::Rephrase(PGLOBAL g, PSZ work)
return false;
} // end of Rephrase
+#endif // 0
/***********************************************************************/
/* Make file output of a constant object. */
diff --git a/storage/connect/xobject.h b/storage/connect/xobject.h
index 79325f155cf..74d571a6e60 100644
--- a/storage/connect/xobject.h
+++ b/storage/connect/xobject.h
@@ -124,7 +124,7 @@ class DllExport CONSTANT : public XOBJECT {
{return Value->SetConstFormat(g, fmt);}
virtual int CheckSpcCol(PTDB, int) {return 1;}
void Convert(PGLOBAL g, int newtype);
- bool Rephrase(PGLOBAL g, PSZ work);
+// bool Rephrase(PGLOBAL g, PSZ work);
void SetValue(PVAL vp) {Value = vp;}
virtual bool VerifyColumn(PTBX txp) {return true;}
virtual bool VerifyTdb(PTDB& tdbp) {return true;}