Commit 48d2141b authored by Olivier Bertrand's avatar Olivier Bertrand

- 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
parent e0c147c2
...@@ -109,6 +109,7 @@ IF(CONNECT_WITH_LIBXML2) ...@@ -109,6 +109,7 @@ IF(CONNECT_WITH_LIBXML2)
FIND_PACKAGE(LibXml2) FIND_PACKAGE(LibXml2)
IF (LIBXML2_FOUND) IF (LIBXML2_FOUND)
INCLUDE_DIRECTORIES(${LIBXML2_INCLUDE_DIR}) INCLUDE_DIRECTORIES(${LIBXML2_INCLUDE_DIR})
SET(ZLIB_LIBRARY "z") # see ZLIB_INCLUDE_DIR below
SET(XML_LIBRARY ${LIBXML2_LIBRARIES}) SET(XML_LIBRARY ${LIBXML2_LIBRARIES})
SET(CONNECT_SOURCES ${CONNECT_SOURCES} libdoc.cpp libdoc.h) SET(CONNECT_SOURCES ${CONNECT_SOURCES} libdoc.cpp libdoc.h)
add_definitions(-DLIBXML2_SUPPORT) add_definitions(-DLIBXML2_SUPPORT)
...@@ -124,7 +125,6 @@ IF(WIN32) ...@@ -124,7 +125,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)
...@@ -326,6 +326,14 @@ IF(NOT TARGET connect) ...@@ -326,6 +326,14 @@ IF(NOT TARGET connect)
RETURN() RETURN()
ENDIF() ENDIF()
# Don't link with bundled zlib and systel libxml2 at the same time.
# System libxml2 uses system zlib, might conflict with the bundled one.
IF (XML_LIBRARY AND BUILD_BUNDLED_ZLIB)
GET_PROPERTY(INCS TARGET connect PROPERTY INCLUDE_DIRECTORIES)
LIST(REMOVE_ITEM INCS ${ZLIB_INCLUDE_DIR})
SET_PROPERTY(TARGET connect PROPERTY INCLUDE_DIRECTORIES ${INCS})
ENDIF()
IF(WIN32) IF(WIN32)
IF (libmongoc-1.0_FOUND) IF (libmongoc-1.0_FOUND)
SET_TARGET_PROPERTIES(connect PROPERTIES LINK_FLAGS SET_TARGET_PROPERTIES(connect PROPERTIES LINK_FLAGS
...@@ -346,23 +354,6 @@ IF(WIN32) ...@@ -346,23 +354,6 @@ IF(WIN32)
DESTINATION ${INSTALL_PLUGINDIR} COMPONENT connect-engine) DESTINATION ${INSTALL_PLUGINDIR} COMPONENT connect-engine)
ENDIF(WIN32) ENDIF(WIN32)
IF(NOT TARGET connect)
RETURN()
ENDIF()
# Install some extra files that belong to connect engine
IF(WIN32)
# install ha_connect.lib
GET_TARGET_PROPERTY(CONNECT_LOCATION connect LOCATION)
STRING(REPLACE "dll" "lib" CONNECT_LIB ${CONNECT_LOCATION})
IF(CMAKE_CONFIGURATION_TYPES)
STRING(REPLACE "${CMAKE_CFG_INTDIR}" "\${CMAKE_INSTALL_CONFIG_NAME}"
CONNECT_LIB ${CONNECT_LIB})
ENDIF()
INSTALL(FILES ${CONNECT_LIB}
DESTINATION ${INSTALL_PLUGINDIR} COMPONENT connect-engine)
ENDIF(WIN32)
IF(CONNECT_WITH_JDBC AND JAVA_FOUND AND JNI_FOUND) IF(CONNECT_WITH_JDBC AND JAVA_FOUND AND JNI_FOUND)
# TODO: Find how to compile and install the java wrapper classes # TODO: Find how to compile and install the java wrapper classes
# Find required libraries and include directories # Find required libraries and include directories
......
...@@ -447,7 +447,7 @@ int DBFFAM::Cardinality(PGLOBAL g) ...@@ -447,7 +447,7 @@ int DBFFAM::Cardinality(PGLOBAL g)
if (rln && Lrecl != rln) { if (rln && Lrecl != rln) {
// This happens always on some Linux platforms // This happens always on some Linux platforms
sprintf(g->Message, MSG(BAD_LRECL), Lrecl, rln); sprintf(g->Message, MSG(BAD_LRECL), Lrecl, (ushort)rln);
if (Accept) { if (Accept) {
Lrecl = rln; Lrecl = rln;
...@@ -967,7 +967,7 @@ int DBMFAM::Cardinality(PGLOBAL g) ...@@ -967,7 +967,7 @@ int DBMFAM::Cardinality(PGLOBAL g)
if (rln && Lrecl != rln) { if (rln && Lrecl != rln) {
// This happens always on some Linux platforms // This happens always on some Linux platforms
sprintf(g->Message, MSG(BAD_LRECL), Lrecl, rln); sprintf(g->Message, MSG(BAD_LRECL), Lrecl, (ushort)rln);
if (Accept) { if (Accept) {
Lrecl = rln; Lrecl = rln;
......
...@@ -65,11 +65,6 @@ ...@@ -65,11 +65,6 @@
extern int num_read, num_there; // Statistics extern int num_read, num_there; // Statistics
static int num_write; static int num_write;
#if defined(UNIX)
// Add dummy strerror (NGC)
char *strerror(int num);
#endif // UNIX
/***********************************************************************/ /***********************************************************************/
/* Header containing block info for not split VEC tables. */ /* Header containing block info for not split VEC tables. */
/* Block and last values can be calculated from NumRec and Nrec. */ /* Block and last values can be calculated from NumRec and Nrec. */
......
...@@ -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)
...@@ -4678,9 +4700,6 @@ int ha_connect::start_stmt(THD *thd, thr_lock_type lock_type) ...@@ -4678,9 +4700,6 @@ int ha_connect::start_stmt(THD *thd, thr_lock_type lock_type)
PGLOBAL g= GetPlug(thd, xp); PGLOBAL g= GetPlug(thd, xp);
DBUG_ENTER("ha_connect::start_stmt"); DBUG_ENTER("ha_connect::start_stmt");
if (table->triggers)
g->More= 1; // We don't know which columns are used by the trigger
if (check_privileges(thd, GetTableOptionStruct(), table->s->db.str, true)) if (check_privileges(thd, GetTableOptionStruct(), table->s->db.str, true))
DBUG_RETURN(HA_ERR_INTERNAL_ERROR); DBUG_RETURN(HA_ERR_INTERNAL_ERROR);
...@@ -4708,8 +4727,24 @@ int ha_connect::start_stmt(THD *thd, thr_lock_type lock_type) ...@@ -4708,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
/** /**
...@@ -4891,21 +4926,16 @@ int ha_connect::external_lock(THD *thd, int lock_type) ...@@ -4891,21 +4926,16 @@ 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 strcpy(g->Message, "This operation requires the FILE privilege");
if (check_privileges(thd, options, table->s->db.str)) { htrc("%s\n", g->Message);
strcpy(g->Message, "This operation requires the FILE privilege"); DBUG_RETURN(HA_ERR_INTERNAL_ERROR);
htrc("%s\n", g->Message); } // endif check_privileges
DBUG_RETURN(HA_ERR_INTERNAL_ERROR);
} // endif check_privileges
DBUG_ASSERT(table && table->s); DBUG_ASSERT(table && table->s);
...@@ -4916,43 +4946,31 @@ int ha_connect::external_lock(THD *thd, int lock_type) ...@@ -4916,43 +4946,31 @@ 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);
// If this is the start of a new query, cleanup the previous one 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 (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("Calling CntCheckDB db=%s cras=%d\n", GetDBName(NULL), cras);
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);
} // 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
} else if (!tdbp || xp->CheckQuery(valid_query_id) || xmod != newmode) { } else if (!tdbp || xp->CheckQuery(valid_query_id) || xmod != newmode) {
...@@ -4972,10 +4990,10 @@ int ha_connect::external_lock(THD *thd, int lock_type) ...@@ -4972,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
/** /**
...@@ -6257,7 +6275,7 @@ int ha_connect::create(const char *name, TABLE *table_arg, ...@@ -6257,7 +6275,7 @@ int ha_connect::create(const char *name, TABLE *table_arg,
TABLE *st= table; // Probably unuseful TABLE *st= table; // Probably unuseful
THD *thd= ha_thd(); THD *thd= ha_thd();
LEX_STRING cnc = table_arg->s->connect_string; LEX_STRING cnc = table_arg->s->connect_string;
#if defined(WITH_PARTITION_STORAGE_ENGINE) #ifdef WITH_PARTITION_STORAGE_ENGINE
partition_info *part_info= table_arg->part_info; partition_info *part_info= table_arg->part_info;
#else // !WITH_PARTITION_STORAGE_ENGINE #else // !WITH_PARTITION_STORAGE_ENGINE
#define part_info 0 #define part_info 0
......
...@@ -507,7 +507,8 @@ int index_prev(uchar *buf); ...@@ -507,7 +507,8 @@ 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);
char *GetDBfromName(const char *name); int check_stmt(PGLOBAL g, MODE newmode, bool cras);
char *GetDBfromName(const char *name);
// Members // Members
static ulong num; // Tracable handler number static ulong num; // Tracable handler number
......
...@@ -194,7 +194,7 @@ static void PROFILE_Save( FILE *file, PROFILESECTION *section ) ...@@ -194,7 +194,7 @@ static void PROFILE_Save( FILE *file, PROFILESECTION *section )
} }
for (key = section->key; key; key = key->next) for (key = section->key; key; key = key->next)
if (key->name && key->name[0]) { if (key->name[0]) {
fprintf(file, "%s", SVP(key->name)); fprintf(file, "%s", SVP(key->name));
if (key->value) if (key->value)
......
...@@ -441,7 +441,7 @@ bool JAVAConn::Open(PGLOBAL g) ...@@ -441,7 +441,7 @@ bool JAVAConn::Open(PGLOBAL g)
//=============== load and initialize Java VM and JNI interface ============= //=============== load and initialize Java VM and JNI interface =============
rc = CreateJavaVM(&jvm, (void**)&env, &vm_args); // YES !! rc = CreateJavaVM(&jvm, (void**)&env, &vm_args); // YES !!
delete options; // we then no longer need the initialisation options. delete[] options; // we then no longer need the initialisation options.
switch (rc) { switch (rc) {
case JNI_OK: case JNI_OK:
......
...@@ -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: */
/* ----------------------- */ /* ----------------------- */
...@@ -2492,8 +2492,10 @@ bool DOSCOL::SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check) ...@@ -2492,8 +2492,10 @@ bool DOSCOL::SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check)
} // endif's Value, Buf_Type } // endif's Value, Buf_Type
// 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
/*******************************************************************/ /*******************************************************************/
...@@ -2738,7 +2742,7 @@ void DOSCOL::WriteColumn(PGLOBAL g) ...@@ -2738,7 +2742,7 @@ void DOSCOL::WriteColumn(PGLOBAL g)
sprintf(g->Message, MSG(BIN_F_TOO_LONG), sprintf(g->Message, MSG(BIN_F_TOO_LONG),
Name, Value->GetSize(), Long); Name, Value->GetSize(), Long);
throw 31; throw 31;
} // endif } // endif
} // end of WriteColumn } // end of WriteColumn
......
...@@ -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)
......
...@@ -177,7 +177,8 @@ bool user_connect::CheckCleanup(bool force) ...@@ -177,7 +177,8 @@ bool user_connect::CheckCleanup(bool force)
g->Createas = 0; g->Createas = 0;
g->Alchecked = 0; g->Alchecked = 0;
g->Mrr = 0; g->Mrr = 0;
last_query_id= thdp->query_id; g->More = 0;
last_query_id= thdp->query_id;
if (trace(65) && !force) if (trace(65) && !force)
printf("=====> Begin new query %llu\n", last_query_id); printf("=====> Begin new query %llu\n", last_query_id);
......
/************* 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