Commit afd373c1 authored by Olivier Bertrand's avatar Olivier Bertrand

- Set connection charset before calling mysql_real_connect for MYSQL

  tables. This should fix bug MDEV-7343.
modified:
  storage/connect/ha_connect.cc
  storage/connect/myconn.cpp
  storage/connect/myconn.h
  storage/connect/reldef.cpp
  storage/connect/reldef.h
  storage/connect/table.cpp
  storage/connect/tabmysql.cpp
  storage/connect/xtable.h

- Prevent double column evaluation when CONNECT does filtering
modified:
  storage/connect/connect.cc

- Export CreateFileMap and CloseMemMap (for OEM tables)
modified:
  storage/connect/maputil.h

- Add the compute function to be used on VALUE types.
  Preserve precision for DOUBLE values.
modified:
  storage/connect/value.cpp
  storage/connect/value.h

- Typo (in preparation to the future JSON table type)
modified:
  storage/connect/ha_connect.cc
  storage/connect/mycat.cc
  storage/connect/plgdbsem.h
parent 8761f22a
...@@ -52,7 +52,7 @@ ...@@ -52,7 +52,7 @@
/* Routines called internally by semantic routines. */ /* Routines called internally by semantic routines. */
/***********************************************************************/ /***********************************************************************/
void CntEndDB(PGLOBAL); void CntEndDB(PGLOBAL);
RCODE EvalColumns(PGLOBAL g, PTDB tdbp, bool mrr= false); RCODE EvalColumns(PGLOBAL g, PTDB tdbp, bool reset, bool mrr= false);
/***********************************************************************/ /***********************************************************************/
/* MySQL routines called externally by semantic routines. */ /* MySQL routines called externally by semantic routines. */
...@@ -388,7 +388,7 @@ bool CntRewindTable(PGLOBAL g, PTDB tdbp) ...@@ -388,7 +388,7 @@ bool CntRewindTable(PGLOBAL g, PTDB tdbp)
/***********************************************************************/ /***********************************************************************/
/* Evaluate all columns after a record is read. */ /* Evaluate all columns after a record is read. */
/***********************************************************************/ /***********************************************************************/
RCODE EvalColumns(PGLOBAL g, PTDB tdbp, bool mrr) RCODE EvalColumns(PGLOBAL g, PTDB tdbp, bool reset, bool mrr)
{ {
RCODE rc= RC_OK; RCODE rc= RC_OK;
PCOL colp; PCOL colp;
...@@ -413,6 +413,7 @@ RCODE EvalColumns(PGLOBAL g, PTDB tdbp, bool mrr) ...@@ -413,6 +413,7 @@ RCODE EvalColumns(PGLOBAL g, PTDB tdbp, bool mrr)
for (colp= tdbp->GetColumns(); rc == RC_OK && colp; for (colp= tdbp->GetColumns(); rc == RC_OK && colp;
colp= colp->GetNext()) { colp= colp->GetNext()) {
if (reset)
colp->Reset(); colp->Reset();
// Virtual columns are computed by MariaDB // Virtual columns are computed by MariaDB
...@@ -457,6 +458,10 @@ RCODE CntReadNext(PGLOBAL g, PTDB tdbp) ...@@ -457,6 +458,10 @@ RCODE CntReadNext(PGLOBAL g, PTDB tdbp)
goto err; goto err;
} // endif rc } // endif rc
// Do it now to avoid double eval when filtering
for (PCOL colp= tdbp->GetColumns(); colp; colp= colp->GetNext())
colp->Reset();
do { do {
if ((rc= (RCODE)tdbp->ReadDB(g)) == RC_OK) if ((rc= (RCODE)tdbp->ReadDB(g)) == RC_OK)
if (!ApplyFilter(g, tdbp->GetFilter())) if (!ApplyFilter(g, tdbp->GetFilter()))
...@@ -466,7 +471,7 @@ RCODE CntReadNext(PGLOBAL g, PTDB tdbp) ...@@ -466,7 +471,7 @@ RCODE CntReadNext(PGLOBAL g, PTDB tdbp)
err: err:
g->jump_level--; g->jump_level--;
return (rc != RC_OK) ? rc : EvalColumns(g, tdbp); return (rc != RC_OK) ? rc : EvalColumns(g, tdbp, false);
} // end of CntReadNext } // end of CntReadNext
/***********************************************************************/ /***********************************************************************/
...@@ -812,7 +817,7 @@ RCODE CntIndexRead(PGLOBAL g, PTDB ptdb, OPVAL op, ...@@ -812,7 +817,7 @@ RCODE CntIndexRead(PGLOBAL g, PTDB ptdb, OPVAL op,
rnd: rnd:
if ((rc= (RCODE)ptdb->ReadDB(g)) == RC_OK) if ((rc= (RCODE)ptdb->ReadDB(g)) == RC_OK)
rc= EvalColumns(g, ptdb, mrr); rc= EvalColumns(g, ptdb, true, mrr);
return rc; return rc;
} // end of CntIndexRead } // end of CntIndexRead
......
...@@ -1055,6 +1055,14 @@ char *ha_connect::GetStringOption(char *opname, char *sdef) ...@@ -1055,6 +1055,14 @@ char *ha_connect::GetStringOption(char *opname, char *sdef)
opval= (char*)options->colist; opval= (char*)options->colist;
else if (!stricmp(opname, "Data_charset")) else if (!stricmp(opname, "Data_charset"))
opval= (char*)options->data_charset; opval= (char*)options->data_charset;
else if (!stricmp(opname, "Table_charset")) {
const CHARSET_INFO *chif= (tshp) ? tshp->table_charset
: table->s->table_charset;
if (chif)
opval= (char*)chif->csname;
} // endif Table_charset
if (!opval && options && options->oplist) if (!opval && options && options->oplist)
opval= GetListOption(xp->g, opname, options->oplist); opval= GetListOption(xp->g, opname, options->oplist);
...@@ -3806,6 +3814,7 @@ bool ha_connect::check_privileges(THD *thd, PTOS options, char *dbn) ...@@ -3806,6 +3814,7 @@ bool ha_connect::check_privileges(THD *thd, PTOS options, char *dbn)
case TAB_XML: case TAB_XML:
case TAB_INI: case TAB_INI:
case TAB_VEC: case TAB_VEC:
// case TAB_JSON:
if (options->filename && *options->filename) { if (options->filename && *options->filename) {
char *s, path[FN_REFLEN], dbpath[FN_REFLEN]; char *s, path[FN_REFLEN], dbpath[FN_REFLEN];
#if defined(WIN32) #if defined(WIN32)
......
...@@ -11,8 +11,8 @@ typedef struct { ...@@ -11,8 +11,8 @@ typedef struct {
DWORD lenH; DWORD lenH;
} MEMMAP; } MEMMAP;
HANDLE CreateFileMap(PGLOBAL, LPCSTR, MEMMAP *, MODE, bool); DllExport HANDLE CreateFileMap(PGLOBAL, LPCSTR, MEMMAP *, MODE, bool);
bool CloseMemMap(void *memory, size_t dwSize); DllExport bool CloseMemMap(void *memory, size_t dwSize);
#ifdef __cplusplus #ifdef __cplusplus
} }
......
/* Copyright (C) Olivier Bertrand 2004 - 2013 /* Copyright (C) Olivier Bertrand 2004 - 2014
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
/* ------------- */ /* ------------- */
/* Version 1.4 */ /* Version 1.4 */
/* */ /* */
/* Author: Olivier Bertrand 2012 - 2013 */ /* Author: Olivier Bertrand 2012 - 2014 */
/* */ /* */
/* WHAT THIS PROGRAM DOES: */ /* WHAT THIS PROGRAM DOES: */
/* ----------------------- */ /* ----------------------- */
...@@ -89,6 +89,7 @@ ...@@ -89,6 +89,7 @@
#include "tabpivot.h" #include "tabpivot.h"
#endif // PIVOT_SUPPORT #endif // PIVOT_SUPPORT
#include "tabvir.h" #include "tabvir.h"
//#include "tabjson.h"
#include "ha_connect.h" #include "ha_connect.h"
#include "mycat.h" #include "mycat.h"
...@@ -139,6 +140,7 @@ TABTYPE GetTypeID(const char *type) ...@@ -139,6 +140,7 @@ TABTYPE GetTypeID(const char *type)
: (!stricmp(type, "PIVOT")) ? TAB_PIVOT : (!stricmp(type, "PIVOT")) ? TAB_PIVOT
#endif #endif
: (!stricmp(type, "VIR")) ? TAB_VIR : (!stricmp(type, "VIR")) ? TAB_VIR
// : (!stricmp(type, "JSON")) ? TAB_JSON
: (!stricmp(type, "OEM")) ? TAB_OEM : TAB_NIY; : (!stricmp(type, "OEM")) ? TAB_OEM : TAB_NIY;
} // end of GetTypeID } // end of GetTypeID
...@@ -159,6 +161,7 @@ bool IsFileType(TABTYPE type) ...@@ -159,6 +161,7 @@ bool IsFileType(TABTYPE type)
case TAB_XML: case TAB_XML:
case TAB_INI: case TAB_INI:
case TAB_VEC: case TAB_VEC:
// case TAB_JSON:
isfile= true; isfile= true;
break; break;
default: default:
...@@ -181,6 +184,7 @@ bool IsExactType(TABTYPE type) ...@@ -181,6 +184,7 @@ bool IsExactType(TABTYPE type)
case TAB_BIN: case TAB_BIN:
case TAB_DBF: case TAB_DBF:
// case TAB_XML: depends on Multiple || Xpand || Coltype // case TAB_XML: depends on Multiple || Xpand || Coltype
// case TAB_JSON: depends on Multiple || Xpand || Coltype
case TAB_VEC: case TAB_VEC:
case TAB_VIR: case TAB_VIR:
exact= true; exact= true;
...@@ -214,7 +218,7 @@ bool IsTypeNullable(TABTYPE type) ...@@ -214,7 +218,7 @@ bool IsTypeNullable(TABTYPE type)
} // end of IsTypeNullable } // end of IsTypeNullable
/***********************************************************************/ /***********************************************************************/
/* Return true for indexable table by XINDEX. */ /* Return true for fixed record length tables. */
/***********************************************************************/ /***********************************************************************/
bool IsTypeFixed(TABTYPE type) bool IsTypeFixed(TABTYPE type)
{ {
...@@ -538,6 +542,7 @@ PRELDEF MYCAT::MakeTableDesc(PGLOBAL g, LPCSTR name, LPCSTR am) ...@@ -538,6 +542,7 @@ PRELDEF MYCAT::MakeTableDesc(PGLOBAL g, LPCSTR name, LPCSTR am)
case TAB_PIVOT: tdp= new(g) PIVOTDEF; break; case TAB_PIVOT: tdp= new(g) PIVOTDEF; break;
#endif // PIVOT_SUPPORT #endif // PIVOT_SUPPORT
case TAB_VIR: tdp= new(g) VIRDEF; break; case TAB_VIR: tdp= new(g) VIRDEF; break;
// case TAB_JSON: tdp= new(g) JSONDEF; break;
default: default:
sprintf(g->Message, MSG(BAD_TABLE_TYPE), am, name); sprintf(g->Message, MSG(BAD_TABLE_TYPE), am, name);
} // endswitch } // endswitch
......
...@@ -430,10 +430,11 @@ int MYSQLC::GetResultSize(PGLOBAL g, PSZ sql) ...@@ -430,10 +430,11 @@ int MYSQLC::GetResultSize(PGLOBAL g, PSZ sql)
/***********************************************************************/ /***********************************************************************/
int MYSQLC::Open(PGLOBAL g, const char *host, const char *db, int MYSQLC::Open(PGLOBAL g, const char *host, const char *db,
const char *user, const char *pwd, const char *user, const char *pwd,
int pt) int pt, const char *csname)
{ {
const char *pipe = NULL; const char *pipe = NULL;
uint cto = 6000, nrt = 12000; uint cto = 6000, nrt = 12000;
my_bool my_true= 1;
m_DB = mysql_init(NULL); m_DB = mysql_init(NULL);
...@@ -470,6 +471,18 @@ int MYSQLC::Open(PGLOBAL g, const char *host, const char *db, ...@@ -470,6 +471,18 @@ int MYSQLC::Open(PGLOBAL g, const char *host, const char *db,
} // endif pwd } // endif pwd
#endif // 0 #endif // 0
/***********************************************************************/
/* BUG# 17044 Federated Storage Engine is not UTF8 clean */
/* Add set names to whatever charset the table is at open of table */
/* this sets the csname like 'set names utf8'. */
/***********************************************************************/
if (csname)
mysql_options(m_DB, MYSQL_SET_CHARSET_NAME, csname);
// Don't know what this one do but FEDERATED does it
mysql_options(m_DB, MYSQL_OPT_USE_THREAD_SPECIFIC_MEMORY,
(char*)&my_true);
if (!mysql_real_connect(m_DB, host, user, pwd, db, pt, pipe, CLIENT_MULTI_RESULTS)) { if (!mysql_real_connect(m_DB, host, user, pwd, db, pt, pipe, CLIENT_MULTI_RESULTS)) {
#if defined(_DEBUG) #if defined(_DEBUG)
sprintf(g->Message, "mysql_real_connect failed: (%d) %s", sprintf(g->Message, "mysql_real_connect failed: (%d) %s",
......
...@@ -67,7 +67,7 @@ class DllItem MYSQLC { ...@@ -67,7 +67,7 @@ class DllItem MYSQLC {
int GetTableSize(PGLOBAL g, PSZ query); int GetTableSize(PGLOBAL g, PSZ query);
int Open(PGLOBAL g, const char *host, const char *db, int Open(PGLOBAL g, const char *host, const char *db,
const char *user= "root", const char *pwd= "*", const char *user= "root", const char *pwd= "*",
int pt= 0); int pt= 0, const char *csname = NULL);
int KillQuery(ulong id); int KillQuery(ulong id);
int ExecSQL(PGLOBAL g, const char *query, int *w = NULL); int ExecSQL(PGLOBAL g, const char *query, int *w = NULL);
int ExecSQLcmd(PGLOBAL g, const char *query, int *w); int ExecSQLcmd(PGLOBAL g, const char *query, int *w);
...@@ -98,5 +98,6 @@ class DllItem MYSQLC { ...@@ -98,5 +98,6 @@ class DllItem MYSQLC {
int m_Fields; // The number of result fields int m_Fields; // The number of result fields
int m_Afrw; // The number of affected rows int m_Afrw; // The number of affected rows
bool m_Use; // Use or store result set bool m_Use; // Use or store result set
const char *csname; // Table charset name
}; // end of class MYSQLC }; // end of class MYSQLC
...@@ -74,9 +74,11 @@ enum TABTYPE {TAB_UNDEF = 0, /* Table of undefined type */ ...@@ -74,9 +74,11 @@ enum TABTYPE {TAB_UNDEF = 0, /* Table of undefined type */
TAB_PLG = 20, /* PLG NIY */ TAB_PLG = 20, /* PLG NIY */
TAB_PIVOT = 21, /* PIVOT table */ TAB_PIVOT = 21, /* PIVOT table */
TAB_VIR = 22, /* Virtual tables */ TAB_VIR = 22, /* Virtual tables */
TAB_JCT = 23, /* Junction tables NIY */ TAB_JSON = 23, /* JSON tables */
TAB_DMY = 24, /* DMY Dummy tables NIY */ TAB_JSN = 24, /* Semi-json tables */
TAB_NIY = 25}; /* Table not implemented yet */ TAB_JCT = 25, /* Junction tables NIY */
TAB_DMY = 26, /* DMY Dummy tables NIY */
TAB_NIY = 27}; /* Table not implemented yet */
enum AMT {TYPE_AM_ERROR = 0, /* Type not defined */ enum AMT {TYPE_AM_ERROR = 0, /* Type not defined */
TYPE_AM_ROWID = 1, /* ROWID type (special column) */ TYPE_AM_ROWID = 1, /* ROWID type (special column) */
......
...@@ -202,6 +202,8 @@ TABDEF::TABDEF(void) ...@@ -202,6 +202,8 @@ TABDEF::TABDEF(void)
Degree = 0; Degree = 0;
Pseudo = 0; Pseudo = 0;
Read_Only = false; Read_Only = false;
m_data_charset = NULL;
csname = NULL;
} // end of TABDEF constructor } // end of TABDEF constructor
/***********************************************************************/ /***********************************************************************/
...@@ -224,6 +226,7 @@ bool TABDEF::Define(PGLOBAL g, PCATLG cat, LPCSTR name, LPCSTR am) ...@@ -224,6 +226,7 @@ bool TABDEF::Define(PGLOBAL g, PCATLG cat, LPCSTR name, LPCSTR am)
m_data_charset= data_charset_name ? m_data_charset= data_charset_name ?
get_charset_by_csname(data_charset_name, MY_CS_PRIMARY, 0): get_charset_by_csname(data_charset_name, MY_CS_PRIMARY, 0):
NULL; NULL;
csname = GetStringCatInfo(g, "Table_charset", NULL);
// Get The column definitions // Get The column definitions
if ((poff = GetColCatInfo(g)) < 0) if ((poff = GetColCatInfo(g)) < 0)
......
...@@ -68,6 +68,7 @@ class DllExport TABDEF : public RELDEF { /* Logical table descriptor */ ...@@ -68,6 +68,7 @@ class DllExport TABDEF : public RELDEF { /* Logical table descriptor */
friend class CATALOG; friend class CATALOG;
friend class PLUGCAT; friend class PLUGCAT;
friend class MYCAT; friend class MYCAT;
friend class TDBASE;
public: public:
// Constructor // Constructor
TABDEF(void); // Constructor TABDEF(void); // Constructor
...@@ -110,6 +111,7 @@ class DllExport TABDEF : public RELDEF { /* Logical table descriptor */ ...@@ -110,6 +111,7 @@ class DllExport TABDEF : public RELDEF { /* Logical table descriptor */
int Pseudo; /* Bit: 1 ROWID Ok, 2 FILEID Ok */ int Pseudo; /* Bit: 1 ROWID Ok, 2 FILEID Ok */
bool Read_Only; /* true for read only tables */ bool Read_Only; /* true for read only tables */
const CHARSET_INFO *m_data_charset; const CHARSET_INFO *m_data_charset;
const char *csname; /* Table charset name */
}; // end of TABDEF }; // end of TABDEF
/***********************************************************************/ /***********************************************************************/
......
...@@ -146,6 +146,7 @@ TDBASE::TDBASE(PTABDEF tdp) : TDB(tdp) ...@@ -146,6 +146,7 @@ TDBASE::TDBASE(PTABDEF tdp) : TDB(tdp)
Knum = 0; Knum = 0;
Read_Only = (tdp) ? tdp->IsReadOnly() : false; Read_Only = (tdp) ? tdp->IsReadOnly() : false;
m_data_charset= (tdp) ? tdp->data_charset() : NULL; m_data_charset= (tdp) ? tdp->data_charset() : NULL;
csname = (tdp) ? tdp->csname : NULL;
} // end of TDBASE constructor } // end of TDBASE constructor
TDBASE::TDBASE(PTDBASE tdbp) : TDB(tdbp) TDBASE::TDBASE(PTDBASE tdbp) : TDB(tdbp)
...@@ -161,6 +162,7 @@ TDBASE::TDBASE(PTDBASE tdbp) : TDB(tdbp) ...@@ -161,6 +162,7 @@ TDBASE::TDBASE(PTDBASE tdbp) : TDB(tdbp)
Knum = tdbp->Knum; Knum = tdbp->Knum;
Read_Only = tdbp->Read_Only; Read_Only = tdbp->Read_Only;
m_data_charset= tdbp->m_data_charset; m_data_charset= tdbp->m_data_charset;
csname = tdbp->csname;
} // end of TDBASE copy constructor } // end of TDBASE copy constructor
/***********************************************************************/ /***********************************************************************/
......
...@@ -777,7 +777,7 @@ int TDBMYSQL::Cardinality(PGLOBAL g) ...@@ -777,7 +777,7 @@ int TDBMYSQL::Cardinality(PGLOBAL g)
char query[96]; char query[96];
MYSQLC myc; MYSQLC myc;
if (myc.Open(g, Host, Database, User, Pwd, Port)) if (myc.Open(g, Host, Database, User, Pwd, Port, csname))
return -1; return -1;
strcpy(query, "SELECT COUNT(*) FROM "); strcpy(query, "SELECT COUNT(*) FROM ");
...@@ -871,7 +871,7 @@ bool TDBMYSQL::OpenDB(PGLOBAL g) ...@@ -871,7 +871,7 @@ bool TDBMYSQL::OpenDB(PGLOBAL g)
/* servers allowing concurency in getting results ??? */ /* servers allowing concurency in getting results ??? */
/*********************************************************************/ /*********************************************************************/
if (!Myc.Connected()) { if (!Myc.Connected()) {
if (Myc.Open(g, Host, Database, User, Pwd, Port)) if (Myc.Open(g, Host, Database, User, Pwd, Port, csname))
return true; return true;
} // endif Connected } // endif Connected
......
...@@ -330,7 +330,7 @@ int ConvertType(int target, int type, CONV kind, bool match) ...@@ -330,7 +330,7 @@ int ConvertType(int target, int type, CONV kind, bool match)
/***********************************************************************/ /***********************************************************************/
/* AllocateConstant: allocates a constant Value. */ /* AllocateConstant: allocates a constant Value. */
/***********************************************************************/ /***********************************************************************/
PVAL AllocateValue(PGLOBAL g, void *value, short type) PVAL AllocateValue(PGLOBAL g, void *value, short type, short prec)
{ {
PVAL valp; PVAL valp;
...@@ -351,7 +351,7 @@ PVAL AllocateValue(PGLOBAL g, void *value, short type) ...@@ -351,7 +351,7 @@ PVAL AllocateValue(PGLOBAL g, void *value, short type)
valp = new(g) TYPVAL<longlong>(*(longlong*)value, TYPE_BIGINT); valp = new(g) TYPVAL<longlong>(*(longlong*)value, TYPE_BIGINT);
break; break;
case TYPE_DOUBLE: case TYPE_DOUBLE:
valp = new(g) TYPVAL<double>(*(double *)value, TYPE_DOUBLE, 2); valp = new(g) TYPVAL<double>(*(double *)value, TYPE_DOUBLE, prec);
break; break;
case TYPE_TINY: case TYPE_TINY:
valp = new(g) TYPVAL<char>(*(char *)value, TYPE_TINY); valp = new(g) TYPVAL<char>(*(char *)value, TYPE_TINY);
...@@ -475,7 +475,7 @@ PVAL AllocateValue(PGLOBAL g, PVAL valp, int newtype, int uns) ...@@ -475,7 +475,7 @@ PVAL AllocateValue(PGLOBAL g, PVAL valp, int newtype, int uns)
break; break;
case TYPE_DOUBLE: case TYPE_DOUBLE:
valp = new(g) TYPVAL<double>(valp->GetFloatValue(), TYPE_DOUBLE, valp = new(g) TYPVAL<double>(valp->GetFloatValue(), TYPE_DOUBLE,
valp->GetValPrec()); (uns) ? uns : valp->GetValPrec());
break; break;
case TYPE_TINY: case TYPE_TINY:
if (un) if (un)
...@@ -542,6 +542,15 @@ BYTE VALUE::TestValue(PVAL vp) ...@@ -542,6 +542,15 @@ BYTE VALUE::TestValue(PVAL vp)
return (n > 0) ? 0x04 : (n < 0) ? 0x02 : 0x01; return (n > 0) ? 0x04 : (n < 0) ? 0x02 : 0x01;
} // end of TestValue } // end of TestValue
/***********************************************************************/
/* Compute a function on a string. */
/***********************************************************************/
bool VALUE::Compute(PGLOBAL g, PVAL *vp, int np, OPVAL op)
{
strcpy(g->Message, "Compute not implemented for this value type");
return true;
} // end of Compute
/* -------------------------- Class TYPVAL ---------------------------- */ /* -------------------------- Class TYPVAL ---------------------------- */
/***********************************************************************/ /***********************************************************************/
...@@ -930,6 +939,188 @@ int TYPVAL<TYPE>::CompareValue(PVAL vp) ...@@ -930,6 +939,188 @@ int TYPVAL<TYPE>::CompareValue(PVAL vp)
return (Tval > n) ? 1 : (Tval < n) ? (-1) : 0; return (Tval > n) ? 1 : (Tval < n) ? (-1) : 0;
} // end of CompareValue } // end of CompareValue
#if 0
/***********************************************************************/
/* Return max type value if b is true, else min type value. */
/***********************************************************************/
template <>
short TYPVAL<short>::MinMaxVal(bool b)
{return (b) ? MAXINT16 : MININT16;}
template <>
USHORT TYPVAL<USHORT>::MinMaxVal(bool b)
{return (b) ? MAXUINT16 : 0;}
template <>
int TYPVAL<int>::MinMaxVal(bool b)
{return (b) ? MAXINT32 : MININT32;}
template <>
UINT TYPVAL<UINT>::MinMaxVal(bool b)
{return (b) ? MAXUINT32 : 0;}
template <>
longlong TYPVAL<longlong>::MinMaxVal(bool b)
{return (b) ? MAXINT64 : MININT64;}
template <>
ulonglong TYPVAL<ulonglong>::MinMaxVal(bool b)
{return (b) ? MAXUINT64 : 0;}
template <>
double TYPVAL<double>::MinMaxVal(bool b)
{assert(false); return 0.0;}
template <>
char TYPVAL<char>::MinMaxVal(bool b)
{return (b) ? MAXINT8 : MININT8;}
template <>
UCHAR TYPVAL<UCHAR>::MinMaxVal(bool b)
{return (b) ? MAXUINT8 : 0;}
/***********************************************************************/
/* SafeAdd: adds a value and test whether overflow/underflow occured. */
/***********************************************************************/
template <class TYPE>
TYPE TYPVAL<TYPE>::SafeAdd(TYPE n1, TYPE n2)
{
PGLOBAL& g = Global;
TYPE n = n1 + n2;
if ((n2 > 0) && (n < n1)) {
// Overflow
strcpy(g->Message, MSG(FIX_OVFLW_ADD));
longjmp(g->jumper[g->jump_level], 138);
} else if ((n2 < 0) && (n > n1)) {
// Underflow
strcpy(g->Message, MSG(FIX_UNFLW_ADD));
longjmp(g->jumper[g->jump_level], 138);
} // endif's n2
return n;
} // end of SafeAdd
template <>
inline double TYPVAL<double>::SafeAdd(double n1, double n2)
{
assert(false); return 0;
} // end of SafeAdd
/***********************************************************************/
/* SafeMult: multiply values and test whether overflow occured. */
/***********************************************************************/
template <class TYPE>
TYPE TYPVAL<TYPE>::SafeMult(TYPE n1, TYPE n2)
{
PGLOBAL& g = Global;
double n = (double)n1 * (double)n2;
if (n > MinMaxVal(true)) {
// Overflow
strcpy(g->Message, MSG(FIX_OVFLW_TIMES));
longjmp(g->jumper[g->jump_level], 138);
} else if (n < MinMaxVal(false)) {
// Underflow
strcpy(g->Message, MSG(FIX_UNFLW_TIMES));
longjmp(g->jumper[g->jump_level], 138);
} // endif's n2
return (TYPE)n;
} // end of SafeMult
template <>
inline double TYPVAL<double>::SafeMult(double n1, double n2)
{
assert(false); return 0;
} // end of SafeMult
#endif // 0
/***********************************************************************/
/* Compute defined functions for the type. */
/***********************************************************************/
template <class TYPE>
bool TYPVAL<TYPE>::Compute(PGLOBAL g, PVAL *vp, int np, OPVAL op)
{
bool rc = false;
TYPE val[2];
assert(np == 2);
for (int i = 0; i < np; i++)
val[i] = GetTypedValue(vp[i]);
switch (op) {
case OP_ADD:
// Tval = SafeAdd(val[0], val[1]);
Tval = val[0] + val[1];
break;
case OP_MULT:
// Tval = SafeMult(val[0], val[1]);
Tval = val[0] * val[1];
break;
default:
rc = Compall(g, vp, np, op);
break;
} // endswitch op
return rc;
} // end of Compute
#if 0
template <>
bool TYPVAL<double>::Compute(PGLOBAL g, PVAL *vp, int np, OPVAL op)
{
bool rc = false;
double val[2];
assert(np == 2);
for (int i = 0; i < np; i++)
val[i] = vp[i]->GetFloatValue();
switch (op) {
case OP_ADD:
Tval = val[0] + val[1];
break;
case OP_MULT:
Tval = val[0] * val[1];
break;
default:
rc = Compall(g, vp, np, op);
} // endswitch op
return rc;
} // end of Compute
#endif // 0
/***********************************************************************/
/* Compute a function for all types. */
/***********************************************************************/
template <class TYPE>
bool TYPVAL<TYPE>::Compall(PGLOBAL g, PVAL *vp, int np, OPVAL op)
{
TYPE val[2];
for (int i = 0; i < np; i++)
val[i] = GetTypedValue(vp[i]);
switch (op) {
case OP_MIN:
Tval = MY_MIN(val[0], val[1]);
break;
case OP_MAX:
Tval = MY_MAX(val[0], val[1]);
break;
default:
// sprintf(g->Message, MSG(BAD_EXP_OPER), op);
strcpy(g->Message, "Function not supported");
return true;
} // endswitch op
return false;
} // end of Compall
/***********************************************************************/ /***********************************************************************/
/* FormatValue: This function set vp (a STRING value) to the string */ /* FormatValue: This function set vp (a STRING value) to the string */
/* constructed from its own value formated using the fmt format. */ /* constructed from its own value formated using the fmt format. */
...@@ -1409,6 +1600,45 @@ int TYPVAL<PSZ>::CompareValue(PVAL vp) ...@@ -1409,6 +1600,45 @@ int TYPVAL<PSZ>::CompareValue(PVAL vp)
return (n > 0) ? 1 : (n < 0) ? -1 : 0; return (n > 0) ? 1 : (n < 0) ? -1 : 0;
} // end of CompareValue } // end of CompareValue
/***********************************************************************/
/* Compute a function on a string. */
/***********************************************************************/
bool TYPVAL<PSZ>::Compute(PGLOBAL g, PVAL *vp, int np, OPVAL op)
{
char *p[2], val[2][32];
int i;
for (i = 0; i < np; i++)
p[i] = vp[i]->GetCharString(val[i]);
switch (op) {
case OP_CNC:
assert(np == 1 || np == 2);
if (np == 2)
strncpy(Strp, p[0], Len);
if ((i = Len - (signed)strlen(Strp)) > 0)
strncat(Strp, p[np - 1], i);
break;
case OP_MIN:
assert(np == 2);
strcpy(Strp, (strcmp(p[0], p[1]) < 0) ? p[0] : p[1]);
break;
case OP_MAX:
assert(np == 2);
strcpy(Strp, (strcmp(p[0], p[1]) > 0) ? p[0] : p[1]);
break;
default:
// sprintf(g->Message, MSG(BAD_EXP_OPER), op);
strcpy(g->Message, "Function not supported");
return true;
} // endswitch op
return false;
} // end of Compute
/***********************************************************************/ /***********************************************************************/
/* FormatValue: This function set vp (a STRING value) to the string */ /* FormatValue: This function set vp (a STRING value) to the string */
/* constructed from its own value formated using the fmt format. */ /* constructed from its own value formated using the fmt format. */
......
...@@ -29,12 +29,9 @@ enum CONV {CNV_ANY = 0, /* Convert to any type */ ...@@ -29,12 +29,9 @@ enum CONV {CNV_ANY = 0, /* Convert to any type */
class CONSTANT; // For friend setting class CONSTANT; // For friend setting
typedef struct _datpar *PDTP; // For DTVAL typedef struct _datpar *PDTP; // For DTVAL
/***********************************************************************/ /***********************************************************************/
/* Utilities used to test types and to allocated values. */ /* Utilities used to test types and to allocated values. */
/***********************************************************************/ /***********************************************************************/
PVAL AllocateValue(PGLOBAL, void *, short);
// Exported functions // Exported functions
DllExport PSZ GetTypeName(int); DllExport PSZ GetTypeName(int);
DllExport int GetTypeSize(int, int); DllExport int GetTypeSize(int, int);
...@@ -47,6 +44,7 @@ DllExport int GetFormatType(char); ...@@ -47,6 +44,7 @@ DllExport int GetFormatType(char);
DllExport bool IsTypeChar(int type); DllExport bool IsTypeChar(int type);
DllExport bool IsTypeNum(int type); DllExport bool IsTypeNum(int type);
DllExport int ConvertType(int, int, CONV, bool match = false); DllExport int ConvertType(int, int, CONV, bool match = false);
DllExport PVAL AllocateValue(PGLOBAL, void *, short, short = 2);
DllExport PVAL AllocateValue(PGLOBAL, PVAL, int = TYPE_VOID, int = 0); DllExport PVAL AllocateValue(PGLOBAL, PVAL, int = TYPE_VOID, int = 0);
DllExport PVAL AllocateValue(PGLOBAL, int, int len = 0, int prec = 0, DllExport PVAL AllocateValue(PGLOBAL, int, int len = 0, int prec = 0,
bool uns = false, PSZ fmt = NULL); bool uns = false, PSZ fmt = NULL);
...@@ -114,6 +112,7 @@ class DllExport VALUE : public BLOCK { ...@@ -114,6 +112,7 @@ class DllExport VALUE : public BLOCK {
virtual char *ShowValue(char *buf, int len = 0) = 0; virtual char *ShowValue(char *buf, int len = 0) = 0;
virtual char *GetCharString(char *p) = 0; virtual char *GetCharString(char *p) = 0;
virtual bool IsEqual(PVAL vp, bool chktype) = 0; virtual bool IsEqual(PVAL vp, bool chktype) = 0;
virtual bool Compute(PGLOBAL g, PVAL *vp, int np, OPVAL op);
virtual bool FormatValue(PVAL vp, char *fmt) = 0; virtual bool FormatValue(PVAL vp, char *fmt) = 0;
protected: protected:
...@@ -149,9 +148,9 @@ class DllExport TYPVAL : public VALUE { ...@@ -149,9 +148,9 @@ class DllExport TYPVAL : public VALUE {
virtual bool IsZero(void) {return Tval == 0;} virtual bool IsZero(void) {return Tval == 0;}
virtual void Reset(void) {Tval = 0;} virtual void Reset(void) {Tval = 0;}
virtual int GetValLen(void); virtual int GetValLen(void);
virtual int GetValPrec() {return 0;} virtual int GetValPrec() {return Prec;}
virtual int GetSize(void) {return sizeof(TYPE);} virtual int GetSize(void) {return sizeof(TYPE);}
virtual PSZ GetCharValue(void) {return VALUE::GetCharValue();} //virtual PSZ GetCharValue(void) {return VALUE::GetCharValue();}
virtual char GetTinyValue(void) {return (char)Tval;} virtual char GetTinyValue(void) {return (char)Tval;}
virtual uchar GetUTinyValue(void) {return (uchar)Tval;} virtual uchar GetUTinyValue(void) {return (uchar)Tval;}
virtual short GetShortValue(void) {return (short)Tval;} virtual short GetShortValue(void) {return (short)Tval;}
...@@ -184,12 +183,18 @@ class DllExport TYPVAL : public VALUE { ...@@ -184,12 +183,18 @@ class DllExport TYPVAL : public VALUE {
virtual char *ShowValue(char *buf, int); virtual char *ShowValue(char *buf, int);
virtual char *GetCharString(char *p); virtual char *GetCharString(char *p);
virtual bool IsEqual(PVAL vp, bool chktype); virtual bool IsEqual(PVAL vp, bool chktype);
virtual bool Compute(PGLOBAL g, PVAL *vp, int np, OPVAL op);
virtual bool SetConstFormat(PGLOBAL, FORMAT&); virtual bool SetConstFormat(PGLOBAL, FORMAT&);
virtual bool FormatValue(PVAL vp, char *fmt); virtual bool FormatValue(PVAL vp, char *fmt);
virtual void Print(PGLOBAL g, FILE *, uint); virtual void Print(PGLOBAL g, FILE *, uint);
virtual void Print(PGLOBAL g, char *, uint); virtual void Print(PGLOBAL g, char *, uint);
protected: protected:
//static TYPE MinMaxVal(bool b);
// TYPE SafeAdd(TYPE n1, TYPE n2);
// TYPE SafeMult(TYPE n1, TYPE n2);
bool Compall(PGLOBAL g, PVAL *vp, int np, OPVAL op);
// Default constructor not to be used // Default constructor not to be used
TYPVAL(void) : VALUE(TYPE_ERROR) {} TYPVAL(void) : VALUE(TYPE_ERROR) {}
...@@ -253,6 +258,7 @@ class DllExport TYPVAL<PSZ>: public VALUE { ...@@ -253,6 +258,7 @@ class DllExport TYPVAL<PSZ>: public VALUE {
virtual char *ShowValue(char *buf, int); virtual char *ShowValue(char *buf, int);
virtual char *GetCharString(char *p); virtual char *GetCharString(char *p);
virtual bool IsEqual(PVAL vp, bool chktype); virtual bool IsEqual(PVAL vp, bool chktype);
virtual bool Compute(PGLOBAL g, PVAL *vp, int np, OPVAL op);
virtual bool FormatValue(PVAL vp, char *fmt); virtual bool FormatValue(PVAL vp, char *fmt);
virtual bool SetConstFormat(PGLOBAL, FORMAT&); virtual bool SetConstFormat(PGLOBAL, FORMAT&);
......
...@@ -209,6 +209,7 @@ class DllExport TDBASE : public TDB { ...@@ -209,6 +209,7 @@ class DllExport TDBASE : public TDB {
int Knum; // Size of key arrays int Knum; // Size of key arrays
bool Read_Only; // True for read only tables bool Read_Only; // True for read only tables
const CHARSET_INFO *m_data_charset; const CHARSET_INFO *m_data_charset;
const char *csname; // Table charset name
}; // end of class TDBASE }; // end of class TDBASE
/***********************************************************************/ /***********************************************************************/
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment