Commit e049f923 authored by Olivier Bertrand's avatar Olivier Bertrand Committed by Sergei Golubchik

Squashed commit of connect/10.0:

commit ac275d0b4ad (connect/10.0)
Author: Olivier Bertrand <bertrandop@gmail.com>
Date:   Wed Mar 27 12:46:20 2019 +0100

    Comment out unrecognized command line options: Modified CMakeLists.txt

commit 592f1f75ad6
Author: Olivier Bertrand <bertrandop@gmail.com>
Date:   Tue Mar 26 19:52:33 2019 +0100

    Replace Command not recognized by CMake modified: CMakeLists.txt

commit 00f72199b16
Author: Olivier Bertrand <bertrandop@gmail.com>
Date:   Tue Mar 26 18:15:08 2019 +0100

    - Fix MDEV-15793: Server crash in PlugCloseFile with sql_mode=''
      Fixed by replacing sprinf by snprintf in ShowValue to avoid
      buffer overflow. It nows always use a buffer and returns int.
      modified:   storage/connect/tabdos.cpp
      modified:   storage/connect/tabfmt.cpp
      modified:   storage/connect/value.cpp
      modified:   storage/connect/value.h

    - Fix MDEV-18292: CONNECT Engine JDBC not able to issue
      simple UPDATE statement from trigger or stored procedure
      Was not fixed when the same table was called several times
      with different modes. Fixed by checking if a new statement
      is compatible in the start_stmt function. It nows do the
      same checks than external_lock.
      modified:   storage/connect/ha_connect.cc
      modified:   storage/connect/ha_connect.h

    - typo
      modified:   storage/connect/user_connect.cc

    - Fix GetTableName that returned wrong value under Windows
      modified:   storage/connect/ha_connect.cc

    - Fix MDEV-13136: enhance CREATE SERVER MyServerName
      FOREIGN DATA WRAPPER to work with CONNECT engine
      modified:   storage/connect/tabjdbc.cpp

    - Add a function to retrieve User variable value (DEVELOPMENT only)
      modified:   storage/connect/ha_connect.cc
      modified:   storage/connect/jsonudf.cpp
      modified:   storage/connect/jsonudf.h
      modified:   storage/connect/tabjdbc.cpp

    - Fix MDEV-18192: CONNECT Engine JDBC not able to issue
      simple UPDATE statement from trigger or stored procedure
      modified:   storage/connect/tabext.cpp
      modified:   storage/connect/tabext.h
      modified:   storage/connect/tabjdbc.cpp

    - Enable CONNECT tables to have triggers
      Update version number
      modified:   storage/connect/ha_connect.cc

    - Make user and password defined in CREATE TABLE have precedence on
      the ones specified in a Federated Server.
      modified:   storage/connect/tabjdbc.cpp

    - JSONColumns: Copy locally constant strings to fix error in OEM modules
      modified:   storage/connect/tabjson.cpp

commit 99de7f4e486
Author: Olivier Bertrand <bertrandop@gmail.com>
Date:   Sun Jan 27 15:16:15 2019 +0100

    - Fix MDEV-18192: CONNECT Engine JDBC not able to issue
      simple UPDATE statement from trigger or stored procedure
      modified:   storage/connect/tabext.cpp
      modified:   storage/connect/tabext.h
      modified:   storage/connect/tabjdbc.cpp

    - Enable CONNECT tables to have triggers
      Update version number
      modified:   storage/connect/ha_connect.cc

    - Make user and password defined in CREATE TABLE have precedence on
      the ones specified in a Federated Server.
      modified:   storage/connect/tabjdbc.cpp

    - JSONColumns: Copy locally constant strings to fix error in OEM modules
      modified:   storage/connect/tabjson.cpp
parent 52eb4f17
...@@ -130,7 +130,6 @@ IF(WIN32) ...@@ -130,7 +130,6 @@ IF(WIN32)
OPTION(CONNECT_WITH_MSXML "Compile CONNECT storage engine with MSXML support" ON) OPTION(CONNECT_WITH_MSXML "Compile CONNECT storage engine with MSXML support" ON)
IF(CONNECT_WITH_MSXML) IF(CONNECT_WITH_MSXML)
add_definitions(-DMSX6 -DDOMDOC_SUPPORT) add_definitions(-DMSX6 -DDOMDOC_SUPPORT)
message(STATUS "MSXML library version: msxml6")
SET(MSXML_FOUND 1) SET(MSXML_FOUND 1)
SET(CONNECT_SOURCES ${CONNECT_SOURCES} domdoc.cpp domdoc.h) SET(CONNECT_SOURCES ${CONNECT_SOURCES} domdoc.cpp domdoc.h)
ENDIF(CONNECT_WITH_MSXML) ENDIF(CONNECT_WITH_MSXML)
...@@ -238,7 +237,7 @@ ENDIF(CONNECT_WITH_ODBC) ...@@ -238,7 +237,7 @@ ENDIF(CONNECT_WITH_ODBC)
# #
# JDBC with MongoDB Java Driver included but disabled if without MONGO # JDBC with MongoDB Java Driver included but disabled if without MONGO
# #
#OPTION(CONNECT_WITH_MONGO "Compile CONNECT storage engine with MONGO support" ON) OPTION(CONNECT_WITH_MONGO "Compile CONNECT storage engine with MONGO support" ON)
OPTION(CONNECT_WITH_JDBC "Compile CONNECT storage engine with JDBC support" ON) OPTION(CONNECT_WITH_JDBC "Compile CONNECT storage engine with JDBC support" ON)
IF(CONNECT_WITH_JDBC) IF(CONNECT_WITH_JDBC)
...@@ -293,7 +292,7 @@ IF(CONNECT_WITH_MONGO) ...@@ -293,7 +292,7 @@ IF(CONNECT_WITH_MONGO)
C:/mongo-c-driver/lib C:/mongo-c-driver/lib
D:/mongo-c-driver/lib) D:/mongo-c-driver/lib)
ENDIF(WIN32) ENDIF(WIN32)
FIND_PACKAGE(libmongoc-1.0 1.7) FIND_PACKAGE(libmongoc-1.0 1.7 QUIET)
IF (libmongoc-1.0_FOUND) IF (libmongoc-1.0_FOUND)
INCLUDE_DIRECTORIES(${MONGOC_INCLUDE_DIRS}) INCLUDE_DIRECTORIES(${MONGOC_INCLUDE_DIRS})
SET(MONGOC_LIBRARY ${MONGOC_LIBRARIES}) SET(MONGOC_LIBRARY ${MONGOC_LIBRARIES})
......
...@@ -170,9 +170,9 @@ ...@@ -170,9 +170,9 @@
#define JSONMAX 10 // JSON Default max grp size #define JSONMAX 10 // JSON Default max grp size
extern "C" { extern "C" {
char version[]= "Version 1.06.0008 October 06, 2018"; char version[]= "Version 1.06.0009 January 27, 2019";
#if defined(__WIN__) #if defined(__WIN__)
char compver[]= "Version 1.06.0008 " __DATE__ " " __TIME__; char compver[]= "Version 1.06.0009 " __DATE__ " " __TIME__;
char slash= '\\'; char slash= '\\';
#else // !__WIN__ #else // !__WIN__
char slash= '/'; char slash= '/';
...@@ -204,6 +204,26 @@ pthread_mutex_t parmut; ...@@ -204,6 +204,26 @@ pthread_mutex_t parmut;
pthread_mutex_t usrmut; pthread_mutex_t usrmut;
pthread_mutex_t tblmut; pthread_mutex_t tblmut;
#if defined(DEVELOPMENT)
char *GetUserVariable(PGLOBAL g, const uchar *varname);
char *GetUserVariable(PGLOBAL g, const uchar *varname)
{
char buf[1024];
bool b;
THD *thd = current_thd;
CHARSET_INFO *cs = system_charset_info;
String *str = NULL, tmp(buf, sizeof(buf), cs);
HASH uvars = thd->user_vars;
user_var_entry *uvar = (user_var_entry*)my_hash_search(&uvars, varname, 0);
if (uvar)
str = uvar->val_str(&b, &tmp, NOT_FIXED_DEC);
return str ? PlugDup(g, str->ptr()) : NULL;
}; // end of GetUserVariable
#endif // DEVELOPMENT
/***********************************************************************/ /***********************************************************************/
/* Utility functions. */ /* Utility functions. */
/***********************************************************************/ /***********************************************************************/
...@@ -1795,7 +1815,9 @@ PCSZ ha_connect::GetDBName(PCSZ name) ...@@ -1795,7 +1815,9 @@ PCSZ ha_connect::GetDBName(PCSZ name)
const char *ha_connect::GetTableName(void) const char *ha_connect::GetTableName(void)
{ {
return tshp ? tshp->table_name.str : table_share->table_name.str; const char *path= tshp ? tshp->path.str : table_share->path.str;
const char *name= strrchr(path, slash);
return name ? name+1 : path;
} // end of GetTableName } // end of GetTableName
char *ha_connect::GetPartName(void) char *ha_connect::GetPartName(void)
...@@ -1914,9 +1936,11 @@ int ha_connect::OpenTable(PGLOBAL g, bool del) ...@@ -1914,9 +1936,11 @@ int ha_connect::OpenTable(PGLOBAL g, bool del)
break; break;
} // endswitch xmode } // endswitch xmode
if (xmod != MODE_INSERT || tdbp->GetAmType() == TYPE_AM_MYSQL // g->More is 1 when executing commands from triggers
if (!g->More && (xmod != MODE_INSERT
|| tdbp->GetAmType() == TYPE_AM_MYSQL
|| tdbp->GetAmType() == TYPE_AM_ODBC || tdbp->GetAmType() == TYPE_AM_ODBC
|| tdbp->GetAmType() == TYPE_AM_JDBC) { || tdbp->GetAmType() == TYPE_AM_JDBC)) {
// Get the list of used fields (columns) // Get the list of used fields (columns)
char *p; char *p;
unsigned int k1, k2, n1, n2; unsigned int k1, k2, n1, n2;
...@@ -4631,6 +4655,8 @@ MODE ha_connect::CheckMode(PGLOBAL g, THD *thd, ...@@ -4631,6 +4655,8 @@ MODE ha_connect::CheckMode(PGLOBAL g, THD *thd,
break; break;
case SQLCOM_CREATE_VIEW: case SQLCOM_CREATE_VIEW:
case SQLCOM_DROP_VIEW: case SQLCOM_DROP_VIEW:
case SQLCOM_CREATE_TRIGGER:
case SQLCOM_DROP_TRIGGER:
newmode= MODE_ANY; newmode= MODE_ANY;
break; break;
case SQLCOM_ALTER_TABLE: case SQLCOM_ALTER_TABLE:
...@@ -4701,8 +4727,24 @@ int ha_connect::start_stmt(THD *thd, thr_lock_type lock_type) ...@@ -4701,8 +4727,24 @@ int ha_connect::start_stmt(THD *thd, thr_lock_type lock_type)
break; break;
} // endswitch mode } // endswitch mode
xmod= CheckMode(g, thd, newmode, &chk, &cras); if (newmode == MODE_ANY) {
DBUG_RETURN((xmod == MODE_ERROR) ? HA_ERR_INTERNAL_ERROR : 0); if (CloseTable(g)) {
// Make error a warning to avoid crash
push_warning(thd, Sql_condition::WARN_LEVEL_WARN, 0, g->Message);
rc = 0;
} // endif Close
locked = 0;
xmod = MODE_ANY; // For info commands
DBUG_RETURN(rc);
} // endif MODE_ANY
newmode = CheckMode(g, thd, newmode, &chk, &cras);
if (newmode == MODE_ERROR)
DBUG_RETURN(HA_ERR_INTERNAL_ERROR);
DBUG_RETURN(check_stmt(g, newmode, cras));
} // end of start_stmt } // end of start_stmt
/** /**
...@@ -4884,17 +4926,12 @@ int ha_connect::external_lock(THD *thd, int lock_type) ...@@ -4884,17 +4926,12 @@ int ha_connect::external_lock(THD *thd, int lock_type)
// Make it a warning to avoid crash // Make it a warning to avoid crash
push_warning(thd, Sql_condition::WARN_LEVEL_WARN, 0, g->Message); push_warning(thd, Sql_condition::WARN_LEVEL_WARN, 0, g->Message);
rc= 0; rc= 0;
//my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0));
//rc = HA_ERR_INTERNAL_ERROR;
} // endif Close } // endif Close
locked= 0; locked= 0;
// m_lock_type= lock_type;
xmod= MODE_ANY; // For info commands xmod= MODE_ANY; // For info commands
DBUG_RETURN(rc); DBUG_RETURN(rc);
} // endif MODE_ANY } else if (check_privileges(thd, options, table->s->db.str)) {
else
if (check_privileges(thd, options, table->s->db.str)) {
strcpy(g->Message, "This operation requires the FILE privilege"); strcpy(g->Message, "This operation requires the FILE privilege");
htrc("%s\n", g->Message); htrc("%s\n", g->Message);
DBUG_RETURN(HA_ERR_INTERNAL_ERROR); DBUG_RETURN(HA_ERR_INTERNAL_ERROR);
...@@ -4909,42 +4946,30 @@ int ha_connect::external_lock(THD *thd, int lock_type) ...@@ -4909,42 +4946,30 @@ int ha_connect::external_lock(THD *thd, int lock_type)
if (newmode == MODE_ERROR) if (newmode == MODE_ERROR)
DBUG_RETURN(HA_ERR_INTERNAL_ERROR); DBUG_RETURN(HA_ERR_INTERNAL_ERROR);
DBUG_RETURN(check_stmt(g, newmode, cras));
} // end of external_lock
int ha_connect::check_stmt(PGLOBAL g, MODE newmode, bool cras)
{
int rc = 0;
DBUG_ENTER("ha_connect::check_stmt");
// If this is the start of a new query, cleanup the previous one // If this is the start of a new query, cleanup the previous one
if (xp->CheckCleanup()) { if (xp->CheckCleanup()) {
tdbp= NULL; tdbp= NULL;
valid_info= false; valid_info= false;
} // endif CheckCleanup } // endif CheckCleanup
#if 0
if (xcheck) {
// This must occur after CheckCleanup
if (!g->Xchk) {
g->Xchk= new(g) XCHK;
((PCHK)g->Xchk)->oldsep= GetBooleanOption("Sepindex", false);
((PCHK)g->Xchk)->oldpix= GetIndexInfo();
} // endif Xchk
} else
g->Xchk= NULL;
#endif // 0
if (cras) if (cras)
g->Createas= 1; // To tell external tables of a multi-table command g->Createas= 1; // To tell external tables of a multi-table command
if (trace(1)) { if (trace(1))
#if 0
htrc("xcheck=%d cras=%d\n", xcheck, cras);
if (xcheck)
htrc("oldsep=%d oldpix=%p\n",
((PCHK)g->Xchk)->oldsep, ((PCHK)g->Xchk)->oldpix);
#endif // 0
htrc("Calling CntCheckDB db=%s cras=%d\n", GetDBName(NULL), cras); htrc("Calling CntCheckDB db=%s cras=%d\n", GetDBName(NULL), cras);
} // endif trace
// Set or reset the good database environment // Set or reset the good database environment
if (CntCheckDB(g, this, GetDBName(NULL))) { if (CntCheckDB(g, this, GetDBName(NULL))) {
htrc("%p external_lock: %s\n", this, g->Message); htrc("%p check_stmt: %s\n", this, g->Message);
rc= HA_ERR_INTERNAL_ERROR; rc= HA_ERR_INTERNAL_ERROR;
// This can NOT be called without open called first, but // This can NOT be called without open called first, but
// the table can have been closed since then // the table can have been closed since then
...@@ -4965,10 +4990,10 @@ int ha_connect::external_lock(THD *thd, int lock_type) ...@@ -4965,10 +4990,10 @@ int ha_connect::external_lock(THD *thd, int lock_type)
} // endif tdbp } // endif tdbp
if (trace(1)) if (trace(1))
htrc("external_lock: rc=%d\n", rc); htrc("check_stmt: rc=%d\n", rc);
DBUG_RETURN(rc); DBUG_RETURN(rc);
} // end of external_lock } // end of check_stmt
/** /**
...@@ -7310,7 +7335,7 @@ maria_declare_plugin(connect) ...@@ -7310,7 +7335,7 @@ maria_declare_plugin(connect)
0x0106, /* version number (1.06) */ 0x0106, /* version number (1.06) */
NULL, /* status variables */ NULL, /* status variables */
connect_system_variables, /* system variables */ connect_system_variables, /* system variables */
"1.06.0008", /* string version */ "1.06.0009", /* string version */
MariaDB_PLUGIN_MATURITY_STABLE /* maturity */ MariaDB_PLUGIN_MATURITY_STABLE /* maturity */
} }
maria_declare_plugin_end; maria_declare_plugin_end;
...@@ -511,6 +511,7 @@ int index_prev(uchar *buf); ...@@ -511,6 +511,7 @@ int index_prev(uchar *buf);
protected: protected:
bool check_privileges(THD *thd, PTOS options, char *dbn, bool quick=false); bool check_privileges(THD *thd, PTOS options, char *dbn, bool quick=false);
MODE CheckMode(PGLOBAL g, THD *thd, MODE newmode, bool *chk, bool *cras); MODE CheckMode(PGLOBAL g, THD *thd, MODE newmode, bool *chk, bool *cras);
int check_stmt(PGLOBAL g, MODE newmode, bool cras);
char *GetDBfromName(const char *name); char *GetDBfromName(const char *name);
// Members // Members
......
...@@ -299,4 +299,3 @@ class JVALUE : public JSON { ...@@ -299,4 +299,3 @@ class JVALUE : public JSON {
PJVAL Next; // Next value in array PJVAL Next; // Next value in array
bool Del; // True when deleted bool Del; // True when deleted
}; // end of class JVALUE }; // end of class JVALUE
...@@ -1666,7 +1666,8 @@ static PCSZ MakeKey(PGLOBAL g, UDF_ARGS *args, int i) ...@@ -1666,7 +1666,8 @@ static PCSZ MakeKey(PGLOBAL g, UDF_ARGS *args, int i)
if (args->arg_count > (unsigned)i) { if (args->arg_count > (unsigned)i) {
int j = 0, n = args->attribute_lengths[i]; int j = 0, n = args->attribute_lengths[i];
my_bool b; // true if attribute is zero terminated my_bool b; // true if attribute is zero terminated
PSZ p, s = args->attributes[i]; PSZ p;
PCSZ s = args->attributes[i];
if (s && *s && (n || *s == '\'')) { if (s && *s && (n || *s == '\'')) {
if ((b = (!n || !s[n]))) if ((b = (!n || !s[n])))
...@@ -5805,6 +5806,52 @@ char *envar(UDF_INIT *initid, UDF_ARGS *args, char *result, ...@@ -5805,6 +5806,52 @@ char *envar(UDF_INIT *initid, UDF_ARGS *args, char *result,
return str; return str;
} // end of envar } // end of envar
#if defined(DEVELOPMENT)
extern char *GetUserVariable(PGLOBAL g, const uchar *varname);
/*********************************************************************************/
/* Utility function returning a user variable value. */
/*********************************************************************************/
my_bool uvar_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
{
unsigned long reslen, memlen;
if (args->arg_count != 1) {
strcpy(message, "Unique argument must be a user variable name");
return true;
} else
CalcLen(args, false, reslen, memlen, true);
initid->maybe_null = true;
return JsonInit(initid, args, message, true, reslen, memlen, 2048);
} // end of uvar_init
char *uvar(UDF_INIT *initid, UDF_ARGS *args, char *result,
unsigned long *res_length, char *is_null, char *)
{
char *str, varname[256];
PGLOBAL g = (PGLOBAL)initid->ptr;
int n = MY_MIN(args->lengths[0], sizeof(varname) - 1);
PlugSubSet(g->Sarea, g->Sarea_Size);
memcpy(varname, args->args[0], n);
varname[n] = 0;
if (!(str = GetUserVariable(g, (const uchar*)&varname))) {
*res_length = 0;
*is_null = 1;
} else
*res_length = strlen(str);
return str;
} // end of uvar
void uvar_deinit(UDF_INIT* initid)
{
JsonFreeMem((PGLOBAL)initid->ptr);
} // end of uvar_deinit
#endif // DEVELOPMENT
/*********************************************************************************/ /*********************************************************************************/
/* Returns the distinct number of B occurences in A. */ /* Returns the distinct number of B occurences in A. */
/*********************************************************************************/ /*********************************************************************************/
...@@ -5851,4 +5898,3 @@ long long countin(UDF_INIT *initid, UDF_ARGS *args, char *result, ...@@ -5851,4 +5898,3 @@ long long countin(UDF_INIT *initid, UDF_ARGS *args, char *result,
free(str2); free(str2);
return n; return n;
} // end of countin } // end of countin
/************* TabDos C++ Program Source Code File (.CPP) **************/ /************* TabDos C++ Program Source Code File (.CPP) **************/
/* PROGRAM NAME: TABDOS */ /* PROGRAM NAME: TABDOS */
/* ------------- */ /* ------------- */
/* Version 4.9.3 */ /* Version 4.9.4 */
/* */ /* */
/* COPYRIGHT: */ /* COPYRIGHT: */
/* ---------- */ /* ---------- */
/* (C) Copyright to the author Olivier BERTRAND 1998-2017 */ /* (C) Copyright to the author Olivier BERTRAND 1998-2019 */
/* */ /* */
/* WHAT THIS PROGRAM DOES: */ /* WHAT THIS PROGRAM DOES: */
/* ----------------------- */ /* ----------------------- */
...@@ -2493,7 +2493,9 @@ bool DOSCOL::SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check) ...@@ -2493,7 +2493,9 @@ bool DOSCOL::SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check)
// Allocate the buffer used in WriteColumn for numeric columns // Allocate the buffer used in WriteColumn for numeric columns
if (!Buf && IsTypeNum(Buf_Type)) if (!Buf && IsTypeNum(Buf_Type))
Buf = (char*)PlugSubAlloc(g, NULL, MY_MAX(32, Long + Dcm + 1)); Buf = (char*)PlugSubAlloc(g, NULL, MY_MAX(64, Long + 1));
else // Text columns do not need additional buffer
Buf = (char*)Value->GetTo_Val();
// Because Colblk's have been made from a copy of the original TDB in // Because Colblk's have been made from a copy of the original TDB in
// case of Update, we must reset them to point to the original one. // case of Update, we must reset them to point to the original one.
...@@ -2603,8 +2605,8 @@ void DOSCOL::ReadColumn(PGLOBAL g) ...@@ -2603,8 +2605,8 @@ void DOSCOL::ReadColumn(PGLOBAL g)
/***********************************************************************/ /***********************************************************************/
void DOSCOL::WriteColumn(PGLOBAL g) void DOSCOL::WriteColumn(PGLOBAL g)
{ {
char *p, *p2, fmt[32]; char *p, fmt[32];
int i, k, len, field; int i, k, n, len, field;
PTDBDOS tdbp = (PTDBDOS)To_Tdb; PTDBDOS tdbp = (PTDBDOS)To_Tdb;
if (trace(2)) if (trace(2))
...@@ -2679,8 +2681,8 @@ void DOSCOL::WriteColumn(PGLOBAL g) ...@@ -2679,8 +2681,8 @@ void DOSCOL::WriteColumn(PGLOBAL g)
case TYPE_DOUBLE: case TYPE_DOUBLE:
case TYPE_DECIM: case TYPE_DECIM:
strcpy(fmt, (Ldz) ? "%0*.*lf" : "%*.*lf"); strcpy(fmt, (Ldz) ? "%0*.*lf" : "%*.*lf");
sprintf(Buf, fmt, field + ((Nod && Dcm) ? 1 : 0), len = field + ((Nod && Dcm) ? 1 : 0);
Dcm, Value->GetFloatValue()); snprintf(Buf, len, fmt, len, Dcm, Value->GetFloatValue());
len = strlen(Buf); len = strlen(Buf);
if (Nod && Dcm) if (Nod && Dcm)
...@@ -2699,35 +2701,37 @@ void DOSCOL::WriteColumn(PGLOBAL g) ...@@ -2699,35 +2701,37 @@ void DOSCOL::WriteColumn(PGLOBAL g)
throw 31; throw 31;
} // endswitch BufType } // endswitch BufType
p2 = Buf; n = strlen(Buf);
} else // Standard CONNECT format } else // Standard CONNECT format
p2 = Value->ShowValue(Buf, field); n = Value->ShowValue(Buf, field);
if (trace(1)) if (trace(1))
htrc("new length(%p)=%d\n", p2, strlen(p2)); htrc("new length(%p)=%d\n", Buf, n);
if ((len = strlen(p2)) > field) { if ((len = n) > field) {
sprintf(g->Message, MSG(VALUE_TOO_LONG), p2, Name, field); char *p = Value->GetCharString(Buf);
sprintf(g->Message, MSG(VALUE_TOO_LONG), p, Name, field);
throw 31; throw 31;
} else if (Dsp) } else if (Dsp)
for (i = 0; i < len; i++) for (i = 0; i < len; i++)
if (p2[i] == '.') if (Buf[i] == '.')
p2[i] = Dsp; Buf[i] = Dsp;
if (trace(2)) if (trace(2))
htrc("buffer=%s\n", p2); htrc("buffer=%s\n", Buf);
/*******************************************************************/ /*******************************************************************/
/* Updating must be done only when not in checking pass. */ /* Updating must be done only when not in checking pass. */
/*******************************************************************/ /*******************************************************************/
if (Status) { if (Status) {
memset(p, ' ', field); memset(p, ' ', field);
memcpy(p, p2, len); memcpy(p, Buf, len);
if (trace(2)) if (trace(2))
htrc(" col write: '%.*s'\n", len, p); htrc(" col write: '%.*s'\n", len, p);
} // endif Use } // endif Status
} else // BIN compressed table } else // BIN compressed table
/*******************************************************************/ /*******************************************************************/
......
/************* Tabext C++ Functions Source Code File (.CPP) ************/ /************* Tabext C++ Functions Source Code File (.CPP) ************/
/* Name: TABEXT.CPP Version 1.0 */ /* Name: TABEXT.CPP Version 1.1 */
/* */ /* */
/* (C) Copyright to the author Olivier BERTRAND 2017 */ /* (C) Copyright to the author Olivier BERTRAND 2017 - 2019 */
/* */ /* */
/* This file contains the TBX, TDB and OPJOIN classes functions. */ /* This file contains the TBX, TDB and OPJOIN classes functions. */
/***********************************************************************/ /***********************************************************************/
...@@ -445,6 +445,43 @@ bool TDBEXT::MakeSQL(PGLOBAL g, bool cnt) ...@@ -445,6 +445,43 @@ bool TDBEXT::MakeSQL(PGLOBAL g, bool cnt)
return false; return false;
} // end of MakeSQL } // end of MakeSQL
/***********************************************************************/
/* Remove the NAME_CONST functions that are added by procedures. */
/***********************************************************************/
void TDBEXT::RemoveConst(PGLOBAL g, char *stmt)
{
char *p, *p2;
char val[1025], nval[1025];
int n, nc;
while ((p = strstr(stmt, "NAME_CONST")))
if ((n = sscanf(p, "%*[^,],%1024[^)])%n", val, &nc))) {
if (trace(33))
htrc("p=%s\nn=%d val=%s nc=%d\n", p, n, val, nc);
*p = 0;
if ((p2 = strstr(val, "'"))) {
if ((n = sscanf(p2, "%*['\\]%1024[^'\\]", nval))) {
if (trace(33))
htrc("p2=%s\nn=%d nval=%s\n", p2, n, nval);
strcat(strcat(strcat(strcat(stmt, "'"), nval), "'"), p + nc);
} else
break;
} else
strcat(strcat(strcat(strcat(stmt, "("), val), ")"), p + nc);
if (trace(33))
htrc("stmt=%s\n", stmt);
} else
break;
return;
} // end of RemoveConst
/***********************************************************************/ /***********************************************************************/
/* MakeCommand: make the Update or Delete statement to send to the */ /* MakeCommand: make the Update or Delete statement to send to the */
/* MySQL server. Limited to remote values and filtering. */ /* MySQL server. Limited to remote values and filtering. */
...@@ -524,6 +561,8 @@ bool TDBEXT::MakeCommand(PGLOBAL g) ...@@ -524,6 +561,8 @@ bool TDBEXT::MakeCommand(PGLOBAL g)
stmt[i++] = (Qrystr[k] == '`') ? q : Qrystr[k]; stmt[i++] = (Qrystr[k] == '`') ? q : Qrystr[k];
} while (Qrystr[k++]); } while (Qrystr[k++]);
RemoveConst(g, stmt);
if (body) if (body)
strcat(stmt, body); strcat(stmt, body);
......
/*************** Tabext H Declares Source Code File (.H) ***************/ /*************** Tabext H Declares Source Code File (.H) ***************/
/* Name: TABEXT.H Version 1.0 */ /* Name: TABEXT.H Version 1.1 */
/* */ /* */
/* (C) Copyright to the author Olivier BERTRAND 2017 */ /* (C) Copyright to the author Olivier BERTRAND 2017 - 2019 */
/* */ /* */
/* This is the EXTDEF, TABEXT and EXTCOL classes definitions. */ /* This is the EXTDEF, TABEXT and EXTCOL classes definitions. */
/***********************************************************************/ /***********************************************************************/
...@@ -130,6 +130,7 @@ class DllExport TDBEXT : public TDB { ...@@ -130,6 +130,7 @@ class DllExport TDBEXT : public TDB {
virtual bool MakeSQL(PGLOBAL g, bool cnt); virtual bool MakeSQL(PGLOBAL g, bool cnt);
//virtual bool MakeInsert(PGLOBAL g); //virtual bool MakeInsert(PGLOBAL g);
virtual bool MakeCommand(PGLOBAL g); virtual bool MakeCommand(PGLOBAL g);
void RemoveConst(PGLOBAL g, char *stmt);
int Decode(PCSZ utf, char *buf, size_t n); int Decode(PCSZ utf, char *buf, size_t n);
// Members // Members
......
...@@ -1485,8 +1485,8 @@ void CSVCOL::ReadColumn(PGLOBAL g) ...@@ -1485,8 +1485,8 @@ void CSVCOL::ReadColumn(PGLOBAL g)
/***********************************************************************/ /***********************************************************************/
void CSVCOL::WriteColumn(PGLOBAL g) void CSVCOL::WriteColumn(PGLOBAL g)
{ {
char *p, buf[64]; char *p;
int flen; int n, flen;
PTDBCSV tdbp = (PTDBCSV)To_Tdb; PTDBCSV tdbp = (PTDBCSV)To_Tdb;
if (trace(2)) if (trace(2))
...@@ -1508,13 +1508,14 @@ void CSVCOL::WriteColumn(PGLOBAL g) ...@@ -1508,13 +1508,14 @@ void CSVCOL::WriteColumn(PGLOBAL g)
/*********************************************************************/ /*********************************************************************/
/* Get the string representation of the column value. */ /* Get the string representation of the column value. */
/*********************************************************************/ /*********************************************************************/
p = Value->ShowValue(buf); p = Value->GetCharString(Buf);
n = strlen(p);
if (trace(2)) if (trace(2))
htrc("new length(%p)=%d\n", p, strlen(p)); htrc("new length(%p)=%d\n", p, n);
if ((signed)strlen(p) > flen) { if (n > flen) {
sprintf(g->Message, MSG(BAD_FLD_LENGTH), Name, p, flen, sprintf(g->Message, MSG(BAD_FLD_LENGTH), Name, p, n,
tdbp->RowNumber(g), tdbp->GetFile(g)); tdbp->RowNumber(g), tdbp->GetFile(g));
throw 34; throw 34;
} else if (Dsp) } else if (Dsp)
......
/************* TabJDBC C++ Program Source Code File (.CPP) *************/ /************* TabJDBC C++ Program Source Code File (.CPP) *************/
/* PROGRAM NAME: TABJDBC */ /* PROGRAM NAME: TABJDBC */
/* ------------- */ /* ------------- */
/* Version 1.2 */ /* Version 1.3 */
/* */ /* */
/* COPYRIGHT: */ /* COPYRIGHT: */
/* ---------- */ /* ---------- */
/* (C) Copyright to the author Olivier BERTRAND 2016-2017 */ /* (C) Copyright to the author Olivier BERTRAND 2016-2019 */
/* */ /* */
/* WHAT THIS PROGRAM DOES: */ /* WHAT THIS PROGRAM DOES: */
/* ----------------------- */ /* ----------------------- */
...@@ -185,10 +185,10 @@ int JDBCDEF::ParseURL(PGLOBAL g, char *url, bool b) ...@@ -185,10 +185,10 @@ int JDBCDEF::ParseURL(PGLOBAL g, char *url, bool b)
} else // host is a URL } else // host is a URL
Url = PlugDup(g, server->host); Url = PlugDup(g, server->host);
if (server->username) if (!Username && server->username)
Username = PlugDup(g, server->username); Username = PlugDup(g, server->username);
if (server->password) if (!Password && server->password)
Password = PlugDup(g, server->password); Password = PlugDup(g, server->password);
return RC_NF; return RC_NF;
...@@ -558,9 +558,10 @@ bool TDBJDBC::OpenDB(PGLOBAL g) ...@@ -558,9 +558,10 @@ bool TDBJDBC::OpenDB(PGLOBAL g)
this, Tdb_No, Use, Mode); this, Tdb_No, Use, Mode);
if (Use == USE_OPEN) { if (Use == USE_OPEN) {
/*******************************************************************/ if (Mode == MODE_READ || Mode == MODE_READX) {
/*****************************************************************/
/* Table already open, just replace it at its beginning. */ /* Table already open, just replace it at its beginning. */
/*******************************************************************/ /*****************************************************************/
if (Memory == 1) { if (Memory == 1) {
if ((Qrp = Jcp->AllocateResult(g, this))) if ((Qrp = Jcp->AllocateResult(g, this)))
Memory = 2; // Must be filled Memory = 2; // Must be filled
...@@ -585,6 +586,14 @@ bool TDBJDBC::OpenDB(PGLOBAL g) ...@@ -585,6 +586,14 @@ bool TDBJDBC::OpenDB(PGLOBAL g)
CurNum = 0; CurNum = 0;
Fpos = 0; Fpos = 0;
Curpos = 1; Curpos = 1;
} else if (Mode == MODE_UPDATE || Mode == MODE_DELETE) {
// new update coming from a trigger or procedure
Query = NULL;
SetCondFil(NULL);
Qrystr = To_Def->GetStringCatInfo(g, "Query_String", "?");
} else { //if (Mode == MODE_INSERT)
} // endif Mode
return false; return false;
} // endif use } // endif use
......
/************* tabjson C++ Program Source Code File (.CPP) *************/ /************* tabjson C++ Program Source Code File (.CPP) *************/
/* PROGRAM NAME: tabjson Version 1.6 */ /* PROGRAM NAME: tabjson Version 1.7 */
/* (C) Copyright to the author Olivier BERTRAND 2014 - 2018 */ /* (C) Copyright to the author Olivier BERTRAND 2014 - 2019 */
/* This program are the JSON class DB execution routines. */ /* This program are the JSON class DB execution routines. */
/***********************************************************************/ /***********************************************************************/
...@@ -110,8 +110,8 @@ PQRYRES JSONColumns(PGLOBAL g, PCSZ db, PCSZ dsn, PTOS topt, bool info) ...@@ -110,8 +110,8 @@ PQRYRES JSONColumns(PGLOBAL g, PCSZ db, PCSZ dsn, PTOS topt, bool info)
buftyp, fldtyp, length, false, false); buftyp, fldtyp, length, false, false);
crp = qrp->Colresp->Next->Next->Next->Next->Next->Next; crp = qrp->Colresp->Next->Next->Next->Next->Next->Next;
crp->Name = "Nullable"; crp->Name = PlugDup(g, "Nullable");
crp->Next->Name = "Jpath"; crp->Next->Name = PlugDup(g, "Jpath");
if (info || !qrp) if (info || !qrp)
return qrp; return qrp;
......
...@@ -177,6 +177,7 @@ bool user_connect::CheckCleanup(bool force) ...@@ -177,6 +177,7 @@ bool user_connect::CheckCleanup(bool force)
g->Createas = 0; g->Createas = 0;
g->Alchecked = 0; g->Alchecked = 0;
g->Mrr = 0; g->Mrr = 0;
g->More = 0;
last_query_id= thdp->query_id; last_query_id= thdp->query_id;
if (trace(65) && !force) if (trace(65) && !force)
......
/************* Value C++ Functions Source Code File (.CPP) *************/ /************* Value C++ Functions Source Code File (.CPP) *************/
/* Name: VALUE.CPP Version 2.8 */ /* Name: VALUE.CPP Version 2.9 */
/* */ /* */
/* (C) Copyright to the author Olivier BERTRAND 2001-2017 */ /* (C) Copyright to the author Olivier BERTRAND 2001-2019 */
/* */ /* */
/* This file contains the VALUE and derived classes family functions. */ /* This file contains the VALUE and derived classes family functions. */
/* These classes contain values of different types. They are used so */ /* These classes contain values of different types. They are used so */
...@@ -882,18 +882,16 @@ bool TYPVAL<TYPE>::GetBinValue(void *buf, int buflen, bool go) ...@@ -882,18 +882,16 @@ bool TYPVAL<TYPE>::GetBinValue(void *buf, int buflen, bool go)
/* TYPVAL ShowValue: get string representation of a typed value. */ /* TYPVAL ShowValue: get string representation of a typed value. */
/***********************************************************************/ /***********************************************************************/
template <class TYPE> template <class TYPE>
char *TYPVAL<TYPE>::ShowValue(char *buf, int len) int TYPVAL<TYPE>::ShowValue(char *buf, int len)
{ {
sprintf(buf, Xfmt, len, Tval); return snprintf(buf, len + 1, Xfmt, len, Tval);
return buf;
} // end of ShowValue } // end of ShowValue
template <> template <>
char *TYPVAL<double>::ShowValue(char *buf, int len) int TYPVAL<double>::ShowValue(char *buf, int len)
{ {
// TODO: use snprintf to avoid possible overflow // TODO: use a more appropriate format to avoid possible truncation
sprintf(buf, Xfmt, len, Prec, Tval); return snprintf(buf, len + 1, Xfmt, len, Prec, Tval);
return buf;
} // end of ShowValue } // end of ShowValue
/***********************************************************************/ /***********************************************************************/
...@@ -1588,10 +1586,17 @@ bool TYPVAL<PSZ>::GetBinValue(void *buf, int buflen, bool go) ...@@ -1588,10 +1586,17 @@ bool TYPVAL<PSZ>::GetBinValue(void *buf, int buflen, bool go)
/***********************************************************************/ /***********************************************************************/
/* STRING ShowValue: get string representation of a char value. */ /* STRING ShowValue: get string representation of a char value. */
/***********************************************************************/ /***********************************************************************/
char *TYPVAL<PSZ>::ShowValue(char *, int) int TYPVAL<PSZ>::ShowValue(char *buf, int buflen)
{ {
return Strp; int len = (Null) ? 0 : strlen(Strp);
} // end of ShowValue
if (buf && buf != Strp) {
memset(buf, ' ', buflen + 1);
memcpy(buf, Strp, MY_MIN(len, buflen));
} // endif buf
return len;
} // end of ShowValue
/***********************************************************************/ /***********************************************************************/
/* STRING GetCharString: get string representation of a char value. */ /* STRING GetCharString: get string representation of a char value. */
...@@ -1800,10 +1805,9 @@ void DECVAL::Reset(void) ...@@ -1800,10 +1805,9 @@ void DECVAL::Reset(void)
/***********************************************************************/ /***********************************************************************/
/* DECIMAL ShowValue: get string representation right justified. */ /* DECIMAL ShowValue: get string representation right justified. */
/***********************************************************************/ /***********************************************************************/
char *DECVAL::ShowValue(char *buf, int len) int DECVAL::ShowValue(char *buf, int len)
{ {
sprintf(buf, Xfmt, len, Strp); return snprintf(buf, len + 1, Xfmt, len, Strp);
return buf;
} // end of ShowValue } // end of ShowValue
/***********************************************************************/ /***********************************************************************/
...@@ -1868,14 +1872,13 @@ int DECVAL::CompareValue(PVAL vp) ...@@ -1868,14 +1872,13 @@ int DECVAL::CompareValue(PVAL vp)
BINVAL::BINVAL(PGLOBAL g, void *p, int cl, int n) : VALUE(TYPE_BIN) BINVAL::BINVAL(PGLOBAL g, void *p, int cl, int n) : VALUE(TYPE_BIN)
{ {
assert(g); assert(g);
//Len = n; Len = n;
Len = (g) ? n : (p) ? strlen((char*)p) : 0;
Clen = cl; Clen = cl;
Binp = PlugSubAlloc(g, NULL, Clen + 1); Binp = PlugSubAlloc(g, NULL, Clen + 1);
memset(Binp, 0, Clen + 1); memset(Binp, 0, Clen + 1);
if (p) if (p)
memcpy(Binp, p, Len); memcpy(Binp, p, MY_MIN(Len,Clen));
Chrp = NULL; Chrp = NULL;
} // end of BINVAL constructor } // end of BINVAL constructor
...@@ -2264,14 +2267,12 @@ bool BINVAL::GetBinValue(void *buf, int buflen, bool go) ...@@ -2264,14 +2267,12 @@ bool BINVAL::GetBinValue(void *buf, int buflen, bool go)
/***********************************************************************/ /***********************************************************************/
/* BINVAL ShowValue: get string representation of a binary value. */ /* BINVAL ShowValue: get string representation of a binary value. */
/***********************************************************************/ /***********************************************************************/
char *BINVAL::ShowValue(char *buf, int len) int BINVAL::ShowValue(char *buf, int len)
{ {
//int n = MY_MIN(Len, len / 2); memset(buf, 0, len + 1);
memcpy(buf, Binp, MY_MIN(len, Len));
//sprintf(buf, GetXfmt(), n, Binp); return Len;
//return buf; } // end of ShowValue
return (char*)Binp;
} // end of ShowValue
/***********************************************************************/ /***********************************************************************/
/* BINVAL GetCharString: get string representation of a binary value. */ /* BINVAL GetCharString: get string representation of a binary value. */
...@@ -2749,43 +2750,33 @@ char *DTVAL::GetCharString(char *p) ...@@ -2749,43 +2750,33 @@ char *DTVAL::GetCharString(char *p)
/***********************************************************************/ /***********************************************************************/
/* DTVAL ShowValue: get string representation of a date value. */ /* DTVAL ShowValue: get string representation of a date value. */
/***********************************************************************/ /***********************************************************************/
char *DTVAL::ShowValue(char *buf, int len) int DTVAL::ShowValue(char *buf, int len)
{ {
if (Pdtp) { int rv = 0;
char *p;
if (Pdtp) {
if (!Null) { if (!Null) {
size_t m, n = 0; size_t n = 0, m = len + 1;
struct tm tm, *ptm = GetGmTime(&tm); struct tm tm, *ptm = GetGmTime(&tm);
if (Len < len) {
p = buf;
m = len;
} else {
p = Sdate;
m = Len + 1;
} // endif Len
if (ptm) if (ptm)
n = strftime(p, m, Pdtp->OutFmt, ptm); n = strftime(buf, m, Pdtp->OutFmt, ptm);
if (!n) { if (!n) {
*p = '\0'; *buf = '\0';
strncat(p, "Error", m); strncat(buf, "Error", m);
} // endif n rv = 5;
} else
rv = (int)n;
} else { } else
p = buf; *buf = '\0'; // DEFAULT VALUE ???
*p = '\0'; // DEFAULT VALUE ???
} // endif Null
return p;
} else } else
return TYPVAL<int>::ShowValue(buf, len); rv = TYPVAL<int>::ShowValue(buf, len);
} // end of ShowValue return rv;
} // end of ShowValue
#if 0 // Not used by CONNECT #if 0 // Not used by CONNECT
/***********************************************************************/ /***********************************************************************/
......
/**************** Value H Declares Source Code File (.H) ***************/ /**************** Value H Declares Source Code File (.H) ***************/
/* Name: VALUE.H Version 2.3 */ /* Name: VALUE.H Version 2.4 */
/* */ /* */
/* (C) Copyright to the author Olivier BERTRAND 2001-2017 */ /* (C) Copyright to the author Olivier BERTRAND 2001-2019 */
/* */ /* */
/* This file contains the VALUE and derived classes declares. */ /* This file contains the VALUE and derived classes declares. */
/***********************************************************************/ /***********************************************************************/
...@@ -117,7 +117,7 @@ class DllExport VALUE : public BLOCK { ...@@ -117,7 +117,7 @@ class DllExport VALUE : public BLOCK {
virtual void SetValue_pvblk(PVBLK blk, int n) = 0; virtual void SetValue_pvblk(PVBLK blk, int n) = 0;
virtual void SetBinValue(void *p) = 0; virtual void SetBinValue(void *p) = 0;
virtual bool GetBinValue(void *buf, int buflen, bool go) = 0; virtual bool GetBinValue(void *buf, int buflen, bool go) = 0;
virtual char *ShowValue(char *buf, int len = 0) = 0; virtual int ShowValue(char *buf, int len) = 0;
virtual char *GetCharString(char *p) = 0; virtual char *GetCharString(char *p) = 0;
virtual bool IsEqual(PVAL vp, bool chktype) = 0; virtual bool IsEqual(PVAL vp, bool chktype) = 0;
virtual bool Compute(PGLOBAL g, PVAL *vp, int np, OPVAL op); virtual bool Compute(PGLOBAL g, PVAL *vp, int np, OPVAL op);
...@@ -229,7 +229,7 @@ class DllExport TYPVAL : public VALUE { ...@@ -229,7 +229,7 @@ class DllExport TYPVAL : public VALUE {
virtual void SetValue_pvblk(PVBLK blk, int n); virtual void SetValue_pvblk(PVBLK blk, int n);
virtual void SetBinValue(void *p); virtual void SetBinValue(void *p);
virtual bool GetBinValue(void *buf, int buflen, bool go); virtual bool GetBinValue(void *buf, int buflen, bool go);
virtual char *ShowValue(char *buf, int); virtual int ShowValue(char *buf, int len);
virtual char *GetCharString(char *p); virtual char *GetCharString(char *p);
virtual bool IsEqual(PVAL vp, bool chktype); virtual bool IsEqual(PVAL vp, bool chktype);
virtual bool Compute(PGLOBAL g, PVAL *vp, int np, OPVAL op); virtual bool Compute(PGLOBAL g, PVAL *vp, int np, OPVAL op);
...@@ -302,7 +302,7 @@ class DllExport TYPVAL<PSZ>: public VALUE { ...@@ -302,7 +302,7 @@ class DllExport TYPVAL<PSZ>: public VALUE {
virtual void SetBinValue(void *p); virtual void SetBinValue(void *p);
virtual int CompareValue(PVAL vp); virtual int CompareValue(PVAL vp);
virtual bool GetBinValue(void *buf, int buflen, bool go); virtual bool GetBinValue(void *buf, int buflen, bool go);
virtual char *ShowValue(char *buf, int); virtual int ShowValue(char *buf, int len);
virtual char *GetCharString(char *p); virtual char *GetCharString(char *p);
virtual bool IsEqual(PVAL vp, bool chktype); virtual bool IsEqual(PVAL vp, bool chktype);
virtual bool Compute(PGLOBAL g, PVAL *vp, int np, OPVAL op); virtual bool Compute(PGLOBAL g, PVAL *vp, int np, OPVAL op);
...@@ -334,7 +334,7 @@ class DllExport DECVAL: public TYPVAL<PSZ> { ...@@ -334,7 +334,7 @@ class DllExport DECVAL: public TYPVAL<PSZ> {
// Methods // Methods
virtual bool GetBinValue(void *buf, int buflen, bool go); virtual bool GetBinValue(void *buf, int buflen, bool go);
virtual char *ShowValue(char *buf, int); virtual int ShowValue(char *buf, int len);
virtual bool IsEqual(PVAL vp, bool chktype); virtual bool IsEqual(PVAL vp, bool chktype);
virtual int CompareValue(PVAL vp); virtual int CompareValue(PVAL vp);
...@@ -387,7 +387,7 @@ class DllExport BINVAL: public VALUE { ...@@ -387,7 +387,7 @@ class DllExport BINVAL: public VALUE {
virtual void SetBinValue(void *p); virtual void SetBinValue(void *p);
virtual bool GetBinValue(void *buf, int buflen, bool go); virtual bool GetBinValue(void *buf, int buflen, bool go);
virtual int CompareValue(PVAL) {assert(false); return 0;} virtual int CompareValue(PVAL) {assert(false); return 0;}
virtual char *ShowValue(char *buf, int); virtual int ShowValue(char *buf, int len);
virtual char *GetCharString(char *p); virtual char *GetCharString(char *p);
virtual bool IsEqual(PVAL vp, bool chktype); virtual bool IsEqual(PVAL vp, bool chktype);
virtual bool FormatValue(PVAL vp, PCSZ fmt); virtual bool FormatValue(PVAL vp, PCSZ fmt);
...@@ -415,7 +415,7 @@ class DllExport DTVAL : public TYPVAL<int> { ...@@ -415,7 +415,7 @@ class DllExport DTVAL : public TYPVAL<int> {
virtual void SetValue_psz(PCSZ s); virtual void SetValue_psz(PCSZ s);
virtual void SetValue_pvblk(PVBLK blk, int n); virtual void SetValue_pvblk(PVBLK blk, int n);
virtual char *GetCharString(char *p); virtual char *GetCharString(char *p);
virtual char *ShowValue(char *buf, int); virtual int ShowValue(char *buf, int len);
virtual bool FormatValue(PVAL vp, PCSZ fmt); virtual bool FormatValue(PVAL vp, PCSZ fmt);
bool SetFormat(PGLOBAL g, PCSZ fmt, int len, int year = 0); bool SetFormat(PGLOBAL g, PCSZ fmt, int len, int year = 0);
bool SetFormat(PGLOBAL g, PVAL valp); bool SetFormat(PGLOBAL g, PVAL valp);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment