mirror of
https://github.com/MariaDB/server.git
synced 2025-08-08 11:22:35 +03:00
- 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
This commit is contained in:
@@ -52,7 +52,7 @@
|
||||
/* Routines called internally by semantic routines. */
|
||||
/***********************************************************************/
|
||||
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. */
|
||||
@@ -388,7 +388,7 @@ bool CntRewindTable(PGLOBAL g, PTDB tdbp)
|
||||
/***********************************************************************/
|
||||
/* 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;
|
||||
PCOL colp;
|
||||
@@ -413,6 +413,7 @@ RCODE EvalColumns(PGLOBAL g, PTDB tdbp, bool mrr)
|
||||
|
||||
for (colp= tdbp->GetColumns(); rc == RC_OK && colp;
|
||||
colp= colp->GetNext()) {
|
||||
if (reset)
|
||||
colp->Reset();
|
||||
|
||||
// Virtual columns are computed by MariaDB
|
||||
@@ -457,6 +458,10 @@ RCODE CntReadNext(PGLOBAL g, PTDB tdbp)
|
||||
goto err;
|
||||
} // endif rc
|
||||
|
||||
// Do it now to avoid double eval when filtering
|
||||
for (PCOL colp= tdbp->GetColumns(); colp; colp= colp->GetNext())
|
||||
colp->Reset();
|
||||
|
||||
do {
|
||||
if ((rc= (RCODE)tdbp->ReadDB(g)) == RC_OK)
|
||||
if (!ApplyFilter(g, tdbp->GetFilter()))
|
||||
@@ -466,7 +471,7 @@ RCODE CntReadNext(PGLOBAL g, PTDB tdbp)
|
||||
|
||||
err:
|
||||
g->jump_level--;
|
||||
return (rc != RC_OK) ? rc : EvalColumns(g, tdbp);
|
||||
return (rc != RC_OK) ? rc : EvalColumns(g, tdbp, false);
|
||||
} // end of CntReadNext
|
||||
|
||||
/***********************************************************************/
|
||||
@@ -812,7 +817,7 @@ RCODE CntIndexRead(PGLOBAL g, PTDB ptdb, OPVAL op,
|
||||
|
||||
rnd:
|
||||
if ((rc= (RCODE)ptdb->ReadDB(g)) == RC_OK)
|
||||
rc= EvalColumns(g, ptdb, mrr);
|
||||
rc= EvalColumns(g, ptdb, true, mrr);
|
||||
|
||||
return rc;
|
||||
} // end of CntIndexRead
|
||||
|
@@ -1055,6 +1055,14 @@ char *ha_connect::GetStringOption(char *opname, char *sdef)
|
||||
opval= (char*)options->colist;
|
||||
else if (!stricmp(opname, "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)
|
||||
opval= GetListOption(xp->g, opname, options->oplist);
|
||||
@@ -3806,6 +3814,7 @@ bool ha_connect::check_privileges(THD *thd, PTOS options, char *dbn)
|
||||
case TAB_XML:
|
||||
case TAB_INI:
|
||||
case TAB_VEC:
|
||||
// case TAB_JSON:
|
||||
if (options->filename && *options->filename) {
|
||||
char *s, path[FN_REFLEN], dbpath[FN_REFLEN];
|
||||
#if defined(WIN32)
|
||||
|
@@ -11,8 +11,8 @@ typedef struct {
|
||||
DWORD lenH;
|
||||
} MEMMAP;
|
||||
|
||||
HANDLE CreateFileMap(PGLOBAL, LPCSTR, MEMMAP *, MODE, bool);
|
||||
bool CloseMemMap(void *memory, size_t dwSize);
|
||||
DllExport HANDLE CreateFileMap(PGLOBAL, LPCSTR, MEMMAP *, MODE, bool);
|
||||
DllExport bool CloseMemMap(void *memory, size_t dwSize);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@@ -1,4 +1,4 @@
|
||||
/* Copyright (C) Olivier Bertrand 2004 - 2013
|
||||
/* Copyright (C) Olivier Bertrand 2004 - 2014
|
||||
|
||||
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
|
||||
@@ -18,7 +18,7 @@
|
||||
/* ------------- */
|
||||
/* Version 1.4 */
|
||||
/* */
|
||||
/* Author: Olivier Bertrand 2012 - 2013 */
|
||||
/* Author: Olivier Bertrand 2012 - 2014 */
|
||||
/* */
|
||||
/* WHAT THIS PROGRAM DOES: */
|
||||
/* ----------------------- */
|
||||
@@ -89,6 +89,7 @@
|
||||
#include "tabpivot.h"
|
||||
#endif // PIVOT_SUPPORT
|
||||
#include "tabvir.h"
|
||||
//#include "tabjson.h"
|
||||
#include "ha_connect.h"
|
||||
#include "mycat.h"
|
||||
|
||||
@@ -139,6 +140,7 @@ TABTYPE GetTypeID(const char *type)
|
||||
: (!stricmp(type, "PIVOT")) ? TAB_PIVOT
|
||||
#endif
|
||||
: (!stricmp(type, "VIR")) ? TAB_VIR
|
||||
// : (!stricmp(type, "JSON")) ? TAB_JSON
|
||||
: (!stricmp(type, "OEM")) ? TAB_OEM : TAB_NIY;
|
||||
} // end of GetTypeID
|
||||
|
||||
@@ -159,6 +161,7 @@ bool IsFileType(TABTYPE type)
|
||||
case TAB_XML:
|
||||
case TAB_INI:
|
||||
case TAB_VEC:
|
||||
// case TAB_JSON:
|
||||
isfile= true;
|
||||
break;
|
||||
default:
|
||||
@@ -181,6 +184,7 @@ bool IsExactType(TABTYPE type)
|
||||
case TAB_BIN:
|
||||
case TAB_DBF:
|
||||
// case TAB_XML: depends on Multiple || Xpand || Coltype
|
||||
// case TAB_JSON: depends on Multiple || Xpand || Coltype
|
||||
case TAB_VEC:
|
||||
case TAB_VIR:
|
||||
exact= true;
|
||||
@@ -214,7 +218,7 @@ bool IsTypeNullable(TABTYPE type)
|
||||
} // end of IsTypeNullable
|
||||
|
||||
/***********************************************************************/
|
||||
/* Return true for indexable table by XINDEX. */
|
||||
/* Return true for fixed record length tables. */
|
||||
/***********************************************************************/
|
||||
bool IsTypeFixed(TABTYPE type)
|
||||
{
|
||||
@@ -538,6 +542,7 @@ PRELDEF MYCAT::MakeTableDesc(PGLOBAL g, LPCSTR name, LPCSTR am)
|
||||
case TAB_PIVOT: tdp= new(g) PIVOTDEF; break;
|
||||
#endif // PIVOT_SUPPORT
|
||||
case TAB_VIR: tdp= new(g) VIRDEF; break;
|
||||
// case TAB_JSON: tdp= new(g) JSONDEF; break;
|
||||
default:
|
||||
sprintf(g->Message, MSG(BAD_TABLE_TYPE), am, name);
|
||||
} // endswitch
|
||||
|
@@ -430,10 +430,11 @@ int MYSQLC::GetResultSize(PGLOBAL g, PSZ sql)
|
||||
/***********************************************************************/
|
||||
int MYSQLC::Open(PGLOBAL g, const char *host, const char *db,
|
||||
const char *user, const char *pwd,
|
||||
int pt)
|
||||
int pt, const char *csname)
|
||||
{
|
||||
const char *pipe = NULL;
|
||||
uint cto = 6000, nrt = 12000;
|
||||
my_bool my_true= 1;
|
||||
|
||||
m_DB = mysql_init(NULL);
|
||||
|
||||
@@ -470,6 +471,18 @@ int MYSQLC::Open(PGLOBAL g, const char *host, const char *db,
|
||||
} // endif pwd
|
||||
#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 defined(_DEBUG)
|
||||
sprintf(g->Message, "mysql_real_connect failed: (%d) %s",
|
||||
|
@@ -67,7 +67,7 @@ class DllItem MYSQLC {
|
||||
int GetTableSize(PGLOBAL g, PSZ query);
|
||||
int Open(PGLOBAL g, const char *host, const char *db,
|
||||
const char *user= "root", const char *pwd= "*",
|
||||
int pt= 0);
|
||||
int pt= 0, const char *csname = NULL);
|
||||
int KillQuery(ulong id);
|
||||
int ExecSQL(PGLOBAL g, const char *query, int *w = NULL);
|
||||
int ExecSQLcmd(PGLOBAL g, const char *query, int *w);
|
||||
@@ -98,5 +98,6 @@ class DllItem MYSQLC {
|
||||
int m_Fields; // The number of result fields
|
||||
int m_Afrw; // The number of affected rows
|
||||
bool m_Use; // Use or store result set
|
||||
const char *csname; // Table charset name
|
||||
}; // end of class MYSQLC
|
||||
|
||||
|
@@ -74,9 +74,11 @@ enum TABTYPE {TAB_UNDEF = 0, /* Table of undefined type */
|
||||
TAB_PLG = 20, /* PLG NIY */
|
||||
TAB_PIVOT = 21, /* PIVOT table */
|
||||
TAB_VIR = 22, /* Virtual tables */
|
||||
TAB_JCT = 23, /* Junction tables NIY */
|
||||
TAB_DMY = 24, /* DMY Dummy tables NIY */
|
||||
TAB_NIY = 25}; /* Table not implemented yet */
|
||||
TAB_JSON = 23, /* JSON tables */
|
||||
TAB_JSN = 24, /* Semi-json tables */
|
||||
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 */
|
||||
TYPE_AM_ROWID = 1, /* ROWID type (special column) */
|
||||
|
@@ -202,6 +202,8 @@ TABDEF::TABDEF(void)
|
||||
Degree = 0;
|
||||
Pseudo = 0;
|
||||
Read_Only = false;
|
||||
m_data_charset = NULL;
|
||||
csname = NULL;
|
||||
} // end of TABDEF constructor
|
||||
|
||||
/***********************************************************************/
|
||||
@@ -224,6 +226,7 @@ bool TABDEF::Define(PGLOBAL g, PCATLG cat, LPCSTR name, LPCSTR am)
|
||||
m_data_charset= data_charset_name ?
|
||||
get_charset_by_csname(data_charset_name, MY_CS_PRIMARY, 0):
|
||||
NULL;
|
||||
csname = GetStringCatInfo(g, "Table_charset", NULL);
|
||||
|
||||
// Get The column definitions
|
||||
if ((poff = GetColCatInfo(g)) < 0)
|
||||
|
@@ -68,6 +68,7 @@ class DllExport TABDEF : public RELDEF { /* Logical table descriptor */
|
||||
friend class CATALOG;
|
||||
friend class PLUGCAT;
|
||||
friend class MYCAT;
|
||||
friend class TDBASE;
|
||||
public:
|
||||
// Constructor
|
||||
TABDEF(void); // Constructor
|
||||
@@ -110,6 +111,7 @@ class DllExport TABDEF : public RELDEF { /* Logical table descriptor */
|
||||
int Pseudo; /* Bit: 1 ROWID Ok, 2 FILEID Ok */
|
||||
bool Read_Only; /* true for read only tables */
|
||||
const CHARSET_INFO *m_data_charset;
|
||||
const char *csname; /* Table charset name */
|
||||
}; // end of TABDEF
|
||||
|
||||
/***********************************************************************/
|
||||
|
@@ -146,6 +146,7 @@ TDBASE::TDBASE(PTABDEF tdp) : TDB(tdp)
|
||||
Knum = 0;
|
||||
Read_Only = (tdp) ? tdp->IsReadOnly() : false;
|
||||
m_data_charset= (tdp) ? tdp->data_charset() : NULL;
|
||||
csname = (tdp) ? tdp->csname : NULL;
|
||||
} // end of TDBASE constructor
|
||||
|
||||
TDBASE::TDBASE(PTDBASE tdbp) : TDB(tdbp)
|
||||
@@ -161,6 +162,7 @@ TDBASE::TDBASE(PTDBASE tdbp) : TDB(tdbp)
|
||||
Knum = tdbp->Knum;
|
||||
Read_Only = tdbp->Read_Only;
|
||||
m_data_charset= tdbp->m_data_charset;
|
||||
csname = tdbp->csname;
|
||||
} // end of TDBASE copy constructor
|
||||
|
||||
/***********************************************************************/
|
||||
|
@@ -777,7 +777,7 @@ int TDBMYSQL::Cardinality(PGLOBAL g)
|
||||
char query[96];
|
||||
MYSQLC myc;
|
||||
|
||||
if (myc.Open(g, Host, Database, User, Pwd, Port))
|
||||
if (myc.Open(g, Host, Database, User, Pwd, Port, csname))
|
||||
return -1;
|
||||
|
||||
strcpy(query, "SELECT COUNT(*) FROM ");
|
||||
@@ -871,7 +871,7 @@ bool TDBMYSQL::OpenDB(PGLOBAL g)
|
||||
/* servers allowing concurency in getting results ??? */
|
||||
/*********************************************************************/
|
||||
if (!Myc.Connected()) {
|
||||
if (Myc.Open(g, Host, Database, User, Pwd, Port))
|
||||
if (Myc.Open(g, Host, Database, User, Pwd, Port, csname))
|
||||
return true;
|
||||
|
||||
} // endif Connected
|
||||
|
@@ -330,7 +330,7 @@ int ConvertType(int target, int type, CONV kind, bool match)
|
||||
/***********************************************************************/
|
||||
/* 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;
|
||||
|
||||
@@ -351,7 +351,7 @@ PVAL AllocateValue(PGLOBAL g, void *value, short type)
|
||||
valp = new(g) TYPVAL<longlong>(*(longlong*)value, TYPE_BIGINT);
|
||||
break;
|
||||
case TYPE_DOUBLE:
|
||||
valp = new(g) TYPVAL<double>(*(double *)value, TYPE_DOUBLE, 2);
|
||||
valp = new(g) TYPVAL<double>(*(double *)value, TYPE_DOUBLE, prec);
|
||||
break;
|
||||
case 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)
|
||||
break;
|
||||
case TYPE_DOUBLE:
|
||||
valp = new(g) TYPVAL<double>(valp->GetFloatValue(), TYPE_DOUBLE,
|
||||
valp->GetValPrec());
|
||||
(uns) ? uns : valp->GetValPrec());
|
||||
break;
|
||||
case TYPE_TINY:
|
||||
if (un)
|
||||
@@ -542,6 +542,15 @@ BYTE VALUE::TestValue(PVAL vp)
|
||||
return (n > 0) ? 0x04 : (n < 0) ? 0x02 : 0x01;
|
||||
} // 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 ---------------------------- */
|
||||
|
||||
/***********************************************************************/
|
||||
@@ -930,6 +939,188 @@ int TYPVAL<TYPE>::CompareValue(PVAL vp)
|
||||
return (Tval > n) ? 1 : (Tval < n) ? (-1) : 0;
|
||||
} // 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 */
|
||||
/* constructed from its own value formated using the fmt format. */
|
||||
@@ -1409,6 +1600,45 @@ int TYPVAL<PSZ>::CompareValue(PVAL vp)
|
||||
return (n > 0) ? 1 : (n < 0) ? -1 : 0;
|
||||
} // 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 */
|
||||
/* constructed from its own value formated using the fmt format. */
|
||||
|
@@ -29,12 +29,9 @@ enum CONV {CNV_ANY = 0, /* Convert to any type */
|
||||
class CONSTANT; // For friend setting
|
||||
typedef struct _datpar *PDTP; // For DTVAL
|
||||
|
||||
|
||||
/***********************************************************************/
|
||||
/* Utilities used to test types and to allocated values. */
|
||||
/***********************************************************************/
|
||||
PVAL AllocateValue(PGLOBAL, void *, short);
|
||||
|
||||
// Exported functions
|
||||
DllExport PSZ GetTypeName(int);
|
||||
DllExport int GetTypeSize(int, int);
|
||||
@@ -47,6 +44,7 @@ DllExport int GetFormatType(char);
|
||||
DllExport bool IsTypeChar(int type);
|
||||
DllExport bool IsTypeNum(int type);
|
||||
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, int, int len = 0, int prec = 0,
|
||||
bool uns = false, PSZ fmt = NULL);
|
||||
@@ -114,6 +112,7 @@ class DllExport VALUE : public BLOCK {
|
||||
virtual char *ShowValue(char *buf, int len = 0) = 0;
|
||||
virtual char *GetCharString(char *p) = 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;
|
||||
|
||||
protected:
|
||||
@@ -149,9 +148,9 @@ class DllExport TYPVAL : public VALUE {
|
||||
virtual bool IsZero(void) {return Tval == 0;}
|
||||
virtual void Reset(void) {Tval = 0;}
|
||||
virtual int GetValLen(void);
|
||||
virtual int GetValPrec() {return 0;}
|
||||
virtual int GetValPrec() {return Prec;}
|
||||
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 uchar GetUTinyValue(void) {return (uchar)Tval;}
|
||||
virtual short GetShortValue(void) {return (short)Tval;}
|
||||
@@ -184,12 +183,18 @@ class DllExport TYPVAL : public VALUE {
|
||||
virtual char *ShowValue(char *buf, int);
|
||||
virtual char *GetCharString(char *p);
|
||||
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 FormatValue(PVAL vp, char *fmt);
|
||||
virtual void Print(PGLOBAL g, FILE *, uint);
|
||||
virtual void Print(PGLOBAL g, char *, uint);
|
||||
|
||||
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
|
||||
TYPVAL(void) : VALUE(TYPE_ERROR) {}
|
||||
|
||||
@@ -253,6 +258,7 @@ class DllExport TYPVAL<PSZ>: public VALUE {
|
||||
virtual char *ShowValue(char *buf, int);
|
||||
virtual char *GetCharString(char *p);
|
||||
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 SetConstFormat(PGLOBAL, FORMAT&);
|
||||
|
||||
|
@@ -209,6 +209,7 @@ class DllExport TDBASE : public TDB {
|
||||
int Knum; // Size of key arrays
|
||||
bool Read_Only; // True for read only tables
|
||||
const CHARSET_INFO *m_data_charset;
|
||||
const char *csname; // Table charset name
|
||||
}; // end of class TDBASE
|
||||
|
||||
/***********************************************************************/
|
||||
|
Reference in New Issue
Block a user