Commit 695c1e28 authored by Nikita Malyavin's avatar Nikita Malyavin

Merge remote-tracking branch 'connect/10.2' into 10.2

parents b1ac251b 4df6952c
......@@ -275,6 +275,7 @@ IF(CONNECT_WITH_JDBC)
JavaWrappers.jar)
add_definitions(-DJAVA_SUPPORT)
IF(CONNECT_WITH_MONGO)
SET(CONNECT_SOURCES ${CONNECT_SOURCES} Mongo2.jar Mongo3.jar)
add_definitions(-DMONGO_SUPPORT)
ENDIF()
ELSE()
......@@ -410,5 +411,11 @@ IF(CONNECT_WITH_JDBC AND JAVA_FOUND AND JNI_FOUND)
${CMAKE_CURRENT_SOURCE_DIR}/JavaWrappers.jar
${CMAKE_CURRENT_BINARY_DIR}/JdbcInterface.jar
DESTINATION ${INSTALL_PLUGINDIR} COMPONENT connect-engine)
IF(CONNECT_WITH_MONGO)
INSTALL(FILES
${CMAKE_CURRENT_SOURCE_DIR}/Mongo2.jar
${CMAKE_CURRENT_SOURCE_DIR}/Mongo3.jar
DESTINATION ${INSTALL_PLUGINDIR} COMPONENT connect-engine)
ENDIF()
ENDIF()
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
......@@ -1138,6 +1138,9 @@ PBVAL BJSON::GetArrayValue(PBVAL bap, int n)
CheckType(bap, TYPE_JAR);
int i = 0;
if (n < 0)
n += GetArraySize(bap);
for (PBVAL bvp = GetArray(bap); bvp; bvp = GetNext(bvp), i++)
if (i == n)
return bvp;
......@@ -1348,12 +1351,17 @@ PBVAL BJSON::NewVal(PVAL valp)
/***********************************************************************/
/* Sub-allocate and initialize a BVAL from another BVAL. */
/***********************************************************************/
PBVAL BJSON::DupVal(PBVAL bvlp) {
PBVAL bvp = NewVal();
PBVAL BJSON::DupVal(PBVAL bvlp)
{
if (bvlp) {
PBVAL bvp = NewVal();
*bvp = *bvlp;
bvp->Next = 0;
return bvp;
} else
return NULL;
*bvp = *bvlp;
bvp->Next = 0;
return bvp;
} // end of DupVal
/***********************************************************************/
......
......@@ -117,7 +117,7 @@ BJNX::BJNX(PGLOBAL g) : BDOC(g)
Jp = NULL;
Nodes = NULL;
Value = NULL;
MulVal = NULL;
//MulVal = NULL;
Jpath = NULL;
Buf_Type = TYPE_STRING;
Long = len;
......@@ -148,7 +148,7 @@ BJNX::BJNX(PGLOBAL g, PBVAL row, int type, int len, int prec, my_bool wr) : BDOC
Jp = NULL;
Nodes = NULL;
Value = AllocateValue(g, type, len, prec);
MulVal = NULL;
//MulVal = NULL;
Jpath = NULL;
Buf_Type = type;
Long = len;
......@@ -273,40 +273,6 @@ my_bool BJNX::SetArrayOptions(PGLOBAL g, char* p, int i, PSZ nm)
return true;
} // endif's
#if 0
// For calculated arrays, a local Value must be used
switch (jnp->Op) {
case OP_NUM:
jnp->Valp = AllocateValue(g, TYPE_INT);
break;
case OP_ADD:
case OP_MULT:
case OP_SEP:
if (!IsTypeChar(Buf_Type))
jnp->Valp = AllocateValue(g, Buf_Type, 0, GetPrecision());
else
jnp->Valp = AllocateValue(g, TYPE_DOUBLE, 0, 2);
break;
case OP_MIN:
case OP_MAX:
jnp->Valp = AllocateValue(g, Buf_Type, Long, GetPrecision());
break;
case OP_CNC:
if (IsTypeChar(Buf_Type))
jnp->Valp = AllocateValue(g, TYPE_STRING, Long, GetPrecision());
else
jnp->Valp = AllocateValue(g, TYPE_STRING, 512);
break;
default:
break;
} // endswitch Op
if (jnp->Valp)
MulVal = AllocateValue(g, jnp->Valp);
#endif // 0
return false;
} // end of SetArrayOptions
......@@ -452,6 +418,8 @@ PBVAL BJNX::MakeJson(PGLOBAL g, PBVAL bvp, int n)
{
PBVAL vlp, jvp = bvp;
Jb = false;
if (n < Nod -1) {
if (bvp->Type == TYPE_JAR) {
int ars = GetArraySize(bvp);
......@@ -3022,7 +2990,7 @@ void bson_object_grp_add(UDF_INIT *initid, UDF_ARGS *args, char*, char*)
PBVAL bop = (PBVAL)g->Activityp;
if (g->N-- > 0)
bxp->SetKeyValue(bop, bxp->MakeValue(args, 1), MakePSZ(g, args, 0));
bxp->SetKeyValue(bop, bxp->MakeValue(args, 1), MakePSZ(g, args, 0));
} // end of bson_object_grp_add
......@@ -3710,7 +3678,7 @@ char *bson_get_item(UDF_INIT *initid, UDF_ARGS *args, char *result,
PUSH_WARNING("CheckMemory error");
goto fin;
} else {
bnx.Reset();
bnx.Reset();
jvp = bnx.MakeValue(args, 0, true);
if (g->Mrr) { // First argument is a constant
......@@ -4056,7 +4024,7 @@ double bsonget_real(UDF_INIT *initid, UDF_ARGS *args,
*is_null = 1;
return 0.0;
} else {
bnx.Reset();
bnx.Reset();
jvp = bnx.MakeValue(args, 0);
if ((p = bnx.GetString(jvp))) {
......
......@@ -41,7 +41,6 @@ typedef struct _jnode {
PSZ Key; // The key used for object
OPVAL Op; // Operator used for this node
PVAL CncVal; // To cont value used for OP_CNC
PVAL Valp; // The internal array VALUE
int Rank; // The rank in array
int Rx; // Read row number
int Nx; // Next to read row number
......@@ -153,7 +152,7 @@ class BJNX : public BDOC {
JOUTSTR *Jp;
JNODE *Nodes; // The intermediate objects
PVAL Value;
PVAL MulVal; // To value used by multiple column
//PVAL MulVal; // To value used by multiple column
char *Jpath; // The json path
int Buf_Type;
int Long;
......
......@@ -150,6 +150,12 @@ void CMgoConn::mongo_init(bool init)
/***********************************************************************/
bool CMgoConn::Connect(PGLOBAL g)
{
if (!Pcg->Db_name || !Pcg->Coll_name) {
// This would crash in mongoc_client_get_collection
strcpy(g->Message, "Missing DB or collection name");
return true;
} // endif name
if (!IsInit)
#if defined(__WIN__)
__try {
......
......@@ -170,7 +170,7 @@
#define JSONMAX 10 // JSON Default max grp size
extern "C" {
char version[]= "Version 1.07.0002 January 27, 2021";
char version[]= "Version 1.07.0002 March 22, 2021";
#if defined(__WIN__)
char compver[]= "Version 1.07.0002 " __DATE__ " " __TIME__;
char slash= '\\';
......@@ -277,6 +277,10 @@ static handler *connect_create_handler(handlerton *hton,
TABLE_SHARE *table,
MEM_ROOT *mem_root);
static bool checkPrivileges(THD* thd, TABTYPE type, PTOS options,
const char* db, TABLE* table = NULL,
bool quick = false);
static int connect_assisted_discovery(handlerton *hton, THD* thd,
TABLE_SHARE *table_s,
HA_CREATE_INFO *info);
......@@ -757,10 +761,10 @@ DllExport LPCSTR PlugSetPath(LPSTR to, LPCSTR name, LPCSTR dir)
used by the default rename_table and delete_table method in
handler.cc.
For engines that have two file name extentions (separate meta/index file
For engines that have two file name extensions (separate meta/index file
and data file), the order of elements is relevant. First element of engine
file name extentions array should be meta/index file extention. Second
element - data file extention. This order is assumed by
file name extensions array should be meta/index file extension. Second
element - data file extension. This order is assumed by
prepare_for_repair() when REPAIR TABLE ... USE_FRM is issued.
@see
......@@ -1296,9 +1300,9 @@ PCSZ GetStringTableOption(PGLOBAL g, PTOS options, PCSZ opname, PCSZ sdef)
else if (!stricmp(opname, "Data_charset"))
opval= options->data_charset;
else if (!stricmp(opname, "Http") || !stricmp(opname, "URL"))
opval = options->http;
opval= options->http;
else if (!stricmp(opname, "Uri"))
opval = options->uri;
opval= options->uri;
if (!opval && options->oplist)
opval= GetListOption(g, opname, options->oplist);
......@@ -1612,7 +1616,7 @@ void *ha_connect::GetColumnOption(PGLOBAL g, void *field, PCOLINFO pcf)
pcf->Opt= (fop) ? (int)fop->opt : 0;
if (fp->field_length >= 0) {
pcf->Length = fp->field_length;
pcf->Length= fp->field_length;
// length is bytes for Connect, not characters
if (!strnicmp(chset, "utf8", 4))
......@@ -1627,7 +1631,7 @@ void *ha_connect::GetColumnOption(PGLOBAL g, void *field, PCOLINFO pcf)
pcf->Offset= (int)fop->offset;
pcf->Freq= (int)fop->freq;
pcf->Datefmt= (char*)fop->dateformat;
pcf->Fieldfmt = fop->fieldformat ? (char*)fop->fieldformat
pcf->Fieldfmt= fop->fieldformat ? (char*)fop->fieldformat
: fop->jsonpath ? (char*)fop->jsonpath : (char*)fop->xmlpath;
} else {
pcf->Offset= -1;
......@@ -4510,11 +4514,9 @@ int ha_connect::delete_all_rows()
} // end of delete_all_rows
bool ha_connect::check_privileges(THD *thd, PTOS options, char *dbn, bool quick)
static bool checkPrivileges(THD *thd, TABTYPE type, PTOS options,
const char *db, TABLE *table, bool quick)
{
const char *db= (dbn && *dbn) ? dbn : NULL;
TABTYPE type=GetRealType(options);
switch (type) {
case TAB_UNDEF:
// case TAB_CATLG:
......@@ -4597,6 +4599,15 @@ bool ha_connect::check_privileges(THD *thd, PTOS options, char *dbn, bool quick)
my_printf_error(ER_UNKNOWN_ERROR, "check_privileges failed", MYF(0));
return true;
} // end of checkPrivileges
// Check whether the user has required (file) privileges
bool ha_connect::check_privileges(THD *thd, PTOS options, char *dbn, bool quick)
{
const char *db= (dbn && *dbn) ? dbn : NULL;
TABTYPE type=GetRealType(options);
return checkPrivileges(thd, type, options, db, table, quick);
} // end of check_privileges
// Check that two indexes are equivalent
......@@ -5390,12 +5401,7 @@ static bool add_field(String* sql, TABTYPE ttp, const char* field_name, int typ,
int len, int dec, char* key, uint tm, const char* rem,
char* dft, char* xtra, char* fmt, int flag, bool dbf, char v)
{
#if defined(DEVELOPMENT)
// Some client programs regard CHAR(36) as GUID
char var = (len > 255 || len == 36) ? 'V' : v;
#else
char var = (len > 255) ? 'V' : v;
#endif
bool q, error = false;
const char* type = PLGtoMYSQLtype(typ, dbf, var);
......@@ -5731,6 +5737,29 @@ static int connect_assisted_discovery(handlerton *, THD* thd,
#endif // REST_SUPPORT
} // endif ttp
if (fn && *fn)
switch (ttp) {
case TAB_FMT:
case TAB_DBF:
case TAB_XML:
case TAB_INI:
case TAB_VEC:
case TAB_REST:
case TAB_JSON:
#if defined(BSON_SUPPORT)
case TAB_BSON:
#endif // BSON_SUPPORT
if (checkPrivileges(thd, ttp, topt, db)) {
strcpy(g->Message, "This operation requires the FILE privilege");
rc= HA_ERR_INTERNAL_ERROR;
goto err;
} // endif check_privileges
break;
default:
break;
} // endswitch ttp
if (!tab) {
if (ttp == TAB_TBL) {
// Make tab the first table of the list
......
/************ Javaconn C++ Functions Source Code File (.CPP) ***********/
/* Name: JAVAConn.CPP Version 1.0 */
/* Name: JAVAConn.CPP Version 1.1 */
/* */
/* (C) Copyright to the author Olivier BERTRAND 2017 */
/* (C) Copyright to the author Olivier BERTRAND 2017 - 2021 */
/* */
/* This file contains the JAVA connection classes functions. */
/***********************************************************************/
......@@ -400,24 +400,35 @@ bool JAVAConn::Open(PGLOBAL g)
jpop->Append(ClassPath);
} // endif ClassPath
// Java source will be compiled as a jar file installed in the plugin dir
#if 0
// Java source will be compiled as a jar file installed in the plugin dir
jpop->Append(sep);
jpop->Append(GetPluginDir());
jpop->Append("JdbcInterface.jar");
#endif // 0
// All wrappers are pre-compiled in JavaWrappers.jar in the plugin dir
jpop->Append(sep);
jpop->Append(GetPluginDir());
jpop->Append("JavaWrappers.jar");
#if defined(MONGO_SUPPORT)
jpop->Append(sep);
jpop->Append(GetPluginDir());
jpop->Append("Mongo3.jar");
jpop->Append(sep);
jpop->Append(GetPluginDir());
jpop->Append("Mongo2.jar");
#endif // MONGO_SUPPORT
if ((cp = getenv("CLASSPATH"))) {
jpop->Append(sep);
jpop->Append(cp);
} // endif cp
if (trace(1)) {
htrc("ClassPath=%s\n", ClassPath);
htrc("CLASSPATH=%s\n", cp);
htrc("ClassPath=%s\n", ClassPath ? ClassPath : "null");
htrc("CLASSPATH=%s\n", cp ? cp : "null");
htrc("%s\n", jpop->GetStr());
} // endif trace
......
......@@ -121,20 +121,21 @@ JMgoConn::JMgoConn(PGLOBAL g, PCSZ collname, PCSZ wrapper)
/***********************************************************************/
void JMgoConn::AddJars(PSTRG jpop, char sep)
{
#if defined(BSON_SUPPORT)
#if defined(DEVELOPMENT)
if (m_Version == 2) {
jpop->Append(sep);
// jpop->Append("C:/Eclipse/workspace/MongoWrap2/bin");
jpop->Append(sep);
// jpop->Append(sep);
jpop->Append("C:/mongo-java-driver/mongo-java-driver-2.13.3.jar");
} else {
jpop->Append(sep);
// jpop->Append("C:/Eclipse/workspace/MongoWrap3/bin");
// jpop->Append(sep);
// jpop->Append("C:/Program Files/MariaDB 10.1/lib/plugin/JavaWrappers.jar");
jpop->Append(sep);
// jpop->Append(sep);
jpop->Append("C:/mongo-java-driver/mongo-java-driver-3.4.2.jar");
} // endif m_Version
#endif // BSON_SUPPORT
#endif // DEVELOPMENT
} // end of AddJars
/***********************************************************************/
......
......@@ -54,15 +54,24 @@ char *GetExceptionDesc(PGLOBAL g, unsigned int e);
#endif // SE_CATCH
char *GetJsonNull(void);
int GetDefaultPrec(void);
/***********************************************************************/
/* IsNum: check whether this string is all digits. */
/***********************************************************************/
bool IsNum(PSZ s) {
for (char* p = s; *p; p++)
bool IsNum(PSZ s)
{
char* p = s;
if (*p == '-')
p++;
if (*p == ']')
return false;
else for (; *p; p++)
if (*p == ']')
break;
else if (!isdigit(*p) || *p == '-')
else if (!isdigit(*p))
return false;
return true;
......@@ -1257,6 +1266,8 @@ PJVAL JARRAY::GetArrayValue(int i)
{
if (Mvals && i >= 0 && i < Size)
return Mvals[i];
else if (Mvals && i < 0 && i >= -Size)
return Mvals[Size + i];
else
return NULL;
} // end of GetValue
......@@ -1752,7 +1763,7 @@ void JVALUE::SetBigint(PGLOBAL g, long long ll)
void JVALUE::SetFloat(PGLOBAL g, double f)
{
F = f;
Nd = 6;
Nd = GetDefaultPrec();
DataType = TYPE_DBL;
} // end of SetFloat
......
......@@ -72,7 +72,7 @@ JSNX::JSNX(PGLOBAL g, PJSON row, int type, int len, int prec, my_bool wr)
Jp = NULL;
Nodes = NULL;
Value = AllocateValue(g, type, len, prec);
MulVal = NULL;
//MulVal = NULL;
Jpath = NULL;
Buf_Type = type;
Long = len;
......@@ -198,38 +198,6 @@ my_bool JSNX::SetArrayOptions(PGLOBAL g, char *p, int i, PSZ nm)
return true;
} // endif's
// For calculated arrays, a local Value must be used
switch (jnp->Op) {
case OP_NUM:
jnp->Valp = AllocateValue(g, TYPE_INT);
break;
case OP_ADD:
case OP_MULT:
case OP_SEP:
if (!IsTypeChar(Buf_Type))
jnp->Valp = AllocateValue(g, Buf_Type, 0, GetPrecision());
else
jnp->Valp = AllocateValue(g, TYPE_DOUBLE, 0, 2);
break;
case OP_MIN:
case OP_MAX:
jnp->Valp = AllocateValue(g, Buf_Type, Long, GetPrecision());
break;
case OP_CNC:
if (IsTypeChar(Buf_Type))
jnp->Valp = AllocateValue(g, TYPE_STRING, Long, GetPrecision());
else
jnp->Valp = AllocateValue(g, TYPE_STRING, 512);
break;
default:
break;
} // endswitch Op
if (jnp->Valp)
MulVal = AllocateValue(g, jnp->Valp);
return false;
} // end of SetArrayOptions
......@@ -312,7 +280,7 @@ my_bool JSNX::ParseJpath(PGLOBAL g)
} // endfor i, p
Nod = i;
MulVal = AllocateValue(g, Value);
//MulVal = AllocateValue(g, Value);
if (trace(1))
for (i = 0; i < Nod; i++)
......@@ -323,23 +291,6 @@ my_bool JSNX::ParseJpath(PGLOBAL g)
return false;
} // end of ParseJpath
/*********************************************************************************/
/* MakeJson: Serialize the json item and set value to it. */
/*********************************************************************************/
PVAL JSNX::MakeJson(PGLOBAL g, PJSON jsp)
{
if (Value->IsTypeNum()) {
strcpy(g->Message, "Cannot make Json for a numeric value");
Value->Reset();
} else if (jsp->GetType() != TYPE_JAR && jsp->GetType() != TYPE_JOB) {
strcpy(g->Message, "Target is not an array or object");
Value->Reset();
} else
Value->SetValue_psz(Serialize(g, jsp, NULL, 0));
return Value;
} // end of MakeJson
/*********************************************************************************/
/* SetValue: Set a value from a JVALUE contains. */
/*********************************************************************************/
......@@ -350,6 +301,7 @@ void JSNX::SetJsonValue(PGLOBAL g, PVAL vp, PJVAL val)
if (Jb) {
vp->SetValue_psz(Serialize(g, val->GetJsp(), NULL, 0));
Jb = false;
} else switch (val->GetValType()) {
case TYPE_DTM:
case TYPE_STRG:
......@@ -394,6 +346,52 @@ void JSNX::SetJsonValue(PGLOBAL g, PVAL vp, PJVAL val)
} // end of SetJsonValue
/*********************************************************************************/
/* MakeJson: Serialize the json item and set value to it. */
/*********************************************************************************/
PJVAL JSNX::MakeJson(PGLOBAL g, PJSON jsp, int n)
{
Jb = false;
if (Value->IsTypeNum()) {
strcpy(g->Message, "Cannot make Json for a numeric value");
return NULL;
} else if (jsp->GetType() != TYPE_JAR && jsp->GetType() != TYPE_JOB) {
strcpy(g->Message, "Target is not an array or object");
return NULL;
} else if (n < Nod -1) {
if (jsp->GetType() == TYPE_JAR) {
int ars = jsp->GetSize(false);
PJNODE jnp = &Nodes[n];
PJAR jarp = new(g) JARRAY;
jnp->Op = OP_EQ;
for (jnp->Rank = 0; jnp->Rank < ars; jnp->Rank++)
jarp->AddArrayValue(g, GetRowValue(g, jsp, n));
jarp->InitArray(g);
jnp->Op = OP_XX;
jnp->Rank = 0;
jsp = jarp;
} else if(jsp->GetType() == TYPE_JOB) {
PJSON jp;
PJOB jobp = new(g) JOBJECT;
for (PJPR prp = ((PJOB)jsp)->GetFirst(); prp; prp = prp->Next) {
jp = (prp->Val->DataType == TYPE_JSON) ? prp->Val->Jsp : prp->Val;
jobp->SetKeyValue(g, GetRowValue(g, jp, n + 1), prp->Key);
} // endfor prp
jsp = jobp;
} // endif Type
} // endif
Jb = true;
return new(g) JVALUE(jsp);
} // end of MakeJson
/*********************************************************************************/
/* GetJson: */
/*********************************************************************************/
......@@ -437,8 +435,7 @@ PJVAL JSNX::GetRowValue(PGLOBAL g, PJSON row, int i, my_bool b)
val = new(g) JVALUE(g, Value);
return val;
} else if (Nodes[i].Op == OP_XX) {
Jb = b;
return new(g)JVALUE(row);
return MakeJson(g, row, i);
} else switch (row->GetType()) {
case TYPE_JOB:
if (!Nodes[i].Key) {
......@@ -504,6 +501,88 @@ PVAL JSNX::ExpandArray(PGLOBAL g, PJAR arp, int n)
return NULL;
} // end of ExpandArray
/*********************************************************************************/
/* Get the value used for calculating the array. */
/*********************************************************************************/
PVAL JSNX::GetCalcValue(PGLOBAL g, PJAR jap, int n)
{
// For calculated arrays, a local Value must be used
int lng = 0;
short type, prec = 0;
bool b = n < Nod - 1;
PVAL valp;
PJVAL vlp, vp;
OPVAL op = Nodes[n].Op;
switch (op) {
case OP_NUM:
type = TYPE_INT;
break;
case OP_ADD:
case OP_MULT:
if (!IsTypeNum(Buf_Type)) {
type = TYPE_INT;
prec = 0;
for (vlp = jap->GetArrayValue(0); vlp; vlp = vlp->Next) {
vp = (b && vlp->GetJsp()) ? GetRowValue(g, vlp, n + 1) : vlp;
switch (vp->DataType) {
case TYPE_BINT:
if (type == TYPE_INT)
type = TYPE_BIGINT;
break;
case TYPE_DBL:
case TYPE_FLOAT:
type = TYPE_DOUBLE;
prec = MY_MAX(prec, vp->Nd);
break;
default:
break;
} // endswitch Type
} // endfor vlp
} else {
type = Buf_Type;
prec = GetPrecision();
} // endif Buf_Type
break;
case OP_SEP:
if (IsTypeChar(Buf_Type)) {
type = TYPE_DOUBLE;
prec = 2;
} else {
type = Buf_Type;
prec = GetPrecision();
} // endif Buf_Type
break;
case OP_MIN:
case OP_MAX:
type = Buf_Type;
lng = Long;
prec = GetPrecision();
break;
case OP_CNC:
type = TYPE_STRING;
if (IsTypeChar(Buf_Type)) {
lng = (Long) ? Long : 512;
prec = GetPrecision();
} else
lng = 512;
break;
default:
break;
} // endswitch Op
return valp = AllocateValue(g, type, lng, prec);
} // end of GetCalcValue
/*********************************************************************************/
/* CalculateArray: */
/*********************************************************************************/
......@@ -512,7 +591,8 @@ PVAL JSNX::CalculateArray(PGLOBAL g, PJAR arp, int n)
int i, ars = arp->size(), nv = 0;
bool err;
OPVAL op = Nodes[n].Op;
PVAL val[2], vp = Nodes[n].Valp;
PVAL val[2], vp = GetCalcValue(g, arp, n);
PVAL mulval = AllocateValue(g, vp);
PJVAL jvrp, jvp;
JVALUE jval;
......@@ -545,9 +625,9 @@ PVAL JSNX::CalculateArray(PGLOBAL g, PJAR arp, int n)
SetJsonValue(g, vp, jvp);
continue;
} else
SetJsonValue(g, MulVal, jvp);
SetJsonValue(g, mulval, jvp);
if (!MulVal->IsNull()) {
if (!mulval->IsNull()) {
switch (op) {
case OP_CNC:
if (Nodes[n].CncVal) {
......@@ -555,18 +635,18 @@ PVAL JSNX::CalculateArray(PGLOBAL g, PJAR arp, int n)
err = vp->Compute(g, val, 1, op);
} // endif CncVal
val[0] = MulVal;
val[0] = mulval;
err = vp->Compute(g, val, 1, op);
break;
// case OP_NUM:
case OP_SEP:
val[0] = Nodes[n].Valp;
val[1] = MulVal;
val[0] = vp;
val[1] = mulval;
err = vp->Compute(g, val, 2, OP_ADD);
break;
default:
val[0] = Nodes[n].Valp;
val[1] = MulVal;
val[0] = vp;
val[1] = mulval;
err = vp->Compute(g, val, 2, op);
} // endswitch Op
......@@ -588,9 +668,9 @@ PVAL JSNX::CalculateArray(PGLOBAL g, PJAR arp, int n)
if (op == OP_SEP) {
// Calculate average
MulVal->SetValue(nv);
mulval->SetValue(nv);
val[0] = vp;
val[1] = MulVal;
val[1] = mulval;
if (vp->Compute(g, val, 2, OP_DIV))
vp->Reset();
......
......@@ -44,7 +44,6 @@ typedef struct _jnode {
PSZ Key; // The key used for object
OPVAL Op; // Operator used for this node
PVAL CncVal; // To cont value used for OP_CNC
PVAL Valp; // The internal array VALUE
int Rank; // The rank in array
int Rx; // Read row number
int Nx; // Next to read row number
......@@ -334,8 +333,9 @@ class JSNX : public BLOCK {
my_bool SetArrayOptions(PGLOBAL g, char *p, int i, PSZ nm);
PVAL GetColumnValue(PGLOBAL g, PJSON row, int i);
PVAL ExpandArray(PGLOBAL g, PJAR arp, int n);
PVAL GetCalcValue(PGLOBAL g, PJAR bap, int n);
PVAL CalculateArray(PGLOBAL g, PJAR arp, int n);
PVAL MakeJson(PGLOBAL g, PJSON jsp);
PJVAL MakeJson(PGLOBAL g, PJSON jsp, int i);
void SetJsonValue(PGLOBAL g, PVAL vp, PJVAL val);
PJSON GetRow(PGLOBAL g);
my_bool CompareValues(PJVAL v1, PJVAL v2);
......@@ -358,7 +358,7 @@ class JSNX : public BLOCK {
JOUTSTR *Jp;
JNODE *Nodes; // The intermediate objects
PVAL Value;
PVAL MulVal; // To value used by multiple column
//PVAL MulVal; // To value used by multiple column
char *Jpath; // The json path
int Buf_Type;
int Long;
......
......@@ -322,7 +322,7 @@ JsonGet_String(Json_Make_Array(45,28,36,45,89),'3')
45
SELECT JsonGet_String(Json_Make_Array(45,28,36,45,89),'["+"]') "list",'=' as "egal",JsonGet_String(Json_Make_Array(45,28,36,45,89),'[+]') "sum";
list egal sum
45+28+36+45+89 = 243.00
45+28+36+45+89 = 243
SELECT JsonGet_String(Json_Make_Array(Json_Make_Array(45,28),Json_Make_Array(36,45,89)),'1.0');
JsonGet_String(Json_Make_Array(Json_Make_Array(45,28),Json_Make_Array(36,45,89)),'1.0')
36
......@@ -349,10 +349,10 @@ Warnings:
Warning 1105
SELECT department, JsonGet_String(Json_Make_Object(department, Json_Array_Grp(salary) "Json_salaries"),'salaries.[+]') Sumsal FROM t3 GROUP BY department;
department Sumsal
0021 28500.00
0318 72230.00
0319 89800.95
2452 45900.00
0021 28500.000000
0318 72230.000000
0319 89800.950000
2452 45900.000000
SELECT JsonGet_Int(@j1, '4');
JsonGet_Int(@j1, '4')
89
......
/************* tabbson C++ Program Source Code File (.CPP) *************/
/* PROGRAM NAME: tabbson Version 1.0 */
/* (C) Copyright to the author Olivier BERTRAND 2020 */
/* PROGRAM NAME: tabbson Version 1.1 */
/* (C) Copyright to the author Olivier BERTRAND 2020 - 2021 */
/* This program are the BSON class DB execution routines. */
/***********************************************************************/
......@@ -158,8 +158,9 @@ BSONDISC::BSONDISC(PGLOBAL g, uint* lg)
bp = NULL;
row = NULL;
sep = NULL;
strfy = NULL;
i = n = bf = ncol = lvl = sz = limit = 0;
all = strfy = false;
all = false;
} // end of BSONDISC constructor
int BSONDISC::GetColumns(PGLOBAL g, PCSZ db, PCSZ dsn, PTOS topt)
......@@ -173,7 +174,7 @@ int BSONDISC::GetColumns(PGLOBAL g, PCSZ db, PCSZ dsn, PTOS topt)
sep = GetStringTableOption(g, topt, "Separator", ".");
sz = GetIntegerTableOption(g, topt, "Jsize", 1024);
limit = GetIntegerTableOption(g, topt, "Limit", 10);
strfy = GetBooleanTableOption(g, topt, "Stringify", false);
strfy = GetStringTableOption(g, topt, "Stringify", NULL);
/*********************************************************************/
/* Open the input file. */
......@@ -186,6 +187,9 @@ int BSONDISC::GetColumns(PGLOBAL g, PCSZ db, PCSZ dsn, PTOS topt)
#endif // ZIP_SUPPORT
tdp->Fn = GetStringTableOption(g, topt, "Filename", NULL);
if (!tdp->Fn && topt->http)
tdp->Fn = GetStringTableOption(g, topt, "Subtype", NULL);
if (!(tdp->Database = SetPath(g, db)))
return 0;
......@@ -199,7 +203,8 @@ int BSONDISC::GetColumns(PGLOBAL g, PCSZ db, PCSZ dsn, PTOS topt)
if (!tdp->Fn && !tdp->Uri) {
strcpy(g->Message, MSG(MISSING_FNAME));
return 0;
} // endif Fn
} else
topt->subtype = NULL;
if (tdp->Fn) {
// We used the file name relative to recorded datapath
......@@ -428,7 +433,7 @@ bool BSONDISC::Find(PGLOBAL g, PBVAL jvp, PCSZ key, int j)
jcol.Type = TYPE_UNKNOWN;
jcol.Len = jcol.Scale = 0;
jcol.Cbn = true;
} else if (j < lvl) {
} else if (j < lvl && !(strfy && !stricmp(strfy, colname))) {
if (!fmt[bf])
strcat(fmt, colname);
......@@ -499,7 +504,7 @@ bool BSONDISC::Find(PGLOBAL g, PBVAL jvp, PCSZ key, int j)
} // endswitch Type
} else if (lvl >= 0) {
if (strfy) {
if (strfy && !stricmp(strfy, colname)) {
if (!fmt[bf])
strcat(fmt, colname);
......@@ -731,7 +736,6 @@ void BCUTIL::SetJsonValue(PGLOBAL g, PVAL vp, PBVAL jvp)
case TYPE_FLOAT:
switch (vp->GetType()) {
case TYPE_STRING:
case TYPE_DATE:
case TYPE_DECIM:
vp->SetValue_psz(GetString(jvp));
break;
......@@ -749,6 +753,16 @@ void BCUTIL::SetJsonValue(PGLOBAL g, PVAL vp, PBVAL jvp)
if (jvp->Type == TYPE_DBL || jvp->Type == TYPE_FLOAT)
vp->SetPrec(jvp->Nd);
break;
case TYPE_DATE:
if (jvp->Type == TYPE_STRG) {
if (!((DTVAL*)vp)->IsFormatted())
((DTVAL*)vp)->SetFormat(g, "YYYY-MM-DDThh:mm:ssZ", 20, 0);
vp->SetValue_psz(GetString(jvp));
} else
vp->SetValue(GetInteger(jvp));
break;
default:
sprintf(G->Message, "Unsupported column type %d", vp->GetType());
......@@ -881,7 +895,7 @@ PBVAL BCUTIL::GetRowValue(PGLOBAL g, PBVAL row, int i)
} // endfor i
return bvp;
} // end of GetColumnValue
} // end of GetRowValue
/***********************************************************************/
/* GetColumnValue: */
......
......@@ -44,10 +44,11 @@ class BSONDISC : public BLOCK {
PBPR row;
PBTUT bp;
PCSZ sep;
PCSZ strfy;
char colname[65], fmt[129], buf[16];
uint *length;
int i, n, bf, ncol, lvl, sz, limit;
bool all, strfy;
bool all;
}; // end of BSONDISC
/***********************************************************************/
......
/************* tabjson C++ Program Source Code File (.CPP) *************/
/* PROGRAM NAME: tabjson Version 1.8 */
/* (C) Copyright to the author Olivier BERTRAND 2014 - 2020 */
/* (C) Copyright to the author Olivier BERTRAND 2014 - 2021 */
/* This program are the JSON class DB execution routines. */
/***********************************************************************/
#undef BSON_SUPPORT
......@@ -9,6 +9,8 @@
/* Include relevant sections of the MariaDB header file. */
/***********************************************************************/
#include <my_global.h>
#include <mysqld.h>
#include <sql_error.h>
/***********************************************************************/
/* Include application header files: */
......@@ -160,22 +162,24 @@ JSONDISC::JSONDISC(PGLOBAL g, uint *lg)
jsp = NULL;
row = NULL;
sep = NULL;
strfy = NULL;
i = n = bf = ncol = lvl = sz = limit = 0;
all = strfy = false;
all = false;
} // end of JSONDISC constructor
int JSONDISC::GetColumns(PGLOBAL g, PCSZ db, PCSZ dsn, PTOS topt)
{
char filename[_MAX_PATH];
size_t reclg = 0;
bool mgo = (GetTypeID(topt->type) == TAB_MONGO);
PGLOBAL G = NULL;
lvl = GetIntegerTableOption(g, topt, "Level", GetDefaultDepth());
lvl = GetIntegerTableOption(g, topt, "Depth", lvl);
sep = GetStringTableOption(g, topt, "Separator", ".");
sz = GetIntegerTableOption(g, topt, "Jsize", 1024);
strfy = GetStringTableOption(g, topt, "Stringify", NULL);
sz = GetIntegerTableOption(g, topt, "Jsize", 250);
limit = GetIntegerTableOption(g, topt, "Limit", 10);
strfy = GetBooleanTableOption(g, topt, "Stringify", false);
/*********************************************************************/
/* Open the input file. */
......@@ -187,6 +191,9 @@ int JSONDISC::GetColumns(PGLOBAL g, PCSZ db, PCSZ dsn, PTOS topt)
#endif // ZIP_SUPPORT
tdp->Fn = GetStringTableOption(g, topt, "Filename", NULL);
if (!tdp->Fn && topt->http)
tdp->Fn = GetStringTableOption(g, topt, "Subtype", NULL);
if (!(tdp->Database = SetPath(g, db)))
return 0;
......@@ -200,7 +207,8 @@ int JSONDISC::GetColumns(PGLOBAL g, PCSZ db, PCSZ dsn, PTOS topt)
if (!tdp->Fn && !tdp->Uri) {
strcpy(g->Message, MSG(MISSING_FNAME));
return 0;
} // endif Fn
} else
topt->subtype = NULL;
if (tdp->Fn) {
// We used the file name relative to recorded datapath
......@@ -247,11 +255,11 @@ int JSONDISC::GetColumns(PGLOBAL g, PCSZ db, PCSZ dsn, PTOS topt)
jsp = (tjsp->GetDoc()) ? tjsp->GetDoc()->GetArrayValue(0) : NULL;
} else {
if (!((tdp->Lrecl = GetIntegerTableOption(g, topt, "Lrecl", 0)))) {
if (!mgo) {
if (!mgo && !tdp->Uri) {
sprintf(g->Message, "LRECL must be specified for pretty=%d", tdp->Pretty);
return 0;
} else
tdp->Lrecl = 8192; // Should be enough
} else
tdp->Lrecl = 8192; // Should be enough
} // endif Lrecl
......@@ -310,7 +318,9 @@ int JSONDISC::GetColumns(PGLOBAL g, PCSZ db, PCSZ dsn, PTOS topt)
case RC_FX:
goto err;
default:
// jsp = tjnp->FindRow(g); // FindRow was done in ReadDB
if (tdp->Pretty != 2)
reclg = strlen(tjnp->To_Line);
jsp = tjnp->Row;
} // endswitch ReadDB
......@@ -361,7 +371,9 @@ int JSONDISC::GetColumns(PGLOBAL g, PCSZ db, PCSZ dsn, PTOS topt)
case RC_FX:
goto err;
default:
// jsp = tjnp->FindRow(g);
if (tdp->Pretty != 2 && reclg < strlen(tjnp->To_Line))
reclg = strlen(tjnp->To_Line);
jsp = tjnp->Row;
} // endswitch ReadDB
......@@ -373,8 +385,12 @@ int JSONDISC::GetColumns(PGLOBAL g, PCSZ db, PCSZ dsn, PTOS topt)
} // endfor i
if (tdp->Pretty != 2)
if (tdp->Pretty != 2) {
if (!topt->lrecl)
topt->lrecl = reclg + 10;
tjnp->CloseDB(g);
} // endif Pretty
return n;
......@@ -426,7 +442,7 @@ bool JSONDISC::Find(PGLOBAL g, PJVAL jvp, PCSZ key, int j)
jcol.Type = TYPE_UNKNOWN;
jcol.Len = jcol.Scale = 0;
jcol.Cbn = true;
} else if (j < lvl) {
} else if (j < lvl && !(strfy && !stricmp(strfy, colname))) {
if (!fmt[bf])
strcat(fmt, colname);
......@@ -480,9 +496,8 @@ bool JSONDISC::Find(PGLOBAL g, PJVAL jvp, PCSZ key, int j)
strncat(strncat(colname, "_", n), buf, n - 1);
} // endif all
} else {
} else
strncat(fmt, (tdp->Uri ? sep : "[*]"), n);
}
if (Find(g, jar->GetArrayValue(k), "", j))
return true;
......@@ -497,7 +512,7 @@ bool JSONDISC::Find(PGLOBAL g, PJVAL jvp, PCSZ key, int j)
} // endswitch Type
} else if (lvl >= 0) {
if (strfy) {
if (strfy && !stricmp(strfy, colname)) {
if (!fmt[bf])
strcat(fmt, colname);
......@@ -1610,7 +1625,7 @@ PSZ JSONCOL::GetJpath(PGLOBAL g, bool proj)
/***********************************************************************/
/* MakeJson: Serialize the json item and set value to it. */
/***********************************************************************/
PVAL JSONCOL::MakeJson(PGLOBAL g, PJSON jsp)
PVAL JSONCOL::MakeJson(PGLOBAL g, PJSON jsp, int n)
{
if (Value->IsTypeNum()) {
strcpy(g->Message, "Cannot make Json for a numeric column");
......@@ -1621,6 +1636,7 @@ PVAL JSONCOL::MakeJson(PGLOBAL g, PJSON jsp)
} // endif Warned
Value->Reset();
return Value;
#if 0
} else if (Value->GetType() == TYPE_BIN) {
if ((unsigned)Value->GetClen() >= sizeof(BSON)) {
......@@ -1634,12 +1650,65 @@ PVAL JSONCOL::MakeJson(PGLOBAL g, PJSON jsp)
Value->SetValue_char(NULL, 0);
} // endif Clen
#endif // 0
} else
Value->SetValue_psz(Serialize(g, jsp, NULL, 0));
} else if (n < Nod - 1) {
if (jsp->GetType() == TYPE_JAR) {
int ars = jsp->GetSize(false);
PJNODE jnp = &Nodes[n];
PJAR jvp = new(g) JARRAY;
for (jnp->Rank = 0; jnp->Rank < ars; jnp->Rank++)
jvp->AddArrayValue(g, GetRowValue(g, jsp, n));
jnp->Rank = 0;
jvp->InitArray(g);
jsp = jvp;
} else if (jsp->Type == TYPE_JOB) {
PJOB jvp = new(g) JOBJECT;
for (PJPR prp = ((PJOB)jsp)->GetFirst(); prp; prp = prp->Next)
jvp->SetKeyValue(g, GetRowValue(g, prp->Val, n + 1), prp->Key);
jsp = jvp;
} // endif Type
} // endif
Value->SetValue_psz(Serialize(g, jsp, NULL, 0));
return Value;
} // end of MakeJson
/***********************************************************************/
/* GetRowValue: */
/***********************************************************************/
PJVAL JSONCOL::GetRowValue(PGLOBAL g, PJSON row, int i)
{
int n = Nod - 1;
PJVAL val = NULL;
for (; i < Nod && row; i++) {
switch (row->GetType()) {
case TYPE_JOB:
val = (Nodes[i].Key) ? ((PJOB)row)->GetKeyValue(Nodes[i].Key) : NULL;
break;
case TYPE_JAR:
val = ((PJAR)row)->GetArrayValue(Nodes[i].Rank);
break;
case TYPE_JVAL:
val = (PJVAL)row;
break;
default:
sprintf(g->Message, "Invalid row JSON type %d", row->GetType());
val = NULL;
} // endswitch Type
if (i < Nod-1)
row = (val) ? val->GetJson() : NULL;
} // endfor i
return val;
} // end of GetRowValue
/***********************************************************************/
/* SetValue: Set a value from a JVALUE contains. */
/***********************************************************************/
......@@ -1656,7 +1725,6 @@ void JSONCOL::SetJsonValue(PGLOBAL g, PVAL vp, PJVAL jvp)
case TYPE_DTM:
switch (vp->GetType()) {
case TYPE_STRING:
case TYPE_DATE:
vp->SetValue_psz(jvp->GetString(g));
break;
case TYPE_INT:
......@@ -1674,7 +1742,17 @@ void JSONCOL::SetJsonValue(PGLOBAL g, PVAL vp, PJVAL jvp)
vp->SetPrec(jvp->Nd);
break;
default:
case TYPE_DATE:
if (jvp->GetValType() == TYPE_STRG) {
if (!((DTVAL*)vp)->IsFormatted())
((DTVAL*)vp)->SetFormat(g, "YYYY-MM-DDThh:mm:ssZ", 20, 0);
vp->SetValue_psz(jvp->GetString(g));
} else
vp->SetValue(jvp->GetInteger());
break;
default:
sprintf(g->Message, "Unsupported column type %d\n", vp->GetType());
throw 888;
} // endswitch Type
......@@ -1740,7 +1818,7 @@ PVAL JSONCOL::GetColumnValue(PGLOBAL g, PJSON row, int i)
Value->SetValue(row->GetType() == TYPE_JAR ? ((PJAR)row)->size() : 1);
return(Value);
} else if (Nodes[i].Op == OP_XX) {
return MakeJson(G, row);
return MakeJson(G, row, i);
} else switch (row->GetType()) {
case TYPE_JOB:
if (!Nodes[i].Key) {
......
/*************** tabjson H Declares Source Code File (.H) **************/
/* Name: tabjson.h Version 1.3 */
/* */
/* (C) Copyright to the author Olivier BERTRAND 2014 - 2018 */
/* (C) Copyright to the author Olivier BERTRAND 2014 - 2021 */
/* */
/* This file contains the JSON classes declares. */
/***********************************************************************/
......@@ -67,10 +67,11 @@ class JSONDISC : public BLOCK {
PJSON jsp;
PJOB row;
PCSZ sep;
PCSZ strfy;
char colname[65], fmt[129], buf[16];
uint *length;
int i, n, bf, ncol, lvl, sz, limit;
bool all, strfy;
bool all;
}; // end of JSONDISC
/***********************************************************************/
......@@ -230,8 +231,9 @@ class DllExport JSONCOL : public DOSCOL {
PVAL GetColumnValue(PGLOBAL g, PJSON row, int i);
PVAL ExpandArray(PGLOBAL g, PJAR arp, int n);
PVAL CalculateArray(PGLOBAL g, PJAR arp, int n);
PVAL MakeJson(PGLOBAL g, PJSON jsp);
void SetJsonValue(PGLOBAL g, PVAL vp, PJVAL val);
PVAL MakeJson(PGLOBAL g, PJSON jsp, int n);
PJVAL GetRowValue(PGLOBAL g, PJSON row, int i);
void SetJsonValue(PGLOBAL g, PVAL vp, PJVAL val);
PJSON GetRow(PGLOBAL g);
// Default constructor not to be used
......
This diff is collapsed.
......@@ -148,14 +148,21 @@ PQRYRES XMLColumns(PGLOBAL g, char *db, char *tab, PTOS topt, bool info)
/* Open the input file. */
/*********************************************************************/
if (!(fn = GetStringTableOption(g, topt, "Filename", NULL))) {
strcpy(g->Message, MSG(MISSING_FNAME));
return NULL;
} else {
lvl = GetIntegerTableOption(g, topt, "Level", GetDefaultDepth());
lvl = GetIntegerTableOption(g, topt, "Depth", lvl);
lvl = (lvl < 0) ? 0 : (lvl > 16) ? 16 : lvl;
if (topt->http) // REST table can have default filename
fn = GetStringTableOption(g, topt, "Subtype", NULL);
if (!fn) {
strcpy(g->Message, MSG(MISSING_FNAME));
return NULL;
} else
topt->subtype = NULL;
} // endif fn
lvl = GetIntegerTableOption(g, topt, "Level", GetDefaultDepth());
lvl = GetIntegerTableOption(g, topt, "Depth", lvl);
lvl = (lvl < 0) ? 0 : (lvl > 16) ? 16 : lvl;
if (trace(1))
htrc("File %s lvl=%d\n", topt->filename, lvl);
......
......@@ -69,7 +69,7 @@ class VALBLK : public BLOCK {
int GetPrec(void) {return Prec;}
void SetCheck(bool b) {Check = b;}
void MoveNull(int i, int j)
{if (To_Nulls) To_Nulls[j] = To_Nulls[j];}
{if (To_Nulls) To_Nulls[j] = To_Nulls[i];}
virtual void SetNull(int n, bool b)
{if (To_Nulls) {To_Nulls[n] = (b) ? '*' : 0;}}
virtual bool IsNull(int n) {return To_Nulls && To_Nulls[n];}
......
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