mirror of
https://github.com/MariaDB/server.git
synced 2025-08-08 11:22:35 +03:00
- Commit merged files
modified: storage/connect/CMakeLists.txt storage/connect/connect.h storage/connect/global.h storage/connect/ha_connect.cc storage/connect/ha_connect.h storage/connect/myconn.cpp storage/connect/myconn.h storage/connect/mysql-test/connect/r/pivot.result storage/connect/mysql-test/connect/suite.pm storage/connect/mysql-test/connect/t/pivot.test storage/connect/myutil.cpp storage/connect/osutil.c storage/connect/plgdbsem.h storage/connect/plugutil.c storage/connect/tabmysql.cpp storage/connect/tabpivot.cpp storage/connect/tabutil.cpp storage/connect/user_connect.cc storage/connect/valblk.cpp storage/connect/valblk.h storage/connect/value.cpp storage/connect/value.h storage/connect/xindex.cpp storage/connect/xindex.h
This commit is contained in:
@@ -264,6 +264,17 @@ int main() {
|
||||
ENDIF(UNIX)
|
||||
ENDIF(CONNECT_WITH_ODBC)
|
||||
|
||||
|
||||
#
|
||||
# XMAP
|
||||
#
|
||||
|
||||
OPTION(CONNECT_WITH_XMAP "Compile CONNECT storage engine with index file mapping support" ON)
|
||||
|
||||
IF(CONNECT_WITH_XMAP)
|
||||
add_definitions(-DXMAP)
|
||||
ENDIF(CONNECT_WITH_XMAP)
|
||||
|
||||
#
|
||||
# Plugin definition
|
||||
#
|
||||
@@ -271,6 +282,7 @@ ENDIF(CONNECT_WITH_ODBC)
|
||||
MYSQL_ADD_PLUGIN(connect ${CONNECT_SOURCES}
|
||||
STORAGE_ENGINE
|
||||
COMPONENT connect-engine
|
||||
RECOMPILE_FOR_EMBEDDED
|
||||
LINK_LIBRARIES ${ZLIB_LIBRARY} ${XML_LIBRARY} ${ICONV_LIBRARY}
|
||||
${ODBC_LIBRARY} ${IPHLPAPI_LIBRARY})
|
||||
|
||||
|
@@ -36,8 +36,7 @@ bool CntRewindTable(PGLOBAL g, PTDB tdbp);
|
||||
int CntCloseTable(PGLOBAL g, PTDB tdbp);
|
||||
int CntIndexInit(PGLOBAL g, PTDB tdbp, int id);
|
||||
RCODE CntReadNext(PGLOBAL g, PTDB tdbp);
|
||||
RCODE CntIndexRead(PGLOBAL g, PTDB, OPVAL op, const void *k, int n,
|
||||
bool mrr = false);
|
||||
RCODE CntIndexRead(PGLOBAL g, PTDB, OPVAL op, const void *k, int n, bool mrr);
|
||||
RCODE CntWriteRow(PGLOBAL g, PTDB tdbp);
|
||||
RCODE CntUpdateRow(PGLOBAL g, PTDB tdbp);
|
||||
RCODE CntDeleteRow(PGLOBAL g, PTDB tdbp, bool all);
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/***********************************************************************/
|
||||
/* GLOBAL.H: Declaration file used by all CONNECT implementations. */
|
||||
/* (C) Copyright Olivier Bertrand 1993-2012 */
|
||||
/* (C) Copyright Olivier Bertrand 1993-2014 */
|
||||
/***********************************************************************/
|
||||
|
||||
/***********************************************************************/
|
||||
@@ -84,6 +84,7 @@
|
||||
#define TYPE_LIST 6
|
||||
#define TYPE_INT 7
|
||||
#define TYPE_DECIM 9
|
||||
#define TYPE_BIN 10
|
||||
|
||||
#if defined(OS32)
|
||||
#define SYS_STAMP "OS32"
|
||||
|
@@ -20,6 +20,7 @@
|
||||
The ha_connect engine is a stubbed storage engine that enables to create tables
|
||||
based on external data. Principally they are based on plain files of many
|
||||
different types, but also on collections of such files, collection of tables,
|
||||
local or remote MySQL/MariaDB tables retrieved via MySQL API,
|
||||
ODBC tables retrieving data from other DBMS having an ODBC server, and even
|
||||
virtual tables.
|
||||
|
||||
@@ -53,14 +54,21 @@
|
||||
|
||||
@note
|
||||
It was written also from the Brian's ha_example handler and contains parts
|
||||
of it that are there but not currently used, such as table variables.
|
||||
of it that are there, such as table and system variables.
|
||||
|
||||
@note
|
||||
When you create an CONNECT table, the MySQL Server creates a table .frm
|
||||
(format) file in the database directory, using the table name as the file
|
||||
name as is customary with MySQL. No other files are created. To get an idea
|
||||
of what occurs, here is an example select that would do a scan of an entire
|
||||
table:
|
||||
name as is customary with MySQL.
|
||||
For file based tables, if a file name is not specified, this is an inward
|
||||
table. An empty file is made in the current data directory that you can
|
||||
populate later like for other engine tables. This file modified on ALTER
|
||||
and is deleted when dropping the table.
|
||||
If a file name is specified, this in an outward table. The specified file
|
||||
will be used as representing the table data and will not be modified or
|
||||
deleted on command such as ALTER or DROP.
|
||||
To get an idea of what occurs, here is an example select that would do
|
||||
a scan of an entire table:
|
||||
|
||||
@code
|
||||
ha-connect::open
|
||||
@@ -157,7 +165,10 @@
|
||||
/***********************************************************************/
|
||||
/* Initialize the ha_connect static members. */
|
||||
/***********************************************************************/
|
||||
//efine CONNECT_INI "connect.ini"
|
||||
#define SZCONV 8192
|
||||
#define SZWORK 67108864 // Default work area size 64M
|
||||
#define SZWMIN 4194304 // Minimum work area size 4M
|
||||
|
||||
extern "C" {
|
||||
char version[]= "Version 1.02.0002 March 16, 2014";
|
||||
|
||||
@@ -165,17 +176,32 @@ extern "C" {
|
||||
char msglang[]; // Default message language
|
||||
#endif
|
||||
int trace= 0; // The general trace value
|
||||
int xconv= 0; // The type conversion option
|
||||
int zconv= SZCONV; // The text conversion size
|
||||
} // extern "C"
|
||||
|
||||
static int xtrace= 0;
|
||||
#if defined(XMAP)
|
||||
bool xmap= false;
|
||||
#endif // XMAP
|
||||
|
||||
uint worksize= SZWORK;
|
||||
ulong ha_connect::num= 0;
|
||||
//int DTVAL::Shift= 0;
|
||||
|
||||
/* CONNECT system variables */
|
||||
static int xtrace= 0;
|
||||
static int conv_size= SZCONV;
|
||||
static uint work_size= SZWORK;
|
||||
static ulong type_conv= 0;
|
||||
#if defined(XMAP)
|
||||
static my_bool indx_map= 0;
|
||||
#endif // XMAP
|
||||
|
||||
/***********************************************************************/
|
||||
/* Utility functions. */
|
||||
/***********************************************************************/
|
||||
PQRYRES OEMColumns(PGLOBAL g, PTOS topt, char *tab, char *db, bool info);
|
||||
void PushWarning(PGLOBAL g, THD *thd, int level);
|
||||
|
||||
static PCONNECT GetUser(THD *thd, PCONNECT xp);
|
||||
static PGLOBAL GetPlug(THD *thd, PCONNECT& lxp);
|
||||
@@ -192,10 +218,42 @@ static void update_connect_xtrace(MYSQL_THD thd,
|
||||
struct st_mysql_sys_var *var,
|
||||
void *var_ptr, const void *save)
|
||||
{
|
||||
xtrace= *(int *)save;
|
||||
//xtrace= *(int *)var_ptr= *(int *)save;
|
||||
xtrace= *(int *)var_ptr= *(int *)save;
|
||||
} // end of update_connect_xtrace
|
||||
|
||||
static void update_connect_zconv(MYSQL_THD thd,
|
||||
struct st_mysql_sys_var *var,
|
||||
void *var_ptr, const void *save)
|
||||
{
|
||||
zconv= *(int *)var_ptr= *(int *)save;
|
||||
} // end of update_connect_zconv
|
||||
|
||||
static void update_connect_xconv(MYSQL_THD thd,
|
||||
struct st_mysql_sys_var *var,
|
||||
void *var_ptr, const void *save)
|
||||
{
|
||||
xconv= (int)(*(ulong *)var_ptr= *(ulong *)save);
|
||||
} // end of update_connect_xconv
|
||||
|
||||
static void update_connect_worksize(MYSQL_THD thd,
|
||||
struct st_mysql_sys_var *var,
|
||||
void *var_ptr, const void *save)
|
||||
{
|
||||
worksize= (uint)(*(ulong *)var_ptr= *(ulong *)save);
|
||||
} // end of update_connect_worksize
|
||||
|
||||
#if defined(XMAP)
|
||||
static void update_connect_xmap(MYSQL_THD thd,
|
||||
struct st_mysql_sys_var *var,
|
||||
void *var_ptr, const void *save)
|
||||
{
|
||||
xmap= (bool)(*(my_bool *)var_ptr= *(my_bool *)save);
|
||||
} // end of update_connect_xmap
|
||||
#endif // XMAP
|
||||
|
||||
/***********************************************************************/
|
||||
/* The CONNECT handlerton object. */
|
||||
/***********************************************************************/
|
||||
handlerton *connect_hton;
|
||||
|
||||
/**
|
||||
@@ -274,21 +332,29 @@ ha_create_table_option connect_index_option_list[]=
|
||||
/* Push G->Message as a MySQL warning. */
|
||||
/***********************************************************************/
|
||||
bool PushWarning(PGLOBAL g, PTDBASE tdbp, int level)
|
||||
{
|
||||
{
|
||||
PHC phc;
|
||||
THD *thd;
|
||||
MYCAT *cat= (MYCAT*)tdbp->GetDef()->GetCat();
|
||||
Sql_condition::enum_warning_level wlvl;
|
||||
|
||||
|
||||
if (!cat || !(phc= cat->GetHandler()) || !phc->GetTable() ||
|
||||
!(thd= (phc->GetTable())->in_use))
|
||||
return true;
|
||||
|
||||
//push_warning(thd, Sql_condition::WARN_LEVEL_WARN, 0, g->Message);
|
||||
PushWarning(g, thd, level);
|
||||
return false;
|
||||
} // end of PushWarning
|
||||
|
||||
void PushWarning(PGLOBAL g, THD *thd, int level)
|
||||
{
|
||||
if (thd) {
|
||||
Sql_condition::enum_warning_level wlvl;
|
||||
|
||||
wlvl= (Sql_condition::enum_warning_level)level;
|
||||
push_warning(thd, wlvl, 0, g->Message);
|
||||
return false;
|
||||
} else
|
||||
htrc("%s\n", g->Message);
|
||||
|
||||
} // end of PushWarning
|
||||
|
||||
#ifdef HAVE_PSI_INTERFACE
|
||||
@@ -883,6 +949,7 @@ PFOS ha_connect::GetFieldOptionStruct(Field *fdp)
|
||||
void *ha_connect::GetColumnOption(PGLOBAL g, void *field, PCOLINFO pcf)
|
||||
{
|
||||
const char *cp;
|
||||
char *chset, v;
|
||||
ha_field_option_struct *fop;
|
||||
Field* fp;
|
||||
Field* *fldp;
|
||||
@@ -934,6 +1001,9 @@ void *ha_connect::GetColumnOption(PGLOBAL g, void *field, PCOLINFO pcf)
|
||||
pcf->Fieldfmt= NULL;
|
||||
} // endif fop
|
||||
|
||||
chset = (char *)fp->charset()->name;
|
||||
v = (!strcmp(chset, "binary")) ? 'B' : 0;
|
||||
|
||||
switch (fp->type()) {
|
||||
case MYSQL_TYPE_BLOB:
|
||||
case MYSQL_TYPE_VARCHAR:
|
||||
@@ -941,7 +1011,7 @@ void *ha_connect::GetColumnOption(PGLOBAL g, void *field, PCOLINFO pcf)
|
||||
pcf->Flags |= U_VAR;
|
||||
/* no break */
|
||||
default:
|
||||
pcf->Type= MYSQLtoPLG(fp->type());
|
||||
pcf->Type= MYSQLtoPLG(fp->type(), &v);
|
||||
break;
|
||||
} // endswitch SQL type
|
||||
|
||||
@@ -2146,13 +2216,17 @@ bool ha_connect::get_error_message(int error, String* buf)
|
||||
|
||||
if (xp && xp->g) {
|
||||
PGLOBAL g= xp->g;
|
||||
char *msg= (char*)PlugSubAlloc(g, NULL, strlen(g->Message) * 3);
|
||||
char msg[3072]; // MAX_STR * 3
|
||||
uint dummy_errors;
|
||||
uint32 len= copy_and_convert(msg, strlen(g->Message) * 3,
|
||||
system_charset_info,
|
||||
g->Message, strlen(g->Message),
|
||||
&my_charset_latin1,
|
||||
&dummy_errors);
|
||||
|
||||
if (trace)
|
||||
htrc("GEM(%u): %s\n", len, g->Message);
|
||||
|
||||
msg[len]= '\0';
|
||||
buf->copy(msg, (uint)strlen(msg), system_charset_info);
|
||||
} else
|
||||
@@ -2638,7 +2712,6 @@ int ha_connect::index_first(uchar *buf)
|
||||
} // end of index_first
|
||||
|
||||
|
||||
#ifdef NOT_USED
|
||||
/**
|
||||
@brief
|
||||
index_last() asks for the last key in the index.
|
||||
@@ -2652,9 +2725,15 @@ int ha_connect::index_first(uchar *buf)
|
||||
int ha_connect::index_last(uchar *buf)
|
||||
{
|
||||
DBUG_ENTER("ha_connect::index_last");
|
||||
DBUG_RETURN(HA_ERR_WRONG_COMMAND);
|
||||
int rc;
|
||||
|
||||
if (indexing <= 0) {
|
||||
rc= HA_ERR_INTERNAL_ERROR;
|
||||
} else
|
||||
rc= ReadIndexed(buf, OP_LAST);
|
||||
|
||||
DBUG_RETURN(rc);
|
||||
}
|
||||
#endif // NOT_USED
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
@@ -3154,7 +3233,7 @@ bool ha_connect::IsSameIndex(PIXDEF xp1, PIXDEF xp2)
|
||||
MODE ha_connect::CheckMode(PGLOBAL g, THD *thd,
|
||||
MODE newmode, bool *chk, bool *cras)
|
||||
{
|
||||
if (xtrace) {
|
||||
if ((trace= xtrace)) {
|
||||
LEX_STRING *query_string= thd_query_string(thd);
|
||||
htrc("%p check_mode: cmdtype=%d\n", this, thd_sql_command(thd));
|
||||
htrc("Cmd=%.*s\n", (int) query_string->length, query_string->str);
|
||||
@@ -4265,6 +4344,8 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
|
||||
PCOLRES crp;
|
||||
PCONNECT xp= NULL;
|
||||
PGLOBAL g= GetPlug(thd, xp);
|
||||
PDBUSER dup= PlgGetUser(g);
|
||||
PCATLG cat= (dup) ? dup->Catalog : NULL;
|
||||
PTOS topt= table_s->option_struct;
|
||||
#if defined(NEW_WAY)
|
||||
//CHARSET_INFO *cs;
|
||||
@@ -4410,8 +4491,6 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
|
||||
if (create_info->connect_string.str) {
|
||||
int len= create_info->connect_string.length;
|
||||
PMYDEF mydef= new(g) MYSQLDEF();
|
||||
PDBUSER dup= PlgGetUser(g);
|
||||
PCATLG cat= (dup) ? dup->Catalog : NULL;
|
||||
|
||||
dsn= (char*)PlugSubAlloc(g, NULL, len + 1);
|
||||
strncpy(dsn, create_info->connect_string.str, len);
|
||||
@@ -4494,8 +4573,6 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
|
||||
if (ok) {
|
||||
char *cnm, *rem, *dft, *xtra;
|
||||
int i, len, prec, dec, typ, flg;
|
||||
PDBUSER dup= PlgGetUser(g);
|
||||
PCATLG cat= (dup) ? dup->Catalog : NULL;
|
||||
|
||||
if (cat)
|
||||
cat->SetDataPath(g, table_s->db.str);
|
||||
@@ -4545,7 +4622,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
|
||||
#endif // ODBC_SUPPORT
|
||||
#if defined(MYSQL_SUPPORT)
|
||||
case TAB_MYSQL:
|
||||
qrp= MyColumns(g, host, db, user, pwd, tab,
|
||||
qrp= MyColumns(g, thd, host, db, user, pwd, tab,
|
||||
NULL, port, fnc == FNC_COL);
|
||||
break;
|
||||
#endif // MYSQL_SUPPORT
|
||||
@@ -4565,7 +4642,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
|
||||
qrp= TabColumns(g, thd, db, tab, bif);
|
||||
|
||||
if (!qrp && bif && fnc != FNC_COL) // tab is a view
|
||||
qrp= MyColumns(g, host, db, user, pwd, tab, NULL, port, false);
|
||||
qrp= MyColumns(g, thd, host, db, user, pwd, tab, NULL, port, false);
|
||||
|
||||
if (qrp && ttp == TAB_OCCUR && fnc != FNC_COL)
|
||||
if (OcrColumns(g, qrp, col, ocl, rnk)) {
|
||||
@@ -4603,12 +4680,11 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
|
||||
if (!len && typ == TYPE_STRING)
|
||||
len= 256; // STRBLK's have 0 length
|
||||
|
||||
#if defined(NEW_WAY)
|
||||
// Now add the field
|
||||
#if defined(NEW_WAY)
|
||||
rc= add_fields(g, thd, &alter_info, cnm, typ, len, dec,
|
||||
NOT_NULL_FLAG, "", flg, dbf, v);
|
||||
#else // !NEW_WAY
|
||||
// Now add the field
|
||||
if (add_field(&sql, cnm, typ, len, dec, NOT_NULL_FLAG,
|
||||
NULL, NULL, NULL, flg, dbf, v))
|
||||
rc= HA_ERR_OUT_OF_MEM;
|
||||
@@ -4666,6 +4742,11 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
|
||||
break;
|
||||
case FLD_EXTRA:
|
||||
xtra= crp->Kdata->GetCharValue(i);
|
||||
|
||||
// Auto_increment is not supported yet
|
||||
if (!stricmp(xtra, "AUTO_INCREMENT"))
|
||||
xtra= NULL;
|
||||
|
||||
break;
|
||||
default:
|
||||
break; // Ignore
|
||||
@@ -5677,12 +5758,63 @@ Item *ha_connect::idx_cond_push(uint keyno_arg, Item* idx_cond_arg)
|
||||
struct st_mysql_storage_engine connect_storage_engine=
|
||||
{ MYSQL_HANDLERTON_INTERFACE_VERSION };
|
||||
|
||||
// Tracing: 0 no, 1 yes, >1 more tracing
|
||||
static MYSQL_SYSVAR_INT(xtrace, xtrace,
|
||||
PLUGIN_VAR_RQCMDARG, "Console trace value.",
|
||||
NULL, update_connect_xtrace, 0, 0, INT_MAX, 1);
|
||||
|
||||
// Size used when converting TEXT columns to VARCHAR
|
||||
static MYSQL_SYSVAR_INT(conv_size, conv_size,
|
||||
PLUGIN_VAR_RQCMDARG, "Size used when converting TEXT columns.",
|
||||
NULL, update_connect_zconv, SZCONV, 0, 65500, 1);
|
||||
|
||||
/**
|
||||
Type conversion:
|
||||
no: Unsupported types -> TYPE_ERROR
|
||||
yes: TEXT -> VARCHAR
|
||||
skip: skip unsupported type columns in Discovery
|
||||
*/
|
||||
const char *xconv_names[]=
|
||||
{
|
||||
"NO", "YES", "SKIP", NullS
|
||||
};
|
||||
|
||||
TYPELIB xconv_typelib=
|
||||
{
|
||||
array_elements(xconv_names) - 1, "xconv_typelib",
|
||||
xconv_names, NULL
|
||||
};
|
||||
|
||||
static MYSQL_SYSVAR_ENUM(
|
||||
type_conv, // name
|
||||
type_conv, // varname
|
||||
PLUGIN_VAR_RQCMDARG, // opt
|
||||
"Unsupported types conversion.", // comment
|
||||
NULL, // check
|
||||
update_connect_xconv, // update function
|
||||
0, // def (no)
|
||||
&xconv_typelib); // typelib
|
||||
|
||||
#if defined(XMAP)
|
||||
// Using file mapping for indexes if true
|
||||
static MYSQL_SYSVAR_BOOL(indx_map, indx_map, PLUGIN_VAR_RQCMDARG,
|
||||
"Using file mapping for indexes",
|
||||
NULL, update_connect_xmap, 0);
|
||||
#endif // XMAP
|
||||
|
||||
// Size used for g->Sarea_Size
|
||||
static MYSQL_SYSVAR_UINT(work_size, work_size,
|
||||
PLUGIN_VAR_RQCMDARG, "Size of the CONNECT work area.",
|
||||
NULL, update_connect_worksize, SZWORK, SZWMIN, UINT_MAX, 1);
|
||||
|
||||
static struct st_mysql_sys_var* connect_system_variables[]= {
|
||||
MYSQL_SYSVAR(xtrace),
|
||||
MYSQL_SYSVAR(conv_size),
|
||||
MYSQL_SYSVAR(type_conv),
|
||||
#if defined(XMAP)
|
||||
MYSQL_SYSVAR(indx_map),
|
||||
#endif // XMAP
|
||||
MYSQL_SYSVAR(work_size),
|
||||
NULL
|
||||
};
|
||||
|
||||
|
@@ -256,7 +256,8 @@ public:
|
||||
*/
|
||||
ulong index_flags(uint inx, uint part, bool all_parts) const
|
||||
{
|
||||
return HA_READ_NEXT | HA_READ_RANGE | HA_READ_ORDER | HA_KEYREAD_ONLY;
|
||||
return HA_READ_NEXT | HA_READ_RANGE | HA_READ_ORDER
|
||||
| HA_KEYREAD_ONLY | HA_KEY_SCAN_NOT_ROR;
|
||||
} // end of index_flags
|
||||
|
||||
/** @brief
|
||||
@@ -432,7 +433,7 @@ PFIL CondFilter(PGLOBAL g, Item *cond);
|
||||
We implement this in ha_connect.cc. It's not an obligatory method;
|
||||
skip it and and MySQL will treat it as not implemented.
|
||||
*/
|
||||
//int index_last(uchar *buf);
|
||||
int index_last(uchar *buf);
|
||||
|
||||
/* Index condition pushdown implementation */
|
||||
//Item *idx_cond_push(uint keyno, Item* idx_cond);
|
||||
|
@@ -47,9 +47,12 @@
|
||||
#include "myconn.h"
|
||||
|
||||
extern "C" int trace;
|
||||
extern "C" int zconv;
|
||||
extern MYSQL_PLUGIN_IMPORT uint mysqld_port;
|
||||
extern MYSQL_PLUGIN_IMPORT char *mysqld_unix_port;
|
||||
|
||||
DllExport void PushWarning(PGLOBAL, THD*, int level = 1);
|
||||
|
||||
// Returns the current used port
|
||||
uint GetDefaultPort(void)
|
||||
{
|
||||
@@ -61,7 +64,7 @@ uint GetDefaultPort(void)
|
||||
/* of a MySQL table or view. */
|
||||
/* info = TRUE to get catalog column informations. */
|
||||
/************************************************************************/
|
||||
PQRYRES MyColumns(PGLOBAL g, const char *host, const char *db,
|
||||
PQRYRES MyColumns(PGLOBAL g, THD *thd, const char *host, const char *db,
|
||||
const char *user, const char *pwd,
|
||||
const char *table, const char *colpat,
|
||||
int port, bool info)
|
||||
@@ -75,7 +78,7 @@ PQRYRES MyColumns(PGLOBAL g, const char *host, const char *db,
|
||||
FLD_REM, FLD_NO, FLD_DEFAULT, FLD_EXTRA,
|
||||
FLD_CHARSET};
|
||||
unsigned int length[] = {0, 4, 16, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0};
|
||||
char *fld, *fmt, v, cmd[128], uns[16], zero[16];
|
||||
char *fld, *colname, *chset, *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;
|
||||
@@ -144,23 +147,24 @@ PQRYRES MyColumns(PGLOBAL g, const char *host, const char *db,
|
||||
/**********************************************************************/
|
||||
/* Now get the results into blocks. */
|
||||
/**********************************************************************/
|
||||
for (i = 0; i < n; i++) {
|
||||
if ((rc = myc.Fetch(g, -1) == RC_FX)) {
|
||||
for (i = 0; i < n; /*i++*/) {
|
||||
if ((rc = myc.Fetch(g, -1)) == RC_FX) {
|
||||
myc.Close();
|
||||
return NULL;
|
||||
} else if (rc == RC_NF)
|
||||
} else if (rc == RC_EF)
|
||||
break;
|
||||
|
||||
// Get column name
|
||||
fld = myc.GetCharField(0);
|
||||
colname = myc.GetCharField(0);
|
||||
crp = qrp->Colresp; // Column_Name
|
||||
crp->Kdata->SetValue(fld, i);
|
||||
crp->Kdata->SetValue(colname, i);
|
||||
|
||||
// Get type, type name, precision, unsigned and zerofill
|
||||
chset = myc.GetCharField(2);
|
||||
fld = myc.GetCharField(1);
|
||||
prec = 0;
|
||||
len = 0;
|
||||
v = 0;
|
||||
v = (chset && !strcmp(chset, "binary")) ? 'B' : 0;
|
||||
*uns = 0;
|
||||
*zero = 0;
|
||||
|
||||
@@ -181,12 +185,29 @@ PQRYRES MyColumns(PGLOBAL g, const char *host, const char *db,
|
||||
} // endswitch nf
|
||||
|
||||
if ((type = MYSQLtoPLG(cmd, &v)) == TYPE_ERROR) {
|
||||
sprintf(g->Message, "Unsupported column type %s", cmd);
|
||||
if (v == 'K') {
|
||||
// Skip this column
|
||||
sprintf(g->Message, "Column %s skipped (unsupported type %s)",
|
||||
colname, cmd);
|
||||
PushWarning(g, thd);
|
||||
continue;
|
||||
} // endif v
|
||||
|
||||
sprintf(g->Message, "Column %s unsupported type %s", colname, cmd);
|
||||
myc.Close();
|
||||
return NULL;
|
||||
} else if (type == TYPE_STRING)
|
||||
} else if (type == TYPE_STRING) {
|
||||
if (v == 'X') {
|
||||
len = zconv;
|
||||
sprintf(g->Message, "Column %s converted to varchar(%d)",
|
||||
colname, len);
|
||||
PushWarning(g, thd);
|
||||
v = 'V';
|
||||
} else
|
||||
len = min(len, 4096);
|
||||
|
||||
} // endif type
|
||||
|
||||
qrp->Nblin++;
|
||||
crp = crp->Next; // Data_Type
|
||||
crp->Kdata->SetValue(type, i);
|
||||
@@ -241,8 +262,10 @@ PQRYRES MyColumns(PGLOBAL g, const char *host, const char *db,
|
||||
crp->Kdata->SetValue(fld, i);
|
||||
|
||||
crp = crp->Next; // New (charset)
|
||||
fld = myc.GetCharField(2);
|
||||
fld = chset;
|
||||
crp->Kdata->SetValue(fld, i);
|
||||
|
||||
i++; // Can be skipped
|
||||
} // endfor i
|
||||
|
||||
#if 0
|
||||
|
@@ -34,7 +34,7 @@ typedef class MYSQLC *PMYC;
|
||||
/***********************************************************************/
|
||||
/* Prototypes of info functions. */
|
||||
/***********************************************************************/
|
||||
PQRYRES MyColumns(PGLOBAL g, const char *host, const char *db,
|
||||
PQRYRES MyColumns(PGLOBAL g, THD *thd, const char *host, const char *db,
|
||||
const char *user, const char *pwd,
|
||||
const char *table, const char *colpat,
|
||||
int port, bool info);
|
||||
|
@@ -229,7 +229,7 @@ DROP TABLE pets;
|
||||
#
|
||||
CREATE TABLE fruit (
|
||||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`name` varchar(32) DEFAULT NULL,
|
||||
`name` varchar(32) NOT NULL,
|
||||
`cnt` int(11) DEFAULT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=MyISAM AUTO_INCREMENT=6 DEFAULT CHARSET=latin1;
|
||||
|
@@ -5,6 +5,11 @@ package My::Suite::Connect;
|
||||
return "No CONNECT engine" unless $ENV{HA_CONNECT_SO} or
|
||||
$::mysqld_variables{'connect'} eq "ON";
|
||||
|
||||
# RECOMPILE_FOR_EMBEDDED also means that a plugin
|
||||
# cannot be dynamically loaded into embedded
|
||||
return "Not run for embedded server" if $::opt_embedded_server and
|
||||
$ENV{HA_CONNECT_SO};
|
||||
|
||||
sub is_default { 1 }
|
||||
|
||||
bless { };
|
||||
|
@@ -149,7 +149,7 @@ DROP TABLE pets;
|
||||
--echo #
|
||||
CREATE TABLE fruit (
|
||||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`name` varchar(32) DEFAULT NULL,
|
||||
`name` varchar(32) NOT NULL,
|
||||
`cnt` int(11) DEFAULT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=MyISAM AUTO_INCREMENT=6 DEFAULT CHARSET=latin1;
|
||||
|
@@ -1,9 +1,9 @@
|
||||
/************** MyUtil C++ Program Source Code File (.CPP) **************/
|
||||
/* PROGRAM NAME: MYUTIL */
|
||||
/* ------------- */
|
||||
/* Version 1.1 */
|
||||
/* Version 1.2 */
|
||||
/* */
|
||||
/* Author Olivier BERTRAND 2013 */
|
||||
/* Author Olivier BERTRAND 2014 */
|
||||
/* */
|
||||
/* WHAT THIS PROGRAM DOES: */
|
||||
/* ----------------------- */
|
||||
@@ -26,6 +26,8 @@
|
||||
#include "myutil.h"
|
||||
#define DLL_EXPORT // Items are exported from this DLL
|
||||
|
||||
extern "C" int xconv;
|
||||
|
||||
/************************************************************************/
|
||||
/* Convert from MySQL type name to PlugDB type number */
|
||||
/************************************************************************/
|
||||
@@ -38,8 +40,7 @@ int MYSQLtoPLG(char *typname, char *var)
|
||||
type = TYPE_INT;
|
||||
else if (!stricmp(typname, "smallint"))
|
||||
type = TYPE_SHORT;
|
||||
else if (!stricmp(typname, "char") || !stricmp(typname, "varchar") ||
|
||||
!stricmp(typname, "text") || !stricmp(typname, "blob"))
|
||||
else if (!stricmp(typname, "char") || !stricmp(typname, "varchar"))
|
||||
type = TYPE_STRING;
|
||||
else if (!stricmp(typname, "double") || !stricmp(typname, "float") ||
|
||||
!stricmp(typname, "real"))
|
||||
@@ -54,7 +55,20 @@ int MYSQLtoPLG(char *typname, char *var)
|
||||
type = TYPE_BIGINT;
|
||||
else if (!stricmp(typname, "tinyint"))
|
||||
type = TYPE_TINY;
|
||||
else
|
||||
else if (!stricmp(typname, "text") && var) {
|
||||
switch (xconv) {
|
||||
case 1:
|
||||
type = TYPE_STRING;
|
||||
*var = 'X';
|
||||
break;
|
||||
case 2:
|
||||
*var = 'K';
|
||||
default:
|
||||
type = TYPE_ERROR;
|
||||
} // endswitch xconv
|
||||
|
||||
return type;
|
||||
} else
|
||||
type = TYPE_ERROR;
|
||||
|
||||
if (var) {
|
||||
@@ -71,9 +85,11 @@ int MYSQLtoPLG(char *typname, char *var)
|
||||
else if (!stricmp(typname, "year"))
|
||||
*var = 'Y';
|
||||
|
||||
} else if (type == TYPE_STRING && stricmp(typname, "char"))
|
||||
} else if (type == TYPE_STRING && !stricmp(typname, "varchar"))
|
||||
// This is to make the difference between CHAR and VARCHAR
|
||||
*var = 'V';
|
||||
else if (type == TYPE_ERROR && xconv == 2)
|
||||
*var = 'K';
|
||||
else
|
||||
*var = 0;
|
||||
|
||||
@@ -196,27 +212,43 @@ int MYSQLtoPLG(int mytype, char *var)
|
||||
#if !defined(ALPHA)
|
||||
case MYSQL_TYPE_VARCHAR:
|
||||
#endif // !ALPHA)
|
||||
case MYSQL_TYPE_STRING:
|
||||
type = TYPE_STRING;
|
||||
break;
|
||||
case MYSQL_TYPE_BLOB:
|
||||
case MYSQL_TYPE_TINY_BLOB:
|
||||
case MYSQL_TYPE_MEDIUM_BLOB:
|
||||
case MYSQL_TYPE_LONG_BLOB:
|
||||
case MYSQL_TYPE_STRING:
|
||||
if (var) {
|
||||
switch (xconv) {
|
||||
case 1:
|
||||
if (*var != 'B') {
|
||||
// This is a TEXT column
|
||||
type = TYPE_STRING;
|
||||
*var = 'X';
|
||||
} else
|
||||
type = TYPE_ERROR;
|
||||
|
||||
break;
|
||||
case 2:
|
||||
*var = 'K'; // Skip
|
||||
default:
|
||||
type = TYPE_ERROR;
|
||||
} // endswitch xconv
|
||||
|
||||
return type;
|
||||
} // endif var
|
||||
|
||||
default:
|
||||
type = TYPE_ERROR;
|
||||
} // endswitch mytype
|
||||
|
||||
if (var) switch (mytype) {
|
||||
// This is to make the difference between CHAR and VARCHAR
|
||||
case MYSQL_TYPE_VAR_STRING:
|
||||
#if !defined(ALPHA)
|
||||
case MYSQL_TYPE_VARCHAR:
|
||||
#endif // !ALPHA)
|
||||
case MYSQL_TYPE_BLOB:
|
||||
case MYSQL_TYPE_TINY_BLOB:
|
||||
case MYSQL_TYPE_MEDIUM_BLOB:
|
||||
case MYSQL_TYPE_LONG_BLOB: *var = 'V'; break;
|
||||
case MYSQL_TYPE_VAR_STRING: *var = 'V'; break;
|
||||
// This is to make the difference between temporal values
|
||||
case MYSQL_TYPE_TIMESTAMP: *var = 'S'; break;
|
||||
case MYSQL_TYPE_DATE: *var = 'D'; break;
|
||||
|
@@ -16,6 +16,7 @@ my_bool CloseFileHandle(HANDLE h)
|
||||
#include <sys/stat.h>
|
||||
#include <ctype.h>
|
||||
#include <fcntl.h>
|
||||
#include <pwd.h>
|
||||
|
||||
extern FILE *debug;
|
||||
|
||||
@@ -172,16 +173,23 @@ char *_fullpath(char *absPath, const char *relPath, size_t maxLength)
|
||||
// Fixme
|
||||
char *p;
|
||||
|
||||
if( *relPath == '\\' || *relPath == '/' ) {
|
||||
if ( *relPath == '\\' || *relPath == '/' ) {
|
||||
strncpy(absPath, relPath, maxLength);
|
||||
} else if(*relPath == '~') {
|
||||
} else if (*relPath == '~') {
|
||||
// get the path to the home directory
|
||||
// Fixme
|
||||
struct passwd *pw = getpwuid(getuid());
|
||||
const char *homedir = pw->pw_dir;
|
||||
|
||||
if (homedir)
|
||||
strcat(strncpy(absPath, homedir, maxLength), relPath + 1);
|
||||
else
|
||||
strncpy(absPath, relPath, maxLength);
|
||||
|
||||
} else {
|
||||
char buff[2*_MAX_PATH];
|
||||
|
||||
assert(getcwd(buff, _MAX_PATH) != NULL);
|
||||
p= getcwd(buff, _MAX_PATH);
|
||||
assert(p);
|
||||
strcat(buff,"/");
|
||||
strcat(buff, relPath);
|
||||
strncpy(absPath, buff, maxLength);
|
||||
|
@@ -293,6 +293,7 @@ enum OPVAL {OP_EQ = 1, /* Filtering operator = */
|
||||
OP_CURDT = 113, /* Scalar function Op CurDate */
|
||||
OP_NWEEK = 114, /* Scalar function Op Week number*/
|
||||
OP_ROW = 115, /* Scalar function Op Row */
|
||||
OP_PREV = 116, /* Index operator Find Previous */
|
||||
OP_SYSTEM = 200, /* Scalar function Op System */
|
||||
OP_REMOVE = 201, /* Scalar function Op Remove */
|
||||
OP_RENAME = 202, /* Scalar function Op Rename */
|
||||
|
@@ -115,11 +115,6 @@ void htrc(char const *fmt, ...)
|
||||
va_list ap;
|
||||
va_start (ap, fmt);
|
||||
|
||||
//if (trace == 0 || (trace == 1 && !debug) || !fmt) {
|
||||
// printf("In %s wrong trace=%d debug=%p fmt=%p\n",
|
||||
// __FILE__, trace, debug, fmt);
|
||||
// trace = 0;
|
||||
// } // endif trace
|
||||
|
||||
//if (trace == 1)
|
||||
// vfprintf(debug, fmt, ap);
|
||||
@@ -257,6 +252,19 @@ LPCSTR PlugSetPath(LPSTR pBuff, LPCSTR prefix, LPCSTR FileName, LPCSTR defpath)
|
||||
return pBuff;
|
||||
} // endif
|
||||
|
||||
#if !defined(WIN32)
|
||||
if (*FileName == '~') {
|
||||
if (_fullpath(pBuff, FileName, _MAX_PATH)) {
|
||||
if (trace > 1)
|
||||
htrc("pbuff='%s'\n", pBuff);
|
||||
|
||||
return pBuff;
|
||||
} else
|
||||
return FileName; // Error, return unchanged name
|
||||
|
||||
} // endif FileName
|
||||
#endif // !WIN32
|
||||
|
||||
if (strcmp(prefix, ".") && !PlugIsAbsolutePath(defpath))
|
||||
{
|
||||
char tmp[_MAX_PATH];
|
||||
@@ -478,10 +486,9 @@ void *PlugSubAlloc(PGLOBAL g, void *memp, size_t size)
|
||||
size = ((size + 7) / 8) * 8; /* Round up size to multiple of 8 */
|
||||
pph = (PPOOLHEADER)memp;
|
||||
|
||||
#if defined(DEBUG2) || defined(DEBUG3)
|
||||
if (trace > 2)
|
||||
htrc("SubAlloc in %p size=%d used=%d free=%d\n",
|
||||
memp, size, pph->To_Free, pph->FreeBlk);
|
||||
#endif
|
||||
|
||||
if ((uint)size > pph->FreeBlk) { /* Not enough memory left in pool */
|
||||
char *pname = "Work";
|
||||
@@ -490,9 +497,8 @@ void *PlugSubAlloc(PGLOBAL g, void *memp, size_t size)
|
||||
"Not enough memory in %s area for request of %u (used=%d free=%d)",
|
||||
pname, (uint) size, pph->To_Free, pph->FreeBlk);
|
||||
|
||||
#if defined(DEBUG2) || defined(DEBUG3)
|
||||
htrc("%s\n", g->Message);
|
||||
#endif
|
||||
if (trace)
|
||||
htrc("PlugSubAlloc: %s\n", g->Message);
|
||||
|
||||
longjmp(g->jumper[g->jump_level], 1);
|
||||
} /* endif size OS32 code */
|
||||
@@ -503,10 +509,11 @@ void *PlugSubAlloc(PGLOBAL g, void *memp, size_t size)
|
||||
memp = MakePtr(memp, pph->To_Free); /* Points to suballocated block */
|
||||
pph->To_Free += size; /* New offset of pool free block */
|
||||
pph->FreeBlk -= size; /* New size of pool free block */
|
||||
#if defined(DEBUG2) || defined(DEBUG3)
|
||||
|
||||
if (trace > 2)
|
||||
htrc("Done memp=%p used=%d free=%d\n",
|
||||
memp, pph->To_Free, pph->FreeBlk);
|
||||
#endif
|
||||
|
||||
return (memp);
|
||||
} /* end of PlugSubAlloc */
|
||||
|
||||
|
@@ -1134,10 +1134,13 @@ MYSQLCOL::MYSQLCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am)
|
||||
MYSQLCOL::MYSQLCOL(MYSQL_FIELD *fld, PTDB tdbp, int i, PSZ am)
|
||||
: COLBLK(NULL, tdbp, i)
|
||||
{
|
||||
const char *chset = get_charset_name(fld->charsetnr);
|
||||
char v = (!strcmp(chset, "binary")) ? 'B' : 0;
|
||||
|
||||
Name = fld->name;
|
||||
Opt = 0;
|
||||
Precision = Long = fld->length;
|
||||
Buf_Type = MYSQLtoPLG(fld->type);
|
||||
Buf_Type = MYSQLtoPLG(fld->type, &v);
|
||||
strcpy(Format.Type, GetFormatType(Buf_Type));
|
||||
Format.Length = Long;
|
||||
Format.Prec = fld->decimals;
|
||||
@@ -1616,5 +1619,5 @@ TDBMCL::TDBMCL(PMYDEF tdp) : TDBCAT(tdp)
|
||||
/***********************************************************************/
|
||||
PQRYRES TDBMCL::GetResult(PGLOBAL g)
|
||||
{
|
||||
return MyColumns(g, Host, Db, User, Pwd, Tab, NULL, Port, false);
|
||||
return MyColumns(g, NULL, Host, Db, User, Pwd, Tab, NULL, Port, false);
|
||||
} // end of GetResult
|
||||
|
@@ -96,10 +96,21 @@ PIVAID::PIVAID(const char *tab, const char *src, const char *picol,
|
||||
PQRYRES PIVAID::MakePivotColumns(PGLOBAL g)
|
||||
{
|
||||
char *query, *colname, buf[64];
|
||||
int ndif, nblin, w = 0;
|
||||
int rc, ndif, nblin, w = 0;
|
||||
bool b = false;
|
||||
PVAL valp;
|
||||
PCOLRES *pcrp, crp, fncrp = NULL;
|
||||
|
||||
// Save stack and allocation environment and prepare error return
|
||||
if (g->jump_level == MAX_JUMP) {
|
||||
strcpy(g->Message, MSG(TOO_MANY_JUMPS));
|
||||
return NULL;
|
||||
} // endif jump_level
|
||||
|
||||
if ((rc= setjmp(g->jumper[++g->jump_level])) != 0) {
|
||||
goto err;
|
||||
} // endif rc
|
||||
|
||||
if (!Tabsrc && Tabname) {
|
||||
// Locate the query
|
||||
query = (char*)PlugSubAlloc(g, NULL, strlen(Tabname) + 16);
|
||||
@@ -113,16 +124,17 @@ PQRYRES PIVAID::MakePivotColumns(PGLOBAL g)
|
||||
// Open a MySQL connection for this table
|
||||
if (Myc.Open(g, Host, Database, User, Pwd, Port))
|
||||
return NULL;
|
||||
else
|
||||
b = true;
|
||||
|
||||
// Send the source command to MySQL
|
||||
if (Myc.ExecSQL(g, query, &w) == RC_FX) {
|
||||
Myc.Close();
|
||||
return NULL;
|
||||
} // endif Exec
|
||||
if (Myc.ExecSQL(g, query, &w) == RC_FX)
|
||||
goto err;
|
||||
|
||||
// We must have a storage query to get pivot column values
|
||||
Qryp = Myc.GetResult(g, true);
|
||||
Myc.Close();
|
||||
b = false;
|
||||
|
||||
if (!Fncol) {
|
||||
for (crp = Qryp->Colresp; crp; crp = crp->Next)
|
||||
@@ -152,6 +164,11 @@ PQRYRES PIVAID::MakePivotColumns(PGLOBAL g)
|
||||
// Prepare the column list
|
||||
for (pcrp = &Qryp->Colresp; crp = *pcrp; )
|
||||
if (!stricmp(Picol, crp->Name)) {
|
||||
if (crp->Nulls) {
|
||||
sprintf(g->Message, "Pivot column %s cannot be nullable", Picol);
|
||||
return NULL;
|
||||
} // endif Nulls
|
||||
|
||||
Rblkp = crp->Kdata;
|
||||
*pcrp = crp->Next;
|
||||
} else if (!stricmp(Fncol, crp->Name)) {
|
||||
@@ -218,6 +235,12 @@ PQRYRES PIVAID::MakePivotColumns(PGLOBAL g)
|
||||
// We added ndif columns and removed 2 (picol and fncol)
|
||||
Qryp->Nbcol += (ndif - 2);
|
||||
return Qryp;
|
||||
|
||||
err:
|
||||
if (b)
|
||||
Myc.Close();
|
||||
|
||||
return NULL;
|
||||
} // end of MakePivotColumns
|
||||
|
||||
/***********************************************************************/
|
||||
|
@@ -55,6 +55,7 @@
|
||||
#include "ha_connect.h"
|
||||
|
||||
extern "C" int trace;
|
||||
extern "C" int zconv;
|
||||
|
||||
/************************************************************************/
|
||||
/* Used by MYSQL tables to get MySQL parameters from the calling proxy */
|
||||
@@ -129,7 +130,7 @@ PQRYRES TabColumns(PGLOBAL g, THD *thd, const char *db,
|
||||
FLD_LENGTH, FLD_SCALE, FLD_RADIX, FLD_NULL,
|
||||
FLD_REM, FLD_NO, FLD_CHARSET};
|
||||
unsigned int length[] = {0, 4, 16, 4, 4, 4, 4, 4, 0, 32, 32};
|
||||
char *fld, *fmt, v;
|
||||
char *fld, *colname, *chset, *fmt, v;
|
||||
int i, n, ncol = sizeof(buftyp) / sizeof(int);
|
||||
int prec, len, type, scale;
|
||||
bool mysql;
|
||||
@@ -176,21 +177,37 @@ PQRYRES TabColumns(PGLOBAL g, THD *thd, const char *db,
|
||||
/**********************************************************************/
|
||||
/* Now get the results into blocks. */
|
||||
/**********************************************************************/
|
||||
for (i = 0, field= s->field; *field; i++, field++) {
|
||||
for (i = 0, field= s->field; *field; field++) {
|
||||
fp= *field;
|
||||
|
||||
// Get column name
|
||||
crp = qrp->Colresp; // Column_Name
|
||||
fld = (char *)fp->field_name;
|
||||
crp->Kdata->SetValue(fld, i);
|
||||
v = 0;
|
||||
colname = (char *)fp->field_name;
|
||||
crp->Kdata->SetValue(colname, i);
|
||||
|
||||
chset = (char *)fp->charset()->name;
|
||||
v = (!strcmp(chset, "binary")) ? 'B' : 0;
|
||||
|
||||
if ((type = MYSQLtoPLG(fp->type(), &v)) == TYPE_ERROR) {
|
||||
sprintf(g->Message, "Unsupported column type %s", GetTypeName(type));
|
||||
if (v == 'K') {
|
||||
// Skip this column
|
||||
sprintf(g->Message, "Column %s skipped (unsupported type)", colname);
|
||||
push_warning(thd, Sql_condition::WARN_LEVEL_WARN, 0, g->Message);
|
||||
continue;
|
||||
} // endif v
|
||||
|
||||
sprintf(g->Message, "Column %s unsupported type", colname);
|
||||
qrp = NULL;
|
||||
break;
|
||||
} // endif type
|
||||
|
||||
if (v == 'X') {
|
||||
len = zconv;
|
||||
sprintf(g->Message, "Column %s converted to varchar(%d)",
|
||||
colname, len);
|
||||
push_warning(thd, Sql_condition::WARN_LEVEL_WARN, 0, g->Message);
|
||||
} // endif v
|
||||
|
||||
crp = crp->Next; // Data_Type
|
||||
crp->Kdata->SetValue(type, i);
|
||||
|
||||
@@ -198,11 +215,12 @@ PQRYRES TabColumns(PGLOBAL g, THD *thd, const char *db,
|
||||
crp->Nulls[i] = 'Z';
|
||||
else if (fp->flags & UNSIGNED_FLAG)
|
||||
crp->Nulls[i] = 'U';
|
||||
else
|
||||
crp->Nulls[i] = v;
|
||||
else // X means TEXT field
|
||||
crp->Nulls[i] = (v == 'X') ? 'V' : v;
|
||||
|
||||
crp = crp->Next; // Type_Name
|
||||
crp->Kdata->SetValue(GetTypeName(type), i);
|
||||
fmt = NULL;
|
||||
|
||||
if (type == TYPE_DATE) {
|
||||
// When creating tables we do need info about date columns
|
||||
@@ -214,7 +232,7 @@ PQRYRES TabColumns(PGLOBAL g, THD *thd, const char *db,
|
||||
prec = len = fp->field_length;
|
||||
} // endif mysql
|
||||
|
||||
} else {
|
||||
} else if (v != 'X') {
|
||||
if (type == TYPE_DECIM)
|
||||
prec = ((Field_new_decimal*)fp)->precision;
|
||||
else
|
||||
@@ -222,8 +240,8 @@ PQRYRES TabColumns(PGLOBAL g, THD *thd, const char *db,
|
||||
// prec = (prec(???) == NOT_FIXED_DEC) ? 0 : fp->field_length;
|
||||
|
||||
len = fp->char_length();
|
||||
fmt = NULL;
|
||||
} // endif type
|
||||
} else
|
||||
prec = len = zconv;
|
||||
|
||||
crp = crp->Next; // Precision
|
||||
crp->Kdata->SetValue(prec, i);
|
||||
@@ -259,6 +277,7 @@ PQRYRES TabColumns(PGLOBAL g, THD *thd, const char *db,
|
||||
|
||||
// Add this item
|
||||
qrp->Nblin++;
|
||||
i++; // Can be skipped
|
||||
} // endfor field
|
||||
|
||||
/**********************************************************************/
|
||||
|
@@ -48,6 +48,7 @@
|
||||
#include "mycat.h"
|
||||
|
||||
extern "C" int trace;
|
||||
extern uint worksize;
|
||||
|
||||
/****************************************************************************/
|
||||
/* Initialize the user_connect static member. */
|
||||
@@ -94,8 +95,9 @@ bool user_connect::user_init()
|
||||
PDBUSER dup= NULL;
|
||||
|
||||
// Areasize= 64M because of VEC tables. Should be parameterisable
|
||||
g= PlugInit(NULL, 67108864);
|
||||
//g= PlugInit(NULL, 67108864);
|
||||
//g= PlugInit(NULL, 134217728); // 128M was because of old embedded tests
|
||||
g= PlugInit(NULL, worksize);
|
||||
|
||||
// Check whether the initialization is complete
|
||||
if (!g || !g->Sarea || PlugSubSet(g, g->Sarea, g->Sarea_Size)
|
||||
@@ -142,6 +144,20 @@ bool user_connect::CheckCleanup(void)
|
||||
{
|
||||
if (thdp->query_id > last_query_id) {
|
||||
PlugCleanup(g, true);
|
||||
|
||||
if (g->Sarea_Size != worksize) {
|
||||
if (g->Sarea)
|
||||
free(g->Sarea);
|
||||
|
||||
// Check whether the work area size was changed
|
||||
if (!(g->Sarea = PlugAllocMem(g, worksize))) {
|
||||
g->Sarea = PlugAllocMem(g, g->Sarea_Size);
|
||||
worksize = g->Sarea_Size; // Was too big
|
||||
} else
|
||||
g->Sarea_Size = worksize; // Ok
|
||||
|
||||
} // endif worksize
|
||||
|
||||
PlugSubSet(g, g->Sarea, g->Sarea_Size);
|
||||
g->Xchk = NULL;
|
||||
g->Createas = 0;
|
||||
|
@@ -44,6 +44,7 @@
|
||||
#define CheckParms(V, N) ChkIndx(N); ChkTyp(V);
|
||||
|
||||
extern "C" int trace;
|
||||
extern MBLOCK Nmblk; /* Used to initialize MBLOCK's */
|
||||
|
||||
/***********************************************************************/
|
||||
/* AllocValBlock: allocate a VALBLK according to type. */
|
||||
@@ -105,8 +106,7 @@ PVBLK AllocValBlock(PGLOBAL g, void *mp, int type, int nval, int len,
|
||||
return NULL;
|
||||
} // endswitch Type
|
||||
|
||||
blkp->Init(g, check);
|
||||
return blkp;
|
||||
return (blkp->Init(g, check)) ? NULL : blkp;
|
||||
} // end of AllocValBlock
|
||||
|
||||
/* -------------------------- Class VALBLK --------------------------- */
|
||||
@@ -116,6 +116,7 @@ PVBLK AllocValBlock(PGLOBAL g, void *mp, int type, int nval, int len,
|
||||
/***********************************************************************/
|
||||
VALBLK::VALBLK(void *mp, int type, int nval, bool un)
|
||||
{
|
||||
Mblk = Nmblk;
|
||||
Blkp = mp;
|
||||
To_Nulls = NULL;
|
||||
Check = true;
|
||||
@@ -179,6 +180,22 @@ void VALBLK::SetNullable(bool b)
|
||||
|
||||
} // end of SetNullable
|
||||
|
||||
/***********************************************************************/
|
||||
/* Buffer allocation routine. */
|
||||
/***********************************************************************/
|
||||
bool VALBLK::AllocBuff(PGLOBAL g, size_t size)
|
||||
{
|
||||
Mblk.Size = size;
|
||||
|
||||
if (!(Blkp = PlgDBalloc(g, NULL, Mblk))) {
|
||||
sprintf(g->Message, MSG(MEM_ALLOC_ERR), "Blkp", Mblk.Size);
|
||||
fprintf(stderr, "%s\n", g->Message);
|
||||
return true;
|
||||
} // endif Blkp
|
||||
|
||||
return false;
|
||||
} // end of AllocBuff
|
||||
|
||||
/***********************************************************************/
|
||||
/* Check functions. */
|
||||
/***********************************************************************/
|
||||
@@ -229,13 +246,15 @@ TYPBLK<TYPE>::TYPBLK(void *mp, int nval, int type, int prec, bool un)
|
||||
/* Initialization routine. */
|
||||
/***********************************************************************/
|
||||
template <class TYPE>
|
||||
void TYPBLK<TYPE>::Init(PGLOBAL g, bool check)
|
||||
bool TYPBLK<TYPE>::Init(PGLOBAL g, bool check)
|
||||
{
|
||||
if (!Blkp)
|
||||
Blkp = PlugSubAlloc(g, NULL, Nval * sizeof(TYPE));
|
||||
if (AllocBuff(g, Nval * sizeof(TYPE)))
|
||||
return true;
|
||||
|
||||
Check = check;
|
||||
Global = g;
|
||||
return false;
|
||||
} // end of Init
|
||||
|
||||
/***********************************************************************/
|
||||
@@ -606,16 +625,18 @@ CHRBLK::CHRBLK(void *mp, int nval, int len, int prec, bool blank)
|
||||
/***********************************************************************/
|
||||
/* Initialization routine. */
|
||||
/***********************************************************************/
|
||||
void CHRBLK::Init(PGLOBAL g, bool check)
|
||||
bool CHRBLK::Init(PGLOBAL g, bool check)
|
||||
{
|
||||
Valp = (char*)PlugSubAlloc(g, NULL, Long + 1);
|
||||
Valp[Long] = '\0';
|
||||
|
||||
if (!Blkp)
|
||||
Blkp = PlugSubAlloc(g, NULL, Nval * Long);
|
||||
if (AllocBuff(g, Nval * Long))
|
||||
return true;
|
||||
|
||||
Check = check;
|
||||
Global = g;
|
||||
return false;
|
||||
} // end of Init
|
||||
|
||||
/***********************************************************************/
|
||||
@@ -996,13 +1017,15 @@ STRBLK::STRBLK(PGLOBAL g, void *mp, int nval)
|
||||
/***********************************************************************/
|
||||
/* Initialization routine. */
|
||||
/***********************************************************************/
|
||||
void STRBLK::Init(PGLOBAL g, bool check)
|
||||
bool STRBLK::Init(PGLOBAL g, bool check)
|
||||
{
|
||||
if (!Blkp)
|
||||
Blkp = PlugSubAlloc(g, NULL, Nval * sizeof(PSZ));
|
||||
if (AllocBuff(g, Nval * sizeof(PSZ)))
|
||||
return true;
|
||||
|
||||
Check = check;
|
||||
Global = g;
|
||||
return false;
|
||||
} // end of Init
|
||||
|
||||
/***********************************************************************/
|
||||
|
@@ -75,7 +75,7 @@ class VALBLK : public BLOCK {
|
||||
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 bool Init(PGLOBAL g, bool check) = 0;
|
||||
virtual int GetVlen(void) = 0;
|
||||
virtual PSZ GetCharValue(int n);
|
||||
virtual char GetTinyValue(int n) = 0;
|
||||
@@ -120,12 +120,14 @@ class VALBLK : public BLOCK {
|
||||
bool Locate(PVAL vp, int& i);
|
||||
|
||||
protected:
|
||||
bool AllocBuff(PGLOBAL g, size_t size);
|
||||
void ChkIndx(int n);
|
||||
void ChkTyp(PVAL v);
|
||||
void ChkTyp(PVBLK vb);
|
||||
|
||||
// Members
|
||||
PGLOBAL Global; // Used for messages and allocation
|
||||
MBLOCK Mblk; // Used to allocate buffer
|
||||
char *To_Nulls; // Null values array
|
||||
void *Blkp; // To value block
|
||||
bool Check; // If true SetValue types must match
|
||||
@@ -146,7 +148,7 @@ class TYPBLK : public VALBLK {
|
||||
TYPBLK(void *mp, int size, int type, int prec = 0, bool un = false);
|
||||
|
||||
// Implementation
|
||||
virtual void Init(PGLOBAL g, bool check);
|
||||
virtual bool Init(PGLOBAL g, bool check);
|
||||
virtual int GetVlen(void) {return sizeof(TYPE);}
|
||||
virtual char GetTinyValue(int n) {return (char)Typp[n];}
|
||||
virtual uchar GetUTinyValue(int n) {return (uchar)Typp[n];}
|
||||
@@ -213,7 +215,7 @@ class CHRBLK : public VALBLK {
|
||||
CHRBLK(void *mp, int size, int len, int prec, bool b);
|
||||
|
||||
// Implementation
|
||||
virtual void Init(PGLOBAL g, bool check);
|
||||
virtual bool Init(PGLOBAL g, bool check);
|
||||
virtual int GetVlen(void) {return Long;}
|
||||
virtual PSZ GetCharValue(int n);
|
||||
virtual char GetTinyValue(int n);
|
||||
@@ -268,7 +270,7 @@ class STRBLK : public VALBLK {
|
||||
virtual void SetNull(int n, bool b) {if (b) {Strp[n] = NULL;}}
|
||||
virtual bool IsNull(int n) {return Strp[n] == NULL;}
|
||||
virtual void SetNullable(bool b) {} // Always nullable
|
||||
virtual void Init(PGLOBAL g, bool check);
|
||||
virtual bool Init(PGLOBAL g, bool check);
|
||||
virtual int GetVlen(void) {return sizeof(PSZ);}
|
||||
virtual PSZ GetCharValue(int n) {return Strp[n];}
|
||||
virtual char GetTinyValue(int n);
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/************* Value C++ Functions Source Code File (.CPP) *************/
|
||||
/* Name: VALUE.CPP Version 2.4 */
|
||||
/* Name: VALUE.CPP Version 2.5 */
|
||||
/* */
|
||||
/* (C) Copyright to the author Olivier BERTRAND 2001-2014 */
|
||||
/* */
|
||||
@@ -183,6 +183,7 @@ PSZ GetTypeName(int type)
|
||||
case TYPE_DOUBLE: name = "DOUBLE"; break;
|
||||
case TYPE_TINY: name = "TINY"; break;
|
||||
case TYPE_DECIM: name = "DECIMAL"; break;
|
||||
case TYPE_BIN: name = "BINARY"; break;
|
||||
default: name = "UNKNOWN"; break;
|
||||
} // endswitch type
|
||||
|
||||
@@ -196,6 +197,7 @@ int GetTypeSize(int type, int len)
|
||||
{
|
||||
switch (type) {
|
||||
case TYPE_DECIM:
|
||||
case TYPE_BIN:
|
||||
case TYPE_STRING: len = len * sizeof(char); break;
|
||||
case TYPE_SHORT: len = sizeof(short); break;
|
||||
case TYPE_INT: len = sizeof(int); break;
|
||||
@@ -225,6 +227,7 @@ char *GetFormatType(int type)
|
||||
case TYPE_DATE: c = "D"; break;
|
||||
case TYPE_TINY: c = "T"; break;
|
||||
case TYPE_DECIM: c = "M"; break;
|
||||
case TYPE_BIN: c = "B"; break;
|
||||
} // endswitch type
|
||||
|
||||
return c;
|
||||
@@ -246,6 +249,7 @@ int GetFormatType(char c)
|
||||
case 'D': type = TYPE_DATE; break;
|
||||
case 'T': type = TYPE_TINY; break;
|
||||
case 'M': type = TYPE_DECIM; break;
|
||||
case 'B': type = TYPE_BIN; break;
|
||||
} // endswitch type
|
||||
|
||||
return type;
|
||||
@@ -298,6 +302,7 @@ const char *GetFmt(int type, bool un)
|
||||
case TYPE_SHORT: fmt = (un) ? "%hu" : "%hd"; break;
|
||||
case TYPE_BIGINT: fmt = (un) ? "%llu" : "%lld"; break;
|
||||
case TYPE_DOUBLE: fmt = "%.*lf"; break;
|
||||
case TYPE_BIN: fmt = "%*x"; break;
|
||||
default: fmt = (un) ? "%u" : "%d"; break;
|
||||
} // endswitch Type
|
||||
|
||||
@@ -438,6 +443,9 @@ PVAL AllocateValue(PGLOBAL g, int type, int len, int prec,
|
||||
case TYPE_DECIM:
|
||||
valp = new(g) DECVAL(g, (PSZ)NULL, len, prec, uns);
|
||||
break;
|
||||
case TYPE_BIN:
|
||||
valp = new(g) BINVAL(g, (void*)NULL, len, prec);
|
||||
break;
|
||||
default:
|
||||
sprintf(g->Message, MSG(BAD_VALUE_TYPE), type);
|
||||
return NULL;
|
||||
@@ -544,6 +552,7 @@ const char *VALUE::GetXfmt(void)
|
||||
case TYPE_SHORT: fmt = (Unsigned) ? "%*hu" : "%*hd"; break;
|
||||
case TYPE_BIGINT: fmt = (Unsigned) ? "%*llu" : "%*lld"; break;
|
||||
case TYPE_DOUBLE: fmt = "%*.*lf"; break;
|
||||
case TYPE_BIN: fmt = "%*x"; break;
|
||||
default: fmt = (Unsigned) ? "%*u" : "%*d"; break;
|
||||
} // endswitch Type
|
||||
|
||||
@@ -1695,6 +1704,426 @@ bool DECVAL::SetConstFormat(PGLOBAL g, FORMAT& fmt)
|
||||
} // end of SetConstFormat
|
||||
#endif // 0
|
||||
|
||||
/* -------------------------- Class BINVAL --------------------------- */
|
||||
|
||||
/***********************************************************************/
|
||||
/* BINVAL public constructor from bytes. */
|
||||
/***********************************************************************/
|
||||
BINVAL::BINVAL(PGLOBAL g, void *p, int cl, int n) : VALUE(TYPE_BIN)
|
||||
{
|
||||
assert(g);
|
||||
Len = n;
|
||||
Clen = cl;
|
||||
Binp = PlugSubAlloc(g, NULL, Clen + 1);
|
||||
memset(Binp, 0, Clen + 1);
|
||||
|
||||
if (p)
|
||||
memcpy(Binp, p, Len);
|
||||
|
||||
Chrp = NULL;
|
||||
} // end of BINVAL constructor
|
||||
|
||||
/***********************************************************************/
|
||||
/* BINVAL: Check whether the hexadecimal value is equal to 0. */
|
||||
/***********************************************************************/
|
||||
bool BINVAL::IsZero(void)
|
||||
{
|
||||
for (int i = 0; i < Len; i++)
|
||||
if (((char*)Binp)[i] != 0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
} // end of IsZero
|
||||
|
||||
/***********************************************************************/
|
||||
/* BINVAL: Reset value to zero. */
|
||||
/***********************************************************************/
|
||||
void BINVAL::Reset(void)
|
||||
{
|
||||
memset(Binp, 0, Clen);
|
||||
Len = 0;
|
||||
} // end of Reset
|
||||
|
||||
/***********************************************************************/
|
||||
/* Get the tiny value pointed by Binp. */
|
||||
/***********************************************************************/
|
||||
char BINVAL::GetTinyValue(void)
|
||||
{
|
||||
return *(char*)Binp;
|
||||
} // end of GetTinyValue
|
||||
|
||||
/***********************************************************************/
|
||||
/* Get the unsigned tiny value pointed by Binp. */
|
||||
/***********************************************************************/
|
||||
uchar BINVAL::GetUTinyValue(void)
|
||||
{
|
||||
return *(uchar*)Binp;
|
||||
} // end of GetUTinyValue
|
||||
|
||||
/***********************************************************************/
|
||||
/* Get the short value pointed by Binp. */
|
||||
/***********************************************************************/
|
||||
short BINVAL::GetShortValue(void)
|
||||
{
|
||||
if (Len >= 2)
|
||||
return *(short*)Binp;
|
||||
else
|
||||
return (short)GetTinyValue();
|
||||
|
||||
} // end of GetShortValue
|
||||
|
||||
/***********************************************************************/
|
||||
/* Get the unsigned short value pointed by Binp. */
|
||||
/***********************************************************************/
|
||||
ushort BINVAL::GetUShortValue(void)
|
||||
{
|
||||
return (ushort)GetShortValue();
|
||||
} // end of GetUshortValue
|
||||
|
||||
/***********************************************************************/
|
||||
/* Get the integer value pointed by Binp. */
|
||||
/***********************************************************************/
|
||||
int BINVAL::GetIntValue(void)
|
||||
{
|
||||
if (Len >= 4)
|
||||
return *(int*)Binp;
|
||||
else
|
||||
return (int)GetShortValue();
|
||||
|
||||
} // end of GetIntValue
|
||||
|
||||
/***********************************************************************/
|
||||
/* Get the unsigned integer value pointed by Binp. */
|
||||
/***********************************************************************/
|
||||
uint BINVAL::GetUIntValue(void)
|
||||
{
|
||||
return (uint)GetIntValue();
|
||||
} // end of GetUintValue
|
||||
|
||||
/***********************************************************************/
|
||||
/* Get the big integer value pointed by Binp. */
|
||||
/***********************************************************************/
|
||||
longlong BINVAL::GetBigintValue(void)
|
||||
{
|
||||
if (Len >= 8)
|
||||
return *(longlong*)Binp;
|
||||
else
|
||||
return (longlong)GetIntValue();
|
||||
|
||||
} // end of GetBigintValue
|
||||
|
||||
/***********************************************************************/
|
||||
/* Get the unsigned big integer value pointed by Binp. */
|
||||
/***********************************************************************/
|
||||
ulonglong BINVAL::GetUBigintValue(void)
|
||||
{
|
||||
return (ulonglong)GetBigintValue();
|
||||
} // end of GetUBigintValue
|
||||
|
||||
/***********************************************************************/
|
||||
/* Get the double value pointed by Binp. */
|
||||
/***********************************************************************/
|
||||
double BINVAL::GetFloatValue(void)
|
||||
{
|
||||
if (Len >= 8)
|
||||
return *(double*)Binp;
|
||||
else if (Len >= 4)
|
||||
return (double)(*(float*)Binp);
|
||||
else
|
||||
return 0.0;
|
||||
|
||||
} // end of GetFloatValue
|
||||
|
||||
/***********************************************************************/
|
||||
/* BINVAL SetValue: copy the value of another Value object. */
|
||||
/***********************************************************************/
|
||||
bool BINVAL::SetValue_pval(PVAL valp, bool chktype)
|
||||
{
|
||||
if (chktype && (valp->GetType() != Type || valp->GetSize() > Clen))
|
||||
return true;
|
||||
|
||||
bool rc = false;
|
||||
|
||||
if (!(Null = valp->IsNull() && Nullable)) {
|
||||
if ((rc = (Len = valp->GetSize()) > Clen))
|
||||
Len = Clen;
|
||||
|
||||
memcpy(Binp, valp->GetTo_Val(), Len);
|
||||
} else
|
||||
Reset();
|
||||
|
||||
return rc;
|
||||
} // end of SetValue_pval
|
||||
|
||||
/***********************************************************************/
|
||||
/* BINVAL SetValue: fill value with chars extracted from a line. */
|
||||
/***********************************************************************/
|
||||
bool BINVAL::SetValue_char(char *p, int n)
|
||||
{
|
||||
bool rc;
|
||||
|
||||
if (p) {
|
||||
rc = n > Clen;
|
||||
Len = min(n, Clen);
|
||||
memcpy(Binp, p, Len);
|
||||
Null = false;
|
||||
} else {
|
||||
rc = false;
|
||||
Reset();
|
||||
Null = Nullable;
|
||||
} // endif p
|
||||
|
||||
return rc;
|
||||
} // end of SetValue_char
|
||||
|
||||
/***********************************************************************/
|
||||
/* BINVAL SetValue: fill value with another string. */
|
||||
/***********************************************************************/
|
||||
void BINVAL::SetValue_psz(PSZ s)
|
||||
{
|
||||
if (s) {
|
||||
Len = min(Clen, (signed)strlen(s));
|
||||
memcpy(Binp, s, Len);
|
||||
Null = false;
|
||||
} else {
|
||||
Reset();
|
||||
Null = Nullable;
|
||||
} // endif s
|
||||
|
||||
} // end of SetValue_psz
|
||||
|
||||
/***********************************************************************/
|
||||
/* BINVAL SetValue: fill value with bytes extracted from a block. */
|
||||
/***********************************************************************/
|
||||
void BINVAL::SetValue_pvblk(PVBLK blk, int n)
|
||||
{
|
||||
// STRBLK's can return a NULL pointer
|
||||
void *vp = blk->GetValPtrEx(n);
|
||||
|
||||
if (!vp || blk->IsNull(n)) {
|
||||
Reset();
|
||||
Null = Nullable;
|
||||
} else if (vp != Binp) {
|
||||
if (blk->GetType() == TYPE_STRING)
|
||||
Len = strlen((char*)vp);
|
||||
else
|
||||
Len = blk->GetVlen();
|
||||
|
||||
Len = min(Clen, Len);
|
||||
memcpy(Binp, vp, Len);
|
||||
Null = false;
|
||||
} // endif vp
|
||||
|
||||
} // end of SetValue_pvblk
|
||||
|
||||
/***********************************************************************/
|
||||
/* BINVAL SetValue: get the binary representation of an integer. */
|
||||
/***********************************************************************/
|
||||
void BINVAL::SetValue(int n)
|
||||
{
|
||||
if (Clen >= 4) {
|
||||
*((int*)Binp) = n;
|
||||
Len = 4;
|
||||
} else
|
||||
SetValue((short)n);
|
||||
|
||||
} // end of SetValue
|
||||
|
||||
/***********************************************************************/
|
||||
/* BINVAL SetValue: get the binary representation of an uint. */
|
||||
/***********************************************************************/
|
||||
void BINVAL::SetValue(uint n)
|
||||
{
|
||||
if (Clen >= 4) {
|
||||
*((uint*)Binp) = n;
|
||||
Len = 4;
|
||||
} else
|
||||
SetValue((ushort)n);
|
||||
|
||||
} // end of SetValue
|
||||
|
||||
/***********************************************************************/
|
||||
/* BINVAL SetValue: get the binary representation of a short int. */
|
||||
/***********************************************************************/
|
||||
void BINVAL::SetValue(short i)
|
||||
{
|
||||
if (Clen >= 2) {
|
||||
*((int*)Binp) = i;
|
||||
Len = 2;
|
||||
} else
|
||||
SetValue((char)i);
|
||||
|
||||
} // end of SetValue
|
||||
|
||||
/***********************************************************************/
|
||||
/* BINVAL SetValue: get the binary representation of a ushort int. */
|
||||
/***********************************************************************/
|
||||
void BINVAL::SetValue(ushort i)
|
||||
{
|
||||
if (Clen >= 2) {
|
||||
*((uint*)Binp) = i;
|
||||
Len = 2;
|
||||
} else
|
||||
SetValue((uchar)i);
|
||||
|
||||
} // end of SetValue
|
||||
|
||||
/***********************************************************************/
|
||||
/* BINVAL SetValue: get the binary representation of a big integer. */
|
||||
/***********************************************************************/
|
||||
void BINVAL::SetValue(longlong n)
|
||||
{
|
||||
if (Clen >= 8) {
|
||||
*((longlong*)Binp) = n;
|
||||
Len = 8;
|
||||
} else
|
||||
SetValue((int)n);
|
||||
|
||||
} // end of SetValue
|
||||
|
||||
/***********************************************************************/
|
||||
/* BINVAL SetValue: get the binary representation of a big integer. */
|
||||
/***********************************************************************/
|
||||
void BINVAL::SetValue(ulonglong n)
|
||||
{
|
||||
if (Clen >= 8) {
|
||||
*((ulonglong*)Binp) = n;
|
||||
Len = 8;
|
||||
} else
|
||||
SetValue((uint)n);
|
||||
} // end of SetValue
|
||||
|
||||
/***********************************************************************/
|
||||
/* BINVAL SetValue: get the binary representation of a double. */
|
||||
/***********************************************************************/
|
||||
void BINVAL::SetValue(double n)
|
||||
{
|
||||
if (Clen >= 8) {
|
||||
*((double*)Binp) = n;
|
||||
Len = 8;
|
||||
} else if (Clen >= 4) {
|
||||
*((float*)Binp) = (float)n;
|
||||
Len = 4;
|
||||
} else
|
||||
Len = 0;
|
||||
|
||||
} // end of SetValue
|
||||
|
||||
/***********************************************************************/
|
||||
/* BINVAL SetValue: get the character binary of a tiny int. */
|
||||
/***********************************************************************/
|
||||
void BINVAL::SetValue(char c)
|
||||
{
|
||||
*((char*)Binp) = c;
|
||||
Len = 1;
|
||||
} // end of SetValue
|
||||
|
||||
/***********************************************************************/
|
||||
/* BINVAL SetValue: get the binary representation of a tiny int. */
|
||||
/***********************************************************************/
|
||||
void BINVAL::SetValue(uchar c)
|
||||
{
|
||||
*((uchar*)Binp) = c;
|
||||
Len = 1;
|
||||
} // end of SetValue
|
||||
|
||||
/***********************************************************************/
|
||||
/* BINVAL SetBinValue: fill string with bytes extracted from a line. */
|
||||
/***********************************************************************/
|
||||
void BINVAL::SetBinValue(void *p)
|
||||
{
|
||||
memcpy(Binp, p, Clen);
|
||||
} // 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 BINVAL::GetBinValue(void *buf, int buflen, bool go)
|
||||
{
|
||||
if (Len > buflen)
|
||||
return true;
|
||||
else if (go) {
|
||||
memset(buf, 0, buflen);
|
||||
memcpy(buf, Binp, Len);
|
||||
} // endif go
|
||||
|
||||
return false;
|
||||
} // end of GetBinValue
|
||||
|
||||
/***********************************************************************/
|
||||
/* BINVAL ShowValue: get string representation of a binary value. */
|
||||
/***********************************************************************/
|
||||
char *BINVAL::ShowValue(char *buf, int len)
|
||||
{
|
||||
int n = min(Len, len / 2);
|
||||
|
||||
sprintf(buf, GetXfmt(), n, Binp);
|
||||
return buf;
|
||||
} // end of ShowValue
|
||||
|
||||
/***********************************************************************/
|
||||
/* BINVAL GetCharString: get string representation of a binary value. */
|
||||
/***********************************************************************/
|
||||
char *BINVAL::GetCharString(char *p)
|
||||
{
|
||||
if (!Chrp)
|
||||
Chrp = (char*)PlugSubAlloc(Global, NULL, Clen * 2 + 1);
|
||||
|
||||
sprintf(Chrp, GetXfmt(), Len, Binp);
|
||||
return Chrp;
|
||||
} // end of GetCharString
|
||||
|
||||
/***********************************************************************/
|
||||
/* BINVAL compare value with another Value. */
|
||||
/***********************************************************************/
|
||||
bool BINVAL::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 if (Len != vp->GetSize())
|
||||
return false;
|
||||
|
||||
char *v1 = (char*)Binp;
|
||||
char *v2 = (char*)vp->GetTo_Val();
|
||||
|
||||
for (int i = 0; i < Len; i++)
|
||||
if (v1[i] != v2[i])
|
||||
return false;
|
||||
|
||||
return true;
|
||||
} // 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 BINVAL::FormatValue(PVAL vp, char *fmt)
|
||||
{
|
||||
char *buf = (char*)vp->GetTo_Val(); // Should be big enough
|
||||
int n = sprintf(buf, fmt, Len, Binp);
|
||||
|
||||
return (n > vp->GetValLen());
|
||||
} // end of FormatValue
|
||||
|
||||
/***********************************************************************/
|
||||
/* BINVAL SetFormat function (used to set SELECT output format). */
|
||||
/***********************************************************************/
|
||||
bool BINVAL::SetConstFormat(PGLOBAL g, FORMAT& fmt)
|
||||
{
|
||||
fmt.Type[0] = 'B';
|
||||
fmt.Length = Clen;
|
||||
fmt.Prec = 0;
|
||||
return false;
|
||||
} // end of SetConstFormat
|
||||
|
||||
/* -------------------------- Class DTVAL ---------------------------- */
|
||||
|
||||
/***********************************************************************/
|
||||
|
@@ -1,7 +1,7 @@
|
||||
/**************** Value H Declares Source Code File (.H) ***************/
|
||||
/* Name: VALUE.H Version 2.0 */
|
||||
/* Name: VALUE.H Version 2.1 */
|
||||
/* */
|
||||
/* (C) Copyright to the author Olivier BERTRAND 2001-2013 */
|
||||
/* (C) Copyright to the author Olivier BERTRAND 2001-2014 */
|
||||
/* */
|
||||
/* This file contains the VALUE and derived classes declares. */
|
||||
/***********************************************************************/
|
||||
@@ -285,6 +285,63 @@ class DllExport DECVAL: public TYPVAL<PSZ> {
|
||||
// Members
|
||||
}; // end of class DECVAL
|
||||
|
||||
/***********************************************************************/
|
||||
/* Specific BINARY class. */
|
||||
/***********************************************************************/
|
||||
class DllExport BINVAL: public VALUE {
|
||||
public:
|
||||
// Constructors
|
||||
//BINVAL(void *p);
|
||||
BINVAL(PGLOBAL g, void *p, int cl, int n);
|
||||
|
||||
// Implementation
|
||||
virtual bool IsTypeNum(void) {return false;}
|
||||
virtual bool IsZero(void);
|
||||
virtual void Reset(void);
|
||||
virtual int GetValLen(void) {return Clen;};
|
||||
virtual int GetValPrec() {return 0;}
|
||||
virtual int GetSize(void) {return Len;}
|
||||
virtual PSZ GetCharValue(void) {return (PSZ)Binp;}
|
||||
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);
|
||||
virtual void *GetTo_Val(void) {return Binp;}
|
||||
|
||||
// Methods
|
||||
virtual bool SetValue_pval(PVAL valp, bool chktype);
|
||||
virtual bool SetValue_char(char *p, int n);
|
||||
virtual void SetValue_psz(PSZ s);
|
||||
virtual void SetValue_pvblk(PVBLK blk, int n);
|
||||
virtual void SetValue(char c);
|
||||
virtual void SetValue(uchar c);
|
||||
virtual void SetValue(short i);
|
||||
virtual void SetValue(ushort i);
|
||||
virtual void SetValue(int n);
|
||||
virtual void SetValue(uint n);
|
||||
virtual void SetValue(longlong n);
|
||||
virtual void SetValue(ulonglong n);
|
||||
virtual void SetValue(double f);
|
||||
virtual void SetBinValue(void *p);
|
||||
virtual bool GetBinValue(void *buf, int buflen, bool go);
|
||||
virtual int CompareValue(PVAL vp) {assert(false); return 0;}
|
||||
virtual char *ShowValue(char *buf, int);
|
||||
virtual char *GetCharString(char *p);
|
||||
virtual bool IsEqual(PVAL vp, bool chktype);
|
||||
virtual bool FormatValue(PVAL vp, char *fmt);
|
||||
virtual bool SetConstFormat(PGLOBAL, FORMAT&);
|
||||
|
||||
// Members
|
||||
void *Binp;
|
||||
char *Chrp;
|
||||
int Len;
|
||||
}; // end of class BINVAL
|
||||
|
||||
/***********************************************************************/
|
||||
/* Class DTVAL: represents a time stamp value. */
|
||||
/***********************************************************************/
|
||||
|
@@ -61,6 +61,9 @@
|
||||
/***********************************************************************/
|
||||
extern MBLOCK Nmblk; /* Used to initialize MBLOCK's */
|
||||
extern "C" int trace;
|
||||
#if defined(XMAP)
|
||||
extern bool xmap;
|
||||
#endif // XMAP
|
||||
|
||||
/***********************************************************************/
|
||||
/* Last two parameters are true to enable type checking, and last one */
|
||||
@@ -810,12 +813,16 @@ bool XINDEX::SaveIndex(PGLOBAL g, PIXDEF sxp)
|
||||
return rc;
|
||||
} // end of SaveIndex
|
||||
|
||||
#if !defined(XMAP)
|
||||
/***********************************************************************/
|
||||
/* Init: Open and Initialize a Key Index. */
|
||||
/***********************************************************************/
|
||||
bool XINDEX::Init(PGLOBAL g)
|
||||
{
|
||||
#if defined(XMAP)
|
||||
if (xmap)
|
||||
return MapInit(g);
|
||||
#endif // XMAP
|
||||
|
||||
/*********************************************************************/
|
||||
/* Table will be accessed through an index table. */
|
||||
/* If sorting is required, this will be done later. */
|
||||
@@ -1051,11 +1058,11 @@ err:
|
||||
return true;
|
||||
} // end of Init
|
||||
|
||||
#else // XMAP
|
||||
#if defined(XMAP)
|
||||
/***********************************************************************/
|
||||
/* Init: Open and Initialize a Key Index. */
|
||||
/***********************************************************************/
|
||||
bool XINDEX::Init(PGLOBAL g)
|
||||
bool XINDEX::MapInit(PGLOBAL g)
|
||||
{
|
||||
/*********************************************************************/
|
||||
/* Table will be accessed through an index table. */
|
||||
@@ -1256,7 +1263,7 @@ bool XINDEX::Init(PGLOBAL g)
|
||||
err:
|
||||
Close();
|
||||
return true;
|
||||
} // end of Init
|
||||
} // end of MapInit
|
||||
#endif // XMAP
|
||||
|
||||
/***********************************************************************/
|
||||
@@ -1563,6 +1570,46 @@ bool XINDEX::NextVal(bool eq)
|
||||
return (Cur_K == Num_K || (eq && neq <= Nval));
|
||||
} // end of NextVal
|
||||
|
||||
/***********************************************************************/
|
||||
/* XINDEX: Find Cur_K and Val_K's of previous index entry. */
|
||||
/* Returns false if Ok, true if there are no more values. */
|
||||
/***********************************************************************/
|
||||
bool XINDEX::PrevVal(void)
|
||||
{
|
||||
int n, neq = Nk + 1, curk;
|
||||
PXCOL kcp;
|
||||
|
||||
if (Cur_K == 0)
|
||||
return true;
|
||||
else
|
||||
curk = --Cur_K;
|
||||
|
||||
for (n = Nk, kcp = To_LastCol; kcp; n--, kcp = kcp->Previous) {
|
||||
if (kcp->Kof) {
|
||||
if (curk < kcp->Kof[kcp->Val_K])
|
||||
neq = n;
|
||||
|
||||
} else {
|
||||
#ifdef _DEBUG
|
||||
assert(curk == kcp->Val_K -1);
|
||||
#endif // _DEBUG
|
||||
neq = n;
|
||||
} // endif Kof
|
||||
|
||||
#ifdef _DEBUG
|
||||
assert(kcp->Val_K >= 0);
|
||||
#endif // _DEBUG
|
||||
|
||||
// If this is not a break...
|
||||
if (neq > n)
|
||||
break; // all previous columns have same value
|
||||
|
||||
curk = --kcp->Val_K; // This is a break, get new column value
|
||||
} // endfor kcp
|
||||
|
||||
return false;
|
||||
} // end of PrevVal
|
||||
|
||||
/***********************************************************************/
|
||||
/* XINDEX: Fetch a physical or logical record. */
|
||||
/***********************************************************************/
|
||||
@@ -1615,6 +1662,12 @@ int XINDEX::Fetch(PGLOBAL g)
|
||||
|
||||
Op = (Mul || Nval < Nk) ? OP_NXTDIF : OP_NEXT;
|
||||
break;
|
||||
case OP_LAST: // Read last key
|
||||
for (Cur_K = Num_K - 1, kp = To_KeyCol; kp; kp = kp->Next)
|
||||
kp->Val_K = kp->Kblp->GetNval() - 1;
|
||||
|
||||
Op = OP_NEXT;
|
||||
break;
|
||||
default: // Should be OP_EQ
|
||||
// if (Tbxp->Key_Rank < 0) {
|
||||
/***************************************************************/
|
||||
@@ -1851,6 +1904,25 @@ int XINDXS::GroupSize(void)
|
||||
: 1;
|
||||
} // end of GroupSize
|
||||
|
||||
/***********************************************************************/
|
||||
/* XINDXS: Find Cur_K and Val_K of previous index value. */
|
||||
/* Returns false if Ok, true if there are no more values. */
|
||||
/***********************************************************************/
|
||||
bool XINDXS::PrevVal(void)
|
||||
{
|
||||
if (--Cur_K < 0)
|
||||
return true;
|
||||
|
||||
if (Mul) {
|
||||
if (Cur_K < Pof[To_KeyCol->Val_K])
|
||||
To_KeyCol->Val_K--;
|
||||
|
||||
} else
|
||||
To_KeyCol->Val_K = Cur_K;
|
||||
|
||||
return false;
|
||||
} // end of PrevVal
|
||||
|
||||
/***********************************************************************/
|
||||
/* XINDXS: Find Cur_K and Val_K of next index value. */
|
||||
/* If b is true next value must be equal to last one. */
|
||||
@@ -1924,7 +1996,17 @@ int XINDXS::Fetch(PGLOBAL g)
|
||||
To_KeyCol->Val_K = Cur_K = 0;
|
||||
Op = (Mul) ? OP_NXTDIF : OP_NEXT;
|
||||
break;
|
||||
default: // Should OP_EQ
|
||||
case OP_LAST: // Read first
|
||||
Cur_K = Num_K - 1;
|
||||
To_KeyCol->Val_K = Ndif - 1;
|
||||
Op = OP_PREV;
|
||||
break;
|
||||
case OP_PREV: // Read previous
|
||||
if (PrevVal())
|
||||
return -1; // End of indexed file
|
||||
|
||||
break;
|
||||
default: // Should be OP_EQ
|
||||
/*****************************************************************/
|
||||
/* Look for the first key equal to the link column values */
|
||||
/* and return its rank whithin the index table. */
|
||||
@@ -2837,7 +2919,8 @@ BYTE* KXYCOL::MapInit(PGLOBAL g, PCOL colp, int *n, BYTE *m)
|
||||
} // endif n[1]
|
||||
|
||||
Ndf = n[0];
|
||||
IsSorted = colp->GetOpt() < 0;
|
||||
//IsSorted = colp->GetOpt() < 0;
|
||||
IsSorted = false;
|
||||
return m + Bkeys.Size + Keys.Size + Koff.Size;
|
||||
} // end of MapInit
|
||||
#endif // XMAP
|
||||
|
@@ -192,9 +192,13 @@ class DllExport XXBASE : public CSORT, public BLOCK {
|
||||
virtual void Print(PGLOBAL g, FILE *f, uint n);
|
||||
virtual void Print(PGLOBAL g, char *ps, uint z);
|
||||
virtual bool Init(PGLOBAL g) = 0;
|
||||
#if defined(XMAP)
|
||||
virtual bool MapInit(PGLOBAL g) = 0;
|
||||
#endif // XMAP
|
||||
virtual int MaxRange(void) {return 1;}
|
||||
virtual int Fetch(PGLOBAL g) = 0;
|
||||
virtual bool NextVal(bool eq) {return true;}
|
||||
virtual bool PrevVal(void) {return true;}
|
||||
virtual int FastFind(int nk) = 0;
|
||||
virtual bool Reorder(PGLOBAL g) {return true;}
|
||||
virtual int Range(PGLOBAL g, int limit = 0, bool incl = true)
|
||||
@@ -248,6 +252,9 @@ class DllExport XINDEX : public XXBASE {
|
||||
// Methods
|
||||
virtual void Reset(void);
|
||||
virtual bool Init(PGLOBAL g);
|
||||
#if defined(XMAP)
|
||||
virtual bool MapInit(PGLOBAL g);
|
||||
#endif // XMAP
|
||||
virtual int Qcompare(int *, int *);
|
||||
virtual int Fetch(PGLOBAL g);
|
||||
virtual int FastFind(int nk);
|
||||
@@ -257,6 +264,7 @@ class DllExport XINDEX : public XXBASE {
|
||||
virtual int ColMaxSame(PXCOL kp);
|
||||
virtual void Close(void);
|
||||
virtual bool NextVal(bool eq);
|
||||
virtual bool PrevVal(void);
|
||||
virtual bool Make(PGLOBAL g, PIXDEF sxp);
|
||||
virtual bool SaveIndex(PGLOBAL g, PIXDEF sxp);
|
||||
virtual bool Reorder(PGLOBAL g);
|
||||
@@ -296,6 +304,7 @@ class DllExport XINDXS : public XINDEX {
|
||||
virtual int Fetch(PGLOBAL g);
|
||||
virtual int FastFind(int nk);
|
||||
virtual bool NextVal(bool eq);
|
||||
virtual bool PrevVal(void);
|
||||
virtual int Range(PGLOBAL g, int limit = 0, bool incl = true);
|
||||
virtual int GroupSize(void);
|
||||
|
||||
@@ -403,6 +412,9 @@ class DllExport XXROW : public XXBASE {
|
||||
|
||||
// Methods
|
||||
virtual bool Init(PGLOBAL g);
|
||||
#if defined(XMAP)
|
||||
virtual bool MapInit(PGLOBAL g) {return true;}
|
||||
#endif // XMAP
|
||||
virtual int Fetch(PGLOBAL g);
|
||||
virtual int FastFind(int nk);
|
||||
virtual int MaxRange(void) {return 1;}
|
||||
|
Reference in New Issue
Block a user