Commit f657aab9 authored by Olivier Bertrand's avatar Olivier Bertrand

Commiting merge from ob-10.0

parents 406e3aaa 8ba013a2
...@@ -28,8 +28,8 @@ tabvct.cpp tabvir.cpp tabxcl.cpp valblk.cpp value.cpp xindex.cpp xobject.cpp ...@@ -28,8 +28,8 @@ tabvct.cpp tabvir.cpp tabxcl.cpp valblk.cpp value.cpp xindex.cpp xobject.cpp
array.h blkfil.h block.h catalog.h checklvl.h colblk.h connect.h csort.h array.h blkfil.h block.h catalog.h checklvl.h colblk.h connect.h csort.h
engmsg.h filamap.h filamdbf.h filamfix.h filamtxt.h filamvct.h filamzip.h engmsg.h filamap.h filamdbf.h filamfix.h filamtxt.h filamvct.h filamzip.h
filter.h global.h ha_connect.h inihandl.h json.h maputil.h msgid.h mycat.h filter.h global.h ha_connect.h inihandl.h json.h jsonudf.h maputil.h msgid.h
myconn.h myutil.h os.h osutil.h plgcnx.h plgdbsem.h preparse.h reldef.h mycat.h myconn.h myutil.h os.h osutil.h plgcnx.h plgdbsem.h preparse.h reldef.h
resource.h tabcol.h tabdos.h tabfix.h tabfmt.h tabjson.h tabmul.h tabmysql.h resource.h tabcol.h tabdos.h tabfix.h tabfmt.h tabjson.h tabmul.h tabmysql.h
taboccur.h tabpivot.h tabsys.h tabtbl.h tabutil.h tabvct.h tabvir.h tabxcl.h taboccur.h tabpivot.h tabsys.h tabtbl.h tabutil.h tabvct.h tabvir.h tabxcl.h
user_connect.h valblk.h value.h xindex.h xobject.h xtable.h) user_connect.h valblk.h value.h xindex.h xobject.h xtable.h)
...@@ -48,7 +48,7 @@ IF(UNIX) ...@@ -48,7 +48,7 @@ IF(UNIX)
# Bar: -Wfatal-errors removed (does not present in gcc on solaris10) # Bar: -Wfatal-errors removed (does not present in gcc on solaris10)
if(WITH_WARNINGS) if(WITH_WARNINGS)
add_definitions(-Wall -Wextra -Wmissing-declarations) add_definitions(-Wall -Wextra -Wmissing-declarations)
message(STATUS "CONNECT: GCC: All warnings enabled") #message(STATUS "CONNECT: GCC: All warnings enabled")
else() else()
add_definitions(-Wall -Wmissing-declarations) add_definitions(-Wall -Wmissing-declarations)
add_definitions(-Wno-write-strings) add_definitions(-Wno-write-strings)
...@@ -69,7 +69,7 @@ IF(UNIX) ...@@ -69,7 +69,7 @@ IF(UNIX)
# These switches are for C++ only # These switches are for C++ only
# add_definitions(-Wno-reorder) # add_definitions(-Wno-reorder)
message(STATUS "CONNECT: GCC: Some warnings disabled") #message(STATUS "CONNECT: GCC: Some warnings disabled")
endif(WITH_WARNINGS) endif(WITH_WARNINGS)
add_definitions( -DUNIX -DLINUX -DUBUNTU ) add_definitions( -DUNIX -DLINUX -DUBUNTU )
......
...@@ -735,15 +735,10 @@ static void SetSwapValue(PVAL valp, char *kp) ...@@ -735,15 +735,10 @@ static void SetSwapValue(PVAL valp, char *kp)
/* IndexRead: fetch a record having the index value. */ /* IndexRead: fetch a record having the index value. */
/***********************************************************************/ /***********************************************************************/
RCODE CntIndexRead(PGLOBAL g, PTDB ptdb, OPVAL op, RCODE CntIndexRead(PGLOBAL g, PTDB ptdb, OPVAL op,
const void *key, int len, bool mrr) const key_range *kr, bool mrr)
{ {
char *kp= (char*)key;
int n, x; int n, x;
short lg;
bool rcb;
RCODE rc; RCODE rc;
PVAL valp;
PCOL colp;
XXBASE *xbp; XXBASE *xbp;
PTDBDOX tdbp; PTDBDOX tdbp;
...@@ -757,13 +752,13 @@ RCODE CntIndexRead(PGLOBAL g, PTDB ptdb, OPVAL op, ...@@ -757,13 +752,13 @@ RCODE CntIndexRead(PGLOBAL g, PTDB ptdb, OPVAL op,
return RC_FX; return RC_FX;
} else if (x == 2) { } else if (x == 2) {
// Remote index // Remote index
if (ptdb->ReadKey(g, op, key, len)) if (ptdb->ReadKey(g, op, kr))
return RC_FX; return RC_FX;
goto rnd; goto rnd;
} else if (x == 3) { } else if (x == 3) {
if (key) if (kr)
((PTDBASE)ptdb)->SetRecpos(g, *(int*)key); ((PTDBASE)ptdb)->SetRecpos(g, *(int*)kr->key);
if (op == OP_SAME) if (op == OP_SAME)
return RC_NF; return RC_NF;
...@@ -790,7 +785,14 @@ RCODE CntIndexRead(PGLOBAL g, PTDB ptdb, OPVAL op, ...@@ -790,7 +785,14 @@ RCODE CntIndexRead(PGLOBAL g, PTDB ptdb, OPVAL op,
xbp= (XXBASE*)tdbp->To_Kindex; xbp= (XXBASE*)tdbp->To_Kindex;
if (key) { if (kr) {
char *kp= (char*)kr->key;
int len= kr->length;
short lg;
bool rcb;
PVAL valp;
PCOL colp;
for (n= 0; n < tdbp->Knum; n++) { for (n= 0; n < tdbp->Knum; n++) {
colp= (PCOL)tdbp->To_Key_Col[n]; colp= (PCOL)tdbp->To_Key_Col[n];
...@@ -832,10 +834,10 @@ RCODE CntIndexRead(PGLOBAL g, PTDB ptdb, OPVAL op, ...@@ -832,10 +834,10 @@ RCODE CntIndexRead(PGLOBAL g, PTDB ptdb, OPVAL op,
kp+= valp->GetClen(); kp+= valp->GetClen();
if (len == kp - (char*)key) { if (len == kp - (char*)kr->key) {
n++; n++;
break; break;
} else if (len < kp - (char*)key) { } else if (len < kp - (char*)kr->key) {
strcpy(g->Message, "Key buffer is too small"); strcpy(g->Message, "Key buffer is too small");
return RC_FX; return RC_FX;
} // endif len } // endif len
......
...@@ -36,7 +36,7 @@ bool CntRewindTable(PGLOBAL g, PTDB tdbp); ...@@ -36,7 +36,7 @@ bool CntRewindTable(PGLOBAL g, PTDB tdbp);
int CntCloseTable(PGLOBAL g, PTDB tdbp, bool nox, bool abort); int CntCloseTable(PGLOBAL g, PTDB tdbp, bool nox, bool abort);
int CntIndexInit(PGLOBAL g, PTDB tdbp, int id, bool sorted); int CntIndexInit(PGLOBAL g, PTDB tdbp, int id, bool sorted);
RCODE CntReadNext(PGLOBAL g, PTDB tdbp); RCODE CntReadNext(PGLOBAL g, PTDB tdbp);
RCODE CntIndexRead(PGLOBAL g, PTDB, OPVAL op, const void *k, int n, bool mrr); RCODE CntIndexRead(PGLOBAL g, PTDB, OPVAL op, const key_range *kr, bool mrr);
RCODE CntWriteRow(PGLOBAL g, PTDB tdbp); RCODE CntWriteRow(PGLOBAL g, PTDB tdbp);
RCODE CntUpdateRow(PGLOBAL g, PTDB tdbp); RCODE CntUpdateRow(PGLOBAL g, PTDB tdbp);
RCODE CntDeleteRow(PGLOBAL g, PTDB tdbp, bool all); RCODE CntDeleteRow(PGLOBAL g, PTDB tdbp, bool all);
...@@ -60,7 +60,7 @@ class TDBDOX: public TDBDOS { ...@@ -60,7 +60,7 @@ class TDBDOX: public TDBDOS {
friend int MakeIndex(PGLOBAL, PTDB, PIXDEF); friend int MakeIndex(PGLOBAL, PTDB, PIXDEF);
friend int CntCloseTable(PGLOBAL, PTDB, bool, bool); friend int CntCloseTable(PGLOBAL, PTDB, bool, bool);
friend int CntIndexInit(PGLOBAL, PTDB, int, bool); friend int CntIndexInit(PGLOBAL, PTDB, int, bool);
friend RCODE CntIndexRead(PGLOBAL, PTDB, OPVAL, const void*, int, bool); friend RCODE CntIndexRead(PGLOBAL, PTDB, OPVAL, const key_range*, bool);
friend RCODE CntDeleteRow(PGLOBAL, PTDB, bool); friend RCODE CntDeleteRow(PGLOBAL, PTDB, bool);
friend int CntIndexRange(PGLOBAL, PTDB, const uchar**, uint*, friend int CntIndexRange(PGLOBAL, PTDB, const uchar**, uint*,
bool*, key_part_map*); bool*, key_part_map*);
......
...@@ -1404,8 +1404,13 @@ void ZLBFAM::Rewind(void) ...@@ -1404,8 +1404,13 @@ void ZLBFAM::Rewind(void)
// We must be positioned after the header block // We must be positioned after the header block
if (CurBlk >= 0) { // Nothing to do if no block read yet if (CurBlk >= 0) { // Nothing to do if no block read yet
if (!Optimized) { // If optimized, fseek will be done in ReadBuffer if (!Optimized) { // If optimized, fseek will be done in ReadBuffer
size_t st;
rewind(Stream); rewind(Stream);
fread(Zlenp, sizeof(int), 1, Stream);
if (!(st = fread(Zlenp, sizeof(int), 1, Stream)) && trace)
htrc("fread error %d in Rewind", errno);
fseek(Stream, *Zlenp + sizeof(int), SEEK_SET); fseek(Stream, *Zlenp + sizeof(int), SEEK_SET);
OldBlk = -1; OldBlk = -1;
} // endif Optimized } // endif Optimized
......
...@@ -169,9 +169,9 @@ ...@@ -169,9 +169,9 @@
#define JSONMAX 10 // JSON Default max grp size #define JSONMAX 10 // JSON Default max grp size
extern "C" { extern "C" {
char version[]= "Version 1.03.0007 October 20, 2015"; char version[]= "Version 1.04.0005 November 20, 2015";
#if defined(__WIN__) #if defined(__WIN__)
char compver[]= "Version 1.03.0007 " __DATE__ " " __TIME__; char compver[]= "Version 1.04.0005 " __DATE__ " " __TIME__;
char slash= '\\'; char slash= '\\';
#else // !__WIN__ #else // !__WIN__
char slash= '/'; char slash= '/';
...@@ -1114,7 +1114,7 @@ int GetIntegerTableOption(PGLOBAL g, PTOS options, char *opname, int idef) ...@@ -1114,7 +1114,7 @@ int GetIntegerTableOption(PGLOBAL g, PTOS options, char *opname, int idef)
else if (!stricmp(opname, "Compressed")) else if (!stricmp(opname, "Compressed"))
opval= (options->compressed); opval= (options->compressed);
if (opval == NO_IVAL) { if (opval == (ulonglong)NO_IVAL) {
char *pv; char *pv;
if ((pv= GetListOption(g, opname, options->oplist))) if ((pv= GetListOption(g, opname, options->oplist)))
...@@ -2195,58 +2195,111 @@ int ha_connect::CheckRecord(PGLOBAL g, const uchar *, uchar *newbuf) ...@@ -2195,58 +2195,111 @@ int ha_connect::CheckRecord(PGLOBAL g, const uchar *, uchar *newbuf)
} // end of dummy CheckRecord } // end of dummy CheckRecord
/***********************************************************************/
/* Return true if this field is used in current indexing. */
/***********************************************************************/
bool ha_connect::IsIndexed(Field *fp)
{
if (active_index < MAX_KEY) {
KEY_PART_INFO *kpart;
KEY *kfp= &table->key_info[active_index];
uint rem= kfp->user_defined_key_parts;
for (kpart= kfp->key_part; rem; rem--, kpart++)
if (kpart->field == fp)
return true;
} // endif active_index
return false;
} // end of IsIndexed
/***********************************************************************/ /***********************************************************************/
/* Return the where clause for remote indexed read. */ /* Return the where clause for remote indexed read. */
/***********************************************************************/ /***********************************************************************/
bool ha_connect::MakeKeyWhere(PGLOBAL g, PSTRG qry, OPVAL op, char q, bool ha_connect::MakeKeyWhere(PGLOBAL g, PSTRG qry, OPVAL vop, char q,
const void *key, int klen) const key_range *kr)
{ {
const uchar *ptr; const uchar *ptr;
uint rem, len, stlen; //, prtlen; //uint i, rem, len, klen, stlen;
bool nq, oom, b= false; uint i, rem, len, stlen;
bool nq, both, oom= false;
OPVAL op;
Field *fp; Field *fp;
const key_range *ranges[2];
my_bitmap_map *old_map;
KEY *kfp; KEY *kfp;
KEY_PART_INFO *kpart; KEY_PART_INFO *kpart;
if (active_index == MAX_KEY) if (active_index == MAX_KEY)
return false; return false;
else if (!key) {
ranges[0]= kr;
ranges[1]= (end_range && !eq_range) ? &save_end_range : NULL;
if (!ranges[0] && !ranges[1]) {
strcpy(g->Message, "MakeKeyWhere: No key"); strcpy(g->Message, "MakeKeyWhere: No key");
return true; return true;
} // endif key } else
both= ranges[0] && ranges[1];
oom= qry->Append(" WHERE (");
kfp= &table->key_info[active_index]; kfp= &table->key_info[active_index];
rem= kfp->user_defined_key_parts, old_map= dbug_tmp_use_all_columns(table, table->write_set);
len= klen,
ptr= (const uchar *)key; for (i = 0; i <= 1; i++) {
if (ranges[i] == NULL)
continue;
if (both && i > 0)
oom|= qry->Append(") AND (");
else
oom|= qry->Append(" WHERE (");
// klen= len= ranges[i]->length;
len= ranges[i]->length;
rem= kfp->user_defined_key_parts;
ptr= ranges[i]->key;
for (kpart= kfp->key_part; rem; rem--, kpart++) { for (kpart= kfp->key_part; rem; rem--, kpart++) {
fp= kpart->field; fp= kpart->field;
stlen= kpart->store_length; stlen= kpart->store_length;
// prtlen= MY_MIN(stlen, len);
nq= fp->str_needs_quotes(); nq= fp->str_needs_quotes();
if (b) if (kpart != kfp->key_part)
oom|= qry->Append(" AND "); oom|= qry->Append(" AND ");
else
b= true;
if (q) {
oom|= qry->Append(q); oom|= qry->Append(q);
oom|= qry->Append((PSZ)fp->field_name); oom|= qry->Append((PSZ)fp->field_name);
oom|= qry->Append(q); oom|= qry->Append(q);
} else
oom|= qry->Append((PSZ)fp->field_name);
switch (op) { switch (ranges[i]->flag) {
case OP_EQ: case HA_READ_KEY_EXACT:
case OP_GT: // op= (stlen >= len || !nq || fp->result_type() != STRING_RESULT)
case OP_GE: // ? OP_EQ : OP_LIKE;
case OP_LT: op= OP_EQ;
case OP_LE: break;
oom |= qry->Append((PSZ)GetValStr(op, false)); case HA_READ_AFTER_KEY:
op= (stlen >= len) ? (!i ? OP_GT : OP_LE) : OP_GE;
break;
case HA_READ_KEY_OR_NEXT:
op= OP_GE;
break;
case HA_READ_BEFORE_KEY:
op= (stlen >= len) ? OP_LT : OP_LE;
break;
case HA_READ_KEY_OR_PREV:
op= OP_LE;
break; break;
default: default:
oom|= qry->Append(" ??? "); sprintf(g->Message, "cannot handle flag %d", ranges[i]->flag);
} // endwitch op goto err;
} // endswitch flag
oom|= qry->Append((PSZ)GetValStr(op, false));
if (nq) if (nq)
oom|= qry->Append('\''); oom|= qry->Append('\'');
...@@ -2255,19 +2308,19 @@ bool ha_connect::MakeKeyWhere(PGLOBAL g, PSTRG qry, OPVAL op, char q, ...@@ -2255,19 +2308,19 @@ bool ha_connect::MakeKeyWhere(PGLOBAL g, PSTRG qry, OPVAL op, char q,
String varchar; String varchar;
uint var_length= uint2korr(ptr); uint var_length= uint2korr(ptr);
varchar.set_quick((char*) ptr+HA_KEY_BLOB_LENGTH, varchar.set_quick((char*)ptr + HA_KEY_BLOB_LENGTH,
var_length, &my_charset_bin); var_length, &my_charset_bin);
oom|= qry->Append(varchar.ptr(), varchar.length()); oom|= qry->Append(varchar.ptr(), varchar.length(), nq);
} else { } else {
char strbuff[MAX_FIELD_WIDTH]; char strbuff[MAX_FIELD_WIDTH];
String str(strbuff, sizeof(strbuff), kpart->field->charset()), *res; String str(strbuff, sizeof(strbuff), kpart->field->charset()), *res;
res= fp->val_str(&str, ptr); res= fp->val_str(&str, ptr);
oom|= qry->Append(res->ptr(), res->length()); oom|= qry->Append(res->ptr(), res->length(), nq);
} // endif flag } // endif flag
if (nq) if (nq)
oom|= qry->Append('\''); oom |= qry->Append('\'');
if (stlen >= len) if (stlen >= len)
break; break;
...@@ -2280,10 +2333,17 @@ bool ha_connect::MakeKeyWhere(PGLOBAL g, PSTRG qry, OPVAL op, char q, ...@@ -2280,10 +2333,17 @@ bool ha_connect::MakeKeyWhere(PGLOBAL g, PSTRG qry, OPVAL op, char q,
ptr+= stlen - MY_TEST(kpart->null_bit); ptr+= stlen - MY_TEST(kpart->null_bit);
} // endfor kpart } // endfor kpart
} // endfor i
if ((oom|= qry->Append(")"))) if ((oom|= qry->Append(")")))
strcpy(g->Message, "Out of memory"); strcpy(g->Message, "Out of memory");
dbug_tmp_restore_column_map(table->write_set, old_map);
return oom; return oom;
err:
dbug_tmp_restore_column_map(table->write_set, old_map);
return true;
} // end of MakeKeyWhere } // end of MakeKeyWhere
...@@ -2483,6 +2543,8 @@ PFIL ha_connect::CondFilter(PGLOBAL g, Item *cond) ...@@ -2483,6 +2543,8 @@ PFIL ha_connect::CondFilter(PGLOBAL g, Item *cond)
case MYSQL_TYPE_YEAR: case MYSQL_TYPE_YEAR:
case MYSQL_TYPE_NEWDATE: case MYSQL_TYPE_NEWDATE:
return NULL; return NULL;
default:
break;
} // endswitch type } // endswitch type
if (trace) { if (trace) {
...@@ -2562,8 +2624,9 @@ PFIL ha_connect::CondFilter(PGLOBAL g, Item *cond) ...@@ -2562,8 +2624,9 @@ PFIL ha_connect::CondFilter(PGLOBAL g, Item *cond)
/***********************************************************************/ /***********************************************************************/
/* Check the WHERE condition and return a MYSQL/ODBC/WQL filter. */ /* Check the WHERE condition and return a MYSQL/ODBC/WQL filter. */
/***********************************************************************/ /***********************************************************************/
PCFIL ha_connect::CheckCond(PGLOBAL g, PCFIL filp, AMT tty, Item *cond) PCFIL ha_connect::CheckCond(PGLOBAL g, PCFIL filp, const Item *cond)
{ {
AMT tty = filp->Type;
char *body= filp->Body; char *body= filp->Body;
unsigned int i; unsigned int i;
bool ismul= false, x= (tty == TYPE_AM_MYX || tty == TYPE_AM_XDBC); bool ismul= false, x= (tty == TYPE_AM_MYX || tty == TYPE_AM_XDBC);
...@@ -2596,7 +2659,7 @@ PCFIL ha_connect::CheckCond(PGLOBAL g, PCFIL filp, AMT tty, Item *cond) ...@@ -2596,7 +2659,7 @@ PCFIL ha_connect::CheckCond(PGLOBAL g, PCFIL filp, AMT tty, Item *cond)
List<Item>* arglist= cond_item->argument_list(); List<Item>* arglist= cond_item->argument_list();
List_iterator<Item> li(*arglist); List_iterator<Item> li(*arglist);
Item *subitem; const Item *subitem;
p1= body + strlen(body); p1= body + strlen(body);
strcpy(p1, "("); strcpy(p1, "(");
...@@ -2604,7 +2667,7 @@ PCFIL ha_connect::CheckCond(PGLOBAL g, PCFIL filp, AMT tty, Item *cond) ...@@ -2604,7 +2667,7 @@ PCFIL ha_connect::CheckCond(PGLOBAL g, PCFIL filp, AMT tty, Item *cond)
for (i= 0; i < arglist->elements; i++) for (i= 0; i < arglist->elements; i++)
if ((subitem= li++)) { if ((subitem= li++)) {
if (!CheckCond(g, filp, tty, subitem)) { if (!CheckCond(g, filp, subitem)) {
if (vop == OP_OR || nonul) if (vop == OP_OR || nonul)
return NULL; return NULL;
else else
...@@ -2626,7 +2689,6 @@ PCFIL ha_connect::CheckCond(PGLOBAL g, PCFIL filp, AMT tty, Item *cond) ...@@ -2626,7 +2689,6 @@ PCFIL ha_connect::CheckCond(PGLOBAL g, PCFIL filp, AMT tty, Item *cond)
} else if (cond->type() == COND::FUNC_ITEM) { } else if (cond->type() == COND::FUNC_ITEM) {
unsigned int i; unsigned int i;
// int n;
bool iscol, neg= FALSE; bool iscol, neg= FALSE;
Item_func *condf= (Item_func *)cond; Item_func *condf= (Item_func *)cond;
Item* *args= condf->arguments(); Item* *args= condf->arguments();
...@@ -2635,8 +2697,6 @@ PCFIL ha_connect::CheckCond(PGLOBAL g, PCFIL filp, AMT tty, Item *cond) ...@@ -2635,8 +2697,6 @@ PCFIL ha_connect::CheckCond(PGLOBAL g, PCFIL filp, AMT tty, Item *cond)
htrc("Func type=%d argnum=%d\n", condf->functype(), htrc("Func type=%d argnum=%d\n", condf->functype(),
condf->argument_count()); condf->argument_count());
// neg= condf->
switch (condf->functype()) { switch (condf->functype()) {
case Item_func::EQUAL_FUNC: case Item_func::EQUAL_FUNC:
case Item_func::EQ_FUNC: vop= OP_EQ; break; case Item_func::EQ_FUNC: vop= OP_EQ; break;
...@@ -2645,6 +2705,10 @@ PCFIL ha_connect::CheckCond(PGLOBAL g, PCFIL filp, AMT tty, Item *cond) ...@@ -2645,6 +2705,10 @@ PCFIL ha_connect::CheckCond(PGLOBAL g, PCFIL filp, AMT tty, Item *cond)
case Item_func::LE_FUNC: vop= OP_LE; break; case Item_func::LE_FUNC: vop= OP_LE; break;
case Item_func::GE_FUNC: vop= OP_GE; break; case Item_func::GE_FUNC: vop= OP_GE; break;
case Item_func::GT_FUNC: vop= OP_GT; break; case Item_func::GT_FUNC: vop= OP_GT; break;
case Item_func::LIKE_FUNC: vop= OP_LIKE; break;
case Item_func::ISNOTNULL_FUNC:
neg = true;
case Item_func::ISNULL_FUNC: vop= OP_NULL; break;
case Item_func::IN_FUNC: vop= OP_IN; case Item_func::IN_FUNC: vop= OP_IN;
case Item_func::BETWEEN: case Item_func::BETWEEN:
ismul= true; ismul= true;
...@@ -2658,7 +2722,7 @@ PCFIL ha_connect::CheckCond(PGLOBAL g, PCFIL filp, AMT tty, Item *cond) ...@@ -2658,7 +2722,7 @@ PCFIL ha_connect::CheckCond(PGLOBAL g, PCFIL filp, AMT tty, Item *cond)
else if (ismul && tty == TYPE_AM_WMI) else if (ismul && tty == TYPE_AM_WMI)
return NULL; // Not supported by WQL return NULL; // Not supported by WQL
if (x && (neg || !(vop == OP_EQ || vop == OP_IN))) if (x && (neg || !(vop == OP_EQ || vop == OP_IN || vop == OP_NULL)))
return NULL; return NULL;
for (i= 0; i < condf->argument_count(); i++) { for (i= 0; i < condf->argument_count(); i++) {
...@@ -2679,9 +2743,10 @@ PCFIL ha_connect::CheckCond(PGLOBAL g, PCFIL filp, AMT tty, Item *cond) ...@@ -2679,9 +2743,10 @@ PCFIL ha_connect::CheckCond(PGLOBAL g, PCFIL filp, AMT tty, Item *cond)
if (x && i) if (x && i)
return NULL; return NULL;
else if (pField->field->table != table)
if (pField->field->table != table)
return NULL; // Field does not belong to this table return NULL; // Field does not belong to this table
else if (tty != TYPE_AM_WMI && IsIndexed(pField->field))
return NULL; // Will be handled by ReadKey
else else
fop= GetFieldOptionStruct(pField->field); fop= GetFieldOptionStruct(pField->field);
...@@ -2712,7 +2777,7 @@ PCFIL ha_connect::CheckCond(PGLOBAL g, PCFIL filp, AMT tty, Item *cond) ...@@ -2712,7 +2777,7 @@ PCFIL ha_connect::CheckCond(PGLOBAL g, PCFIL filp, AMT tty, Item *cond)
strcat(body, fnm); strcat(body, fnm);
} else if (args[i]->type() == COND::FUNC_ITEM) { } else if (args[i]->type() == COND::FUNC_ITEM) {
if (tty == TYPE_AM_MYSQL) { if (tty == TYPE_AM_MYSQL) {
if (!CheckCond(g, filp, tty, args[i])) if (!CheckCond(g, filp, args[i]))
return NULL; return NULL;
} else } else
...@@ -2901,14 +2966,17 @@ const COND *ha_connect::cond_push(const COND *cond) ...@@ -2901,14 +2966,17 @@ const COND *ha_connect::cond_push(const COND *cond)
goto fin; goto fin;
if (b) { if (b) {
PCFIL filp= (PCFIL)PlugSubAlloc(g, NULL, sizeof(CONDFIL)); PCFIL filp;
if ((filp= tdbp->GetCondFil()) && filp->Cond == cond &&
filp->Idx == active_index && filp->Type == tty)
goto fin; // Already done
filp= new(g) CONDFIL(cond, active_index, tty);
filp->Body= (char*)PlugSubAlloc(g, NULL, (x) ? 128 : 0); filp->Body= (char*)PlugSubAlloc(g, NULL, (x) ? 128 : 0);
*filp->Body= 0; *filp->Body= 0;
filp->Op= OP_XX;
filp->Cmds= NULL;
if (CheckCond(g, filp, tty, (Item *)cond)) { if (CheckCond(g, filp, cond)) {
if (trace) if (trace)
htrc("cond_push: %s\n", filp->Body); htrc("cond_push: %s\n", filp->Body);
...@@ -3372,13 +3440,13 @@ int ha_connect::index_end() ...@@ -3372,13 +3440,13 @@ int ha_connect::index_end()
/****************************************************************************/ /****************************************************************************/
/* This is internally called by all indexed reading functions. */ /* This is internally called by all indexed reading functions. */
/****************************************************************************/ /****************************************************************************/
int ha_connect::ReadIndexed(uchar *buf, OPVAL op, const uchar *key, uint key_len) int ha_connect::ReadIndexed(uchar *buf, OPVAL op, const key_range *kr)
{ {
int rc; int rc;
//statistic_increment(ha_read_key_count, &LOCK_status); //statistic_increment(ha_read_key_count, &LOCK_status);
switch (CntIndexRead(xp->g, tdbp, op, key, (int)key_len, mrr)) { switch (CntIndexRead(xp->g, tdbp, op, kr, mrr)) {
case RC_OK: case RC_OK:
xp->fnd++; xp->fnd++;
rc= MakeRecord((char*)buf); rc= MakeRecord((char*)buf);
...@@ -3444,7 +3512,12 @@ int ha_connect::index_read(uchar * buf, const uchar * key, uint key_len, ...@@ -3444,7 +3512,12 @@ int ha_connect::index_read(uchar * buf, const uchar * key, uint key_len,
htrc("%p index_read: op=%d\n", this, op); htrc("%p index_read: op=%d\n", this, op);
if (indexing > 0) { if (indexing > 0) {
rc= ReadIndexed(buf, op, key, key_len); start_key.key= key;
start_key.length= key_len;
start_key.flag= find_flag;
start_key.keypart_map= 0;
rc= ReadIndexed(buf, op, &start_key);
if (rc == HA_ERR_INTERNAL_ERROR) { if (rc == HA_ERR_INTERNAL_ERROR) {
nox= true; // To block making indexes nox= true; // To block making indexes
...@@ -3750,7 +3823,7 @@ void ha_connect::position(const uchar *) ...@@ -3750,7 +3823,7 @@ void ha_connect::position(const uchar *)
//if (((PTDBASE)tdbp)->GetDef()->Indexable()) //if (((PTDBASE)tdbp)->GetDef()->Indexable())
my_store_ptr(ref, ref_length, (my_off_t)((PTDBASE)tdbp)->GetRecpos()); my_store_ptr(ref, ref_length, (my_off_t)((PTDBASE)tdbp)->GetRecpos());
if (trace) if (trace > 1)
htrc("position: pos=%d\n", ((PTDBASE)tdbp)->GetRecpos()); htrc("position: pos=%d\n", ((PTDBASE)tdbp)->GetRecpos());
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
...@@ -4034,7 +4107,27 @@ bool ha_connect::check_privileges(THD *thd, PTOS options, char *dbn) ...@@ -4034,7 +4107,27 @@ bool ha_connect::check_privileges(THD *thd, PTOS options, char *dbn)
case TAB_MAC: case TAB_MAC:
case TAB_WMI: case TAB_WMI:
case TAB_OEM: case TAB_OEM:
#ifdef NO_EMBEDDED_ACCESS_CHECKS
return false;
#endif
/*
If table or table->mdl_ticket is NULL - it's a DLL, e.g. CREATE TABLE.
if the table has an MDL_EXCLUSIVE lock - it's a DDL too, e.g. the
insert step of CREATE ... SELECT.
Otherwise it's a DML, the table was normally opened, locked,
privilege were already checked, and table->grant.privilege is set.
With SQL SECURITY DEFINER, table->grant.privilege has definer's privileges.
*/
if (!table || !table->mdl_ticket || table->mdl_ticket->get_type() == MDL_EXCLUSIVE)
return check_access(thd, FILE_ACL, db, NULL, NULL, 0, 0); return check_access(thd, FILE_ACL, db, NULL, NULL, 0, 0);
if (table->grant.privilege & FILE_ACL)
return false;
status_var_increment(thd->status_var.access_denied_errors);
my_error(access_denied_error_code(thd->password), MYF(0),
thd->security_ctx->priv_user, thd->security_ctx->priv_host,
(thd->password ? ER(ER_YES) : ER(ER_NO)));
return true;
// This is temporary until a solution is found // This is temporary until a solution is found
case TAB_TBL: case TAB_TBL:
...@@ -4421,15 +4514,16 @@ int ha_connect::external_lock(THD *thd, int lock_type) ...@@ -4421,15 +4514,16 @@ int ha_connect::external_lock(THD *thd, int lock_type)
xmod= MODE_ANY; // For info commands xmod= MODE_ANY; // For info commands
DBUG_RETURN(rc); DBUG_RETURN(rc);
} // endif MODE_ANY } // endif MODE_ANY
else
DBUG_ASSERT(table && table->s);
if (check_privileges(thd, options, table->s->db.str)) { if (check_privileges(thd, options, table->s->db.str)) {
strcpy(g->Message, "This operation requires the FILE privilege"); strcpy(g->Message, "This operation requires the FILE privilege");
htrc("%s\n", g->Message); htrc("%s\n", g->Message);
DBUG_RETURN(HA_ERR_INTERNAL_ERROR); DBUG_RETURN(HA_ERR_INTERNAL_ERROR);
} // endif check_privileges } // endif check_privileges
DBUG_ASSERT(table && table->s);
// Table mode depends on the query type // Table mode depends on the query type
newmode= CheckMode(g, thd, newmode, &xcheck, &cras); newmode= CheckMode(g, thd, newmode, &xcheck, &cras);
...@@ -5068,7 +5162,6 @@ static int connect_assisted_discovery(handlerton *, THD* thd, ...@@ -5068,7 +5162,6 @@ static int connect_assisted_discovery(handlerton *, THD* thd,
hdr= (int)topt->header; hdr= (int)topt->header;
tbl= topt->tablist; tbl= topt->tablist;
col= topt->colist; col= topt->colist;
lrecl= (int)topt->lrecl;
if (topt->oplist) { if (topt->oplist) {
host= GetListOption(g, "host", topt->oplist, "localhost"); host= GetListOption(g, "host", topt->oplist, "localhost");
...@@ -5684,6 +5777,14 @@ int ha_connect::create(const char *name, TABLE *table_arg, ...@@ -5684,6 +5777,14 @@ int ha_connect::create(const char *name, TABLE *table_arg,
PGLOBAL g= xp->g; PGLOBAL g= xp->g;
DBUG_ENTER("ha_connect::create"); DBUG_ENTER("ha_connect::create");
/*
This assignment fixes test failures if some
"ALTER TABLE t1 ADD KEY(a)" query exits on ER_ACCESS_DENIED_ERROR
(e.g. on missing FILE_ACL). All following "CREATE TABLE" failed with
"ERROR 1105: CONNECT index modification should be in-place"
TODO: check with Olivier.
*/
g->Xchk= NULL;
int sqlcom= thd_sql_command(table_arg->in_use); int sqlcom= thd_sql_command(table_arg->in_use);
PTOS options= GetTableOptionStruct(table_arg->s); PTOS options= GetTableOptionStruct(table_arg->s);
...@@ -6173,10 +6274,6 @@ bool ha_connect::FileExists(const char *fn, bool bf) ...@@ -6173,10 +6274,6 @@ bool ha_connect::FileExists(const char *fn, bool bf)
int n; int n;
struct stat info; struct stat info;
if (check_access(ha_thd(), FILE_ACL, table->s->db.str,
NULL, NULL, 0, 0))
return true;
#if defined(__WIN__) #if defined(__WIN__)
s= "\\"; s= "\\";
#else // !__WIN__ #else // !__WIN__
...@@ -6662,10 +6759,10 @@ maria_declare_plugin(connect) ...@@ -6662,10 +6759,10 @@ maria_declare_plugin(connect)
PLUGIN_LICENSE_GPL, PLUGIN_LICENSE_GPL,
connect_init_func, /* Plugin Init */ connect_init_func, /* Plugin Init */
connect_done_func, /* Plugin Deinit */ connect_done_func, /* Plugin Deinit */
0x0103, /* version number (1.03) */ 0x0104, /* version number (1.04) */
NULL, /* status variables */ NULL, /* status variables */
connect_system_variables, /* system variables */ connect_system_variables, /* system variables */
"1.03.0007", /* string version */ "1.04.0003", /* string version */
MariaDB_PLUGIN_MATURITY_GAMMA /* maturity */ MariaDB_PLUGIN_MATURITY_BETA /* maturity */
} }
maria_declare_plugin_end; maria_declare_plugin_end;
...@@ -241,11 +241,12 @@ class ha_connect: public handler ...@@ -241,11 +241,12 @@ class ha_connect: public handler
int MakeRecord(char *buf); int MakeRecord(char *buf);
int ScanRecord(PGLOBAL g, uchar *buf); int ScanRecord(PGLOBAL g, uchar *buf);
int CheckRecord(PGLOBAL g, const uchar *oldbuf, uchar *newbuf); int CheckRecord(PGLOBAL g, const uchar *oldbuf, uchar *newbuf);
int ReadIndexed(uchar *buf, OPVAL op, const uchar* key= NULL, int ReadIndexed(uchar *buf, OPVAL op, const key_range *kr= NULL);
uint key_len= 0); bool IsIndexed(Field *fp);
bool MakeKeyWhere(PGLOBAL g, PSTRG qry, OPVAL op, char q, bool MakeKeyWhere(PGLOBAL g, PSTRG qry, OPVAL op, char q,
const void *key, int klen); const key_range *kr);
inline char *Strz(LEX_STRING &ls); inline char *Strz(LEX_STRING &ls);
key_range start_key;
/** @brief /** @brief
...@@ -374,7 +375,7 @@ class ha_connect: public handler ...@@ -374,7 +375,7 @@ class ha_connect: public handler
condition stack. condition stack.
*/ */
virtual const COND *cond_push(const COND *cond); virtual const COND *cond_push(const COND *cond);
PCFIL CheckCond(PGLOBAL g, PCFIL filp, AMT tty, Item *cond); PCFIL CheckCond(PGLOBAL g, PCFIL filp, const Item *cond);
const char *GetValStr(OPVAL vop, bool neg); const char *GetValStr(OPVAL vop, bool neg);
PFIL CondFilter(PGLOBAL g, Item *cond); PFIL CondFilter(PGLOBAL g, Item *cond);
//PFIL CheckFilter(PGLOBAL g); //PFIL CheckFilter(PGLOBAL g);
......
/*************** json CPP Declares Source Code File (.H) ***************/ /*************** json CPP Declares Source Code File (.H) ***************/
/* Name: json.cpp Version 1.1 */ /* Name: json.cpp Version 1.2 */
/* */ /* */
/* (C) Copyright to the author Olivier BERTRAND 2014 - 2015 */ /* (C) Copyright to the author Olivier BERTRAND 2014 - 2015 */
/* */ /* */
...@@ -31,11 +31,12 @@ ...@@ -31,11 +31,12 @@
/***********************************************************************/ /***********************************************************************/
/* Parse a json string. */ /* Parse a json string. */
/* Note: when pretty is not known, the caller set pretty to 3. */
/***********************************************************************/ /***********************************************************************/
PJSON ParseJson(PGLOBAL g, char *s, int len, int pretty, bool *comma) PJSON ParseJson(PGLOBAL g, char *s, int len, int *ptyp, bool *comma)
{ {
int i, rc; int i, rc, pretty = (ptyp) ? *ptyp : 3;
bool b = false; bool b = false, pty[3] = {true, true, true};
PJSON jsp = NULL; PJSON jsp = NULL;
STRG src; STRG src;
...@@ -48,6 +49,10 @@ PJSON ParseJson(PGLOBAL g, char *s, int len, int pretty, bool *comma) ...@@ -48,6 +49,10 @@ PJSON ParseJson(PGLOBAL g, char *s, int len, int pretty, bool *comma)
src.str = s; src.str = s;
src.len = len; src.len = len;
// Trying to guess the pretty format
if (s[0] == '[' && (s[1] == '\n' || (s[1] == '\r' && s[2] == '\n')))
pty[0] = false;
// Save stack and allocation environment and prepare error return // Save stack and allocation environment and prepare error return
if (g->jump_level == MAX_JUMP) { if (g->jump_level == MAX_JUMP) {
strcpy(g->Message, MSG(TOO_MANY_JUMPS)); strcpy(g->Message, MSG(TOO_MANY_JUMPS));
...@@ -61,18 +66,16 @@ PJSON ParseJson(PGLOBAL g, char *s, int len, int pretty, bool *comma) ...@@ -61,18 +66,16 @@ PJSON ParseJson(PGLOBAL g, char *s, int len, int pretty, bool *comma)
for (i = 0; i < len; i++) for (i = 0; i < len; i++)
switch (s[i]) { switch (s[i]) {
case '[': case '[':
if (jsp) { if (jsp)
strcpy(g->Message, "More than one item in file"); goto tryit;
goto err; else if (!(jsp = ParseArray(g, ++i, src, pty)))
} else if (!(jsp = ParseArray(g, ++i, src)))
goto err; goto err;
break; break;
case '{': case '{':
if (jsp) { if (jsp)
strcpy(g->Message, "More than one item in file"); goto tryit;
goto err; else if (!(jsp = ParseObject(g, ++i, src, pty)))
} else if (!(jsp = ParseObject(g, ++i, src)))
goto err; goto err;
break; break;
...@@ -82,20 +85,16 @@ PJSON ParseJson(PGLOBAL g, char *s, int len, int pretty, bool *comma) ...@@ -82,20 +85,16 @@ PJSON ParseJson(PGLOBAL g, char *s, int len, int pretty, bool *comma)
case '\r': case '\r':
break; break;
case ',': case ',':
if (jsp && pretty == 1) { if (jsp && (pretty == 1 || pretty == 3)) {
if (comma) if (comma)
*comma = true; *comma = true;
pty[0] = pty[2] = false;
break; break;
} // endif pretty } // endif pretty
sprintf(g->Message, "Unexpected ',' (pretty=%d)", pretty); sprintf(g->Message, "Unexpected ',' (pretty=%d)", pretty);
goto err; goto err;
case '"':
if (!(jsp = ParseValue(g, i, src)))
goto err;
break;
case '(': case '(':
b = true; b = true;
break; break;
...@@ -106,18 +105,41 @@ PJSON ParseJson(PGLOBAL g, char *s, int len, int pretty, bool *comma) ...@@ -106,18 +105,41 @@ PJSON ParseJson(PGLOBAL g, char *s, int len, int pretty, bool *comma)
} // endif b } // endif b
default: default:
sprintf(g->Message, "Bad '%c' character near %.*s", if (jsp)
s[i], ARGS); goto tryit;
else if (!(jsp = ParseValue(g, i, src, pty)))
goto err; goto err;
break;
}; // endswitch s[i] }; // endswitch s[i]
if (!jsp) if (!jsp)
sprintf(g->Message, "Invalid Json string '%.*s'", 50, s); sprintf(g->Message, "Invalid Json string '%.*s'", 50, s);
else if (ptyp && pretty == 3) {
*ptyp = 3; // Not recognized pretty
for (i = 0; i < 3; i++)
if (pty[i]) {
*ptyp = i;
break;
} // endif pty
} // endif ptyp
g->jump_level--; g->jump_level--;
return jsp; return jsp;
err: tryit:
if (pty[0] && (!pretty || pretty > 2)) {
if ((jsp = ParseArray(g, (i = 0), src, pty)) && ptyp && pretty == 3)
*ptyp = (pty[0]) ? 0 : 3;
g->jump_level--;
return jsp;
} else
strcpy(g->Message, "More than one item in file");
err:
g->jump_level--; g->jump_level--;
return NULL; return NULL;
} // end of ParseJson } // end of ParseJson
...@@ -125,11 +147,12 @@ PJSON ParseJson(PGLOBAL g, char *s, int len, int pretty, bool *comma) ...@@ -125,11 +147,12 @@ PJSON ParseJson(PGLOBAL g, char *s, int len, int pretty, bool *comma)
/***********************************************************************/ /***********************************************************************/
/* Parse a JSON Array. */ /* Parse a JSON Array. */
/***********************************************************************/ /***********************************************************************/
PJAR ParseArray(PGLOBAL g, int& i, STRG& src) PJAR ParseArray(PGLOBAL g, int& i, STRG& src, bool *pty)
{ {
char *s = src.str; char *s = src.str;
int len = src.len; int len = src.len;
int level = 0; int level = 0;
bool b = (!i);
PJAR jarp = new(g) JARRAY; PJAR jarp = new(g) JARRAY;
PJVAL jvp = NULL; PJVAL jvp = NULL;
...@@ -151,25 +174,32 @@ PJAR ParseArray(PGLOBAL g, int& i, STRG& src) ...@@ -151,25 +174,32 @@ PJAR ParseArray(PGLOBAL g, int& i, STRG& src)
jarp->InitArray(g); jarp->InitArray(g);
return jarp; return jarp;
case ' ':
case '\t':
case '\n': case '\n':
if (!b)
pty[0] = pty[1] = false;
case '\r': case '\r':
case ' ':
case '\t':
break; break;
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; return NULL;
} else if ((jvp = ParseValue(g, i, src))) { } else if ((jvp = ParseValue(g, i, src, pty)))
jarp->AddValue(g, jvp); jarp->AddValue(g, jvp);
level = 2; else
} else
return NULL; return NULL;
level = 2; level = (b) ? 1 : 2;
break; break;
}; // endswitch s[i] }; // endswitch s[i]
if (b) {
// Case of Pretty == 0
jarp->InitArray(g);
return jarp;
} // endif b
strcpy(g->Message, "Unexpected EOF in array"); strcpy(g->Message, "Unexpected EOF in array");
return NULL; return NULL;
} // end of ParseArray } // end of ParseArray
...@@ -177,7 +207,7 @@ PJAR ParseArray(PGLOBAL g, int& i, STRG& src) ...@@ -177,7 +207,7 @@ PJAR ParseArray(PGLOBAL g, int& i, STRG& src)
/***********************************************************************/ /***********************************************************************/
/* Parse a JSON Object. */ /* Parse a JSON Object. */
/***********************************************************************/ /***********************************************************************/
PJOB ParseObject(PGLOBAL g, int& i, STRG& src) PJOB ParseObject(PGLOBAL g, int& i, STRG& src, bool *pty)
{ {
PSZ key; PSZ key;
char *s = src.str; char *s = src.str;
...@@ -204,7 +234,7 @@ PJOB ParseObject(PGLOBAL g, int& i, STRG& src) ...@@ -204,7 +234,7 @@ PJOB ParseObject(PGLOBAL g, int& i, STRG& src)
break; break;
case ':': case ':':
if (level == 1) { if (level == 1) {
if (!(jpp->Val = ParseValue(g, ++i, src))) if (!(jpp->Val = ParseValue(g, ++i, src, pty)))
return NULL; return NULL;
level = 2; level = 2;
...@@ -229,10 +259,11 @@ PJOB ParseObject(PGLOBAL g, int& i, STRG& src) ...@@ -229,10 +259,11 @@ PJOB ParseObject(PGLOBAL g, int& i, STRG& src)
} // endif level } // endif level
return jobp; return jobp;
case ' ':
case '\t':
case '\n': case '\n':
pty[0] = pty[1] = false;
case '\r': case '\r':
case ' ':
case '\t':
break; break;
default: default:
sprintf(g->Message, "Unexpected character '%c' near %.*s", sprintf(g->Message, "Unexpected character '%c' near %.*s",
...@@ -247,7 +278,7 @@ PJOB ParseObject(PGLOBAL g, int& i, STRG& src) ...@@ -247,7 +278,7 @@ PJOB ParseObject(PGLOBAL g, int& i, STRG& src)
/***********************************************************************/ /***********************************************************************/
/* Parse a JSON Value. */ /* Parse a JSON Value. */
/***********************************************************************/ /***********************************************************************/
PJVAL ParseValue(PGLOBAL g, int& i, STRG& src) PJVAL ParseValue(PGLOBAL g, int& i, STRG& src, bool *pty)
{ {
char *strval, *s = src.str; char *strval, *s = src.str;
int n, len = src.len; int n, len = src.len;
...@@ -255,10 +286,11 @@ PJVAL ParseValue(PGLOBAL g, int& i, STRG& src) ...@@ -255,10 +286,11 @@ PJVAL ParseValue(PGLOBAL g, int& i, STRG& src)
for (; i < len; i++) for (; i < len; i++)
switch (s[i]) { switch (s[i]) {
case ' ':
case '\t':
case '\n': case '\n':
pty[0] = pty[1] = false;
case '\r': case '\r':
case ' ':
case '\t':
break; break;
default: default:
goto suite; goto suite;
...@@ -267,12 +299,12 @@ PJVAL ParseValue(PGLOBAL g, int& i, STRG& src) ...@@ -267,12 +299,12 @@ PJVAL ParseValue(PGLOBAL g, int& i, STRG& src)
suite: suite:
switch (s[i]) { switch (s[i]) {
case '[': case '[':
if (!(jvp->Jsp = ParseArray(g, ++i, src))) if (!(jvp->Jsp = ParseArray(g, ++i, src, pty)))
return NULL; return NULL;
break; break;
case '{': case '{':
if (!(jvp->Jsp = ParseObject(g, ++i, src))) if (!(jvp->Jsp = ParseObject(g, ++i, src, pty)))
return NULL; return NULL;
break; break;
...@@ -319,7 +351,6 @@ PJVAL ParseValue(PGLOBAL g, int& i, STRG& src) ...@@ -319,7 +351,6 @@ PJVAL ParseValue(PGLOBAL g, int& i, STRG& src)
}; // endswitch s[i] }; // endswitch s[i]
jvp->Size = 1;
return jvp; return jvp;
err: err:
...@@ -481,9 +512,9 @@ PVAL ParseNumeric(PGLOBAL g, int& i, STRG& src) ...@@ -481,9 +512,9 @@ PVAL ParseNumeric(PGLOBAL g, int& i, STRG& src)
valp = AllocateValue(g, &dv, TYPE_DOUBLE, nd); valp = AllocateValue(g, &dv, TYPE_DOUBLE, nd);
} else { } else {
int iv = strtol(buf, NULL, 10); long long iv = strtoll(buf, NULL, 10);
valp = AllocateValue(g, &iv, TYPE_INT); valp = AllocateValue(g, &iv, TYPE_BIGINT);
} // endif has } // endif has
i--; // Unstack following character i--; // Unstack following character
...@@ -501,27 +532,48 @@ PVAL ParseNumeric(PGLOBAL g, int& i, STRG& src) ...@@ -501,27 +532,48 @@ PVAL ParseNumeric(PGLOBAL g, int& i, STRG& src)
/***********************************************************************/ /***********************************************************************/
/* Serialize a JSON tree: */ /* Serialize a JSON tree: */
/***********************************************************************/ /***********************************************************************/
PSZ Serialize(PGLOBAL g, PJSON jsp, FILE *fs, int pretty) PSZ Serialize(PGLOBAL g, PJSON jsp, char *fn, int pretty)
{ {
PSZ str = NULL;
bool b = false, err = true; bool b = false, err = true;
JOUT *jp; JOUT *jp;
FILE *fs = NULL;
g->Message[0] = 0; g->Message[0] = 0;
// Save stack and allocation environment and prepare error return
if (g->jump_level == MAX_JUMP) {
strcpy(g->Message, MSG(TOO_MANY_JUMPS));
return NULL;
} // endif jump_level
if (setjmp(g->jumper[++g->jump_level])) {
str = NULL;
goto fin;
} // endif jmp
if (!jsp) { if (!jsp) {
strcpy(g->Message, "Null json tree"); strcpy(g->Message, "Null json tree");
return NULL; goto fin;
} else if (!fs) { } else if (!fn) {
// Serialize to a string // Serialize to a string
jp = new(g) JOUTSTR(g); jp = new(g) JOUTSTR(g);
b = pretty == 1; b = pretty == 1;
} else if (pretty == 2) { } else {
if (!(fs = fopen(fn, "wb"))) {
sprintf(g->Message, MSG(OPEN_MODE_ERROR),
"w", (int)errno, fn);
strcat(strcat(g->Message, ": "), strerror(errno));
goto fin;;
} else if (pretty >= 2) {
// Serialize to a pretty file // Serialize to a pretty file
jp = new(g) JOUTPRT(g, fs); jp = new(g)JOUTPRT(g, fs);
} else { } else {
// Serialize to a flat file // Serialize to a flat file
jp = new(g) JOUTFILE(g, fs); b = true;
b = pretty == 1; jp = new(g)JOUTFILE(g, fs, pretty);
} // endif's
} // endif's } // endif's
switch (jsp->GetType()) { switch (jsp->GetType()) {
...@@ -529,7 +581,7 @@ PSZ Serialize(PGLOBAL g, PJSON jsp, FILE *fs, int pretty) ...@@ -529,7 +581,7 @@ PSZ Serialize(PGLOBAL g, PJSON jsp, FILE *fs, int pretty)
err = SerializeArray(jp, (PJAR)jsp, b); err = SerializeArray(jp, (PJAR)jsp, b);
break; break;
case TYPE_JOB: case TYPE_JOB:
err = (b && jp->WriteChr('\t')); err = ((b && jp->Prty()) && jp->WriteChr('\t'));
err |= SerializeObject(jp, (PJOB)jsp); err |= SerializeObject(jp, (PJOB)jsp);
break; break;
case TYPE_JVAL: case TYPE_JVAL:
...@@ -540,22 +592,22 @@ PSZ Serialize(PGLOBAL g, PJSON jsp, FILE *fs, int pretty) ...@@ -540,22 +592,22 @@ PSZ Serialize(PGLOBAL g, PJSON jsp, FILE *fs, int pretty)
} // endswitch Type } // endswitch Type
if (fs) { if (fs) {
fputc('\n', fs); fputs(EL, fs);
fclose(fs); fclose(fs);
return (err) ? g->Message : NULL; str = (err) ? NULL : "Ok";
} else if (!err) { } else if (!err) {
PSZ str = ((JOUTSTR*)jp)->Strp; str = ((JOUTSTR*)jp)->Strp;
jp->WriteChr('\0'); jp->WriteChr('\0');
PlugSubAlloc(g, NULL, ((JOUTSTR*)jp)->N); PlugSubAlloc(g, NULL, ((JOUTSTR*)jp)->N);
return str;
} else { } else {
if (!g->Message[0]) if (!g->Message[0])
strcpy(g->Message, "Error in Serialize"); strcpy(g->Message, "Error in Serialize");
return NULL;
} // endif's } // endif's
fin:
g->jump_level--;
return str;
} // end of Serialize } // end of Serialize
/***********************************************************************/ /***********************************************************************/
...@@ -565,29 +617,40 @@ bool SerializeArray(JOUT *js, PJAR jarp, bool b) ...@@ -565,29 +617,40 @@ bool SerializeArray(JOUT *js, PJAR jarp, bool b)
{ {
bool first = true; bool first = true;
if (b) {
if (js->Prty()) {
if (js->WriteChr('[')) if (js->WriteChr('['))
return true; return true;
else if (b && (js->WriteStr(EL) || js->WriteChr('\t'))) else if (js->Prty() == 1 && (js->WriteStr(EL) || js->WriteChr('\t')))
return true;
} // endif Prty
} else if (js->WriteChr('['))
return true; return true;
for (int i = 0; i < jarp->size(); i++) { for (int i = 0; i < jarp->size(); i++) {
if (first) if (first)
first = false; first = false;
else if (js->WriteChr(',')) else if ((!b || js->Prty()) && js->WriteChr(','))
return true;
else if (b) {
if (js->Prty() < 2 && js->WriteStr(EL))
return true; return true;
else if (b && (js->WriteStr(EL) || js->WriteChr('\t'))) else if (js->Prty() == 1 && js->WriteChr('\t'))
return true; return true;
} // endif b
if (SerializeValue(js, jarp->GetValue(i))) if (SerializeValue(js, jarp->GetValue(i)))
return true; return true;
} // endfor i } // endfor i
if (b && js->WriteStr(EL)) if (b && js->Prty() == 1 && js->WriteStr(EL))
return true; return true;
return js->WriteChr(']'); return ((!b || js->Prty()) && js->WriteChr(']'));
} // end of SerializeArray } // end of SerializeArray
/***********************************************************************/ /***********************************************************************/
...@@ -647,8 +710,8 @@ bool SerializeValue(JOUT *js, PJVAL jvp) ...@@ -647,8 +710,8 @@ bool SerializeValue(JOUT *js, PJVAL jvp)
} // endswitch Type } // endswitch Type
strcpy(js->g->Message, "Unrecognized value"); strcpy(js->g->Message, "Unrecognized value");
return true; return true;
} // end of SerializeValue } // end of SerializeValue
/* -------------------------- Class JOUTSTR -------------------------- */ /* -------------------------- Class JOUTSTR -------------------------- */
...@@ -866,6 +929,20 @@ PJPR JOBJECT::AddPair(PGLOBAL g, PSZ key) ...@@ -866,6 +929,20 @@ PJPR JOBJECT::AddPair(PGLOBAL g, PSZ key)
return jpp; return jpp;
} // end of AddPair } // end of AddPair
/***********************************************************************/
/* Return all keys as an array. */
/***********************************************************************/
PJAR JOBJECT::GetKeyList(PGLOBAL g)
{
PJAR jarp = new(g) JARRAY();
for (PJPR jpp = First; jpp; jpp = jpp->Next)
jarp->AddValue(g, new(g) JVALUE(g, jpp->GetKey()));
jarp->InitArray(g);
return jarp;
} // end of GetKeyList
/***********************************************************************/ /***********************************************************************/
/* Get the value corresponding to the given key. */ /* Get the value corresponding to the given key. */
/***********************************************************************/ /***********************************************************************/
...@@ -903,6 +980,24 @@ PSZ JOBJECT::GetText(PGLOBAL g, PSZ text) ...@@ -903,6 +980,24 @@ PSZ JOBJECT::GetText(PGLOBAL g, PSZ text)
return text + n; return text + n;
} // end of GetValue; } // end of GetValue;
/***********************************************************************/
/* Merge two objects. */
/***********************************************************************/
bool JOBJECT::Merge(PGLOBAL g, PJSON jsp)
{
if (jsp->GetType() != TYPE_JOB) {
strcpy(g->Message, "Second argument is not an object");
return true;
} // endif Type
PJOB jobp = (PJOB)jsp;
for (PJPR jpp = jobp->First; jpp; jpp = jpp->Next)
SetValue(g, jpp->GetVal(), jpp->GetKey());
return false;
} // end of Marge;
/***********************************************************************/ /***********************************************************************/
/* Set or add a value corresponding to the given key. */ /* Set or add a value corresponding to the given key. */
/***********************************************************************/ /***********************************************************************/
...@@ -923,6 +1018,23 @@ void JOBJECT::SetValue(PGLOBAL g, PJVAL jvp, PSZ key) ...@@ -923,6 +1018,23 @@ void JOBJECT::SetValue(PGLOBAL g, PJVAL jvp, PSZ key)
} // end of SetValue } // end of SetValue
/***********************************************************************/
/* Delete a value corresponding to the given key. */
/***********************************************************************/
void JOBJECT::DeleteKey(PSZ key)
{
PJPR jp, *pjp = &First;
for (jp = First; jp; jp = jp->Next)
if (!strcmp(jp->Key, key)) {
*pjp = jp->Next;
Size--;
break;
} else
pjp = &jp->Next;
} // end of DeleteKey
/***********************************************************************/ /***********************************************************************/
/* True if void or if all members are nulls. */ /* True if void or if all members are nulls. */
/***********************************************************************/ /***********************************************************************/
...@@ -943,23 +1055,25 @@ bool JOBJECT::IsNull(void) ...@@ -943,23 +1055,25 @@ bool JOBJECT::IsNull(void)
void JARRAY::InitArray(PGLOBAL g) void JARRAY::InitArray(PGLOBAL g)
{ {
int i; int i;
PJVAL jvp; PJVAL jvp, *pjvp = &First;
for (Size = 0, jvp = First; jvp; jvp = jvp->Next) for (Size = 0, jvp = First; jvp; jvp = jvp->Next)
if (!jvp->Del) if (!jvp->Del)
Size++; Size++;
if (!Size) { if (Size > Alloc) {
return;
} else if (Size > Alloc) {
// No need to realloc after deleting values // No need to realloc after deleting values
Mvals = (PJVAL*)PlugSubAlloc(g, NULL, Size * sizeof(PJVAL)); Mvals = (PJVAL*)PlugSubAlloc(g, NULL, Size * sizeof(PJVAL));
Alloc = Size; Alloc = Size;
} // endif Size } // endif Size
for (i = 0, jvp = First; jvp; jvp = jvp->Next) for (i = 0, jvp = First; jvp; jvp = jvp->Next)
if (!jvp->Del) if (!jvp->Del) {
Mvals[i++] = jvp; Mvals[i++] = jvp;
pjvp = &jvp->Next;
Last = jvp;
} else
*pjvp = jvp->Next;
} // end of InitArray } // end of InitArray
...@@ -975,31 +1089,66 @@ PJVAL JARRAY::GetValue(int i) ...@@ -975,31 +1089,66 @@ PJVAL JARRAY::GetValue(int i)
} // end of GetValue } // end of GetValue
/***********************************************************************/ /***********************************************************************/
/* Add a Value to the Arrays Value list. */ /* Add a Value to the Array Value list. */
/***********************************************************************/ /***********************************************************************/
PJVAL JARRAY::AddValue(PGLOBAL g, PJVAL jvp) PJVAL JARRAY::AddValue(PGLOBAL g, PJVAL jvp, int *x)
{ {
if (!jvp) if (!jvp)
jvp = new(g) JVALUE; jvp = new(g) JVALUE;
if (Last) if (x) {
Last->Next = jvp; int i = 0, n = *x;
else PJVAL jp, *jpp = &First;
for (jp = First; jp && i < n; i++, jp = *(jpp = &jp->Next));
(*jpp) = jvp;
if (!(jvp->Next = jp))
Last = jvp;
} else {
if (!First)
First = jvp; First = jvp;
else if (Last == First)
First->Next = Last = jvp;
else
Last->Next = jvp;
Last = jvp; Last = jvp;
} // endif x
return jvp; return jvp;
} // end of AddValue } // end of AddValue
/***********************************************************************/ /***********************************************************************/
/* Add a Value to the Arrays Value list. */ /* Merge two arrays. */
/***********************************************************************/
bool JARRAY::Merge(PGLOBAL g, PJSON jsp)
{
if (jsp->GetType() != TYPE_JAR) {
strcpy(g->Message, "Second argument is not an array");
return true;
} // endif Type
PJAR arp = (PJAR)jsp;
for (int i = 0; i < jsp->size(); i++)
AddValue(g, arp->GetValue(i));
InitArray(g);
return false;
} // end of Merge
/***********************************************************************/
/* Set the nth Value of the Array Value list. */
/***********************************************************************/ /***********************************************************************/
bool JARRAY::SetValue(PGLOBAL g, PJVAL jvp, int n) bool JARRAY::SetValue(PGLOBAL g, PJVAL jvp, int n)
{ {
int i = 0; int i = 0;
PJVAL jp, *jpp = &First; PJVAL jp, *jpp = &First;
for (i = 0, jp = First; i < n; i++, jp = *(jpp = &jp->Next)) for (jp = First; i < n; i++, jp = *(jpp = &jp->Next))
if (!jp) if (!jp)
*jpp = jp = new(g) JVALUE; *jpp = jp = new(g) JVALUE;
...@@ -1048,6 +1197,17 @@ JVALUE::JVALUE(PGLOBAL g, PVAL valp) : JSON() ...@@ -1048,6 +1197,17 @@ JVALUE::JVALUE(PGLOBAL g, PVAL valp) : JSON()
Del = false; Del = false;
} // end of JVALUE constructor } // end of JVALUE constructor
/***********************************************************************/
/* Constructor for a given string. */
/***********************************************************************/
JVALUE::JVALUE(PGLOBAL g, PSZ strp) : JSON()
{
Jsp = NULL;
Value = AllocateValue(g, strp, TYPE_STRING);
Next = NULL;
Del = false;
} // end of JVALUE constructor
/***********************************************************************/ /***********************************************************************/
/* Returns the type of the Value's value. */ /* Returns the type of the Value's value. */
/***********************************************************************/ /***********************************************************************/
...@@ -1092,6 +1252,14 @@ int JVALUE::GetInteger(void) ...@@ -1092,6 +1252,14 @@ int JVALUE::GetInteger(void)
return (Value) ? Value->GetIntValue() : 0; return (Value) ? Value->GetIntValue() : 0;
} // end of GetInteger } // end of GetInteger
/***********************************************************************/
/* Return the Value's Big integer value. */
/***********************************************************************/
long long JVALUE::GetBigint(void)
{
return (Value) ? Value->GetBigintValue() : 0;
} // end of GetBigint
/***********************************************************************/ /***********************************************************************/
/* Return the Value's Double value. */ /* Return the Value's Double value. */
/***********************************************************************/ /***********************************************************************/
...@@ -1128,13 +1296,44 @@ PSZ JVALUE::GetText(PGLOBAL g, PSZ text) ...@@ -1128,13 +1296,44 @@ PSZ JVALUE::GetText(PGLOBAL g, PSZ text)
return text; return text;
} // end of GetText } // end of GetText
void JVALUE::SetValue(PJSON jsp)
{
if (jsp && jsp->GetType() == TYPE_JVAL) {
Jsp = jsp->GetJsp();
Value = jsp->GetValue();
} else {
Jsp = jsp;
Value = NULL;
} // endif Type
} // end of SetValue;
/***********************************************************************/ /***********************************************************************/
/* Set the Value's value as the given integer. */ /* Set the Value's value as the given integer. */
/***********************************************************************/ /***********************************************************************/
void JVALUE::SetInteger(PGLOBAL g, int n) void JVALUE::SetInteger(PGLOBAL g, int n)
{ {
Value = AllocateValue(g, &n, TYPE_INT); Value = AllocateValue(g, &n, TYPE_INT);
} // end of AddInteger Jsp = NULL;
} // end of SetInteger
/***********************************************************************/
/* Set the Value's Boolean value as a tiny integer. */
/***********************************************************************/
void JVALUE::SetTiny(PGLOBAL g, char n)
{
Value = AllocateValue(g, &n, TYPE_TINY);
Jsp = NULL;
} // end of SetInteger
/***********************************************************************/
/* Set the Value's value as the given big integer. */
/***********************************************************************/
void JVALUE::SetBigint(PGLOBAL g, long long ll)
{
Value = AllocateValue(g, &ll, TYPE_BIGINT);
Jsp = NULL;
} // end of SetBigint
/***********************************************************************/ /***********************************************************************/
/* Set the Value's value as the given DOUBLE. */ /* Set the Value's value as the given DOUBLE. */
...@@ -1142,15 +1341,17 @@ void JVALUE::SetInteger(PGLOBAL g, int n) ...@@ -1142,15 +1341,17 @@ void JVALUE::SetInteger(PGLOBAL g, int n)
void JVALUE::SetFloat(PGLOBAL g, double f) void JVALUE::SetFloat(PGLOBAL g, double f)
{ {
Value = AllocateValue(g, &f, TYPE_DOUBLE, 6); Value = AllocateValue(g, &f, TYPE_DOUBLE, 6);
} // end of AddFloat Jsp = NULL;
} // end of SetFloat
/***********************************************************************/ /***********************************************************************/
/* Set the Value's value as the given string. */ /* Set the Value's value as the given string. */
/***********************************************************************/ /***********************************************************************/
void JVALUE::SetString(PGLOBAL g, PSZ s) void JVALUE::SetString(PGLOBAL g, PSZ s, short c)
{ {
Value = AllocateValue(g, s, TYPE_STRING); Value = AllocateValue(g, s, TYPE_STRING, c);
} // end of AddFloat Jsp = NULL;
} // end of SetString
/***********************************************************************/ /***********************************************************************/
/* True when its JSON or normal value is null. */ /* True when its JSON or normal value is null. */
......
/**************** json H Declares Source Code File (.H) ****************/ /**************** json H Declares Source Code File (.H) ****************/
/* Name: json.h Version 1.1 */ /* Name: json.h Version 1.2 */
/* */ /* */
/* (C) Copyright to the author Olivier BERTRAND 2014 - 2015 */ /* (C) Copyright to the author Olivier BERTRAND 2014 - 2015 */
/* */ /* */
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
enum JTYP {TYPE_STRG = 1, enum JTYP {TYPE_STRG = 1,
TYPE_DBL = 2, TYPE_DBL = 2,
TYPE_BOOL = 4, TYPE_BOOL = 4,
TYPE_BINT = 5,
TYPE_INTG = 7, TYPE_INTG = 7,
TYPE_JSON = 12, TYPE_JSON = 12,
TYPE_JAR, TYPE_JAR,
...@@ -40,13 +41,13 @@ typedef struct { ...@@ -40,13 +41,13 @@ typedef struct {
int len; int len;
} STRG, *PSG; } STRG, *PSG;
PJSON ParseJson(PGLOBAL g, char *s, int n, int prty, 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); PJAR ParseArray(PGLOBAL g, int& i, STRG& src, bool *pty);
PJOB ParseObject(PGLOBAL g, int& i, STRG& src); PJOB ParseObject(PGLOBAL g, int& i, STRG& src, bool *pty);
PJVAL ParseValue(PGLOBAL g, int& i, STRG& src); PJVAL ParseValue(PGLOBAL g, int& i, STRG& src, bool *pty);
char *ParseString(PGLOBAL g, int& i, STRG& src); char *ParseString(PGLOBAL g, int& i, STRG& src);
PVAL ParseNumeric(PGLOBAL g, int& i, STRG& src); PVAL ParseNumeric(PGLOBAL g, int& i, STRG& src);
PSZ Serialize(PGLOBAL g, PJSON jsp, FILE *fs, 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);
bool SerializeValue(JOUT *js, PJVAL jvp); bool SerializeValue(JOUT *js, PJVAL jvp);
...@@ -56,14 +57,16 @@ bool SerializeValue(JOUT *js, PJVAL jvp); ...@@ -56,14 +57,16 @@ bool SerializeValue(JOUT *js, PJVAL jvp);
/***********************************************************************/ /***********************************************************************/
class JOUT : public BLOCK { class JOUT : public BLOCK {
public: public:
JOUT(PGLOBAL gp) : BLOCK() {g = gp;} JOUT(PGLOBAL gp) : BLOCK() {g = gp; Pretty = 3;}
virtual bool WriteStr(const char *s) = 0; virtual bool WriteStr(const char *s) = 0;
virtual bool WriteChr(const char c) = 0; virtual bool WriteChr(const char c) = 0;
virtual bool Escape(const char *s) = 0; virtual bool Escape(const char *s) = 0;
int Prty(void) {return Pretty;}
// Member // Member
PGLOBAL g; PGLOBAL g;
int Pretty;
}; // end of class JOUT }; // end of class JOUT
/***********************************************************************/ /***********************************************************************/
...@@ -88,7 +91,7 @@ class JOUTSTR : public JOUT { ...@@ -88,7 +91,7 @@ class JOUTSTR : public JOUT {
/***********************************************************************/ /***********************************************************************/
class JOUTFILE : public JOUT { class JOUTFILE : public JOUT {
public: public:
JOUTFILE(PGLOBAL g, FILE *str) : JOUT(g) {Stream = str;} JOUTFILE(PGLOBAL g, FILE *str, int pty) : JOUT(g) {Stream = str; Pretty = pty;}
virtual bool WriteStr(const char *s); virtual bool WriteStr(const char *s);
virtual bool WriteChr(const char c); virtual bool WriteChr(const char c);
...@@ -103,7 +106,7 @@ class JOUTFILE : public JOUT { ...@@ -103,7 +106,7 @@ class JOUTFILE : public JOUT {
/***********************************************************************/ /***********************************************************************/
class JOUTPRT : public JOUTFILE { class JOUTPRT : public JOUTFILE {
public: public:
JOUTPRT(PGLOBAL g, FILE *str) : JOUTFILE(g, str) {M = 0; B = false;} JOUTPRT(PGLOBAL g, FILE *str) : JOUTFILE(g, str, 2) {M = 0; B = false;}
virtual bool WriteStr(const char *s); virtual bool WriteStr(const char *s);
virtual bool WriteChr(const char c); virtual bool WriteChr(const char c);
...@@ -118,7 +121,8 @@ class JOUTPRT : public JOUTFILE { ...@@ -118,7 +121,8 @@ class JOUTPRT : public JOUTFILE {
/***********************************************************************/ /***********************************************************************/
class JPAIR : public BLOCK { class JPAIR : public BLOCK {
friend class JOBJECT; friend class JOBJECT;
friend PJOB ParseObject(PGLOBAL, int&, STRG&); friend class JSNX;
friend PJOB ParseObject(PGLOBAL, int&, STRG&, bool*);
friend bool SerializeObject(JOUT *, PJOB); friend bool SerializeObject(JOUT *, PJOB);
public: public:
JPAIR(PSZ key) : BLOCK() {Key = key; Val = NULL; Next = NULL;} JPAIR(PSZ key) : BLOCK() {Key = key; Val = NULL; Next = NULL;}
...@@ -145,26 +149,30 @@ class JSON : public BLOCK { ...@@ -145,26 +149,30 @@ class JSON : public BLOCK {
virtual JTYP GetType(void) {return TYPE_JSON;} virtual JTYP GetType(void) {return TYPE_JSON;}
virtual JTYP GetValType(void) {X return TYPE_JSON;} virtual JTYP GetValType(void) {X return TYPE_JSON;}
virtual void InitArray(PGLOBAL g) {X} virtual void InitArray(PGLOBAL g) {X}
virtual PJVAL AddValue(PGLOBAL g, PJVAL jvp = NULL) {X return NULL;} //virtual PJVAL AddValue(PGLOBAL g, PJVAL jvp = NULL, int *x = NULL) {X return NULL;}
virtual PJPR AddPair(PGLOBAL g, PSZ key) {X return NULL;} virtual PJPR AddPair(PGLOBAL g, PSZ key) {X return NULL;}
virtual PJAR GetKeyList(PGLOBAL g) {X return NULL;}
virtual PJVAL GetValue(const char *key) {X return NULL;} virtual PJVAL GetValue(const char *key) {X return NULL;}
virtual PJOB GetObject(void) {return NULL;} virtual PJOB GetObject(void) {return NULL;}
virtual PJAR GetArray(void) {return NULL;} virtual PJAR GetArray(void) {return NULL;}
virtual PJVAL GetValue(int i) {X return NULL;} virtual PJVAL GetValue(int i) {X return NULL;}
virtual PVAL GetValue(void) {X return NULL;} virtual PVAL GetValue(void) {X return NULL;}
virtual PJSON GetJson(void) {X return NULL;} virtual PJSON GetJsp(void) { X return NULL; }
virtual PJSON GetJson(void) { X return NULL; }
virtual PJPR GetFirst(void) {X return NULL;} virtual PJPR GetFirst(void) {X return NULL;}
virtual int GetInteger(void) {X return 0;} virtual int GetInteger(void) {X return 0;}
virtual double GetFloat() {X return 0.0;} virtual double GetFloat() {X return 0.0;}
virtual PSZ GetString() {X return NULL;} virtual PSZ GetString() {X return NULL;}
virtual PSZ GetText(PGLOBAL g, PSZ text) {X return NULL;} virtual PSZ GetText(PGLOBAL g, PSZ text) {X return NULL;}
virtual bool SetValue(PGLOBAL g, PJVAL jvp, int i) {X return true;} virtual bool Merge(PGLOBAL g, PJSON jsp) { X return true; }
virtual bool SetValue(PGLOBAL g, PJVAL jvp, int i) { X return true; }
virtual void SetValue(PGLOBAL g, PJVAL jvp, PSZ key) {X} virtual void SetValue(PGLOBAL g, PJVAL jvp, PSZ key) {X}
virtual void SetValue(PVAL valp) {X} virtual void SetValue(PVAL valp) {X}
virtual void SetValue(PJSON jsp) {X} virtual void SetValue(PJSON jsp) {X}
virtual void SetString(PGLOBAL g, PSZ s) {X} virtual void SetString(PGLOBAL g, PSZ s, short c) {X}
virtual void SetInteger(PGLOBAL g, int n) {X} virtual void SetInteger(PGLOBAL g, int n) {X}
virtual void SetFloat(PGLOBAL g, double f) {X} virtual void SetFloat(PGLOBAL g, double f) {X}
virtual void DeleteKey(char *k) {X}
virtual bool DeleteValue(int i) {X return true;} virtual bool DeleteValue(int i) {X return true;}
virtual bool IsNull(void) {X return true;} virtual bool IsNull(void) {X return true;}
...@@ -176,8 +184,9 @@ class JSON : public BLOCK { ...@@ -176,8 +184,9 @@ class JSON : public BLOCK {
/* 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&); friend PJOB ParseObject(PGLOBAL, int&, STRG&, bool*);
friend bool SerializeObject(JOUT *, PJOB); friend bool SerializeObject(JOUT *, PJOB);
friend class JSNX;
public: public:
JOBJECT(void) : JSON() {First = Last = NULL;} JOBJECT(void) : JSON() {First = Last = NULL;}
...@@ -189,8 +198,11 @@ class JOBJECT : public JSON { ...@@ -189,8 +198,11 @@ class JOBJECT : public JSON {
virtual PJPR AddPair(PGLOBAL g, PSZ key); virtual PJPR AddPair(PGLOBAL g, PSZ key);
virtual PJOB GetObject(void) {return this;} virtual PJOB GetObject(void) {return this;}
virtual PJVAL GetValue(const char* key); virtual PJVAL GetValue(const char* key);
virtual PJAR GetKeyList(PGLOBAL g);
virtual PSZ GetText(PGLOBAL g, PSZ text); virtual PSZ GetText(PGLOBAL g, PSZ text);
virtual bool Merge(PGLOBAL g, PJSON jsp);
virtual void SetValue(PGLOBAL g, PJVAL jvp, PSZ key); virtual void SetValue(PGLOBAL g, PJVAL jvp, PSZ key);
virtual void DeleteKey(char *k);
virtual bool IsNull(void); virtual bool IsNull(void);
protected: protected:
...@@ -202,7 +214,7 @@ class JOBJECT : public JSON { ...@@ -202,7 +214,7 @@ class JOBJECT : public JSON {
/* Class JARRAY. */ /* Class JARRAY. */
/***********************************************************************/ /***********************************************************************/
class JARRAY : public JSON { class JARRAY : public JSON {
friend PJAR ParseArray(PGLOBAL, int&, STRG&); friend PJAR ParseArray(PGLOBAL, int&, STRG&, bool*);
public: public:
JARRAY(void) : JSON() {Alloc = 0; First = Last = NULL; Mvals = NULL;} JARRAY(void) : JSON() {Alloc = 0; First = Last = NULL; Mvals = NULL;}
...@@ -211,9 +223,10 @@ class JARRAY : public JSON { ...@@ -211,9 +223,10 @@ class JARRAY : public JSON {
virtual void Clear(void) {First = Last = NULL; Size = 0;} virtual void Clear(void) {First = Last = NULL; Size = 0;}
virtual JTYP GetType(void) {return TYPE_JAR;} virtual JTYP GetType(void) {return TYPE_JAR;}
virtual PJAR GetArray(void) {return this;} virtual PJAR GetArray(void) {return this;}
virtual PJVAL AddValue(PGLOBAL g, PJVAL jvp = NULL); PJVAL AddValue(PGLOBAL g, PJVAL jvp = NULL, int *x = NULL);
virtual void InitArray(PGLOBAL g); virtual void InitArray(PGLOBAL g);
virtual PJVAL GetValue(int i); virtual PJVAL GetValue(int i);
virtual bool Merge(PGLOBAL g, PJSON jsp);
virtual bool SetValue(PGLOBAL g, PJVAL jvp, int i); virtual bool SetValue(PGLOBAL g, PJVAL jvp, int i);
virtual bool DeleteValue(int n); virtual bool DeleteValue(int n);
virtual bool IsNull(void); virtual bool IsNull(void);
...@@ -231,7 +244,8 @@ class JARRAY : public JSON { ...@@ -231,7 +244,8 @@ class JARRAY : public JSON {
/***********************************************************************/ /***********************************************************************/
class JVALUE : public JSON { class JVALUE : public JSON {
friend class JARRAY; friend class JARRAY;
friend PJVAL ParseValue(PGLOBAL, int&, STRG&); friend class JSNX;
friend PJVAL ParseValue(PGLOBAL, int&, STRG&, bool*);
friend bool SerializeValue(JOUT *, PJVAL); friend bool SerializeValue(JOUT *, PJVAL);
public: public:
JVALUE(void) : JSON() JVALUE(void) : JSON()
...@@ -239,6 +253,7 @@ class JVALUE : public JSON { ...@@ -239,6 +253,7 @@ class JVALUE : public JSON {
JVALUE(PJSON jsp) : JSON() JVALUE(PJSON jsp) : JSON()
{Jsp = jsp; Value = NULL; Next = NULL; Del = false;} {Jsp = jsp; Value = NULL; Next = NULL; Del = false;}
JVALUE(PGLOBAL g, PVAL valp); JVALUE(PGLOBAL g, PVAL valp);
JVALUE(PGLOBAL g, PSZ strp);
using JSON::GetValue; using JSON::GetValue;
using JSON::SetValue; using JSON::SetValue;
...@@ -249,16 +264,20 @@ class JVALUE : public JSON { ...@@ -249,16 +264,20 @@ class JVALUE : public JSON {
virtual PJOB GetObject(void); virtual PJOB GetObject(void);
virtual PJAR GetArray(void); virtual PJAR GetArray(void);
virtual PVAL GetValue(void) {return Value;} virtual PVAL GetValue(void) {return Value;}
virtual PJSON GetJson(void) {return (Jsp ? Jsp : this);} virtual PJSON GetJsp(void) {return Jsp;}
virtual PJSON GetJson(void) { return (Jsp ? Jsp : this); }
virtual int GetInteger(void); virtual int GetInteger(void);
virtual long long GetBigint(void);
virtual double GetFloat(void); virtual double GetFloat(void);
virtual PSZ GetString(void); virtual PSZ GetString(void);
virtual PSZ GetText(PGLOBAL g, PSZ text); virtual PSZ GetText(PGLOBAL g, PSZ text);
virtual void SetValue(PVAL valp) {Value = valp;} virtual void SetValue(PJSON jsp);
virtual void SetValue(PJSON jsp) {Jsp = jsp;} virtual void SetValue(PVAL valp) { Value = valp; Jsp = NULL; }
virtual void SetString(PGLOBAL g, PSZ s); virtual void SetString(PGLOBAL g, PSZ s, short c = 0);
virtual void SetInteger(PGLOBAL g, int n); virtual void SetInteger(PGLOBAL g, int n);
virtual void SetBigint(PGLOBAL g, longlong ll);
virtual void SetFloat(PGLOBAL g, double f); virtual void SetFloat(PGLOBAL g, double f);
virtual void SetTiny(PGLOBAL g, char f);
virtual bool IsNull(void); virtual bool IsNull(void);
protected: protected:
......
This source diff could not be displayed because it is too large. You can view the blob instead.
/******************** tabjson H Declares Source Code File (.H) *******************/
/* Name: jsonudf.h Version 1.2 */
/* */
/* (C) Copyright to the author Olivier BERTRAND 2015 */
/* */
/* This file contains the JSON UDF function and class declares. */
/*********************************************************************************/
#include "global.h"
#include "plgdbsem.h"
#include "block.h"
#include "osutil.h"
#include "maputil.h"
#include "json.h"
#define UDF_EXEC_ARGS \
UDF_INIT*, UDF_ARGS*, char*, unsigned long*, char*, char*
/*********************************************************************************/
/* The JSON tree node. Can be an Object or an Array. */
/*********************************************************************************/
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
} JNODE, *PJNODE;
typedef class JSNX *PJSNX;
typedef class JOUTPATH *PJTP;
typedef class JOUTALL *PJTA;
extern "C" {
DllExport my_bool jsonvalue_init(UDF_INIT*, UDF_ARGS*, char*);
DllExport char *jsonvalue(UDF_EXEC_ARGS);
DllExport void jsonvalue_deinit(UDF_INIT*);
DllExport my_bool json_array_init(UDF_INIT*, UDF_ARGS*, char*);
DllExport char *json_array(UDF_EXEC_ARGS);
DllExport void json_array_deinit(UDF_INIT*);
DllExport my_bool json_array_add_values_init(UDF_INIT*, UDF_ARGS*, char*);
DllExport char *json_array_add_values(UDF_EXEC_ARGS);
DllExport void json_array_add_values_deinit(UDF_INIT*);
DllExport my_bool json_array_add_init(UDF_INIT*, UDF_ARGS*, char*);
DllExport char *json_array_add(UDF_EXEC_ARGS);
DllExport void json_array_add_deinit(UDF_INIT*);
DllExport my_bool json_array_delete_init(UDF_INIT*, UDF_ARGS*, char*);
DllExport char *json_array_delete(UDF_EXEC_ARGS);
DllExport void json_array_delete_deinit(UDF_INIT*);
DllExport my_bool json_object_init(UDF_INIT*, UDF_ARGS*, char*);
DllExport char *json_object(UDF_EXEC_ARGS);
DllExport void json_object_deinit(UDF_INIT*);
DllExport my_bool json_object_nonull_init(UDF_INIT*, UDF_ARGS*, char*);
DllExport char *json_object_nonull(UDF_EXEC_ARGS);
DllExport void json_object_nonull_deinit(UDF_INIT*);
DllExport my_bool json_object_key_init(UDF_INIT*, UDF_ARGS*, char*);
DllExport char *json_object_key(UDF_EXEC_ARGS);
DllExport void json_object_key_deinit(UDF_INIT*);
DllExport my_bool json_object_add_init(UDF_INIT*, UDF_ARGS*, char*);
DllExport char *json_object_add(UDF_EXEC_ARGS);
DllExport void json_object_add_deinit(UDF_INIT*);
DllExport my_bool json_object_delete_init(UDF_INIT*, UDF_ARGS*, char*);
DllExport char *json_object_delete(UDF_EXEC_ARGS);
DllExport void json_object_delete_deinit(UDF_INIT*);
DllExport my_bool json_object_list_init(UDF_INIT*, UDF_ARGS*, char*);
DllExport char *json_object_list(UDF_EXEC_ARGS);
DllExport void json_object_list_deinit(UDF_INIT*);
DllExport my_bool json_array_grp_init(UDF_INIT*, UDF_ARGS*, char*);
DllExport void json_array_grp_add(UDF_INIT *, UDF_ARGS *, char *, char *);
DllExport char *json_array_grp(UDF_EXEC_ARGS);
DllExport void json_array_grp_clear(UDF_INIT *, char *, char *);
DllExport void json_array_grp_deinit(UDF_INIT*);
DllExport my_bool json_object_grp_init(UDF_INIT*, UDF_ARGS*, char*);
DllExport void json_object_grp_add(UDF_INIT *, UDF_ARGS *, char *, char *);
DllExport char *json_object_grp(UDF_EXEC_ARGS);
DllExport void json_object_grp_clear(UDF_INIT *, char *, char *);
DllExport void json_object_grp_deinit(UDF_INIT*);
DllExport my_bool json_item_merge_init(UDF_INIT*, UDF_ARGS*, char*);
DllExport char *json_item_merge(UDF_EXEC_ARGS);
DllExport void json_item_merge_deinit(UDF_INIT*);
DllExport my_bool json_get_item_init(UDF_INIT*, UDF_ARGS*, char*);
DllExport char *json_get_item(UDF_EXEC_ARGS);
DllExport void json_get_item_deinit(UDF_INIT*);
DllExport my_bool jsonget_string_init(UDF_INIT*, UDF_ARGS*, char*);
DllExport char *jsonget_string(UDF_EXEC_ARGS);
DllExport void jsonget_string_deinit(UDF_INIT*);
DllExport my_bool jsonget_int_init(UDF_INIT*, UDF_ARGS*, char*);
DllExport long long jsonget_int(UDF_INIT*, UDF_ARGS*, char*, char*);
DllExport void jsonget_int_deinit(UDF_INIT*);
DllExport my_bool jsonget_real_init(UDF_INIT*, UDF_ARGS*, char*);
DllExport double jsonget_real(UDF_INIT*, UDF_ARGS*, char*, char*);
DllExport void jsonget_real_deinit(UDF_INIT*);
DllExport my_bool jsoncontains_init(UDF_INIT*, UDF_ARGS*, char*);
DllExport long long jsoncontains(UDF_EXEC_ARGS);
DllExport void jsoncontains_deinit(UDF_INIT*);
DllExport my_bool jsonlocate_init(UDF_INIT*, UDF_ARGS*, char*);
DllExport char *jsonlocate(UDF_EXEC_ARGS);
DllExport void jsonlocate_deinit(UDF_INIT*);
DllExport my_bool json_locate_all_init(UDF_INIT*, UDF_ARGS*, char*);
DllExport char *json_locate_all(UDF_EXEC_ARGS);
DllExport void json_locate_all_deinit(UDF_INIT*);
DllExport my_bool jsoncontains_path_init(UDF_INIT*, UDF_ARGS*, char*);
DllExport long long jsoncontains_path(UDF_EXEC_ARGS);
DllExport void jsoncontains_path_deinit(UDF_INIT*);
DllExport my_bool json_set_item_init(UDF_INIT*, UDF_ARGS*, char*);
DllExport char *json_set_item(UDF_EXEC_ARGS);
DllExport void json_set_item_deinit(UDF_INIT*);
DllExport my_bool json_insert_item_init(UDF_INIT*, UDF_ARGS*, char*);
DllExport char *json_insert_item(UDF_EXEC_ARGS);
DllExport void json_insert_item_deinit(UDF_INIT*);
DllExport my_bool json_update_item_init(UDF_INIT*, UDF_ARGS*, char*);
DllExport char *json_update_item(UDF_EXEC_ARGS);
DllExport void json_update_item_deinit(UDF_INIT*);
DllExport my_bool json_file_init(UDF_INIT*, UDF_ARGS*, char*);
DllExport char *json_file(UDF_EXEC_ARGS);
DllExport void json_file_deinit(UDF_INIT*);
DllExport my_bool jfile_make_init(UDF_INIT*, UDF_ARGS*, char*);
DllExport char *jfile_make(UDF_EXEC_ARGS);
DllExport void jfile_make_deinit(UDF_INIT*);
DllExport my_bool jbin_array_init(UDF_INIT*, UDF_ARGS*, char*);
DllExport char *jbin_array(UDF_EXEC_ARGS);
DllExport void jbin_array_deinit(UDF_INIT*);
DllExport my_bool jbin_array_add_values_init(UDF_INIT*, UDF_ARGS*, char*);
DllExport char *jbin_array_add_values(UDF_EXEC_ARGS);
DllExport void jbin_array_add_values_deinit(UDF_INIT*);
DllExport my_bool jbin_array_add_init(UDF_INIT*, UDF_ARGS*, char*);
DllExport char *jbin_array_add(UDF_EXEC_ARGS);
DllExport void jbin_array_add_deinit(UDF_INIT*);
DllExport my_bool jbin_array_delete_init(UDF_INIT*, UDF_ARGS*, char*);
DllExport char *jbin_array_delete(UDF_EXEC_ARGS);
DllExport void jbin_array_delete_deinit(UDF_INIT*);
DllExport my_bool jbin_object_init(UDF_INIT*, UDF_ARGS*, char*);
DllExport char *jbin_object(UDF_EXEC_ARGS);
DllExport void jbin_object_deinit(UDF_INIT*);
DllExport my_bool jbin_object_nonull_init(UDF_INIT*, UDF_ARGS*, char*);
DllExport char *jbin_object_nonull(UDF_EXEC_ARGS);
DllExport void jbin_object_nonull_deinit(UDF_INIT*);
DllExport my_bool jbin_object_key_init(UDF_INIT*, UDF_ARGS*, char*);
DllExport char *jbin_object_key(UDF_EXEC_ARGS);
DllExport void jbin_object_key_deinit(UDF_INIT*);
DllExport my_bool jbin_object_add_init(UDF_INIT*, UDF_ARGS*, char*);
DllExport char *jbin_object_add(UDF_EXEC_ARGS);
DllExport void jbin_object_add_deinit(UDF_INIT*);
DllExport my_bool jbin_object_delete_init(UDF_INIT*, UDF_ARGS*, char*);
DllExport char *jbin_object_delete(UDF_EXEC_ARGS);
DllExport void jbin_object_delete_deinit(UDF_INIT*);
DllExport my_bool jbin_object_list_init(UDF_INIT*, UDF_ARGS*, char*);
DllExport char *jbin_object_list(UDF_EXEC_ARGS);
DllExport void jbin_object_list_deinit(UDF_INIT*);
DllExport my_bool jbin_get_item_init(UDF_INIT*, UDF_ARGS*, char*);
DllExport char *jbin_get_item(UDF_EXEC_ARGS);
DllExport void jbin_get_item_deinit(UDF_INIT*);
DllExport my_bool jbin_item_merge_init(UDF_INIT*, UDF_ARGS*, char*);
DllExport char *jbin_item_merge(UDF_EXEC_ARGS);
DllExport void jbin_item_merge_deinit(UDF_INIT*);
DllExport my_bool jbin_set_item_init(UDF_INIT*, UDF_ARGS*, char*);
DllExport char *jbin_set_item(UDF_EXEC_ARGS);
DllExport void jbin_set_item_deinit(UDF_INIT*);
DllExport my_bool jbin_insert_item_init(UDF_INIT*, UDF_ARGS*, char*);
DllExport char *jbin_insert_item(UDF_EXEC_ARGS);
DllExport void jbin_insert_item_deinit(UDF_INIT*);
DllExport my_bool jbin_update_item_init(UDF_INIT*, UDF_ARGS*, char*);
DllExport char *jbin_update_item(UDF_EXEC_ARGS);
DllExport void jbin_update_item_deinit(UDF_INIT*);
DllExport my_bool jbin_file_init(UDF_INIT*, UDF_ARGS*, char*);
DllExport char *jbin_file(UDF_EXEC_ARGS);
DllExport void jbin_file_deinit(UDF_INIT*);
DllExport my_bool json_serialize_init(UDF_INIT*, UDF_ARGS*, char*);
DllExport char *json_serialize(UDF_EXEC_ARGS);
DllExport void json_serialize_deinit(UDF_INIT*);
} // extern "C"
/*********************************************************************************/
/* Structure JPN. Used to make the locate path. */
/*********************************************************************************/
typedef struct _jpn {
enum JTYP Type;
PSZ Key;
int N;
} JPN, *PJPN;
/*********************************************************************************/
/* Class JSNX: JSON access method. */
/*********************************************************************************/
class JSNX : public BLOCK {
public:
// Constructors
JSNX(PGLOBAL g, PJSON row, int type, int len = 64, int prec = 0, my_bool wr = false);
// Implementation
int GetPrecision(void) {return Prec;}
PVAL GetValue(void) {return Value;}
// Methods
my_bool SetJpath(PGLOBAL g, char *path, my_bool jb = false);
my_bool ParseJpath(PGLOBAL g);
void ReadValue(PGLOBAL g);
PJVAL GetRowValue(PGLOBAL g, PJSON row, int i, my_bool b = true);
PJVAL GetJson(PGLOBAL g);
my_bool CheckPath(PGLOBAL g);
my_bool WriteValue(PGLOBAL g, PJVAL jvalp);
char *Locate(PGLOBAL g, PJSON jsp, PJVAL jvp, int k = 1);
char *LocateAll(PGLOBAL g, PJSON jsp, PJVAL jvp, int mx = 10);
protected:
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 CalculateArray(PGLOBAL g, PJAR arp, int n);
PVAL MakeJson(PGLOBAL g, PJSON jsp);
void SetJsonValue(PGLOBAL g, PVAL vp, PJVAL val, int n);
PJSON GetRow(PGLOBAL g);
my_bool LocateArray(PJAR jarp);
my_bool LocateObject(PJOB jobp);
my_bool LocateValue(PJVAL jvp);
my_bool LocateArrayAll(PJAR jarp);
my_bool LocateObjectAll(PJOB jobp);
my_bool LocateValueAll(PJVAL jvp);
my_bool CompareTree(PJSON jp1, PJSON jp2);
my_bool AddPath(void);
// Default constructor not to be used
JSNX(void) {}
// Members
PJSON Row;
PJVAL Jvalp;
PJPN Jpnp;
JOUTSTR *Jp;
JNODE *Nodes; // The intermediate objects
PVAL Value;
PVAL MulVal; // To value used by multiple column
char *Jpath; // The json path
int Buf_Type;
int Long;
int Prec;
int Nod; // The number of intermediate objects
int Xnod; // Index of multiple values
int K; // Kth item to locate
int I; // Index of JPN
int Imax; // Max number of JPN's
int B; // Index base
my_bool Xpd; // True for expandable column
my_bool Parsed; // True when parsed
my_bool Found; // Item found by locate
my_bool Wr; // Write mode
my_bool Jb; // Must return json item
}; // end of class JSNX
...@@ -89,6 +89,7 @@ ...@@ -89,6 +89,7 @@
#if defined(XML_SUPPORT) #if defined(XML_SUPPORT)
#include "tabxml.h" #include "tabxml.h"
#endif // XML_SUPPORT #endif // XML_SUPPORT
#include "mycat.h"
/***********************************************************************/ /***********************************************************************/
/* Extern static variables. */ /* Extern static variables. */
...@@ -299,13 +300,13 @@ int GetIndexType(TABTYPE type) ...@@ -299,13 +300,13 @@ int GetIndexType(TABTYPE type)
xtyp= 1; xtyp= 1;
break; break;
case TAB_MYSQL: case TAB_MYSQL:
// case TAB_ODBC: case TAB_ODBC:
xtyp= 2; xtyp= 2;
break; break;
case TAB_VIR: case TAB_VIR:
xtyp= 3; xtyp= 3;
break; break;
case TAB_ODBC: // case TAB_ODBC:
default: default:
xtyp= 0; xtyp= 0;
break; break;
......
...@@ -74,6 +74,7 @@ struct ha_table_option_struct { ...@@ -74,6 +74,7 @@ struct ha_table_option_struct {
typedef class ha_connect *PHC; typedef class ha_connect *PHC;
char *GetPluginDir(void);
TABTYPE GetTypeID(const char *type); TABTYPE GetTypeID(const char *type);
bool IsFileType(TABTYPE type); bool IsFileType(TABTYPE type);
bool IsExactType(TABTYPE type); bool IsExactType(TABTYPE type);
......
...@@ -30,3 +30,30 @@ SELECT id, TIME(tim) FROM t1 LIMIT 1; ...@@ -30,3 +30,30 @@ SELECT id, TIME(tim) FROM t1 LIMIT 1;
id TIME(tim) id TIME(tim)
1 09:35:08.000000 1 09:35:08.000000
DROP TABLE t1; DROP TABLE t1;
#
# Testing use of dates in where clause (MDEV-8926)
#
CREATE TABLE t1 (col1 DATE) ENGINE=CONNECT TABLE_TYPE=CSV;
Warnings:
Warning 1105 No file name. Table will use t1.csv
INSERT INTO t1 VALUES('2015-01-01'),('2015-02-01'),('2015-03-01'),('2015-04-01');
SELECT * FROM t1 WHERE col1 = '2015-02-01';
col1
2015-02-01
SELECT * FROM t1 WHERE col1 > '2015-02-01';
col1
2015-03-01
2015-04-01
SELECT * FROM t1 WHERE col1 >= '2015-02-01';
col1
2015-02-01
2015-03-01
2015-04-01
SELECT * FROM t1 WHERE col1 < '2015-02-01';
col1
2015-01-01
SELECT * FROM t1 WHERE col1 <= '2015-02-01';
col1
2015-01-01
2015-02-01
DROP TABLE t1;
set sql_mode="";
# #
# Testing FILE privilege # Testing FILE privilege
# #
...@@ -46,7 +47,7 @@ ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) ...@@ -46,7 +47,7 @@ ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
SELECT user(); SELECT user();
user() user()
root@localhost root@localhost
CREATE VIEW v1 AS SELECT * FROM t1; CREATE SQL SECURITY INVOKER VIEW v1 AS SELECT * FROM t1;
SELECT user(); SELECT user();
user() user()
user@localhost user@localhost
...@@ -70,6 +71,7 @@ DROP USER user@localhost; ...@@ -70,6 +71,7 @@ DROP USER user@localhost;
# #
# Beginning of grant.inc # Beginning of grant.inc
# #
CREATE USER user@localhost;
GRANT ALL PRIVILEGES ON *.* TO user@localhost; GRANT ALL PRIVILEGES ON *.* TO user@localhost;
REVOKE FILE ON *.* FROM user@localhost; REVOKE FILE ON *.* FROM user@localhost;
SELECT user(); SELECT user();
...@@ -130,7 +132,7 @@ ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) ...@@ -130,7 +132,7 @@ ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
SELECT user(); SELECT user();
user() user()
root@localhost root@localhost
CREATE VIEW v1 AS SELECT * FROM t1; CREATE SQL SECURITY INVOKER VIEW v1 AS SELECT * FROM t1;
SELECT user(); SELECT user();
user() user()
user@localhost user@localhost
...@@ -164,6 +166,7 @@ DROP USER user@localhost; ...@@ -164,6 +166,7 @@ DROP USER user@localhost;
# #
# Beginning of grant.inc # Beginning of grant.inc
# #
CREATE USER user@localhost;
GRANT ALL PRIVILEGES ON *.* TO user@localhost; GRANT ALL PRIVILEGES ON *.* TO user@localhost;
REVOKE FILE ON *.* FROM user@localhost; REVOKE FILE ON *.* FROM user@localhost;
SELECT user(); SELECT user();
...@@ -224,7 +227,7 @@ ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) ...@@ -224,7 +227,7 @@ ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
SELECT user(); SELECT user();
user() user()
root@localhost root@localhost
CREATE VIEW v1 AS SELECT * FROM t1; CREATE SQL SECURITY INVOKER VIEW v1 AS SELECT * FROM t1;
SELECT user(); SELECT user();
user() user()
user@localhost user@localhost
...@@ -258,6 +261,7 @@ DROP USER user@localhost; ...@@ -258,6 +261,7 @@ DROP USER user@localhost;
# #
# Beginning of grant.inc # Beginning of grant.inc
# #
CREATE USER user@localhost;
GRANT ALL PRIVILEGES ON *.* TO user@localhost; GRANT ALL PRIVILEGES ON *.* TO user@localhost;
REVOKE FILE ON *.* FROM user@localhost; REVOKE FILE ON *.* FROM user@localhost;
SELECT user(); SELECT user();
...@@ -318,7 +322,7 @@ ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) ...@@ -318,7 +322,7 @@ ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
SELECT user(); SELECT user();
user() user()
root@localhost root@localhost
CREATE VIEW v1 AS SELECT * FROM t1; CREATE SQL SECURITY INVOKER VIEW v1 AS SELECT * FROM t1;
SELECT user(); SELECT user();
user() user()
user@localhost user@localhost
...@@ -352,6 +356,7 @@ DROP USER user@localhost; ...@@ -352,6 +356,7 @@ DROP USER user@localhost;
# #
# Beginning of grant.inc # Beginning of grant.inc
# #
CREATE USER user@localhost;
GRANT ALL PRIVILEGES ON *.* TO user@localhost; GRANT ALL PRIVILEGES ON *.* TO user@localhost;
REVOKE FILE ON *.* FROM user@localhost; REVOKE FILE ON *.* FROM user@localhost;
SELECT user(); SELECT user();
...@@ -412,7 +417,7 @@ ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) ...@@ -412,7 +417,7 @@ ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
SELECT user(); SELECT user();
user() user()
root@localhost root@localhost
CREATE VIEW v1 AS SELECT * FROM t1; CREATE SQL SECURITY INVOKER VIEW v1 AS SELECT * FROM t1;
SELECT user(); SELECT user();
user() user()
user@localhost user@localhost
...@@ -446,6 +451,7 @@ DROP USER user@localhost; ...@@ -446,6 +451,7 @@ DROP USER user@localhost;
# #
# Beginning of grant.inc # Beginning of grant.inc
# #
CREATE USER user@localhost;
GRANT ALL PRIVILEGES ON *.* TO user@localhost; GRANT ALL PRIVILEGES ON *.* TO user@localhost;
REVOKE FILE ON *.* FROM user@localhost; REVOKE FILE ON *.* FROM user@localhost;
SELECT user(); SELECT user();
...@@ -506,7 +512,7 @@ ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) ...@@ -506,7 +512,7 @@ ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
SELECT user(); SELECT user();
user() user()
root@localhost root@localhost
CREATE VIEW v1 AS SELECT * FROM t1; CREATE SQL SECURITY INVOKER VIEW v1 AS SELECT * FROM t1;
SELECT user(); SELECT user();
user() user()
user@localhost user@localhost
...@@ -537,3 +543,4 @@ DROP USER user@localhost; ...@@ -537,3 +543,4 @@ DROP USER user@localhost;
# #
# End of grant.inc # End of grant.inc
# #
set sql_mode=default;
# #
# Checking FILE privileges # Checking FILE privileges
# #
set sql_mode="";
GRANT ALL PRIVILEGES ON *.* TO user@localhost; GRANT ALL PRIVILEGES ON *.* TO user@localhost;
REVOKE FILE ON *.* FROM user@localhost; REVOKE FILE ON *.* FROM user@localhost;
set sql_mode=default;
SELECT user(); SELECT user();
user() user()
user@localhost user@localhost
...@@ -59,7 +61,7 @@ ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) ...@@ -59,7 +61,7 @@ ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
SELECT user(); SELECT user();
user() user()
root@localhost root@localhost
CREATE VIEW v1 AS SELECT * FROM t1; CREATE SQL SECURITY INVOKER VIEW v1 AS SELECT * FROM t1;
SELECT user(); SELECT user();
user() user()
user@localhost user@localhost
......
...@@ -171,6 +171,40 @@ line ...@@ -171,6 +171,40 @@ line
] ]
DROP TABLE t1; DROP TABLE t1;
# #
# Testing a pretty=0 file
#
CREATE TABLE t1
(
ISBN CHAR(15) NOT NULL,
Language CHAR(2) FIELD_FORMAT='LANG',
Subject CHAR(32) FIELD_FORMAT='SUBJECT',
AuthorFN CHAR(128) FIELD_FORMAT='AUTHOR:[X]:FIRSTNAME',
AuthorLN CHAR(128) FIELD_FORMAT='AUTHOR:[X]:LASTNAME',
Title CHAR(32) FIELD_FORMAT='TITLE',
Translation CHAR(32) FIELD_FORMAT='TRANSLATED:PREFIX',
TranslatorFN CHAR(80) FIELD_FORMAT='TRANSLATED:TRANSLATOR:FIRSTNAME',
TranslatorLN CHAR(80) FIELD_FORMAT='TRANSLATED:TRANSLATOR:LASTNAME',
Publisher CHAR(20) FIELD_FORMAT='PUBLISHER:NAME',
Location CHAR(16) FIELD_FORMAT='PUBLISHER:PLACE',
Year int(4) FIELD_FORMAT='DATEPUB',
INDEX IX(ISBN)
)
ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='bib0.json' LRECL=320 OPTION_LIST='Pretty=0';
SHOW INDEX FROM t1;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
t1 1 IX 1 ISBN A NULL NULL NULL XINDEX
SELECT * FROM t1;
ISBN Language Subject AuthorFN AuthorLN Title Translation TranslatorFN TranslatorLN Publisher Location Year
9782212090819 fr applications Jean-Michel Bernadac Construire une application XML NULL NULL NULL Eyrolles Paris 1999
9782212090819 fr applications Franois Knab Construire une application XML NULL NULL NULL Eyrolles Paris 1999
9782840825685 fr applications William J. Pardi XML en Action adapt de l'anglais par James Guerin Microsoft Press Paris 2001
DESCRIBE SELECT * FROM t1 WHERE ISBN = '9782212090819';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref IX IX 15 const 1 Using where
UPDATE t1 SET AuthorFN = 'Philippe' WHERE ISBN = '9782212090819';
ERROR HY000: Got error 122 'Cannot write expanded column when Pretty is not 2' from CONNECT
DROP TABLE t1;
#
# A file with 2 arrays # A file with 2 arrays
# #
CREATE TABLE t1 ( CREATE TABLE t1 (
......
CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=VIR BLOCK_SIZE=5;
# #
# Test UDF's with constant arguments # Test UDF's with constant arguments
# #
SELECT JsonValue(56, 3.1416, 'foo', NULL);
ERROR HY000: Can't initialize function 'jsonvalue'; Cannot accept more than 1 argument
SELECT JsonValue(3.1416);
JsonValue(3.1416)
3.141600
SELECT JsonValue(-80);
JsonValue(-80)
-80
SELECT JsonValue('foo');
JsonValue('foo')
"foo"
SELECT JsonValue(9223372036854775807);
JsonValue(9223372036854775807)
9223372036854775807
SELECT JsonValue(NULL);
JsonValue(NULL)
null
SELECT JsonValue(TRUE);
JsonValue(TRUE)
true
SELECT JsonValue(FALSE);
JsonValue(FALSE)
false
SELECT JsonValue();
JsonValue()
null
SELECT JsonValue('[11, 22, 33]' json_) FROM t1;
JsonValue('[11, 22, 33]' json_)
[11,22,33]
[11,22,33]
[11,22,33]
[11,22,33]
[11,22,33]
SELECT Json_Array(); SELECT Json_Array();
Json_Array() Json_Array()
[] []
SELECT Json_Object(56,3.1416,'foo',NULL); SELECT Json_Array(56, 3.1416, 'My name is "Foo"', NULL);
Json_Object(56,3.1416,'foo',NULL) Json_Array(56, 3.1416, 'My name is "Foo"', NULL)
{"56":56,"3.1416":3.141600,"foo":"foo","NULL":null}
SELECT Json_Object(56 qty,3.1416 price,'foo' truc, NULL garanty);
Json_Object(56 qty,3.1416 price,'foo' truc, NULL garanty)
{"qty":56,"price":3.141600,"truc":"foo","garanty":null}
SELECT Json_Array(56,3.1416,'My name is "Foo"',NULL);
Json_Array(56,3.1416,'My name is "Foo"',NULL)
[56,3.141600,"My name is \"Foo\"",null] [56,3.141600,"My name is \"Foo\"",null]
SELECT Json_Array_Add(Json_Array(56,3.1416,'foo',NULL)) Array; SELECT Json_Array(Json_Array(56, 3.1416, 'foo'), TRUE);
ERROR HY000: Can't initialize function 'Json_Array_Add'; Json_Value_Add must have at least 2 arguments Json_Array(Json_Array(56, 3.1416, 'foo'), TRUE)
SELECT Json_Array_Add(Json_Array(56,3.1416,'foo',NULL),'One more') Array; [[56,3.141600,"foo"],true]
SELECT Json_Array_Add(Json_Array(56, 3.1416, 'foo', NULL)) Array;
ERROR HY000: Can't initialize function 'json_array_add'; This function must have at least 2 arguments
SELECT Json_Array_Add(Json_Array(56, 3.1416, 'foo', NULL), 'One more') Array;
Array Array
[56,3.141600,"foo",null,"One more"] [56,3.141600,"foo",null,"One more"]
SELECT Json_Array_Add(Json_Value('one value'),'One more'); SELECT Json_Array_Add(JsonValue('one value'), 'One more');
Json_Array_Add(Json_Value('one value'),'One more') ERROR HY000: Can't initialize function 'json_array_add'; First argument must be a json item
["one value","One more"] SELECT Json_Array_Add('one value', 'One more');
SELECT Json_Array_Add('one value','One more'); ERROR HY000: Can't initialize function 'json_array_add'; First argument must be a json item
ERROR HY000: Can't initialize function 'Json_Array_Add'; Json_Value_Add first argument must be a json item SELECT Json_Array_Add('one value' json_, 'One more');
SELECT Json_Array_Add('one value' json_,'One more'); Json_Array_Add('one value' json_, 'One more')
Json_Array_Add('one value' json_,'One more') one value
[null,"One more"]
Warnings: Warnings:
Warning 1105 Bad 'o' character near one value Warning 1105 Error 2 opening one value
SELECT Json_Value(56,3.1416,'foo',NULL); Warning 1105 First argument target is not an array
ERROR HY000: Can't initialize function 'Json_Value'; Json_Value cannot accept more than 1 argument SELECT Json_Array_Add(5 json_, 'One more');
SELECT Json_Value(3.1416); ERROR HY000: Can't initialize function 'json_array_add'; First argument must be a json item
Json_Value(3.1416) SELECT Json_Array_Add('[5,3,8,7,9]' json_, 4, 0);
3.141600 Json_Array_Add('[5,3,8,7,9]' json_, 4, 0)
SELECT Json_Value('foo'); [4,5,3,8,7,9]
Json_Value('foo') SELECT Json_Array_Add('[5,3,8,7,9]' json_, 4, 2) Array;
"foo" Array
SELECT Json_Value(NULL); [5,3,4,8,7,9]
Json_Value(NULL) SELECT Json_Array_Add('[5,3,8,7,9]' json_, 4, 9);
null Json_Array_Add('[5,3,8,7,9]' json_, 4, 9)
SELECT Json_Value(); [5,3,8,7,9,4]
Json_Value() SELECT Json_Array_Add(Json_Array(1, 2, Json_Array(11, 22)), '[2]', 33, 1);
null Json_Array_Add(Json_Array(1, 2, Json_Array(11, 22)), '[2]', 33, 1)
[1,2,[11,22],"[2]"]
SELECT Json_Array_Add(Json_Array(1, 2, Json_Array(11, 22)), 33, '[2]', 1);
Json_Array_Add(Json_Array(1, 2, Json_Array(11, 22)), 33, '[2]', 1)
[1,2,[11,33,22]]
SELECT Json_Array_Add(Json_Array(1, 2, Json_Array(11, 22)), 33, 1, '[2]');
Json_Array_Add(Json_Array(1, 2, Json_Array(11, 22)), 33, 1, '[2]')
[1,2,[11,33,22]]
SELECT Json_Array_Add_Values(Json_Array(56, 3.1416, 'machin', NULL), 'One more', 'Two more') Array;
Array
[56,3.141600,"machin",null,"One more","Two more"]
SELECT Json_Array_Add_Values(Json_Array(56, 3.1416, 'machin'), 'One more', 'Two more') Array FROM t1;
Array
[56,3.141600,"machin","One more","Two more"]
[56,3.141600,"machin","One more","Two more"]
[56,3.141600,"machin","One more","Two more"]
[56,3.141600,"machin","One more","Two more"]
[56,3.141600,"machin","One more","Two more"]
SELECT Json_Array_Add_Values(Json_Array(56, 3.1416, 'machin'), n) Array FROM t1;
Array
[56,3.141600,"machin",1]
[56,3.141600,"machin",2]
[56,3.141600,"machin",3]
[56,3.141600,"machin",4]
[56,3.141600,"machin",5]
SELECT Json_Array_Add_Values(Json_Array(n, 3.1416, 'machin'), n) Array FROM t1;
Array
[1,3.141600,"machin",1]
[2,3.141600,"machin",2]
[3,3.141600,"machin",3]
[4,3.141600,"machin",4]
[5,3.141600,"machin",5]
SELECT Json_Array_Add_Values('[56]', 3.1416, 'machin') Array;
Array
[56,3.141600,"machin"]
SELECT Json_Array_Delete(Json_Array(56, 3.1416, 'My name is "Foo"', NULL), 0);
Json_Array_Delete(Json_Array(56, 3.1416, 'My name is "Foo"', NULL), 0)
[3.141600,"My name is \"Foo\"",null]
SELECT Json_Array_Delete(Json_Object(56, 3.1416, 'My name is Foo', NULL), 2);
Json_Array_Delete(Json_Object(56, 3.1416, 'My name is Foo', NULL), 2)
{"56":56,"3.1416":3.141600,"My name is Foo":"My name is Foo","NULL":null}
Warnings:
Warning 1105 First argument target is not an array
SELECT Json_Array_Delete(Json_Array(56, 3.1416, 'My name is "Foo"', NULL), '2');
Json_Array_Delete(Json_Array(56, 3.1416, 'My name is "Foo"', NULL), '2')
[56,3.141600,"My name is \"Foo\"",null]
Warnings:
Warning 1105 Missing or null array index
SELECT Json_Array_Delete(json_array(56, 3.1416, 'My name is "Foo"', NULL), '2', 2);
Json_Array_Delete(json_array(56, 3.1416, 'My name is "Foo"', NULL), '2', 2)
[56,3.141600,"My name is \"Foo\"",null]
Warnings:
Warning 1105 No sub-item at '2'
SELECT Json_Object(56, 3.1416, 'foo', NULL);
Json_Object(56, 3.1416, 'foo', NULL)
{"56":56,"3.1416":3.141600,"foo":"foo","NULL":null}
SELECT Json_Object(56 qty, 3.1416 price, 'foo' truc, NULL garanty);
Json_Object(56 qty, 3.1416 price, 'foo' truc, NULL garanty)
{"qty":56,"price":3.141600,"truc":"foo","garanty":null}
SELECT Json_Object(); SELECT Json_Object();
Json_Object() Json_Object()
{} {}
SELECT Json_Object(Json_Array(56,3.1416,'foo'),NULL); SELECT Json_Object(Json_Array(56, 3.1416, 'foo'), NULL);
Json_Object(Json_Array(56,3.1416,'foo'),NULL) Json_Object(Json_Array(56, 3.1416, 'foo'), NULL)
{"Array(56,3.1416,'foo')":[56,3.141600,"foo"],"NULL":null} {"Array(56, 3.1416, 'foo')":[56,3.141600,"foo"],"NULL":null}
SELECT Json_Array(Json_Array(56,3.1416,'foo'),NULL); SELECT Json_Array(Json_Object(56 "qty", 3.1416 "price", 'foo') ,NULL);
Json_Array(Json_Array(56,3.1416,'foo'),NULL) Json_Array(Json_Object(56 "qty", 3.1416 "price", 'foo') ,NULL)
[[56,3.141600,"foo"],null]
SELECT Json_Array(Json_Object(56 "qty",3.1416 "price",'foo'),NULL);
Json_Array(Json_Object(56 "qty",3.1416 "price",'foo'),NULL)
[{"qty":56,"price":3.141600,"foo":"foo"},null] [{"qty":56,"price":3.141600,"foo":"foo"},null]
SELECT Json_Object_Key('qty', 56, 'price', 3.1416, 'truc', 'machin', 'garanty', NULL);
Json_Object_Key('qty', 56, 'price', 3.1416, 'truc', 'machin', 'garanty', NULL)
{"qty":56,"price":3.141600,"truc":"machin","garanty":null}
SELECT Json_Object_Key('qty', 56, 'price', 3.1416, 'truc', 'machin', 'garanty');
ERROR HY000: Can't initialize function 'json_object_key'; This function must have an even number of arguments
SELECT Json_Object_Add(Json_Object(56 qty, 3.1416 price, 'machin' truc, NULL garanty), 'blue' color);
Json_Object_Add(Json_Object(56 qty, 3.1416 price, 'machin' truc, NULL garanty), 'blue' color)
{"qty":56,"price":3.141600,"truc":"machin","garanty":null,"color":"blue"}
SELECT Json_Object_Add(Json_Object(56 qty, 3.1416 price, 'machin' truc, NULL garanty), 45.99 price);
Json_Object_Add(Json_Object(56 qty, 3.1416 price, 'machin' truc, NULL garanty), 45.99 price)
{"qty":56,"price":45.990000,"truc":"machin","garanty":null}
SELECT Json_Object_Add(Json_File('notexist.json'), 'cheese' item, '[1]', 1);
Json_Object_Add(Json_File('notexist.json'), 'cheese' item, '[1]', 1)
NULL
Warnings:
Warning 1105 Error 2 opening notexist.json
Warning 1105 First argument target is not an object
SELECT Json_Object_Delete(Json_Object(56 qty, 3.1416 price, 'machin' truc, NULL garanty), 'truc');
Json_Object_Delete(Json_Object(56 qty, 3.1416 price, 'machin' truc, NULL garanty), 'truc')
{"qty":56,"price":3.141600,"garanty":null}
SELECT Json_Object_Delete(Json_Object(56 qty, 3.1416 price, 'machin' truc, NULL garanty), 'chose');
Json_Object_Delete(Json_Object(56 qty, 3.1416 price, 'machin' truc, NULL garanty), 'chose')
{"qty":56,"price":3.141600,"truc":"machin","garanty":null}
SELECT Json_Object_List(Json_Object(56 qty, 3.1416 price, 'machin' truc, NULL garanty)) "Key List";
Key List
["qty","price","truc","garanty"]
SELECT Json_Object_List('{"qty":56, "price":3.1416, "truc":"machin", "garanty":null}') "Key List";
Key List
["qty","price","truc","garanty"]
# #
# Test UDF's with column arguments # Test UDF's with column arguments
# #
CREATE TABLE t1 CREATE TABLE t2
( (
ISBN CHAR(15), ISBN CHAR(15),
LANG CHAR(2), LANG CHAR(2),
...@@ -69,21 +183,20 @@ TRANSLATOR CHAR(80), ...@@ -69,21 +183,20 @@ TRANSLATOR CHAR(80),
PUBLISHER CHAR(32), PUBLISHER CHAR(32),
DATEPUB int(4) DATEPUB int(4)
) ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='biblio.json'; ) ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='biblio.json';
SELECT Json_Array(AUTHOR, TITLE, DATEPUB) FROM t1; SELECT Json_Array(AUTHOR, TITLE, DATEPUB) FROM t2;
Json_Array(AUTHOR, TITLE, DATEPUB) Json_Array(AUTHOR, TITLE, DATEPUB)
["Jean-Christophe Bernadac","Construire une application XML",1999] ["Jean-Christophe Bernadac","Construire une application XML",1999]
["William J. Pardi","XML en Action",1999] ["William J. Pardi","XML en Action",1999]
SELECT Json_Object(AUTHOR, TITLE, DATEPUB) FROM t1; SELECT Json_Object(AUTHOR, TITLE, DATEPUB) FROM t2;
Json_Object(AUTHOR, TITLE, DATEPUB) Json_Object(AUTHOR, TITLE, DATEPUB)
{"AUTHOR":"Jean-Christophe Bernadac","TITLE":"Construire une application XML","DATEPUB":1999} {"AUTHOR":"Jean-Christophe Bernadac","TITLE":"Construire une application XML","DATEPUB":1999}
{"AUTHOR":"William J. Pardi","TITLE":"XML en Action","DATEPUB":1999} {"AUTHOR":"William J. Pardi","TITLE":"XML en Action","DATEPUB":1999}
SELECT Json_Array_Grp(TITLE, DATEPUB) FROM t1; SELECT Json_Array_Grp(TITLE, DATEPUB) FROM t2;
ERROR HY000: Can't initialize function 'Json_Array_Grp'; Json_Array_Grp can only accept 1 argument ERROR HY000: Can't initialize function 'json_array_grp'; This function can only accept 1 argument
SELECT Json_Array_Grp(TITLE) FROM t1; SELECT Json_Array_Grp(TITLE) FROM t2;
Json_Array_Grp(TITLE) Json_Array_Grp(TITLE)
["Construire une application XML","XML en Action"] ["Construire une application XML","XML en Action"]
DROP TABLE t1; CREATE TABLE t3 (
CREATE TABLE t1 (
SERIALNO CHAR(5) NOT NULL, SERIALNO CHAR(5) NOT NULL,
NAME VARCHAR(12) NOT NULL FLAG=6, NAME VARCHAR(12) NOT NULL FLAG=6,
SEX SMALLINT(1) NOT NULL, SEX SMALLINT(1) NOT NULL,
...@@ -93,10 +206,10 @@ DEPARTMENT CHAr(4) NOT NULL FLAG=41, ...@@ -93,10 +206,10 @@ DEPARTMENT CHAr(4) NOT NULL FLAG=41,
SECRETARY CHAR(5) DEFAULT NULL FLAG=46, SECRETARY CHAR(5) DEFAULT NULL FLAG=46,
SALARY DOUBLE(8,2) NOT NULL FLAG=52 SALARY DOUBLE(8,2) NOT NULL FLAG=52
) ENGINE=CONNECT TABLE_TYPE=FIX BLOCK_SIZE=8 FILE_NAME='employee.dat' ENDING=1; ) ENGINE=CONNECT TABLE_TYPE=FIX BLOCK_SIZE=8 FILE_NAME='employee.dat' ENDING=1;
SELECT Json_Object(SERIALNO, NAME, TITLE, SALARY) FROM t1 WHERE NAME = 'MERCHANT'; SELECT Json_Object(SERIALNO, NAME, TITLE, SALARY) FROM t3 WHERE NAME = 'MERCHANT';
Json_Object(SERIALNO, NAME, TITLE, SALARY) Json_Object(SERIALNO, NAME, TITLE, SALARY)
{"SERIALNO":"78943","NAME":"MERCHANT","TITLE":"SALESMAN","SALARY":8700.000000} {"SERIALNO":"78943","NAME":"MERCHANT","TITLE":"SALESMAN","SALARY":8700.000000}
SELECT DEPARTMENT, Json_Array_Grp(NAME) FROM t1 GROUP BY DEPARTMENT; SELECT DEPARTMENT, Json_Array_Grp(NAME) FROM t3 GROUP BY DEPARTMENT;
DEPARTMENT Json_Array_Grp(NAME) DEPARTMENT Json_Array_Grp(NAME)
0021 ["STRONG","SHORTSIGHT"] 0021 ["STRONG","SHORTSIGHT"]
0318 ["BANCROFT","PLUMHEAD","HONEY","TONGHO","WALTER","SHRINKY","WERTHER","MERCHANT","WHEELFOR"] 0318 ["BANCROFT","PLUMHEAD","HONEY","TONGHO","WALTER","SHRINKY","WERTHER","MERCHANT","WHEELFOR"]
...@@ -104,26 +217,36 @@ DEPARTMENT Json_Array_Grp(NAME) ...@@ -104,26 +217,36 @@ DEPARTMENT Json_Array_Grp(NAME)
2452 ["BIGHEAD","ORELLY","BIGHORN","SMITH","CHERRY"] 2452 ["BIGHEAD","ORELLY","BIGHORN","SMITH","CHERRY"]
Warnings: Warnings:
Warning 1105 Result truncated to json_grp_size values Warning 1105 Result truncated to json_grp_size values
set connect_json_grp_size=30; SET connect_json_grp_size=30;
SELECT Json_Array(DEPARTMENT, Json_Array_Grp(NAME)) FROM t1 GROUP BY DEPARTMENT; SELECT Json_Object(title, Json_Array_Grp(name) `json_names`) from t3 GROUP BY title;
Json_Object(title, Json_Array_Grp(name) `json_names`)
{"title":"ADMINISTRATOR","names":["GOOSEPEN","FUNNIGUY","SHRINKY"]}
{"title":"DIRECTOR","names":["QUINN","WERTHER","STRONG"]}
{"title":"ENGINEER","names":["BROWNY","ORELLY","MARTIN","TONGHO","WALTER","SMITH"]}
{"title":"PROGRAMMER","names":["BUGHAPPY"]}
{"title":"SALESMAN","names":["WHEELFOR","MERCHANT","BULLOZER","BANCROFT","FODDERMAN"]}
{"title":"SCIENTIST","names":["BIGHEAD","BIGHORN"]}
{"title":"SECRETARY","names":["MESSIFUL","HONEY","SHORTSIGHT","CHERRY","MONAPENNY"]}
{"title":"TYPIST","names":["KITTY","PLUMHEAD"]}
SELECT Json_Array(DEPARTMENT, Json_Array_Grp(NAME)) FROM t3 GROUP BY DEPARTMENT;
Json_Array(DEPARTMENT, Json_Array_Grp(NAME)) Json_Array(DEPARTMENT, Json_Array_Grp(NAME))
["0021",["STRONG","SHORTSIGHT"]] ["0021",["STRONG","SHORTSIGHT"]]
["0318",["BANCROFT","PLUMHEAD","HONEY","TONGHO","WALTER","SHRINKY","WERTHER","MERCHANT","WHEELFOR"]] ["0318",["BANCROFT","PLUMHEAD","HONEY","TONGHO","WALTER","SHRINKY","WERTHER","MERCHANT","WHEELFOR"]]
["0319",["BULLOZER","QUINN","BROWNY","KITTY","MONAPENNY","MARTIN","FUNNIGUY","BUGHAPPY","FODDERMAN","MESSIFUL","GOOSEPEN"]] ["0319",["BULLOZER","QUINN","BROWNY","KITTY","MONAPENNY","MARTIN","FUNNIGUY","BUGHAPPY","FODDERMAN","MESSIFUL","GOOSEPEN"]]
["2452",["BIGHEAD","ORELLY","BIGHORN","SMITH","CHERRY"]] ["2452",["BIGHEAD","ORELLY","BIGHORN","SMITH","CHERRY"]]
SELECT Json_Object(DEPARTMENT, Json_Array_Grp(NAME) json_NAMES) FROM t1 GROUP BY DEPARTMENT; SELECT Json_Object(DEPARTMENT, Json_Array_Grp(NAME) json_NAMES) FROM t3 GROUP BY DEPARTMENT;
Json_Object(DEPARTMENT, Json_Array_Grp(NAME) json_NAMES) Json_Object(DEPARTMENT, Json_Array_Grp(NAME) json_NAMES)
{"DEPARTMENT":"0021","NAMES":["STRONG","SHORTSIGHT"]} {"DEPARTMENT":"0021","NAMES":["STRONG","SHORTSIGHT"]}
{"DEPARTMENT":"0318","NAMES":["BANCROFT","PLUMHEAD","HONEY","TONGHO","WALTER","SHRINKY","WERTHER","MERCHANT","WHEELFOR"]} {"DEPARTMENT":"0318","NAMES":["BANCROFT","PLUMHEAD","HONEY","TONGHO","WALTER","SHRINKY","WERTHER","MERCHANT","WHEELFOR"]}
{"DEPARTMENT":"0319","NAMES":["BULLOZER","QUINN","BROWNY","KITTY","MONAPENNY","MARTIN","FUNNIGUY","BUGHAPPY","FODDERMAN","MESSIFUL","GOOSEPEN"]} {"DEPARTMENT":"0319","NAMES":["BULLOZER","QUINN","BROWNY","KITTY","MONAPENNY","MARTIN","FUNNIGUY","BUGHAPPY","FODDERMAN","MESSIFUL","GOOSEPEN"]}
{"DEPARTMENT":"2452","NAMES":["BIGHEAD","ORELLY","BIGHORN","SMITH","CHERRY"]} {"DEPARTMENT":"2452","NAMES":["BIGHEAD","ORELLY","BIGHORN","SMITH","CHERRY"]}
SELECT Json_Object(DEPARTMENT, Json_Array_Grp(Json_Object(SERIALNO, NAME, TITLE, SALARY)) json_EMPLOYES) FROM t1 GROUP BY DEPARTMENT; SELECT Json_Object(DEPARTMENT, Json_Array_Grp(Json_Object(SERIALNO, NAME, TITLE, SALARY)) json_EMPLOYES) FROM t3 GROUP BY DEPARTMENT;
Json_Object(DEPARTMENT, Json_Array_Grp(Json_Object(SERIALNO, NAME, TITLE, SALARY)) json_EMPLOYES) Json_Object(DEPARTMENT, Json_Array_Grp(Json_Object(SERIALNO, NAME, TITLE, SALARY)) json_EMPLOYES)
{"DEPARTMENT":"0021","EMPLOYES":[{"SERIALNO":"87777","NAME":"STRONG","TITLE":"DIRECTOR","SALARY":23000.000000},{"SERIALNO":"22222","NAME":"SHORTSIGHT","TITLE":"SECRETARY","SALARY":5500.000000}]} {"DEPARTMENT":"0021","EMPLOYES":[{"SERIALNO":"87777","NAME":"STRONG","TITLE":"DIRECTOR","SALARY":23000.000000},{"SERIALNO":"22222","NAME":"SHORTSIGHT","TITLE":"SECRETARY","SALARY":5500.000000}]}
{"DEPARTMENT":"0318","EMPLOYES":[{"SERIALNO":"74200","NAME":"BANCROFT","TITLE":"SALESMAN","SALARY":9600.000000},{"SERIALNO":"24888","NAME":"PLUMHEAD","TITLE":"TYPIST","SALARY":2800.000000},{"SERIALNO":"27845","NAME":"HONEY","TITLE":"SECRETARY","SALARY":4900.000000},{"SERIALNO":"73452","NAME":"TONGHO","TITLE":"ENGINEER","SALARY":6800.000000},{"SERIALNO":"74234","NAME":"WALTER","TITLE":"ENGINEER","SALARY":7400.000000},{"SERIALNO":"77777","NAME":"SHRINKY","TITLE":"ADMINISTRATOR","SALARY":7500.000000},{"SERIALNO":"70012","NAME":"WERTHER","TITLE":"DIRECTOR","SALARY":14500.000000},{"SERIALNO":"78943","NAME":"MERCHANT","TITLE":"SALESMAN","SALARY":8700.000000},{"SERIALNO":"73111","NAME":"WHEELFOR","TITLE":"SALESMAN","SALARY":10030.000000}]} {"DEPARTMENT":"0318","EMPLOYES":[{"SERIALNO":"74200","NAME":"BANCROFT","TITLE":"SALESMAN","SALARY":9600.000000},{"SERIALNO":"24888","NAME":"PLUMHEAD","TITLE":"TYPIST","SALARY":2800.000000},{"SERIALNO":"27845","NAME":"HONEY","TITLE":"SECRETARY","SALARY":4900.000000},{"SERIALNO":"73452","NAME":"TONGHO","TITLE":"ENGINEER","SALARY":6800.000000},{"SERIALNO":"74234","NAME":"WALTER","TITLE":"ENGINEER","SALARY":7400.000000},{"SERIALNO":"77777","NAME":"SHRINKY","TITLE":"ADMINISTRATOR","SALARY":7500.000000},{"SERIALNO":"70012","NAME":"WERTHER","TITLE":"DIRECTOR","SALARY":14500.000000},{"SERIALNO":"78943","NAME":"MERCHANT","TITLE":"SALESMAN","SALARY":8700.000000},{"SERIALNO":"73111","NAME":"WHEELFOR","TITLE":"SALESMAN","SALARY":10030.000000}]}
{"DEPARTMENT":"0319","EMPLOYES":[{"SERIALNO":"76543","NAME":"BULLOZER","TITLE":"SALESMAN","SALARY":14800.000000},{"SERIALNO":"40567","NAME":"QUINN","TITLE":"DIRECTOR","SALARY":14000.000000},{"SERIALNO":"00137","NAME":"BROWNY","TITLE":"ENGINEER","SALARY":10500.000000},{"SERIALNO":"12345","NAME":"KITTY","TITLE":"TYPIST","SALARY":3000.450000},{"SERIALNO":"33333","NAME":"MONAPENNY","TITLE":"SECRETARY","SALARY":3800.000000},{"SERIALNO":"00023","NAME":"MARTIN","TITLE":"ENGINEER","SALARY":10000.000000},{"SERIALNO":"07654","NAME":"FUNNIGUY","TITLE":"ADMINISTRATOR","SALARY":8500.000000},{"SERIALNO":"45678","NAME":"BUGHAPPY","TITLE":"PROGRAMMER","SALARY":8500.000000},{"SERIALNO":"56789","NAME":"FODDERMAN","TITLE":"SALESMAN","SALARY":7000.000000},{"SERIALNO":"55555","NAME":"MESSIFUL","TITLE":"SECRETARY","SALARY":5000.500000},{"SERIALNO":"98765","NAME":"GOOSEPEN","TITLE":"ADMINISTRATOR","SALARY":4700.000000}]} {"DEPARTMENT":"0319","EMPLOYES":[{"SERIALNO":"76543","NAME":"BULLOZER","TITLE":"SALESMAN","SALARY":14800.000000},{"SERIALNO":"40567","NAME":"QUINN","TITLE":"DIRECTOR","SALARY":14000.000000},{"SERIALNO":"00137","NAME":"BROWNY","TITLE":"ENGINEER","SALARY":10500.000000},{"SERIALNO":"12345","NAME":"KITTY","TITLE":"TYPIST","SALARY":3000.450000},{"SERIALNO":"33333","NAME":"MONAPENNY","TITLE":"SECRETARY","SALARY":3800.000000},{"SERIALNO":"00023","NAME":"MARTIN","TITLE":"ENGINEER","SALARY":10000.000000},{"SERIALNO":"07654","NAME":"FUNNIGUY","TITLE":"ADMINISTRATOR","SALARY":8500.000000},{"SERIALNO":"45678","NAME":"BUGHAPPY","TITLE":"PROGRAMMER","SALARY":8500.000000},{"SERIALNO":"56789","NAME":"FODDERMAN","TITLE":"SALESMAN","SALARY":7000.000000},{"SERIALNO":"55555","NAME":"MESSIFUL","TITLE":"SECRETARY","SALARY":5000.500000},{"SERIALNO":"98765","NAME":"GOOSEPEN","TITLE":"ADMINISTRATOR","SALARY":4700.000000}]}
{"DEPARTMENT":"2452","EMPLOYES":[{"SERIALNO":"34567","NAME":"BIGHEAD","TITLE":"SCIENTIST","SALARY":8000.000000},{"SERIALNO":"31416","NAME":"ORELLY","TITLE":"ENGINEER","SALARY":13400.000000},{"SERIALNO":"36666","NAME":"BIGHORN","TITLE":"SCIENTIST","SALARY":11000.000000},{"SERIALNO":"02345","NAME":"SMITH","TITLE":"ENGINEER","SALARY":9000.000000},{"SERIALNO":"11111","NAME":"CHERRY","TITLE":"SECRETARY","SALARY":4500.000000}]} {"DEPARTMENT":"2452","EMPLOYES":[{"SERIALNO":"34567","NAME":"BIGHEAD","TITLE":"SCIENTIST","SALARY":8000.000000},{"SERIALNO":"31416","NAME":"ORELLY","TITLE":"ENGINEER","SALARY":13400.000000},{"SERIALNO":"36666","NAME":"BIGHORN","TITLE":"SCIENTIST","SALARY":11000.000000},{"SERIALNO":"02345","NAME":"SMITH","TITLE":"ENGINEER","SALARY":9000.000000},{"SERIALNO":"11111","NAME":"CHERRY","TITLE":"SECRETARY","SALARY":4500.000000}]}
SELECT Json_Object(DEPARTMENT, TITLE, Json_Array_Grp(Json_Object(SERIALNO, NAME, SALARY)) json_EMPLOYES) FROM t1 GROUP BY DEPARTMENT, TITLE; SELECT Json_Object(DEPARTMENT, TITLE, Json_Array_Grp(Json_Object(SERIALNO, NAME, SALARY)) json_EMPLOYES) FROM t3 GROUP BY DEPARTMENT, TITLE;
Json_Object(DEPARTMENT, TITLE, Json_Array_Grp(Json_Object(SERIALNO, NAME, SALARY)) json_EMPLOYES) Json_Object(DEPARTMENT, TITLE, Json_Array_Grp(Json_Object(SERIALNO, NAME, SALARY)) json_EMPLOYES)
{"DEPARTMENT":"0021","TITLE":"DIRECTOR","EMPLOYES":[{"SERIALNO":"87777","NAME":"STRONG","SALARY":23000.000000}]} {"DEPARTMENT":"0021","TITLE":"DIRECTOR","EMPLOYES":[{"SERIALNO":"87777","NAME":"STRONG","SALARY":23000.000000}]}
{"DEPARTMENT":"0021","TITLE":"SECRETARY","EMPLOYES":[{"SERIALNO":"22222","NAME":"SHORTSIGHT","SALARY":5500.000000}]} {"DEPARTMENT":"0021","TITLE":"SECRETARY","EMPLOYES":[{"SERIALNO":"22222","NAME":"SHORTSIGHT","SALARY":5500.000000}]}
...@@ -143,25 +266,382 @@ Json_Object(DEPARTMENT, TITLE, Json_Array_Grp(Json_Object(SERIALNO, NAME, SALARY ...@@ -143,25 +266,382 @@ Json_Object(DEPARTMENT, TITLE, Json_Array_Grp(Json_Object(SERIALNO, NAME, SALARY
{"DEPARTMENT":"2452","TITLE":"ENGINEER","EMPLOYES":[{"SERIALNO":"31416","NAME":"ORELLY","SALARY":13400.000000},{"SERIALNO":"02345","NAME":"SMITH","SALARY":9000.000000}]} {"DEPARTMENT":"2452","TITLE":"ENGINEER","EMPLOYES":[{"SERIALNO":"31416","NAME":"ORELLY","SALARY":13400.000000},{"SERIALNO":"02345","NAME":"SMITH","SALARY":9000.000000}]}
{"DEPARTMENT":"2452","TITLE":"SCIENTIST","EMPLOYES":[{"SERIALNO":"34567","NAME":"BIGHEAD","SALARY":8000.000000},{"SERIALNO":"36666","NAME":"BIGHORN","SALARY":11000.000000}]} {"DEPARTMENT":"2452","TITLE":"SCIENTIST","EMPLOYES":[{"SERIALNO":"34567","NAME":"BIGHEAD","SALARY":8000.000000},{"SERIALNO":"36666","NAME":"BIGHORN","SALARY":11000.000000}]}
{"DEPARTMENT":"2452","TITLE":"SECRETARY","EMPLOYES":[{"SERIALNO":"11111","NAME":"CHERRY","SALARY":4500.000000}]} {"DEPARTMENT":"2452","TITLE":"SECRETARY","EMPLOYES":[{"SERIALNO":"11111","NAME":"CHERRY","SALARY":4500.000000}]}
SELECT Json_Object_Grp(SALARY) FROM t1; SELECT Json_Object_Grp(SALARY) FROM t3;
ERROR HY000: Can't initialize function 'Json_Object_Grp'; Json_Array_Grp can only accept 2 arguments ERROR HY000: Can't initialize function 'json_object_grp'; This function requires 2 arguments (key, value)
SELECT Json_Object_Grp(SALARY, NAME) FROM t1; SELECT Json_Object_Grp(NAME, SALARY) FROM t3;
Json_Object_Grp(SALARY, NAME) Json_Object_Grp(NAME, SALARY)
{"BANCROFT":9600.000000,"SMITH":9000.000000,"MERCHANT":8700.000000,"FUNNIGUY":8500.000000,"BUGHAPPY":8500.000000,"BIGHEAD":8000.000000,"SHRINKY":7500.000000,"WALTER":7400.000000,"FODDERMAN":7000.000000,"TONGHO":6800.000000,"SHORTSIGHT":5500.000000,"MESSIFUL":5000.500000,"HONEY":4900.000000,"GOOSEPEN":4700.000000,"CHERRY":4500.000000,"MONAPENNY":3800.000000,"KITTY":3000.450000,"PLUMHEAD":2800.000000,"STRONG":23000.000000,"BULLOZER":14800.000000,"WERTHER":14500.000000,"QUINN":14000.000000,"ORELLY":13400.000000,"BIGHORN":11000.000000,"BROWNY":10500.000000,"WHEELFOR":10030.000000,"MARTIN":10000.000000} {"BANCROFT":9600.000000,"SMITH":9000.000000,"MERCHANT":8700.000000,"FUNNIGUY":8500.000000,"BUGHAPPY":8500.000000,"BIGHEAD":8000.000000,"SHRINKY":7500.000000,"WALTER":7400.000000,"FODDERMAN":7000.000000,"TONGHO":6800.000000,"SHORTSIGHT":5500.000000,"MESSIFUL":5000.500000,"HONEY":4900.000000,"GOOSEPEN":4700.000000,"CHERRY":4500.000000,"MONAPENNY":3800.000000,"KITTY":3000.450000,"PLUMHEAD":2800.000000,"STRONG":23000.000000,"BULLOZER":14800.000000,"WERTHER":14500.000000,"QUINN":14000.000000,"ORELLY":13400.000000,"BIGHORN":11000.000000,"BROWNY":10500.000000,"WHEELFOR":10030.000000,"MARTIN":10000.000000}
SELECT Json_Object(DEPARTMENT, Json_Object_Grp(SALARY, NAME) "Json_SALARIES") FROM t1 GROUP BY DEPARTMENT; SELECT Json_Object(DEPARTMENT, Json_Object_Grp(NAME, SALARY) "Json_SALARIES") FROM t3 GROUP BY DEPARTMENT;
Json_Object(DEPARTMENT, Json_Object_Grp(SALARY, NAME) "Json_SALARIES") Json_Object(DEPARTMENT, Json_Object_Grp(NAME, SALARY) "Json_SALARIES")
{"DEPARTMENT":"0021","SALARIES":{"STRONG":23000.000000,"SHORTSIGHT":5500.000000}} {"DEPARTMENT":"0021","SALARIES":{"STRONG":23000.000000,"SHORTSIGHT":5500.000000}}
{"DEPARTMENT":"0318","SALARIES":{"BANCROFT":9600.000000,"PLUMHEAD":2800.000000,"HONEY":4900.000000,"TONGHO":6800.000000,"WALTER":7400.000000,"SHRINKY":7500.000000,"WERTHER":14500.000000,"MERCHANT":8700.000000,"WHEELFOR":10030.000000}} {"DEPARTMENT":"0318","SALARIES":{"BANCROFT":9600.000000,"PLUMHEAD":2800.000000,"HONEY":4900.000000,"TONGHO":6800.000000,"WALTER":7400.000000,"SHRINKY":7500.000000,"WERTHER":14500.000000,"MERCHANT":8700.000000,"WHEELFOR":10030.000000}}
{"DEPARTMENT":"0319","SALARIES":{"BULLOZER":14800.000000,"QUINN":14000.000000,"BROWNY":10500.000000,"KITTY":3000.450000,"MONAPENNY":3800.000000,"MARTIN":10000.000000,"FUNNIGUY":8500.000000,"BUGHAPPY":8500.000000,"FODDERMAN":7000.000000,"MESSIFUL":5000.500000,"GOOSEPEN":4700.000000}} {"DEPARTMENT":"0319","SALARIES":{"BULLOZER":14800.000000,"QUINN":14000.000000,"BROWNY":10500.000000,"KITTY":3000.450000,"MONAPENNY":3800.000000,"MARTIN":10000.000000,"FUNNIGUY":8500.000000,"BUGHAPPY":8500.000000,"FODDERMAN":7000.000000,"MESSIFUL":5000.500000,"GOOSEPEN":4700.000000}}
{"DEPARTMENT":"2452","SALARIES":{"BIGHEAD":8000.000000,"ORELLY":13400.000000,"BIGHORN":11000.000000,"SMITH":9000.000000,"CHERRY":4500.000000}} {"DEPARTMENT":"2452","SALARIES":{"BIGHEAD":8000.000000,"ORELLY":13400.000000,"BIGHORN":11000.000000,"SMITH":9000.000000,"CHERRY":4500.000000}}
SELECT Json_Array_Grp(NAME) from t1; SELECT Json_Array_Grp(NAME) FROM t3;
Json_Array_Grp(NAME) Json_Array_Grp(NAME)
["BANCROFT","SMITH","MERCHANT","FUNNIGUY","BUGHAPPY","BIGHEAD","SHRINKY","WALTER","FODDERMAN","TONGHO","SHORTSIGHT","MESSIFUL","HONEY","GOOSEPEN","CHERRY","MONAPENNY","KITTY","PLUMHEAD","STRONG","BULLOZER","WERTHER","QUINN","ORELLY","BIGHORN","BROWNY","WHEELFOR","MARTIN"] ["BANCROFT","SMITH","MERCHANT","FUNNIGUY","BUGHAPPY","BIGHEAD","SHRINKY","WALTER","FODDERMAN","TONGHO","SHORTSIGHT","MESSIFUL","HONEY","GOOSEPEN","CHERRY","MONAPENNY","KITTY","PLUMHEAD","STRONG","BULLOZER","WERTHER","QUINN","ORELLY","BIGHORN","BROWNY","WHEELFOR","MARTIN"]
SELECT Json_Object_Key(name, title) FROM t3 WHERE DEPARTMENT = 318;
Json_Object_Key(name, title)
{"BANCROFT":"SALESMAN"}
{"MERCHANT":"SALESMAN"}
{"SHRINKY":"ADMINISTRATOR"}
{"WALTER":"ENGINEER"}
{"TONGHO":"ENGINEER"}
{"HONEY":"SECRETARY"}
{"PLUMHEAD":"TYPIST"}
{"WERTHER":"DIRECTOR"}
{"WHEELFOR":"SALESMAN"}
SELECT Json_Object_Grp(name, title) FROM t3 WHERE DEPARTMENT = 318;
Json_Object_Grp(name, title)
{"BANCROFT":"SALESMAN","MERCHANT":"SALESMAN","SHRINKY":"ADMINISTRATOR","WALTER":"ENGINEER","TONGHO":"ENGINEER","HONEY":"SECRETARY","PLUMHEAD":"TYPIST","WERTHER":"DIRECTOR","WHEELFOR":"SALESMAN"}
#
# Test value getting UDF's
#
SELECT JsonGet_String(Json_Array_Grp(name),'[#]') FROM t3;
JsonGet_String(Json_Array_Grp(name),'[#]')
27
SELECT JsonGet_String(Json_Array_Grp(name),'[","]') FROM t3;
JsonGet_String(Json_Array_Grp(name),'[","]')
BANCROFT,SMITH,MERCHANT,FUNNIGUY,BUGHAPPY,BIGHEAD,SHRINKY,WALTER,FODDERMAN,TONGHO,SHORTSIGHT,MESSIFUL,HONEY,GOOSEPEN,CHERRY,MONAPENNY,KITTY,PLUMHEAD,STRONG,BULLOZER,WERTHER,QUINN,ORELLY,BIGHORN,BROWNY,WHEELFOR,MARTIN
SELECT JsonGet_String(Json_Array_Grp(name),'[>]') FROM t3;
JsonGet_String(Json_Array_Grp(name),'[>]')
WHEELFOR
SET @j1 = '[45,28,36,45,89]';
SELECT JsonGet_String(@j1,'[1]');
JsonGet_String(@j1,'[1]')
28
SELECT JsonGet_String(@j1 json_,'[3]');
JsonGet_String(@j1 json_,'[3]')
45
SELECT JsonGet_String(Json_Array(45,28,36,45,89),'[3]');
JsonGet_String(Json_Array(45,28,36,45,89),'[3]')
45
SELECT JsonGet_String(Json_Array(45,28,36,45,89),'["+"]') "list",'=' as "egal",JsonGet_String(Json_Array(45,28,36,45,89),'[+]') "sum";
list egal sum
45+28+36+45+89 = 243.00
SELECT JsonGet_String(Json_Array(json_array(45,28),json_array(36,45,89)),'[1]:[0]');
JsonGet_String(Json_Array(json_array(45,28),json_array(36,45,89)),'[1]:[0]')
36
SELECT JsonGet_String(Json_Array(json_array(45,28),json_array(36,45,89)),'[1]:*');
JsonGet_String(Json_Array(json_array(45,28),json_array(36,45,89)),'[1]:*')
[36,45,89]
SELECT JsonGet_String(Json_Object(56 qty,3.1416 price,'machin' truc, NULL garanty),'truc');
JsonGet_String(Json_Object(56 qty,3.1416 price,'machin' truc, NULL garanty),'truc')
machin
SET @j2 = '{"qty":56,"price":3.141600,"truc":"machin","garanty":null}';
SELECT JsonGet_String(@j2 json_,'truc');
JsonGet_String(@j2 json_,'truc')
machin
SELECT JsonGet_String(@j2,'truc');
JsonGet_String(@j2,'truc')
machin
SELECT JsonGet_String(@j2,'chose');
JsonGet_String(@j2,'chose')
NULL
SELECT JsonGet_String(NULL json_, NULL);
JsonGet_String(NULL json_, NULL)
NULL
Warnings:
Warning 1105
SELECT department, JsonGet_String(Json_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
SELECT JsonGet_Int(@j1, '[4]');
JsonGet_Int(@j1, '[4]')
89
SELECT JsonGet_Int(@j1, '[#]');
JsonGet_Int(@j1, '[#]')
5
SELECT JsonGet_Int(@j1, '[+]');
JsonGet_Int(@j1, '[+]')
243
SELECT JsonGet_Int(@j1 json_, '[3]');
JsonGet_Int(@j1 json_, '[3]')
45
SELECT JsonGet_Int(Json_Array(45,28,36,45,89), '[3]');
JsonGet_Int(Json_Array(45,28,36,45,89), '[3]')
45
SELECT JsonGet_Int(Json_Array(45,28,36,45,89), '["+"]');
JsonGet_Int(Json_Array(45,28,36,45,89), '["+"]')
45
SELECT JsonGet_Int(Json_Array(45,28,36,45,89), '[+]');
JsonGet_Int(Json_Array(45,28,36,45,89), '[+]')
243
SELECT JsonGet_Int(Json_Array(json_array(45,28), json_array(36,45,89)), '[1]:[0]');
JsonGet_Int(Json_Array(json_array(45,28), json_array(36,45,89)), '[1]:[0]')
36
SELECT JsonGet_Int(Json_Array(json_array(45,28), json_array(36,45,89)), '[0]:[1]');
JsonGet_Int(Json_Array(json_array(45,28), json_array(36,45,89)), '[0]:[1]')
28
SELECT JsonGet_Int(Json_Object(56 qty, 3.1416 price, 'machin' truc, NULL garanty), 'qty');
JsonGet_Int(Json_Object(56 qty, 3.1416 price, 'machin' truc, NULL garanty), 'qty')
56
SELECT JsonGet_Int(@j2 json_, 'price');
JsonGet_Int(@j2 json_, 'price')
3
SELECT JsonGet_Int(@j2, 'qty');
JsonGet_Int(@j2, 'qty')
56
SELECT JsonGet_Int('{"qty":56,"price":3.141600,"truc":"machin","garanty":null}', 'chose');
JsonGet_Int('{"qty":56,"price":3.141600,"truc":"machin","garanty":null}', 'chose')
NULL
SELECT JsonGet_Int(JsonGet_String(Json_Array(Json_Array(45,28),Json_Array(36,45,89)), '[1]:*'), '[+]') sum;
sum
170
SELECT department, JsonGet_Int(Json_Object(department, Json_Array_Grp(salary) "Json_salaries"), 'salaries:[+]') Sumsal FROM t3 GROUP BY department;
department Sumsal
0021 28500
0318 72230
0319 89800
2452 45900
SELECT JsonGet_Real(@j1, '[2]');
JsonGet_Real(@j1, '[2]')
36.000000000000000
SELECT JsonGet_Real(@j1 json_, '[3]', 2);
JsonGet_Real(@j1 json_, '[3]', 2)
45.00
SELECT JsonGet_Real(Json_Array(45,28,36,45,89), '[3]');
JsonGet_Real(Json_Array(45,28,36,45,89), '[3]')
45.000000000000000
SELECT JsonGet_Real(Json_Array(45,28,36,45,89), '["+"]');
JsonGet_Real(Json_Array(45,28,36,45,89), '["+"]')
45.000000000000000
SELECT JsonGet_Real(Json_Array(45,28,36,45,89), '[+]');
JsonGet_Real(Json_Array(45,28,36,45,89), '[+]')
243.000000000000000
SELECT JsonGet_Real(Json_Array(45,28,36,45,89), '[!]');
JsonGet_Real(Json_Array(45,28,36,45,89), '[!]')
48.600000000000000
SELECT JsonGet_Real(Json_Array(json_array(45,28), json_array(36,45,89)), '[1]:[0]');
JsonGet_Real(Json_Array(json_array(45,28), json_array(36,45,89)), '[1]:[0]')
36.000000000000000
SELECT JsonGet_Real(Json_Object(56 qty, 3.1416 price, 'machin' truc, NULL garanty), 'price');
JsonGet_Real(Json_Object(56 qty, 3.1416 price, 'machin' truc, NULL garanty), 'price')
3.141600000000000
SELECT JsonGet_Real('{"qty":56,"price":3.141600,"truc":"machin","garanty":null}' json_, 'qty');
JsonGet_Real('{"qty":56,"price":3.141600,"truc":"machin","garanty":null}' json_, 'qty')
56.000000000000000
SELECT JsonGet_Real('{"qty":56,"price":3.141600,"truc":"machin","garanty":null}', 'price');
JsonGet_Real('{"qty":56,"price":3.141600,"truc":"machin","garanty":null}', 'price')
3.141600000000000
SELECT JsonGet_Real('{"qty":56,"price":3.141600,"truc":"machin","garanty":null}', 'price', 4);
JsonGet_Real('{"qty":56,"price":3.141600,"truc":"machin","garanty":null}', 'price', 4)
3.1416
SELECT JsonGet_Real('{"qty":56,"price":3.141600,"truc":"machin","garanty":null}', 'chose');
JsonGet_Real('{"qty":56,"price":3.141600,"truc":"machin","garanty":null}', 'chose')
NULL
SELECT department, JsonGet_Real(Json_Object(department, Json_Array_Grp(salary) "Json_salaries"),'salaries:[+]') Sumsal FROM t3 GROUP BY department;
department Sumsal
0021 28500.000000000000000
0318 72230.000000000000000
0319 89800.950000000000000
2452 45900.000000000000000
#
# Documentation examples
#
SELECT
JsonGet_Int(Json_Array(45,28,36,45,89), '[4]') "Rank",
JsonGet_Int(Json_Array(45,28,36,45,89), '[#]') "Number",
JsonGet_String(Json_Array(45,28,36,45,89), '[","]') "Concat",
JsonGet_Int(Json_Array(45,28,36,45,89), '[+]') "Sum",
JsonGet_Real(Json_Array(45,28,36,45,89), '[!]', 2) "Avg";
Rank Number Concat Sum Avg
89 5 45,28,36,45,89 243 48.60
SELECT
JsonGet_String('{"qty":7,"price":29.50,"garanty":null}', 'price') "String",
JsonGet_Int('{"qty":7,"price":29.50,"garanty":null}', 'price') "Int",
JsonGet_Real('{"qty":7,"price":29.50,"garanty":null}', 'price') "Real";
String Int Real
29.50 29 29.500000000000000
SELECT JsonGet_Real('{"qty":7,"price":29.50,"garanty":null}', 'price', 3) "Real";
Real
29.500
#
# Testing Locate
#
SELECT JsonLocate(Json_Object(56 qty,3.1416 price,'machin' truc, NULL garanty),'machin');
JsonLocate(Json_Object(56 qty,3.1416 price,'machin' truc, NULL garanty),'machin')
truc
SELECT JsonLocate(Json_Object(56 qty,3.1416 price,'machin' truc, NULL garanty),56);
JsonLocate(Json_Object(56 qty,3.1416 price,'machin' truc, NULL garanty),56)
qty
SELECT JsonLocate(Json_Object(56 qty,3.1416 price,'machin' truc, NULL garanty),3.1416);
JsonLocate(Json_Object(56 qty,3.1416 price,'machin' truc, NULL garanty),3.1416)
price
SELECT JsonLocate(Json_Object(56 qty,3.1416 price,'machin' truc, NULL garanty),'chose');
JsonLocate(Json_Object(56 qty,3.1416 price,'machin' truc, NULL garanty),'chose')
NULL
SELECT JsonLocate('{"AUTHORS":[{"FN":"Jules", "LN":"Verne"}, {"FN":"Jack", "LN":"London"}]}' json_, 'Jack') Path;
Path
AUTHORS:[1]:FN
SELECT JsonLocate('{"AUTHORS":[{"FN":"Jules", "LN":"Verne"}, {"FN":"Jack", "LN":"London"}]}' json_, 'jack' ci) Path;
Path
AUTHORS:[1]:FN
SELECT JsonLocate('{"AUTHORS":[{"FN":"Jules", "LN":"Verne"}, {"FN":"Jack", "LN":"London"}]}' json_, '{"FN":"Jack", "LN":"London"}' json_) Path;
Path
AUTHORS:[1]
SELECT JsonLocate('{"AUTHORS":[{"FN":"Jules", "LN":"Verne"}, {"FN":"Jack", "LN":"London"}]}' json_, '{"FN":"jack", "LN":"London"}' json_) Path;
Path
NULL
SELECT JsonLocate('[45,28,36,45,89]',36);
JsonLocate('[45,28,36,45,89]',36)
[2]
SELECT JsonLocate('[45,28,36,45,89]' json_,28.0);
JsonLocate('[45,28,36,45,89]' json_,28.0)
NULL
SELECT Json_Locate_All('[45,28,36,45,89]',10);
Json_Locate_All('[45,28,36,45,89]',10)
[]
SELECT Json_Locate_All('[45,28,36,45,89]',45);
Json_Locate_All('[45,28,36,45,89]',45)
["[0]","[3]"]
SELECT Json_Locate_All('[[45,28],36,45,89]',45);
Json_Locate_All('[[45,28],36,45,89]',45)
["[0]:[0]","[2]"]
SELECT Json_Locate_All('[[45,28,45],36,45,89]',45);
Json_Locate_All('[[45,28,45],36,45,89]',45)
["[0]:[0]","[0]:[2]","[2]"]
SELECT Json_Locate_All('[[45,28,45],36,45,89]',JsonGet_Int('[3,45]','[1]'));
Json_Locate_All('[[45,28,45],36,45,89]',JsonGet_Int('[3,45]','[1]'))
["[0]:[0]","[0]:[2]","[2]"]
SELECT JsonLocate('[[45,28,45],36,45,89]',45,n) from t1;
JsonLocate('[[45,28,45],36,45,89]',45,n)
[0]:[0]
[0]:[2]
[2]
NULL
NULL
SELECT JsonGet_String(Json_Locate_All('[[45,28,45],36,45,89]',45),concat('[',n-1,']')) FROM t1;
JsonGet_String(Json_Locate_All('[[45,28,45],36,45,89]',45),concat('[',n-1,']'))
[0]:[0]
[0]:[2]
[2]
NULL
NULL
SELECT JsonGet_String(Json_Locate_All('[[45,28,45],36,45,89]',45),concat('[',n-1,']')) AS `Path` FROM t1 GROUP BY n HAVING `Path` IS NOT NULL;
Path
[0]:[0]
[0]:[2]
[2]
SELECT Json_Locate_All('[45,28,[36,45,89]]',45);
Json_Locate_All('[45,28,[36,45,89]]',45)
["[0]","[2]:[1]"]
SELECT Json_Locate_All('[[45,28],[36,45.0,89]]',JsonValue(45.0));
Json_Locate_All('[[45,28],[36,45.0,89]]',JsonValue(45.0))
[]
SELECT Json_Locate_All('[[45,28],[36,45.0,89]]',45.0);
Json_Locate_All('[[45,28],[36,45.0,89]]',45.0)
["[1]:[1]"]
SELECT JsonLocate('[[45,28],[36,45,89]]','[36,45,89]' json_);
JsonLocate('[[45,28],[36,45,89]]','[36,45,89]' json_)
[1]
SELECT JsonLocate('[[45,28],[36,45,89]]','[45,28]' json_);
JsonLocate('[[45,28],[36,45,89]]','[45,28]' json_)
[0]
SELECT Json_Locate_All('[[45,28],[[36,45],89]]','45') "All paths";
All paths
[]
SELECT Json_Locate_All('[[45,28],[[36,45],89]]','[36,45]' json_);
Json_Locate_All('[[45,28],[[36,45],89]]','[36,45]' json_)
["[1]:[0]"]
SELECT JsonGet_Int(Json_Locate_All('[[45,28],[[36,45],89]]',45), '[#]') "Nb of occurs";
Nb of occurs
2
SELECT Json_Locate_All('[[45,28],[[36,45],89]]',45,2);
Json_Locate_All('[[45,28],[[36,45],89]]',45,2)
["[0]:[0]"]
SELECT JsonGet_String(Json_Locate_All('[45,28,36,45,89]',45),'[0]');
JsonGet_String(Json_Locate_All('[45,28,36,45,89]',45),'[0]')
[0]
SELECT JsonLocate(Json_File('test/biblio.json'), 'Knab');
JsonLocate(Json_File('test/biblio.json'), 'Knab')
[0]:AUTHOR:[1]:LASTNAME
SELECT Json_Locate_All('test/biblio.json' jfile_, 'Knab');
Json_Locate_All('test/biblio.json' jfile_, 'Knab')
["[0]:AUTHOR:[1]:LASTNAME"]
#
# Testing json files
#
SELECT Jfile_Make('[{"_id":5,"type":"food","item":"beer","taste":"light","price":5.65,"ratings":[5,8,9]},
{"_id":6,"type":"car","item":"roadster","mileage":56000,"ratings":[6,9]},
{"_id":7,"type":"food","item":"meat","origin":"argentina","ratings":[2,4]},
{"_id":8,"type":"furniture","item":"table","size":{"W":60,"L":80,"H":40},"ratings":[5,8,7]}]', 'test/fx.json', 0) AS NewFile;
NewFile
test/fx.json
SELECT Jfile_Make('test/fx.json', 1);
Jfile_Make('test/fx.json', 1)
test/fx.json
SELECT Jfile_Make('test/fx.json' jfile_);
Jfile_Make('test/fx.json' jfile_)
test/fx.json
SELECT Jfile_Make(Jbin_File('test/fx.json'), 0);
Jfile_Make(Jbin_File('test/fx.json'), 0)
test/fx.json
SELECT Json_File('test/fx.json', 1);
Json_File('test/fx.json', 1)
[{"_id":5,"type":"food","item":"beer","taste":"light","price":5.65,"ratings":[5,8,9]},{"_id":6,"type":"car","item":"roadster","mileage":56000,"ratings":[6,9]},{"_id":7,"type":"food","item":"meat","origin":"argentina","ratings":[2,4]},{"_id":8,"type":"furniture","item":"table","size":{"W":60,"L":80,"H":40},"ratings":[5,8,7]}]
Warnings:
Warning 1105 File pretty format doesn't match the specified pretty value
SELECT Json_File('test/fx.json', 2);
Json_File('test/fx.json', 2)
[{"_id":5,"type":"food","item":"beer","taste":"light","price":5.65,"ratings":[5,8,9]},{"_id":6,"type":"car","item":"roadster","mileage":56000,"ratings":[6,9]},{"_id":7,"type":"food","item":"meat","origin":"argentina","ratings":[2,4]},{"_id":8,"type":"furniture","item":"table","size":{"W":60,"L":80,"H":40},"ratings":[5,8,7]}]
Warnings:
Warning 1105 File pretty format doesn't match the specified pretty value
SELECT Json_File('test/fx.json', 0);
Json_File('test/fx.json', 0)
[{"_id":5,"type":"food","item":"beer","taste":"light","price":5.65,"ratings":[5,8,9]},{"_id":6,"type":"car","item":"roadster","mileage":56000,"ratings":[6,9]},{"_id":7,"type":"food","item":"meat","origin":"argentina","ratings":[2,4]},{"_id":8,"type":"furniture","item":"table","size":{"W":60,"L":80,"H":40},"ratings":[5,8,7]}]
SELECT Json_File('test/fx.json', '[0]');
Json_File('test/fx.json', '[0]')
{"_id":5,"type":"food","item":"beer","taste":"light","price":5.65,"ratings":[5,8,9]}
SELECT Json_File('test/fx.json', '[?]');
Json_File('test/fx.json', '[?]')
NULL
Warnings:
Warning 1105 Invalid function specification ?
SELECT JsonGet_String(Json_File('test/fx.json'), '[1]:*');
JsonGet_String(Json_File('test/fx.json'), '[1]:*')
{"_id":6,"type":"car","item":"roadster","mileage":56000,"ratings":[6,9]}
SELECT JsonGet_String(Json_File('test/fx.json'), '[1]');
JsonGet_String(Json_File('test/fx.json'), '[1]')
6 car roadster 56000 ???
SELECT JsonGet_Int(Json_File('test/fx.json'), '[1]:mileage') AS Mileage;
Mileage
56000
SELECT JsonGet_Real(Json_File('test/fx.json'), '[0]:price', 2) AS Price;
Price
5.65
SELECT Json_Array_Add(Json_File('test/fx.json', '[2]'), 6, 'ratings');
Json_Array_Add(Json_File('test/fx.json', '[2]'), 6, 'ratings')
{"_id":7,"type":"food","item":"meat","origin":"argentina","ratings":[2,4,6]}
SELECT Json_Array_Add(Json_File('test/fx.json', '[2]'), 6, 1, 'ratings');
Json_Array_Add(Json_File('test/fx.json', '[2]'), 6, 1, 'ratings')
{"_id":7,"type":"food","item":"meat","origin":"argentina","ratings":[2,6,4]}
SELECT Json_Array_Add(Json_File('test/fx.json', '[2]'), 6, 'ratings', 1);
Json_Array_Add(Json_File('test/fx.json', '[2]'), 6, 'ratings', 1)
{"_id":7,"type":"food","item":"meat","origin":"argentina","ratings":[2,6,4]}
SELECT Json_Array_Add(Json_File('test/fx.json', '[2]:ratings'), 6, 0);
Json_Array_Add(Json_File('test/fx.json', '[2]:ratings'), 6, 0)
[6,2,4]
SELECT Json_Array_Delete(Json_File('test/fx.json', '[2]'), 'ratings', 1);
Json_Array_Delete(Json_File('test/fx.json', '[2]'), 'ratings', 1)
{"_id":7,"type":"food","item":"meat","origin":"argentina","ratings":[2]}
SELECT Json_Object_Add(Json_File('test/fx.json', '[2]'), 'france' origin);
Json_Object_Add(Json_File('test/fx.json', '[2]'), 'france' origin)
{"_id":7,"type":"food","item":"meat","origin":"france","ratings":[2,4]}
SELECT Json_Object_Add(Json_File('test/fx.json', '[2]'), 70 H, 'size');
Json_Object_Add(Json_File('test/fx.json', '[2]'), 70 H, 'size')
{"_id":7,"type":"food","item":"meat","origin":"argentina","ratings":[2,4]}
Warnings:
Warning 1105 No sub-item at 'size'
SELECT Json_Object_Add(Json_File('test/fx.json', '[3]'), 70 H, 'size');
Json_Object_Add(Json_File('test/fx.json', '[3]'), 70 H, 'size')
{"_id":8,"type":"furniture","item":"table","size":{"W":60,"L":80,"H":70},"ratings":[5,8,7]}
SELECT Json_Object_List(Json_File('test/fx.json', '[3]:size'));
Json_Object_List(Json_File('test/fx.json', '[3]:size'))
["W","L","H"]
DROP TABLE t1; DROP TABLE t1;
DROP FUNCTION Json_Array; DROP TABLE t2;
DROP FUNCTION Json_Array_Add; DROP TABLE t3;
DROP FUNCTION Json_Object;
DROP FUNCTION Json_Object_Nonull;
DROP FUNCTION Json_Value;
DROP FUNCTION Json_Array_Grp;
DROP FUNCTION Json_Object_Grp;
CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=VIR BLOCK_SIZE=3;
#
# Test Jbin UDF's
#
SELECT Json_Array_Add(Jbin_Array(56, 3.1416, 'My name is "Foo"', NULL), n) from t1;
Json_Array_Add(Jbin_Array(56, 3.1416, 'My name is "Foo"', NULL), n)
[56,3.141600,"My name is \"Foo\"",null,1]
[56,3.141600,"My name is \"Foo\"",null,2]
[56,3.141600,"My name is \"Foo\"",null,3]
SELECT Json_Array_Add(Jbin_Array(n, 3.1416, 'My name is "Foo"', NULL), n) from t1;
Json_Array_Add(Jbin_Array(n, 3.1416, 'My name is "Foo"', NULL), n)
[1,3.141600,"My name is \"Foo\"",null,1]
[2,3.141600,"My name is \"Foo\"",null,2]
[3,3.141600,"My name is \"Foo\"",null,3]
SELECT Json_Array_Add(Jbin_Array(56, 3.1416, 'My name is "Foo"', NULL), Jbin_Array('a','b',n)) from t1;
Json_Array_Add(Jbin_Array(56, 3.1416, 'My name is "Foo"', NULL), Jbin_Array('a','b',n))
[56,3.141600,"My name is \"Foo\"",null,["a","b",1]]
[56,3.141600,"My name is \"Foo\"",null,["a","b",2]]
[56,3.141600,"My name is \"Foo\"",null,["a","b",3]]
SELECT Json_Array_Add(Jbin_Array(56, 3.1416, 'My name is "Foo"', NULL), JsonGet_String(Jbin_Array('a','b','c'), '[1]'));
Json_Array_Add(Jbin_Array(56, 3.1416, 'My name is "Foo"', NULL), JsonGet_String(Jbin_Array('a','b','c'), '[1]'))
[56,3.141600,"My name is \"Foo\"",null,"b"]
SELECT Json_Array_Delete(Jbin_Array_Add_Values(Jbin_Array(56, 3.1416, 'My name is "Foo"', NULL), "One more", 2), 4);
Json_Array_Delete(Jbin_Array_Add_Values(Jbin_Array(56, 3.1416, 'My name is "Foo"', NULL), "One more", 2), 4)
[56,3.141600,"My name is \"Foo\"",null,2]
SELECT Json_Array_Delete(Jbin_Array(56, Jbin_Array(3.1416, 'My name is "Foo"'), NULL), '[1]', 1);
Json_Array_Delete(Jbin_Array(56, Jbin_Array(3.1416, 'My name is "Foo"'), NULL), '[1]', 1)
[56,[3.141600],null]
SELECT Json_Array_Delete(Jbin_Array(56, Jbin_Array(3.1416, 'My name is "Foo"'), TRUE), 1, '[1]');
Json_Array_Delete(Jbin_Array(56, Jbin_Array(3.1416, 'My name is "Foo"'), TRUE), 1, '[1]')
[56,[3.141600],true]
SELECT Json_Array(1, TRUE, 0, FALSE);
Json_Array(1, TRUE, 0, FALSE)
[1,true,0,false]
SELECT Json_Serialize(Jbin_Array(TRUE, FALSE));
Json_Serialize(Jbin_Array(TRUE, FALSE))
[true,false]
SELECT Json_Object_Key('qty', 56, 'price', 3.1416, 'truc', 'machin', 'garanty', NULL);
Json_Object_Key('qty', 56, 'price', 3.1416, 'truc', 'machin', 'garanty', NULL)
{"qty":56,"price":3.141600,"truc":"machin","garanty":null}
SELECT Json_Serialize(Jbin_Object_Key('qty', 56, 'price', 3.1416, 'truc', 'machin', 'garanty', NULL));
Json_Serialize(Jbin_Object_Key('qty', 56, 'price', 3.1416, 'truc', 'machin', 'garanty', NULL))
{"qty":56,"price":3.141600,"truc":"machin","garanty":null}
SELECT Jbin_Object_Key('qty', 56, 'price', 3.1416, 'truc', 'machin', 'garanty');
ERROR HY000: Can't initialize function 'jbin_object_key'; This function must have an even number of arguments
SELECT Json_Object_Add(Jbin_Object(56 qty, 3.1416 price, 'machin' truc, NULL garanty), 'blue' color);
Json_Object_Add(Jbin_Object(56 qty, 3.1416 price, 'machin' truc, NULL garanty), 'blue' color)
{"qty":56,"price":3.141600,"truc":"machin","garanty":null,"color":"blue"}
SELECT Json_Object_Add(Jbin_Object(56 qty, 3.1416 price, 'machin' truc, NULL garanty), 45.99 price);
Json_Object_Add(Jbin_Object(56 qty, 3.1416 price, 'machin' truc, NULL garanty), 45.99 price)
{"qty":56,"price":45.990000,"truc":"machin","garanty":null}
SELECT Json_Object_Add(Jbin_Object_Nonull(56 qty, 3.1416 price, 'machin' truc, NULL garanty), 'blue' color);
Json_Object_Add(Jbin_Object_Nonull(56 qty, 3.1416 price, 'machin' truc, NULL garanty), 'blue' color)
{"qty":56,"price":3.141600,"truc":"machin","color":"blue"}
SELECT Json_Object_Add(Jbin_Object_Nonull(56 qty, 3.1416 price, 'machin' truc, NULL garanty), 45.99 price);
Json_Object_Add(Jbin_Object_Nonull(56 qty, 3.1416 price, 'machin' truc, NULL garanty), 45.99 price)
{"qty":56,"price":45.990000,"truc":"machin"}
#
# Test Jbin file UDF's
#
SELECT Json_Serialize(Jbin_File('gloss.json'));
Json_Serialize(Jbin_File('gloss.json'))
{"glossary":{"title":"example glossary","GlossDiv":{"title":"S","GlossList":{"GlossEntry":{"ID":"SGML","SortAs":"SGML","GlossTerm":"Standard Generalized Markup Language","Acronym":"SGML","Abbrev":"ISO 8879:1986","GlossDef":{"para":"A meta-markup language, used to create markup languages such as DocBook.","GlossSeeAlso":["GML","XML"]},"GlossSee":"markup"}}}}}
SELECT JsonLocate(Jbin_File('gloss.json'),'XML');
JsonLocate(Jbin_File('gloss.json'),'XML')
glossary:GlossDiv:GlossList:GlossEntry:GlossDef:GlossSeeAlso:[1]
SELECT Json_Object_Key('first', 'foo', 'second', Jbin_Array('a', 33));
Json_Object_Key('first', 'foo', 'second', Jbin_Array('a', 33))
{"first":"foo","second":["a",33]}
SELECT Json_Get_Item(Json_Array('a','b','c'), '[1]');
Json_Get_Item(Json_Array('a','b','c'), '[1]')
NULL
SELECT Json_Get_Item(Json_Object('foo' AS "first", Json_Array('a', 33) AS "json_second"), 'second') AS "item";
item
["a",33]
SELECT Json_Get_Item(Jbin_Object('foo' first, Jbin_Array('a', 33) jbin_second), 'second:*') item;
item
["a",33]
SELECT Json_Get_Item(Jbin_File('gloss.json'),'glossary:GlossDiv');
Json_Get_Item(Jbin_File('gloss.json'),'glossary:GlossDiv')
{"title":"S","GlossList":{"GlossEntry":{"ID":"SGML","SortAs":"SGML","GlossTerm":"Standard Generalized Markup Language","Acronym":"SGML","Abbrev":"ISO 8879:1986","GlossDef":{"para":"A meta-markup language, used to create markup languages such as DocBook.","GlossSeeAlso":["GML","XML"]},"GlossSee":"markup"}}}
SELECT Json_Serialize(Jbin_Get_Item(Jbin_File('gloss.json'),'glossary:GlossDiv'));
Json_Serialize(Jbin_Get_Item(Jbin_File('gloss.json'),'glossary:GlossDiv'))
{"title":"S","GlossList":{"GlossEntry":{"ID":"SGML","SortAs":"SGML","GlossTerm":"Standard Generalized Markup Language","Acronym":"SGML","Abbrev":"ISO 8879:1986","GlossDef":{"para":"A meta-markup language, used to create markup languages such as DocBook.","GlossSeeAlso":["GML","XML"]},"GlossSee":"markup"}}}
SELECT Json_Get_Item(Jbin_File('gloss.json'),'glossary:GlossDiv:*');
Json_Get_Item(Jbin_File('gloss.json'),'glossary:GlossDiv:*')
{"title":"S","GlossList":{"GlossEntry":{"ID":"SGML","SortAs":"SGML","GlossTerm":"Standard Generalized Markup Language","Acronym":"SGML","Abbrev":"ISO 8879:1986","GlossDef":{"para":"A meta-markup language, used to create markup languages such as DocBook.","GlossSeeAlso":["GML","XML"]},"GlossSee":"markup"}}}
SELECT JsonGet_String(Json_File('gloss.json'),'glossary:GlossDiv:GlossList:GlossEntry:GlossDef:GlossSeeAlso') lang;
lang
GML
SELECT Json_Get_Item(Jbin_File('gloss.json'),'glossary:GlossDiv:GlossList:GlossEntry:GlossDef:GlossSeeAlso') "See also";
See also
["GML","XML"]
SELECT Json_Serialize(Jbin_Get_Item(Jbin_File('gloss.json'),'glossary:GlossDiv:GlossList:GlossEntry:GlossDef:GlossSeeAlso')) "See also";
See also
["GML","XML"]
SELECT JsonGet_String(Json_Get_Item(Json_File('gloss.json'),'glossary:GlossDiv:GlossList:GlossEntry:GlossDef:GlossSeeAlso'),'[0]') lang;
lang
GML
#
# Test Item Get/Set/Insert/Update UDF's
#
SELECT Json_Get_Item(Json_Array(1, 2, Json_Object_Key('trois', 3, 'quatre', 4)), '[]');
Json_Get_Item(Json_Array(1, 2, Json_Object_Key('trois', 3, 'quatre', 4)), '[]')
[1,2,{"trois":3,"quatre":4}]
SELECT Json_Get_Item(Jbin_Array(1, 2, Json_Object_Key('trois', 3, 'quatre', 4)), '[1]');
Json_Get_Item(Jbin_Array(1, 2, Json_Object_Key('trois', 3, 'quatre', 4)), '[1]')
NULL
SELECT Json_Get_Item(Jbin_Array(1, 2, Jbin_Object_Key('trois', 3, 'quatre', 4)), '[1]');
Json_Get_Item(Jbin_Array(1, 2, Jbin_Object_Key('trois', 3, 'quatre', 4)), '[1]')
NULL
SELECT Json_Set_Item(Json_Array(1, 2, Json_Object_Key('trois', 3, 'quatre', 4)));
Json_Set_Item(Json_Array(1, 2, Json_Object_Key('trois', 3, 'quatre', 4)))
[1,2,{"trois":3,"quatre":4}]
SELECT Json_Set_Item(Jbin_Array(1, 2, Jbin_Object_Key('trois', 3, 'quatre', 4)), 'foo');
ERROR HY000: Can't initialize function 'json_set_item'; This function must have an odd number of arguments
SELECT Json_Set_Item(Jbin_Array(1, 2, Jbin_Object_Key('trois', 3, 'quatre', 4)), 5, '[2]:cinq');
Json_Set_Item(Jbin_Array(1, 2, Jbin_Object_Key('trois', 3, 'quatre', 4)), 5, '[2]:cinq')
[1,2,{"trois":3,"quatre":4,"cinq":5}]
SELECT Json_Set_Item(Jbin_Array(1, 2, Jbin_Object_Key('trois', 3, 'quatre', 4)), 7, '[1]');
Json_Set_Item(Jbin_Array(1, 2, Jbin_Object_Key('trois', 3, 'quatre', 4)), 7, '[1]')
[1,7,{"trois":3,"quatre":4}]
SELECT Json_Set_Item(Jbin_Array(1, 2, Jbin_Object_Key('trois', 3, 'quatre', 4)), 5, '[2]:cinq', 7, '[1]');
Json_Set_Item(Jbin_Array(1, 2, Jbin_Object_Key('trois', 3, 'quatre', 4)), 5, '[2]:cinq', 7, '[1]')
[1,7,{"trois":3,"quatre":4,"cinq":5}]
SELECT Json_Set_Item(Jbin_Array(1, 2, Jbin_Object_Key('trois', 3, 'quatre', 4)), Json_Array(7, 8, 9), '[1]');
Json_Set_Item(Jbin_Array(1, 2, Jbin_Object_Key('trois', 3, 'quatre', 4)), Json_Array(7, 8, 9), '[1]')
[1,[7,8,9],{"trois":3,"quatre":4}]
SELECT Json_Set_Item(Jbin_Array(1, 2, Jbin_Object_Key('trois', 3, 'quatre', 4)), Jbin_Array(7, 8, 9), '[2]');
Json_Set_Item(Jbin_Array(1, 2, Jbin_Object_Key('trois', 3, 'quatre', 4)), Jbin_Array(7, 8, 9), '[2]')
[1,2,[7,8,9]]
SELECT Json_Set_Item(Jbin_Array(1, 2, Jbin_Object_Key('trois', 3, 'quatre', 4)), Jbin_Array(7, 8, 9), '[2]:*');
Json_Set_Item(Jbin_Array(1, 2, Jbin_Object_Key('trois', 3, 'quatre', 4)), Jbin_Array(7, 8, 9), '[2]:*')
[1,2,{"trois":3,"quatre":4}]
Warnings:
Warning 1105 Invalid specification * in a write path
SELECT Json_Set_Item(Jbin_Array(1, 2, Jbin_Object_Key('trois', 3, 'quatre', 4)), 3.1416, 'foo');
Json_Set_Item(Jbin_Array(1, 2, Jbin_Object_Key('trois', 3, 'quatre', 4)), 3.1416, 'foo')
[1,2,{"trois":3,"quatre":4}]
SELECT Json_Set_Item(Jbin_Array(1, Jbin_Array(7, 8, 9), Jbin_Object_Key('trois', 3, 'quatre', 4)), 'toto', '[1]:[2]');
Json_Set_Item(Jbin_Array(1, Jbin_Array(7, 8, 9), Jbin_Object_Key('trois', 3, 'quatre', 4)), 'toto', '[1]:[2]')
[1,[7,8,"toto"],{"trois":3,"quatre":4}]
SELECT Json_Set_Item(Jbin_Array(1, Jbin_Array(7, 8, 9), Jbin_Object_Key('trois', 3, 'quatre', 4)), 300, '[2]:nxt:total:[]');
Json_Set_Item(Jbin_Array(1, Jbin_Array(7, 8, 9), Jbin_Object_Key('trois', 3, 'quatre', 4)), 300, '[2]:nxt:total:[]')
[1,[7,8,9],{"trois":3,"quatre":4,"nxt":{"total":[300]}}]
SELECT Json_Set_Item(Jbin_Array(1, Jbin_Array(7, 8, 9), Jbin_Object_Key('trois', 3, 'quatre', 4)), 5, '[2]:cinq', 10, '[1]:[]', 300, '[2]:nxt:total:[]');
Json_Set_Item(Jbin_Array(1, Jbin_Array(7, 8, 9), Jbin_Object_Key('trois', 3, 'quatre', 4)), 5, '[2]:cinq', 10, '[1]:[]', 300, '[2]:nxt:total:[]')
[1,[7,8,9,10],{"trois":3,"quatre":4,"cinq":5,"nxt":{"total":[300]}}]
SELECT Json_Set_Item(Jbin_Array(1, 2, Jbin_Object_Key('trois', 3, 'quatre', 4)), Jbin_Array(7, 8, 9), '[1]', 5, '[2]:cinq', 10, '[1]:[]');
Json_Set_Item(Jbin_Array(1, 2, Jbin_Object_Key('trois', 3, 'quatre', 4)), Jbin_Array(7, 8, 9), '[1]', 5, '[2]:cinq', 10, '[1]:[]')
[1,[7,8,9,10],{"trois":3,"quatre":4,"cinq":5}]
SELECT Json_Set_Item(Jbin_Array(1, 2, Jbin_Object_Key('trois', 3, 'quatre', 4)), 44, '[2]:quatre');
Json_Set_Item(Jbin_Array(1, 2, Jbin_Object_Key('trois', 3, 'quatre', 4)), 44, '[2]:quatre')
[1,2,{"trois":3,"quatre":44}]
SELECT Json_Set_Item(Jbin_Array(1, 2, Jbin_Object_Key('trois', 3, 'quatre', 4)), 5, 'truc');
Json_Set_Item(Jbin_Array(1, 2, Jbin_Object_Key('trois', 3, 'quatre', 4)), 5, 'truc')
[1,2,{"trois":3,"quatre":4}]
SELECT Json_Set_Item(Jbin_Array(1, 2, Jbin_Object_Key('trois', 3, 'quatre', 4)), 5, '');
Json_Set_Item(Jbin_Array(1, 2, Jbin_Object_Key('trois', 3, 'quatre', 4)), 5, '')
[1,2,{"trois":3,"quatre":4},5]
SELECT Json_Set_Item(Jbin_Array(1, 2, Jbin_Object_Key('trois', 3, 'quatre', 4)), 5, '*');
Json_Set_Item(Jbin_Array(1, 2, Jbin_Object_Key('trois', 3, 'quatre', 4)), 5, '*')
[1,2,{"trois":3,"quatre":4}]
Warnings:
Warning 1105 Invalid specification * in a write path
SELECT Json_Serialize(Jbin_Set_Item(Json_Array(1, 2, Json_Object_Key('trois', 3, 'quatre', 4)), 5, '[2]:cinq'));
Json_Serialize(Jbin_Set_Item(Json_Array(1, 2, Json_Object_Key('trois', 3, 'quatre', 4)), 5, '[2]:cinq'))
[1,2,{"trois":3,"quatre":4,"cinq":5}]
SELECT Json_Insert_Item(Json_Array(1, 2, Json_Object_Key('trois', 3, 'quatre', 4)), 5, '[2]:cinq');
Json_Insert_Item(Json_Array(1, 2, Json_Object_Key('trois', 3, 'quatre', 4)), 5, '[2]:cinq')
[1,2,{"trois":3,"quatre":4,"cinq":5}]
SELECT Json_Update_Item(Json_Array(1, 2, Json_Object_Key('trois', 3, 'quatre', 4)), 5, '[2]:cinq');
Json_Update_Item(Json_Array(1, 2, Json_Object_Key('trois', 3, 'quatre', 4)), 5, '[2]:cinq')
[1,2,{"trois":3,"quatre":4}]
SELECT Json_Insert_Item(Jbin_Array(1, Jbin_Array(7, 8, 9), Jbin_Object_Key('trois', 3, 'quatre', 4)), 5, '[2]:cinq', 10, '[1]:[]', 44, '[2]:quatre');
Json_Insert_Item(Jbin_Array(1, Jbin_Array(7, 8, 9), Jbin_Object_Key('trois', 3, 'quatre', 4)), 5, '[2]:cinq', 10, '[1]:[]', 44, '[2]:quatre')
[1,[7,8,9,10],{"trois":3,"quatre":4,"cinq":5}]
SELECT Json_Update_Item(Jbin_Array(1, Jbin_Array(7, 8, 9), Jbin_Object_Key('trois', 3, 'quatre', 4)), 5, '[2]:cinq', 10, '[1]:[]', 44, '[2]:quatre');
Json_Update_Item(Jbin_Array(1, Jbin_Array(7, 8, 9), Jbin_Object_Key('trois', 3, 'quatre', 4)), 5, '[2]:cinq', 10, '[1]:[]', 44, '[2]:quatre')
[1,[7,8,9],{"trois":3,"quatre":44}]
SELECT Json_Insert_Item(Json_Array(1, Json_Array(7, 8, 9), Json_Object_Key('trois', 3, 'quatre', 4)), 5, '[2]:cinq', 10, '[1]:[1]', 300, '[2]:nxt:total:[]');
Json_Insert_Item(Json_Array(1, Json_Array(7, 8, 9), Json_Object_Key('trois', 3, 'quatre', 4)), 5, '[2]:cinq', 10, '[1]:[1]', 300, '[2]:nxt:total:[]')
[1,[7,8,9],{"trois":3,"quatre":4,"cinq":5,"nxt":{"total":[300]}}]
SELECT Json_Update_Item(Json_Array(1, Json_Array(7, 8, 9), Json_Object_Key('trois', 3, 'quatre', 4)), 5, '[2]:cinq', 10, '[1]:[1]', 300, '[2]:nxt:total:[]');
Json_Update_Item(Json_Array(1, Json_Array(7, 8, 9), Json_Object_Key('trois', 3, 'quatre', 4)), 5, '[2]:cinq', 10, '[1]:[1]', 300, '[2]:nxt:total:[]')
[1,[7,10,9],{"trois":3,"quatre":4}]
SELECT Json_Insert_Item(Json_Array(1, 2, Json_Object_Key('trois', 3, 'quatre', 4)), 5, '[]');
Json_Insert_Item(Json_Array(1, 2, Json_Object_Key('trois', 3, 'quatre', 4)), 5, '[]')
[1,2,{"trois":3,"quatre":4},5]
SELECT Json_Update_Item(Json_Array(1, 2, Json_Object_Key('trois', 3, 'quatre', 4)), 5, '[]');
Json_Update_Item(Json_Array(1, 2, Json_Object_Key('trois', 3, 'quatre', 4)), 5, '[]')
[1,2,{"trois":3,"quatre":4}]
#
# Test merging items UDF's
#
SELECT Json_Item_Merge(Jbin_Array('a','b','c'), Jbin_Array('d','e','f'));
Json_Item_Merge(Jbin_Array('a','b','c'), Jbin_Array('d','e','f'))
["a","b","c","d","e","f"]
SELECT Json_Item_Merge(Json_Array('a','b','c'), Json_Array('d','e','f')) AS "Result";
Result
["a","b","c","d","e","f"]
SELECT Json_Array_Add(Jbin_Item_Merge(Jbin_Array('a','b','c'), Jbin_Array('d','e','f')), 'and', 3);
Json_Array_Add(Jbin_Item_Merge(Jbin_Array('a','b','c'), Jbin_Array('d','e','f')), 'and', 3)
["a","b","c","and","d","e","f"]
SELECT Json_Item_Merge(Jbin_Object(1 "a",2 "b",3 "c"), Jbin_Object(4 "d",5 "e",6 "f"));
Json_Item_Merge(Jbin_Object(1 "a",2 "b",3 "c"), Jbin_Object(4 "d",5 "e",6 "f"))
{"a":1,"b":2,"c":3,"d":4,"e":5,"f":6}
SELECT Json_Item_Merge(Jbin_Object(1 "a",2 "b",2 "c"), Jbin_Array('d','e','f'));
Json_Item_Merge(Jbin_Object(1 "a",2 "b",2 "c"), Jbin_Array('d','e','f'))
Binary Json object
Warnings:
Warning 1105 Second argument is not an object
SELECT Json_Object_Add(Jbin_Item_Merge(Jbin_Object(1 "a",2 "b",3 "c"), Jbin_Object(4 "d",5 "e",6 "f")), 'x' AS "and");
Json_Object_Add(Jbin_Item_Merge(Jbin_Object(1 "a",2 "b",3 "c"), Jbin_Object(4 "d",5 "e",6 "f")), 'x' AS "and")
{"a":1,"b":2,"c":3,"d":4,"e":5,"f":6,"and":"x"}
SELECT Json_Item_Merge(Jbin_Object(1 "a",2 "b",3 "c"), Jbin_Object(4 "a",5 "e",6 "f"));
Json_Item_Merge(Jbin_Object(1 "a",2 "b",3 "c"), Jbin_Object(4 "a",5 "e",6 "f"))
{"a":4,"b":2,"c":3,"e":5,"f":6}
SELECT Json_Item_Merge('foo', Json_Array('d','e','f'));
ERROR HY000: Can't initialize function 'json_item_merge'; First argument must be a json item
#
# Test making file UDF's
#
SELECT Jfile_Make(Jbin_Array('a','b','c'), 'bt1.json');
Jfile_Make(Jbin_Array('a','b','c'), 'bt1.json')
bt1.json
SELECT Json_File('bt1.json');
Json_File('bt1.json')
[
"a",
"b",
"c"
]
SELECT Json_File(Jfile_Make(Jbin_File('bt1.json'), 0));
Json_File(Jfile_Make(Jbin_File('bt1.json'), 0))
"a"
"b"
"c"
SELECT Json_File(Jfile_Make(Jbin_File('bt1.json'), 1));
Json_File(Jfile_Make(Jbin_File('bt1.json'), 1))
[
"a",
"b",
"c"
]
SELECT Json_File(Jfile_Make(Jbin_File('bt1.json'), 2));
Json_File(Jfile_Make(Jbin_File('bt1.json'), 2))
[
"a",
"b",
"c"
]
SELECT Json_File('bt1.json', 0);
Json_File('bt1.json', 0)
["a","b","c"]
Warnings:
Warning 1105 File pretty format doesn't match the specified pretty value
SELECT Json_File('bt1.json', 1);
Json_File('bt1.json', 1)
["a","b","c"]
Warnings:
Warning 1105 File pretty format doesn't match the specified pretty value
SELECT Json_File('bt1.json', 2);
Json_File('bt1.json', 2)
["a","b","c"]
SELECT Json_Serialize(Jbin_Array('a','b','c'));
Json_Serialize(Jbin_Array('a','b','c'))
["a","b","c"]
SELECT Json_Serialize(Jbin_Array_Add(Jbin_File('not_exist.json'), 'd'));
Json_Serialize(Jbin_Array_Add(Jbin_File('not_exist.json'), 'd'))
Null json tree
Warnings:
Warning 1105 Open(map) error 2 on not_exist.json
Warning 1105 First argument is not an array
# This does not modify the file
SELECT Json_Serialize(Jbin_Array_Add(Jbin_File('bt1.json'), 'd'));
Json_Serialize(Jbin_Array_Add(Jbin_File('bt1.json'), 'd'))
["a","b","c","d"]
SELECT Json_File('bt1.json', 2);
Json_File('bt1.json', 2)
["a","b","c"]
# This does modify the file
SELECT Json_Array_Add(Jbin_File('bt1.json'), 'd');
Json_Array_Add(Jbin_File('bt1.json'), 'd')
bt1.json
SELECT Json_File('bt1.json', 2);
Json_File('bt1.json', 2)
["a","b","c","d"]
# Back to the original file
SELECT Jfile_Make(Jbin_Array('a','b','c'), 'bt1.json');
Jfile_Make(Jbin_Array('a','b','c'), 'bt1.json')
bt1.json
SELECT Json_Object(Jbin_Array_Add(Jbin_Array('a','b','c'), 'd') "Jbin_foo") AS "Result";
Result
{"foo":["a","b","c","d"]}
SELECT Json_Object(Jbin_Array_Add(Jbin_File('bt1.json'), 'd')) AS "Result";
Result
{"Array_Add(Jbin_File('bt1.json'), 'd')":["a","b","c","d"]}
SELECT Json_Object(Jbin_Array_Add(Jbin_File('bt1.json'), 'd') "Jbin_bt1") AS "Result";
Result
{"bt1":["a","b","c","d"]}
# This does modify the file
SELECT Json_Object(Json_Array_Add(Jbin_File('bt1.json'), 'd') "Jfile_bt1") AS "Result";
Result
{"bt1":["a","b","c","d"]}
SELECT Json_File('bt1.json');
Json_File('bt1.json')
[
"a",
"b",
"c",
"d"
]
SELECT Json_File(Json_Array_Delete(Jbin_File('bt1.json'), 3), 2);
Json_File(Json_Array_Delete(Jbin_File('bt1.json'), 3), 2)
["a","b","c"]
SELECT Json_Object(Jbin_Array_Add(Jbin_File('bt1.json'), 'd') "Jbin_bt1", n "t1") AS "Result" from t1;
Result
{"bt1":["a","b","c","d"],"t1":1}
{"bt1":["a","b","c","d"],"t1":2}
{"bt1":["a","b","c","d"],"t1":3}
SELECT Json_File(Json_Array_Add(Jbin_Array_Add(Jbin_File('bt1.json'), 'd'), 'e')) AS "Result";
Result
[
"a",
"b",
"c",
"d",
"e"
]
SELECT Jfile_Make(Jbin_Array('a','b','c'), 'bt1.json');
Jfile_Make(Jbin_Array('a','b','c'), 'bt1.json')
bt1.json
SELECT Json_File(Json_Array_Add(Jbin_Array_Add(Jbin_File('bt1.json'), 'd'), 'e')) AS "Result" from t1;
Result
[
"a",
"b",
"c",
"d",
"e"
]
[
"a",
"b",
"c",
"d",
"e"
]
[
"a",
"b",
"c",
"d",
"e"
]
SELECT Jfile_Make(Jbin_Array('a','b','c'), 'bt1.json');
Jfile_Make(Jbin_Array('a','b','c'), 'bt1.json')
bt1.json
SELECT Json_Array_Add(Jbin_Array_Add(Jbin_File('bt1.json'), 'd'), n) AS "Result" from t1;
Result
bt1.json
bt1.json
bt1.json
# Show modified file
SELECT Json_File('bt1.json');
Json_File('bt1.json')
[
"a",
"b",
"c",
"d",
1,
"d",
2,
"d",
3
]
SELECT Jfile_Make(Jbin_Array('a','b','c'), 'bt1.json');
Jfile_Make(Jbin_Array('a','b','c'), 'bt1.json')
bt1.json
SELECT Json_Array_Add(Jbin_File('bt1.json'), n) AS "Result" from t1;
Result
bt1.json
bt1.json
bt1.json
# Show modified file
SELECT Json_File('bt1.json');
Json_File('bt1.json')
[
"a",
"b",
"c",
1,
2,
3
]
SELECT Jfile_Make(Jbin_Array('a','b','c'), 'bt1.json');
Jfile_Make(Jbin_Array('a','b','c'), 'bt1.json')
bt1.json
SELECT Json_File(Jbin_Item_Merge(Jbin_File('bt1.json'), Jbin_Array('d','e','f')));
Json_File(Jbin_Item_Merge(Jbin_File('bt1.json'), Jbin_Array('d','e','f')))
[
"a",
"b",
"c"
]
SELECT Json_File(Json_Item_Merge(Jbin_File('bt1.json'), Jbin_Array('d','e','f')));
Json_File(Json_Item_Merge(Jbin_File('bt1.json'), Jbin_Array('d','e','f')))
[
"a",
"b",
"c",
"d",
"e",
"f"
]
SELECT Jfile_Make(Jbin_Array('a','b','c'), 'bt1.json');
Jfile_Make(Jbin_Array('a','b','c'), 'bt1.json')
bt1.json
# Test DELETE from file
SELECT Json_Object(Jbin_Array_Delete(Jbin_File('bt1.json'), 1)) AS "Result";
Result
{"Array_Delete(Jbin_File('bt1.json'), 1)":["a","c"]}
SELECT Json_Object(Jbin_Array_Delete(Jbin_File('bt1.json'), 2) "Jbin_bt1") AS "Result";
Result
{"bt1":["a","b"]}
SELECT Json_Object(Jbin_Array_Delete(Jbin_File('bt1.json'), 0) "Jbin_bt1", n "t1") AS "Result" from t1;
Result
{"bt1":["b","c"],"t1":1}
{"bt1":["b","c"],"t1":2}
{"bt1":["b","c"],"t1":3}
SELECT Json_Object(Jbin_Array_Delete(Jbin_File('bt1.json'), 3 - n) "Jbin_bt1") AS "Result" from t1;
Result
{"bt1":["a","b"]}
{"bt1":["a"]}
{"bt1":[]}
SELECT Json_Object(Json_Array_Delete(Jbin_File('bt1.json'), 3 - n) "Jbin_bt1") AS "Result" from t1;
Result
{"bt1":["a","b"]}
{"bt1":["a"]}
{"bt1":[]}
# Show modified file
SELECT Json_File('bt1.json');
Json_File('bt1.json')
[
]
# Object file
SELECT Jfile_Make(Jbin_Object(1 "a", 2 "b", 3 "c"), 'bt2.json', 0);
Jfile_Make(Jbin_Object(1 "a", 2 "b", 3 "c"), 'bt2.json', 0)
bt2.json
SELECT Json_File('bt2.json', 0);
Json_File('bt2.json', 0)
{"a":1,"b":2,"c":3}
SELECT Json_File('bt2.json');
Json_File('bt2.json')
{"a":1,"b":2,"c":3}
SELECT Json_Serialize(Jbin_Object_Add(Jbin_File('bt2.json'), 4 "d"));
Json_Serialize(Jbin_Object_Add(Jbin_File('bt2.json'), 4 "d"))
{"a":1,"b":2,"c":3,"d":4}
# First query (file not modified)
SELECT Json_Object(Jbin_Object_Add(Jbin_File('bt2.json'), 4 AS "d") AS "Jbin_new") AS "Result";
Result
{"new":{"a":1,"b":2,"c":3,"d":4}}
# First query (file modified)
SELECT Json_Object(Json_Object_Add(Jbin_File('bt2.json'), 4 AS "d") AS "Jfile_new") AS "Result";
Result
{"new":{"a":1,"b":2,"c":3,"d":4}}
SELECT Jfile_Make(Jbin_Object(1 "a", 2 "b", 3 "c"), 'bt2.json', 0);
Jfile_Make(Jbin_Object(1 "a", 2 "b", 3 "c"), 'bt2.json', 0)
bt2.json
SELECT Json_Object(Jbin_Object_Add(Jbin_File('bt2.json'), 4 "d") "Jbin_new", n "t1") AS "Result" from t1;
Result
{"new":{"a":1,"b":2,"c":3,"d":4},"t1":1}
{"new":{"a":1,"b":2,"c":3,"d":4},"t1":2}
{"new":{"a":1,"b":2,"c":3,"d":4},"t1":3}
SELECT Json_File(Json_Object_Add(Jbin_Object_Add(Jbin_File('bt2.json'), 4 "d"), 5 "e")) AS "Result";
Result
{"a":1,"b":2,"c":3,"d":4,"e":5}
SELECT Json_Object_Add(Jbin_Object_Add(Jbin_File('bt2.json'), 4 "d"), 5 "e") AS "Result" from t1;
Result
bt2.json
bt2.json
bt2.json
SELECT Json_Object_Add(Jbin_Object_Add(Jbin_File('bt2.json'), 4 "d"), n "n") AS "Result" from t1;
Result
bt2.json
bt2.json
bt2.json
SELECT Jfile_Make(Jbin_Object(1 "a", 2 "b", 3 "c"), 'bt2.json', 0);
Jfile_Make(Jbin_Object(1 "a", 2 "b", 3 "c"), 'bt2.json', 0)
bt2.json
SELECT Json_Object_Add(Jbin_File('bt2.json'), n) AS "Result" from t1;
Result
bt2.json
bt2.json
bt2.json
SELECT Json_File('bt2.json');
Json_File('bt2.json')
{"a":1,"b":2,"c":3,"n":3}
SELECT Jfile_Make(Jbin_Object(1 "a", 2 "b", 3 "c"), 'bt2.json', 0);
Jfile_Make(Jbin_Object(1 "a", 2 "b", 3 "c"), 'bt2.json', 0)
bt2.json
SELECT Json_Serialize(Jbin_Item_Merge(Jbin_File('bt2.json'), Jbin_Object(4 "d",5 "e",6 "f"))) AS "Result";
Result
{"a":1,"b":2,"c":3,"d":4,"e":5,"f":6}
SELECT Json_File(Json_Item_Merge(Jbin_File('bt2.json'), Jbin_Object(4 "d",5 "e",6 "f"))) AS "Result";
Result
{"a":1,"b":2,"c":3,"d":4,"e":5,"f":6}
SELECT Json_Item_Merge(Json_Object(1 "a", 2 "b", 3 "c"), Json_Object(4 "d",5 "b",6 "f")) AS "Result";
Result
{"a":1,"b":5,"c":3,"d":4,"f":6}
SELECT Json_Object(Json_Object_Delete(Jbin_File('bt2.json'), 'b')) AS "Result";
Result
{"Object_Delete(Jbin_File('bt2.json'), 'b')":{"a":1,"c":3,"d":4,"e":5,"f":6}}
SELECT Json_Object(Jbin_Object_Delete(Jbin_File('bt2.json'), 'c') "Jbin_bt1") AS "Result";
Result
{"bt1":{"a":1,"d":4,"e":5,"f":6}}
SELECT Json_Object(Json_Object_Delete(Jbin_File('bt2.json'), 'c') "Jbin_bt1") AS "Result";
Result
{"bt1":{"a":1,"d":4,"e":5,"f":6}}
SELECT Json_Object(Json_Object_Delete(Jbin_File('bt2.json'), 'c') "Jfile_bt1") AS "Result";
Result
{"bt1":{"a":1,"d":4,"e":5,"f":6}}
SELECT Json_Object(Json_Object_Delete(Jbin_File('bt2.json'), 'a') "Jbin_bt1", n "t1") AS "Result" from t1;
Result
{"bt1":{"d":4,"e":5,"f":6},"t1":1}
{"bt1":{"d":4,"e":5,"f":6},"t1":2}
{"bt1":{"d":4,"e":5,"f":6},"t1":3}
SELECT Json_Serialize(Jbin_Object_List(Jbin_File('bt2.json'))) "Key list";
Key list
["d","e","f"]
SELECT Jfile_Make('{"a":1, "b":[44, 55]}' json_, 'bt3.json', 0);
Jfile_Make('{"a":1, "b":[44, 55]}' json_, 'bt3.json', 0)
bt3.json
SELECT Json_Array_Add(Json_File('bt3.json', 'b'), 66);
Json_Array_Add(Json_File('bt3.json', 'b'), 66)
[44,55,66]
SELECT Json_Array_Add(Json_File('bt3.json'), 66, 'b');
Json_Array_Add(Json_File('bt3.json'), 66, 'b')
{"a":1,"b":[44,55,66]}
SELECT Json_Array_Add(Jbin_File('bt3.json', 'b'), 66);
Json_Array_Add(Jbin_File('bt3.json', 'b'), 66)
bt3.json
SELECT Json_File('bt3.json', 3);
Json_File('bt3.json', 3)
{"a":1,"b":[44,55,66]}
SELECT Jfile_Make('{"a":1, "b":[44, 55]}' json_, 'bt3.json', 0);
Jfile_Make('{"a":1, "b":[44, 55]}' json_, 'bt3.json', 0)
bt3.json
CREATE TABLE t2 (
n INT KEY,
jfile_cols CHAR(12) NOT NULL)
ENGINE= MYISAM;
INSERT INTO t2 VALUES(1,'bt3.json');
# In this table, the jfile_cols column just contains a file name
UPDATE t2 SET jfile_cols = Json_Array_Add(Jbin_File('bt3.json', 'b'), 66) WHERE n = 1;
SELECT JsonGet_String(jfile_cols, '*') FROM t2;
JsonGet_String(jfile_cols, '*')
{"a":1,"b":[44,55,66]}
UPDATE t2 SET jfile_cols = Json_Insert_Item(jfile_cols, 77, 'b:[]') WHERE n = 1;
SELECT JsonGet_String(jfile_cols, 'b:*') FROM t2;
JsonGet_String(jfile_cols, 'b:*')
[44,55,66,77]
UPDATE t2 SET jfile_cols = Json_Insert_Item(Jbin_Insert_Item(jfile_cols, 88, 'b:') , 99, 'b:') WHERE n = 1;
SELECT JsonGet_String(jfile_cols, '*') FROM t2;
JsonGet_String(jfile_cols, '*')
{"a":1,"b":[44,55,66,77,88,99]}
DROP TABLE t1, t2;
# #
# Testing FILE privilege # Testing FILE privilege
# #
set sql_mode="";
GRANT ALL PRIVILEGES ON *.* TO user@localhost; GRANT ALL PRIVILEGES ON *.* TO user@localhost;
REVOKE FILE ON *.* FROM user@localhost; REVOKE FILE ON *.* FROM user@localhost;
set sql_mode=default;
SELECT user(); SELECT user();
user() user()
user@localhost user@localhost
...@@ -40,7 +42,7 @@ ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) ...@@ -40,7 +42,7 @@ ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
SELECT user(); SELECT user();
user() user()
root@localhost root@localhost
CREATE VIEW v1 AS SELECT * FROM t1; CREATE SQL SECURITY INVOKER VIEW v1 AS SELECT * FROM t1;
SELECT user(); SELECT user();
user() user()
user@localhost user@localhost
......
...@@ -49,10 +49,11 @@ ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) ...@@ -49,10 +49,11 @@ ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
CREATE VIEW v1 AS SELECT * FROM t1; CREATE VIEW v1 AS SELECT * FROM t1;
ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
# Testing a VIEW created with FILE privileges but accessed with no FILE # Testing a VIEW created with FILE privileges but accessed with no FILE
# using SQL SECIRITY INVOKER
SELECT user(); SELECT user();
user() user()
root@localhost root@localhost
CREATE VIEW v1 AS SELECT * FROM t1; CREATE SQL SECURITY INVOKER VIEW v1 AS SELECT * FROM t1;
SELECT user(); SELECT user();
user() user()
user@localhost user@localhost
...@@ -64,6 +65,19 @@ UPDATE v1 SET a=123; ...@@ -64,6 +65,19 @@ UPDATE v1 SET a=123;
ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
DELETE FROM v1; DELETE FROM v1;
ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
# Testing a VIEW created with FILE privileges but accessed with no FILE
# using SQL SECIRITY DEFINER
DROP VIEW v1;
SELECT user();
user()
root@localhost
CREATE SQL SECURITY DEFINER VIEW v1 AS SELECT * FROM t1;
SELECT user();
user()
user@localhost
SELECT * FROM v1 WHERE a='test1';
a
test1
SELECT user(); SELECT user();
user() user()
root@localhost root@localhost
......
...@@ -3,6 +3,7 @@ Warning 1105 No file name. Table will use t1.xml ...@@ -3,6 +3,7 @@ Warning 1105 No file name. Table will use t1.xml
# #
# Beginning of grant.inc # Beginning of grant.inc
# #
CREATE USER user@localhost;
GRANT ALL PRIVILEGES ON *.* TO user@localhost; GRANT ALL PRIVILEGES ON *.* TO user@localhost;
REVOKE FILE ON *.* FROM user@localhost; REVOKE FILE ON *.* FROM user@localhost;
SELECT user(); SELECT user();
...@@ -63,7 +64,7 @@ ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) ...@@ -63,7 +64,7 @@ ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
SELECT user(); SELECT user();
user() user()
root@localhost root@localhost
CREATE VIEW v1 AS SELECT * FROM t1; CREATE SQL SECURITY INVOKER VIEW v1 AS SELECT * FROM t1;
SELECT user(); SELECT user();
user() user()
user@localhost user@localhost
......
{"ISBN":"9782212090819","LANG":"fr","SUBJECT":"applications","AUTHOR":[{"FIRSTNAME":"Jean-Michel","LASTNAME":"Bernadac"},{"FIRSTNAME":"Franois","LASTNAME":"Knab"}],"TITLE":"Construire une application XML","PUBLISHER":{"NAME":"Eyrolles","PLACE":"Paris"},"DATEPUB":1999}
{"ISBN":"9782840825685","LANG":"fr","SUBJECT":"applications","AUTHOR":[{"FIRSTNAME":"William J.","LASTNAME":"Pardi"}],"TITLE":"XML en Action","TRANSLATED":{"PREFIX":"adapt de l'anglais par","TRANSLATOR":{"FIRSTNAME":"James","LASTNAME":"Guerin"}},"PUBLISHER":{"NAME":"Microsoft Press","PLACE":"Paris"},"DATEPUB":2001}
...@@ -24,12 +24,10 @@ ...@@ -24,12 +24,10 @@
"ISBN": "9782840825685", "ISBN": "9782840825685",
"LANG": "fr", "LANG": "fr",
"SUBJECT": "applications", "SUBJECT": "applications",
"AUTHOR": [ "AUTHOR": {
{
"FIRSTNAME": "William J.", "FIRSTNAME": "William J.",
"LASTNAME": "Pardi" "LASTNAME": "Pardi"
} },
],
"TITLE": "XML en Action", "TITLE": "XML en Action",
"TRANSLATION": "adapté de l'anglais par", "TRANSLATION": "adapté de l'anglais par",
"TRANSLATOR": { "TRANSLATOR": {
......
{
"glossary": {
"title": "example glossary",
"GlossDiv": {
"title": "S",
"GlossList": {
"GlossEntry": {
"ID": "SGML",
"SortAs": "SGML",
"GlossTerm": "Standard Generalized Markup Language",
"Acronym": "SGML",
"Abbrev": "ISO 8879:1986",
"GlossDef": {
"para": "A meta-markup language, used to create markup languages such as DocBook.",
"GlossSeeAlso": ["GML", "XML"]
},
"GlossSee": "markup"
}
}
}
}
}
...@@ -14,3 +14,15 @@ SELECT id, DAYNAME(dat) FROM t1; ...@@ -14,3 +14,15 @@ SELECT id, DAYNAME(dat) FROM t1;
SELECT id, DAYNAME(datim) FROM t1 LIMIT 1; SELECT id, DAYNAME(datim) FROM t1 LIMIT 1;
SELECT id, TIME(tim) FROM t1 LIMIT 1; SELECT id, TIME(tim) FROM t1 LIMIT 1;
DROP TABLE t1; DROP TABLE t1;
--echo #
--echo # Testing use of dates in where clause (MDEV-8926)
--echo #
CREATE TABLE t1 (col1 DATE) ENGINE=CONNECT TABLE_TYPE=CSV;
INSERT INTO t1 VALUES('2015-01-01'),('2015-02-01'),('2015-03-01'),('2015-04-01');
SELECT * FROM t1 WHERE col1 = '2015-02-01';
SELECT * FROM t1 WHERE col1 > '2015-02-01';
SELECT * FROM t1 WHERE col1 >= '2015-02-01';
SELECT * FROM t1 WHERE col1 < '2015-02-01';
SELECT * FROM t1 WHERE col1 <= '2015-02-01';
DROP TABLE t1;
--echo # --echo #
--echo # Beginning of grant.inc --echo # Beginning of grant.inc
--echo # --echo #
CREATE USER user@localhost;
GRANT ALL PRIVILEGES ON *.* TO user@localhost; GRANT ALL PRIVILEGES ON *.* TO user@localhost;
REVOKE FILE ON *.* FROM user@localhost; REVOKE FILE ON *.* FROM user@localhost;
--connect(user,localhost,user,,) --connect(user,localhost,user,,)
...@@ -53,7 +54,7 @@ CREATE VIEW v1 AS SELECT * FROM t1; ...@@ -53,7 +54,7 @@ CREATE VIEW v1 AS SELECT * FROM t1;
--echo # Testing a VIEW created with FILE privileges but accessed with no FILE --echo # Testing a VIEW created with FILE privileges but accessed with no FILE
--connection default --connection default
SELECT user(); SELECT user();
CREATE VIEW v1 AS SELECT * FROM t1; CREATE SQL SECURITY INVOKER VIEW v1 AS SELECT * FROM t1;
--connection user --connection user
SELECT user(); SELECT user();
--error ER_ACCESS_DENIED_ERROR --error ER_ACCESS_DENIED_ERROR
......
-- source include/not_embedded.inc -- source include/not_embedded.inc
set sql_mode="";
let $MYSQLD_DATADIR= `select @@datadir`; let $MYSQLD_DATADIR= `select @@datadir`;
...@@ -49,7 +50,7 @@ CREATE VIEW v1 AS SELECT * FROM t1; ...@@ -49,7 +50,7 @@ CREATE VIEW v1 AS SELECT * FROM t1;
--echo # Testing a VIEW created with FILE privileges but accessed with no FILE --echo # Testing a VIEW created with FILE privileges but accessed with no FILE
--connection default --connection default
SELECT user(); SELECT user();
CREATE VIEW v1 AS SELECT * FROM t1; CREATE SQL SECURITY INVOKER VIEW v1 AS SELECT * FROM t1;
--connection user --connection user
SELECT user(); SELECT user();
--error ER_ACCESS_DENIED_ERROR --error ER_ACCESS_DENIED_ERROR
...@@ -92,4 +93,4 @@ let $TABLE_OPTIONS=TABLE_TYPE=VEC MAX_ROWS=100; ...@@ -92,4 +93,4 @@ let $TABLE_OPTIONS=TABLE_TYPE=VEC MAX_ROWS=100;
let $FILE_EXT=VEC; let $FILE_EXT=VEC;
--source grant.inc --source grant.inc
set sql_mode=default;
...@@ -5,8 +5,10 @@ let $MYSQLD_DATADIR= `select @@datadir`; ...@@ -5,8 +5,10 @@ let $MYSQLD_DATADIR= `select @@datadir`;
--echo # --echo #
--echo # Checking FILE privileges --echo # Checking FILE privileges
--echo # --echo #
set sql_mode="";
GRANT ALL PRIVILEGES ON *.* TO user@localhost; GRANT ALL PRIVILEGES ON *.* TO user@localhost;
REVOKE FILE ON *.* FROM user@localhost; REVOKE FILE ON *.* FROM user@localhost;
set sql_mode=default;
--connect(user,localhost,user,,) --connect(user,localhost,user,,)
--connection user --connection user
SELECT user(); SELECT user();
...@@ -54,7 +56,7 @@ CREATE VIEW v1 AS SELECT * FROM t1; ...@@ -54,7 +56,7 @@ CREATE VIEW v1 AS SELECT * FROM t1;
--echo # Testing a VIEW created with FILE privileges but accessed with no FILE --echo # Testing a VIEW created with FILE privileges but accessed with no FILE
--connection default --connection default
SELECT user(); SELECT user();
CREATE VIEW v1 AS SELECT * FROM t1; CREATE SQL SECURITY INVOKER VIEW v1 AS SELECT * FROM t1;
--connection user --connection user
SELECT user(); SELECT user();
--error ER_ACCESS_DENIED_ERROR --error ER_ACCESS_DENIED_ERROR
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
let $MYSQLD_DATADIR= `select @@datadir`; let $MYSQLD_DATADIR= `select @@datadir`;
--copy_file $MTR_SUITE_DIR/std_data/biblio.json $MYSQLD_DATADIR/test/biblio.json --copy_file $MTR_SUITE_DIR/std_data/biblio.json $MYSQLD_DATADIR/test/biblio.json
--copy_file $MTR_SUITE_DIR/std_data/bib0.json $MYSQLD_DATADIR/test/bib0.json
--copy_file $MTR_SUITE_DIR/std_data/expense.json $MYSQLD_DATADIR/test/expense.json --copy_file $MTR_SUITE_DIR/std_data/expense.json $MYSQLD_DATADIR/test/expense.json
--copy_file $MTR_SUITE_DIR/std_data/mulexp3.json $MYSQLD_DATADIR/test/mulexp3.json --copy_file $MTR_SUITE_DIR/std_data/mulexp3.json $MYSQLD_DATADIR/test/mulexp3.json
--copy_file $MTR_SUITE_DIR/std_data/mulexp4.json $MYSQLD_DATADIR/test/mulexp4.json --copy_file $MTR_SUITE_DIR/std_data/mulexp4.json $MYSQLD_DATADIR/test/mulexp4.json
...@@ -115,6 +116,33 @@ ENGINE=CONNECT TABLE_TYPE=DOS FILE_NAME='biblio.json'; ...@@ -115,6 +116,33 @@ ENGINE=CONNECT TABLE_TYPE=DOS FILE_NAME='biblio.json';
SELECT * FROM t1; SELECT * FROM t1;
DROP TABLE t1; DROP TABLE t1;
--echo #
--echo # Testing a pretty=0 file
--echo #
CREATE TABLE t1
(
ISBN CHAR(15) NOT NULL,
Language CHAR(2) FIELD_FORMAT='LANG',
Subject CHAR(32) FIELD_FORMAT='SUBJECT',
AuthorFN CHAR(128) FIELD_FORMAT='AUTHOR:[X]:FIRSTNAME',
AuthorLN CHAR(128) FIELD_FORMAT='AUTHOR:[X]:LASTNAME',
Title CHAR(32) FIELD_FORMAT='TITLE',
Translation CHAR(32) FIELD_FORMAT='TRANSLATED:PREFIX',
TranslatorFN CHAR(80) FIELD_FORMAT='TRANSLATED:TRANSLATOR:FIRSTNAME',
TranslatorLN CHAR(80) FIELD_FORMAT='TRANSLATED:TRANSLATOR:LASTNAME',
Publisher CHAR(20) FIELD_FORMAT='PUBLISHER:NAME',
Location CHAR(16) FIELD_FORMAT='PUBLISHER:PLACE',
Year int(4) FIELD_FORMAT='DATEPUB',
INDEX IX(ISBN)
)
ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='bib0.json' LRECL=320 OPTION_LIST='Pretty=0';
SHOW INDEX FROM t1;
SELECT * FROM t1;
DESCRIBE SELECT * FROM t1 WHERE ISBN = '9782212090819';
--error ER_GET_ERRMSG
UPDATE t1 SET AuthorFN = 'Philippe' WHERE ISBN = '9782212090819';
DROP TABLE t1;
--echo # --echo #
--echo # A file with 2 arrays --echo # A file with 2 arrays
--echo # --echo #
...@@ -258,6 +286,8 @@ DROP TABLE t1, t2, t3, t4; ...@@ -258,6 +286,8 @@ DROP TABLE t1, t2, t3, t4;
# Clean up # Clean up
# #
--remove_file $MYSQLD_DATADIR/test/biblio.json --remove_file $MYSQLD_DATADIR/test/biblio.json
--remove_file $MYSQLD_DATADIR/test/bib0.dnx
--remove_file $MYSQLD_DATADIR/test/bib0.json
--remove_file $MYSQLD_DATADIR/test/expense.json --remove_file $MYSQLD_DATADIR/test/expense.json
--remove_file $MYSQLD_DATADIR/test/mulexp3.json --remove_file $MYSQLD_DATADIR/test/mulexp3.json
--remove_file $MYSQLD_DATADIR/test/mulexp4.json --remove_file $MYSQLD_DATADIR/test/mulexp4.json
......
...@@ -9,28 +9,50 @@ if (!$HA_CONNECT_SO) { ...@@ -9,28 +9,50 @@ if (!$HA_CONNECT_SO) {
--skip Needs a dynamically built ha_connect.so --skip Needs a dynamically built ha_connect.so
} }
let $is_win = `select convert(@@version_compile_os using latin1) IN ("Win32","Win64","Windows")`; --eval CREATE FUNCTION json_array RETURNS STRING SONAME '$HA_CONNECT_SO';
--eval CREATE FUNCTION json_array_add RETURNS STRING SONAME '$HA_CONNECT_SO';
--eval CREATE FUNCTION json_array_add_values RETURNS STRING SONAME '$HA_CONNECT_SO';
--eval CREATE FUNCTION json_array_delete RETURNS STRING SONAME '$HA_CONNECT_SO';
--eval CREATE FUNCTION json_object RETURNS STRING SONAME '$HA_CONNECT_SO';
--eval CREATE FUNCTION json_object_nonull RETURNS STRING SONAME '$HA_CONNECT_SO';
--eval CREATE FUNCTION json_object_key RETURNS STRING SONAME '$HA_CONNECT_SO';
--eval CREATE FUNCTION json_object_add RETURNS STRING SONAME '$HA_CONNECT_SO';
--eval CREATE FUNCTION json_object_delete RETURNS STRING SONAME '$HA_CONNECT_SO';
--eval CREATE FUNCTION json_object_list RETURNS STRING SONAME '$HA_CONNECT_SO';
--eval CREATE FUNCTION jsonvalue RETURNS STRING SONAME '$HA_CONNECT_SO';
--eval CREATE AGGREGATE FUNCTION json_array_grp RETURNS STRING SONAME '$HA_CONNECT_SO';
--eval CREATE AGGREGATE FUNCTION json_object_grp RETURNS STRING SONAME '$HA_CONNECT_SO';
--eval CREATE FUNCTION jsonget_string RETURNS STRING SONAME '$HA_CONNECT_SO';
--eval CREATE FUNCTION jsonget_int RETURNS INTEGER SONAME '$HA_CONNECT_SO';
--eval CREATE FUNCTION jsonget_real RETURNS REAL SONAME '$HA_CONNECT_SO';
--eval CREATE FUNCTION jsonlocate RETURNS STRING SONAME '$HA_CONNECT_SO';
--eval CREATE FUNCTION json_locate_all RETURNS STRING SONAME '$HA_CONNECT_SO';
--eval CREATE FUNCTION json_file RETURNS STRING SONAME '$HA_CONNECT_SO';
--eval CREATE FUNCTION jfile_make RETURNS STRING SONAME '$HA_CONNECT_SO';
--eval CREATE FUNCTION jsoncontains RETURNS INTEGER SONAME '$HA_CONNECT_SO';
--eval CREATE FUNCTION jsoncontains_path RETURNS INTEGER SONAME '$HA_CONNECT_SO';
--eval CREATE FUNCTION json_get_item RETURNS STRING SONAME '$HA_CONNECT_SO';
--eval CREATE FUNCTION json_set_item RETURNS STRING SONAME '$HA_CONNECT_SO';
--eval CREATE FUNCTION json_insert_item RETURNS STRING SONAME '$HA_CONNECT_SO';
--eval CREATE FUNCTION json_update_item RETURNS STRING SONAME '$HA_CONNECT_SO';
--eval CREATE FUNCTION json_item_merge RETURNS STRING SONAME '$HA_CONNECT_SO';
--eval CREATE FUNCTION json_serialize RETURNS STRING SONAME '$HA_CONNECT_SO';
--eval CREATE FUNCTION jbin_array RETURNS STRING SONAME '$HA_CONNECT_SO';
--eval CREATE FUNCTION jbin_array_add_values RETURNS STRING SONAME '$HA_CONNECT_SO';
--eval CREATE FUNCTION jbin_array_add RETURNS STRING SONAME '$HA_CONNECT_SO';
--eval CREATE FUNCTION jbin_array_delete RETURNS STRING SONAME '$HA_CONNECT_SO';
--eval CREATE FUNCTION jbin_object RETURNS STRING SONAME '$HA_CONNECT_SO';
--eval CREATE FUNCTION jbin_object_nonull RETURNS STRING SONAME '$HA_CONNECT_SO';
--eval CREATE FUNCTION jbin_object_key RETURNS STRING SONAME '$HA_CONNECT_SO';
--eval CREATE FUNCTION jbin_object_add RETURNS STRING SONAME '$HA_CONNECT_SO';
--eval CREATE FUNCTION jbin_object_delete RETURNS STRING SONAME '$HA_CONNECT_SO';
--eval CREATE FUNCTION jbin_object_list RETURNS STRING SONAME '$HA_CONNECT_SO';
--eval CREATE FUNCTION jbin_get_item RETURNS STRING SONAME '$HA_CONNECT_SO';
--eval CREATE FUNCTION jbin_item_merge RETURNS STRING SONAME '$HA_CONNECT_SO';
--eval CREATE FUNCTION jbin_set_item RETURNS STRING SONAME '$HA_CONNECT_SO';
--eval CREATE FUNCTION jbin_insert_item RETURNS STRING SONAME '$HA_CONNECT_SO';
--eval CREATE FUNCTION jbin_update_item RETURNS STRING SONAME '$HA_CONNECT_SO';
--eval CREATE FUNCTION jbin_file RETURNS STRING SONAME '$HA_CONNECT_SO';
if ($is_win)
{
--eval CREATE FUNCTION Json_Array RETURNS STRING SONAME 'ha_connect.dll';
--eval CREATE FUNCTION Json_Array_Add RETURNS STRING SONAME 'ha_connect.dll';
--eval CREATE FUNCTION Json_Object RETURNS STRING SONAME 'ha_connect.dll';
--eval CREATE FUNCTION Json_Object_Nonull RETURNS STRING SONAME 'ha_connect.dll';
--eval CREATE FUNCTION Json_Value returns STRING SONAME 'ha_connect.dll';
--eval CREATE AGGREGATE FUNCTION Json_Array_Grp RETURNS STRING SONAME 'ha_connect.dll';
--eval CREATE AGGREGATE FUNCTION Json_Object_Grp RETURNS STRING SONAME 'ha_connect.dll';
}
if (!$is_win)
{
--eval CREATE FUNCTION Json_Array RETURNS STRING SONAME 'ha_connect.so';
--eval CREATE FUNCTION Json_Array_Add RETURNS STRING SONAME 'ha_connect.so';
--eval CREATE FUNCTION Json_Object RETURNS STRING SONAME 'ha_connect.so';
--eval CREATE FUNCTION Json_Object_Nonull RETURNS STRING SONAME 'ha_connect.so';
--eval CREATE FUNCTION Json_Value returns STRING SONAME 'ha_connect.so';
--eval CREATE AGGREGATE FUNCTION Json_Array_Grp RETURNS STRING SONAME 'ha_connect.so';
--eval CREATE AGGREGATE FUNCTION Json_Object_Grp RETURNS STRING SONAME 'ha_connect.so';
}
--enable_query_log --enable_query_log
...@@ -5,35 +5,78 @@ let $MYSQLD_DATADIR= `select @@datadir`; ...@@ -5,35 +5,78 @@ let $MYSQLD_DATADIR= `select @@datadir`;
--copy_file $MTR_SUITE_DIR/std_data/biblio.json $MYSQLD_DATADIR/test/biblio.json --copy_file $MTR_SUITE_DIR/std_data/biblio.json $MYSQLD_DATADIR/test/biblio.json
--copy_file $MTR_SUITE_DIR/std_data/employee.dat $MYSQLD_DATADIR/test/employee.dat --copy_file $MTR_SUITE_DIR/std_data/employee.dat $MYSQLD_DATADIR/test/employee.dat
CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=VIR BLOCK_SIZE=5;
--echo # --echo #
--echo # Test UDF's with constant arguments --echo # Test UDF's with constant arguments
--echo # --echo #
--error ER_CANT_INITIALIZE_UDF
SELECT JsonValue(56, 3.1416, 'foo', NULL);
SELECT JsonValue(3.1416);
SELECT JsonValue(-80);
SELECT JsonValue('foo');
SELECT JsonValue(9223372036854775807);
SELECT JsonValue(NULL);
SELECT JsonValue(TRUE);
SELECT JsonValue(FALSE);
SELECT JsonValue();
SELECT JsonValue('[11, 22, 33]' json_) FROM t1;
#
SELECT Json_Array(); SELECT Json_Array();
SELECT Json_Object(56,3.1416,'foo',NULL); SELECT Json_Array(56, 3.1416, 'My name is "Foo"', NULL);
SELECT Json_Object(56 qty,3.1416 price,'foo' truc, NULL garanty); SELECT Json_Array(Json_Array(56, 3.1416, 'foo'), TRUE);
SELECT Json_Array(56,3.1416,'My name is "Foo"',NULL); #
--error ER_CANT_INITIALIZE_UDF --error ER_CANT_INITIALIZE_UDF
SELECT Json_Array_Add(Json_Array(56,3.1416,'foo',NULL)) Array; SELECT Json_Array_Add(Json_Array(56, 3.1416, 'foo', NULL)) Array;
SELECT Json_Array_Add(Json_Array(56,3.1416,'foo',NULL),'One more') Array; SELECT Json_Array_Add(Json_Array(56, 3.1416, 'foo', NULL), 'One more') Array;
SELECT Json_Array_Add(Json_Value('one value'),'One more');
--error ER_CANT_INITIALIZE_UDF --error ER_CANT_INITIALIZE_UDF
SELECT Json_Array_Add('one value','One more'); SELECT Json_Array_Add(JsonValue('one value'), 'One more');
SELECT Json_Array_Add('one value' json_,'One more');
--error ER_CANT_INITIALIZE_UDF --error ER_CANT_INITIALIZE_UDF
SELECT Json_Value(56,3.1416,'foo',NULL); SELECT Json_Array_Add('one value', 'One more');
SELECT Json_Value(3.1416); SELECT Json_Array_Add('one value' json_, 'One more');
SELECT Json_Value('foo'); --error ER_CANT_INITIALIZE_UDF
SELECT Json_Value(NULL); SELECT Json_Array_Add(5 json_, 'One more');
SELECT Json_Value(); SELECT Json_Array_Add('[5,3,8,7,9]' json_, 4, 0);
SELECT Json_Array_Add('[5,3,8,7,9]' json_, 4, 2) Array;
SELECT Json_Array_Add('[5,3,8,7,9]' json_, 4, 9);
SELECT Json_Array_Add(Json_Array(1, 2, Json_Array(11, 22)), '[2]', 33, 1);
SELECT Json_Array_Add(Json_Array(1, 2, Json_Array(11, 22)), 33, '[2]', 1);
SELECT Json_Array_Add(Json_Array(1, 2, Json_Array(11, 22)), 33, 1, '[2]');
#
SELECT Json_Array_Add_Values(Json_Array(56, 3.1416, 'machin', NULL), 'One more', 'Two more') Array;
SELECT Json_Array_Add_Values(Json_Array(56, 3.1416, 'machin'), 'One more', 'Two more') Array FROM t1;
SELECT Json_Array_Add_Values(Json_Array(56, 3.1416, 'machin'), n) Array FROM t1;
SELECT Json_Array_Add_Values(Json_Array(n, 3.1416, 'machin'), n) Array FROM t1;
SELECT Json_Array_Add_Values('[56]', 3.1416, 'machin') Array;
#
SELECT Json_Array_Delete(Json_Array(56, 3.1416, 'My name is "Foo"', NULL), 0);
SELECT Json_Array_Delete(Json_Object(56, 3.1416, 'My name is Foo', NULL), 2);
SELECT Json_Array_Delete(Json_Array(56, 3.1416, 'My name is "Foo"', NULL), '2');
SELECT Json_Array_Delete(json_array(56, 3.1416, 'My name is "Foo"', NULL), '2', 2);
#
SELECT Json_Object(56, 3.1416, 'foo', NULL);
SELECT Json_Object(56 qty, 3.1416 price, 'foo' truc, NULL garanty);
SELECT Json_Object(); SELECT Json_Object();
SELECT Json_Object(Json_Array(56,3.1416,'foo'),NULL); SELECT Json_Object(Json_Array(56, 3.1416, 'foo'), NULL);
SELECT Json_Array(Json_Array(56,3.1416,'foo'),NULL); SELECT Json_Array(Json_Object(56 "qty", 3.1416 "price", 'foo') ,NULL);
SELECT Json_Array(Json_Object(56 "qty",3.1416 "price",'foo'),NULL); SELECT Json_Object_Key('qty', 56, 'price', 3.1416, 'truc', 'machin', 'garanty', NULL);
--error ER_CANT_INITIALIZE_UDF
SELECT Json_Object_Key('qty', 56, 'price', 3.1416, 'truc', 'machin', 'garanty');
#
SELECT Json_Object_Add(Json_Object(56 qty, 3.1416 price, 'machin' truc, NULL garanty), 'blue' color);
SELECT Json_Object_Add(Json_Object(56 qty, 3.1416 price, 'machin' truc, NULL garanty), 45.99 price);
SELECT Json_Object_Add(Json_File('notexist.json'), 'cheese' item, '[1]', 1);
#
SELECT Json_Object_Delete(Json_Object(56 qty, 3.1416 price, 'machin' truc, NULL garanty), 'truc');
SELECT Json_Object_Delete(Json_Object(56 qty, 3.1416 price, 'machin' truc, NULL garanty), 'chose');
#
SELECT Json_Object_List(Json_Object(56 qty, 3.1416 price, 'machin' truc, NULL garanty)) "Key List";
SELECT Json_Object_List('{"qty":56, "price":3.1416, "truc":"machin", "garanty":null}') "Key List";
--echo # --echo #
--echo # Test UDF's with column arguments --echo # Test UDF's with column arguments
--echo # --echo #
CREATE TABLE t1 CREATE TABLE t2
( (
ISBN CHAR(15), ISBN CHAR(15),
LANG CHAR(2), LANG CHAR(2),
...@@ -46,14 +89,13 @@ CREATE TABLE t1 ...@@ -46,14 +89,13 @@ CREATE TABLE t1
DATEPUB int(4) DATEPUB int(4)
) ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='biblio.json'; ) ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='biblio.json';
SELECT Json_Array(AUTHOR, TITLE, DATEPUB) FROM t1; SELECT Json_Array(AUTHOR, TITLE, DATEPUB) FROM t2;
SELECT Json_Object(AUTHOR, TITLE, DATEPUB) FROM t1; SELECT Json_Object(AUTHOR, TITLE, DATEPUB) FROM t2;
--error ER_CANT_INITIALIZE_UDF --error ER_CANT_INITIALIZE_UDF
SELECT Json_Array_Grp(TITLE, DATEPUB) FROM t1; SELECT Json_Array_Grp(TITLE, DATEPUB) FROM t2;
SELECT Json_Array_Grp(TITLE) FROM t1; SELECT Json_Array_Grp(TITLE) FROM t2;
DROP TABLE t1;
CREATE TABLE t1 ( CREATE TABLE t3 (
SERIALNO CHAR(5) NOT NULL, SERIALNO CHAR(5) NOT NULL,
NAME VARCHAR(12) NOT NULL FLAG=6, NAME VARCHAR(12) NOT NULL FLAG=6,
SEX SMALLINT(1) NOT NULL, SEX SMALLINT(1) NOT NULL,
...@@ -64,30 +106,160 @@ CREATE TABLE t1 ( ...@@ -64,30 +106,160 @@ CREATE TABLE t1 (
SALARY DOUBLE(8,2) NOT NULL FLAG=52 SALARY DOUBLE(8,2) NOT NULL FLAG=52
) ENGINE=CONNECT TABLE_TYPE=FIX BLOCK_SIZE=8 FILE_NAME='employee.dat' ENDING=1; ) ENGINE=CONNECT TABLE_TYPE=FIX BLOCK_SIZE=8 FILE_NAME='employee.dat' ENDING=1;
SELECT Json_Object(SERIALNO, NAME, TITLE, SALARY) FROM t1 WHERE NAME = 'MERCHANT'; SELECT Json_Object(SERIALNO, NAME, TITLE, SALARY) FROM t3 WHERE NAME = 'MERCHANT';
SELECT DEPARTMENT, Json_Array_Grp(NAME) FROM t1 GROUP BY DEPARTMENT; SELECT DEPARTMENT, Json_Array_Grp(NAME) FROM t3 GROUP BY DEPARTMENT;
set connect_json_grp_size=30; SET connect_json_grp_size=30;
SELECT Json_Array(DEPARTMENT, Json_Array_Grp(NAME)) FROM t1 GROUP BY DEPARTMENT; SELECT Json_Object(title, Json_Array_Grp(name) `json_names`) from t3 GROUP BY title;
SELECT Json_Object(DEPARTMENT, Json_Array_Grp(NAME) json_NAMES) FROM t1 GROUP BY DEPARTMENT; SELECT Json_Array(DEPARTMENT, Json_Array_Grp(NAME)) FROM t3 GROUP BY DEPARTMENT;
SELECT Json_Object(DEPARTMENT, Json_Array_Grp(Json_Object(SERIALNO, NAME, TITLE, SALARY)) json_EMPLOYES) FROM t1 GROUP BY DEPARTMENT; SELECT Json_Object(DEPARTMENT, Json_Array_Grp(NAME) json_NAMES) FROM t3 GROUP BY DEPARTMENT;
SELECT Json_Object(DEPARTMENT, TITLE, Json_Array_Grp(Json_Object(SERIALNO, NAME, SALARY)) json_EMPLOYES) FROM t1 GROUP BY DEPARTMENT, TITLE; SELECT Json_Object(DEPARTMENT, Json_Array_Grp(Json_Object(SERIALNO, NAME, TITLE, SALARY)) json_EMPLOYES) FROM t3 GROUP BY DEPARTMENT;
SELECT Json_Object(DEPARTMENT, TITLE, Json_Array_Grp(Json_Object(SERIALNO, NAME, SALARY)) json_EMPLOYES) FROM t3 GROUP BY DEPARTMENT, TITLE;
--error ER_CANT_INITIALIZE_UDF --error ER_CANT_INITIALIZE_UDF
SELECT Json_Object_Grp(SALARY) FROM t1; SELECT Json_Object_Grp(SALARY) FROM t3;
SELECT Json_Object_Grp(SALARY, NAME) FROM t1; SELECT Json_Object_Grp(NAME, SALARY) FROM t3;
SELECT Json_Object(DEPARTMENT, Json_Object_Grp(SALARY, NAME) "Json_SALARIES") FROM t1 GROUP BY DEPARTMENT; SELECT Json_Object(DEPARTMENT, Json_Object_Grp(NAME, SALARY) "Json_SALARIES") FROM t3 GROUP BY DEPARTMENT;
SELECT Json_Array_Grp(NAME) from t1; SELECT Json_Array_Grp(NAME) FROM t3;
DROP TABLE t1; #
SELECT Json_Object_Key(name, title) FROM t3 WHERE DEPARTMENT = 318;
SELECT Json_Object_Grp(name, title) FROM t3 WHERE DEPARTMENT = 318;
DROP FUNCTION Json_Array; --echo #
DROP FUNCTION Json_Array_Add; --echo # Test value getting UDF's
DROP FUNCTION Json_Object; --echo #
DROP FUNCTION Json_Object_Nonull; SELECT JsonGet_String(Json_Array_Grp(name),'[#]') FROM t3;
DROP FUNCTION Json_Value; SELECT JsonGet_String(Json_Array_Grp(name),'[","]') FROM t3;
DROP FUNCTION Json_Array_Grp; SELECT JsonGet_String(Json_Array_Grp(name),'[>]') FROM t3;
DROP FUNCTION Json_Object_Grp; SET @j1 = '[45,28,36,45,89]';
SELECT JsonGet_String(@j1,'[1]');
SELECT JsonGet_String(@j1 json_,'[3]');
SELECT JsonGet_String(Json_Array(45,28,36,45,89),'[3]');
SELECT JsonGet_String(Json_Array(45,28,36,45,89),'["+"]') "list",'=' as "egal",JsonGet_String(Json_Array(45,28,36,45,89),'[+]') "sum";
SELECT JsonGet_String(Json_Array(json_array(45,28),json_array(36,45,89)),'[1]:[0]');
SELECT JsonGet_String(Json_Array(json_array(45,28),json_array(36,45,89)),'[1]:*');
SELECT JsonGet_String(Json_Object(56 qty,3.1416 price,'machin' truc, NULL garanty),'truc');
SET @j2 = '{"qty":56,"price":3.141600,"truc":"machin","garanty":null}';
SELECT JsonGet_String(@j2 json_,'truc');
SELECT JsonGet_String(@j2,'truc');
SELECT JsonGet_String(@j2,'chose');
SELECT JsonGet_String(NULL json_, NULL);
SELECT department, JsonGet_String(Json_Object(department, Json_Array_Grp(salary) "Json_salaries"),'salaries:[+]') Sumsal FROM t3 GROUP BY department;
#
SELECT JsonGet_Int(@j1, '[4]');
SELECT JsonGet_Int(@j1, '[#]');
SELECT JsonGet_Int(@j1, '[+]');
SELECT JsonGet_Int(@j1 json_, '[3]');
SELECT JsonGet_Int(Json_Array(45,28,36,45,89), '[3]');
SELECT JsonGet_Int(Json_Array(45,28,36,45,89), '["+"]');
SELECT JsonGet_Int(Json_Array(45,28,36,45,89), '[+]');
SELECT JsonGet_Int(Json_Array(json_array(45,28), json_array(36,45,89)), '[1]:[0]');
SELECT JsonGet_Int(Json_Array(json_array(45,28), json_array(36,45,89)), '[0]:[1]');
SELECT JsonGet_Int(Json_Object(56 qty, 3.1416 price, 'machin' truc, NULL garanty), 'qty');
SELECT JsonGet_Int(@j2 json_, 'price');
SELECT JsonGet_Int(@j2, 'qty');
SELECT JsonGet_Int('{"qty":56,"price":3.141600,"truc":"machin","garanty":null}', 'chose');
SELECT JsonGet_Int(JsonGet_String(Json_Array(Json_Array(45,28),Json_Array(36,45,89)), '[1]:*'), '[+]') sum;
SELECT department, JsonGet_Int(Json_Object(department, Json_Array_Grp(salary) "Json_salaries"), 'salaries:[+]') Sumsal FROM t3 GROUP BY department;
#
SELECT JsonGet_Real(@j1, '[2]');
SELECT JsonGet_Real(@j1 json_, '[3]', 2);
SELECT JsonGet_Real(Json_Array(45,28,36,45,89), '[3]');
SELECT JsonGet_Real(Json_Array(45,28,36,45,89), '["+"]');
SELECT JsonGet_Real(Json_Array(45,28,36,45,89), '[+]');
SELECT JsonGet_Real(Json_Array(45,28,36,45,89), '[!]');
SELECT JsonGet_Real(Json_Array(json_array(45,28), json_array(36,45,89)), '[1]:[0]');
SELECT JsonGet_Real(Json_Object(56 qty, 3.1416 price, 'machin' truc, NULL garanty), 'price');
SELECT JsonGet_Real('{"qty":56,"price":3.141600,"truc":"machin","garanty":null}' json_, 'qty');
SELECT JsonGet_Real('{"qty":56,"price":3.141600,"truc":"machin","garanty":null}', 'price');
SELECT JsonGet_Real('{"qty":56,"price":3.141600,"truc":"machin","garanty":null}', 'price', 4);
SELECT JsonGet_Real('{"qty":56,"price":3.141600,"truc":"machin","garanty":null}', 'chose');
SELECT department, JsonGet_Real(Json_Object(department, Json_Array_Grp(salary) "Json_salaries"),'salaries:[+]') Sumsal FROM t3 GROUP BY department;
--echo #
--echo # Documentation examples
--echo #
SELECT
JsonGet_Int(Json_Array(45,28,36,45,89), '[4]') "Rank",
JsonGet_Int(Json_Array(45,28,36,45,89), '[#]') "Number",
JsonGet_String(Json_Array(45,28,36,45,89), '[","]') "Concat",
JsonGet_Int(Json_Array(45,28,36,45,89), '[+]') "Sum",
JsonGet_Real(Json_Array(45,28,36,45,89), '[!]', 2) "Avg";
SELECT
JsonGet_String('{"qty":7,"price":29.50,"garanty":null}', 'price') "String",
JsonGet_Int('{"qty":7,"price":29.50,"garanty":null}', 'price') "Int",
JsonGet_Real('{"qty":7,"price":29.50,"garanty":null}', 'price') "Real";
SELECT JsonGet_Real('{"qty":7,"price":29.50,"garanty":null}', 'price', 3) "Real";
--echo #
--echo # Testing Locate
--echo #
SELECT JsonLocate(Json_Object(56 qty,3.1416 price,'machin' truc, NULL garanty),'machin');
SELECT JsonLocate(Json_Object(56 qty,3.1416 price,'machin' truc, NULL garanty),56);
SELECT JsonLocate(Json_Object(56 qty,3.1416 price,'machin' truc, NULL garanty),3.1416);
SELECT JsonLocate(Json_Object(56 qty,3.1416 price,'machin' truc, NULL garanty),'chose');
SELECT JsonLocate('{"AUTHORS":[{"FN":"Jules", "LN":"Verne"}, {"FN":"Jack", "LN":"London"}]}' json_, 'Jack') Path;
SELECT JsonLocate('{"AUTHORS":[{"FN":"Jules", "LN":"Verne"}, {"FN":"Jack", "LN":"London"}]}' json_, 'jack' ci) Path;
SELECT JsonLocate('{"AUTHORS":[{"FN":"Jules", "LN":"Verne"}, {"FN":"Jack", "LN":"London"}]}' json_, '{"FN":"Jack", "LN":"London"}' json_) Path;
SELECT JsonLocate('{"AUTHORS":[{"FN":"Jules", "LN":"Verne"}, {"FN":"Jack", "LN":"London"}]}' json_, '{"FN":"jack", "LN":"London"}' json_) Path;
SELECT JsonLocate('[45,28,36,45,89]',36);
SELECT JsonLocate('[45,28,36,45,89]' json_,28.0);
SELECT Json_Locate_All('[45,28,36,45,89]',10);
SELECT Json_Locate_All('[45,28,36,45,89]',45);
SELECT Json_Locate_All('[[45,28],36,45,89]',45);
SELECT Json_Locate_All('[[45,28,45],36,45,89]',45);
SELECT Json_Locate_All('[[45,28,45],36,45,89]',JsonGet_Int('[3,45]','[1]'));
SELECT JsonLocate('[[45,28,45],36,45,89]',45,n) from t1;
SELECT JsonGet_String(Json_Locate_All('[[45,28,45],36,45,89]',45),concat('[',n-1,']')) FROM t1;
SELECT JsonGet_String(Json_Locate_All('[[45,28,45],36,45,89]',45),concat('[',n-1,']')) AS `Path` FROM t1 GROUP BY n HAVING `Path` IS NOT NULL;
SELECT Json_Locate_All('[45,28,[36,45,89]]',45);
SELECT Json_Locate_All('[[45,28],[36,45.0,89]]',JsonValue(45.0));
SELECT Json_Locate_All('[[45,28],[36,45.0,89]]',45.0);
SELECT JsonLocate('[[45,28],[36,45,89]]','[36,45,89]' json_);
SELECT JsonLocate('[[45,28],[36,45,89]]','[45,28]' json_);
SELECT Json_Locate_All('[[45,28],[[36,45],89]]','45') "All paths";
SELECT Json_Locate_All('[[45,28],[[36,45],89]]','[36,45]' json_);
SELECT JsonGet_Int(Json_Locate_All('[[45,28],[[36,45],89]]',45), '[#]') "Nb of occurs";
SELECT Json_Locate_All('[[45,28],[[36,45],89]]',45,2);
SELECT JsonGet_String(Json_Locate_All('[45,28,36,45,89]',45),'[0]');
SELECT JsonLocate(Json_File('test/biblio.json'), 'Knab');
SELECT Json_Locate_All('test/biblio.json' jfile_, 'Knab');
--echo #
--echo # Testing json files
--echo #
SELECT Jfile_Make('[{"_id":5,"type":"food","item":"beer","taste":"light","price":5.65,"ratings":[5,8,9]},
{"_id":6,"type":"car","item":"roadster","mileage":56000,"ratings":[6,9]},
{"_id":7,"type":"food","item":"meat","origin":"argentina","ratings":[2,4]},
{"_id":8,"type":"furniture","item":"table","size":{"W":60,"L":80,"H":40},"ratings":[5,8,7]}]', 'test/fx.json', 0) AS NewFile;
SELECT Jfile_Make('test/fx.json', 1);
SELECT Jfile_Make('test/fx.json' jfile_);
SELECT Jfile_Make(Jbin_File('test/fx.json'), 0);
SELECT Json_File('test/fx.json', 1);
SELECT Json_File('test/fx.json', 2);
SELECT Json_File('test/fx.json', 0);
SELECT Json_File('test/fx.json', '[0]');
SELECT Json_File('test/fx.json', '[?]');
SELECT JsonGet_String(Json_File('test/fx.json'), '[1]:*');
SELECT JsonGet_String(Json_File('test/fx.json'), '[1]');
SELECT JsonGet_Int(Json_File('test/fx.json'), '[1]:mileage') AS Mileage;
SELECT JsonGet_Real(Json_File('test/fx.json'), '[0]:price', 2) AS Price;
SELECT Json_Array_Add(Json_File('test/fx.json', '[2]'), 6, 'ratings');
SELECT Json_Array_Add(Json_File('test/fx.json', '[2]'), 6, 1, 'ratings');
SELECT Json_Array_Add(Json_File('test/fx.json', '[2]'), 6, 'ratings', 1);
SELECT Json_Array_Add(Json_File('test/fx.json', '[2]:ratings'), 6, 0);
SELECT Json_Array_Delete(Json_File('test/fx.json', '[2]'), 'ratings', 1);
SELECT Json_Object_Add(Json_File('test/fx.json', '[2]'), 'france' origin);
SELECT Json_Object_Add(Json_File('test/fx.json', '[2]'), 70 H, 'size');
SELECT Json_Object_Add(Json_File('test/fx.json', '[3]'), 70 H, 'size');
SELECT Json_Object_List(Json_File('test/fx.json', '[3]:size'));
DROP TABLE t1;
DROP TABLE t2;
DROP TABLE t3;
# #
# Clean up # Clean up
# #
--source json_udf2.inc
--remove_file $MYSQLD_DATADIR/test/biblio.json --remove_file $MYSQLD_DATADIR/test/biblio.json
--remove_file $MYSQLD_DATADIR/test/employee.dat --remove_file $MYSQLD_DATADIR/test/employee.dat
--remove_file $MYSQLD_DATADIR/test/fx.json
--disable_query_log
DROP FUNCTION json_array;
DROP FUNCTION json_array_add;
DROP FUNCTION json_array_add_values;
DROP FUNCTION json_array_delete;
DROP FUNCTION json_object;
DROP FUNCTION json_object_nonull;
DROP FUNCTION json_object_key;
DROP FUNCTION json_object_add;
DROP FUNCTION json_object_delete;
DROP FUNCTION json_object_list;
DROP FUNCTION jsonvalue;
DROP FUNCTION json_array_grp;
DROP FUNCTION json_object_grp;
DROP FUNCTION jsonget_string;
DROP FUNCTION jsonget_int;
DROP FUNCTION jsonget_real;
DROP FUNCTION jsonlocate;
DROP FUNCTION json_locate_all;
DROP FUNCTION json_file;
DROP FUNCTION jfile_make;
DROP FUNCTION json_get_item;
DROP FUNCTION json_item_merge;
DROP FUNCTION jsoncontains;
DROP FUNCTION jsoncontains_path;
DROP FUNCTION json_set_item;
DROP FUNCTION json_insert_item;
DROP FUNCTION json_update_item;
DROP FUNCTION json_serialize;
DROP FUNCTION jbin_array;
DROP FUNCTION jbin_array_add_values;
DROP FUNCTION jbin_array_add;
DROP FUNCTION jbin_array_delete;
DROP FUNCTION jbin_object;
DROP FUNCTION jbin_object_nonull;
DROP FUNCTION jbin_object_key;
DROP FUNCTION jbin_object_add;
DROP FUNCTION jbin_object_delete;
DROP FUNCTION jbin_object_list;
DROP FUNCTION jbin_get_item;
DROP FUNCTION jbin_item_merge;
DROP FUNCTION jbin_set_item;
DROP FUNCTION jbin_insert_item;
DROP FUNCTION jbin_update_item;
DROP FUNCTION jbin_file;
--enable_query_log
--source json_udf.inc
let $MYSQLD_DATADIR= `select @@datadir`;
--copy_file $MTR_SUITE_DIR/std_data/gloss.json $MYSQLD_DATADIR/gloss.json
CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=VIR BLOCK_SIZE=3;
--echo #
--echo # Test Jbin UDF's
--echo #
SELECT Json_Array_Add(Jbin_Array(56, 3.1416, 'My name is "Foo"', NULL), n) from t1;
SELECT Json_Array_Add(Jbin_Array(n, 3.1416, 'My name is "Foo"', NULL), n) from t1;
SELECT Json_Array_Add(Jbin_Array(56, 3.1416, 'My name is "Foo"', NULL), Jbin_Array('a','b',n)) from t1;
SELECT Json_Array_Add(Jbin_Array(56, 3.1416, 'My name is "Foo"', NULL), JsonGet_String(Jbin_Array('a','b','c'), '[1]'));
SELECT Json_Array_Delete(Jbin_Array_Add_Values(Jbin_Array(56, 3.1416, 'My name is "Foo"', NULL), "One more", 2), 4);
SELECT Json_Array_Delete(Jbin_Array(56, Jbin_Array(3.1416, 'My name is "Foo"'), NULL), '[1]', 1);
SELECT Json_Array_Delete(Jbin_Array(56, Jbin_Array(3.1416, 'My name is "Foo"'), TRUE), 1, '[1]');
SELECT Json_Array(1, TRUE, 0, FALSE);
SELECT Json_Serialize(Jbin_Array(TRUE, FALSE));
#
SELECT Json_Object_Key('qty', 56, 'price', 3.1416, 'truc', 'machin', 'garanty', NULL);
SELECT Json_Serialize(Jbin_Object_Key('qty', 56, 'price', 3.1416, 'truc', 'machin', 'garanty', NULL));
--error ER_CANT_INITIALIZE_UDF
SELECT Jbin_Object_Key('qty', 56, 'price', 3.1416, 'truc', 'machin', 'garanty');
SELECT Json_Object_Add(Jbin_Object(56 qty, 3.1416 price, 'machin' truc, NULL garanty), 'blue' color);
SELECT Json_Object_Add(Jbin_Object(56 qty, 3.1416 price, 'machin' truc, NULL garanty), 45.99 price);
SELECT Json_Object_Add(Jbin_Object_Nonull(56 qty, 3.1416 price, 'machin' truc, NULL garanty), 'blue' color);
SELECT Json_Object_Add(Jbin_Object_Nonull(56 qty, 3.1416 price, 'machin' truc, NULL garanty), 45.99 price);
--echo #
--echo # Test Jbin file UDF's
--echo #
SELECT Json_Serialize(Jbin_File('gloss.json'));
SELECT JsonLocate(Jbin_File('gloss.json'),'XML');
#
SELECT Json_Object_Key('first', 'foo', 'second', Jbin_Array('a', 33));
SELECT Json_Get_Item(Json_Array('a','b','c'), '[1]');
SELECT Json_Get_Item(Json_Object('foo' AS "first", Json_Array('a', 33) AS "json_second"), 'second') AS "item";
SELECT Json_Get_Item(Jbin_Object('foo' first, Jbin_Array('a', 33) jbin_second), 'second:*') item;
SELECT Json_Get_Item(Jbin_File('gloss.json'),'glossary:GlossDiv');
SELECT Json_Serialize(Jbin_Get_Item(Jbin_File('gloss.json'),'glossary:GlossDiv'));
SELECT Json_Get_Item(Jbin_File('gloss.json'),'glossary:GlossDiv:*');
SELECT JsonGet_String(Json_File('gloss.json'),'glossary:GlossDiv:GlossList:GlossEntry:GlossDef:GlossSeeAlso') lang;
SELECT Json_Get_Item(Jbin_File('gloss.json'),'glossary:GlossDiv:GlossList:GlossEntry:GlossDef:GlossSeeAlso') "See also";
SELECT Json_Serialize(Jbin_Get_Item(Jbin_File('gloss.json'),'glossary:GlossDiv:GlossList:GlossEntry:GlossDef:GlossSeeAlso')) "See also";
SELECT JsonGet_String(Json_Get_Item(Json_File('gloss.json'),'glossary:GlossDiv:GlossList:GlossEntry:GlossDef:GlossSeeAlso'),'[0]') lang;
--echo #
--echo # Test Item Get/Set/Insert/Update UDF's
--echo #
SELECT Json_Get_Item(Json_Array(1, 2, Json_Object_Key('trois', 3, 'quatre', 4)), '[]');
SELECT Json_Get_Item(Jbin_Array(1, 2, Json_Object_Key('trois', 3, 'quatre', 4)), '[1]');
SELECT Json_Get_Item(Jbin_Array(1, 2, Jbin_Object_Key('trois', 3, 'quatre', 4)), '[1]');
#
SELECT Json_Set_Item(Json_Array(1, 2, Json_Object_Key('trois', 3, 'quatre', 4)));
--error ER_CANT_INITIALIZE_UDF
SELECT Json_Set_Item(Jbin_Array(1, 2, Jbin_Object_Key('trois', 3, 'quatre', 4)), 'foo');
SELECT Json_Set_Item(Jbin_Array(1, 2, Jbin_Object_Key('trois', 3, 'quatre', 4)), 5, '[2]:cinq');
SELECT Json_Set_Item(Jbin_Array(1, 2, Jbin_Object_Key('trois', 3, 'quatre', 4)), 7, '[1]');
SELECT Json_Set_Item(Jbin_Array(1, 2, Jbin_Object_Key('trois', 3, 'quatre', 4)), 5, '[2]:cinq', 7, '[1]');
SELECT Json_Set_Item(Jbin_Array(1, 2, Jbin_Object_Key('trois', 3, 'quatre', 4)), Json_Array(7, 8, 9), '[1]');
SELECT Json_Set_Item(Jbin_Array(1, 2, Jbin_Object_Key('trois', 3, 'quatre', 4)), Jbin_Array(7, 8, 9), '[2]');
SELECT Json_Set_Item(Jbin_Array(1, 2, Jbin_Object_Key('trois', 3, 'quatre', 4)), Jbin_Array(7, 8, 9), '[2]:*');
SELECT Json_Set_Item(Jbin_Array(1, 2, Jbin_Object_Key('trois', 3, 'quatre', 4)), 3.1416, 'foo');
SELECT Json_Set_Item(Jbin_Array(1, Jbin_Array(7, 8, 9), Jbin_Object_Key('trois', 3, 'quatre', 4)), 'toto', '[1]:[2]');
SELECT Json_Set_Item(Jbin_Array(1, Jbin_Array(7, 8, 9), Jbin_Object_Key('trois', 3, 'quatre', 4)), 300, '[2]:nxt:total:[]');
SELECT Json_Set_Item(Jbin_Array(1, Jbin_Array(7, 8, 9), Jbin_Object_Key('trois', 3, 'quatre', 4)), 5, '[2]:cinq', 10, '[1]:[]', 300, '[2]:nxt:total:[]');
SELECT Json_Set_Item(Jbin_Array(1, 2, Jbin_Object_Key('trois', 3, 'quatre', 4)), Jbin_Array(7, 8, 9), '[1]', 5, '[2]:cinq', 10, '[1]:[]');
SELECT Json_Set_Item(Jbin_Array(1, 2, Jbin_Object_Key('trois', 3, 'quatre', 4)), 44, '[2]:quatre');
SELECT Json_Set_Item(Jbin_Array(1, 2, Jbin_Object_Key('trois', 3, 'quatre', 4)), 5, 'truc');
SELECT Json_Set_Item(Jbin_Array(1, 2, Jbin_Object_Key('trois', 3, 'quatre', 4)), 5, '');
SELECT Json_Set_Item(Jbin_Array(1, 2, Jbin_Object_Key('trois', 3, 'quatre', 4)), 5, '*');
SELECT Json_Serialize(Jbin_Set_Item(Json_Array(1, 2, Json_Object_Key('trois', 3, 'quatre', 4)), 5, '[2]:cinq'));
#
SELECT Json_Insert_Item(Json_Array(1, 2, Json_Object_Key('trois', 3, 'quatre', 4)), 5, '[2]:cinq');
SELECT Json_Update_Item(Json_Array(1, 2, Json_Object_Key('trois', 3, 'quatre', 4)), 5, '[2]:cinq');
SELECT Json_Insert_Item(Jbin_Array(1, Jbin_Array(7, 8, 9), Jbin_Object_Key('trois', 3, 'quatre', 4)), 5, '[2]:cinq', 10, '[1]:[]', 44, '[2]:quatre');
SELECT Json_Update_Item(Jbin_Array(1, Jbin_Array(7, 8, 9), Jbin_Object_Key('trois', 3, 'quatre', 4)), 5, '[2]:cinq', 10, '[1]:[]', 44, '[2]:quatre');
SELECT Json_Insert_Item(Json_Array(1, Json_Array(7, 8, 9), Json_Object_Key('trois', 3, 'quatre', 4)), 5, '[2]:cinq', 10, '[1]:[1]', 300, '[2]:nxt:total:[]');
SELECT Json_Update_Item(Json_Array(1, Json_Array(7, 8, 9), Json_Object_Key('trois', 3, 'quatre', 4)), 5, '[2]:cinq', 10, '[1]:[1]', 300, '[2]:nxt:total:[]');
SELECT Json_Insert_Item(Json_Array(1, 2, Json_Object_Key('trois', 3, 'quatre', 4)), 5, '[]');
SELECT Json_Update_Item(Json_Array(1, 2, Json_Object_Key('trois', 3, 'quatre', 4)), 5, '[]');
--echo #
--echo # Test merging items UDF's
--echo #
SELECT Json_Item_Merge(Jbin_Array('a','b','c'), Jbin_Array('d','e','f'));
SELECT Json_Item_Merge(Json_Array('a','b','c'), Json_Array('d','e','f')) AS "Result";
SELECT Json_Array_Add(Jbin_Item_Merge(Jbin_Array('a','b','c'), Jbin_Array('d','e','f')), 'and', 3);
SELECT Json_Item_Merge(Jbin_Object(1 "a",2 "b",3 "c"), Jbin_Object(4 "d",5 "e",6 "f"));
SELECT Json_Item_Merge(Jbin_Object(1 "a",2 "b",2 "c"), Jbin_Array('d','e','f'));
SELECT Json_Object_Add(Jbin_Item_Merge(Jbin_Object(1 "a",2 "b",3 "c"), Jbin_Object(4 "d",5 "e",6 "f")), 'x' AS "and");
SELECT Json_Item_Merge(Jbin_Object(1 "a",2 "b",3 "c"), Jbin_Object(4 "a",5 "e",6 "f"));
--error ER_CANT_INITIALIZE_UDF
SELECT Json_Item_Merge('foo', Json_Array('d','e','f'));
--echo #
--echo # Test making file UDF's
--echo #
SELECT Jfile_Make(Jbin_Array('a','b','c'), 'bt1.json');
SELECT Json_File('bt1.json');
SELECT Json_File(Jfile_Make(Jbin_File('bt1.json'), 0));
SELECT Json_File(Jfile_Make(Jbin_File('bt1.json'), 1));
SELECT Json_File(Jfile_Make(Jbin_File('bt1.json'), 2));
SELECT Json_File('bt1.json', 0);
SELECT Json_File('bt1.json', 1);
SELECT Json_File('bt1.json', 2);
SELECT Json_Serialize(Jbin_Array('a','b','c'));
SELECT Json_Serialize(Jbin_Array_Add(Jbin_File('not_exist.json'), 'd'));
--echo # This does not modify the file
SELECT Json_Serialize(Jbin_Array_Add(Jbin_File('bt1.json'), 'd'));
SELECT Json_File('bt1.json', 2);
--echo # This does modify the file
SELECT Json_Array_Add(Jbin_File('bt1.json'), 'd');
SELECT Json_File('bt1.json', 2);
--echo # Back to the original file
SELECT Jfile_Make(Jbin_Array('a','b','c'), 'bt1.json');
SELECT Json_Object(Jbin_Array_Add(Jbin_Array('a','b','c'), 'd') "Jbin_foo") AS "Result";
SELECT Json_Object(Jbin_Array_Add(Jbin_File('bt1.json'), 'd')) AS "Result";
SELECT Json_Object(Jbin_Array_Add(Jbin_File('bt1.json'), 'd') "Jbin_bt1") AS "Result";
--echo # This does modify the file
SELECT Json_Object(Json_Array_Add(Jbin_File('bt1.json'), 'd') "Jfile_bt1") AS "Result";
SELECT Json_File('bt1.json');
SELECT Json_File(Json_Array_Delete(Jbin_File('bt1.json'), 3), 2);
SELECT Json_Object(Jbin_Array_Add(Jbin_File('bt1.json'), 'd') "Jbin_bt1", n "t1") AS "Result" from t1;
SELECT Json_File(Json_Array_Add(Jbin_Array_Add(Jbin_File('bt1.json'), 'd'), 'e')) AS "Result";
SELECT Jfile_Make(Jbin_Array('a','b','c'), 'bt1.json');
SELECT Json_File(Json_Array_Add(Jbin_Array_Add(Jbin_File('bt1.json'), 'd'), 'e')) AS "Result" from t1;
SELECT Jfile_Make(Jbin_Array('a','b','c'), 'bt1.json');
SELECT Json_Array_Add(Jbin_Array_Add(Jbin_File('bt1.json'), 'd'), n) AS "Result" from t1;
--echo # Show modified file
SELECT Json_File('bt1.json');
SELECT Jfile_Make(Jbin_Array('a','b','c'), 'bt1.json');
SELECT Json_Array_Add(Jbin_File('bt1.json'), n) AS "Result" from t1;
--echo # Show modified file
SELECT Json_File('bt1.json');
SELECT Jfile_Make(Jbin_Array('a','b','c'), 'bt1.json');
SELECT Json_File(Jbin_Item_Merge(Jbin_File('bt1.json'), Jbin_Array('d','e','f')));
SELECT Json_File(Json_Item_Merge(Jbin_File('bt1.json'), Jbin_Array('d','e','f')));
SELECT Jfile_Make(Jbin_Array('a','b','c'), 'bt1.json');
--echo # Test DELETE from file
SELECT Json_Object(Jbin_Array_Delete(Jbin_File('bt1.json'), 1)) AS "Result";
SELECT Json_Object(Jbin_Array_Delete(Jbin_File('bt1.json'), 2) "Jbin_bt1") AS "Result";
SELECT Json_Object(Jbin_Array_Delete(Jbin_File('bt1.json'), 0) "Jbin_bt1", n "t1") AS "Result" from t1;
SELECT Json_Object(Jbin_Array_Delete(Jbin_File('bt1.json'), 3 - n) "Jbin_bt1") AS "Result" from t1;
SELECT Json_Object(Json_Array_Delete(Jbin_File('bt1.json'), 3 - n) "Jbin_bt1") AS "Result" from t1;
--echo # Show modified file
SELECT Json_File('bt1.json');
--echo # Object file
SELECT Jfile_Make(Jbin_Object(1 "a", 2 "b", 3 "c"), 'bt2.json', 0);
SELECT Json_File('bt2.json', 0);
SELECT Json_File('bt2.json');
SELECT Json_Serialize(Jbin_Object_Add(Jbin_File('bt2.json'), 4 "d"));
--echo # First query (file not modified)
SELECT Json_Object(Jbin_Object_Add(Jbin_File('bt2.json'), 4 AS "d") AS "Jbin_new") AS "Result";
--echo # First query (file modified)
SELECT Json_Object(Json_Object_Add(Jbin_File('bt2.json'), 4 AS "d") AS "Jfile_new") AS "Result";
SELECT Jfile_Make(Jbin_Object(1 "a", 2 "b", 3 "c"), 'bt2.json', 0);
SELECT Json_Object(Jbin_Object_Add(Jbin_File('bt2.json'), 4 "d") "Jbin_new", n "t1") AS "Result" from t1;
SELECT Json_File(Json_Object_Add(Jbin_Object_Add(Jbin_File('bt2.json'), 4 "d"), 5 "e")) AS "Result";
SELECT Json_Object_Add(Jbin_Object_Add(Jbin_File('bt2.json'), 4 "d"), 5 "e") AS "Result" from t1;
SELECT Json_Object_Add(Jbin_Object_Add(Jbin_File('bt2.json'), 4 "d"), n "n") AS "Result" from t1;
SELECT Jfile_Make(Jbin_Object(1 "a", 2 "b", 3 "c"), 'bt2.json', 0);
SELECT Json_Object_Add(Jbin_File('bt2.json'), n) AS "Result" from t1;
SELECT Json_File('bt2.json');
SELECT Jfile_Make(Jbin_Object(1 "a", 2 "b", 3 "c"), 'bt2.json', 0);
SELECT Json_Serialize(Jbin_Item_Merge(Jbin_File('bt2.json'), Jbin_Object(4 "d",5 "e",6 "f"))) AS "Result";
SELECT Json_File(Json_Item_Merge(Jbin_File('bt2.json'), Jbin_Object(4 "d",5 "e",6 "f"))) AS "Result";
SELECT Json_Item_Merge(Json_Object(1 "a", 2 "b", 3 "c"), Json_Object(4 "d",5 "b",6 "f")) AS "Result";
#
SELECT Json_Object(Json_Object_Delete(Jbin_File('bt2.json'), 'b')) AS "Result";
SELECT Json_Object(Jbin_Object_Delete(Jbin_File('bt2.json'), 'c') "Jbin_bt1") AS "Result";
SELECT Json_Object(Json_Object_Delete(Jbin_File('bt2.json'), 'c') "Jbin_bt1") AS "Result";
SELECT Json_Object(Json_Object_Delete(Jbin_File('bt2.json'), 'c') "Jfile_bt1") AS "Result";
SELECT Json_Object(Json_Object_Delete(Jbin_File('bt2.json'), 'a') "Jbin_bt1", n "t1") AS "Result" from t1;
#
SELECT Json_Serialize(Jbin_Object_List(Jbin_File('bt2.json'))) "Key list";
#
# Test documentation examples
#
SELECT Jfile_Make('{"a":1, "b":[44, 55]}' json_, 'bt3.json', 0);
SELECT Json_Array_Add(Json_File('bt3.json', 'b'), 66);
SELECT Json_Array_Add(Json_File('bt3.json'), 66, 'b');
SELECT Json_Array_Add(Jbin_File('bt3.json', 'b'), 66);
SELECT Json_File('bt3.json', 3);
SELECT Jfile_Make('{"a":1, "b":[44, 55]}' json_, 'bt3.json', 0);
#
CREATE TABLE t2 (
n INT KEY,
jfile_cols CHAR(12) NOT NULL)
ENGINE= MYISAM;
INSERT INTO t2 VALUES(1,'bt3.json');
--echo # In this table, the jfile_cols column just contains a file name
UPDATE t2 SET jfile_cols = Json_Array_Add(Jbin_File('bt3.json', 'b'), 66) WHERE n = 1;
SELECT JsonGet_String(jfile_cols, '*') FROM t2;
UPDATE t2 SET jfile_cols = Json_Insert_Item(jfile_cols, 77, 'b:[]') WHERE n = 1;
SELECT JsonGet_String(jfile_cols, 'b:*') FROM t2;
UPDATE t2 SET jfile_cols = Json_Insert_Item(Jbin_Insert_Item(jfile_cols, 88, 'b:') , 99, 'b:') WHERE n = 1;
SELECT JsonGet_String(jfile_cols, '*') FROM t2;
DROP TABLE t1, t2;
#
# Clean up
#
--source json_udf2.inc
--remove_file $MYSQLD_DATADIR/gloss.json
--remove_file $MYSQLD_DATADIR/bt1.json
--remove_file $MYSQLD_DATADIR/bt2.json
--remove_file $MYSQLD_DATADIR/bt3.json
...@@ -19,8 +19,10 @@ DROP TABLE t1; ...@@ -19,8 +19,10 @@ DROP TABLE t1;
--echo # --echo #
--echo # Testing FILE privilege --echo # Testing FILE privilege
--echo # --echo #
set sql_mode="";
GRANT ALL PRIVILEGES ON *.* TO user@localhost; GRANT ALL PRIVILEGES ON *.* TO user@localhost;
REVOKE FILE ON *.* FROM user@localhost; REVOKE FILE ON *.* FROM user@localhost;
set sql_mode=default;
--connect(user,localhost,user,,) --connect(user,localhost,user,,)
--connection user --connection user
SELECT user(); SELECT user();
...@@ -54,7 +56,7 @@ CREATE VIEW v1 AS SELECT * FROM t1; ...@@ -54,7 +56,7 @@ CREATE VIEW v1 AS SELECT * FROM t1;
--echo # Testing a VIEW created with FILE privileges but accessed with no FILE --echo # Testing a VIEW created with FILE privileges but accessed with no FILE
--connection default --connection default
SELECT user(); SELECT user();
CREATE VIEW v1 AS SELECT * FROM t1; CREATE SQL SECURITY INVOKER VIEW v1 AS SELECT * FROM t1;
--connection user --connection user
SELECT user(); SELECT user();
--error ER_ACCESS_DENIED_ERROR --error ER_ACCESS_DENIED_ERROR
......
...@@ -27,6 +27,15 @@ ...@@ -27,6 +27,15 @@
#Servername=localhost #Servername=localhost
#Port=5432 #Port=5432
# #
# 5. Allow user "mtr" to connect to the database "mtr"
# Add this line into the begginning of pg_hba.conf
# (usually /var/lib/pgsql/data/pg_hba.conf on Linux):
#host mtr mtr 127.0.0.1/32 password
#
# 6. Restart the server:
# sudo service postgresql restart
#
#
SET NAMES utf8; SET NAMES utf8;
......
...@@ -56,9 +56,10 @@ ALTER TABLE t1 READONLY=1; ...@@ -56,9 +56,10 @@ ALTER TABLE t1 READONLY=1;
CREATE VIEW v1 AS SELECT * FROM t1; CREATE VIEW v1 AS SELECT * FROM t1;
--echo # Testing a VIEW created with FILE privileges but accessed with no FILE --echo # Testing a VIEW created with FILE privileges but accessed with no FILE
--echo # using SQL SECIRITY INVOKER
--connection default --connection default
SELECT user(); SELECT user();
CREATE VIEW v1 AS SELECT * FROM t1; CREATE SQL SECURITY INVOKER VIEW v1 AS SELECT * FROM t1;
--connection user --connection user
SELECT user(); SELECT user();
--error ER_ACCESS_DENIED_ERROR --error ER_ACCESS_DENIED_ERROR
...@@ -70,6 +71,17 @@ UPDATE v1 SET a=123; ...@@ -70,6 +71,17 @@ UPDATE v1 SET a=123;
--error ER_ACCESS_DENIED_ERROR --error ER_ACCESS_DENIED_ERROR
DELETE FROM v1; DELETE FROM v1;
--echo # Testing a VIEW created with FILE privileges but accessed with no FILE
--echo # using SQL SECIRITY DEFINER
--connection default
DROP VIEW v1;
SELECT user();
CREATE SQL SECURITY DEFINER VIEW v1 AS SELECT * FROM t1;
--connection user
SELECT user();
SELECT * FROM v1 WHERE a='test1';
--disconnect user --disconnect user
--connection default --connection default
SELECT user(); SELECT user();
......
...@@ -143,7 +143,7 @@ PGLOBAL PlugInit(LPCSTR Language, uint worksize) ...@@ -143,7 +143,7 @@ PGLOBAL PlugInit(LPCSTR Language, uint worksize)
fprintf(stderr, MSG(GLOBAL_ERROR), (int)sizeof(GLOBAL)); fprintf(stderr, MSG(GLOBAL_ERROR), (int)sizeof(GLOBAL));
return NULL; return NULL;
} else { } else {
g->Sarea_Size = worksize; g->Sarea = NULL;
g->Createas = 0; g->Createas = 0;
g->Alchecked = 0; g->Alchecked = 0;
g->Mrr = 0; g->Mrr = 0;
...@@ -155,7 +155,7 @@ PGLOBAL PlugInit(LPCSTR Language, uint worksize) ...@@ -155,7 +155,7 @@ PGLOBAL PlugInit(LPCSTR Language, uint worksize)
/*******************************************************************/ /*******************************************************************/
/* Allocate the main work segment. */ /* Allocate the main work segment. */
/*******************************************************************/ /*******************************************************************/
if (!(g->Sarea = PlugAllocMem(g, worksize))) { if (worksize && !(g->Sarea = PlugAllocMem(g, worksize))) {
char errmsg[256]; char errmsg[256];
sprintf(errmsg, MSG(WORK_AREA), g->Message); sprintf(errmsg, MSG(WORK_AREA), g->Message);
strcpy(g->Message, errmsg); strcpy(g->Message, errmsg);
......
...@@ -47,6 +47,7 @@ ...@@ -47,6 +47,7 @@
#include "valblk.h" #include "valblk.h"
#include "tabmul.h" #include "tabmul.h"
#include "ha_connect.h" #include "ha_connect.h"
#include "mycat.h"
#if !defined(__WIN__) #if !defined(__WIN__)
extern handlerton *connect_hton; extern handlerton *connect_hton;
......
...@@ -2204,7 +2204,7 @@ bool TDBDOS::PrepareWriting(PGLOBAL) ...@@ -2204,7 +2204,7 @@ bool TDBDOS::PrepareWriting(PGLOBAL)
} // endif Mode } // endif Mode
return false; return false;
} // end of WriteDB } // end of PrepareWriting
/***********************************************************************/ /***********************************************************************/
/* WriteDB: Data Base write routine for DOS access method. */ /* WriteDB: Data Base write routine for DOS access method. */
...@@ -2216,7 +2216,7 @@ int TDBDOS::WriteDB(PGLOBAL g) ...@@ -2216,7 +2216,7 @@ int TDBDOS::WriteDB(PGLOBAL g)
// Make the line to write // Make the line to write
if (PrepareWriting(g)) if (PrepareWriting(g))
return true; return RC_FX;
if (trace > 1) if (trace > 1)
htrc("Write: line is='%s'\n", To_Line); htrc("Write: line is='%s'\n", To_Line);
......
...@@ -38,6 +38,7 @@ ...@@ -38,6 +38,7 @@
/***********************************************************************/ /***********************************************************************/
#define MAXCOL 200 /* Default max column nb in result */ #define MAXCOL 200 /* Default max column nb in result */
#define TYPE_UNKNOWN 12 /* Must be greater than other types */ #define TYPE_UNKNOWN 12 /* Must be greater than other types */
#define USE_G 1 /* Use recoverable memory if 1 */
/***********************************************************************/ /***********************************************************************/
/* External function. */ /* External function. */
...@@ -411,9 +412,23 @@ PTDB JSONDEF::GetTable(PGLOBAL g, MODE m) ...@@ -411,9 +412,23 @@ PTDB JSONDEF::GetTable(PGLOBAL g, MODE m)
// Txfp must be set for TDBDOS // Txfp must be set for TDBDOS
tdbp = new(g) TDBJSN(this, txfp); tdbp = new(g) TDBJSN(this, txfp);
#if USE_G
// Allocate the parse work memory
PGLOBAL G = (PGLOBAL)PlugSubAlloc(g, NULL, sizeof(GLOBAL));
memset(G, 0, sizeof(GLOBAL));
G->Sarea_Size = Lrecl * 10;
G->Sarea = PlugSubAlloc(g, NULL, G->Sarea_Size);
PlugSubSet(G, G->Sarea, G->Sarea_Size);
G->jump_level = -1;
((TDBJSN*)tdbp)->G = G;
#else
((TDBJSN*)tdbp)->G = g;
#endif
} else { } else {
txfp = new(g) MAPFAM(this); txfp = new(g) MAPFAM(this);
tdbp = new(g) TDBJSON(this, txfp); tdbp = new(g) TDBJSON(this, txfp);
((TDBJSON*)tdbp)->G = g;
} // endif Pretty } // endif Pretty
if (Multiple) if (Multiple)
...@@ -462,6 +477,7 @@ TDBJSN::TDBJSN(PJDEF tdp, PTXF txfp) : TDBDOS(tdp, txfp) ...@@ -462,6 +477,7 @@ TDBJSN::TDBJSN(PJDEF tdp, PTXF txfp) : TDBDOS(tdp, txfp)
TDBJSN::TDBJSN(TDBJSN *tdbp) : TDBDOS(NULL, tdbp) TDBJSN::TDBJSN(TDBJSN *tdbp) : TDBDOS(NULL, tdbp)
{ {
G = NULL;
Top = tdbp->Top; Top = tdbp->Top;
Row = tdbp->Row; Row = tdbp->Row;
Val = tdbp->Val; Val = tdbp->Val;
...@@ -485,6 +501,7 @@ TDBJSN::TDBJSN(TDBJSN *tdbp) : TDBDOS(NULL, tdbp) ...@@ -485,6 +501,7 @@ TDBJSN::TDBJSN(TDBJSN *tdbp) : TDBDOS(NULL, tdbp)
// Used for update // Used for update
PTDB TDBJSN::CopyOne(PTABS t) PTDB TDBJSN::CopyOne(PTABS t)
{ {
G = NULL;
PTDB tp; PTDB tp;
PJCOL cp1, cp2; PJCOL cp1, cp2;
PGLOBAL g = t->G; PGLOBAL g = t->G;
...@@ -655,19 +672,26 @@ int TDBJSN::ReadDB(PGLOBAL g) ...@@ -655,19 +672,26 @@ int TDBJSN::ReadDB(PGLOBAL g)
NextSame = 0; NextSame = 0;
M++; M++;
return RC_OK; return RC_OK;
} else if ((rc = TDBDOS::ReadDB(g)) == RC_OK) } else if ((rc = TDBDOS::ReadDB(g)) == RC_OK) {
if (!IsRead() && ((rc = ReadBuffer(g)) != RC_OK)) { if (!IsRead() && ((rc = ReadBuffer(g)) != RC_OK))
// Deferred reading failed // Deferred reading failed
} else if (!(Row = ParseJson(g, To_Line, return rc;
strlen(To_Line), Pretty, &Comma))) {
rc = (Pretty == 1 && !strcmp(To_Line, "]")) ? RC_EF : RC_FX; #if USE_G
} else { // Recover the memory used for parsing
PlugSubSet(G, G->Sarea, G->Sarea_Size);
#endif
if ((Row = ParseJson(G, To_Line, strlen(To_Line), &Pretty, &Comma))) {
Row = FindRow(g); Row = FindRow(g);
SameRow = 0; SameRow = 0;
Fpos++; Fpos++;
M = 1; M = 1;
rc = RC_OK; rc = RC_OK;
} // endif's } else
rc = (Pretty == 1 && !strcmp(To_Line, "]")) ? RC_EF : RC_FX;
} // endif ReadDB
return rc; return rc;
} // end of ReadDB } // end of ReadDB
...@@ -744,7 +768,7 @@ int TDBJSN::MakeTopTree(PGLOBAL g, PJSON jsp) ...@@ -744,7 +768,7 @@ int TDBJSN::MakeTopTree(PGLOBAL g, PJSON jsp)
if (MakeTopTree(g, Row)) if (MakeTopTree(g, Row))
return true; return true;
if ((s = Serialize(g, Top, NULL, Pretty))) { if ((s = Serialize(G, Top, NULL, Pretty))) {
if (Comma) if (Comma)
strcat(s, ","); strcat(s, ",");
...@@ -755,22 +779,36 @@ int TDBJSN::MakeTopTree(PGLOBAL g, PJSON jsp) ...@@ -755,22 +779,36 @@ int TDBJSN::MakeTopTree(PGLOBAL g, PJSON jsp)
} else } else
strcpy(To_Line, s); strcpy(To_Line, s);
// Row->Clear();
return false; return false;
} else } else
return true; return true;
} // end of PrepareWriting } // end of PrepareWriting
/* ---------------------------- JSONCOL ------------------------------ */ /***********************************************************************/
/* WriteDB: Data Base write routine for DOS access method. */
/***********************************************************************/
int TDBJSN::WriteDB(PGLOBAL g)
{
int rc = TDBDOS::WriteDB(g);
#if USE_G
PlugSubSet(G, G->Sarea, G->Sarea_Size);
#endif
Row->Clear();
return rc;
} // end of WriteDB
/* ---------------------------- JSONCOL ------------------------------ */
/***********************************************************************/ /***********************************************************************/
/* JSONCOL public constructor. */ /* JSONCOL public constructor. */
/***********************************************************************/ /***********************************************************************/
JSONCOL::JSONCOL(PGLOBAL g, PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i) JSONCOL::JSONCOL(PGLOBAL g, PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i)
: DOSCOL(g, cdp, tdbp, cprec, i, "DOS") : DOSCOL(g, cdp, tdbp, cprec, i, "DOS")
{ {
Tjp = (TDBJSN *)(tdbp->GetOrig() ? tdbp->GetOrig() : tdbp); Tjp = (TDBJSN *)(tdbp->GetOrig() ? tdbp->GetOrig() : tdbp);
G = Tjp->G;
Jpath = cdp->GetFmt(); Jpath = cdp->GetFmt();
MulVal = NULL; MulVal = NULL;
Nodes = NULL; Nodes = NULL;
...@@ -778,14 +816,15 @@ JSONCOL::JSONCOL(PGLOBAL g, PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i) ...@@ -778,14 +816,15 @@ JSONCOL::JSONCOL(PGLOBAL g, PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i)
Xnod = -1; Xnod = -1;
Xpd = false; Xpd = false;
Parsed = false; Parsed = false;
} // end of JSONCOL constructor } // end of JSONCOL constructor
/***********************************************************************/ /***********************************************************************/
/* JSONCOL constructor used for copying columns. */ /* JSONCOL constructor used for copying columns. */
/* tdbp is the pointer to the new table descriptor. */ /* tdbp is the pointer to the new table descriptor. */
/***********************************************************************/ /***********************************************************************/
JSONCOL::JSONCOL(JSONCOL *col1, PTDB tdbp) : DOSCOL(col1, tdbp) JSONCOL::JSONCOL(JSONCOL *col1, PTDB tdbp) : DOSCOL(col1, tdbp)
{ {
G = col1->G;
Tjp = col1->Tjp; Tjp = col1->Tjp;
Jpath = col1->Jpath; Jpath = col1->Jpath;
MulVal = col1->MulVal; MulVal = col1->MulVal;
...@@ -794,7 +833,7 @@ JSONCOL::JSONCOL(JSONCOL *col1, PTDB tdbp) : DOSCOL(col1, tdbp) ...@@ -794,7 +833,7 @@ JSONCOL::JSONCOL(JSONCOL *col1, PTDB tdbp) : DOSCOL(col1, tdbp)
Xnod = col1->Xnod; Xnod = col1->Xnod;
Xpd = col1->Xpd; Xpd = col1->Xpd;
Parsed = col1->Parsed; Parsed = col1->Parsed;
} // end of JSONCOL copy constructor } // end of JSONCOL copy constructor
/***********************************************************************/ /***********************************************************************/
/* SetBuffer: prepare a column block for write operation. */ /* SetBuffer: prepare a column block for write operation. */
...@@ -809,6 +848,7 @@ bool JSONCOL::SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check) ...@@ -809,6 +848,7 @@ bool JSONCOL::SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check)
return true; return true;
Tjp = (TDBJSN*)To_Tdb; Tjp = (TDBJSN*)To_Tdb;
G = Tjp->G;
return false; return false;
} // end of SetBuffer } // end of SetBuffer
...@@ -1046,6 +1086,7 @@ void JSONCOL::SetJsonValue(PGLOBAL g, PVAL vp, PJVAL val, int n) ...@@ -1046,6 +1086,7 @@ void JSONCOL::SetJsonValue(PGLOBAL g, PVAL vp, PJVAL val, int n)
switch (val->GetValType()) { switch (val->GetValType()) {
case TYPE_STRG: case TYPE_STRG:
case TYPE_INTG: case TYPE_INTG:
case TYPE_BINT:
case TYPE_DBL: case TYPE_DBL:
vp->SetValue_pval(val->GetValue()); vp->SetValue_pval(val->GetValue());
break; break;
...@@ -1103,15 +1144,15 @@ PVAL JSONCOL::GetColumnValue(PGLOBAL g, PJSON row, int i) ...@@ -1103,15 +1144,15 @@ PVAL JSONCOL::GetColumnValue(PGLOBAL g, PJSON row, int i)
Value->SetValue(row->GetType() == TYPE_JAR ? row->size() : 1); Value->SetValue(row->GetType() == TYPE_JAR ? row->size() : 1);
return(Value); return(Value);
} else if (Nodes[i].Op == OP_XX) { } else if (Nodes[i].Op == OP_XX) {
return MakeJson(g, row); return MakeJson(G, row);
} else switch (row->GetType()) { } else switch (row->GetType()) {
case TYPE_JOB: case TYPE_JOB:
if (!Nodes[i].Key) { if (!Nodes[i].Key) {
// Expected Array was not there // Expected Array was not there, wrap the value
if (i < Nod-1) if (i < Nod-1)
continue; continue;
else else
val = new(g) JVALUE(row); val = new(G) JVALUE(row);
} else } else
val = ((PJOB)row)->GetValue(Nodes[i].Key); val = ((PJOB)row)->GetValue(Nodes[i].Key);
...@@ -1128,11 +1169,11 @@ PVAL JSONCOL::GetColumnValue(PGLOBAL g, PJSON row, int i) ...@@ -1128,11 +1169,11 @@ PVAL JSONCOL::GetColumnValue(PGLOBAL g, PJSON row, int i)
else else
return CalculateArray(g, arp, i); return CalculateArray(g, arp, i);
} else if (i < Nod-1) { } else {
strcpy(g->Message, "Unexpected array"); // Unexpected array, unwrap it as [0]
val = NULL; // Not an expected array
} else
val = arp->GetValue(0); val = arp->GetValue(0);
i--;
} // endif's
break; break;
case TYPE_JVAL: case TYPE_JVAL:
...@@ -1275,29 +1316,30 @@ PJSON JSONCOL::GetRow(PGLOBAL g) ...@@ -1275,29 +1316,30 @@ PJSON JSONCOL::GetRow(PGLOBAL g)
PJAR arp; PJAR arp;
PJSON nwr, row = Tjp->Row; PJSON nwr, row = Tjp->Row;
for (int i = 0; i < Nod-1 && row; i++) { for (int i = 0; i < Nod && row; i++) {
if (Nodes[i+1].Op == OP_XX) if (Nodes[i+1].Op == OP_XX)
break; break;
else switch (row->GetType()) { else switch (row->GetType()) {
case TYPE_JOB: case TYPE_JOB:
if (!Nodes[i].Key) if (!Nodes[i].Key)
// Expected Array was not there // Expected Array was not there, wrap the value
continue; continue;
val = ((PJOB)row)->GetValue(Nodes[i].Key); val = ((PJOB)row)->GetValue(Nodes[i].Key);
break; break;
case TYPE_JAR: case TYPE_JAR:
if (!Nodes[i].Key) {
arp = (PJAR)row; arp = (PJAR)row;
if (!Nodes[i].Key) {
if (Nodes[i].Op == OP_EQ) if (Nodes[i].Op == OP_EQ)
val = arp->GetValue(Nodes[i].Rank); val = arp->GetValue(Nodes[i].Rank);
else else
val = arp->GetValue(Nodes[i].Rx); val = arp->GetValue(Nodes[i].Rx);
} else { } else {
strcpy(g->Message, "Unexpected array"); // Unexpected array, unwrap it as [0]
val = NULL; // Not an expected array val = arp->GetValue(0);
i--;
} // endif Nodes } // endif Nodes
break; break;
...@@ -1318,15 +1360,15 @@ PJSON JSONCOL::GetRow(PGLOBAL g) ...@@ -1318,15 +1360,15 @@ PJSON JSONCOL::GetRow(PGLOBAL g)
break; break;
else if (!Nodes[i].Key) else if (!Nodes[i].Key)
// Construct intermediate array // Construct intermediate array
nwr = new(g) JARRAY; nwr = new(G) JARRAY;
else else
nwr = new(g) JOBJECT; nwr = new(G) JOBJECT;
if (row->GetType() == TYPE_JOB) { if (row->GetType() == TYPE_JOB) {
((PJOB)row)->SetValue(g, new(g) JVALUE(nwr), Nodes[i-1].Key); ((PJOB)row)->SetValue(G, new(G) JVALUE(nwr), Nodes[i-1].Key);
} else if (row->GetType() == TYPE_JAR) { } else if (row->GetType() == TYPE_JAR) {
((PJAR)row)->AddValue(g, new(g) JVALUE(nwr)); ((PJAR)row)->AddValue(G, new(G) JVALUE(nwr));
((PJAR)row)->InitArray(g); ((PJAR)row)->InitArray(G);
} else { } else {
strcpy(g->Message, "Wrong type when writing new row"); strcpy(g->Message, "Wrong type when writing new row");
nwr = NULL; nwr = NULL;
...@@ -1370,7 +1412,6 @@ void JSONCOL::WriteColumn(PGLOBAL g) ...@@ -1370,7 +1412,6 @@ void JSONCOL::WriteColumn(PGLOBAL g)
PJAR arp = NULL; PJAR arp = NULL;
PJVAL jvp = NULL; PJVAL jvp = NULL;
PJSON jsp, row = GetRow(g); PJSON jsp, row = GetRow(g);
JTYP type = row->GetType();
switch (row->GetType()) { switch (row->GetType()) {
case TYPE_JOB: objp = (PJOB)row; break; case TYPE_JOB: objp = (PJOB)row; break;
...@@ -1384,21 +1425,21 @@ void JSONCOL::WriteColumn(PGLOBAL g) ...@@ -1384,21 +1425,21 @@ void JSONCOL::WriteColumn(PGLOBAL g)
if (Nodes[Nod-1].Op == OP_XX) { if (Nodes[Nod-1].Op == OP_XX) {
s = Value->GetCharValue(); s = Value->GetCharValue();
if (!(jsp = ParseJson(g, s, (int)strlen(s), 0))) { if (!(jsp = ParseJson(G, s, (int)strlen(s)))) {
strcpy(g->Message, s); strcpy(g->Message, s);
longjmp(g->jumper[g->jump_level], 666); longjmp(g->jumper[g->jump_level], 666);
} // endif jsp } // endif jsp
if (arp) { if (arp) {
if (Nod > 1 && Nodes[Nod-2].Op == OP_EQ) if (Nod > 1 && Nodes[Nod-2].Op == OP_EQ)
arp->SetValue(g, new(g) JVALUE(jsp), Nodes[Nod-2].Rank); arp->SetValue(G, new(G) JVALUE(jsp), Nodes[Nod-2].Rank);
else else
arp->AddValue(g, new(g) JVALUE(jsp)); arp->AddValue(G, new(G) JVALUE(jsp));
arp->InitArray(g); arp->InitArray(G);
} else if (objp) { } else if (objp) {
if (Nod > 1 && Nodes[Nod-2].Key) if (Nod > 1 && Nodes[Nod-2].Key)
objp->SetValue(g, new(g) JVALUE(jsp), Nodes[Nod-2].Key); objp->SetValue(G, new(G) JVALUE(jsp), Nodes[Nod-2].Key);
} else if (jvp) } else if (jvp)
jvp->SetValue(jsp); jvp->SetValue(jsp);
...@@ -1409,17 +1450,19 @@ void JSONCOL::WriteColumn(PGLOBAL g) ...@@ -1409,17 +1450,19 @@ void JSONCOL::WriteColumn(PGLOBAL g)
// Passthru // Passthru
case TYPE_DATE: case TYPE_DATE:
case TYPE_INT: case TYPE_INT:
case TYPE_SHORT:
case TYPE_BIGINT:
case TYPE_DOUBLE: case TYPE_DOUBLE:
if (arp) { if (arp) {
if (Nodes[Nod-1].Op == OP_EQ) if (Nodes[Nod-1].Op == OP_EQ)
arp->SetValue(g, new(g) JVALUE(g, Value), Nodes[Nod-1].Rank); arp->SetValue(G, new(G) JVALUE(G, Value), Nodes[Nod-1].Rank);
else else
arp->AddValue(g, new(g) JVALUE(g, Value)); arp->AddValue(G, new(G) JVALUE(G, Value));
arp->InitArray(g); arp->InitArray(G);
} else if (objp) { } else if (objp) {
if (Nodes[Nod-1].Key) if (Nodes[Nod-1].Key)
objp->SetValue(g, new(g) JVALUE(g, Value), Nodes[Nod-1].Key); objp->SetValue(G, new(G) JVALUE(G, Value), Nodes[Nod-1].Key);
} else if (jvp) } else if (jvp)
jvp->SetValue(Value); jvp->SetValue(Value);
...@@ -1522,7 +1565,7 @@ int TDBJSON::MakeDocument(PGLOBAL g) ...@@ -1522,7 +1565,7 @@ int TDBJSON::MakeDocument(PGLOBAL g)
/* Parse the json file and allocate its tree structure. */ /* Parse the json file and allocate its tree structure. */
/*********************************************************************/ /*********************************************************************/
g->Message[0] = 0; g->Message[0] = 0;
jsp = Top = ParseJson(g, memory, len, Pretty); jsp = Top = ParseJson(g, memory, len, &Pretty);
Txfp->CloseTableFile(g, false); Txfp->CloseTableFile(g, false);
Mode = mode; // Restore saved Mode Mode = mode; // Restore saved Mode
...@@ -1540,7 +1583,7 @@ int TDBJSON::MakeDocument(PGLOBAL g) ...@@ -1540,7 +1583,7 @@ int TDBJSON::MakeDocument(PGLOBAL g)
if (*objpath != '[') { // objpass is a key if (*objpath != '[') { // objpass is a key
if (jsp->GetType() != TYPE_JOB) { if (jsp->GetType() != TYPE_JOB) {
strcpy(g->Message, "Table path does no match json file"); strcpy(g->Message, "Table path does not match the json file");
return RC_FX; return RC_FX;
} // endif Type } // endif Type
...@@ -1556,7 +1599,7 @@ int TDBJSON::MakeDocument(PGLOBAL g) ...@@ -1556,7 +1599,7 @@ int TDBJSON::MakeDocument(PGLOBAL g)
} else if (objpath[strlen(objpath)-1] == ']') { } else if (objpath[strlen(objpath)-1] == ']') {
if (jsp->GetType() != TYPE_JAR) { if (jsp->GetType() != TYPE_JAR) {
strcpy(g->Message, "Table path does no match json file"); strcpy(g->Message, "Table path does not match the json file");
return RC_FX; return RC_FX;
} // endif Type } // endif Type
...@@ -1836,8 +1879,6 @@ void TDBJSON::CloseDB(PGLOBAL g) ...@@ -1836,8 +1879,6 @@ void TDBJSON::CloseDB(PGLOBAL g)
// Save the modified document // Save the modified document
char filename[_MAX_PATH]; char filename[_MAX_PATH];
PSZ msg;
FILE *fop;
Doc->InitArray(g); Doc->InitArray(g);
...@@ -1845,12 +1886,8 @@ void TDBJSON::CloseDB(PGLOBAL g) ...@@ -1845,12 +1886,8 @@ void TDBJSON::CloseDB(PGLOBAL g)
PlugSetPath(filename, ((PJDEF)To_Def)->Fn, GetPath()); PlugSetPath(filename, ((PJDEF)To_Def)->Fn, GetPath());
// Serialize the modified table // Serialize the modified table
if (!(fop = fopen(filename, "wb"))) { if (!Serialize(g, Top, filename, Pretty))
sprintf(g->Message, MSG(OPEN_MODE_ERROR), puts(g->Message);
"w", (int)errno, filename);
strcat(strcat(g->Message, ": "), strerror(errno));
} else if ((msg = Serialize(g, Top, fop, Pretty)))
puts(msg);
} // end of CloseDB } // end of CloseDB
......
...@@ -68,7 +68,8 @@ class JSONDEF : public DOSDEF { /* Table description */ ...@@ -68,7 +68,8 @@ class JSONDEF : public DOSDEF { /* Table description */
/***********************************************************************/ /***********************************************************************/
class TDBJSN : public TDBDOS { class TDBJSN : public TDBDOS {
friend class JSONCOL; friend class JSONCOL;
public: friend class JSONDEF;
public:
// Constructor // Constructor
TDBJSN(PJDEF tdp, PTXF txfp); TDBJSN(PJDEF tdp, PTXF txfp);
TDBJSN(TDBJSN *tdbp); TDBJSN(TDBJSN *tdbp);
...@@ -90,14 +91,16 @@ class TDBJSN : public TDBDOS { ...@@ -90,14 +91,16 @@ class TDBJSN : public TDBDOS {
virtual int Cardinality(PGLOBAL g); virtual int Cardinality(PGLOBAL g);
virtual int GetMaxSize(PGLOBAL g); virtual int GetMaxSize(PGLOBAL g);
virtual bool OpenDB(PGLOBAL g); virtual bool OpenDB(PGLOBAL g);
virtual bool PrepareWriting(PGLOBAL g);
virtual int ReadDB(PGLOBAL g); virtual int ReadDB(PGLOBAL g);
virtual bool PrepareWriting(PGLOBAL g);
virtual int WriteDB(PGLOBAL g);
protected: protected:
PJSON FindRow(PGLOBAL g); PJSON FindRow(PGLOBAL g);
int MakeTopTree(PGLOBAL g, PJSON jsp); int MakeTopTree(PGLOBAL g, PJSON jsp);
// Members // Members
PGLOBAL G; // Support of parse memory
PJSON Top; // The top JSON tree PJSON Top; // The top JSON tree
PJSON Row; // The current row PJSON Row; // The current row
PJSON Val; // The value of the current row PJSON Val; // The value of the current row
...@@ -154,6 +157,7 @@ class JSONCOL : public DOSCOL { ...@@ -154,6 +157,7 @@ class JSONCOL : public DOSCOL {
JSONCOL(void) {} JSONCOL(void) {}
// Members // Members
PGLOBAL G; // Support of parse memory
TDBJSN *Tjp; // To the JSN table block TDBJSN *Tjp; // To the JSN table block
PVAL MulVal; // To value used by multiple column PVAL MulVal; // To value used by multiple column
char *Jpath; // The json path char *Jpath; // The json path
...@@ -170,6 +174,7 @@ class JSONCOL : public DOSCOL { ...@@ -170,6 +174,7 @@ class JSONCOL : public DOSCOL {
/* This is the JSON Access Method class declaration. */ /* This is the JSON Access Method class declaration. */
/***********************************************************************/ /***********************************************************************/
class TDBJSON : public TDBJSN { class TDBJSON : public TDBJSN {
friend class JSONDEF;
friend class JSONCOL; friend class JSONCOL;
public: public:
// Constructor // Constructor
......
...@@ -1054,32 +1054,14 @@ int TDBMYSQL::SendCommand(PGLOBAL g) ...@@ -1054,32 +1054,14 @@ int TDBMYSQL::SendCommand(PGLOBAL g)
/***********************************************************************/ /***********************************************************************/
/* Data Base indexed read routine for MYSQL access method. */ /* Data Base indexed read routine for MYSQL access method. */
/***********************************************************************/ /***********************************************************************/
bool TDBMYSQL::ReadKey(PGLOBAL g, OPVAL op, const void *key, int len) bool TDBMYSQL::ReadKey(PGLOBAL g, OPVAL op, const key_range *kr)
{ {
bool oom;
int oldlen = Query->GetLength(); int oldlen = Query->GetLength();
PHC hc = To_Def->GetHandler(); PHC hc = To_Def->GetHandler();
if (op == OP_FIRST && hc->end_range) { if (!(kr || hc->end_range) || op == OP_NEXT ||
#ifdef _DEBUG
assert(!key);
#endif
key_range *end_key = &hc->save_end_range;
key = end_key->key;
len = end_key->length;
switch (end_key->flag) {
case HA_READ_BEFORE_KEY: op = OP_LT; break;
case HA_READ_AFTER_KEY: op = OP_LE; break;
default: key = NULL;
} // endswitch flag
} // endif OP_FIRST
if (!key || op == OP_NEXT ||
Mode == MODE_UPDATE || Mode == MODE_DELETE) { Mode == MODE_UPDATE || Mode == MODE_DELETE) {
if (!key && Mode == MODE_READX) { if (!kr && Mode == MODE_READX) {
// This is a false indexed read // This is a false indexed read
m_Rc = Myc.ExecSQL(g, Query->GetStr()); m_Rc = Myc.ExecSQL(g, Query->GetStr());
Mode = MODE_READ; Mode = MODE_READ;
...@@ -1091,22 +1073,34 @@ bool TDBMYSQL::ReadKey(PGLOBAL g, OPVAL op, const void *key, int len) ...@@ -1091,22 +1073,34 @@ bool TDBMYSQL::ReadKey(PGLOBAL g, OPVAL op, const void *key, int len)
if (Myc.m_Res) if (Myc.m_Res)
Myc.FreeResult(); Myc.FreeResult();
if (hc->MakeKeyWhere(g, Query, op, '`', key, len)) if (hc->MakeKeyWhere(g, Query, op, '`', kr))
return true; return true;
if (To_CondFil) { if (To_CondFil) {
oom = Query->Append(" AND ("); if (To_CondFil->Idx != hc->active_index) {
oom |= Query->Append(To_CondFil->Body); To_CondFil->Idx = hc->active_index;
To_CondFil->Body= (char*)PlugSubAlloc(g, NULL, 0);
*To_CondFil->Body= 0;
if ((To_CondFil = hc->CheckCond(g, To_CondFil, To_CondFil->Cond)))
PlugSubAlloc(g, NULL, strlen(To_CondFil->Body) + 1);
if ((oom |= Query->Append(')'))) { } // endif active_index
if (To_CondFil)
if (Query->Append(" AND ") || Query->Append(To_CondFil->Body)) {
strcpy(g->Message, "Readkey: Out of memory"); strcpy(g->Message, "Readkey: Out of memory");
return true; return true;
} // endif oom } // endif Append
} // endif To_Condfil } // endif To_Condfil
Mode = MODE_READ;
} // endif's op } // endif's op
if (trace)
htrc("MYSQL ReadKey: Query=%s\n", Query->GetStr());
m_Rc = Myc.ExecSQL(g, Query->GetStr()); m_Rc = Myc.ExecSQL(g, Query->GetStr());
Query->Truncate(oldlen); Query->Truncate(oldlen);
return (m_Rc == RC_FX) ? true : false; return (m_Rc == RC_FX) ? true : false;
......
...@@ -99,7 +99,7 @@ class TDBMYSQL : public TDBASE { ...@@ -99,7 +99,7 @@ class TDBMYSQL : public TDBASE {
virtual int WriteDB(PGLOBAL g); virtual int WriteDB(PGLOBAL g);
virtual int DeleteDB(PGLOBAL g, int irc); virtual int DeleteDB(PGLOBAL g, int irc);
virtual void CloseDB(PGLOBAL g); virtual void CloseDB(PGLOBAL g);
virtual bool ReadKey(PGLOBAL g, OPVAL op, const void *key, int len); virtual bool ReadKey(PGLOBAL g, OPVAL op, const key_range *kr);
// Specific routines // Specific routines
bool SetColumnRanks(PGLOBAL g); bool SetColumnRanks(PGLOBAL g);
......
/************* Tabodbc C++ Program Source Code File (.CPP) *************/ /************* Tabodbc C++ Program Source Code File (.CPP) *************/
/* PROGRAM NAME: TABODBC */ /* PROGRAM NAME: TABODBC */
/* ------------- */ /* ------------- */
/* Version 2.9 */ /* Version 3.0 */
/* */ /* */
/* COPYRIGHT: */ /* COPYRIGHT: */
/* ---------- */ /* ---------- */
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
/* Include relevant MariaDB header file. */ /* Include relevant MariaDB header file. */
/***********************************************************************/ /***********************************************************************/
#include "my_global.h" #include "my_global.h"
#include "sql_class.h"
#if defined(__WIN__) #if defined(__WIN__)
#include <io.h> #include <io.h>
#include <fcntl.h> #include <fcntl.h>
...@@ -72,6 +73,7 @@ ...@@ -72,6 +73,7 @@
#include "reldef.h" #include "reldef.h"
#include "tabcol.h" #include "tabcol.h"
#include "valblk.h" #include "valblk.h"
#include "ha_connect.h"
#include "sql_string.h" #include "sql_string.h"
...@@ -397,176 +399,209 @@ int TDBODBC::Decode(char *txt, char *buf, size_t n) ...@@ -397,176 +399,209 @@ int TDBODBC::Decode(char *txt, char *buf, size_t n)
/* Note: when implementing EOM filtering, column only used in local */ /* Note: when implementing EOM filtering, column only used in local */
/* filter should be removed from column list. */ /* filter should be removed from column list. */
/***********************************************************************/ /***********************************************************************/
char *TDBODBC::MakeSQL(PGLOBAL g, bool cnt) bool TDBODBC::MakeSQL(PGLOBAL g, bool cnt)
{ {
char *colist, *tabname, *sql, buf[NAM_LEN * 3]; char *schmp = NULL, *catp = NULL, buf[NAM_LEN * 3];
LPCSTR schmp = NULL, catp = NULL; int len;
int len, ncol = 0; bool oom = false, first = true;
bool first = true;
PTABLE tablep = To_Table; PTABLE tablep = To_Table;
PCOL colp; PCOL colp;
if (Srcdef) if (Srcdef) {
return Srcdef; Query = new(g)STRING(g, 0, Srcdef);
return false;
} // endif Srcdef
// Allocate the string used to contain the Query
Query = new(g)STRING(g, 1023, "SELECT ");
if (!cnt) { if (!cnt) {
if (Columns) {
// Normal SQL statement to retrieve results // Normal SQL statement to retrieve results
for (colp = Columns; colp; colp = colp->GetNext())
if (!colp->IsSpecial())
ncol++;
if (ncol) {
colist = (char*)PlugSubAlloc(g, NULL, (NAM_LEN + 4) * ncol);
for (colp = Columns; colp; colp = colp->GetNext()) for (colp = Columns; colp; colp = colp->GetNext())
if (!colp->IsSpecial()) { if (!colp->IsSpecial()) {
// Column name can be in UTF-8 encoding if (!first)
/*rc=*/ Decode(colp->GetName(), buf, sizeof(buf)); oom |= Query->Append(", ");
else
if (Quote) {
if (first) {
strcat(strcat(strcpy(colist, Quote), buf), Quote);
first = false; first = false;
} else
strcat(strcat(strcat(strcat(colist, ", "),
Quote), buf), Quote);
} else { // Column name can be encoded in UTF-8
if (first) { Decode(colp->GetName(), buf, sizeof(buf));
strcpy(colist, buf);
first = false;
} else
strcat(strcat(colist, ", "), buf);
} // endif Quote if (Quote) {
// Put column name between identifier quotes in case in contains blanks
oom |= Query->Append(Quote);
oom |= Query->Append(buf);
oom |= Query->Append(Quote);
} else
oom |= Query->Append(buf);
} // endif !Special } // endif colp
} else { } else
// ncol == 0 can occur for queries such that sql count(*) from... // !Columns can occur for queries such that sql count(*) from...
// for which we will count the rows from sql * from... // for which we will count the rows from sql * from...
colist = (char*)PlugSubAlloc(g, NULL, 2); oom |= Query->Append('*');
strcpy(colist, "*");
} // endif ncol
} else { } else
// SQL statement used to retrieve the size of the result // SQL statement used to retrieve the size of the result
colist = (char*)PlugSubAlloc(g, NULL, 9); oom |= Query->Append("count(*)");
strcpy(colist, "count(*)");
} // endif cnt
// Table name can be encoded in UTF-8
/*rc = */Decode(TableName, buf, sizeof(buf));
// Put table name between identifier quotes in case in contains blanks
tabname = (char*)PlugSubAlloc(g, NULL, strlen(buf) + 3);
if (Quote)
strcat(strcat(strcpy(tabname, Quote), buf), Quote);
else
strcpy(tabname, buf);
// Below 14 is length of 'select ' + length of ' from ' + 1 oom |= Query->Append(" FROM ");
len = (strlen(colist) + strlen(buf) + 14);
len += (To_CondFil ? strlen(To_CondFil->Body) + 7 : 0);
if (Catalog && *Catalog) if (Catalog && *Catalog)
catp = Catalog; catp = Catalog;
if (catp)
len += (strlen(catp) + 2);
if (tablep->GetSchema()) if (tablep->GetSchema())
schmp = tablep->GetSchema(); schmp = (char*)tablep->GetSchema();
else if (Schema && *Schema) else if (Schema && *Schema)
schmp = Schema; schmp = Schema;
if (schmp) if (catp) {
len += (strlen(schmp) + 1); oom |= Query->Append(catp);
sql = (char*)PlugSubAlloc(g, NULL, len); if (schmp) {
strcat(strcat(strcpy(sql, "SELECT "), colist), " FROM "); oom |= Query->Append('.');
oom |= Query->Append(schmp);
} // endif schmp
if (catp) { oom |= Query->Append('.');
strcat(sql, catp); } else if (schmp) {
oom |= Query->Append(schmp);
oom |= Query->Append('.');
} // endif schmp
if (schmp) // Table name can be encoded in UTF-8
strcat(strcat(sql, "."), schmp); Decode(TableName, buf, sizeof(buf));
else
strcat(sql, ".");
strcat(sql, "."); if (Quote) {
} else if (schmp) // Put table name between identifier quotes in case in contains blanks
strcat(strcat(sql, schmp), "."); oom |= Query->Append(Quote);
oom |= Query->Append(buf);
oom |= Query->Append(Quote);
} else
oom |= Query->Append(buf);
strcat(sql, tabname); len = Query->GetLength();
if (To_CondFil) if (To_CondFil) {
strcat(strcat(sql, " WHERE "), To_CondFil->Body); if (Mode == MODE_READ) {
oom |= Query->Append(" WHERE ");
oom |= Query->Append(To_CondFil->Body);
len = Query->GetLength() + 1;
} else
len += (strlen(To_CondFil->Body) + 256);
} else
len += ((Mode == MODE_READX) ? 256 : 1);
if (oom || Query->Resize(len)) {
strcpy(g->Message, "MakeSQL: Out of memory");
return true;
} // endif oom
if (trace) if (trace)
htrc("sql: '%s'\n", sql); htrc("Query=%s\n", Query->GetStr());
return sql; return false;
} // end of MakeSQL } // end of MakeSQL
/***********************************************************************/ /***********************************************************************/
/* MakeInsert: make the Insert statement used with ODBC connection. */ /* MakeInsert: make the Insert statement used with ODBC connection. */
/***********************************************************************/ /***********************************************************************/
char *TDBODBC::MakeInsert(PGLOBAL g) bool TDBODBC::MakeInsert(PGLOBAL g)
{ {
char *stmt, *colist, *valist, buf[NAM_LEN * 3]; char *schmp = NULL, *catp = NULL, buf[NAM_LEN * 3];
// char *tk = "`";
int len = 0; int len = 0;
bool b = FALSE; bool b = false, oom = false;
PTABLE tablep = To_Table;
PCOL colp; PCOL colp;
for (colp = Columns; colp; colp = colp->GetNext()) for (colp = Columns; colp; colp = colp->GetNext())
if (colp->IsSpecial()) { if (colp->IsSpecial()) {
strcpy(g->Message, MSG(NO_ODBC_SPECOL)); strcpy(g->Message, MSG(NO_ODBC_SPECOL));
return NULL; return true;
} else { } else {
len += (strlen(colp->GetName()) + 4); // Column name can be encoded in UTF-8
Decode(colp->GetName(), buf, sizeof(buf));
len += (strlen(buf) + 6); // comma + quotes + valist
((PODBCCOL)colp)->Rank = ++Nparm; ((PODBCCOL)colp)->Rank = ++Nparm;
} // endif colp } // endif colp
colist = (char*)PlugSubAlloc(g, NULL, len); // Below 32 is enough to contain the fixed part of the query
*colist = '\0'; if (Catalog && *Catalog)
valist = (char*)PlugSubAlloc(g, NULL, 2 * Nparm); catp = Catalog;
*valist = '\0';
for (colp = Columns; colp; colp = colp->GetNext()) { if (catp)
if (b) { len += strlen(catp) + 1;
strcat(colist, ", ");
strcat(valist, ","); if (tablep->GetSchema())
schmp = (char*)tablep->GetSchema();
else if (Schema && *Schema)
schmp = Schema;
if (schmp)
len += strlen(schmp) + 1;
// Column name can be encoded in UTF-8
Decode(TableName, buf, sizeof(buf));
len += (strlen(buf) + 32);
Query = new(g) STRING(g, len, "INSERT INTO ");
if (catp) {
oom |= Query->Append(catp);
if (schmp) {
oom |= Query->Append('.');
oom |= Query->Append(schmp);
} // endif schmp
oom |= Query->Append('.');
} else if (schmp) {
oom |= Query->Append(schmp);
oom |= Query->Append('.');
} // endif schmp
if (Quote) {
// Put table name between identifier quotes in case in contains blanks
oom |= Query->Append(Quote);
oom |= Query->Append(buf);
oom |= Query->Append(Quote);
} else } else
oom |= Query->Append(buf);
oom |= Query->Append('(');
for (colp = Columns; colp; colp = colp->GetNext()) {
if (b)
oom |= Query->Append(", ");
else
b = true; b = true;
// Column name can be in UTF-8 encoding // Column name can be in UTF-8 encoding
Decode(colp->GetName(), buf, sizeof(buf)); Decode(colp->GetName(), buf, sizeof(buf));
if (Quote) if (Quote) {
strcat(strcat(strcat(colist, Quote), buf), Quote); // Put column name between identifier quotes in case in contains blanks
else oom |= Query->Append(Quote);
strcat(colist, buf); oom |= Query->Append(buf);
oom |= Query->Append(Quote);
} else
oom |= Query->Append(buf);
strcat(valist, "?"); // Parameter marker
} // endfor colp } // endfor colp
// Below 32 is enough to contain the fixed part of the query oom |= Query->Append(") VALUES (");
len = (strlen(TableName) + strlen(colist) + strlen(valist) + 32);
stmt = (char*)PlugSubAlloc(g, NULL, len);
strcpy(stmt, "INSERT INTO ");
if (Quote) for (int i = 0; i < Nparm; i++)
strcat(strcat(strcat(stmt, Quote), TableName), Quote); oom |= Query->Append("?,");
else
strcat(stmt, TableName);
strcat(strcat(strcat(stmt, " ("), colist), ") VALUES ("); if (oom)
strcat(strcat(stmt, valist), ")"); strcpy(g->Message, "MakeInsert: Out of memory");
else
Query->RepLast(')');
return stmt; return oom;
} // end of MakeInsert } // end of MakeInsert
/***********************************************************************/ /***********************************************************************/
...@@ -591,7 +626,7 @@ bool TDBODBC::BindParameters(PGLOBAL g) ...@@ -591,7 +626,7 @@ bool TDBODBC::BindParameters(PGLOBAL g)
/* MakeCommand: make the Update or Delete statement to send to the */ /* MakeCommand: make the Update or Delete statement to send to the */
/* MySQL server. Limited to remote values and filtering. */ /* MySQL server. Limited to remote values and filtering. */
/***********************************************************************/ /***********************************************************************/
char *TDBODBC::MakeCommand(PGLOBAL g) bool TDBODBC::MakeCommand(PGLOBAL g)
{ {
char *p, *stmt, name[68], *body = NULL, *qc = Ocp->GetQuoteChar(); char *p, *stmt, name[68], *body = NULL, *qc = Ocp->GetQuoteChar();
char *qrystr = (char*)PlugSubAlloc(g, NULL, strlen(Qrystr) + 1); char *qrystr = (char*)PlugSubAlloc(g, NULL, strlen(Qrystr) + 1);
...@@ -649,7 +684,8 @@ char *TDBODBC::MakeCommand(PGLOBAL g) ...@@ -649,7 +684,8 @@ char *TDBODBC::MakeCommand(PGLOBAL g)
return NULL; return NULL;
} // endif p } // endif p
return stmt; Query = new(g) STRING(g, 0, stmt);
return (!Query->GetSize());
} // end of MakeCommand } // end of MakeCommand
#if 0 #if 0
...@@ -826,10 +862,12 @@ bool TDBODBC::OpenDB(PGLOBAL g) ...@@ -826,10 +862,12 @@ bool TDBODBC::OpenDB(PGLOBAL g)
if (Memory < 3) { if (Memory < 3) {
// Method will depend on cursor type // Method will depend on cursor type
if ((Rbuf = Ocp->Rewind(Query, (PODBCCOL)Columns)) < 0) { if ((Rbuf = Ocp->Rewind(Query->GetStr(), (PODBCCOL)Columns)) < 0)
if (Mode != MODE_READX) {
Ocp->Close(); Ocp->Close();
return true; return true;
} // endif Rewind } else
Rbuf = 0;
} else } else
Rbuf = Qrp->Nblin; Rbuf = Qrp->Nblin;
...@@ -864,15 +902,14 @@ bool TDBODBC::OpenDB(PGLOBAL g) ...@@ -864,15 +902,14 @@ bool TDBODBC::OpenDB(PGLOBAL g)
/*********************************************************************/ /*********************************************************************/
if (Mode == MODE_READ || Mode == MODE_READX) { if (Mode == MODE_READ || Mode == MODE_READX) {
if (Memory > 1 && !Srcdef) { if (Memory > 1 && !Srcdef) {
char *Sql;
int n; int n;
if ((Sql = MakeSQL(g, true))) { if (!MakeSQL(g, true)) {
// Allocate a Count(*) column // Allocate a Count(*) column
Cnp = new(g) ODBCCOL; Cnp = new(g) ODBCCOL;
Cnp->InitValue(g); Cnp->InitValue(g);
if ((n = Ocp->GetResultSize(Sql, Cnp)) < 0) { if ((n = Ocp->GetResultSize(Query->GetStr(), Cnp)) < 0) {
strcpy(g->Message, "Cannot get result size"); strcpy(g->Message, "Cannot get result size");
return true; return true;
} // endif n } // endif n
...@@ -882,36 +919,36 @@ bool TDBODBC::OpenDB(PGLOBAL g) ...@@ -882,36 +919,36 @@ bool TDBODBC::OpenDB(PGLOBAL g)
if ((Qrp = Ocp->AllocateResult(g))) if ((Qrp = Ocp->AllocateResult(g)))
Memory = 2; // Must be filled Memory = 2; // Must be filled
else { else {
strcpy(g->Message, "Memory allocation failed"); strcpy(g->Message, "Result set memory allocation failed");
return true; return true;
} // endif n } // endif n
Ocp->m_Rows = 0; Ocp->m_Rows = 0;
} else { } else
strcpy(g->Message, "MakeSQL failed");
return true; return true;
} // endif Sql
} // endif Memory } // endif Memory
if ((Query = MakeSQL(g, false))) { if (!(rc = MakeSQL(g, false))) {
for (PODBCCOL colp = (PODBCCOL)Columns; colp; for (PODBCCOL colp = (PODBCCOL)Columns; colp;
colp = (PODBCCOL)colp->GetNext()) colp = (PODBCCOL)colp->GetNext())
if (!colp->IsSpecial()) if (!colp->IsSpecial())
colp->AllocateBuffers(g, Rows); colp->AllocateBuffers(g, Rows);
rc = ((Rows = Ocp->ExecDirectSQL(Query, (PODBCCOL)Columns)) < 0); rc = (Mode == MODE_READ)
} // endif Query ? ((Rows = Ocp->ExecDirectSQL(Query->GetStr(), (PODBCCOL)Columns)) < 0)
: false;
} // endif rc
} else if (Mode == MODE_INSERT) { } else if (Mode == MODE_INSERT) {
if ((Query = MakeInsert(g))) { if (!(rc = MakeInsert(g))) {
if (Nparm != Ocp->PrepareSQL(Query)) { if (Nparm != Ocp->PrepareSQL(Query->GetStr())) {
strcpy(g->Message, MSG(PARM_CNT_MISS)); strcpy(g->Message, MSG(PARM_CNT_MISS));
rc = true; rc = true;
} else } else
rc = BindParameters(g); rc = BindParameters(g);
} // endif Query } // endif rc
} else if (Mode == MODE_UPDATE || Mode == MODE_DELETE) { } else if (Mode == MODE_UPDATE || Mode == MODE_DELETE) {
rc = false; // wait for CheckCond before calling MakeCommand(g); rc = false; // wait for CheckCond before calling MakeCommand(g);
...@@ -969,6 +1006,59 @@ bool TDBODBC::SetRecpos(PGLOBAL g, int recpos) ...@@ -969,6 +1006,59 @@ bool TDBODBC::SetRecpos(PGLOBAL g, int recpos)
return false; return false;
} // end of SetRecpos } // end of SetRecpos
/***********************************************************************/
/* Data Base indexed read routine for MYSQL access method. */
/***********************************************************************/
bool TDBODBC::ReadKey(PGLOBAL g, OPVAL op, const key_range *kr)
{
char c = Quote ? *Quote : 0;
int oldlen = Query->GetLength();
PHC hc = To_Def->GetHandler();
if (!(kr || hc->end_range) || op == OP_NEXT ||
Mode == MODE_UPDATE || Mode == MODE_DELETE) {
if (!kr && Mode == MODE_READX) {
// This is a false indexed read
Rows = Ocp->ExecDirectSQL((char*)Query->GetStr(), (PODBCCOL)Columns);
Mode = MODE_READ;
return (Rows < 0);
} // endif key
return false;
} else {
if (To_Def->GetHandler()->MakeKeyWhere(g, Query, op, c, kr))
return true;
if (To_CondFil) {
if (To_CondFil->Idx != hc->active_index) {
To_CondFil->Idx = hc->active_index;
To_CondFil->Body= (char*)PlugSubAlloc(g, NULL, 0);
*To_CondFil->Body= 0;
if ((To_CondFil = hc->CheckCond(g, To_CondFil, To_CondFil->Cond)))
PlugSubAlloc(g, NULL, strlen(To_CondFil->Body) + 1);
} // endif active_index
if (To_CondFil)
if (Query->Append(" AND ") || Query->Append(To_CondFil->Body)) {
strcpy(g->Message, "Readkey: Out of memory");
return true;
} // endif Append
} // endif To_Condfil
Mode = MODE_READ;
} // endif's op
if (trace)
htrc("ODBC ReadKey: Query=%s\n", Query->GetStr());
Rows = Ocp->ExecDirectSQL((char*)Query->GetStr(), (PODBCCOL)Columns);
Query->Truncate(oldlen);
return (Rows < 0);
} // end of ReadKey
/***********************************************************************/ /***********************************************************************/
/* VRDNDOS: Data Base read routine for odbc access method. */ /* VRDNDOS: Data Base read routine for odbc access method. */
/***********************************************************************/ /***********************************************************************/
...@@ -981,11 +1071,11 @@ int TDBODBC::ReadDB(PGLOBAL g) ...@@ -981,11 +1071,11 @@ int TDBODBC::ReadDB(PGLOBAL g)
GetTdb_No(), Mode, To_Key_Col, To_Link, To_Kindex); GetTdb_No(), Mode, To_Key_Col, To_Link, To_Kindex);
if (Mode == MODE_UPDATE || Mode == MODE_DELETE) { if (Mode == MODE_UPDATE || Mode == MODE_DELETE) {
if (!Query && !(Query = MakeCommand(g))) if (!Query && MakeCommand(g))
return RC_FX; return RC_FX;
// Send the UPDATE/DELETE command to the remote table // Send the UPDATE/DELETE command to the remote table
if (!Ocp->ExecSQLcommand(Query)) { if (!Ocp->ExecSQLcommand(Query->GetStr())) {
sprintf(g->Message, "%s: %d affected rows", TableName, AftRows); sprintf(g->Message, "%s: %d affected rows", TableName, AftRows);
if (trace) if (trace)
...@@ -1063,11 +1153,11 @@ int TDBODBC::WriteDB(PGLOBAL g) ...@@ -1063,11 +1153,11 @@ int TDBODBC::WriteDB(PGLOBAL g)
int TDBODBC::DeleteDB(PGLOBAL g, int irc) int TDBODBC::DeleteDB(PGLOBAL g, int irc)
{ {
if (irc == RC_FX) { if (irc == RC_FX) {
if (!Query && !(Query = MakeCommand(g))) if (!Query && MakeCommand(g))
return RC_FX; return RC_FX;
// Send the DELETE (all) command to the remote table // Send the DELETE (all) command to the remote table
if (!Ocp->ExecSQLcommand(Query)) { if (!Ocp->ExecSQLcommand(Query->GetStr())) {
sprintf(g->Message, "%s: %d affected rows", TableName, AftRows); sprintf(g->Message, "%s: %d affected rows", TableName, AftRows);
if (trace) if (trace)
...@@ -1279,12 +1369,7 @@ void ODBCCOL::ReadColumn(PGLOBAL g) ...@@ -1279,12 +1369,7 @@ void ODBCCOL::ReadColumn(PGLOBAL g)
} // endif Buf_Type } // endif Buf_Type
// Nulls are handled by StrLen[n] == SQL_NULL_DATA if (trace > 1) {
// MDEV-8561
//if (Value->IsZero())
// Value->SetNull(Nullable);
if (trace) {
char buf[64]; char buf[64];
htrc("ODBC Column %s: rows=%d buf=%p type=%d value=%s\n", htrc("ODBC Column %s: rows=%d buf=%p type=%d value=%s\n",
...@@ -1572,9 +1657,12 @@ bool TDBXDBC::OpenDB(PGLOBAL g) ...@@ -1572,9 +1657,12 @@ bool TDBXDBC::OpenDB(PGLOBAL g)
int TDBXDBC::ReadDB(PGLOBAL g) int TDBXDBC::ReadDB(PGLOBAL g)
{ {
if (Cmdlist) { if (Cmdlist) {
Query = Cmdlist->Cmd; if (!Query)
Query = new(g)STRING(g, 0, Cmdlist->Cmd);
else
Query->Set(Cmdlist->Cmd);
if (Ocp->ExecSQLcommand(Query)) if (Ocp->ExecSQLcommand(Query->GetStr()))
Nerr++; Nerr++;
Fpos++; // Used for progress info Fpos++; // Used for progress info
...@@ -1632,7 +1720,7 @@ void XSRCCOL::ReadColumn(PGLOBAL g) ...@@ -1632,7 +1720,7 @@ void XSRCCOL::ReadColumn(PGLOBAL g)
PTDBXDBC tdbp = (PTDBXDBC)To_Tdb; PTDBXDBC tdbp = (PTDBXDBC)To_Tdb;
switch (Flag) { switch (Flag) {
case 0: Value->SetValue_psz(tdbp->Query); break; case 0: Value->SetValue_psz(tdbp->Query->GetStr()); break;
case 1: Value->SetValue(tdbp->AftRows); break; case 1: Value->SetValue(tdbp->AftRows); break;
case 2: Value->SetValue_psz(g->Message); break; case 2: Value->SetValue_psz(g->Message); break;
default: Value->SetValue_psz("Invalid Flag"); break; default: Value->SetValue_psz("Invalid Flag"); break;
......
...@@ -42,6 +42,7 @@ class DllExport ODBCDEF : public TABDEF { /* Logical table description */ ...@@ -42,6 +42,7 @@ class DllExport ODBCDEF : public TABDEF { /* Logical table description */
int GetOptions(void) {return Options;} int GetOptions(void) {return Options;}
// Methods // Methods
virtual int Indexable(void) {return 2;}
virtual bool DefineAM(PGLOBAL g, LPCSTR am, int poff); virtual bool DefineAM(PGLOBAL g, LPCSTR am, int poff);
virtual PTDB GetTable(PGLOBAL g, MODE m); virtual PTDB GetTable(PGLOBAL g, MODE m);
...@@ -111,15 +112,14 @@ class TDBODBC : public TDBASE { ...@@ -111,15 +112,14 @@ class TDBODBC : public TDBASE {
virtual int WriteDB(PGLOBAL g); virtual int WriteDB(PGLOBAL g);
virtual int DeleteDB(PGLOBAL g, int irc); virtual int DeleteDB(PGLOBAL g, int irc);
virtual void CloseDB(PGLOBAL g); virtual void CloseDB(PGLOBAL g);
virtual bool ReadKey(PGLOBAL g, OPVAL op, const void *key, int len) virtual bool ReadKey(PGLOBAL g, OPVAL op, const key_range *kr);
{return true;}
protected: protected:
// Internal functions // Internal functions
int Decode(char *utf, char *buf, size_t n); int Decode(char *utf, char *buf, size_t n);
char *MakeSQL(PGLOBAL g, bool cnt); bool MakeSQL(PGLOBAL g, bool cnt);
char *MakeInsert(PGLOBAL g); bool MakeInsert(PGLOBAL g);
char *MakeCommand(PGLOBAL g); bool MakeCommand(PGLOBAL g);
//bool MakeFilter(PGLOBAL g, bool c); //bool MakeFilter(PGLOBAL g, bool c);
bool BindParameters(PGLOBAL g); bool BindParameters(PGLOBAL g);
//char *MakeUpdate(PGLOBAL g); //char *MakeUpdate(PGLOBAL g);
...@@ -129,6 +129,7 @@ class TDBODBC : public TDBASE { ...@@ -129,6 +129,7 @@ class TDBODBC : public TDBASE {
ODBConn *Ocp; // Points to an ODBC connection class ODBConn *Ocp; // Points to an ODBC connection class
ODBCCOL *Cnp; // Points to count(*) column ODBCCOL *Cnp; // Points to count(*) column
ODBCPARM Ops; // Additional parameters ODBCPARM Ops; // Additional parameters
PSTRG Query; // Constructed SQL query
char *Connect; // Points to connection string char *Connect; // Points to connection string
char *TableName; // Points to ODBC table name char *TableName; // Points to ODBC table name
char *Schema; // Points to ODBC table Schema char *Schema; // Points to ODBC table Schema
...@@ -136,7 +137,6 @@ class TDBODBC : public TDBASE { ...@@ -136,7 +137,6 @@ class TDBODBC : public TDBASE {
char *Pwd; // Password connect info char *Pwd; // Password connect info
char *Catalog; // Points to ODBC table Catalog char *Catalog; // Points to ODBC table Catalog
char *Srcdef; // The source table SQL definition char *Srcdef; // The source table SQL definition
char *Query; // Points to SQL statement
char *Count; // Points to count(*) SQL statement char *Count; // Points to count(*) SQL statement
//char *Where; // Points to local where clause //char *Where; // Points to local where clause
char *Quote; // The identifier quoting character char *Quote; // The identifier quoting character
......
...@@ -60,7 +60,7 @@ extern "C" char version[]; ...@@ -60,7 +60,7 @@ extern "C" char version[];
#endif // !__WIN__ #endif // !__WIN__
#define TYPE_UNKNOWN 12 /* Must be greater than other types */ #define TYPE_UNKNOWN 12 /* Must be greater than other types */
#define XSTR(M) sizeof(M) - strlen(M) - 1 /* To avoid overflow*/ #define XLEN(M) sizeof(M) - strlen(M) - 1 /* To avoid overflow*/
/***********************************************************************/ /***********************************************************************/
/* Class and structure used by XMLColumns. */ /* Class and structure used by XMLColumns. */
...@@ -226,30 +226,30 @@ PQRYRES XMLColumns(PGLOBAL g, char *db, char *tab, PTOS topt, bool info) ...@@ -226,30 +226,30 @@ PQRYRES XMLColumns(PGLOBAL g, char *db, char *tab, PTOS topt, bool info)
more: more:
if (vp->atp) { if (vp->atp) {
strncpy(colname, vp->atp->GetName(g), sizeof(colname)); strncpy(colname, vp->atp->GetName(g), sizeof(colname));
strncat(xcol->Name, colname, XSTR(xcol->Name)); strncat(xcol->Name, colname, XLEN(xcol->Name));
switch (vp->atp->GetText(g, buf, sizeof(buf))) { switch (vp->atp->GetText(g, buf, sizeof(buf))) {
case RC_INFO: case RC_INFO:
PushWarning(g, txmp); PushWarning(g, txmp);
case RC_OK: case RC_OK:
strncat(fmt, "@", XSTR(fmt)); strncat(fmt, "@", XLEN(fmt));
break; break;
default: default:
goto err; goto err;
} // enswitch rc } // enswitch rc
if (j) if (j)
strncat(fmt, colname, XSTR(fmt)); strncat(fmt, colname, XLEN(fmt));
} else { } else {
if (tdp->Usedom && node->GetType() != 1) if (tdp->Usedom && node->GetType() != 1)
continue; continue;
strncpy(colname, node->GetName(g), sizeof(colname)); strncpy(colname, node->GetName(g), sizeof(colname));
strncat(xcol->Name, colname, XSTR(xcol->Name)); strncat(xcol->Name, colname, XLEN(xcol->Name));
if (j) if (j)
strncat(fmt, colname, XSTR(fmt)); strncat(fmt, colname, XLEN(fmt));
if (j < lvl && ok) { if (j < lvl && ok) {
vp = lvlp[j+1]; vp = lvlp[j+1];
...@@ -267,9 +267,9 @@ PQRYRES XMLColumns(PGLOBAL g, char *db, char *tab, PTOS topt, bool info) ...@@ -267,9 +267,9 @@ PQRYRES XMLColumns(PGLOBAL g, char *db, char *tab, PTOS topt, bool info)
if (!vp->atp) if (!vp->atp)
node = vp->nl->GetItem(g, vp->k++, node); node = vp->nl->GetItem(g, vp->k++, node);
strncat(fmt, colname, XSTR(fmt)); strncat(fmt, colname, XLEN(fmt));
strncat(fmt, "/", XSTR(fmt)); strncat(fmt, "/", XLEN(fmt));
strncat(xcol->Name, "_", XSTR(xcol->Name)); strncat(xcol->Name, "_", XLEN(xcol->Name));
j++; j++;
vp->n = (int)strlen(xcol->Name); vp->n = (int)strlen(xcol->Name);
vp->m = (int)strlen(fmt); vp->m = (int)strlen(fmt);
......
...@@ -340,7 +340,7 @@ PVAL AllocateValue(PGLOBAL g, void *value, short type, short prec) ...@@ -340,7 +340,7 @@ PVAL AllocateValue(PGLOBAL g, void *value, short type, short prec)
switch (type) { switch (type) {
case TYPE_STRING: case TYPE_STRING:
valp = new(g) TYPVAL<PSZ>((PSZ)value); valp = new(g) TYPVAL<PSZ>((PSZ)value, prec);
break; break;
case TYPE_SHORT: case TYPE_SHORT:
valp = new(g) TYPVAL<short>(*(short*)value, TYPE_SHORT); valp = new(g) TYPVAL<short>(*(short*)value, TYPE_SHORT);
...@@ -1209,12 +1209,12 @@ void TYPVAL<TYPE>::Print(PGLOBAL g, char *ps, uint z) ...@@ -1209,12 +1209,12 @@ void TYPVAL<TYPE>::Print(PGLOBAL g, char *ps, uint z)
/***********************************************************************/ /***********************************************************************/
/* STRING public constructor from a constant string. */ /* STRING public constructor from a constant string. */
/***********************************************************************/ /***********************************************************************/
TYPVAL<PSZ>::TYPVAL(PSZ s) : VALUE(TYPE_STRING) TYPVAL<PSZ>::TYPVAL(PSZ s, short c) : VALUE(TYPE_STRING)
{ {
Strp = s; Strp = s;
Len = strlen(s); Len = strlen(s);
Clen = Len; Clen = Len;
Ci = false; Ci = (c == 1);
} // end of STRING constructor } // end of STRING constructor
/***********************************************************************/ /***********************************************************************/
......
...@@ -216,7 +216,7 @@ template <> ...@@ -216,7 +216,7 @@ template <>
class DllExport TYPVAL<PSZ>: public VALUE { class DllExport TYPVAL<PSZ>: public VALUE {
public: public:
// Constructors // Constructors
TYPVAL(PSZ s); TYPVAL(PSZ s, short c = 0);
TYPVAL(PGLOBAL g, PSZ s, int n, int c); TYPVAL(PGLOBAL g, PSZ s, int n, int c);
// Implementation // Implementation
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
/* Include mariaDB header file. */ /* Include mariaDB header file. */
/***********************************************************************/ /***********************************************************************/
#include "my_global.h" #include "my_global.h"
#include "m_string.h"
/***********************************************************************/ /***********************************************************************/
/* Include required application header files */ /* Include required application header files */
...@@ -292,12 +293,12 @@ bool STRING::Set(char *s, uint n) ...@@ -292,12 +293,12 @@ bool STRING::Set(char *s, uint n)
/***********************************************************************/ /***********************************************************************/
/* Append a char* to a STRING. */ /* Append a char* to a STRING. */
/***********************************************************************/ /***********************************************************************/
bool STRING::Append(const char *s, uint ln) bool STRING::Append(const char *s, uint ln, bool nq)
{ {
if (!s) if (!s)
return false; return false;
uint len = Length + ln + 1; uint i, len = Length + ln + 1;
if (len > Size) { if (len > Size) {
char *p = Realloc(len); char *p = Realloc(len);
...@@ -311,8 +312,22 @@ bool STRING::Append(const char *s, uint ln) ...@@ -311,8 +312,22 @@ bool STRING::Append(const char *s, uint ln)
} // endif n } // endif n
strncpy(Strp + Length, s, ln); if (nq) {
Length = len - 1; for (i = 0; i < ln; i++)
switch (s[i]) {
case '\\': Strp[Length++] = '\\'; Strp[Length++] = '\\'; break;
case '\0': Strp[Length++] = '\\'; Strp[Length++] = '0'; break;
case '\'': Strp[Length++] = '\\'; Strp[Length++] = '\''; break;
case '\n': Strp[Length++] = '\\'; Strp[Length++] = 'n'; break;
case '\r': Strp[Length++] = '\\'; Strp[Length++] = 'r'; break;
case '\032': Strp[Length++] = '\\'; Strp[Length++] = 'Z'; break;
default: Strp[Length++] = s[i];
} // endswitch s[i]
} else
for (i = 0; i < ln && s[i]; i++)
Strp[Length++] = s[i];
Strp[Length] = 0; Strp[Length] = 0;
return false; return false;
} // end of Append } // end of Append
......
...@@ -134,7 +134,7 @@ class DllExport STRING : public BLOCK { ...@@ -134,7 +134,7 @@ class DllExport STRING : public BLOCK {
inline void Reset(void) {*Strp = 0;} inline void Reset(void) {*Strp = 0;}
bool Set(PSZ s); bool Set(PSZ s);
bool Set(char *s, uint n); bool Set(char *s, uint n);
bool Append(const char *s, uint ln); bool Append(const char *s, uint ln, bool nq = false);
bool Append(PSZ s); bool Append(PSZ s);
bool Append(STRING &str); bool Append(STRING &str);
bool Append(char c); bool Append(char c);
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include "m_ctype.h" #include "m_ctype.h"
typedef class CMD *PCMD; typedef class CMD *PCMD;
typedef struct st_key_range key_range;
// Commands executed by XDBC and MYX tables // Commands executed by XDBC and MYX tables
class CMD : public BLOCK { class CMD : public BLOCK {
...@@ -32,12 +33,24 @@ class CMD : public BLOCK { ...@@ -32,12 +33,24 @@ class CMD : public BLOCK {
}; // end of class CMD }; // end of class CMD
// Condition filter structure // Condition filter structure
typedef struct _cond_filter { class CONDFIL : public BLOCK {
public:
// Constructor
CONDFIL(const Item *cond, uint idx, AMT type)
{
Cond = cond; Idx = idx; Type = type; Body = NULL; Op = OP_XX; Cmds = NULL;
}
// Members
const Item *Cond;
AMT Type;
uint Idx;
char *Body; char *Body;
OPVAL Op; OPVAL Op;
PCMD Cmds; PCMD Cmds;
} CONDFIL, *PCFIL; }; // end of class CONDFIL
typedef class CONDFIL *PCFIL;
typedef class TDBCAT *PTDBCAT; typedef class TDBCAT *PTDBCAT;
typedef class CATCOL *PCATCOL; typedef class CATCOL *PCATCOL;
...@@ -109,7 +122,7 @@ class DllExport TDB: public BLOCK { // Table Descriptor Block. ...@@ -109,7 +122,7 @@ class DllExport TDB: public BLOCK { // Table Descriptor Block.
virtual int DeleteDB(PGLOBAL, int) = 0; virtual int DeleteDB(PGLOBAL, int) = 0;
virtual void CloseDB(PGLOBAL) = 0; virtual void CloseDB(PGLOBAL) = 0;
virtual int CheckWrite(PGLOBAL) {return 0;} virtual int CheckWrite(PGLOBAL) {return 0;}
virtual bool ReadKey(PGLOBAL, OPVAL, const void *, int) = 0; virtual bool ReadKey(PGLOBAL, OPVAL, const key_range *) = 0;
protected: protected:
// Members // Members
...@@ -188,7 +201,7 @@ class DllExport TDBASE : public TDB { ...@@ -188,7 +201,7 @@ class DllExport TDBASE : public TDB {
virtual void MarkDB(PGLOBAL g, PTDB tdb2); virtual void MarkDB(PGLOBAL g, PTDB tdb2);
virtual int MakeIndex(PGLOBAL g, PIXDEF, bool) virtual int MakeIndex(PGLOBAL g, PIXDEF, bool)
{strcpy(g->Message, "Remote index"); return RC_INFO;} {strcpy(g->Message, "Remote index"); return RC_INFO;}
virtual bool ReadKey(PGLOBAL, OPVAL, const void *, int) virtual bool ReadKey(PGLOBAL, OPVAL, const key_range *)
{assert(false); return true;} {assert(false); return true;}
protected: protected:
......
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