Commit dc3a693b authored by Olivier Bertrand's avatar Olivier Bertrand

- Inline MakePtr and MakeOff with OFFSET as size_t

  Also add a new member Saved_Size in the Global structure.
  modified:   storage/connect/global.h
  modified:   storage/connect/plugutil.cpp
  modified:   storage/connect/user_connect.cc
  modified:   storage/connect/jsonudf.cpp

- Add session variables json_all_path and default_depth
  modified:   storage/connect/ha_connect.cc
  modified:   storage/connect/mongo.cpp
  modified:   storage/connect/tabjson.cpp
  modified:   storage/connect/tabxml.cpp

- ADD column options JPATH and XPATH
  Work as FIELD_FORMAT but are more readable
  modified:   storage/connect/ha_connect.cc
  modified:   storage/connect/ha_connect.h
  modified:   storage/connect/mysql-test/connect/r/json_java_2.result
  modified:   storage/connect/mysql-test/connect/r/json_java_3.result
  modified:   storage/connect/mysql-test/connect/r/json_mongo_c.result

- Handle negative numbes in the option list
  modified:   storage/connect/ha_connect.cc

- Fix Json parse that could crash the server.
  Was because it could use THROW out of the TRY block.
  Also handle all error by THROW.
  It is now done by a new class JSON.
  modified:   storage/connect/json.cpp
  modified:   storage/connect/json.h

- Add a new UDF function jfile_translate.
  It translate a Json file to pretty = 0.
  Fast because it does not a real parse of the file.
  modified:   storage/connect/jsonudf.cpp
  modified:   storage/connect/jsonudf.h

- Add a now options JSIZE and STRINGIFY to Json tables.
  STRINGIFY makes Objects or Arrays to be returned by their
  json representation instead of by their concatenated values.
  JSIZE allows to specify the LRECL (was 256) defaults to 1024.
  Also fix a bug about locating the sub-table by its path.
  modified:   storage/connect/tabjson.cpp
  modified:   storage/connect/tabjson.h
parent 5d2ddef2
...@@ -89,14 +89,10 @@ extern "C" { ...@@ -89,14 +89,10 @@ extern "C" {
#define PAT_LOG "log" #define PAT_LOG "log"
#if defined(UNIX) || defined(LINUX) || defined(UNIV_LINUX) #if defined(UNIX) || defined(LINUX) || defined(UNIV_LINUX)
/*********************************************************************/ // printf does not accept null pointer for %s target
/* printf does not accept null pointer for %s target. */
/*********************************************************************/
#define SVP(S) ((S) ? S : "<null>") #define SVP(S) ((S) ? S : "<null>")
#else #else
/*********************************************************************/ // printf accepts null pointer for %s target
/* printf accepts null pointer for %s target. */
/*********************************************************************/
#define SVP(S) S #define SVP(S) S
#endif #endif
...@@ -112,9 +108,6 @@ extern "C" { ...@@ -112,9 +108,6 @@ extern "C" {
/***********************************************************************/ /***********************************************************************/
#include "os.h" #include "os.h"
typedef size_t OFFSET;
typedef char NAME[9];
typedef struct { typedef struct {
ushort Length; ushort Length;
char String[2]; char String[2];
...@@ -127,6 +120,7 @@ typedef struct _global *PGLOBAL; ...@@ -127,6 +120,7 @@ typedef struct _global *PGLOBAL;
typedef struct _globplg *PGS; typedef struct _globplg *PGS;
typedef struct _activity *PACTIVITY; typedef struct _activity *PACTIVITY;
typedef struct _parm *PPARM; typedef struct _parm *PPARM;
typedef char NAME[9];
/***********************************************************************/ /***********************************************************************/
/* Segment Sub-Allocation block structure declares. */ /* Segment Sub-Allocation block structure declares. */
...@@ -135,7 +129,7 @@ typedef struct _parm *PPARM; ...@@ -135,7 +129,7 @@ typedef struct _parm *PPARM;
/* restore them if needed. This scheme implies that no SubFree be used */ /* restore them if needed. This scheme implies that no SubFree be used */
/***********************************************************************/ /***********************************************************************/
typedef struct { /* Plug Area SubAlloc header */ typedef struct { /* Plug Area SubAlloc header */
OFFSET To_Free; /* Offset of next free block */ size_t To_Free; /* Offset of next free block */
size_t FreeBlk; /* Size of remaining free memory */ size_t FreeBlk; /* Size of remaining free memory */
} POOLHEADER, *PPOOLHEADER; } POOLHEADER, *PPOOLHEADER;
...@@ -190,9 +184,10 @@ typedef struct _global { /* Global structure */ ...@@ -190,9 +184,10 @@ typedef struct _global { /* Global structure */
void *Sarea; /* Points to work area */ void *Sarea; /* Points to work area */
size_t Sarea_Size; /* Work area size */ size_t Sarea_Size; /* Work area size */
PACTIVITY Activityp; PACTIVITY Activityp;
char Message[MAX_STR]; char Message[MAX_STR]; /* Message (result, error, trace) */
ulong More; /* Used by jsonudf */ ulong More; /* Used by jsonudf */
int Createas; /* To pass multi to ext tables */ size_t Saved_Size; /* Saved work area to_free */
bool Createas; /* To pass multi to ext tables */
void *Xchk; /* indexes in create/alter */ void *Xchk; /* indexes in create/alter */
short Alchecked; /* Checked for ALTER */ short Alchecked; /* Checked for ALTER */
short Mrr; /* True when doing mrr */ short Mrr; /* True when doing mrr */
...@@ -222,7 +217,6 @@ DllExport void FreeSarea(PGLOBAL); ...@@ -222,7 +217,6 @@ DllExport void FreeSarea(PGLOBAL);
DllExport BOOL PlugSubSet(void *, size_t); DllExport BOOL PlugSubSet(void *, size_t);
DllExport void *PlugSubAlloc(PGLOBAL, void *, size_t); DllExport void *PlugSubAlloc(PGLOBAL, void *, size_t);
DllExport char *PlugDup(PGLOBAL g, const char *str); DllExport char *PlugDup(PGLOBAL g, const char *str);
DllExport void *MakePtr(void *, OFFSET);
DllExport void htrc(char const *fmt, ...); DllExport void htrc(char const *fmt, ...);
DllExport void xtrc(uint, char const* fmt, ...); DllExport void xtrc(uint, char const* fmt, ...);
DllExport uint GetTraceValue(void); DllExport uint GetTraceValue(void);
...@@ -232,8 +226,24 @@ DllExport uint GetTraceValue(void); ...@@ -232,8 +226,24 @@ DllExport uint GetTraceValue(void);
#endif #endif
/***********************************************************************/ /***********************************************************************/
/* Non exported routine declarations. */ /* Inline routine definitions. */
/***********************************************************************/
/***********************************************************************/
/* This routine makes a pointer from an offset to a memory pointer. */
/***********************************************************************/
inline void* MakePtr(void* memp, size_t offset) {
// return ((offset == 0) ? NULL : &((char*)memp)[offset]);
return (!offset) ? NULL : (char *)memp + offset;
} /* end of MakePtr */
/***********************************************************************/
/* This routine makes an offset from a pointer new format. */
/***********************************************************************/ /***********************************************************************/
//void *PlugSubAlloc(PGLOBAL, void *, size_t); // Does throw inline size_t MakeOff(void* memp, void* ptr) {
#if defined(_DEBUG)
assert(ptr > memp);
#endif // _DEBUG
return ((!ptr) ? 0 : (size_t)((char*)ptr - (size_t)memp));
} /* end of MakeOff */
/*-------------------------- End of Global.H --------------------------*/ /*-------------------------- End of Global.H --------------------------*/
...@@ -170,7 +170,7 @@ ...@@ -170,7 +170,7 @@
#define JSONMAX 10 // JSON Default max grp size #define JSONMAX 10 // JSON Default max grp size
extern "C" { extern "C" {
char version[]= "Version 1.07.0002 October 03, 2020"; char version[]= "Version 1.07.0002 October 18, 2020";
#if defined(__WIN__) #if defined(__WIN__)
char compver[]= "Version 1.07.0002 " __DATE__ " " __TIME__; char compver[]= "Version 1.07.0002 " __DATE__ " " __TIME__;
char slash= '\\'; char slash= '\\';
...@@ -251,6 +251,7 @@ bool ExactInfo(void); ...@@ -251,6 +251,7 @@ bool ExactInfo(void);
USETEMP UseTemp(void); USETEMP UseTemp(void);
int GetConvSize(void); int GetConvSize(void);
TYPCONV GetTypeConv(void); TYPCONV GetTypeConv(void);
bool JsonAllPath(void);
char *GetJsonNull(void); char *GetJsonNull(void);
uint GetJsonGrpSize(void); uint GetJsonGrpSize(void);
char *GetJavaWrapper(void); char *GetJavaWrapper(void);
...@@ -394,6 +395,11 @@ static MYSQL_THDVAR_ENUM( ...@@ -394,6 +395,11 @@ static MYSQL_THDVAR_ENUM(
1, // def (yes) 1, // def (yes)
&xconv_typelib); // typelib &xconv_typelib); // typelib
// Adding JPATH to all Json table columns
static MYSQL_THDVAR_BOOL(json_all_path, PLUGIN_VAR_RQCMDARG,
"Adding JPATH to all Json table columns",
NULL, NULL, 0); // NO by default
// Null representation for JSON values // Null representation for JSON values
static MYSQL_THDVAR_STR(json_null, static MYSQL_THDVAR_STR(json_null,
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_MEMALLOC, PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_MEMALLOC,
...@@ -401,6 +407,12 @@ static MYSQL_THDVAR_STR(json_null, ...@@ -401,6 +407,12 @@ static MYSQL_THDVAR_STR(json_null,
// check_json_null, update_json_null, // check_json_null, update_json_null,
NULL, NULL, "<null>"); NULL, NULL, "<null>");
// Default Json, XML or Mongo depth
static MYSQL_THDVAR_INT(default_depth,
PLUGIN_VAR_RQCMDARG,
"Default depth used by Json, XML and Mongo discovery",
NULL, NULL, 0, -1, 16, 1);
// Estimate max number of rows for JSON aggregate functions // Estimate max number of rows for JSON aggregate functions
static MYSQL_THDVAR_UINT(json_grp_size, static MYSQL_THDVAR_UINT(json_grp_size,
PLUGIN_VAR_RQCMDARG, // opt PLUGIN_VAR_RQCMDARG, // opt
...@@ -462,11 +474,13 @@ uint GetTraceValue(void) ...@@ -462,11 +474,13 @@ uint GetTraceValue(void)
{return (uint)(connect_hton ? THDVAR(current_thd, xtrace) : 0);} {return (uint)(connect_hton ? THDVAR(current_thd, xtrace) : 0);}
bool ExactInfo(void) {return THDVAR(current_thd, exact_info);} bool ExactInfo(void) {return THDVAR(current_thd, exact_info);}
static bool CondPushEnabled(void) {return THDVAR(current_thd, cond_push);} static bool CondPushEnabled(void) {return THDVAR(current_thd, cond_push);}
bool JsonAllPath(void) {return THDVAR(current_thd, json_all_path);}
USETEMP UseTemp(void) {return (USETEMP)THDVAR(current_thd, use_tempfile);} USETEMP UseTemp(void) {return (USETEMP)THDVAR(current_thd, use_tempfile);}
int GetConvSize(void) {return THDVAR(current_thd, conv_size);} int GetConvSize(void) {return THDVAR(current_thd, conv_size);}
TYPCONV GetTypeConv(void) {return (TYPCONV)THDVAR(current_thd, type_conv);} TYPCONV GetTypeConv(void) {return (TYPCONV)THDVAR(current_thd, type_conv);}
char *GetJsonNull(void) char *GetJsonNull(void)
{return connect_hton ? THDVAR(current_thd, json_null) : NULL;} {return connect_hton ? THDVAR(current_thd, json_null) : NULL;}
int GetDefaultDepth(void) {return THDVAR(current_thd, default_depth);}
uint GetJsonGrpSize(void) uint GetJsonGrpSize(void)
{return connect_hton ? THDVAR(current_thd, json_grp_size) : 10;} {return connect_hton ? THDVAR(current_thd, json_grp_size) : 10;}
size_t GetWorkSize(void) {return (size_t)THDVAR(current_thd, work_size);} size_t GetWorkSize(void) {return (size_t)THDVAR(current_thd, work_size);}
...@@ -630,8 +644,10 @@ ha_create_table_option connect_field_option_list[]= ...@@ -630,8 +644,10 @@ ha_create_table_option connect_field_option_list[]=
HA_FOPTION_NUMBER("FIELD_LENGTH", fldlen, 0, 0, INT_MAX32, 1), HA_FOPTION_NUMBER("FIELD_LENGTH", fldlen, 0, 0, INT_MAX32, 1),
HA_FOPTION_STRING("DATE_FORMAT", dateformat), HA_FOPTION_STRING("DATE_FORMAT", dateformat),
HA_FOPTION_STRING("FIELD_FORMAT", fieldformat), HA_FOPTION_STRING("FIELD_FORMAT", fieldformat),
HA_FOPTION_STRING("SPECIAL", special), HA_FOPTION_STRING("JPATH", jsonpath),
HA_FOPTION_ENUM("DISTRIB", opt, "scattered,clustered,sorted", 0), HA_FOPTION_STRING("XPATH", xmlpath),
HA_FOPTION_STRING("SPECIAL", special),
HA_FOPTION_ENUM("DISTRIB", opt, "scattered,clustered,sorted", 0),
HA_FOPTION_END HA_FOPTION_END
}; };
...@@ -1322,9 +1338,10 @@ int GetIntegerTableOption(PGLOBAL g, PTOS options, PCSZ opname, int idef) ...@@ -1322,9 +1338,10 @@ int GetIntegerTableOption(PGLOBAL g, PTOS options, PCSZ opname, int idef)
if ((ulonglong) opval == (ulonglong)NO_IVAL) { if ((ulonglong) opval == (ulonglong)NO_IVAL) {
PCSZ pv; PCSZ pv;
if ((pv= GetListOption(g, opname, options->oplist))) if ((pv = GetListOption(g, opname, options->oplist))) {
opval= CharToNumber((char*)pv, strlen(pv), ULONGLONG_MAX, true); // opval = CharToNumber((char*)pv, strlen(pv), ULONGLONG_MAX, false);
else return atoi(pv);
} else
return idef; return idef;
} // endif opval } // endif opval
...@@ -1576,8 +1593,9 @@ void *ha_connect::GetColumnOption(PGLOBAL g, void *field, PCOLINFO pcf) ...@@ -1576,8 +1593,9 @@ void *ha_connect::GetColumnOption(PGLOBAL g, void *field, PCOLINFO pcf)
pcf->Offset= (int)fop->offset; pcf->Offset= (int)fop->offset;
pcf->Freq= (int)fop->freq; pcf->Freq= (int)fop->freq;
pcf->Datefmt= (char*)fop->dateformat; pcf->Datefmt= (char*)fop->dateformat;
pcf->Fieldfmt= (char*)fop->fieldformat; pcf->Fieldfmt = fop->fieldformat ? (char*)fop->fieldformat
} else { : fop->jsonpath ? (char*)fop->jsonpath : (char*)fop->xmlpath;
} else {
pcf->Offset= -1; pcf->Offset= -1;
pcf->Freq= 0; pcf->Freq= 0;
pcf->Datefmt= NULL; pcf->Datefmt= NULL;
...@@ -4984,7 +5002,7 @@ int ha_connect::check_stmt(PGLOBAL g, MODE newmode, bool cras) ...@@ -4984,7 +5002,7 @@ int ha_connect::check_stmt(PGLOBAL g, MODE newmode, bool cras)
} // endif CheckCleanup } // endif CheckCleanup
if (cras) if (cras)
g->Createas= 1; // To tell external tables of a multi-table command g->Createas= true; // To tell external tables of a multi-table command
if (trace(1)) if (trace(1))
htrc("Calling CntCheckDB db=%s cras=%d\n", GetDBName(NULL), cras); htrc("Calling CntCheckDB db=%s cras=%d\n", GetDBName(NULL), cras);
...@@ -5334,96 +5352,100 @@ static char *encode(PGLOBAL g, const char *cnm) ...@@ -5334,96 +5352,100 @@ static char *encode(PGLOBAL g, const char *cnm)
@return @return
Return 0 if ok Return 0 if ok
*/ */
static bool add_field(String *sql, const char *field_name, int typ, int len, static bool add_field(String* sql, TABTYPE ttp, const char* field_name, int typ,
int dec, char *key, uint tm, const char *rem, char *dft, int len, int dec, char* key, uint tm, const char* rem,
char *xtra, char *fmt, int flag, bool dbf, char v) char* dft, char* xtra, char* fmt, int flag, bool dbf, char v) {
{
#if defined(DEVELOPMENT) #if defined(DEVELOPMENT)
// Some client programs regard CHAR(36) as GUID // Some client programs regard CHAR(36) as GUID
char var= (len > 255 || len == 36) ? 'V' : v; char var = (len > 255 || len == 36) ? 'V' : v;
#else #else
char var = (len > 255) ? 'V' : v; char var = (len > 255) ? 'V' : v;
#endif #endif
bool q, error= false; bool q, error = false;
const char *type= PLGtoMYSQLtype(typ, dbf, var); const char* type = PLGtoMYSQLtype(typ, dbf, var);
error|= sql->append('`'); error |= sql->append('`');
error|= sql->append(field_name); error |= sql->append(field_name);
error|= sql->append("` "); error |= sql->append("` ");
error|= sql->append(type); error |= sql->append(type);
if (typ == TYPE_STRING || if (typ == TYPE_STRING ||
(len && typ != TYPE_DATE && (typ != TYPE_DOUBLE || dec >= 0))) { (len && typ != TYPE_DATE && (typ != TYPE_DOUBLE || dec >= 0))) {
error|= sql->append('('); error |= sql->append('(');
error|= sql->append_ulonglong(len); error |= sql->append_ulonglong(len);
if (typ == TYPE_DOUBLE) { if (typ == TYPE_DOUBLE) {
error|= sql->append(','); error |= sql->append(',');
// dec must be < len and < 31 // dec must be < len and < 31
error|= sql->append_ulonglong(MY_MIN(dec, (MY_MIN(len, 31) - 1))); error |= sql->append_ulonglong(MY_MIN(dec, (MY_MIN(len, 31) - 1)));
} else if (dec > 0 && !strcmp(type, "DECIMAL")) { } else if (dec > 0 && !strcmp(type, "DECIMAL")) {
error|= sql->append(','); error |= sql->append(',');
// dec must be < len // dec must be < len
error|= sql->append_ulonglong(MY_MIN(dec, len - 1)); error |= sql->append_ulonglong(MY_MIN(dec, len - 1));
} // endif dec } // endif dec
error|= sql->append(')'); error |= sql->append(')');
} // endif len } // endif len
if (v == 'U') if (v == 'U')
error|= sql->append(" UNSIGNED"); error |= sql->append(" UNSIGNED");
else if (v == 'Z') else if (v == 'Z')
error|= sql->append(" ZEROFILL"); error |= sql->append(" ZEROFILL");
if (key && *key) { if (key && *key) {
error|= sql->append(" "); error |= sql->append(" ");
error|= sql->append(key); error |= sql->append(key);
} // endif key } // endif key
if (tm) if (tm)
error|= sql->append(STRING_WITH_LEN(" NOT NULL"), system_charset_info); error |= sql->append(STRING_WITH_LEN(" NOT NULL"), system_charset_info);
if (dft && *dft) { if (dft && *dft) {
error|= sql->append(" DEFAULT "); error |= sql->append(" DEFAULT ");
if (typ == TYPE_DATE) if (typ == TYPE_DATE)
q= (strspn(dft, "0123456789 -:/") == strlen(dft)); q = (strspn(dft, "0123456789 -:/") == strlen(dft));
else else
q= !IsTypeNum(typ); q = !IsTypeNum(typ);
if (q) { if (q) {
error|= sql->append("'"); error |= sql->append("'");
error|= sql->append_for_single_quote(dft, strlen(dft)); error |= sql->append_for_single_quote(dft, strlen(dft));
error|= sql->append("'"); error |= sql->append("'");
} else } else
error|= sql->append(dft); error |= sql->append(dft);
} // endif dft } // endif dft
if (xtra && *xtra) { if (xtra && *xtra) {
error|= sql->append(" "); error |= sql->append(" ");
error|= sql->append(xtra); error |= sql->append(xtra);
} // endif rem } // endif rem
if (rem && *rem) { if (rem && *rem) {
error|= sql->append(" COMMENT '"); error |= sql->append(" COMMENT '");
error|= sql->append_for_single_quote(rem, strlen(rem)); error |= sql->append_for_single_quote(rem, strlen(rem));
error|= sql->append("'"); error |= sql->append("'");
} // endif rem } // endif rem
if (fmt && *fmt) { if (fmt && *fmt) {
error|= sql->append(" FIELD_FORMAT='"); switch (ttp) {
error|= sql->append_for_single_quote(fmt, strlen(fmt)); case TAB_JSON: error |= sql->append(" JPATH='"); break;
error|= sql->append("'"); case TAB_XML: error |= sql->append(" XPATH='"); break;
} // endif flag default: error |= sql->append(" FIELD_FORMAT='");
} // endswitch ttp
if (flag) {
error|= sql->append(" FLAG="); error |= sql->append_for_single_quote(fmt, strlen(fmt));
error|= sql->append_ulonglong(flag); error |= sql->append("'");
} // endif flag } // endif flag
error|= sql->append(','); if (flag) {
return error; error |= sql->append(" FLAG=");
error |= sql->append_ulonglong(flag);
} // endif flag
error |= sql->append(',');
return error;
} // end of add_field } // end of add_field
/** /**
...@@ -6045,7 +6067,7 @@ static int connect_assisted_discovery(handlerton *, THD* thd, ...@@ -6045,7 +6067,7 @@ static int connect_assisted_discovery(handlerton *, THD* thd,
len= 256; // STRBLK's have 0 length len= 256; // STRBLK's have 0 length
// Now add the field // Now add the field
if (add_field(&sql, cnm, typ, len, dec, NULL, tm, if (add_field(&sql, ttp, cnm, typ, len, dec, NULL, tm,
NULL, NULL, NULL, NULL, flg, dbf, v)) NULL, NULL, NULL, NULL, flg, dbf, v))
rc= HA_ERR_OUT_OF_MEM; rc= HA_ERR_OUT_OF_MEM;
} // endfor crp } // endfor crp
...@@ -6239,7 +6261,7 @@ static int connect_assisted_discovery(handlerton *, THD* thd, ...@@ -6239,7 +6261,7 @@ static int connect_assisted_discovery(handlerton *, THD* thd,
prec= 0; prec= 0;
// Now add the field // Now add the field
if (add_field(&sql, cnm, typ, prec, dec, key, tm, rem, dft, xtra, if (add_field(&sql, ttp, cnm, typ, prec, dec, key, tm, rem, dft, xtra,
fmt, flg, dbf, v)) fmt, flg, dbf, v))
rc= HA_ERR_OUT_OF_MEM; rc= HA_ERR_OUT_OF_MEM;
} // endfor i } // endfor i
...@@ -6992,7 +7014,7 @@ bool ha_connect::NoFieldOptionChange(TABLE *tab) ...@@ -6992,7 +7014,7 @@ bool ha_connect::NoFieldOptionChange(TABLE *tab)
fop1->fldlen == fop2->fldlen && fop1->fldlen == fop2->fldlen &&
CheckString(fop1->dateformat, fop2->dateformat) && CheckString(fop1->dateformat, fop2->dateformat) &&
CheckString(fop1->fieldformat, fop2->fieldformat) && CheckString(fop1->fieldformat, fop2->fieldformat) &&
CheckString(fop1->special, fop2->special)); CheckString(fop1->special, fop2->special));
} // endfor fld } // endfor fld
return rc; return rc;
...@@ -7362,7 +7384,9 @@ static struct st_mysql_sys_var* connect_system_variables[]= { ...@@ -7362,7 +7384,9 @@ static struct st_mysql_sys_var* connect_system_variables[]= {
MYSQL_SYSVAR(errmsg_dir_path), MYSQL_SYSVAR(errmsg_dir_path),
#endif // XMSG #endif // XMSG
MYSQL_SYSVAR(json_null), MYSQL_SYSVAR(json_null),
MYSQL_SYSVAR(json_grp_size), MYSQL_SYSVAR(json_all_path),
MYSQL_SYSVAR(default_depth),
MYSQL_SYSVAR(json_grp_size),
#if defined(JAVA_SUPPORT) #if defined(JAVA_SUPPORT)
MYSQL_SYSVAR(jvm_path), MYSQL_SYSVAR(jvm_path),
MYSQL_SYSVAR(class_path), MYSQL_SYSVAR(class_path),
......
...@@ -104,7 +104,9 @@ struct ha_field_option_struct ...@@ -104,7 +104,9 @@ struct ha_field_option_struct
uint opt; uint opt;
const char *dateformat; const char *dateformat;
const char *fieldformat; const char *fieldformat;
char *special; const char* jsonpath;
const char* xmlpath;
char *special;
}; };
/* /*
......
...@@ -93,9 +93,8 @@ char *NextChr(PSZ s, char sep) ...@@ -93,9 +93,8 @@ char *NextChr(PSZ s, char sep)
PJSON ParseJson(PGLOBAL g, char *s, int len, int *ptyp, bool *comma) PJSON ParseJson(PGLOBAL g, char *s, int len, int *ptyp, bool *comma)
{ {
int i, pretty = (ptyp) ? *ptyp : 3; int i, pretty = (ptyp) ? *ptyp : 3;
bool b = false, pty[3] = {true, true, true}; bool b = false, pty[3] = {true,true,true};
PJSON jsp = NULL; PJSON jsp = NULL, jp = NULL;
STRG src;
if (trace(1)) if (trace(1))
htrc("ParseJson: s=%.10s len=%d\n", s, len); htrc("ParseJson: s=%.10s len=%d\n", s, len);
...@@ -106,27 +105,29 @@ PJSON ParseJson(PGLOBAL g, char *s, int len, int *ptyp, bool *comma) ...@@ -106,27 +105,29 @@ PJSON ParseJson(PGLOBAL g, char *s, int len, int *ptyp, bool *comma)
} else if (comma) } else if (comma)
*comma = false; *comma = false;
src.str = s;
src.len = len;
// Trying to guess the pretty format // Trying to guess the pretty format
if (s[0] == '[' && (s[1] == '\n' || (s[1] == '\r' && s[2] == '\n'))) if (s[0] == '[' && (s[1] == '\n' || (s[1] == '\r' && s[2] == '\n')))
pty[0] = false; pty[0] = false;
try { try {
for (i = 0; i < len; i++) jp = new(g) JSON();
jp->s = s;
jp->len = len;
jp->pty = pty;
for (i = 0; i < jp->len; i++)
switch (s[i]) { switch (s[i]) {
case '[': case '[':
if (jsp) if (jsp)
goto tryit; jsp = jp->ParseAsArray(g, i, pretty, ptyp);
else if (!(jsp = ParseArray(g, ++i, src, pty))) else
throw 1; jsp = jp->ParseArray(g, ++i);
break; break;
case '{': case '{':
if (jsp) if (jsp)
goto tryit; jsp = jp->ParseAsArray(g, i, pretty, ptyp);
else if (!(jsp = ParseObject(g, ++i, src, pty))) else if (!(jsp = jp->ParseObject(g, ++i)))
throw 2; throw 2;
break; break;
...@@ -157,8 +158,8 @@ PJSON ParseJson(PGLOBAL g, char *s, int len, int *ptyp, bool *comma) ...@@ -157,8 +158,8 @@ PJSON ParseJson(PGLOBAL g, char *s, int len, int *ptyp, bool *comma)
default: default:
if (jsp) if (jsp)
goto tryit; jsp = jp->ParseAsArray(g, i, pretty, ptyp);
else if (!(jsp = ParseValue(g, i, src, pty))) else if (!(jsp = jp->ParseValue(g, i)))
throw 4; throw 4;
break; break;
...@@ -187,10 +188,17 @@ PJSON ParseJson(PGLOBAL g, char *s, int len, int *ptyp, bool *comma) ...@@ -187,10 +188,17 @@ PJSON ParseJson(PGLOBAL g, char *s, int len, int *ptyp, bool *comma)
} // end catch } // end catch
return jsp; return jsp;
} // end of ParseJson
tryit: /***********************************************************************/
/* Parse several items as being in an array. */
/***********************************************************************/
PJAR JSON::ParseAsArray(PGLOBAL g, int& i, int pretty, int *ptyp)
{
if (pty[0] && (!pretty || pretty > 2)) { if (pty[0] && (!pretty || pretty > 2)) {
if ((jsp = ParseArray(g, (i = 0), src, pty)) && ptyp && pretty == 3) PJAR jsp;
if ((jsp = ParseArray(g, (i = 0))) && ptyp && pretty == 3)
*ptyp = (pty[0]) ? 0 : 3; *ptyp = (pty[0]) ? 0 : 3;
return jsp; return jsp;
...@@ -198,26 +206,23 @@ PJSON ParseJson(PGLOBAL g, char *s, int len, int *ptyp, bool *comma) ...@@ -198,26 +206,23 @@ PJSON ParseJson(PGLOBAL g, char *s, int len, int *ptyp, bool *comma)
strcpy(g->Message, "More than one item in file"); strcpy(g->Message, "More than one item in file");
return NULL; return NULL;
} // end of ParseJson } // end of ParseAsArray
/***********************************************************************/ /***********************************************************************/
/* Parse a JSON Array. */ /* Parse a JSON Array. */
/***********************************************************************/ /***********************************************************************/
PJAR ParseArray(PGLOBAL g, int& i, STRG& src, bool *pty) PJAR JSON::ParseArray(PGLOBAL g, int& i)
{ {
char *s = src.str; int level = 0;
int len = src.len; bool b = (!i);
int level = 0; PJAR jarp = new(g) JARRAY;
bool b = (!i);
PJAR jarp = new(g) JARRAY;
PJVAL jvp = NULL;
for (; i < len; i++) for (; i < len; i++)
switch (s[i]) { switch (s[i]) {
case ',': case ',':
if (level < 2) { if (level < 2) {
sprintf(g->Message, "Unexpected ',' near %.*s",ARGS); sprintf(g->Message, "Unexpected ',' near %.*s",ARGS);
return NULL; throw 1;
} else } else
level = 1; level = 1;
...@@ -225,8 +230,8 @@ PJAR ParseArray(PGLOBAL g, int& i, STRG& src, bool *pty) ...@@ -225,8 +230,8 @@ PJAR ParseArray(PGLOBAL g, int& i, STRG& src, bool *pty)
case ']': case ']':
if (level == 1) { if (level == 1) {
sprintf(g->Message, "Unexpected ',]' near %.*s", ARGS); sprintf(g->Message, "Unexpected ',]' near %.*s", ARGS);
return NULL; throw 1;
} // endif level } // endif level
jarp->InitArray(g); jarp->InitArray(g);
return jarp; return jarp;
...@@ -240,11 +245,9 @@ PJAR ParseArray(PGLOBAL g, int& i, STRG& src, bool *pty) ...@@ -240,11 +245,9 @@ PJAR ParseArray(PGLOBAL g, int& i, STRG& src, bool *pty)
default: default:
if (level == 2) { if (level == 2) {
sprintf(g->Message, "Unexpected value near %.*s", ARGS); sprintf(g->Message, "Unexpected value near %.*s", ARGS);
return NULL; throw 1;
} else if ((jvp = ParseValue(g, i, src, pty))) } else
jarp->AddValue(g, jvp); jarp->AddValue(g, ParseValue(g, i));
else
return NULL;
level = (b) ? 1 : 2; level = (b) ? 1 : 2;
break; break;
...@@ -256,18 +259,15 @@ PJAR ParseArray(PGLOBAL g, int& i, STRG& src, bool *pty) ...@@ -256,18 +259,15 @@ PJAR ParseArray(PGLOBAL g, int& i, STRG& src, bool *pty)
return jarp; return jarp;
} // endif b } // endif b
strcpy(g->Message, "Unexpected EOF in array"); throw ("Unexpected EOF in array");
return NULL;
} // end of ParseArray } // end of ParseArray
/***********************************************************************/ /***********************************************************************/
/* Parse a JSON Object. */ /* Parse a JSON Object. */
/***********************************************************************/ /***********************************************************************/
PJOB ParseObject(PGLOBAL g, int& i, STRG& src, bool *pty) PJOB JSON::ParseObject(PGLOBAL g, int& i)
{ {
PSZ key; PSZ key;
char *s = src.str;
int len = src.len;
int level = 0; int level = 0;
PJOB jobp = new(g) JOBJECT; PJOB jobp = new(g) JOBJECT;
PJPR jpp = NULL; PJPR jpp = NULL;
...@@ -276,42 +276,37 @@ PJOB ParseObject(PGLOBAL g, int& i, STRG& src, bool *pty) ...@@ -276,42 +276,37 @@ PJOB ParseObject(PGLOBAL g, int& i, STRG& src, bool *pty)
switch (s[i]) { switch (s[i]) {
case '"': case '"':
if (level < 2) { if (level < 2) {
if ((key = ParseString(g, ++i, src))) { key = ParseString(g, ++i);
jpp = jobp->AddPair(g, key); jpp = jobp->AddPair(g, key);
level = 1; level = 1;
} else
return NULL;
} else { } else {
sprintf(g->Message, "misplaced string near %.*s", ARGS); sprintf(g->Message, "misplaced string near %.*s", ARGS);
return NULL; throw 2;
} // endif level } // endif level
break; break;
case ':': case ':':
if (level == 1) { if (level == 1) {
if (!(jpp->Val = ParseValue(g, ++i, src, pty))) jpp->Val = ParseValue(g, ++i);
return NULL;
level = 2; level = 2;
} else { } else {
sprintf(g->Message, "Unexpected ':' near %.*s", ARGS); sprintf(g->Message, "Unexpected ':' near %.*s", ARGS);
return NULL; throw 2;
} // endif level } // endif level
break; break;
case ',': case ',':
if (level < 2) { if (level < 2) {
sprintf(g->Message, "Unexpected ',' near %.*s", ARGS); sprintf(g->Message, "Unexpected ',' near %.*s", ARGS);
return NULL; throw 2;
} else } else
level = 1; level = 0;
break; break;
case '}': case '}':
if (level == 1) { if (level < 2) {
sprintf(g->Message, "Unexpected '}' near %.*s", ARGS); sprintf(g->Message, "Unexpected '}' near %.*s", ARGS);
return NULL; throw 2;
} // endif level } // endif level
return jobp; return jobp;
...@@ -324,20 +319,19 @@ PJOB ParseObject(PGLOBAL g, int& i, STRG& src, bool *pty) ...@@ -324,20 +319,19 @@ PJOB ParseObject(PGLOBAL g, int& i, STRG& src, bool *pty)
default: default:
sprintf(g->Message, "Unexpected character '%c' near %.*s", sprintf(g->Message, "Unexpected character '%c' near %.*s",
s[i], ARGS); s[i], ARGS);
return NULL; throw 2;
}; // endswitch s[i] }; // endswitch s[i]
strcpy(g->Message, "Unexpected EOF in Object"); strcpy(g->Message, "Unexpected EOF in Object");
return NULL; throw 2;
} // end of ParseObject } // end of ParseObject
/***********************************************************************/ /***********************************************************************/
/* Parse a JSON Value. */ /* Parse a JSON Value. */
/***********************************************************************/ /***********************************************************************/
PJVAL ParseValue(PGLOBAL g, int& i, STRG& src, bool *pty) PJVAL JSON::ParseValue(PGLOBAL g, int& i)
{ {
char *strval, *s = src.str; int n;
int n, len = src.len;
PJVAL jvp = new(g) JVALUE; PJVAL jvp = new(g) JVALUE;
for (; i < len; i++) for (; i < len; i++)
...@@ -355,21 +349,13 @@ PJVAL ParseValue(PGLOBAL g, int& i, STRG& src, bool *pty) ...@@ -355,21 +349,13 @@ PJVAL ParseValue(PGLOBAL g, int& i, STRG& src, bool *pty)
suite: suite:
switch (s[i]) { switch (s[i]) {
case '[': case '[':
if (!(jvp->Jsp = ParseArray(g, ++i, src, pty))) jvp->Jsp = ParseArray(g, ++i);
return NULL;
break; break;
case '{': case '{':
if (!(jvp->Jsp = ParseObject(g, ++i, src, pty))) jvp->Jsp = ParseObject(g, ++i);
return NULL;
break; break;
case '"': case '"':
if ((strval = ParseString(g, ++i, src))) jvp->Value = AllocateValue(g, ParseString(g, ++i), TYPE_STRING);
jvp->Value = AllocateValue(g, strval, TYPE_STRING);
else
return NULL;
break; break;
case 't': case 't':
if (!strncmp(s + i, "true", 4)) { if (!strncmp(s + i, "true", 4)) {
...@@ -398,11 +384,9 @@ PJVAL ParseValue(PGLOBAL g, int& i, STRG& src, bool *pty) ...@@ -398,11 +384,9 @@ PJVAL ParseValue(PGLOBAL g, int& i, STRG& src, bool *pty)
break; break;
case '-': case '-':
default: default:
if (s[i] == '-' || isdigit(s[i])) { if (s[i] == '-' || isdigit(s[i]))
if (!(jvp->Value = ParseNumeric(g, i, src))) jvp->Value = ParseNumeric(g, i);
goto err; else
} else
goto err; goto err;
}; // endswitch s[i] }; // endswitch s[i]
...@@ -410,25 +394,21 @@ PJVAL ParseValue(PGLOBAL g, int& i, STRG& src, bool *pty) ...@@ -410,25 +394,21 @@ PJVAL ParseValue(PGLOBAL g, int& i, STRG& src, bool *pty)
return jvp; return jvp;
err: err:
sprintf(g->Message, "Unexpected character '%c' near %.*s", sprintf(g->Message, "Unexpected character '%c' near %.*s", s[i], ARGS);
s[i], ARGS); throw 3;
return NULL;
} // end of ParseValue } // end of ParseValue
/***********************************************************************/ /***********************************************************************/
/* Unescape and parse a JSON string. */ /* Unescape and parse a JSON string. */
/***********************************************************************/ /***********************************************************************/
char *ParseString(PGLOBAL g, int& i, STRG& src) char *JSON::ParseString(PGLOBAL g, int& i)
{ {
char *s = src.str;
uchar *p; uchar *p;
int n = 0, len = src.len; int n = 0;
// Be sure of memory availability // Be sure of memory availability
if ((unsigned)(len + 1 - i) > ((PPOOLHEADER)g->Sarea)->FreeBlk) { if (((size_t)len + 1 - i) > ((PPOOLHEADER)g->Sarea)->FreeBlk)
strcpy(g->Message, "ParseString: Out of memory"); throw("ParseString: Out of memory");
return NULL;
} // endif len
// The size to allocate is not known yet // The size to allocate is not known yet
p = (uchar*)PlugSubAlloc(g, NULL, 0); p = (uchar*)PlugSubAlloc(g, NULL, 0);
...@@ -502,17 +482,16 @@ char *ParseString(PGLOBAL g, int& i, STRG& src) ...@@ -502,17 +482,16 @@ char *ParseString(PGLOBAL g, int& i, STRG& src)
}; // endswitch s[i] }; // endswitch s[i]
err: err:
strcpy(g->Message, "Unexpected EOF in String"); throw("Unexpected EOF in String");
return NULL;
} // end of ParseString } // end of ParseString
/***********************************************************************/ /***********************************************************************/
/* Parse a JSON numeric value. */ /* Parse a JSON numeric value. */
/***********************************************************************/ /***********************************************************************/
PVAL ParseNumeric(PGLOBAL g, int& i, STRG& src) PVAL JSON::ParseNumeric(PGLOBAL g, int& i)
{ {
char *s = src.str, buf[50]; char buf[50];
int n = 0, len = src.len; int n = 0;
short nd = 0; short nd = 0;
bool has_dot = false; bool has_dot = false;
bool has_e = false; bool has_e = false;
...@@ -575,14 +554,11 @@ PVAL ParseNumeric(PGLOBAL g, int& i, STRG& src) ...@@ -575,14 +554,11 @@ PVAL ParseNumeric(PGLOBAL g, int& i, STRG& src)
i--; // Unstack following character i--; // Unstack following character
return valp; return valp;
} else { } else
strcpy(g->Message, "No digit found"); throw("No digit found");
return NULL;
} // endif found_digit
err: err:
strcpy(g->Message, "Unexpected EOF in number"); throw("Unexpected EOF in number");
return NULL;
} // end of ParseNumeric } // end of ParseNumeric
/***********************************************************************/ /***********************************************************************/
......
...@@ -69,12 +69,7 @@ PBSON JbinAlloc(PGLOBAL g, UDF_ARGS* args, ulong len, PJSON jsp); ...@@ -69,12 +69,7 @@ PBSON JbinAlloc(PGLOBAL g, UDF_ARGS* args, ulong len, PJSON jsp);
char *NextChr(PSZ s, char sep); char *NextChr(PSZ s, char sep);
char *GetJsonNull(void); char *GetJsonNull(void);
PJSON ParseJson(PGLOBAL g, char *s, int n, int *prty = NULL, bool *b = NULL); PJSON ParseJson(PGLOBAL g, char* s, int n, int* prty = NULL, bool* b = NULL);
PJAR ParseArray(PGLOBAL g, int& i, STRG& src, bool *pty);
PJOB ParseObject(PGLOBAL g, int& i, STRG& src, bool *pty);
PJVAL ParseValue(PGLOBAL g, int& i, STRG& src, bool *pty);
char *ParseString(PGLOBAL g, int& i, STRG& src);
PVAL ParseNumeric(PGLOBAL g, int& i, STRG& src);
PSZ Serialize(PGLOBAL g, PJSON jsp, char *fn, int pretty); PSZ Serialize(PGLOBAL g, PJSON jsp, char *fn, int pretty);
bool SerializeArray(JOUT *js, PJAR jarp, bool b); bool SerializeArray(JOUT *js, PJAR jarp, bool b);
bool SerializeObject(JOUT *js, PJOB jobp); bool SerializeObject(JOUT *js, PJOB jobp);
...@@ -152,7 +147,7 @@ class JOUTPRT : public JOUTFILE { ...@@ -152,7 +147,7 @@ class JOUTPRT : public JOUTFILE {
class JPAIR : public BLOCK { class JPAIR : public BLOCK {
friend class JOBJECT; friend class JOBJECT;
friend class JSNX; friend class JSNX;
friend PJOB ParseObject(PGLOBAL, int&, STRG&, bool*); friend class JSON;
friend bool SerializeObject(JOUT *, PJOB); friend bool SerializeObject(JOUT *, PJOB);
public: public:
JPAIR(PCSZ key) : BLOCK() {Key = key; Val = NULL; Next = NULL;} JPAIR(PCSZ key) : BLOCK() {Key = key; Val = NULL; Next = NULL;}
...@@ -171,8 +166,9 @@ class JPAIR : public BLOCK { ...@@ -171,8 +166,9 @@ class JPAIR : public BLOCK {
/* Class JSON. The base class for all other json classes. */ /* Class JSON. The base class for all other json classes. */
/***********************************************************************/ /***********************************************************************/
class JSON : public BLOCK { class JSON : public BLOCK {
friend PJSON ParseJson(PGLOBAL, char*, int, int*, bool*);
public: public:
JSON(void) {Size = 0;} JSON(void) : s(NULL), len(0), pty(NULL) {Size = 0;}
int size(void) {return Size;} int size(void) {return Size;}
virtual int GetSize(bool b) {return Size;} virtual int GetSize(bool b) {return Size;}
...@@ -209,14 +205,27 @@ class JSON : public BLOCK { ...@@ -209,14 +205,27 @@ class JSON : public BLOCK {
virtual bool IsNull(void) {X return true;} virtual bool IsNull(void) {X return true;}
protected: protected:
int Size; PJAR ParseArray(PGLOBAL g, int& i);
PJOB ParseObject(PGLOBAL g, int& i);
PJVAL ParseValue(PGLOBAL g, int& i);
char *ParseString(PGLOBAL g, int& i);
PVAL ParseNumeric(PGLOBAL g, int& i);
PJAR ParseAsArray(PGLOBAL g, int& i, int pretty, int *ptyp);
// Members
int Size;
// Only used when parsing
private:
char *s;
int len;
bool *pty;
}; // end of class JSON }; // end of class JSON
/***********************************************************************/ /***********************************************************************/
/* Class JOBJECT: contains a list of value pairs. */ /* Class JOBJECT: contains a list of value pairs. */
/***********************************************************************/ /***********************************************************************/
class JOBJECT : public JSON { class JOBJECT : public JSON {
friend PJOB ParseObject(PGLOBAL, int&, STRG&, bool*);
friend bool SerializeObject(JOUT *, PJOB); friend bool SerializeObject(JOUT *, PJOB);
friend class JSNX; friend class JSNX;
public: public:
...@@ -282,8 +291,8 @@ class JVALUE : public JSON { ...@@ -282,8 +291,8 @@ class JVALUE : public JSON {
friend class JARRAY; friend class JARRAY;
friend class JSNX; friend class JSNX;
friend class JSONCOL; friend class JSONCOL;
friend PJVAL ParseValue(PGLOBAL, int&, STRG&, bool*); friend class JSON;
friend bool SerializeValue(JOUT *, PJVAL); friend bool SerializeValue(JOUT*, PJVAL);
public: public:
JVALUE(void) : JSON() {Clear();} JVALUE(void) : JSON() {Clear();}
JVALUE(PJSON jsp); JVALUE(PJSON jsp);
......
...@@ -1076,27 +1076,6 @@ my_bool JSNX::AddPath(void) ...@@ -1076,27 +1076,6 @@ my_bool JSNX::AddPath(void)
/* --------------------------------- JSON UDF ---------------------------------- */ /* --------------------------------- JSON UDF ---------------------------------- */
#if 0 // Moved to json.h
// BSON size should be equal on Linux and Windows
#define BMX 255
typedef struct BSON *PBSON;
/*********************************************************************************/
/* Structure used to return binary json. */
/*********************************************************************************/
struct BSON {
char Msg[BMX + 1];
char *Filename;
PGLOBAL G;
int Pretty;
ulong Reslen;
my_bool Changed;
PJSON Top;
PJSON Jsp;
PBSON Bsp;
}; // end of struct BSON
#endif // 0
/*********************************************************************************/ /*********************************************************************************/
/* Allocate and initialize a BSON structure. */ /* Allocate and initialize a BSON structure. */
/*********************************************************************************/ /*********************************************************************************/
...@@ -1146,7 +1125,7 @@ static my_bool JsonSubSet(PGLOBAL g) ...@@ -1146,7 +1125,7 @@ static my_bool JsonSubSet(PGLOBAL g)
{ {
PPOOLHEADER pph = (PPOOLHEADER)g->Sarea; PPOOLHEADER pph = (PPOOLHEADER)g->Sarea;
pph->To_Free = (OFFSET)((g->Createas) ? g->Createas : sizeof(POOLHEADER)); pph->To_Free = (g->Saved_Size) ? g->Saved_Size : (size_t)sizeof(POOLHEADER);
pph->FreeBlk = g->Sarea_Size - pph->To_Free; pph->FreeBlk = g->Sarea_Size - pph->To_Free;
return FALSE; return FALSE;
} /* end of JsonSubSet */ } /* end of JsonSubSet */
...@@ -1156,7 +1135,7 @@ static my_bool JsonSubSet(PGLOBAL g) ...@@ -1156,7 +1135,7 @@ static my_bool JsonSubSet(PGLOBAL g)
/*********************************************************************************/ /*********************************************************************************/
inline void JsonMemSave(PGLOBAL g) inline void JsonMemSave(PGLOBAL g)
{ {
g->Createas = (int)((PPOOLHEADER)g->Sarea)->To_Free; g->Saved_Size = ((PPOOLHEADER)g->Sarea)->To_Free;
} /* end of JsonMemSave */ } /* end of JsonMemSave */
/*********************************************************************************/ /*********************************************************************************/
...@@ -1627,7 +1606,7 @@ static my_bool CheckMemory(PGLOBAL g, UDF_INIT *initid, UDF_ARGS *args, uint n, ...@@ -1627,7 +1606,7 @@ static my_bool CheckMemory(PGLOBAL g, UDF_INIT *initid, UDF_ARGS *args, uint n,
return true; return true;
} // endif SareaAlloc } // endif SareaAlloc
g->Createas = 0; g->Saved_Size = 0;
g->Xchk = NULL; g->Xchk = NULL;
initid->max_length = rl; initid->max_length = rl;
} // endif Size } // endif Size
...@@ -4501,6 +4480,7 @@ my_bool jfile_make_init(UDF_INIT *initid, UDF_ARGS *args, char *message) ...@@ -4501,6 +4480,7 @@ my_bool jfile_make_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
} // endif } // endif
CalcLen(args, false, reslen, memlen); CalcLen(args, false, reslen, memlen);
memlen = memlen + 5000; // To take care of not pretty files
return JsonInit(initid, args, message, true, reslen, memlen); return JsonInit(initid, args, message, true, reslen, memlen);
} // end of jfile_make_init } // end of jfile_make_init
...@@ -5781,6 +5761,478 @@ void json_serialize_deinit(UDF_INIT* initid) ...@@ -5781,6 +5761,478 @@ void json_serialize_deinit(UDF_INIT* initid)
JsonFreeMem((PGLOBAL)initid->ptr); JsonFreeMem((PGLOBAL)initid->ptr);
} // end of json_serialize_deinit } // end of json_serialize_deinit
/*********************************************************************************/
/* Convert a prettiest Json file to Pretty=0. */
/*********************************************************************************/
my_bool jfile_convert_init(UDF_INIT* initid, UDF_ARGS* args, char* message) {
unsigned long reslen, memlen;
if (args->arg_count != 3) {
strcpy(message, "This function must have 3 arguments");
return true;
} else if (args->arg_type[2] != INT_RESULT) {
strcpy(message, "Third Argument must be an integer (LRECL)");
return true;
} else for (int i = 0; i < 2; i++)
if (args->arg_type[i] != STRING_RESULT) {
sprintf(message, "Arguments %d must be a string (file name)", i+1);
return true;
} // endif args
CalcLen(args, false, reslen, memlen);
return JsonInit(initid, args, message, false, reslen, memlen);
} // end of jfile_convert_init
char *jfile_convert(UDF_INIT* initid, UDF_ARGS* args, char* result,
unsigned long *res_length, char *, char *error) {
char *str, *fn, *ofn;
int lrecl = (int)*(longlong*)args->args[2];
PGLOBAL g = (PGLOBAL)initid->ptr;
PlugSubSet(g->Sarea, g->Sarea_Size);
fn = MakePSZ(g, args, 0);
ofn = MakePSZ(g, args, 1);
if (!g->Xchk) {
JUP* jup = new(g) JUP(g);
str = jup->UnprettyJsonFile(g, fn, ofn, lrecl);
g->Xchk = str;
} else
str = (char*)g->Xchk;
if (!str) {
if (g->Message)
str = PlugDup(g, g->Message);
else
str = PlugDup(g, "Unexpected error");
} // endif str
*res_length = strlen(str);
return str;
} // end of jfile_convert
void jfile_convert_deinit(UDF_INIT* initid) {
JsonFreeMem((PGLOBAL)initid->ptr);
} // end of jfile_convert_deinit
/* --------------------------------- Class JUP --------------------------------- */
#define ARGS MY_MIN(24,len-i),s+MY_MAX(i-3,0)
/*********************************************************************************/
/* JUP public constructor. */
/*********************************************************************************/
JUP::JUP(PGLOBAL g) {
fs = NULL;
s = buff = NULL;
i = k = len = recl = 0;
} // end of JUP constructor
/*********************************************************************************/
/* Copy a json file to another with pretty = 0. */
/*********************************************************************************/
char* JUP::UnprettyJsonFile(PGLOBAL g, char *fn, char *outfn, int lrecl) {
char *ret = NULL;
HANDLE hFile;
MEMMAP mm;
/*******************************************************************************/
/* Create the mapping file object. */
/*******************************************************************************/
hFile = CreateFileMap(g, fn, &mm, MODE_READ, false);
if (hFile == INVALID_HANDLE_VALUE) {
DWORD rc = GetLastError();
if (!(*g->Message))
sprintf(g->Message, MSG(OPEN_MODE_ERROR), "map", (int)rc, fn);
return NULL;
} // endif hFile
/*******************************************************************************/
/* Get the file size (assuming file is smaller than 4 GB) */
/*******************************************************************************/
if (!mm.lenL) { // Empty or deleted file
CloseFileHandle(hFile);
return NULL;
} else
len = (int)mm.lenL;
if (!mm.memory) {
CloseFileHandle(hFile);
sprintf(g->Message, MSG(MAP_VIEW_ERROR), fn, GetLastError());
return NULL;
} else
s = (char*)mm.memory;
CloseFileHandle(hFile); // Not used anymore
/*********************************************************************************/
/* Parse the json file and allocate its tree structure. */
/*********************************************************************************/
if (!(fs = fopen(outfn, "wb"))) {
sprintf(g->Message, MSG(OPEN_MODE_ERROR),
"w", (int)errno, outfn);
strcat(strcat(g->Message, ": "), strerror(errno));
CloseMemMap(mm.memory, (size_t)mm.lenL);
return NULL;
} // endif fs
g->Message[0] = 0;
if (!unPretty(g, lrecl))
ret = outfn;
CloseMemMap(mm.memory, (size_t)mm.lenL);
fclose(fs);
return ret;
} // end of UnprettyJsonFile
/***********************************************************************/
/* Translate a json file to pretty = 0. */
/***********************************************************************/
bool JUP::unPretty(PGLOBAL g, int lrecl) {
bool go, next, rc = false;
if (trace(1))
htrc("UnPretty: s=%.10s len=%zd lrecl=%d\n", s, len, lrecl);
if (!s || !len) {
strcpy(g->Message, "Void JSON file");
return true;
} else if (*s != '[') {
// strcpy(g->Message, "JSON file is not an array");
s = strchr(s, '[');
// return true;
} // endif s
i = 1;
go = next = true;
try {
// Allocate the record
buff = (char*)PlugSubAlloc(g, NULL, (size_t)lrecl + 3);
recl = lrecl;
do {
for (k = 0; go && i < len; i++)
switch (s[i]) {
case '{':
buff[k++] = s[i++];
CopyObject(g);
break;
case '[':
throw "JSON file is not an array of objects";
break;
case ' ':
case '\t':
case '\n':
case '\r':
break;
case ',':
go = false;
break;
case ']':
go = next = false;
break;
default:
sprintf(g->Message, "Unexpected '%c' near %.*s", s[i], ARGS);
throw 4;
break;
}; // endswitch s[i]
// Write the record
#ifdef __win_
buff[k++] = '\r';
#endif
buff[k++] = '\n';
buff[k] = 0;
if ((fputs(buff, fs)) == EOF) {
sprintf(g->Message, MSG(FPUTS_ERROR), strerror(errno));
throw 5;
} // endif EOF
go = true;
} while (next);
} catch (int n) {
if (trace(1))
htrc("Exception %d: %s\n", n, g->Message);
rc = true;
} catch (const char* msg) {
strcpy(g->Message, msg);
rc = true;
} // end catch
return rc;
} // end of unPretty
/***********************************************************************/
/* Copy a JSON Object. */
/***********************************************************************/
void JUP::CopyObject(PGLOBAL g) {
int level = 0;
for (; i < len; i++)
switch (s[i]) {
case '"':
AddBuff(s[i++]);
if (level < 2) {
CopyString(g);
level = 1;
} else {
sprintf(g->Message, "misplaced string near %.*s", ARGS);
throw 3;
} // endif level
break;
case ':':
AddBuff(s[i++]);
if (level == 1) {
CopyValue(g);
level = 2;
} else {
sprintf(g->Message, "Unexpected ':' near %.*s", ARGS);
throw 3;
} // endif level
break;
case ',':
AddBuff(s[i]);
if (level < 2) {
sprintf(g->Message, "Unexpected ',' near %.*s", ARGS);
throw 3;
} else
level = 0;
break;
case '}':
AddBuff(s[i]);
if (level == 1) {
sprintf(g->Message, "Unexpected '}' near %.*s", ARGS);
throw 3;
} // endif level
return;
case '\n':
case '\r':
case ' ':
case '\t':
break;
default:
sprintf(g->Message, "Unexpected character '%c' near %.*s", s[i], ARGS);
throw 3;
}; // endswitch s[i]
throw "Unexpected EOF in Object";
} // end of CopyObject
/***********************************************************************/
/* Copy a JSON Array. */
/***********************************************************************/
void JUP::CopyArray(PGLOBAL g) {
int level = 0;
for (; i < len; i++)
switch (s[i]) {
case ',':
if (level < 2) {
sprintf(g->Message, "Unexpected ',' near %.*s", ARGS);
throw 2;
} else
level = 1;
AddBuff(s[i]);
break;
case ']':
if (level == 1) {
sprintf(g->Message, "Unexpected ',]' near %.*s", ARGS);
throw 2;
} // endif level
AddBuff(s[i]);
return;
case '\n':
case '\r':
case ' ':
case '\t':
break;
default:
if (level == 2) {
sprintf(g->Message, "Unexpected value near %.*s", ARGS);
throw 2;
} // endif level
CopyValue(g);
level = 2;
break;
}; // endswitch s[i]
throw "Unexpected EOF in array";
} // end of CopyArray
/***********************************************************************/
/* Copy a JSON Value. */
/***********************************************************************/
void JUP::CopyValue(PGLOBAL g) {
for (; i < len; i++)
switch (s[i]) {
case '\n':
case '\r':
case ' ':
case '\t':
break;
default:
goto suite;
} // endswitch
suite:
switch (s[i]) {
case '[':
AddBuff(s[i++]);
CopyArray(g);
break;
case '{':
AddBuff(s[i++]);
CopyObject(g);
break;
case '"':
AddBuff(s[i++]);
CopyString(g);
break;
case 't':
if (!strncmp(s + i, "true", 4)) {
AddBuff(s[i++]);
AddBuff(s[i++]);
AddBuff(s[i++]);
AddBuff(s[i]);
} else
goto err;
break;
case 'f':
if (!strncmp(s + i, "false", 5)) {
AddBuff(s[i++]);
AddBuff(s[i++]);
AddBuff(s[i++]);
AddBuff(s[i++]);
AddBuff(s[i]);
} else
goto err;
break;
case 'n':
if (!strncmp(s + i, "null", 4)) {
AddBuff(s[i++]);
AddBuff(s[i++]);
AddBuff(s[i++]);
AddBuff(s[i]);
} else
goto err;
break;
default:
if (s[i] == '-' || isdigit(s[i]))
CopyNumeric(g);
else
goto err;
}; // endswitch s[i]
return;
err:
sprintf(g->Message, "Unexpected character '%c' near %.*s", s[i], ARGS);
throw 1;
} // end of CopyValue
/***********************************************************************/
/* Unescape and parse a JSON string. */
/***********************************************************************/
void JUP::CopyString(PGLOBAL g) {
for (; i < len; i++) {
AddBuff(s[i]);
switch (s[i]) {
case '"':
return;
case '\\':
AddBuff(s[++i]);
break;
default:
break;
}; // endswitch s[i]
} // endfor i
throw "Unexpected EOF in String";
} // end of CopyString
/***********************************************************************/
/* Copy a JSON numeric value. */
/***********************************************************************/
void JUP::CopyNumeric(PGLOBAL g) {
bool has_dot = false;
bool has_e = false;
bool found_digit = false;
for (; i < len; i++) {
switch (s[i]) {
case '.':
if (!found_digit || has_dot || has_e)
goto err;
has_dot = true;
break;
case 'e':
case 'E':
if (!found_digit || has_e)
goto err;
has_e = true;
found_digit = false;
break;
case '+':
if (!has_e)
goto err;
// fall through
case '-':
if (found_digit)
goto err;
break;
default:
if (isdigit(s[i])) {
found_digit = true;
} else
goto fin;
}; // endswitch s[i]
AddBuff(s[i]);
} // endfor i
fin:
if (!found_digit)
throw "No digit found";
else
i--;
return;
err:
throw "Unexpected EOF in number";
} // end of CopyNumeric
/*********************************************************************************/ /*********************************************************************************/
/* Utility function returning an environment variable value. */ /* Utility function returning an environment variable value. */
/*********************************************************************************/ /*********************************************************************************/
......
...@@ -235,6 +235,10 @@ extern "C" { ...@@ -235,6 +235,10 @@ extern "C" {
DllExport char *json_serialize(UDF_EXEC_ARGS); DllExport char *json_serialize(UDF_EXEC_ARGS);
DllExport void json_serialize_deinit(UDF_INIT*); DllExport void json_serialize_deinit(UDF_INIT*);
DllExport my_bool jfile_convert_init(UDF_INIT*, UDF_ARGS*, char*);
DllExport char* jfile_convert(UDF_EXEC_ARGS);
DllExport void jfile_convert_deinit(UDF_INIT*);
DllExport my_bool envar_init(UDF_INIT*, UDF_ARGS*, char*); DllExport my_bool envar_init(UDF_INIT*, UDF_ARGS*, char*);
DllExport char *envar(UDF_EXEC_ARGS); DllExport char *envar(UDF_EXEC_ARGS);
...@@ -324,3 +328,38 @@ class JSNX : public BLOCK { ...@@ -324,3 +328,38 @@ class JSNX : public BLOCK {
my_bool Wr; // Write mode my_bool Wr; // Write mode
my_bool Jb; // Must return json item my_bool Jb; // Must return json item
}; // end of class JSNX }; // end of class JSNX
/*********************************************************************************/
/* Class JUP: used by jfile_convert to make a json file pretty = 0. */
/*********************************************************************************/
class JUP : public BLOCK {
public:
// Constructor
JUP(PGLOBAL g);
// Implementation
void AddBuff(char c) {
if (k < recl)
buff[k++] = c;
else
throw "Record size is too small";
} // end of AddBuff
// Methods
char *UnprettyJsonFile(PGLOBAL g, char* fn, char* outfn, int lrecl);
bool unPretty(PGLOBAL g, int lrecl);
void CopyObject(PGLOBAL g);
void CopyArray(PGLOBAL g);
void CopyValue(PGLOBAL g);
void CopyString(PGLOBAL g);
void CopyNumeric(PGLOBAL g);
// Members
FILE* fs;
char* s;
char* buff;
int len;
int recl;
int i, k;
}; // end of class JUP
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
bool MakeSelector(PGLOBAL g, PFIL fp, PSTRG s); bool MakeSelector(PGLOBAL g, PFIL fp, PSTRG s);
bool IsNum(PSZ s); bool IsNum(PSZ s);
int GetDefaultDepth(void);
/***********************************************************************/ /***********************************************************************/
/* Make selector json representation for Mongo tables. */ /* Make selector json representation for Mongo tables. */
...@@ -248,15 +249,10 @@ MGODISC::MGODISC(PGLOBAL g, int *lg) { ...@@ -248,15 +249,10 @@ MGODISC::MGODISC(PGLOBAL g, int *lg) {
/***********************************************************************/ /***********************************************************************/
int MGODISC::GetColumns(PGLOBAL g, PCSZ db, PCSZ uri, PTOS topt) int MGODISC::GetColumns(PGLOBAL g, PCSZ db, PCSZ uri, PTOS topt)
{ {
PCSZ level = GetStringTableOption(g, topt, "Level", NULL);
PMGODEF tdp; PMGODEF tdp;
if (level = GetStringTableOption(g, topt, "Depth", level)) { lvl = GetIntegerTableOption(g, topt, "Level", GetDefaultDepth());
lvl = atoi(level); lvl = GetIntegerTableOption(g, topt, "Depth", lvl);
lvl = (lvl > 16) ? 16 : lvl;
} else
lvl = 0;
all = GetBooleanTableOption(g, topt, "Fullarray", false); all = GetBooleanTableOption(g, topt, "Fullarray", false);
/*********************************************************************/ /*********************************************************************/
......
...@@ -20,12 +20,12 @@ SELECT * from t1; ...@@ -20,12 +20,12 @@ SELECT * from t1;
Column_Name Data_Type Type_Name Column_Size Buffer_Length Decimal_Digits Nullable Jpath Column_Name Data_Type Type_Name Column_Size Buffer_Length Decimal_Digits Nullable Jpath
_id 1 CHAR 24 24 0 0 _id _id 1 CHAR 24 24 0 0 _id
address_building 1 CHAR 10 10 0 0 address.building address_building 1 CHAR 10 10 0 0 address.building
address_coord 1 CHAR 256 256 0 1 address.coord address_coord 1 CHAR 1024 1024 0 1 address.coord
address_street 1 CHAR 38 38 0 0 address.street address_street 1 CHAR 38 38 0 0 address.street
address_zipcode 1 CHAR 5 5 0 0 address.zipcode address_zipcode 1 CHAR 5 5 0 0 address.zipcode
borough 1 CHAR 13 13 0 0 borough 1 CHAR 13 13 0 0
cuisine 1 CHAR 64 64 0 0 cuisine 1 CHAR 64 64 0 0
grades_date 1 CHAR 256 256 0 1 grades.0.date grades_date 1 CHAR 1024 1024 0 1 grades.0.date
grades_grade 1 CHAR 14 14 0 1 grades.0.grade grades_grade 1 CHAR 14 14 0 1 grades.0.grade
grades_score 5 BIGINT 2 2 0 1 grades.0.score grades_score 5 BIGINT 2 2 0 1 grades.0.score
name 1 CHAR 98 98 0 0 name 1 CHAR 98 98 0 0
...@@ -64,16 +64,16 @@ OPTION_LIST='Level=1,Driver=Java,Version=2' CONNECTION='mongodb://localhost:2701 ...@@ -64,16 +64,16 @@ OPTION_LIST='Level=1,Driver=Java,Version=2' CONNECTION='mongodb://localhost:2701
SHOW CREATE TABLE t1; SHOW CREATE TABLE t1;
Table Create Table Table Create Table
t1 CREATE TABLE `t1` ( t1 CREATE TABLE `t1` (
`_id` char(24) NOT NULL `FIELD_FORMAT`='_id', `_id` char(24) NOT NULL `JPATH`='_id',
`address_building` char(10) NOT NULL `FIELD_FORMAT`='address.building', `address_building` char(10) NOT NULL `JPATH`='address.building',
`address_coord` varchar(256) DEFAULT NULL `FIELD_FORMAT`='address.coord', `address_coord` varchar(1024) DEFAULT NULL `JPATH`='address.coord',
`address_street` char(38) NOT NULL `FIELD_FORMAT`='address.street', `address_street` char(38) NOT NULL `JPATH`='address.street',
`address_zipcode` char(5) NOT NULL `FIELD_FORMAT`='address.zipcode', `address_zipcode` char(5) NOT NULL `JPATH`='address.zipcode',
`borough` char(13) NOT NULL, `borough` char(13) NOT NULL,
`cuisine` char(64) NOT NULL, `cuisine` char(64) NOT NULL,
`grades_date` varchar(256) DEFAULT NULL `FIELD_FORMAT`='grades.0.date', `grades_date` varchar(1024) DEFAULT NULL `JPATH`='grades.0.date',
`grades_grade` char(14) DEFAULT NULL `FIELD_FORMAT`='grades.0.grade', `grades_grade` char(14) DEFAULT NULL `JPATH`='grades.0.grade',
`grades_score` bigint(2) DEFAULT NULL `FIELD_FORMAT`='grades.0.score', `grades_score` bigint(2) DEFAULT NULL `JPATH`='grades.0.score',
`name` char(98) NOT NULL, `name` char(98) NOT NULL,
`restaurant_id` char(8) NOT NULL `restaurant_id` char(8) NOT NULL
) ENGINE=CONNECT DEFAULT CHARSET=latin1 CONNECTION='mongodb://localhost:27017' `TABLE_TYPE`='JSON' `TABNAME`='restaurants' `OPTION_LIST`='Level=1,Driver=Java,Version=2' `DATA_CHARSET`='utf8' `LRECL`=4096 ) ENGINE=CONNECT DEFAULT CHARSET=latin1 CONNECTION='mongodb://localhost:27017' `TABLE_TYPE`='JSON' `TABNAME`='restaurants' `OPTION_LIST`='Level=1,Driver=Java,Version=2' `DATA_CHARSET`='utf8' `LRECL`=4096
...@@ -251,15 +251,15 @@ OPTION_LIST='Driver=Java,level=2,version=2'; ...@@ -251,15 +251,15 @@ OPTION_LIST='Driver=Java,level=2,version=2';
SHOW CREATE TABLE t1; SHOW CREATE TABLE t1;
Table Create Table Table Create Table
t1 CREATE TABLE `t1` ( t1 CREATE TABLE `t1` (
`_id` char(24) NOT NULL `FIELD_FORMAT`='_id', `_id` char(24) NOT NULL `JPATH`='_id',
`address_building` char(10) NOT NULL `FIELD_FORMAT`='address.building', `address_building` char(10) NOT NULL `JPATH`='address.building',
`address_coord` double(18,16) DEFAULT NULL `FIELD_FORMAT`='address.coord.0', `address_coord` double(18,16) DEFAULT NULL `JPATH`='address.coord.0',
`address_street` char(38) NOT NULL `FIELD_FORMAT`='address.street', `address_street` char(38) NOT NULL `JPATH`='address.street',
`address_zipcode` char(5) NOT NULL `FIELD_FORMAT`='address.zipcode', `address_zipcode` char(5) NOT NULL `JPATH`='address.zipcode',
`borough` char(13) NOT NULL, `borough` char(13) NOT NULL,
`grades_date` char(24) DEFAULT NULL `FIELD_FORMAT`='grades.0.date', `grades_date` char(24) DEFAULT NULL `JPATH`='grades.0.date',
`grades_grade` char(14) DEFAULT NULL `FIELD_FORMAT`='grades.0.grade', `grades_grade` char(14) DEFAULT NULL `JPATH`='grades.0.grade',
`grades_score` bigint(2) DEFAULT NULL `FIELD_FORMAT`='grades.0.score', `grades_score` bigint(2) DEFAULT NULL `JPATH`='grades.0.score',
`name` char(98) NOT NULL, `name` char(98) NOT NULL,
`restaurant_id` char(8) NOT NULL `restaurant_id` char(8) NOT NULL
) ENGINE=CONNECT DEFAULT CHARSET=latin1 CONNECTION='mongodb://localhost:27017' `TABLE_TYPE`='JSON' `TABNAME`='restaurants' `COLIST`='{"cuisine":0}' `FILTER`='{"cuisine":"French","borough":{"$ne":"Manhattan"}}' `OPTION_LIST`='Driver=Java,level=2,version=2' `LRECL`=4096 ) ENGINE=CONNECT DEFAULT CHARSET=latin1 CONNECTION='mongodb://localhost:27017' `TABLE_TYPE`='JSON' `TABNAME`='restaurants' `COLIST`='{"cuisine":0}' `FILTER`='{"cuisine":"French","borough":{"$ne":"Manhattan"}}' `OPTION_LIST`='Driver=Java,level=2,version=2' `LRECL`=4096
......
...@@ -20,12 +20,12 @@ SELECT * from t1; ...@@ -20,12 +20,12 @@ SELECT * from t1;
Column_Name Data_Type Type_Name Column_Size Buffer_Length Decimal_Digits Nullable Jpath Column_Name Data_Type Type_Name Column_Size Buffer_Length Decimal_Digits Nullable Jpath
_id 1 CHAR 24 24 0 0 _id _id 1 CHAR 24 24 0 0 _id
address_building 1 CHAR 10 10 0 0 address.building address_building 1 CHAR 10 10 0 0 address.building
address_coord 1 CHAR 256 256 0 1 address.coord address_coord 1 CHAR 1024 1024 0 1 address.coord
address_street 1 CHAR 38 38 0 0 address.street address_street 1 CHAR 38 38 0 0 address.street
address_zipcode 1 CHAR 5 5 0 0 address.zipcode address_zipcode 1 CHAR 5 5 0 0 address.zipcode
borough 1 CHAR 13 13 0 0 borough 1 CHAR 13 13 0 0
cuisine 1 CHAR 64 64 0 0 cuisine 1 CHAR 64 64 0 0
grades_date 1 CHAR 256 256 0 1 grades.0.date grades_date 1 CHAR 1024 1024 0 1 grades.0.date
grades_grade 1 CHAR 14 14 0 1 grades.0.grade grades_grade 1 CHAR 14 14 0 1 grades.0.grade
grades_score 5 BIGINT 2 2 0 1 grades.0.score grades_score 5 BIGINT 2 2 0 1 grades.0.score
name 1 CHAR 98 98 0 0 name 1 CHAR 98 98 0 0
...@@ -64,16 +64,16 @@ OPTION_LIST='Level=1,Driver=Java,Version=3' CONNECTION='mongodb://localhost:2701 ...@@ -64,16 +64,16 @@ OPTION_LIST='Level=1,Driver=Java,Version=3' CONNECTION='mongodb://localhost:2701
SHOW CREATE TABLE t1; SHOW CREATE TABLE t1;
Table Create Table Table Create Table
t1 CREATE TABLE `t1` ( t1 CREATE TABLE `t1` (
`_id` char(24) NOT NULL `FIELD_FORMAT`='_id', `_id` char(24) NOT NULL `JPATH`='_id',
`address_building` char(10) NOT NULL `FIELD_FORMAT`='address.building', `address_building` char(10) NOT NULL `JPATH`='address.building',
`address_coord` varchar(256) DEFAULT NULL `FIELD_FORMAT`='address.coord', `address_coord` varchar(1024) DEFAULT NULL `JPATH`='address.coord',
`address_street` char(38) NOT NULL `FIELD_FORMAT`='address.street', `address_street` char(38) NOT NULL `JPATH`='address.street',
`address_zipcode` char(5) NOT NULL `FIELD_FORMAT`='address.zipcode', `address_zipcode` char(5) NOT NULL `JPATH`='address.zipcode',
`borough` char(13) NOT NULL, `borough` char(13) NOT NULL,
`cuisine` char(64) NOT NULL, `cuisine` char(64) NOT NULL,
`grades_date` varchar(256) DEFAULT NULL `FIELD_FORMAT`='grades.0.date', `grades_date` varchar(1024) DEFAULT NULL `JPATH`='grades.0.date',
`grades_grade` char(14) DEFAULT NULL `FIELD_FORMAT`='grades.0.grade', `grades_grade` char(14) DEFAULT NULL `JPATH`='grades.0.grade',
`grades_score` bigint(2) DEFAULT NULL `FIELD_FORMAT`='grades.0.score', `grades_score` bigint(2) DEFAULT NULL `JPATH`='grades.0.score',
`name` char(98) NOT NULL, `name` char(98) NOT NULL,
`restaurant_id` char(8) NOT NULL `restaurant_id` char(8) NOT NULL
) ENGINE=CONNECT DEFAULT CHARSET=latin1 CONNECTION='mongodb://localhost:27017' `TABLE_TYPE`='JSON' `TABNAME`='restaurants' `OPTION_LIST`='Level=1,Driver=Java,Version=3' `DATA_CHARSET`='utf8' `LRECL`=4096 ) ENGINE=CONNECT DEFAULT CHARSET=latin1 CONNECTION='mongodb://localhost:27017' `TABLE_TYPE`='JSON' `TABNAME`='restaurants' `OPTION_LIST`='Level=1,Driver=Java,Version=3' `DATA_CHARSET`='utf8' `LRECL`=4096
...@@ -251,15 +251,15 @@ OPTION_LIST='Driver=Java,level=2,version=3'; ...@@ -251,15 +251,15 @@ OPTION_LIST='Driver=Java,level=2,version=3';
SHOW CREATE TABLE t1; SHOW CREATE TABLE t1;
Table Create Table Table Create Table
t1 CREATE TABLE `t1` ( t1 CREATE TABLE `t1` (
`_id` char(24) NOT NULL `FIELD_FORMAT`='_id', `_id` char(24) NOT NULL `JPATH`='_id',
`address_building` char(10) NOT NULL `FIELD_FORMAT`='address.building', `address_building` char(10) NOT NULL `JPATH`='address.building',
`address_coord` double(18,16) DEFAULT NULL `FIELD_FORMAT`='address.coord.0', `address_coord` double(18,16) DEFAULT NULL `JPATH`='address.coord.0',
`address_street` char(38) NOT NULL `FIELD_FORMAT`='address.street', `address_street` char(38) NOT NULL `JPATH`='address.street',
`address_zipcode` char(5) NOT NULL `FIELD_FORMAT`='address.zipcode', `address_zipcode` char(5) NOT NULL `JPATH`='address.zipcode',
`borough` char(13) NOT NULL, `borough` char(13) NOT NULL,
`grades_date` bigint(13) DEFAULT NULL `FIELD_FORMAT`='grades.0.date', `grades_date` bigint(13) DEFAULT NULL `JPATH`='grades.0.date',
`grades_grade` char(14) DEFAULT NULL `FIELD_FORMAT`='grades.0.grade', `grades_grade` char(14) DEFAULT NULL `JPATH`='grades.0.grade',
`grades_score` bigint(2) DEFAULT NULL `FIELD_FORMAT`='grades.0.score', `grades_score` bigint(2) DEFAULT NULL `JPATH`='grades.0.score',
`name` char(98) NOT NULL, `name` char(98) NOT NULL,
`restaurant_id` char(8) NOT NULL `restaurant_id` char(8) NOT NULL
) ENGINE=CONNECT DEFAULT CHARSET=latin1 CONNECTION='mongodb://localhost:27017' `TABLE_TYPE`='JSON' `TABNAME`='restaurants' `COLIST`='{"cuisine":0}' `FILTER`='{"cuisine":"French","borough":{"$ne":"Manhattan"}}' `OPTION_LIST`='Driver=Java,level=2,version=3' `LRECL`=4096 ) ENGINE=CONNECT DEFAULT CHARSET=latin1 CONNECTION='mongodb://localhost:27017' `TABLE_TYPE`='JSON' `TABNAME`='restaurants' `COLIST`='{"cuisine":0}' `FILTER`='{"cuisine":"French","borough":{"$ne":"Manhattan"}}' `OPTION_LIST`='Driver=Java,level=2,version=3' `LRECL`=4096
......
...@@ -20,12 +20,12 @@ SELECT * from t1; ...@@ -20,12 +20,12 @@ SELECT * from t1;
Column_Name Data_Type Type_Name Column_Size Buffer_Length Decimal_Digits Nullable Jpath Column_Name Data_Type Type_Name Column_Size Buffer_Length Decimal_Digits Nullable Jpath
_id 1 CHAR 24 24 0 0 _id _id 1 CHAR 24 24 0 0 _id
address_building 1 CHAR 10 10 0 0 address.building address_building 1 CHAR 10 10 0 0 address.building
address_coord 1 CHAR 256 256 0 1 address.coord address_coord 1 CHAR 1024 1024 0 1 address.coord
address_street 1 CHAR 38 38 0 0 address.street address_street 1 CHAR 38 38 0 0 address.street
address_zipcode 1 CHAR 5 5 0 0 address.zipcode address_zipcode 1 CHAR 5 5 0 0 address.zipcode
borough 1 CHAR 13 13 0 0 borough 1 CHAR 13 13 0 0
cuisine 1 CHAR 64 64 0 0 cuisine 1 CHAR 64 64 0 0
grades_date 1 CHAR 256 256 0 1 grades.0.date grades_date 1 CHAR 1024 1024 0 1 grades.0.date
grades_grade 1 CHAR 14 14 0 1 grades.0.grade grades_grade 1 CHAR 14 14 0 1 grades.0.grade
grades_score 5 BIGINT 2 2 0 1 grades.0.score grades_score 5 BIGINT 2 2 0 1 grades.0.score
name 1 CHAR 98 98 0 0 name 1 CHAR 98 98 0 0
...@@ -64,16 +64,16 @@ OPTION_LIST='Level=1,Driver=C,Version=0' CONNECTION='mongodb://localhost:27017' ...@@ -64,16 +64,16 @@ OPTION_LIST='Level=1,Driver=C,Version=0' CONNECTION='mongodb://localhost:27017'
SHOW CREATE TABLE t1; SHOW CREATE TABLE t1;
Table Create Table Table Create Table
t1 CREATE TABLE `t1` ( t1 CREATE TABLE `t1` (
`_id` char(24) NOT NULL `FIELD_FORMAT`='_id', `_id` char(24) NOT NULL `JPATH`='_id',
`address_building` char(10) NOT NULL `FIELD_FORMAT`='address.building', `address_building` char(10) NOT NULL `JPATH`='address.building',
`address_coord` varchar(256) DEFAULT NULL `FIELD_FORMAT`='address.coord', `address_coord` varchar(1024) DEFAULT NULL `JPATH`='address.coord',
`address_street` char(38) NOT NULL `FIELD_FORMAT`='address.street', `address_street` char(38) NOT NULL `JPATH`='address.street',
`address_zipcode` char(5) NOT NULL `FIELD_FORMAT`='address.zipcode', `address_zipcode` char(5) NOT NULL `JPATH`='address.zipcode',
`borough` char(13) NOT NULL, `borough` char(13) NOT NULL,
`cuisine` char(64) NOT NULL, `cuisine` char(64) NOT NULL,
`grades_date` varchar(256) DEFAULT NULL `FIELD_FORMAT`='grades.0.date', `grades_date` varchar(1024) DEFAULT NULL `JPATH`='grades.0.date',
`grades_grade` char(14) DEFAULT NULL `FIELD_FORMAT`='grades.0.grade', `grades_grade` char(14) DEFAULT NULL `JPATH`='grades.0.grade',
`grades_score` bigint(2) DEFAULT NULL `FIELD_FORMAT`='grades.0.score', `grades_score` bigint(2) DEFAULT NULL `JPATH`='grades.0.score',
`name` char(98) NOT NULL, `name` char(98) NOT NULL,
`restaurant_id` char(8) NOT NULL `restaurant_id` char(8) NOT NULL
) ENGINE=CONNECT DEFAULT CHARSET=latin1 CONNECTION='mongodb://localhost:27017' `TABLE_TYPE`='JSON' `TABNAME`='restaurants' `OPTION_LIST`='Level=1,Driver=C,Version=0' `DATA_CHARSET`='utf8' `LRECL`=1024 ) ENGINE=CONNECT DEFAULT CHARSET=latin1 CONNECTION='mongodb://localhost:27017' `TABLE_TYPE`='JSON' `TABNAME`='restaurants' `OPTION_LIST`='Level=1,Driver=C,Version=0' `DATA_CHARSET`='utf8' `LRECL`=1024
...@@ -251,15 +251,15 @@ OPTION_LIST='Driver=C,level=2,version=0'; ...@@ -251,15 +251,15 @@ OPTION_LIST='Driver=C,level=2,version=0';
SHOW CREATE TABLE t1; SHOW CREATE TABLE t1;
Table Create Table Table Create Table
t1 CREATE TABLE `t1` ( t1 CREATE TABLE `t1` (
`_id` char(24) NOT NULL `FIELD_FORMAT`='_id', `_id` char(24) NOT NULL `JPATH`='_id',
`address_building` char(10) NOT NULL `FIELD_FORMAT`='address.building', `address_building` char(10) NOT NULL `JPATH`='address.building',
`address_coord` double(23,20) DEFAULT NULL `FIELD_FORMAT`='address.coord.0', `address_coord` double(23,20) DEFAULT NULL `JPATH`='address.coord.0',
`address_street` char(38) NOT NULL `FIELD_FORMAT`='address.street', `address_street` char(38) NOT NULL `JPATH`='address.street',
`address_zipcode` char(5) NOT NULL `FIELD_FORMAT`='address.zipcode', `address_zipcode` char(5) NOT NULL `JPATH`='address.zipcode',
`borough` char(13) NOT NULL, `borough` char(13) NOT NULL,
`grades_date` bigint(13) DEFAULT NULL `FIELD_FORMAT`='grades.0.date', `grades_date` bigint(13) DEFAULT NULL `JPATH`='grades.0.date',
`grades_grade` char(14) DEFAULT NULL `FIELD_FORMAT`='grades.0.grade', `grades_grade` char(14) DEFAULT NULL `JPATH`='grades.0.grade',
`grades_score` bigint(2) DEFAULT NULL `FIELD_FORMAT`='grades.0.score', `grades_score` bigint(2) DEFAULT NULL `JPATH`='grades.0.score',
`name` char(98) NOT NULL, `name` char(98) NOT NULL,
`restaurant_id` char(8) NOT NULL `restaurant_id` char(8) NOT NULL
) ENGINE=CONNECT DEFAULT CHARSET=latin1 CONNECTION='mongodb://localhost:27017' `TABLE_TYPE`='JSON' `TABNAME`='restaurants' `COLIST`='{"projection":{"cuisine":0}}' `FILTER`='{"cuisine":"French","borough":{"$ne":"Manhattan"}}' `OPTION_LIST`='Driver=C,level=2,version=0' `LRECL`=1024 ) ENGINE=CONNECT DEFAULT CHARSET=latin1 CONNECTION='mongodb://localhost:27017' `TABLE_TYPE`='JSON' `TABNAME`='restaurants' `COLIST`='{"projection":{"cuisine":0}}' `FILTER`='{"cuisine":"French","borough":{"$ne":"Manhattan"}}' `OPTION_LIST`='Driver=C,level=2,version=0' `LRECL`=1024
......
...@@ -158,13 +158,14 @@ PGLOBAL PlugInit(LPCSTR Language, size_t worksize) ...@@ -158,13 +158,14 @@ PGLOBAL PlugInit(LPCSTR Language, size_t worksize)
} // end try/catch } // end try/catch
g->Sarea = NULL; g->Sarea = NULL;
g->Createas = 0; g->Createas = false;
g->Alchecked = 0; g->Alchecked = 0;
g->Mrr = 0; g->Mrr = 0;
g->Activityp = NULL; g->Activityp = NULL;
g->Xchk = NULL; g->Xchk = NULL;
g->N = 0; g->N = 0;
g->More = 0; g->More = 0;
g->Saved_Size = 0;
strcpy(g->Message, ""); strcpy(g->Message, "");
/*******************************************************************/ /*******************************************************************/
...@@ -528,7 +529,7 @@ BOOL PlugSubSet(void *memp, size_t size) ...@@ -528,7 +529,7 @@ BOOL PlugSubSet(void *memp, size_t size)
{ {
PPOOLHEADER pph = (PPOOLHEADER)memp; PPOOLHEADER pph = (PPOOLHEADER)memp;
pph->To_Free = (OFFSET)sizeof(POOLHEADER); pph->To_Free = (size_t)sizeof(POOLHEADER);
pph->FreeBlk = size - pph->To_Free; pph->FreeBlk = size - pph->To_Free;
return FALSE; return FALSE;
} /* end of PlugSubSet */ } /* end of PlugSubSet */
...@@ -580,7 +581,7 @@ void *PlugSubAlloc(PGLOBAL g, void *memp, size_t size) ...@@ -580,7 +581,7 @@ void *PlugSubAlloc(PGLOBAL g, void *memp, size_t size)
/* Do the suballocation the simplest way. */ /* Do the suballocation the simplest way. */
/*********************************************************************/ /*********************************************************************/
memp = MakePtr(memp, pph->To_Free); /* Points to suballocated block */ memp = MakePtr(memp, pph->To_Free); /* Points to suballocated block */
pph->To_Free += (OFFSET)size; /* New offset of pool free block */ pph->To_Free += size; /* New offset of pool free block */
pph->FreeBlk -= size; /* New size of pool free block */ pph->FreeBlk -= size; /* New size of pool free block */
if (trace(16)) if (trace(16))
...@@ -605,40 +606,4 @@ char *PlugDup(PGLOBAL g, const char *str) ...@@ -605,40 +606,4 @@ char *PlugDup(PGLOBAL g, const char *str)
} // end of PlugDup } // end of PlugDup
#if 0
/***********************************************************************/
/* This routine suballocate a copy of the passed string. */
/***********************************************************************/
char *PlugDup(PGLOBAL g, const char *str)
{
char *buf;
size_t len;
if (str && (len = strlen(str))) {
buf = (char*)PlugSubAlloc(g, NULL, len + 1);
strcpy(buf, str);
} else
buf = NULL;
return(buf);
} /* end of PlugDup */
#endif // 0
/***********************************************************************/
/* This routine makes a pointer from an offset to a memory pointer. */
/***********************************************************************/
void *MakePtr(void *memp, OFFSET offset)
{
return ((offset == 0) ? NULL : &((char *)memp)[offset]);
} /* end of MakePtr */
/***********************************************************************/
/* This routine makes an offset from a pointer new format. */
/***********************************************************************/
#if 0
OFFSET MakeOff(void *memp, void *ptr)
{
return ((!ptr) ? 0 : (OFFSET)((char *)ptr - (char *)memp));
} /* end of MakeOff */
#endif
/*--------------------- End of PLUGUTIL program -----------------------*/ /*--------------------- End of PLUGUTIL program -----------------------*/
...@@ -52,19 +52,10 @@ ...@@ -52,19 +52,10 @@
/* External functions. */ /* External functions. */
/***********************************************************************/ /***********************************************************************/
USETEMP UseTemp(void); USETEMP UseTemp(void);
bool JsonAllPath(void);
int GetDefaultDepth(void);
char *GetJsonNull(void); char *GetJsonNull(void);
//typedef struct _jncol {
// struct _jncol *Next;
// char *Name;
// char *Fmt;
// int Type;
// int Len;
// int Scale;
// bool Cbn;
// bool Found;
//} JCOL, *PJCL;
/***********************************************************************/ /***********************************************************************/
/* JSONColumns: construct the result blocks containing the description */ /* JSONColumns: construct the result blocks containing the description */
/* of all the columns of a table contained inside a JSON file. */ /* of all the columns of a table contained inside a JSON file. */
...@@ -167,23 +158,20 @@ JSONDISC::JSONDISC(PGLOBAL g, uint *lg) ...@@ -167,23 +158,20 @@ JSONDISC::JSONDISC(PGLOBAL g, uint *lg)
jsp = NULL; jsp = NULL;
row = NULL; row = NULL;
sep = NULL; sep = NULL;
i = n = bf = ncol = lvl = 0; i = n = bf = ncol = lvl = sz = 0;
all = false; all = strfy = false;
} // end of JSONDISC constructor } // end of JSONDISC constructor
int JSONDISC::GetColumns(PGLOBAL g, PCSZ db, PCSZ dsn, PTOS topt) int JSONDISC::GetColumns(PGLOBAL g, PCSZ db, PCSZ dsn, PTOS topt)
{ {
char filename[_MAX_PATH]; char filename[_MAX_PATH];
bool mgo = (GetTypeID(topt->type) == TAB_MONGO); bool mgo = (GetTypeID(topt->type) == TAB_MONGO);
PCSZ level = GetStringTableOption(g, topt, "Level", NULL);
if ((level = GetStringTableOption(g, topt, "Depth", level))) {
lvl = atoi(level);
lvl = (lvl > 16) ? 16 : lvl;
} else
lvl = 0;
sep = GetStringTableOption(g, topt, "Separator", "."); lvl = GetIntegerTableOption(g, topt, "Level", GetDefaultDepth());
lvl = GetIntegerTableOption(g, topt, "Depth", lvl);
sep = GetStringTableOption(g, topt, "Separator", ".");
sz = GetIntegerTableOption(g, topt, "Jsize", 1024);
strfy = GetBooleanTableOption(g, topt, "Stringify", false);
/*********************************************************************/ /*********************************************************************/
/* Open the input file. */ /* Open the input file. */
...@@ -306,7 +294,7 @@ int JSONDISC::GetColumns(PGLOBAL g, PCSZ db, PCSZ dsn, PTOS topt) ...@@ -306,7 +294,7 @@ int JSONDISC::GetColumns(PGLOBAL g, PCSZ db, PCSZ dsn, PTOS topt)
// Allocate the parse work memory // Allocate the parse work memory
PGLOBAL G = (PGLOBAL)PlugSubAlloc(g, NULL, sizeof(GLOBAL)); PGLOBAL G = (PGLOBAL)PlugSubAlloc(g, NULL, sizeof(GLOBAL));
memset(G, 0, sizeof(GLOBAL)); memset(G, 0, sizeof(GLOBAL));
G->Sarea_Size = tdp->Lrecl * 10; G->Sarea_Size = (size_t)tdp->Lrecl * 10;
G->Sarea = PlugSubAlloc(g, NULL, G->Sarea_Size); G->Sarea = PlugSubAlloc(g, NULL, G->Sarea_Size);
PlugSubSet(G->Sarea, G->Sarea_Size); PlugSubSet(G->Sarea, G->Sarea_Size);
G->jump_level = 0; G->jump_level = 0;
...@@ -403,7 +391,10 @@ bool JSONDISC::Find(PGLOBAL g, PJVAL jvp, PCSZ key, int j) ...@@ -403,7 +391,10 @@ bool JSONDISC::Find(PGLOBAL g, PJVAL jvp, PCSZ key, int j)
PJAR jar; PJAR jar;
if ((valp = jvp ? jvp->GetValue() : NULL)) { if ((valp = jvp ? jvp->GetValue() : NULL)) {
jcol.Type = valp->GetType(); if (JsonAllPath() && !fmt[bf])
strcat(fmt, colname);
jcol.Type = valp->GetType();
jcol.Len = valp->GetValLen(); jcol.Len = valp->GetValLen();
jcol.Scale = valp->GetValPrec(); jcol.Scale = valp->GetValPrec();
jcol.Cbn = valp->IsNull(); jcol.Cbn = valp->IsNull();
...@@ -482,8 +473,16 @@ bool JSONDISC::Find(PGLOBAL g, PJVAL jvp, PCSZ key, int j) ...@@ -482,8 +473,16 @@ bool JSONDISC::Find(PGLOBAL g, PJVAL jvp, PCSZ key, int j)
} // endswitch Type } // endswitch Type
} else if (lvl >= 0) { } else if (lvl >= 0) {
jcol.Type = TYPE_STRING; if (strfy) {
jcol.Len = 256; if (!fmt[bf])
strcat(fmt, colname);
strcat(fmt, ".*");
} else if (JsonAllPath() && !fmt[bf])
strcat(fmt, colname);
jcol.Type = TYPE_STRING;
jcol.Len = sz;
jcol.Scale = 0; jcol.Scale = 0;
jcol.Cbn = true; jcol.Cbn = true;
} else } else
...@@ -2040,7 +2039,7 @@ int TDBJSON::MakeDocument(PGLOBAL g) ...@@ -2040,7 +2039,7 @@ int TDBJSON::MakeDocument(PGLOBAL g)
if ((objpath = PlugDup(g, Objname))) { if ((objpath = PlugDup(g, Objname))) {
if (*objpath == '$') objpath++; if (*objpath == '$') objpath++;
if (*objpath == '.') objpath++; if (*objpath == '.') objpath++;
p1 = p2 = NULL; p1 = (*objpath == '[') ? objpath++ : NULL;
/*********************************************************************/ /*********************************************************************/
/* Find the table in the tree structure. */ /* Find the table in the tree structure. */
......
...@@ -68,8 +68,8 @@ class JSONDISC : public BLOCK { ...@@ -68,8 +68,8 @@ class JSONDISC : public BLOCK {
PCSZ sep; PCSZ sep;
char colname[65], fmt[129], buf[16]; char colname[65], fmt[129], buf[16];
uint *length; uint *length;
int i, n, bf, ncol, lvl; int i, n, bf, ncol, lvl, sz;
bool all; bool all, strfy;
}; // end of JSONDISC }; // end of JSONDISC
/***********************************************************************/ /***********************************************************************/
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
/* ------------- */ /* ------------- */
/* Version 3.0 */ /* Version 3.0 */
/* */ /* */
/* Author Olivier BERTRAND 2007 - 2017 */ /* Author Olivier BERTRAND 2007 - 2020 */
/* */ /* */
/* This program are the XML tables classes using MS-DOM or libxml2. */ /* This program are the XML tables classes using MS-DOM or libxml2. */
/***********************************************************************/ /***********************************************************************/
...@@ -62,6 +62,8 @@ extern "C" char version[]; ...@@ -62,6 +62,8 @@ extern "C" char version[];
#define TYPE_UNKNOWN 12 /* Must be greater than other types */ #define TYPE_UNKNOWN 12 /* Must be greater than other types */
#define XLEN(M) sizeof(M) - strlen(M) - 1 /* To avoid overflow*/ #define XLEN(M) sizeof(M) - strlen(M) - 1 /* To avoid overflow*/
int GetDefaultDepth(void);
/***********************************************************************/ /***********************************************************************/
/* Class and structure used by XMLColumns. */ /* Class and structure used by XMLColumns. */
/***********************************************************************/ /***********************************************************************/
...@@ -149,7 +151,7 @@ PQRYRES XMLColumns(PGLOBAL g, char *db, char *tab, PTOS topt, bool info) ...@@ -149,7 +151,7 @@ PQRYRES XMLColumns(PGLOBAL g, char *db, char *tab, PTOS topt, bool info)
strcpy(g->Message, MSG(MISSING_FNAME)); strcpy(g->Message, MSG(MISSING_FNAME));
return NULL; return NULL;
} else { } else {
lvl = GetIntegerTableOption(g, topt, "Level", 0); lvl = GetIntegerTableOption(g, topt, "Level", GetDefaultDepth());
lvl = GetIntegerTableOption(g, topt, "Depth", lvl); lvl = GetIntegerTableOption(g, topt, "Depth", lvl);
lvl = (lvl < 0) ? 0 : (lvl > 16) ? 16 : lvl; lvl = (lvl < 0) ? 0 : (lvl > 16) ? 16 : lvl;
} // endif fn } // endif fn
......
...@@ -158,16 +158,16 @@ bool user_connect::CheckCleanup(bool force) ...@@ -158,16 +158,16 @@ bool user_connect::CheckCleanup(bool force)
{ {
if (thdp->query_id > last_query_id || force) { if (thdp->query_id > last_query_id || force) {
size_t worksize = GetWorkSize(); size_t worksize = GetWorkSize();
size_t size = g->Sarea_Size;
PlugCleanup(g, true); PlugCleanup(g, true);
if (size != worksize) { if (worksize != g->Sarea_Size) {
FreeSarea(g); FreeSarea(g);
g->Saved_Size = g->Sarea_Size;
// Check whether the work area could be allocated // Check whether the work area could be allocated
if (AllocSarea(g, worksize)) { if (AllocSarea(g, worksize)) {
AllocSarea(g, size); AllocSarea(g, g->Saved_Size);
SetWorkSize(g->Sarea_Size); // Was too big SetWorkSize(g->Sarea_Size); // Was too big
} // endif sarea } // endif sarea
...@@ -175,10 +175,11 @@ bool user_connect::CheckCleanup(bool force) ...@@ -175,10 +175,11 @@ bool user_connect::CheckCleanup(bool force)
PlugSubSet(g->Sarea, g->Sarea_Size); PlugSubSet(g->Sarea, g->Sarea_Size);
g->Xchk = NULL; g->Xchk = NULL;
g->Createas = 0; g->Createas = false;
g->Alchecked = 0; g->Alchecked = 0;
g->Mrr = 0; g->Mrr = 0;
g->More = 0; g->More = 0;
g->Saved_Size = 0;
last_query_id= thdp->query_id; last_query_id= thdp->query_id;
if (trace(65) && !force) if (trace(65) && !force)
......
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