Commit e3d37bfe authored by Sergei Golubchik's avatar Sergei Golubchik

Merge branch 'connect/10.1' into 10.1

parents 7f19330c ad916ef3
......@@ -735,15 +735,10 @@ static void SetSwapValue(PVAL valp, char *kp)
/* IndexRead: fetch a record having the index value. */
/***********************************************************************/
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;
short lg;
bool rcb;
RCODE rc;
PVAL valp;
PCOL colp;
XXBASE *xbp;
PTDBDOX tdbp;
......@@ -757,13 +752,13 @@ RCODE CntIndexRead(PGLOBAL g, PTDB ptdb, OPVAL op,
return RC_FX;
} else if (x == 2) {
// Remote index
if (ptdb->ReadKey(g, op, key, len))
if (ptdb->ReadKey(g, op, kr))
return RC_FX;
goto rnd;
} else if (x == 3) {
if (key)
((PTDBASE)ptdb)->SetRecpos(g, *(int*)key);
if (kr)
((PTDBASE)ptdb)->SetRecpos(g, *(int*)kr->key);
if (op == OP_SAME)
return RC_NF;
......@@ -790,7 +785,14 @@ RCODE CntIndexRead(PGLOBAL g, PTDB ptdb, OPVAL op,
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++) {
colp= (PCOL)tdbp->To_Key_Col[n];
......@@ -832,10 +834,10 @@ RCODE CntIndexRead(PGLOBAL g, PTDB ptdb, OPVAL op,
kp+= valp->GetClen();
if (len == kp - (char*)key) {
if (len == kp - (char*)kr->key) {
n++;
break;
} else if (len < kp - (char*)key) {
} else if (len < kp - (char*)kr->key) {
strcpy(g->Message, "Key buffer is too small");
return RC_FX;
} // endif len
......
......@@ -36,7 +36,7 @@ bool CntRewindTable(PGLOBAL g, PTDB tdbp);
int CntCloseTable(PGLOBAL g, PTDB tdbp, bool nox, bool abort);
int CntIndexInit(PGLOBAL g, PTDB tdbp, int id, bool sorted);
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 CntUpdateRow(PGLOBAL g, PTDB tdbp);
RCODE CntDeleteRow(PGLOBAL g, PTDB tdbp, bool all);
......@@ -60,7 +60,7 @@ class TDBDOX: public TDBDOS {
friend int MakeIndex(PGLOBAL, PTDB, PIXDEF);
friend int CntCloseTable(PGLOBAL, PTDB, bool, 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 int CntIndexRange(PGLOBAL, PTDB, const uchar**, uint*,
bool*, key_part_map*);
......
100 IDS_TABLES "Table Headers"
101 IDS_TAB_01 "Table_Cat"
102 IDS_TAB_02 "Table_Schema"
103 IDS_TAB_03 "Table_Name"
104 IDS_TAB_04 "Table_Type"
105 IDS_TAB_05 "Remark"
106 IDS_COLUMNS "Column Headers"
107 IDS_COL_01 "Table_Cat"
108 IDS_COL_02 "Table_Schema"
109 IDS_COL_03 "Table_Name"
110 IDS_COL_04 "Column_Name"
111 IDS_COL_05 "Data_Type"
112 IDS_COL_06 "Type_Name"
113 IDS_COL_07 "Column_Size"
114 IDS_COL_08 "Buffer_Length"
115 IDS_COL_09 "Decimal_Digits"
116 IDS_COL_10 "Radix"
117 IDS_COL_11 "Nullable"
118 IDS_COL_12 "Remarks"
119 IDS_PKEY "Key Headers"
120 IDS_PKY_01 "Table_Catalog"
121 IDS_PKY_02 "Table_Schema"
122 IDS_PKY_03 "Table_Name"
123 IDS_PKY_04 "Column_Name"
124 IDS_PKY_05 "Key_Seq"
125 IDS_PKY_06 "Pk_Name"
126 IDS_STAT "Stat Headers"
127 IDS_STA_01 "Table_Catalog"
128 IDS_STA_02 "Table_Schema"
129 IDS_STA_03 "Table_Name"
130 IDS_STA_04 "Non_Unique"
131 IDS_STA_05 "Index_Qualifier"
132 IDS_STA_06 "Index_Name"
133 IDS_STA_07 "Type"
134 IDS_STA_08 "Seq_in_Index"
135 IDS_STA_09 "Column_Name"
136 IDS_STA_10 "Collation"
137 IDS_STA_11 "Cardinality"
138 IDS_STA_12 "Pages"
139 IDS_STA_13 "Filter_Condition"
140 IDS_DRIVER "Driver Headers"
141 IDS_DRV_01 "Description"
142 IDS_DRV_02 "Attributes"
143 IDS_DSRC "DataSrc Headers"
144 IDS_DSC_01 "Name"
145 IDS_DSC_02 "Description"
200 ACCESS_VIOLATN "Access violation"
201 ADD_BAD_TYPE "Array add value type mismatch (%s -> %s)"
202 ALLOC_ERROR "Error allocating %s"
203 ANSWER_TYPE "Answer of type"
204 API_CONF_ERROR "SQL Error: API_CONFORMANCE"
205 APPL_NOT_INIT "Application not initialized"
206 ARRAY_BNDS_EXCD "Array bounds exceeded"
207 BAD_ARRAY_OPER "Arrays must be used with the IN operator"
208 BAD_ARRAY_TYPE "Illegal array type %d"
209 BAD_ARRAY_VAL "Arrays must have the same number of values"
210 BAD_BIN_FMT "Invalid format %c for the %s BIN column"
211 BAD_BLK_ESTIM "Number of blocks exceeds estimate"
212 BAD_BLK_SIZE "No match in block %d size"
213 BAD_BYTE_NUM "bad number of bytes written"
214 BAD_BYTE_READ "bad number of bytes read"
215 BAD_COL_TYPE "Invalid type %s for column %s"
216 BAD_COL_XPATH "Invalid Xpath in column %s for HTML table %s"
217 BAD_CONST_TYPE "Bad constant type=%d"
218 BAD_CONV_TYPE "Invalid convert type %d"
219 BAD_DATETIME "Invalid datetime value"
220 BAD_DBF_FILE "DBF file %s is corrupted"
221 BAD_DBF_REC "DBF file %s corrupted at record %d"
222 BAD_DBF_TYPE "Unsupported DBF type %c for column %s"
223 BAD_DIRECTORY "Bad directory %s: %s"
224 BAD_FIELD_RANK "Invalid field rank %d for column %s"
225 BAD_FIELD_TYPE "Bad type field %s"
226 BAD_FILE_HANDLE "Invalid File Handle: %s"
227 BAD_FILTER "Bad filter: Opc=%d B_T=%d %d Type=%d %d"
228 BAD_FILTER_CONV "Bad filter conversion, B_T=%d,%d"
229 BAD_FILTER_OP "Invalid filter operator %d"
230 BAD_FLD_FORMAT "Bad format for field %d of %s"
231 BAD_FLD_LENGTH "Field %s too long (%s --> %d) line %d of %s"
232 BAD_FREQ_SET "Bad frequency setting for column %s"
233 BAD_FUNC_MODE "%s: invalid mode %d"
234 BAD_HANDLE_VAL "Invalid handle value"
235 BAD_HEADER "File %s: Header corrupted"
236 BAD_HEAD_END "Can't read end of header"
237 BAD_INDEX_FILE "Wrong index file %s"
238 BAD_LINEFLD_FMT "Bad format line %d field %d of %s"
239 BAD_LINE_LEN "Line length not equal to Lrecl"
240 BAD_LRECL "Table/File lrecl mismatch (%d,%hd)"
241 BAD_NODE_TYPE "Bad type %d for table node"
242 BAD_OFFSET_VAL "Invalid null offset value for a CSV table"
243 BAD_OPEN_MODE "Invalid open mode %d"
244 BAD_PARAM_TYPE "%.8s: Bad parameter type=%d"
245 BAD_PARM_COUNT "Parameter count mismatch"
246 BAD_QUOTE_FIELD "Missing ending quote in %s field %d line %d"
247 BAD_READ_NUMBER "Wrong number %d of values read from %s"
248 BAD_RECFM "Invalid recfm type %d for DOSCOL"
249 BAD_RECFM_VAL "Bad Recfm value %d"
250 BAD_SET_CASE "Cannot set sensitive an insensitive array"
251 BAD_SET_STRING "Invalid SetValue from string"
252 BAD_SPECIAL_COL "Bad special column %s"
253 BAD_SPEC_COLUMN "Special column invalid for this table type"
254 BAD_TABLE_TYPE "Bad type %s for table %s"
255 BAD_TYPE_LIKE "Bad operand(%d) type=%d for LIKE"
256 BAD_VALBLK_INDX "Out of range valblock index value"
257 BAD_VALBLK_TYPE "Invalid value block type %d"
258 BAD_VALNODE "Bad type %d for column %s value node"
259 BAD_VALUE_TYPE "Invalid value type %d"
260 BAD_VAL_UPDATE "Don't know which %s value to update"
261 BAS_NS_LIST "Invalid namespaces list format"
262 BIN_F_TOO_LONG "Value too long for field %s (%d --> %d)"
263 BIN_MODE_FAIL "Set binary mode failed: %s"
264 BLKTYPLEN_MISM "Non matching block types/lengths in SetValue"
265 BLK_IS_NULL "Blk is NULL"
266 BREAKPOINT "Breakpoint"
267 BUILD_INDEX "Building index %s on %s"
268 CANNOT_OPEN "Cannot open %s"
269 CHSIZE_ERROR "chsize error: %s"
270 COL_ALLOC_ERR "Cannot allocate column node"
271 COL_ISNOT_TABLE "Column %s is not in table %s"
272 COL_NOT_SORTED "Column %s of table %s is not sorted"
273 COL_NUM_MISM "Number of columns mismatch"
274 COM_ERROR "Com error"
275 CONCAT_SUBNODE "Cannot concatenate sub-nodes"
276 CONNECT_CANCEL "Connection cancelled by user"
277 CONTROL_C_EXIT "Control C exit"
278 DATABASE_LOADED "Database %s loaded"
279 DATA_MISALIGN "Datatype misalignment"
280 DBASE_FILE "dBASE dbf file: "
281 DEF_ALLOC_ERROR "Error allocating %s DEF class"
282 DEL_FILE_ERR "Error deleting %s"
283 DEL_READ_ERROR "Delete: read error req=%d len=%d"
284 DEL_WRITE_ERROR "Delete: write error: %s"
285 DEPREC_FLAG "Deprecated option Flag, use Coltype"
286 DLL_LOAD_ERROR "Error %d loading module %s"
287 DOM_NOT_SUPP "MS-DOM not supported by this version"
288 DVAL_NOTIN_LIST "Value %s not found in distinct values list of column %s"
289 EMPTY_DOC "Empty document"
290 EMPTY_FILE "%s empty file %s: "
291 EOF_AFTER_LINE "EOF after line %d"
292 EOF_INDEX_FILE "EOF while reading index file"
293 ERROR_IN_LSK "Error %d in lseek64"
294 ERROR_IN_SFP "Error %d in SetFilePointer"
295 ERR_READING_REC "Error reading record %d of %s"
296 FAIL_ADD_NODE "Failed to add %s table node"
297 FETCH_NO_RES "Fetch: No Result Set"
298 FIELD_TOO_LONG "Value too long for field %d line %d"
299 FILELEN_ERROR "Error in %s for %s"
300 FILE_IS_EMPTY "File %s is empty"
301 FILE_MAP_ERR "File mapping error"
302 FILE_MAP_ERROR "CreateFileMapping %s error rc=%d"
303 FILE_OPEN_YET "File %s already open"
304 FILE_UNFOUND "File %s not found"
305 FLD_TOO_LNG_FOR "Field %d too long for %s line %d of %s"
306 FLT_BAD_RESULT "Float inexact result"
307 FLT_DENORMAL_OP "Float denormal operand"
308 FLT_INVALID_OP "Float invalid operation"
309 FLT_OVERFLOW "Float overflow"
310 FLT_STACK_CHECK "Float stack check"
311 FLT_UNDERFLOW "Float underflow"
312 FLT_ZERO_DIVIDE "Float divide by zero"
313 FMT_WRITE_NIY "Writing %s files is not implemented yet"
314 FOXPRO_FILE "FoxPro file: "
315 FPUTS_ERROR "fputs error: %s"
316 FSEEK_ERROR "fseek error: %s"
317 FSETPOS_ERROR "fseek error for i=%d"
318 FTELL_ERROR "ftell error for recd=%d: %s"
319 FUNCTION_ERROR "%s error: %d"
320 FUNC_ERRNO "Error %d in %s"
321 FUNC_ERROR "Error in %s"
322 FUNC_ERR_S "%s error: %s"
323 FWRITE_ERROR "fwrite error: %s"
324 GET_DIST_VALS "Retrieving distinct values from "
325 GET_FUNC_ERR "Error getting function %s: %s"
326 GLOBAL_ERROR "Cannot allocate Global (size=%d)\n"
327 GUARD_PAGE "Guard page violation"
328 GZOPEN_ERROR "gzopen %s error %d on %s"
329 ILLEGAL_INSTR "Illegal instruction"
330 ILL_FILTER_CONV "Filtering implies an illegal conversion"
331 INDEX_NOT_UNIQ "Index is not unique"
332 INDEX_YET_ON "Index %s already exists on %s"
333 INDX_COL_NOTIN "Index column %s is not in table %s"
334 INDX_EXIST_YET "Index entry already exists"
335 INIT_FAILED "Failed to initialize %s processing"
336 INT_COL_ERROR "Internal error for index column %s"
337 INT_OVERFLOW "Integer overflow"
338 INT_ZERO_DIVIDE "Integer divide by zero"
339 INVALID_DISP "Invalid disposition"
340 INVALID_FTYPE "SBV: invalid Ftype %d"
341 INVALID_HANDLE "Invalid handle"
342 INVALID_OPER "Invalid operator %d for %s"
343 INV_COLUMN_TYPE "Invalid type %d for column %s"
344 INV_COL_TYPE "Invalid column type %s"
345 INV_DEF_READ "Invalid deferred Read rc=%d"
346 INV_DIRCOL_OFST "Invalid DIRCOL offset %d"
347 INV_MAP_POS "Invalid map position"
348 INV_RAND_ACC "Invalid random access to non optimized table"
349 INV_REC_POS "Invalid record position"
350 INV_RESULT_TYPE "Invalid result type %s"
351 INV_UPDT_TABLE "Table %s invalid for update"
352 IN_WITHOUT_SUB "IN or EXISTS without array or subquery"
353 KEY_ALLOC_ERR "Error allocating Key offset block"
354 KEY_ALLOC_ERROR "Memory allocation error, Klen=%d n=%d"
355 LINE_TOO_LONG "New line is too long"
356 LIST "--List--"
357 LOADING_FAILED "Loading of %s failed"
358 LRECL_TOO_SMALL "Lrecl too small (headlen = %d)"
359 MAKE_EMPTY_FILE "Making empty file %s: %s"
360 MAKING "Making"
361 MALLOC_ERROR "Memory allocation failed: %s returned Null"
362 MAP_VIEW_ERROR "MapViewOfFile %s error rc=%d"
363 MAXSIZE_ERROR "Cannot calculate max size on open table"
364 MEM_ALLOC_ERR "Memory allocation error, %s size=%d"
365 MEM_ALLOC_ERROR "Memory allocation error"
366 MISPLACED_QUOTE "Misplaced quote in line %d"
367 MISSING_ARG "Missing argument for operator %d"
368 MISSING_FIELD "Missing field %d in %s line %d"
369 MISSING_FNAME "Missing file name"
370 MISSING_NODE "Missing %s node in %s"
371 MISSING_ROWNODE "Can't find RowNode for row %d"
372 MIS_TAG_LIST "Missing column tag list"
373 MUL_MAKECOL_ERR "Tabmul MakeCol logical error"
374 NAME_CONV_ERR "Error converting node name"
375 NEW_DOC_FAILED "Cannot create new document"
376 NEW_RETURN_NULL "New returned Null in PlugEvalLike"
377 NEXT_FILE_ERROR "Couldn't find next file. rc=%d"
378 NONCONT_EXCEPT "Noncontinuable exception"
379 NOP_ZLIB_INDEX "Cannot do indexing on non optimized zlib table"
380 NOT_A_DBF_FILE "Not a dBASE dbf file "
381 NOT_FIXED_LEN "File %s is not fixed length, len=%d lrecl=%d"
382 NO_0DH_HEAD "No 0Dh at end of header (dbc=%d)"
383 NO_ACTIVE_DB "No active database"
384 NO_CHAR_FROM "Cannot return char value from type %d"
385 NO_DATE_FMT "No date format for valblock of type %d"
386 NO_DEF_FNCCOL "Cannot find default function column"
387 NO_DEF_PIVOTCOL "Cannot find default pivot column"
388 NO_DIR_INDX_RD "No direct access of %s tables"
389 NO_FEAT_SUPPORT "No %s support in this version"
390 NO_FLD_FORMAT "Missing format for field %d of %s"
391 NO_FORMAT_COL "Cannot format the type COLUMN"
392 NO_FORMAT_TYPE "Cannot set format from type %d"
393 NO_INDEX_READ "No indexed read for multiple tables"
394 NO_KEY_COL "No key columns found"
395 NO_KEY_UPDATE "Cannot update key names"
396 NO_MAP_INSERT "MAP incompatible with Insert"
397 NO_MATCHING_COL "No matching column %s in %s"
398 NO_MATCH_COL "Cannot find matching column"
399 NO_MEMORY "No memory"
400 NO_MODE_PADDED "Mode not supported for padded files"
401 NO_MUL_VCT "VCT tables cannot be multiple"
402 NO_ODBC_DELETE "Delete should not be called for ODBC tables"
403 NO_ODBC_DIRECT "Direct access of ODBC tables not implemented yet"
404 NO_ODBC_MUL "Multiple(2) not supported for ODBC tables"
405 NO_ODBC_SPECOL "No ODBC special columns"
406 NO_PART_DEL "No partial delete of %s files"
407 NO_PART_MAP "Partial mapping not implemented for this OS"
408 NO_PAR_BLK_INS "Cannot insert partial block yet"
409 NO_PIV_DIR_ACC "No direct access to PIVOT tables"
410 NO_READ_32 "Can't read 32 bytes"
411 NO_RECOV_SPACE "Cannot recover space in index file"
412 NO_ROWID_FOR_AM "Can't get RowID in direct access for tables of type %s"
413 NO_ROW_NODE "Row node name is not defined"
414 NO_SECTION_NAME "Missing section name"
415 NO_SEC_UPDATE "Cannot update section names"
416 NO_SETPOS_YET "%s SetPos not implemented yet"
417 NO_SPEC_COL "No MySQL special columns"
418 NO_SUB_VAL "No sub value for array of type %d"
419 NO_TABCOL_DATA "No data found for table %s column %s"
420 NO_TABLE_DEL "Delete not enabled for %s tables "
421 NO_TAB_DATA "No data found for table %s"
422 NO_VCT_DELETE "Partial delete not yet implemented for VCT files"
423 NO_ZIP_DELETE "Delete Zip files not implemented yet"
424 OPENING "Opening"
425 OPEN_EMPTY_FILE "Opening empty file %s: %s"
426 OPEN_ERROR "Open error %d in mode %d on %s: "
427 OPEN_ERROR_IS "Open error on %s: %s"
428 OPEN_MODE_ERROR "Open(%s) error %d on %s"
429 OPEN_STRERROR "open error: %s"
430 OPTBLK_RD_ERR "Error reading opt block values: %s"
431 OPTBLK_WR_ERR "Error writing opt block values: %s"
432 OPTIMIZING "Optimizing "
433 OPT_BMAP_RD_ERR "Error reading opt bitmaps: %s"
434 OPT_BMAP_WR_ERR "Error writing opt bitmaps: %s"
435 OPT_CANCELLED "Optimize cancelled by User"
436 OPT_DVAL_RD_ERR "Error reading distinct values: %s"
437 OPT_DVAL_WR_ERR "Error writing distinct values: %s"
438 OPT_HEAD_RD_ERR "Error reading opt file header: %s"
439 OPT_HEAD_WR_ERR "Error writing opt file header: %s"
440 OPT_LOGIC_ERR "Logical error in SetBitmap, i=%d"
441 OPT_MAX_RD_ERR "Error reading opt max values: %s"
442 OPT_MAX_WR_ERR "Error writing opt max values: %s"
443 OPT_MIN_RD_ERR "Error reading opt min values: %s"
444 OPT_MIN_WR_ERR "Error writing opt min values: %s"
445 OPT_NOT_MATCH "Non-matching opt file %s"
446 PAGE_ERROR "In page error"
447 PARM_CNT_MISS "Parameter count mismatch"
448 PREC_VBLP_NULL "ARRAY SetPrecision: Vblp is NULL"
449 PRIV_INSTR "Privileged instruction"
450 PROCADD_ERROR "Error %d getting address of %s"
451 QUERY_CANCELLED "Query Cancelled by User"
452 RANGE_NO_JOIN "Range is not meant for join index"
453 RC_READING "rc=%d reading table %s"
454 READY "Ready"
455 READ_ERROR "Error reading %s: %s"
456 READ_ONLY "Cannot modify this read/only protected table"
457 READ_SEEK_ERROR "Read seek error: %s"
458 REGISTER_ERR "Unable to register NS with prefix='%s' and href='%s'"
459 REMOVE_ERROR "Error removing %s: %s"
460 RENAME_ERROR "Error renaming %s to %s: %s"
461 ROWID_NOT_IMPL "RowNumber not implemented for tables of type %s"
462 SEC_KEY_FIRST "Section and key names must come first on Insert"
463 SEC_NAME_FIRST "Section name must come first on Insert"
464 SEP_IN_FIELD "Field %d contains the separator character"
465 SEQUENCE_ERROR "Sequence error on statement allocation"
466 SETEOF_ERROR "Error %d in SetEndOfFile"
467 SETRECPOS_NIY "SetRecpos not implemented for this table type"
468 SET_STR_TRUNC "SetValue: String would be truncated"
469 SFP_ERROR "SetFilePointer error: %s"
470 SHARED_LIB_ERR "Error loading shared library %s: %s"
471 SINGLE_STEP "Single step"
472 SORTING_VAL "Sorting %d values"
473 SPCOL_READONLY "Special column %s is Read Only"
474 SQL_CONF_ERROR "SQL Error: SQL_CONFORMANCE"
475 SRCH_CLOSE_ERR "Couldn't close search handle"
476 SRC_TABLE_UNDEF "Source table is not defined"
477 STACK_OVERFLOW "Stack overflow"
478 TABDIR_READONLY "DIR tables are read/only"
479 TABLE_NOT_OPT "Not an optimizable table"
480 TABLE_NO_INDEX "Table %s is not indexable"
481 TABLE_READ_ONLY "%s tables are read only "
482 TABMUL_READONLY "Multiple tables are read/only"
483 TOO_MANY_FIELDS "Too many fields line %d of %s"
484 TOO_MANY_JUMPS "Too many jump levels"
485 TOO_MANY_KEYS "Too many keys (%d)"
486 TO_BLK_IS_NULL "To Blk is NULL"
487 TRUNCATE_ERROR "truncate error: %s"
488 TRUNC_BY_ESTIM "truncated by Estimate"
489 TYPE_MISMATCH "Key and source are not of the same type"
490 TYPE_VALUE_ERR "Column %s type(%s)/value(%s) mismatch"
491 UNBALANCE_QUOTE "Unbalanced quote in line %d"
492 UNDEFINED_AM "COLBLK %s: undefined Access Method"
493 UNKNOWN_EXCPT "Unknown exception"
494 UNMATCH_FIL_ARG "Unmatched filter argument"
495 UPDATE_ERROR "Error updating %s"
496 UPD_ZIP_NOT_IMP "Updating ZDOS tables not implemented yet"
497 VALSTR_TOO_LONG "Value %s too long for string of length %d"
498 VALTYPE_NOMATCH "Non matching Value types"
499 VALUE_ERROR "Column %s: value is null"
500 VALUE_TOO_BIG "Value %lld too big for column %s"
501 VALUE_TOO_LONG "Value %s too long for column %s of length %d"
502 VAL_ALLOC_ERR "Cannot allocate value node"
503 VIR_NO_DELETE "Delete not allowed for %s tables"
504 VIR_READ_ONLY "Virtual %s tables are read only"
505 VOID_FIRST_ARG "First argument should not be void"
506 WORK_AREA "Work area: %s"
507 WRITE_SEEK_ERR "Write seek error: %s"
508 WRITE_STRERROR "Error writing %s: %s"
509 WRITING "Writing"
510 WRITING_ERROR "Error writing to %s: %s"
511 WS_CONV_ERR "Error converting %s to WS"
512 XCOL_MISMATCH "Column %s mismatch in index"
513 XFILE_READERR "Error %d reading index file"
514 XFILE_WRITERR "Error writing index file: %s"
515 XMLTAB_INIT_ERR "Error initializing XML table"
516 XML_INIT_ERROR "Error initializing new XML file"
517 XPATH_CNTX_ERR "Unable to create new XPath context"
518 XPATH_EVAL_ERR "Unable to evaluate xpath location '%s'"
519 XPATH_NOT_SUPP "Unsupported Xpath for column %s"
100 IDS_TABLES "Table Entêtes"
101 IDS_TAB_01 "Catalogue"
102 IDS_TAB_02 "Schéma"
103 IDS_TAB_03 "Nom"
104 IDS_TAB_04 "Type"
105 IDS_TAB_05 "Remarque"
106 IDS_COLUMNS "Colonne Entêtes"
107 IDS_COL_01 "Cat_Table"
108 IDS_COL_02 "Schem_Table"
109 IDS_COL_03 "Nom_Table"
110 IDS_COL_04 "Nom_Colonne"
111 IDS_COL_05 "Type_Données"
112 IDS_COL_06 "Nom_Type"
113 IDS_COL_07 "Précision"
114 IDS_COL_08 "Longueur"
115 IDS_COL_09 "Echelle"
116 IDS_COL_10 "Base"
117 IDS_COL_11 "Nullifiable"
118 IDS_COL_12 "Remarques"
119 IDS_PKEY "Clé Entêtes"
120 IDS_PKY_01 "Cat_Table"
121 IDS_PKY_02 "Schem_Table"
122 IDS_PKY_03 "Nom_Table"
123 IDS_PKY_04 "Nom_Colonne"
124 IDS_PKY_05 "Numéro_Clé"
125 IDS_PKY_06 "Nom_Clé"
126 IDS_STAT "Stat Entêtes"
127 IDS_STA_01 "Table_Catalog"
128 IDS_STA_02 "Table_Schema"
129 IDS_STA_03 "Table_Name"
130 IDS_STA_04 "Non_Unique"
131 IDS_STA_05 "Index_Qualifier"
132 IDS_STA_06 "Index_Name"
133 IDS_STA_07 "Type"
134 IDS_STA_08 "Seq_in_Index"
135 IDS_STA_09 "Column_Name"
136 IDS_STA_10 "Collation"
137 IDS_STA_11 "Cardinality"
138 IDS_STA_12 "Pages"
139 IDS_STA_13 "Filter_Condition"
140 IDS_DRIVER "Driver Entêtes"
141 IDS_DRV_01 "Description"
142 IDS_DRV_02 "Attributs"
143 IDS_DSRC "DataSrc Entêtes"
144 IDS_DSC_01 "Nom"
145 IDS_DSC_02 "Description"
200 ACCESS_VIOLATN "Violation accès mémoire"
201 ADD_BAD_TYPE "Ajout d'une valeur de type %s non conforme dans un tableau %s"
202 ALLOC_ERROR "Erreur d'allocation de %s"
203 ANSWER_TYPE "Réponse de type"
204 API_CONF_ERROR "Erreur SQL: API_CONFORMANCE"
205 APPL_NOT_INIT "Application non initialisée"
206 ARRAY_BNDS_EXCD "Hors limite de tableau"
207 BAD_ARRAY_OPER "Les tableaux doivent utiliser l'opérateur IN"
208 BAD_ARRAY_TYPE "Type=%d invalide pour un tableau"
209 BAD_ARRAY_VAL "Les tableaux doivent avoir le même nombre de valeurs"
210 BAD_BIN_FMT "Format invalide %c pour la colonne BIN %s"
211 BAD_BLK_ESTIM "Nombre de blocs supérieur à l'estimation"
212 BAD_BLK_SIZE "Taille du bloc %d non conforme"
213 BAD_BYTE_NUM "Le nombre d'octets écrits est faux"
214 BAD_BYTE_READ "Le nombre d'octets lus est faux"
215 BAD_COL_TYPE "Type invalide %s pour la colonne %s"
216 BAD_COL_XPATH "Xpath invalide colonne %s de la table HTML %s"
217 BAD_CONST_TYPE "Type=%d invalide pour une constante"
218 BAD_CONV_TYPE "Convertion de type invalide %d"
219 BAD_DATETIME "Valeur date/temps invalide"
220 BAD_DBF_FILE "Le fichier DBF %s est altéré"
221 BAD_DBF_REC "Fichier DBF %s altéré enregistrement %d"
222 BAD_DBF_TYPE "Type DBF %c non supporté colonne %s"
223 BAD_DIRECTORY "Répertoire invalide %s: %s"
224 BAD_FIELD_RANK "Rang %d invalide pour la colonne %s"
225 BAD_FIELD_TYPE "Mauvais type de champ %s"
226 BAD_FILE_HANDLE "Handle de fichier invalide: %s"
227 BAD_FILTER "Mauvais filtre: Opc=%d B_T=%d %d Type=%d %d"
228 BAD_FILTER_CONV "Conversion filtre incorrecte, B_T=%d,%d"
229 BAD_FILTER_OP "Opérateur de filtre invalide %d"
230 BAD_FLD_FORMAT "Format invalide pour le champs %d de %s"
231 BAD_FLD_LENGTH "Champs %s trop long (%s --> %d) ligne %d de %s"
232 BAD_FREQ_SET "Spécification erronnée de Freq pour la colonne %s"
233 BAD_FUNC_MODE "%s: mode invalide %d"
234 BAD_HANDLE_VAL "Valeur Handle invalide"
235 BAD_HEADER "Fichier %s: bloc en-tête altéré"
236 BAD_HEAD_END "Lecture fin d'en-tête impossible"
237 BAD_INDEX_FILE "Fichier index %s corrompu"
238 BAD_LINEFLD_FMT "Format invalide ligne %d champs %d de %s"
239 BAD_LINE_LEN "Longueur ligne non égale à Lrecl"
240 BAD_LRECL "Disparité lrecl table/fichier (%d,%hd)"
241 BAD_NODE_TYPE "Type noeud erroné pour la table"
242 BAD_OFFSET_VAL "Nul offset invalide pour une table CSV"
243 BAD_OPEN_MODE "Mode d'ouverture invalide %d"
244 BAD_PARAM_TYPE "%.8s: Paramètre de type=%d invalide"
245 BAD_PARM_COUNT "Nombre de paramètres incohérent"
246 BAD_QUOTE_FIELD "Quote manquante dans %s champs %d ligne %d"
247 BAD_READ_NUMBER "Mauvais nombre %d de valeurs lues dans %s"
248 BAD_RECFM "Recfm type %d invalide pour DOSCOL"
249 BAD_RECFM_VAL "Valeur invalide %d de Recfm"
250 BAD_SET_CASE "La casse d'un tableau ne peut pas passer de non respect à respecter"
251 BAD_SET_STRING "SetValue: appel invalide pour STRING"
252 BAD_SPECIAL_COL "Colonne spéciale invalide %s"
253 BAD_SPEC_COLUMN "Colonne spéciale invalide pour ce type de table"
254 BAD_TABLE_TYPE "Type invalide %s pour la table %s"
255 BAD_TYPE_LIKE "Type(%d)= %d invalide pour LIKE"
256 BAD_VALBLK_INDX "Valeur hors limites de l'index du bloc de valeurs"
257 BAD_VALBLK_TYPE "Type=%d invalide pour un bloc de valeurs"
258 BAD_VALNODE "Type %d invalide pour le noeud valeur colonne %s"
259 BAD_VALUE_TYPE "Type de valeur invalide %d"
260 BAD_VAL_UPDATE "Impossible de déterminer quelle valeur %s doit être mise à jour"
261 BAS_NS_LIST "Format invalide de la liste des espace-noms"
262 BIN_F_TOO_LONG "Valeur trop longue pour le champ %s (%d --> %d)"
263 BIN_MODE_FAIL "Echec mode binaire: %s"
264 BLKTYPLEN_MISM "Disparité types/longueurs de bloc dans SetValue"
265 BLK_IS_NULL "Blk est nul"
266 BREAKPOINT "Point de contrôle"
267 BUILD_INDEX "Construction index %s sur %s"
268 CANNOT_OPEN "Ouverture impossible de %s"
269 CHSIZE_ERROR "Erreur dans chsize: %s"
270 COL_ALLOC_ERR "Allocation impossible du noeud colonne"
271 COL_ISNOT_TABLE "La colonne %s n'est pas dans la table %s"
272 COL_NOT_SORTED "La colonne %s de la table %s n'est pas triée"
273 COL_NUM_MISM "Disparité du nombre de colonnes"
274 COM_ERROR "Erreur Com"
275 CONCAT_SUBNODE "Concaténation de sous-noeuds impossible"
276 CONNECT_CANCEL "Connection interrompue par l'utilisateur"
277 CONTROL_C_EXIT "Exit par Ctrl-C"
278 DATABASE_LOADED "Base de données %s chargée"
279 DATA_MISALIGN "Mauvais alignement pour ce type de données"
280 DBASE_FILE "Fichier dBASE dbf: "
281 DEF_ALLOC_ERROR "Erreur d'allocation de la classe DEF %s"
282 DEL_FILE_ERR "Erreur à l'effacement de %s"
283 DEL_READ_ERROR "Delete: erreur en lecture req=%d len=%d"
284 DEL_WRITE_ERROR "Delete: erreur en écriture: %s"
285 DEPREC_FLAG "Option Flag périmée, utiliser Coltype"
286 DLL_LOAD_ERROR "Erreur %d au chargement du module %s"
287 DOM_NOT_SUPP "MS-DOM non supporté par cette version"
288 DVAL_NOTIN_LIST "Valeur %s non trouvée dans la liste des valeurs distinctes de la colonne %s"
289 EMPTY_DOC "Document vide"
290 EMPTY_FILE "%s du fichier vide %s: "
291 EOF_AFTER_LINE "Fin de fichier après la ligne %d"
292 EOF_INDEX_FILE "EOF lisant le fichier index"
293 ERROR_IN_LSK "Erreur %d dans lseek64"
294 ERROR_IN_SFP "Erreur %d dans SetFilePointer"
295 ERR_READING_REC "Erreur lisant l'enregistrement %d de %s"
296 FAIL_ADD_NODE "L'ajout du noeud %s dans la table a échoué"
297 FETCH_NO_RES "Fetch: Pas de Résultats"
298 FIELD_TOO_LONG "Valeur trop longue pour le champs %d ligne %d"
299 FILELEN_ERROR "Erreur dans %s pour %s"
300 FILE_IS_EMPTY "Le fichier %s est vide"
301 FILE_MAP_ERR "Erreur de File mapping"
302 FILE_MAP_ERROR "CreateFileMapping %s erreur rc=%d"
303 FILE_OPEN_YET "Fichier %s déjà ouvert"
304 FILE_UNFOUND "Fichier %s non trouvé"
305 FLD_TOO_LNG_FOR "Champs %d trop long pour %s ligne %d de %s"
306 FLT_BAD_RESULT "Virgule flottante: résultat inexacte"
307 FLT_DENORMAL_OP "Opérande virgule flottante non normalisé"
308 FLT_INVALID_OP "Opération virgule flottante invalide"
309 FLT_OVERFLOW "Dépassement de capacité virgule flottante"
310 FLT_STACK_CHECK "Virgule flottante: Erreur de la pile"
311 FLT_UNDERFLOW "Sous-dépassement de capacité virgule flottante"
312 FLT_ZERO_DIVIDE "Virgule flottante: division par zéro"
313 FMT_WRITE_NIY "L'écriture des fichiers %s n'est pas encore implémentée"
314 FOXPRO_FILE "Fichier FoxPro: "
315 FPUTS_ERROR "Erreur dans fputs: %s"
316 FSEEK_ERROR "Erreur dans fseek: %s"
317 FSETPOS_ERROR "Erreur dans fseek pour i=%d"
318 FTELL_ERROR "Erreur dans ftell enregistrement=%d: %s"
319 FUNCTION_ERROR "Erreur dans %s: %d"
320 FUNC_ERRNO "Erreur %d dans %s"
321 FUNC_ERROR "Erreur dans %s"
322 FUNC_ERR_S "Erreur dans %s: %s"
323 FWRITE_ERROR "Erreur dans fwrite: %s"
324 GET_DIST_VALS "Récupération des valeurs distinctes de "
325 GET_FUNC_ERR "Erreur en recherche de la fonction %s: %s"
326 GLOBAL_ERROR "Erreur d'allocation de Global (taille=%d)\n"
327 GUARD_PAGE "Violation de page de garde"
328 GZOPEN_ERROR "gzopen %s: erreur %d sur %s"
329 ILLEGAL_INSTR "Instruction illégale"
330 ILL_FILTER_CONV "Conversion implicite illégale dans un filtre"
331 INDEX_NOT_UNIQ "L'index n'est pas Unique"
332 INDEX_YET_ON "L'index %s existe déjà sur %s"
333 INDX_COL_NOTIN "La colonne index %s n'existe pas dans la table %s"
334 INDX_EXIST_YET "L'entrée index existe déjà"
335 INIT_FAILED "L'initialisation de %s a échoué"
336 INT_COL_ERROR "Erreur interne sur la colonne index %s"
337 INT_OVERFLOW "Dépassement de capacité sur entier"
338 INT_ZERO_DIVIDE "Division entière par zéro"
339 INVALID_DISP "Disposition invalide"
340 INVALID_FTYPE "SBV: Ftype %d invalide"
341 INVALID_HANDLE "Poignée invalide"
342 INVALID_OPER "Opérateur invalide %d pour %s"
343 INV_COLUMN_TYPE "Type %d Invalide pour la colonne %s"
344 INV_COL_TYPE "Type de colonne %s invalide"
345 INV_DEF_READ "Lecture différée invalide rc=%d"
346 INV_DIRCOL_OFST "Offset invalide pour une colonne DIR"
347 INV_MAP_POS "Position mémoire invalide"
348 INV_RAND_ACC "L'accès aléatoire d'une table non optimisée est impossible"
349 INV_REC_POS "Position d'enregistrement invalide"
350 INV_RESULT_TYPE "Type de résultat invalide %s"
351 INV_UPDT_TABLE "Table %s invalide pour Update"
352 IN_WITHOUT_SUB "IN ou EXISTS sans tableau ou subquery"
353 KEY_ALLOC_ERR "Erreur d'allocation d'un bloc offset clé"
354 KEY_ALLOC_ERROR "Erreur d'allocation mémoire, Klen=%d n=%d"
355 LINE_TOO_LONG "La nouvelle ligne est trop longue"
356 LIST "--Liste--"
357 LOADING_FAILED "Le chargement de %s a échoué"
358 LRECL_TOO_SMALL "Lrecl trop petit (longueur en-tête = %d)"
359 MAKE_EMPTY_FILE "Génération du fichier vide %s: %s"
360 MAKING "Génération"
361 MALLOC_ERROR "Allocation mémoire impossible par %s"
362 MAP_VIEW_ERROR "MapViewOfFile %s erreur rc=%d"
363 MAXSIZE_ERROR "Maxsize incalculable sur table ouverte"
364 MEM_ALLOC_ERR "Erreur d'allocation mémoire, taille %s = %d"
365 MEM_ALLOC_ERROR "Erreur d'allocation mémoire"
366 MISPLACED_QUOTE "Appostrophe mal placée ligne %d"
367 MISSING_ARG "Argument manquant pour l'opérateur %d"
368 MISSING_FIELD "Champs %d manquant dans %s ligne %d"
369 MISSING_FNAME "Nom du fichier manquant"
370 MISSING_NODE "Noeud %s manquant dans %s"
371 MISSING_ROWNODE "Impossible de trouver le noeud de la ligne %d"
372 MIS_TAG_LIST "Liste des balises colonne manquante"
373 MUL_MAKECOL_ERR "Erreur logique dans TABMUL::MakeCol"
374 NAME_CONV_ERR "Erreur de convertion du nom de noeud"
375 NEW_DOC_FAILED "Impossible de créer le nouveau document"
376 NEW_RETURN_NULL "NULL renvoyé par New dans PlugEvalLike"
377 NEXT_FILE_ERROR "Erreur en recherche du fichier suivant. rc=%s"
378 NONCONT_EXCEPT "Exception non-continuable"
379 NOP_ZLIB_INDEX "L'indexage d'une table zlib non optimisée est impossible"
380 NOT_A_DBF_FILE "Le fichier n'a pas le format dBASE dbf "
381 NOT_FIXED_LEN "Fichier %s non fixe, len=%d lrecl=%d"
382 NO_0DH_HEAD "0DH manquant en fin d'en-tête (dbc=%d)"
383 NO_ACTIVE_DB "Pas de base de données active"
384 NO_CHAR_FROM "Conversion de type %d en caractères impossible"
385 NO_DATE_FMT "Pas de format date pour le valblock de type %d"
386 NO_DEF_FNCCOL "Colonne fonction par défaut introuvable"
387 NO_DEF_PIVOTCOL "Colonne pivot par défaut introuvable"
388 NO_DIR_INDX_RD "Pas d'accès directe des tables %s"
389 NO_FEAT_SUPPORT "%s non supporté dans cette version"
390 NO_FLD_FORMAT "Format absent pour le champs %d de %s"
391 NO_FORMAT_COL "Type COLUMN informattable"
392 NO_FORMAT_TYPE "Le format ne peut pas être défini à partir du type %d"
393 NO_INDEX_READ "Pas d'accès directe des tables multiples"
394 NO_KEY_COL "Pas de colonne clé trouvée"
395 NO_KEY_UPDATE "Le nom des clés ne peut pas être modifié"
396 NO_MAP_INSERT "MAP incompatible avec Insert"
397 NO_MATCHING_COL "Pas de colonne correspondant à %s dans %s"
398 NO_MATCH_COL "Colonne correspondante introuvable"
399 NO_MEMORY "Mémoire pleine"
400 NO_MODE_PADDED "Mode non supporté pour les fichiers 'padded'"
401 NO_MUL_VCT "Les tables VCT ne peuvent pas être multiples"
402 NO_ODBC_DELETE "Delete ne devrait pas être appelé pour les tables ODBC"
403 NO_ODBC_DIRECT "Accès directe des tables ODBC non encore implémenté"
404 NO_ODBC_MUL "Multiple(2) non supporté pour les tables ODBC"
405 NO_ODBC_SPECOL "Pas de colonne spéciale ODBC"
406 NO_PART_DEL "Delete partiel des fichier %s impossible"
407 NO_PART_MAP "Mapping partiel non implémenté pour cet OS"
408 NO_PAR_BLK_INS "Insertion de bloc partiel impossible"
409 NO_PIV_DIR_ACC "Pas d'accès directe aux tables PIVOT"
410 NO_READ_32 "Lecture de 32 octets impossible"
411 NO_RECOV_SPACE "Espace non recouvrable dans le fichier index"
412 NO_ROWID_FOR_AM "Accès direct impossible de ROWID pour les tables de type %s"
413 NO_ROW_NODE "Le nom du Rownode n'est pas défini"
414 NO_SECTION_NAME "Nom de section manquant"
415 NO_SEC_UPDATE "Les noms de section ne peuvent pas être modifiés"
416 NO_SETPOS_YET "SetPos pas encore implémenté pour les fichier %s"
417 NO_SPEC_COL "Pas de colonne spéciales MYSQL"
418 NO_SUB_VAL "Pas de sous-value d'un tableau de type %d"
419 NO_TABCOL_DATA "Pas de données pour la table %s colonne %s"
420 NO_TABLE_DEL "Delete non autorisé pour les tables %s "
421 NO_TAB_DATA "Pas de données pour la table %s"
422 NO_VCT_DELETE "Délétion Partielle non implémentée pour les fichiers VCT"
423 NO_ZIP_DELETE "Delete sur fichier Zip non encore implementé"
424 OPENING "Ouverture"
425 OPEN_EMPTY_FILE "Ouverture du fichier vide %s: %s"
426 OPEN_ERROR "Erreur d'ouverture %d en mode %d sur %s: "
427 OPEN_ERROR_IS "Erreur à l'ouverture de %s: %s"
428 OPEN_MODE_ERROR "Erreur d'ouverture(%s) %d sur %s"
429 OPEN_STRERROR "Erreur à l'ouverture: %s"
430 OPTBLK_RD_ERR "Erreur à la lecture d'un bloc optimisation: %s"
431 OPTBLK_WR_ERR "Erreur à l'écriture d'un bloc optimisation: %s"
432 OPTIMIZING "Optimisation de "
433 OPT_BMAP_RD_ERR "Erreur en lecture des bitmaps d'optimisation: %s"
434 OPT_BMAP_WR_ERR "Erreur en écriture des bitmaps d'optimisation: %s"
435 OPT_CANCELLED "Optimisation interrompue par l'utilisateur"
436 OPT_DVAL_RD_ERR "Erreur en lecture des valeurs distinctes: %s"
437 OPT_DVAL_WR_ERR "Erreur en écriture des valeurs distinctes: %s"
438 OPT_HEAD_RD_ERR "Erreur en lecture de l'entête du fichier opt: %s"
439 OPT_HEAD_WR_ERR "Erreur en écriture de l'entête du fichier opt: %s"
440 OPT_LOGIC_ERR "Erreur logique dans SetBitmap, i=%d"
441 OPT_MAX_RD_ERR "Erreur en lecture des valeurs maxi: %s"
442 OPT_MAX_WR_ERR "Erreur en écriture des valeurs maxi: %s"
443 OPT_MIN_RD_ERR "Erreur en lecture des valeurs mini: %s"
444 OPT_MIN_WR_ERR "Erreur en écriture des valeurs mini: %s"
445 OPT_NOT_MATCH "Le fichier opt %s n'est pas à jour"
446 PAGE_ERROR "Erreur de pagination"
447 PARM_CNT_MISS "Disparité du nombre de Paramètres"
448 PREC_VBLP_NULL "ARRAY SetPrecision: Vblp est NULL"
449 PRIV_INSTR "Instruction privilégiée"
450 PROCADD_ERROR "Erreur %d sur l'adresse de %s"
451 QUERY_CANCELLED "Requête interrompue par l'utilisateur"
452 RANGE_NO_JOIN "Range non compatible avec les index de jointure"
453 RC_READING "rc=%d en lecture de la table %s"
454 READY "Prêt"
455 READ_ERROR "Erreur en lecture sur %s: %s"
456 READ_ONLY "Cette table protégée en lecture seule ne peut être modifiée"
457 READ_SEEK_ERROR "Erreur de recherche en lecture: %s"
458 REGISTER_ERR "Enregistrement NS impossible, préfix='%s' et href='%s'"
459 REMOVE_ERROR "Erreur en supprimant %s: %s"
460 RENAME_ERROR "Erreur renommant %s en %s: %s"
461 ROWID_NOT_IMPL "RowNumber non implémenté pour les tables de type %s"
462 SEC_KEY_FIRST "Les sections et clés doivent être insérées en premier"
463 SEC_NAME_FIRST "Le nom de section doit être en tête de liste en insertion"
464 SEP_IN_FIELD "Le champ %d contient le caractère séparateur"
465 SEQUENCE_ERROR "HSTMT: Allocation hors séquence"
466 SETEOF_ERROR "Erreur %d dans SetEndOfFile"
467 SETRECPOS_NIY "SetRecpos non implémenté pour ce type de table"
468 SET_STR_TRUNC "SetValue: Chaîne de caractères tronquée"
469 SFP_ERROR "Erreur sur SetFilePointer: %s"
470 SHARED_LIB_ERR "Erreur au chargement de la librairie partagée %s: %s"
471 SINGLE_STEP "Pas à pas"
472 SORTING_VAL "Tri de %d valeurs"
473 SPCOL_READONLY "La colonne spéciale %s est en lecture seulement"
474 SQL_CONF_ERROR "Erreur SQL: SQL_CONFORMANCE"
475 SRCH_CLOSE_ERR "Erreur à la fermeture de l'Handle de recherche"
476 SRC_TABLE_UNDEF "La table source n'est pas définie"
477 STACK_OVERFLOW "Dépassement de capacité de la pile"
478 TABDIR_READONLY "Les tables DIR sont en lecture seulement"
479 TABLE_NOT_OPT "Table non optimisable"
480 TABLE_NO_INDEX "La table %s n'est pas indexable"
481 TABLE_READ_ONLY "Les tables %s sont en lecture seulement "
482 TABMUL_READONLY "Les tables multiples sont en lecture seulement"
483 TOO_MANY_FIELDS "Trop de champs ligne %d de %s"
484 TOO_MANY_JUMPS "Trop de niveaux de saut"
485 TOO_MANY_KEYS "Trop de clés (%d)"
486 TO_BLK_IS_NULL "To Blk est nul"
487 TRUNCATE_ERROR "Erreur en troncation: %s"
488 TRUNC_BY_ESTIM "Tronqué par l'option Estimate"
489 TYPE_MISMATCH "Clé et source ne sont pas du même type"
490 TYPE_VALUE_ERR "Colonne %s: disparité type(%s)/valeur(%s)"
491 UNBALANCE_QUOTE "Appostrophe en trop ligne %d"
492 UNDEFINED_AM "COLBLK %s: méthode d'accès indéfinie"
493 UNKNOWN_EXCPT "Exception non répertoriée"
494 UNMATCH_FIL_ARG "Argument de filtre dépareillé"
495 UPDATE_ERROR "Erreur en Update sur %s"
496 UPD_ZIP_NOT_IMP "Mise à jour des tables ZDOS non encore implementé"
497 VALSTR_TOO_LONG "Valeur %s trop longue pour une chaîne de longueur %d"
498 VALTYPE_NOMATCH "Disparité types de valeur"
499 VALUE_ERROR "Colonne %s: bloc valeur nul"
500 VALUE_TOO_BIG "Valeur %lld trop grande pour la colonne %s"
501 VALUE_TOO_LONG "Valeur %s trop longue pour la colonne %s de longueur %d"
502 VAL_ALLOC_ERR "Allocation impossible du noeud valeur"
503 VIR_NO_DELETE "Delete impossible sur les tables %s"
504 VIR_READ_ONLY "Les tables virtuelles %s sont en lecture seulement"
505 VOID_FIRST_ARG "Le premier argument ne doit pas être vide"
506 WORK_AREA "Espace de travail: %s"
507 WRITE_SEEK_ERR "Erreur de recherche en écriture: %s"
508 WRITE_STRERROR "Erreur en écriture sur %s: %s"
509 WRITING "Ecriture"
510 WRITING_ERROR "Erreur à l'écriture de %s: %s"
511 WS_CONV_ERR "Erreur de convertion de %s en WS"
512 XCOL_MISMATCH "La colonne %s ne correspond pas à l'index"
513 XFILE_READERR "Erreur %d en lisant le fichier index"
514 XFILE_WRITERR "Erreur en écrivant le fichier index: %s"
515 XMLTAB_INIT_ERR "Erreur d'initialisation de la table XML"
516 XML_INIT_ERROR "Erreur d'initialisation du nouveau fichier XML"
517 XPATH_CNTX_ERR "Le nouveau contexte XPath ne peut être créé"
518 XPATH_EVAL_ERR "Impossible d'évaluer l'emplacement xpath '%s'"
519 XPATH_NOT_SUPP "Xpath non supporté colonne %s"
......@@ -169,9 +169,9 @@
#define JSONMAX 10 // JSON Default max grp size
extern "C" {
char version[]= "Version 1.03.0007 October 20, 2015";
char version[]= "Version 1.04.0003 October 25, 2015";
#if defined(__WIN__)
char compver[]= "Version 1.03.0007 " __DATE__ " " __TIME__;
char compver[]= "Version 1.04.0003 " __DATE__ " " __TIME__;
char slash= '\\';
#else // !__WIN__
char slash= '/';
......@@ -941,7 +941,7 @@ ulonglong ha_connect::table_flags() const
// HA_NULL_IN_KEY | not implemented yet
// HA_FAST_KEY_READ | causes error when sorting (???)
HA_NO_TRANSACTIONS | HA_DUPLICATE_KEY_NOT_IN_ORDER |
HA_NO_BLOBS | HA_CAN_TABLE_CONDITION_PUSHDOWN;
HA_NO_BLOBS | HA_MUST_USE_TABLE_CONDITION_PUSHDOWN;
ha_connect *hp= (ha_connect*)this;
PTOS pos= hp->GetTableOptionStruct();
......@@ -1095,7 +1095,7 @@ bool GetBooleanTableOption(PGLOBAL g, PTOS options, char *opname, bool bdef)
/****************************************************************************/
int GetIntegerTableOption(PGLOBAL g, PTOS options, char *opname, int idef)
{
longlong opval= NO_IVAL;
ulonglong opval= NO_IVAL;
if (!options)
return idef;
......@@ -2195,58 +2195,111 @@ int ha_connect::CheckRecord(PGLOBAL g, const uchar *, uchar *newbuf)
} // 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. */
/***********************************************************************/
bool ha_connect::MakeKeyWhere(PGLOBAL g, PSTRG qry, OPVAL op, char q,
const void *key, int klen)
bool ha_connect::MakeKeyWhere(PGLOBAL g, PSTRG qry, OPVAL vop, char q,
const key_range *kr)
{
const uchar *ptr;
uint rem, len, stlen; //, prtlen;
bool nq, oom, b= false;
//uint i, rem, len, klen, stlen;
uint i, rem, len, stlen;
bool nq, both, oom= false;
OPVAL op;
Field *fp;
const key_range *ranges[2];
my_bitmap_map *old_map;
KEY *kfp;
KEY_PART_INFO *kpart;
if (active_index == MAX_KEY)
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");
return true;
} // endif key
} else
both= ranges[0] && ranges[1];
oom= qry->Append(" WHERE (");
kfp= &table->key_info[active_index];
rem= kfp->user_defined_key_parts,
len= klen,
ptr= (const uchar *)key;
old_map= dbug_tmp_use_all_columns(table, table->write_set);
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++) {
fp= kpart->field;
stlen= kpart->store_length;
// prtlen= MY_MIN(stlen, len);
nq= fp->str_needs_quotes();
if (b)
if (kpart != kfp->key_part)
oom|= qry->Append(" AND ");
else
b= true;
if (q) {
oom|= qry->Append(q);
oom|= qry->Append((PSZ)fp->field_name);
oom|= qry->Append(q);
} else
oom|= qry->Append((PSZ)fp->field_name);
switch (op) {
case OP_EQ:
case OP_GT:
case OP_GE:
case OP_LT:
case OP_LE:
oom |= qry->Append((PSZ)GetValStr(op, false));
switch (ranges[i]->flag) {
case HA_READ_KEY_EXACT:
// op= (stlen >= len || !nq || fp->result_type() != STRING_RESULT)
// ? OP_EQ : OP_LIKE;
op= OP_EQ;
break;
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;
default:
oom|= qry->Append(" ??? ");
} // endwitch op
sprintf(g->Message, "cannot handle flag %d", ranges[i]->flag);
goto err;
} // endswitch flag
oom|= qry->Append((PSZ)GetValStr(op, false));
if (nq)
oom|= qry->Append('\'');
......@@ -2255,19 +2308,19 @@ bool ha_connect::MakeKeyWhere(PGLOBAL g, PSTRG qry, OPVAL op, char q,
String varchar;
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);
oom|= qry->Append(varchar.ptr(), varchar.length());
oom|= qry->Append(varchar.ptr(), varchar.length(), nq);
} else {
char strbuff[MAX_FIELD_WIDTH];
String str(strbuff, sizeof(strbuff), kpart->field->charset()), *res;
res= fp->val_str(&str, ptr);
oom|= qry->Append(res->ptr(), res->length());
oom|= qry->Append(res->ptr(), res->length(), nq);
} // endif flag
if (nq)
oom|= qry->Append('\'');
oom |= qry->Append('\'');
if (stlen >= len)
break;
......@@ -2280,10 +2333,17 @@ bool ha_connect::MakeKeyWhere(PGLOBAL g, PSTRG qry, OPVAL op, char q,
ptr+= stlen - MY_TEST(kpart->null_bit);
} // endfor kpart
} // endfor i
if ((oom|= qry->Append(")")))
strcpy(g->Message, "Out of memory");
dbug_tmp_restore_column_map(table->write_set, old_map);
return oom;
err:
dbug_tmp_restore_column_map(table->write_set, old_map);
return true;
} // end of MakeKeyWhere
......@@ -2483,6 +2543,8 @@ PFIL ha_connect::CondFilter(PGLOBAL g, Item *cond)
case MYSQL_TYPE_YEAR:
case MYSQL_TYPE_NEWDATE:
return NULL;
default:
break;
} // endswitch type
if (trace) {
......@@ -2562,8 +2624,9 @@ PFIL ha_connect::CondFilter(PGLOBAL g, Item *cond)
/***********************************************************************/
/* 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;
unsigned int i;
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)
List<Item>* arglist= cond_item->argument_list();
List_iterator<Item> li(*arglist);
Item *subitem;
const Item *subitem;
p1= body + strlen(body);
strcpy(p1, "(");
......@@ -2604,7 +2667,7 @@ PCFIL ha_connect::CheckCond(PGLOBAL g, PCFIL filp, AMT tty, Item *cond)
for (i= 0; i < arglist->elements; i++)
if ((subitem= li++)) {
if (!CheckCond(g, filp, tty, subitem)) {
if (!CheckCond(g, filp, subitem)) {
if (vop == OP_OR || nonul)
return NULL;
else
......@@ -2626,7 +2689,6 @@ PCFIL ha_connect::CheckCond(PGLOBAL g, PCFIL filp, AMT tty, Item *cond)
} else if (cond->type() == COND::FUNC_ITEM) {
unsigned int i;
// int n;
bool iscol, neg= FALSE;
Item_func *condf= (Item_func *)cond;
Item* *args= condf->arguments();
......@@ -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(),
condf->argument_count());
// neg= condf->
switch (condf->functype()) {
case Item_func::EQUAL_FUNC:
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)
case Item_func::LE_FUNC: vop= OP_LE; break;
case Item_func::GE_FUNC: vop= OP_GE; 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::BETWEEN:
ismul= true;
......@@ -2658,7 +2722,7 @@ PCFIL ha_connect::CheckCond(PGLOBAL g, PCFIL filp, AMT tty, Item *cond)
else if (ismul && tty == TYPE_AM_WMI)
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;
for (i= 0; i < condf->argument_count(); i++) {
......@@ -2679,9 +2743,10 @@ PCFIL ha_connect::CheckCond(PGLOBAL g, PCFIL filp, AMT tty, Item *cond)
if (x && i)
return NULL;
if (pField->field->table != table)
else if (pField->field->table != 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
fop= GetFieldOptionStruct(pField->field);
......@@ -2712,7 +2777,7 @@ PCFIL ha_connect::CheckCond(PGLOBAL g, PCFIL filp, AMT tty, Item *cond)
strcat(body, fnm);
} else if (args[i]->type() == COND::FUNC_ITEM) {
if (tty == TYPE_AM_MYSQL) {
if (!CheckCond(g, filp, tty, args[i]))
if (!CheckCond(g, filp, args[i]))
return NULL;
} else
......@@ -2901,14 +2966,17 @@ const COND *ha_connect::cond_push(const COND *cond)
goto fin;
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= 0;
filp->Op= OP_XX;
filp->Cmds= NULL;
if (CheckCond(g, filp, tty, (Item *)cond)) {
if (CheckCond(g, filp, cond)) {
if (trace)
htrc("cond_push: %s\n", filp->Body);
......@@ -3372,13 +3440,13 @@ int ha_connect::index_end()
/****************************************************************************/
/* 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;
//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:
xp->fnd++;
rc= MakeRecord((char*)buf);
......@@ -3400,6 +3468,7 @@ int ha_connect::ReadIndexed(uchar *buf, OPVAL op, const uchar *key, uint key_len
if (trace > 1)
htrc("ReadIndexed: op=%d rc=%d\n", op, rc);
table->status= (rc == RC_OK) ? 0 : STATUS_NOT_FOUND;
return rc;
} // end of ReadIndexed
......@@ -3443,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);
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) {
nox= true; // To block making indexes
......@@ -3516,6 +3590,7 @@ int ha_connect::index_first(uchar *buf)
else if (indexing < 0)
rc= HA_ERR_INTERNAL_ERROR;
else if (CntRewindTable(xp->g, tdbp)) {
table->status= STATUS_NOT_FOUND;
rc= HA_ERR_INTERNAL_ERROR;
} else
rc= rnd_next(buf);
......@@ -3716,6 +3791,7 @@ int ha_connect::rnd_next(uchar *buf)
xp->fnd= xp->nfd= 0;
} // endif nrd
table->status= (!rc) ? 0 : STATUS_NOT_FOUND;
DBUG_RETURN(rc);
} // end of rnd_next
......@@ -3747,7 +3823,7 @@ void ha_connect::position(const uchar *)
//if (((PTDBASE)tdbp)->GetDef()->Indexable())
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());
DBUG_VOID_RETURN;
......@@ -5040,7 +5116,7 @@ static int connect_assisted_discovery(handlerton *, THD* thd,
char *nsp= NULL, *cls= NULL;
#endif // __WIN__
int port= 0, hdr= 0, mxr= 0, mxe= 0, rc= 0;
int cop __attribute__((unused))= 0;
int cop __attribute__((unused))= 0, lrecl= 0;
#if defined(ODBC_SUPPORT)
POPARM sop = NULL;
char *ucnc = NULL;
......@@ -6198,6 +6274,10 @@ bool ha_connect::FileExists(const char *fn, bool bf)
int n;
struct stat info;
if (check_access(ha_thd(), FILE_ACL, table->s->db.str,
NULL, NULL, 0, 0))
return true;
#if defined(__WIN__)
s= "\\";
#else // !__WIN__
......@@ -6683,10 +6763,10 @@ maria_declare_plugin(connect)
PLUGIN_LICENSE_GPL,
connect_init_func, /* Plugin Init */
connect_done_func, /* Plugin Deinit */
0x0103, /* version number (1.03) */
0x0104, /* version number (1.04) */
NULL, /* status variables */
connect_system_variables, /* system variables */
"1.03.0007", /* string version */
MariaDB_PLUGIN_MATURITY_GAMMA /* maturity */
"1.04.0003", /* string version */
MariaDB_PLUGIN_MATURITY_BETA /* maturity */
}
maria_declare_plugin_end;
......@@ -241,11 +241,12 @@ class ha_connect: public handler
int MakeRecord(char *buf);
int ScanRecord(PGLOBAL g, uchar *buf);
int CheckRecord(PGLOBAL g, const uchar *oldbuf, uchar *newbuf);
int ReadIndexed(uchar *buf, OPVAL op, const uchar* key= NULL,
uint key_len= 0);
int ReadIndexed(uchar *buf, OPVAL op, const key_range *kr= NULL);
bool IsIndexed(Field *fp);
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);
key_range start_key;
/** @brief
......@@ -374,7 +375,7 @@ class ha_connect: public handler
condition stack.
*/
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);
PFIL CondFilter(PGLOBAL g, Item *cond);
//PFIL CheckFilter(PGLOBAL g);
......
/*************** 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 */
/* */
......@@ -31,11 +31,12 @@
/***********************************************************************/
/* 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;
bool b = false;
int i, rc, pretty = (ptyp) ? *ptyp : 3;
bool b = false, pty[3] = {true, true, true};
PJSON jsp = NULL;
STRG src;
......@@ -48,6 +49,10 @@ PJSON ParseJson(PGLOBAL g, char *s, int len, int pretty, bool *comma)
src.str = s;
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
if (g->jump_level == MAX_JUMP) {
strcpy(g->Message, MSG(TOO_MANY_JUMPS));
......@@ -61,18 +66,16 @@ PJSON ParseJson(PGLOBAL g, char *s, int len, int pretty, bool *comma)
for (i = 0; i < len; i++)
switch (s[i]) {
case '[':
if (jsp) {
strcpy(g->Message, "More than one item in file");
goto err;
} else if (!(jsp = ParseArray(g, ++i, src)))
if (jsp)
goto tryit;
else if (!(jsp = ParseArray(g, ++i, src, pty)))
goto err;
break;
case '{':
if (jsp) {
strcpy(g->Message, "More than one item in file");
goto err;
} else if (!(jsp = ParseObject(g, ++i, src)))
if (jsp)
goto tryit;
else if (!(jsp = ParseObject(g, ++i, src, pty)))
goto err;
break;
......@@ -82,20 +85,16 @@ PJSON ParseJson(PGLOBAL g, char *s, int len, int pretty, bool *comma)
case '\r':
break;
case ',':
if (jsp && pretty == 1) {
if (jsp && (pretty == 1 || pretty == 3)) {
if (comma)
*comma = true;
pty[0] = pty[2] = false;
break;
} // endif pretty
sprintf(g->Message, "Unexpected ',' (pretty=%d)", pretty);
goto err;
case '"':
if (!(jsp = ParseValue(g, i, src)))
goto err;
break;
case '(':
b = true;
break;
......@@ -106,18 +105,41 @@ PJSON ParseJson(PGLOBAL g, char *s, int len, int pretty, bool *comma)
} // endif b
default:
sprintf(g->Message, "Bad '%c' character near %.*s",
s[i], ARGS);
if (jsp)
goto tryit;
else if (!(jsp = ParseValue(g, i, src, pty)))
goto err;
break;
}; // endswitch s[i]
if (!jsp)
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--;
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--;
return NULL;
} // end of ParseJson
......@@ -125,11 +147,12 @@ PJSON ParseJson(PGLOBAL g, char *s, int len, int pretty, bool *comma)
/***********************************************************************/
/* 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;
int len = src.len;
int level = 0;
bool b = (!i);
PJAR jarp = new(g) JARRAY;
PJVAL jvp = NULL;
......@@ -151,25 +174,32 @@ PJAR ParseArray(PGLOBAL g, int& i, STRG& src)
jarp->InitArray(g);
return jarp;
case ' ':
case '\t':
case '\n':
if (!b)
pty[0] = pty[1] = false;
case '\r':
case ' ':
case '\t':
break;
default:
if (level == 2) {
sprintf(g->Message, "Unexpected value near %.*s", ARGS);
return NULL;
} else if ((jvp = ParseValue(g, i, src))) {
} else if ((jvp = ParseValue(g, i, src, pty)))
jarp->AddValue(g, jvp);
level = 2;
} else
else
return NULL;
level = 2;
level = (b) ? 1 : 2;
break;
}; // endswitch s[i]
if (b) {
// Case of Pretty == 0
jarp->InitArray(g);
return jarp;
} // endif b
strcpy(g->Message, "Unexpected EOF in array");
return NULL;
} // end of ParseArray
......@@ -177,7 +207,7 @@ PJAR ParseArray(PGLOBAL g, int& i, STRG& src)
/***********************************************************************/
/* Parse a JSON Object. */
/***********************************************************************/
PJOB ParseObject(PGLOBAL g, int& i, STRG& src)
PJOB ParseObject(PGLOBAL g, int& i, STRG& src, bool *pty)
{
PSZ key;
char *s = src.str;
......@@ -204,7 +234,7 @@ PJOB ParseObject(PGLOBAL g, int& i, STRG& src)
break;
case ':':
if (level == 1) {
if (!(jpp->Val = ParseValue(g, ++i, src)))
if (!(jpp->Val = ParseValue(g, ++i, src, pty)))
return NULL;
level = 2;
......@@ -229,10 +259,11 @@ PJOB ParseObject(PGLOBAL g, int& i, STRG& src)
} // endif level
return jobp;
case ' ':
case '\t':
case '\n':
pty[0] = pty[1] = false;
case '\r':
case ' ':
case '\t':
break;
default:
sprintf(g->Message, "Unexpected character '%c' near %.*s",
......@@ -247,7 +278,7 @@ PJOB ParseObject(PGLOBAL g, int& i, STRG& src)
/***********************************************************************/
/* 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;
int n, len = src.len;
......@@ -255,10 +286,11 @@ PJVAL ParseValue(PGLOBAL g, int& i, STRG& src)
for (; i < len; i++)
switch (s[i]) {
case ' ':
case '\t':
case '\n':
pty[0] = pty[1] = false;
case '\r':
case ' ':
case '\t':
break;
default:
goto suite;
......@@ -267,12 +299,12 @@ PJVAL ParseValue(PGLOBAL g, int& i, STRG& src)
suite:
switch (s[i]) {
case '[':
if (!(jvp->Jsp = ParseArray(g, ++i, src)))
if (!(jvp->Jsp = ParseArray(g, ++i, src, pty)))
return NULL;
break;
case '{':
if (!(jvp->Jsp = ParseObject(g, ++i, src)))
if (!(jvp->Jsp = ParseObject(g, ++i, src, pty)))
return NULL;
break;
......@@ -319,7 +351,6 @@ PJVAL ParseValue(PGLOBAL g, int& i, STRG& src)
}; // endswitch s[i]
jvp->Size = 1;
return jvp;
err:
......@@ -481,9 +512,9 @@ PVAL ParseNumeric(PGLOBAL g, int& i, STRG& src)
valp = AllocateValue(g, &dv, TYPE_DOUBLE, nd);
} 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
i--; // Unstack following character
......@@ -501,27 +532,36 @@ PVAL ParseNumeric(PGLOBAL g, int& i, STRG& src)
/***********************************************************************/
/* Serialize a JSON tree: */
/***********************************************************************/
PSZ Serialize(PGLOBAL g, PJSON jsp, FILE *fs, int pretty)
PSZ Serialize(PGLOBAL g, PJSON jsp, char *fn, int pretty)
{
bool b = false, err = true;
JOUT *jp;
FILE *fs = NULL;
g->Message[0] = 0;
if (!jsp) {
strcpy(g->Message, "Null json tree");
return NULL;
} else if (!fs) {
} else if (!fn) {
// Serialize to a string
jp = new(g) JOUTSTR(g);
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));
return g->Message;
} else if (pretty >= 2) {
// Serialize to a pretty file
jp = new(g) JOUTPRT(g, fs);
jp = new(g)JOUTPRT(g, fs);
} else {
// Serialize to a flat file
jp = new(g) JOUTFILE(g, fs);
b = pretty == 1;
b = true;
jp = new(g)JOUTFILE(g, fs, pretty);
} // endif's
} // endif's
switch (jsp->GetType()) {
......@@ -529,7 +569,7 @@ PSZ Serialize(PGLOBAL g, PJSON jsp, FILE *fs, int pretty)
err = SerializeArray(jp, (PJAR)jsp, b);
break;
case TYPE_JOB:
err = (b && jp->WriteChr('\t'));
err = ((b && jp->Prty()) && jp->WriteChr('\t'));
err |= SerializeObject(jp, (PJOB)jsp);
break;
case TYPE_JVAL:
......@@ -540,7 +580,7 @@ PSZ Serialize(PGLOBAL g, PJSON jsp, FILE *fs, int pretty)
} // endswitch Type
if (fs) {
fputc('\n', fs);
fputs(EL, fs);
fclose(fs);
return (err) ? g->Message : NULL;
} else if (!err) {
......@@ -565,29 +605,40 @@ bool SerializeArray(JOUT *js, PJAR jarp, bool b)
{
bool first = true;
if (b) {
if (js->Prty()) {
if (js->WriteChr('['))
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;
for (int i = 0; i < jarp->size(); i++) {
if (first)
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;
else if (b && (js->WriteStr(EL) || js->WriteChr('\t')))
else if (js->Prty() == 1 && js->WriteChr('\t'))
return true;
} // endif b
if (SerializeValue(js, jarp->GetValue(i)))
return true;
} // endfor i
if (b && js->WriteStr(EL))
if (b && js->Prty() == 1 && js->WriteStr(EL))
return true;
return js->WriteChr(']');
return ((!b || js->Prty()) && js->WriteChr(']'));
} // end of SerializeArray
/***********************************************************************/
......@@ -647,8 +698,8 @@ bool SerializeValue(JOUT *js, PJVAL jvp)
} // endswitch Type
strcpy(js->g->Message, "Unrecognized value");
return true;
strcpy(js->g->Message, "Unrecognized value");
return true;
} // end of SerializeValue
/* -------------------------- Class JOUTSTR -------------------------- */
......@@ -866,6 +917,20 @@ PJPR JOBJECT::AddPair(PGLOBAL g, PSZ key)
return jpp;
} // 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. */
/***********************************************************************/
......@@ -903,6 +968,24 @@ PSZ JOBJECT::GetText(PGLOBAL g, PSZ text)
return text + n;
} // 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. */
/***********************************************************************/
......@@ -923,6 +1006,23 @@ void JOBJECT::SetValue(PGLOBAL g, PJVAL jvp, PSZ key)
} // 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. */
/***********************************************************************/
......@@ -943,23 +1043,25 @@ bool JOBJECT::IsNull(void)
void JARRAY::InitArray(PGLOBAL g)
{
int i;
PJVAL jvp;
PJVAL jvp, *pjvp = &First;
for (Size = 0, jvp = First; jvp; jvp = jvp->Next)
if (!jvp->Del)
Size++;
if (!Size) {
return;
} else if (Size > Alloc) {
if (Size > Alloc) {
// No need to realloc after deleting values
Mvals = (PJVAL*)PlugSubAlloc(g, NULL, Size * sizeof(PJVAL));
Alloc = Size;
} // endif Size
for (i = 0, jvp = First; jvp; jvp = jvp->Next)
if (!jvp->Del)
if (!jvp->Del) {
Mvals[i++] = jvp;
pjvp = &jvp->Next;
Last = jvp;
} else
*pjvp = jvp->Next;
} // end of InitArray
......@@ -975,31 +1077,64 @@ PJVAL JARRAY::GetValue(int i)
} // 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)
jvp = new(g) JVALUE;
if (x) {
int i = 0, n = *x;
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 (Last)
Last->Next = jvp;
else
First = jvp;
Last = jvp;
} // endif x
return jvp;
} // 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)
{
int i = 0;
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)
*jpp = jp = new(g) JVALUE;
......@@ -1048,6 +1183,17 @@ JVALUE::JVALUE(PGLOBAL g, PVAL valp) : JSON()
Del = false;
} // 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. */
/***********************************************************************/
......@@ -1092,6 +1238,14 @@ int JVALUE::GetInteger(void)
return (Value) ? Value->GetIntValue() : 0;
} // 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. */
/***********************************************************************/
......@@ -1134,7 +1288,26 @@ PSZ JVALUE::GetText(PGLOBAL g, PSZ text)
void JVALUE::SetInteger(PGLOBAL g, int n)
{
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. */
......@@ -1142,15 +1315,17 @@ void JVALUE::SetInteger(PGLOBAL g, int n)
void JVALUE::SetFloat(PGLOBAL g, double f)
{
Value = AllocateValue(g, &f, TYPE_DOUBLE, 6);
} // end of AddFloat
Jsp = NULL;
} // end of SetFloat
/***********************************************************************/
/* 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);
} // end of AddFloat
Value = AllocateValue(g, s, TYPE_STRING, c);
Jsp = NULL;
} // end of SetString
/***********************************************************************/
/* True when its JSON or normal value is null. */
......
/**************** 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 */
/* */
......@@ -16,6 +16,7 @@
enum JTYP {TYPE_STRG = 1,
TYPE_DBL = 2,
TYPE_BOOL = 4,
TYPE_BINT = 5,
TYPE_INTG = 7,
TYPE_JSON = 12,
TYPE_JAR,
......@@ -40,13 +41,13 @@ typedef struct {
int len;
} STRG, *PSG;
PJSON ParseJson(PGLOBAL g, char *s, int n, int prty, bool *b = NULL);
PJAR ParseArray(PGLOBAL g, int& i, STRG& src);
PJOB ParseObject(PGLOBAL g, int& i, STRG& src);
PJVAL ParseValue(PGLOBAL g, int& i, STRG& src);
PJSON ParseJson(PGLOBAL g, char *s, int n, int *prty = NULL, bool *b = NULL);
PJAR ParseArray(PGLOBAL g, int& i, STRG& src, bool *pty);
PJOB ParseObject(PGLOBAL g, int& i, STRG& src, bool *pty);
PJVAL ParseValue(PGLOBAL g, int& i, STRG& src, bool *pty);
char *ParseString(PGLOBAL g, int& i, STRG& src);
PVAL ParseNumeric(PGLOBAL g, int& i, STRG& src);
PSZ Serialize(PGLOBAL g, PJSON jsp, FILE *fs, int pretty);
PSZ Serialize(PGLOBAL g, PJSON jsp, char *fn, int pretty);
bool SerializeArray(JOUT *js, PJAR jarp, bool b);
bool SerializeObject(JOUT *js, PJOB jobp);
bool SerializeValue(JOUT *js, PJVAL jvp);
......@@ -56,14 +57,16 @@ bool SerializeValue(JOUT *js, PJVAL jvp);
/***********************************************************************/
class JOUT : public BLOCK {
public:
JOUT(PGLOBAL gp) : BLOCK() {g = gp;}
JOUT(PGLOBAL gp) : BLOCK() {g = gp; Pretty = 3;}
virtual bool WriteStr(const char *s) = 0;
virtual bool WriteChr(const char c) = 0;
virtual bool Escape(const char *s) = 0;
int Prty(void) {return Pretty;}
// Member
PGLOBAL g;
int Pretty;
}; // end of class JOUT
/***********************************************************************/
......@@ -88,7 +91,7 @@ class JOUTSTR : public JOUT {
/***********************************************************************/
class JOUTFILE : public JOUT {
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 WriteChr(const char c);
......@@ -103,7 +106,7 @@ class JOUTFILE : public JOUT {
/***********************************************************************/
class JOUTPRT : public JOUTFILE {
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 WriteChr(const char c);
......@@ -118,7 +121,8 @@ class JOUTPRT : public JOUTFILE {
/***********************************************************************/
class JPAIR : public BLOCK {
friend class JOBJECT;
friend PJOB ParseObject(PGLOBAL, int&, STRG&);
friend class JSNX;
friend PJOB ParseObject(PGLOBAL, int&, STRG&, bool*);
friend bool SerializeObject(JOUT *, PJOB);
public:
JPAIR(PSZ key) : BLOCK() {Key = key; Val = NULL; Next = NULL;}
......@@ -145,26 +149,30 @@ class JSON : public BLOCK {
virtual JTYP GetType(void) {return TYPE_JSON;}
virtual JTYP GetValType(void) {X return TYPE_JSON;}
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 PJAR GetKeyList(PGLOBAL g) {X return NULL;}
virtual PJVAL GetValue(const char *key) {X return NULL;}
virtual PJOB GetObject(void) {return NULL;}
virtual PJAR GetArray(void) {return NULL;}
virtual PJVAL GetValue(int i) {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 int GetInteger(void) {X return 0;}
virtual double GetFloat() {X return 0.0;}
virtual PSZ GetString() {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(PVAL valp) {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 SetFloat(PGLOBAL g, double f) {X}
virtual void DeleteKey(char *k) {X}
virtual bool DeleteValue(int i) {X return true;}
virtual bool IsNull(void) {X return true;}
......@@ -176,8 +184,9 @@ class JSON : public BLOCK {
/* Class JOBJECT: contains a list of value pairs. */
/***********************************************************************/
class JOBJECT : public JSON {
friend PJOB ParseObject(PGLOBAL, int&, STRG&);
friend PJOB ParseObject(PGLOBAL, int&, STRG&, bool*);
friend bool SerializeObject(JOUT *, PJOB);
friend class JSNX;
public:
JOBJECT(void) : JSON() {First = Last = NULL;}
......@@ -189,8 +198,11 @@ class JOBJECT : public JSON {
virtual PJPR AddPair(PGLOBAL g, PSZ key);
virtual PJOB GetObject(void) {return this;}
virtual PJVAL GetValue(const char* key);
virtual PJAR GetKeyList(PGLOBAL g);
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 DeleteKey(char *k);
virtual bool IsNull(void);
protected:
......@@ -202,7 +214,7 @@ class JOBJECT : public JSON {
/* Class JARRAY. */
/***********************************************************************/
class JARRAY : public JSON {
friend PJAR ParseArray(PGLOBAL, int&, STRG&);
friend PJAR ParseArray(PGLOBAL, int&, STRG&, bool*);
public:
JARRAY(void) : JSON() {Alloc = 0; First = Last = NULL; Mvals = NULL;}
......@@ -211,9 +223,10 @@ class JARRAY : public JSON {
virtual void Clear(void) {First = Last = NULL; Size = 0;}
virtual JTYP GetType(void) {return TYPE_JAR;}
virtual PJAR GetArray(void) {return this;}
virtual PJVAL AddValue(PGLOBAL g, PJVAL jvp = NULL);
virtual PJVAL AddValue(PGLOBAL g, PJVAL jvp = NULL, int *x = NULL);
virtual void InitArray(PGLOBAL g);
virtual PJVAL GetValue(int i);
virtual bool Merge(PGLOBAL g, PJSON jsp);
virtual bool SetValue(PGLOBAL g, PJVAL jvp, int i);
virtual bool DeleteValue(int n);
virtual bool IsNull(void);
......@@ -231,7 +244,8 @@ class JARRAY : public JSON {
/***********************************************************************/
class JVALUE : public JSON {
friend class JARRAY;
friend PJVAL ParseValue(PGLOBAL, int&, STRG&);
friend class JSNX;
friend PJVAL ParseValue(PGLOBAL, int&, STRG&, bool*);
friend bool SerializeValue(JOUT *, PJVAL);
public:
JVALUE(void) : JSON()
......@@ -239,6 +253,7 @@ class JVALUE : public JSON {
JVALUE(PJSON jsp) : JSON()
{Jsp = jsp; Value = NULL; Next = NULL; Del = false;}
JVALUE(PGLOBAL g, PVAL valp);
JVALUE(PGLOBAL g, PSZ strp);
using JSON::GetValue;
using JSON::SetValue;
......@@ -249,16 +264,20 @@ class JVALUE : public JSON {
virtual PJOB GetObject(void);
virtual PJAR GetArray(void);
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 long long GetBigint(void);
virtual double GetFloat(void);
virtual PSZ GetString(void);
virtual PSZ GetText(PGLOBAL g, PSZ text);
virtual void SetValue(PVAL valp) {Value = valp;}
virtual void SetValue(PJSON jsp) {Jsp = jsp;}
virtual void SetString(PGLOBAL g, PSZ s);
virtual void SetValue(PVAL valp) {Value = valp; Jsp = NULL;}
virtual void SetValue(PJSON jsp) {Jsp = jsp; Value = NULL;}
virtual void SetString(PGLOBAL g, PSZ s, short c = 0);
virtual void SetInteger(PGLOBAL g, int n);
virtual void SetBigint(PGLOBAL g, longlong ll);
virtual void SetFloat(PGLOBAL g, double f);
virtual void SetTiny(PGLOBAL g, char f);
virtual bool IsNull(void);
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_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 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 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_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_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);
// 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 GetValue(PGLOBAL g, PJSON row, int i, my_bool b = true);
PJVAL GetJson(PGLOBAL g);
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);
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
}; // end of class JSNX
......@@ -299,13 +299,13 @@ int GetIndexType(TABTYPE type)
xtyp= 1;
break;
case TAB_MYSQL:
// case TAB_ODBC:
case TAB_ODBC:
xtyp= 2;
break;
case TAB_VIR:
xtyp= 3;
break;
case TAB_ODBC:
// case TAB_ODBC:
default:
xtyp= 0;
break;
......
......@@ -30,3 +30,30 @@ SELECT id, TIME(tim) FROM t1 LIMIT 1;
id TIME(tim)
1 09:35:08.000000
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;
......@@ -171,6 +171,40 @@ line
]
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
#
CREATE TABLE t1 (
......
CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=VIR BLOCK_SIZE=5;
#
# 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('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();
Json_Array()
[]
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_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]
SELECT Json_Array(Json_Array(56,3.1416,'foo'),NULL);
Json_Array(Json_Array(56,3.1416,'foo'),NULL)
[[56,3.141600,"foo"],null]
SELECT Json_Array_Add(Json_Array(56,3.1416,'foo',NULL)) Array;
ERROR HY000: Can't initialize function 'Json_Array_Add'; Json_Value_Add must have at least 2 arguments
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
[56,3.141600,"foo",null,"One more"]
SELECT Json_Array_Add(Json_Value('one value'),'One more');
Json_Array_Add(Json_Value('one value'),'One more')
["one value","One more"]
SELECT Json_Array_Add(JsonValue('one value'),'One more');
ERROR HY000: Can't initialize function 'json_array_add'; First argument must be a json item
SELECT Json_Array_Add('one value','One more');
ERROR HY000: Can't initialize function 'Json_Array_Add'; Json_Value_Add first argument must be a json item
ERROR HY000: Can't initialize function 'json_array_add'; First argument must be a json item
SELECT Json_Array_Add('one value' json_,'One more');
Json_Array_Add('one value' json_,'One more')
[null,"One more"]
one value
Warnings:
Warning 1105 Bad 'o' character near one value
SELECT Json_Value(56,3.1416,'foo',NULL);
ERROR HY000: Can't initialize function 'Json_Value'; Json_Value cannot accept more than 1 argument
SELECT Json_Value(3.1416);
Json_Value(3.1416)
3.141600
SELECT Json_Value('foo');
Json_Value('foo')
"foo"
SELECT Json_Value(NULL);
Json_Value(NULL)
null
SELECT Json_Value();
Json_Value()
null
Warning 1105 Error 2 opening one value
Warning 1105 First argument target is not an array
SELECT Json_Array_Add('[5,3,8,7,9]' json_, 4, 0);
Json_Array_Add('[5,3,8,7,9]' json_, 4, 0)
[4,5,3,8,7,9]
SELECT Json_Array_Add('[5,3,8,7,9]' json_, 4, 2) Array;
Array
[5,3,4,8,7,9]
SELECT Json_Array_Add('[5,3,8,7,9]' json_, 4, 9);
Json_Array_Add('[5,3,8,7,9]' json_, 4, 9)
[5,3,8,7,9,4]
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_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();
Json_Object()
{}
SELECT 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}
SELECT Json_Array(Json_Array(56,3.1416,'foo'),NULL);
Json_Array(Json_Array(56,3.1416,'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)
SELECT 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}
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]
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_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
#
CREATE TABLE t1
CREATE TABLE t2
(
ISBN CHAR(15),
LANG CHAR(2),
......@@ -69,21 +153,20 @@ TRANSLATOR CHAR(80),
PUBLISHER CHAR(32),
DATEPUB int(4)
) 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)
["Jean-Christophe Bernadac","Construire une application XML",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)
{"AUTHOR":"Jean-Christophe Bernadac","TITLE":"Construire une application XML","DATEPUB":1999}
{"AUTHOR":"William J. Pardi","TITLE":"XML en Action","DATEPUB":1999}
SELECT Json_Array_Grp(TITLE, DATEPUB) FROM t1;
ERROR HY000: Can't initialize function 'Json_Array_Grp'; Json_Array_Grp can only accept 1 argument
SELECT Json_Array_Grp(TITLE) FROM t1;
SELECT Json_Array_Grp(TITLE, DATEPUB) FROM t2;
ERROR HY000: Can't initialize function 'json_array_grp'; This function can only accept 1 argument
SELECT Json_Array_Grp(TITLE) FROM t2;
Json_Array_Grp(TITLE)
["Construire une application XML","XML en Action"]
DROP TABLE t1;
CREATE TABLE t1 (
CREATE TABLE t3 (
SERIALNO CHAR(5) NOT NULL,
NAME VARCHAR(12) NOT NULL FLAG=6,
SEX SMALLINT(1) NOT NULL,
......@@ -93,10 +176,10 @@ DEPARTMENT CHAr(4) NOT NULL FLAG=41,
SECRETARY CHAR(5) DEFAULT NULL FLAG=46,
SALARY DOUBLE(8,2) NOT NULL FLAG=52
) 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)
{"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)
0021 ["STRONG","SHORTSIGHT"]
0318 ["BANCROFT","PLUMHEAD","HONEY","TONGHO","WALTER","SHRINKY","WERTHER","MERCHANT","WHEELFOR"]
......@@ -104,26 +187,26 @@ DEPARTMENT Json_Array_Grp(NAME)
2452 ["BIGHEAD","ORELLY","BIGHORN","SMITH","CHERRY"]
Warnings:
Warning 1105 Result truncated to json_grp_size values
set connect_json_grp_size=30;
SELECT Json_Array(DEPARTMENT, Json_Array_Grp(NAME)) FROM t1 GROUP BY DEPARTMENT;
SET connect_json_grp_size=30;
SELECT Json_Array(DEPARTMENT, Json_Array_Grp(NAME)) FROM t3 GROUP BY DEPARTMENT;
Json_Array(DEPARTMENT, Json_Array_Grp(NAME))
["0021",["STRONG","SHORTSIGHT"]]
["0318",["BANCROFT","PLUMHEAD","HONEY","TONGHO","WALTER","SHRINKY","WERTHER","MERCHANT","WHEELFOR"]]
["0319",["BULLOZER","QUINN","BROWNY","KITTY","MONAPENNY","MARTIN","FUNNIGUY","BUGHAPPY","FODDERMAN","MESSIFUL","GOOSEPEN"]]
["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)
{"DEPARTMENT":"0021","NAMES":["STRONG","SHORTSIGHT"]}
{"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":"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)
{"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":"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}]}
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)
{"DEPARTMENT":"0021","TITLE":"DIRECTOR","EMPLOYES":[{"SERIALNO":"87777","NAME":"STRONG","SALARY":23000.000000}]}
{"DEPARTMENT":"0021","TITLE":"SECRETARY","EMPLOYES":[{"SERIALNO":"22222","NAME":"SHORTSIGHT","SALARY":5500.000000}]}
......@@ -143,25 +226,372 @@ 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":"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}]}
SELECT Json_Object_Grp(SALARY) FROM t1;
ERROR HY000: Can't initialize function 'Json_Object_Grp'; Json_Array_Grp can only accept 2 arguments
SELECT Json_Object_Grp(SALARY, NAME) FROM t1;
SELECT Json_Object_Grp(SALARY) FROM t3;
ERROR HY000: Can't initialize function 'json_object_grp'; This function requires 2 arguments (value, key)
SELECT Json_Object_Grp(SALARY, NAME) FROM t3;
Json_Object_Grp(SALARY, NAME)
{"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(SALARY, NAME) "Json_SALARIES") FROM t3 GROUP BY DEPARTMENT;
Json_Object(DEPARTMENT, Json_Object_Grp(SALARY, NAME) "Json_SALARIES")
{"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":"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}}
SELECT Json_Array_Grp(NAME) from t1;
SELECT Json_Array_Grp(NAME) FROM t3;
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"]
#
# 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
Warnings:
Warning 1105 Value not found
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
Warnings:
Warning 1105 Value not found
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 FUNCTION Json_Array;
DROP FUNCTION Json_Array_Add;
DROP FUNCTION Json_Object;
DROP FUNCTION Json_Object_Nonull;
DROP FUNCTION Json_Value;
DROP FUNCTION Json_Array_Grp;
DROP FUNCTION Json_Object_Grp;
DROP TABLE t2;
DROP TABLE t3;
SET NAMES utf8;
CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CONNECTION='Bad connection string';
ERROR HY000: SQLDriverConnect: [unixODBC][Driver Manager]Data source name not found, and no default driver specified
CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CATFUNC=Sources;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`Name` varchar(256) NOT NULL,
`Description` varchar(256) NOT NULL
) ENGINE=CONNECT DEFAULT CHARSET=latin1 `TABLE_TYPE`='ODBC' `CATFUNC`='Sources'
SELECT * FROM t1;
Name Description
Firebird Firebird
DROP TABLE t1;
CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CATFUNC=Drivers;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`Description` char(128) NOT NULL,
`Attributes` varchar(256) NOT NULL
) ENGINE=CONNECT DEFAULT CHARSET=latin1 `TABLE_TYPE`='ODBC' `CATFUNC`='Drivers'
SELECT * FROM t1;
Description Attributes
Firebird Description=Firebird ODBC Driver in usr;Driver=/usr/local/lib/libOdbcFb.so;Setup=/usr/local/lib/libOdbcFb.so;FileUsage=1;
DROP TABLE t1;
CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CATFUNC=Tables CONNECTION='Not important';
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`Table_Cat` char(128) NOT NULL,
`Table_Schema` char(128) NOT NULL,
`Table_Name` char(128) NOT NULL,
`Table_Type` char(16) NOT NULL,
`Remark` char(255) NOT NULL
) ENGINE=CONNECT DEFAULT CHARSET=latin1 CONNECTION='Not important' `TABLE_TYPE`='ODBC' `CATFUNC`='Tables'
DROP TABLE t1;
CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CATFUNC=Columns CONNECTION='Not important';
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`Table_Cat` char(128) NOT NULL,
`Table_Schema` char(128) NOT NULL,
`Table_Name` char(128) NOT NULL,
`Column_Name` char(128) NOT NULL,
`Data_Type` smallint(6) NOT NULL,
`Type_Name` char(30) NOT NULL,
`Column_Size` int(10) NOT NULL,
`Buffer_Length` int(10) NOT NULL,
`Decimal_Digits` smallint(6) NOT NULL,
`Radix` smallint(6) NOT NULL,
`Nullable` smallint(6) NOT NULL,
`Remarks` char(255) NOT NULL
) ENGINE=CONNECT DEFAULT CHARSET=latin1 CONNECTION='Not important' `TABLE_TYPE`='ODBC' `CATFUNC`='Columns'
DROP TABLE t1;
CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC TABNAME='EMPLOYEE' CONNECTION='DSN=Firebird;UID=SYSDBA;PWD=manager';
SELECT * FROM t1;
EMP_NO FIRST_NAME LAST_NAME PHONE_EXT HIRE_DATE DEPT_NO JOB_CODE JOB_GRADE JOB_COUNTRY SALARY FULL_NAME
2 Robert Nelson 250 1988-12-28 00:00:00 600 VP 2 USA 105900.00 Nelson, Robert
4 Bruce Young 233 1988-12-28 00:00:00 621 Eng 2 USA 97500.00 Young, Bruce
5 Kim Lambert 22 1989-02-06 00:00:00 130 Eng 2 USA 102750.00 Lambert, Kim
8 Leslie Johnson 410 1989-04-05 00:00:00 180 Mktg 3 USA 64635.00 Johnson, Leslie
9 Phil Forest 229 1989-04-17 00:00:00 622 Mngr 3 USA 75060.00 Forest, Phil
11 K. J. Weston 34 1990-01-17 00:00:00 130 SRep 4 USA 86292.94 Weston, K. J.
12 Terri Lee 256 1990-05-01 00:00:00 000 Admin 4 USA 53793.00 Lee, Terri
14 Stewart Hall 227 1990-06-04 00:00:00 900 Finan 3 USA 69482.63 Hall, Stewart
15 Katherine Young 231 1990-06-14 00:00:00 623 Mngr 3 USA 67241.25 Young, Katherine
20 Chris Papadopoulos 887 1990-01-01 00:00:00 671 Mngr 3 USA 89655.00 Papadopoulos, Chris
24 Pete Fisher 888 1990-09-12 00:00:00 671 Eng 3 USA 81810.19 Fisher, Pete
28 Ann Bennet 5 1991-02-01 00:00:00 120 Admin 5 England 22935.00 Bennet, Ann
29 Roger De Souza 288 1991-02-18 00:00:00 623 Eng 3 USA 69482.63 De Souza, Roger
34 Janet Baldwin 2 1991-03-21 00:00:00 110 Sales 3 USA 61637.81 Baldwin, Janet
36 Roger Reeves 6 1991-04-25 00:00:00 120 Sales 3 England 33620.63 Reeves, Roger
37 Willie Stansbury 7 1991-04-25 00:00:00 120 Eng 4 England 39224.06 Stansbury, Willie
44 Leslie Phong 216 1991-06-03 00:00:00 623 Eng 4 USA 56034.38 Phong, Leslie
45 Ashok Ramanathan 209 1991-08-01 00:00:00 621 Eng 3 USA 80689.50 Ramanathan, Ashok
46 Walter Steadman 210 1991-08-09 00:00:00 900 CFO 1 USA 116100.00 Steadman, Walter
52 Carol Nordstrom 420 1991-10-02 00:00:00 180 PRel 4 USA 42742.50 Nordstrom, Carol
61 Luke Leung 3 1992-02-18 00:00:00 110 SRep 4 USA 68805.00 Leung, Luke
65 Sue Anne O'Brien 877 1992-03-23 00:00:00 670 Admin 5 USA 31275.00 O'Brien, Sue Anne
71 Jennifer M. Burbank 289 1992-04-15 00:00:00 622 Eng 3 USA 53167.50 Burbank, Jennifer M.
72 Claudia Sutherland NULL 1992-04-20 00:00:00 140 SRep 4 Canada 100914.00 Sutherland, Claudia
83 Dana Bishop 290 1992-06-01 00:00:00 621 Eng 3 USA 62550.00 Bishop, Dana
85 Mary S. MacDonald 477 1992-06-01 00:00:00 100 VP 2 USA 111262.50 MacDonald, Mary S.
94 Randy Williams 892 1992-08-08 00:00:00 672 Mngr 4 USA 56295.00 Williams, Randy
105 Oliver H. Bender 255 1992-10-08 00:00:00 000 CEO 1 USA 212850.00 Bender, Oliver H.
107 Kevin Cook 894 1993-02-01 00:00:00 670 Dir 2 USA 111262.50 Cook, Kevin
109 Kelly Brown 202 1993-02-04 00:00:00 600 Admin 5 USA 27000.00 Brown, Kelly
110 Yuki Ichida 22 1993-02-04 00:00:00 115 Eng 3 Japan 6000000.00 Ichida, Yuki
113 Mary Page 845 1993-04-12 00:00:00 671 Eng 4 USA 48000.00 Page, Mary
114 Bill Parker 247 1993-06-01 00:00:00 623 Eng 5 USA 35000.00 Parker, Bill
118 Takashi Yamamoto 23 1993-07-01 00:00:00 115 SRep 4 Japan 7480000.00 Yamamoto, Takashi
121 Roberto Ferrari 1 1993-07-12 00:00:00 125 SRep 4 Italy 99000000.00 Ferrari, Roberto
127 Michael Yanowski 492 1993-08-09 00:00:00 100 SRep 4 USA 44000.00 Yanowski, Michael
134 Jacques Glon NULL 1993-08-23 00:00:00 123 SRep 4 France 390500.00 Glon, Jacques
136 Scott Johnson 265 1993-09-13 00:00:00 623 Doc 3 USA 60000.00 Johnson, Scott
138 T.J. Green 218 1993-11-01 00:00:00 621 Eng 4 USA 36000.00 Green, T.J.
141 Pierre Osborne NULL 1994-01-03 00:00:00 121 SRep 4 Switzerland 110000.00 Osborne, Pierre
144 John Montgomery 820 1994-03-30 00:00:00 672 Eng 5 USA 35000.00 Montgomery, John
145 Mark Guckenheimer 221 1994-05-02 00:00:00 622 Eng 5 USA 32000.00 Guckenheimer, Mark
DROP TABLE t1;
{"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 @@
"ISBN": "9782840825685",
"LANG": "fr",
"SUBJECT": "applications",
"AUTHOR": [
{
"AUTHOR": {
"FIRSTNAME": "William J.",
"LASTNAME": "Pardi"
}
],
},
"TITLE": "XML en Action",
"TRANSLATION": "adapté de l'anglais par",
"TRANSLATOR": {
......
......@@ -14,3 +14,15 @@ SELECT id, DAYNAME(dat) FROM t1;
SELECT id, DAYNAME(datim) FROM t1 LIMIT 1;
SELECT id, TIME(tim) FROM t1 LIMIT 1;
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;
......@@ -4,6 +4,7 @@
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/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/mulexp3.json $MYSQLD_DATADIR/test/mulexp3.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';
SELECT * FROM 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=350 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 # A file with 2 arrays
--echo #
......@@ -258,6 +286,8 @@ DROP TABLE t1, t2, t3, t4;
# Clean up
#
--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/mulexp3.json
--remove_file $MYSQLD_DATADIR/test/mulexp4.json
......
......@@ -9,28 +9,40 @@ if (!$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")`;
CREATE FUNCTION json_array RETURNS STRING SONAME 'ha_connect';
CREATE FUNCTION json_array_add RETURNS STRING SONAME 'ha_connect';
CREATE FUNCTION json_array_add_values RETURNS STRING SONAME 'ha_connect';
CREATE FUNCTION json_array_delete RETURNS STRING SONAME 'ha_connect';
CREATE FUNCTION json_object RETURNS STRING SONAME 'ha_connect';
CREATE FUNCTION json_object_nonull RETURNS STRING SONAME 'ha_connect';
CREATE FUNCTION json_object_add RETURNS STRING SONAME 'ha_connect';
CREATE FUNCTION json_object_delete RETURNS STRING SONAME 'ha_connect';
CREATE FUNCTION json_object_list RETURNS STRING SONAME 'ha_connect';
CREATE FUNCTION jsonvalue RETURNS STRING SONAME 'ha_connect';
CREATE AGGREGATE FUNCTION json_array_grp RETURNS STRING SONAME 'ha_connect';
CREATE AGGREGATE FUNCTION json_object_grp RETURNS STRING SONAME 'ha_connect';
CREATE FUNCTION json_item_merge RETURNS STRING SONAME 'ha_connect';
CREATE FUNCTION json_get_item RETURNS STRING SONAME 'ha_connect';
CREATE FUNCTION jsonget_string RETURNS STRING SONAME 'ha_connect';
CREATE FUNCTION jsonget_int RETURNS INTEGER SONAME 'ha_connect';
CREATE FUNCTION jsonget_real RETURNS REAL SONAME 'ha_connect';
CREATE FUNCTION jsonlocate RETURNS STRING SONAME 'ha_connect';
CREATE FUNCTION json_locate_all RETURNS STRING SONAME 'ha_connect';
CREATE FUNCTION json_file RETURNS STRING SONAME 'ha_connect';
CREATE FUNCTION jfile_make RETURNS STRING SONAME 'ha_connect';
CREATE FUNCTION json_serialize RETURNS STRING SONAME 'ha_connect';
CREATE FUNCTION jbin_array RETURNS STRING SONAME 'ha_connect';
CREATE FUNCTION jbin_array_add_values RETURNS STRING SONAME 'ha_connect';
CREATE FUNCTION jbin_array_add RETURNS STRING SONAME 'ha_connect';
CREATE FUNCTION jbin_array_delete RETURNS STRING SONAME 'ha_connect';
CREATE FUNCTION jbin_object RETURNS STRING SONAME 'ha_connect';
CREATE FUNCTION jbin_object_nonull RETURNS STRING SONAME 'ha_connect';
CREATE FUNCTION jbin_object_add RETURNS STRING SONAME 'ha_connect';
CREATE FUNCTION jbin_object_delete RETURNS STRING SONAME 'ha_connect';
CREATE FUNCTION jbin_object_list RETURNS STRING SONAME 'ha_connect';
CREATE FUNCTION jbin_get_item RETURNS STRING SONAME 'ha_connect';
CREATE FUNCTION jbin_item_merge RETURNS STRING SONAME 'ha_connect';
CREATE FUNCTION jbin_file RETURNS STRING SONAME 'ha_connect';
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
......@@ -5,35 +5,62 @@ 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/employee.dat $MYSQLD_DATADIR/test/employee.dat
CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=VIR BLOCK_SIZE=5;
--echo #
--echo # Test UDF's with constant arguments
--echo #
--error ER_CANT_INITIALIZE_UDF
SELECT JsonValue(56,3.1416,'foo',NULL);
SELECT JsonValue(3.1416);
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_Object(56,3.1416,'foo',NULL);
SELECT Json_Object(56 qty,3.1416 price,'foo' truc, NULL garanty);
SELECT Json_Array(56,3.1416,'My name is "Foo"',NULL);
SELECT Json_Array(Json_Array(56,3.1416,'foo'),NULL);
--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),'One more') Array;
SELECT Json_Array_Add(Json_Value('one value'),'One more');
--error ER_CANT_INITIALIZE_UDF
SELECT Json_Array_Add(JsonValue('one value'),'One more');
--error ER_CANT_INITIALIZE_UDF
SELECT Json_Array_Add('one value','One more');
SELECT Json_Array_Add('one value' json_,'One more');
--error ER_CANT_INITIALIZE_UDF
SELECT Json_Value(56,3.1416,'foo',NULL);
SELECT Json_Value(3.1416);
SELECT Json_Value('foo');
SELECT Json_Value(NULL);
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_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_Object(56, 3.1416, 'foo', NULL);
SELECT Json_Object(56 qty, 3.1416 price, 'foo' truc, NULL garanty);
SELECT Json_Object();
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_Object(Json_Array(56, 3.1416, 'foo'), NULL);
SELECT Json_Array(Json_Object(56 "qty", 3.1416 "price", 'foo') ,NULL);
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_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 # Test UDF's with column arguments
--echo #
CREATE TABLE t1
CREATE TABLE t2
(
ISBN CHAR(15),
LANG CHAR(2),
......@@ -46,14 +73,13 @@ CREATE TABLE t1
DATEPUB int(4)
) ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='biblio.json';
SELECT Json_Array(AUTHOR, TITLE, DATEPUB) FROM t1;
SELECT Json_Object(AUTHOR, TITLE, DATEPUB) FROM t1;
SELECT Json_Array(AUTHOR, TITLE, DATEPUB) FROM t2;
SELECT Json_Object(AUTHOR, TITLE, DATEPUB) FROM t2;
--error ER_CANT_INITIALIZE_UDF
SELECT Json_Array_Grp(TITLE, DATEPUB) FROM t1;
SELECT Json_Array_Grp(TITLE) FROM t1;
DROP TABLE t1;
SELECT Json_Array_Grp(TITLE, DATEPUB) FROM t2;
SELECT Json_Array_Grp(TITLE) FROM t2;
CREATE TABLE t1 (
CREATE TABLE t3 (
SERIALNO CHAR(5) NOT NULL,
NAME VARCHAR(12) NOT NULL FLAG=6,
SEX SMALLINT(1) NOT NULL,
......@@ -64,30 +90,156 @@ CREATE TABLE t1 (
SALARY DOUBLE(8,2) NOT NULL FLAG=52
) 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 DEPARTMENT, Json_Array_Grp(NAME) FROM t1 GROUP BY DEPARTMENT;
set connect_json_grp_size=30;
SELECT Json_Array(DEPARTMENT, Json_Array_Grp(NAME)) FROM t1 GROUP BY DEPARTMENT;
SELECT Json_Object(DEPARTMENT, Json_Array_Grp(NAME) json_NAMES) FROM t1 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, TITLE, Json_Array_Grp(Json_Object(SERIALNO, NAME, SALARY)) json_EMPLOYES) FROM t1 GROUP BY DEPARTMENT, TITLE;
SELECT Json_Object(SERIALNO, NAME, TITLE, SALARY) FROM t3 WHERE NAME = 'MERCHANT';
SELECT DEPARTMENT, Json_Array_Grp(NAME) FROM t3 GROUP BY DEPARTMENT;
SET connect_json_grp_size=30;
SELECT Json_Array(DEPARTMENT, Json_Array_Grp(NAME)) FROM t3 GROUP BY DEPARTMENT;
SELECT Json_Object(DEPARTMENT, Json_Array_Grp(NAME) json_NAMES) FROM t3 GROUP BY DEPARTMENT;
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
SELECT Json_Object_Grp(SALARY) FROM t1;
SELECT Json_Object_Grp(SALARY, NAME) FROM t1;
SELECT Json_Object(DEPARTMENT, Json_Object_Grp(SALARY, NAME) "Json_SALARIES") FROM t1 GROUP BY DEPARTMENT;
SELECT Json_Array_Grp(NAME) from t1;
DROP TABLE t1;
SELECT Json_Object_Grp(SALARY) FROM t3;
SELECT Json_Object_Grp(SALARY, NAME) FROM t3;
SELECT Json_Object(DEPARTMENT, Json_Object_Grp(SALARY, NAME) "Json_SALARIES") FROM t3 GROUP BY DEPARTMENT;
SELECT Json_Array_Grp(NAME) FROM t3;
--echo #
--echo # Test value getting UDF's
--echo #
SELECT JsonGet_String(Json_Array_Grp(name),'[#]') FROM t3;
SELECT JsonGet_String(Json_Array_Grp(name),'[","]') FROM t3;
SELECT JsonGet_String(Json_Array_Grp(name),'[>]') FROM t3;
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;
DROP FUNCTION Json_Array;
DROP FUNCTION Json_Array_Add;
DROP FUNCTION Json_Object;
DROP FUNCTION Json_Object_Nonull;
DROP FUNCTION Json_Value;
DROP FUNCTION Json_Array_Grp;
DROP FUNCTION Json_Object_Grp;
--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
#
--source json_udf2.inc
--remove_file $MYSQLD_DATADIR/test/biblio.json
--remove_file $MYSQLD_DATADIR/test/employee.dat
--remove_file $MYSQLD_DATADIR/test/fx.json
--disable_query_log
DROP FUNCTION jsonvalue;
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_add;
DROP FUNCTION json_object_delete;
DROP FUNCTION json_object_list;
DROP FUNCTION json_array_grp;
DROP FUNCTION json_object_grp;
DROP FUNCTION json_item_merge;
DROP FUNCTION json_get_item;
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 json_serialize;
DROP FUNCTION jfile_make;
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_add;
DROP FUNCTION jbin_object_delete;
DROP FUNCTION jbin_object_list;
DROP FUNCTION jbin_get_item;
DROP FUNCTION jbin_item_merge;
DROP FUNCTION jbin_file;
--enable_query_log
--source have_odbc.inc
SET NAMES utf8;
# MS ODBC and unixODBC return different error message text,
# so disable displaying error messages
#--disable_result_log ONCE
--error ER_UNKNOWN_ERROR
CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CONNECTION='Bad connection string';
CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CATFUNC=Sources;
SHOW CREATE TABLE t1;
SELECT * FROM t1;
DROP TABLE t1;
CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CATFUNC=Drivers;
SHOW CREATE TABLE t1;
SELECT * FROM t1;
DROP TABLE t1;
CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CATFUNC=Tables CONNECTION='Not important';
SHOW CREATE TABLE t1;
DROP TABLE t1;
CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CATFUNC=Columns CONNECTION='Not important';
SHOW CREATE TABLE t1;
DROP TABLE t1;
CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC TABNAME='EMPLOYEE' CONNECTION='DSN=Firebird;UID=SYSDBA;PWD=manager';
SELECT * FROM t1;
DROP TABLE t1;
/***********************************************************************/
/* (C) Copyright to the author Olivier BERTRAND 2015 */
/***********************************************************************/
#include <my_global.h>
#include <mysqld.h>
#include <string.h>
#if defined(__WIN__)
#define DllExport __declspec( dllexport )
#else // !__WIN__
#define DllExport
#endif // !__WIN__
extern "C" {
DllExport my_bool noconst_init(UDF_INIT*, UDF_ARGS*, char*);
DllExport char *noconst(UDF_INIT*, UDF_ARGS*, char*, unsigned long*, char*, char*);
} // extern "C"
/***********************************************************************/
/* Returns its argument saying it is not a constant. */
/***********************************************************************/
my_bool noconst_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
{
if (args->arg_count != 1 || args->arg_type[0] != STRING_RESULT) {
strcpy(message, "noconst unique argument must be a string");
return true;
} // endif arg
initid->const_item = false; // The trick!
return false;
} // end of noconst_init
char *noconst(UDF_INIT *initid, UDF_ARGS *args, char *result,
unsigned long *res_length, char *, char *)
{
return args->args[0];
} // end of noconst
......@@ -143,7 +143,7 @@ PGLOBAL PlugInit(LPCSTR Language, uint worksize)
fprintf(stderr, MSG(GLOBAL_ERROR), (int)sizeof(GLOBAL));
return NULL;
} else {
g->Sarea_Size = worksize;
g->Sarea = NULL;
g->Createas = 0;
g->Alchecked = 0;
g->Mrr = 0;
......@@ -155,7 +155,7 @@ PGLOBAL PlugInit(LPCSTR Language, uint worksize)
/*******************************************************************/
/* Allocate the main work segment. */
/*******************************************************************/
if (!(g->Sarea = PlugAllocMem(g, worksize))) {
if (worksize && !(g->Sarea = PlugAllocMem(g, worksize))) {
char errmsg[256];
sprintf(errmsg, MSG(WORK_AREA), g->Message);
strcpy(g->Message, errmsg);
......
......@@ -57,6 +57,7 @@ extern handlerton *connect_hton;
/* External function. */
/***********************************************************************/
USETEMP UseTemp(void);
char *GetPluginDir(void);
/* --------------------------- Class RELDEF -------------------------- */
......
......@@ -2204,7 +2204,7 @@ bool TDBDOS::PrepareWriting(PGLOBAL)
} // endif Mode
return false;
} // end of WriteDB
} // end of PrepareWriting
/***********************************************************************/
/* WriteDB: Data Base write routine for DOS access method. */
......@@ -2216,7 +2216,7 @@ int TDBDOS::WriteDB(PGLOBAL g)
// Make the line to write
if (PrepareWriting(g))
return true;
return RC_FX;
if (trace > 1)
htrc("Write: line is='%s'\n", To_Line);
......
......@@ -659,7 +659,7 @@ int TDBJSN::ReadDB(PGLOBAL g)
if (!IsRead() && ((rc = ReadBuffer(g)) != RC_OK)) {
// Deferred reading failed
} else if (!(Row = ParseJson(g, To_Line,
strlen(To_Line), Pretty, &Comma))) {
strlen(To_Line), &Pretty, &Comma))) {
rc = (Pretty == 1 && !strcmp(To_Line, "]")) ? RC_EF : RC_FX;
} else {
Row = FindRow(g);
......@@ -755,7 +755,6 @@ int TDBJSN::MakeTopTree(PGLOBAL g, PJSON jsp)
} else
strcpy(To_Line, s);
// Row->Clear();
return false;
} else
return true;
......@@ -1046,6 +1045,7 @@ void JSONCOL::SetJsonValue(PGLOBAL g, PVAL vp, PJVAL val, int n)
switch (val->GetValType()) {
case TYPE_STRG:
case TYPE_INTG:
case TYPE_BINT:
case TYPE_DBL:
vp->SetValue_pval(val->GetValue());
break;
......@@ -1384,7 +1384,7 @@ void JSONCOL::WriteColumn(PGLOBAL g)
if (Nodes[Nod-1].Op == OP_XX) {
s = Value->GetCharValue();
if (!(jsp = ParseJson(g, s, (int)strlen(s), 0))) {
if (!(jsp = ParseJson(g, s, (int)strlen(s)))) {
strcpy(g->Message, s);
longjmp(g->jumper[g->jump_level], 666);
} // endif jsp
......@@ -1522,7 +1522,7 @@ int TDBJSON::MakeDocument(PGLOBAL g)
/* Parse the json file and allocate its tree structure. */
/*********************************************************************/
g->Message[0] = 0;
jsp = Top = ParseJson(g, memory, len, Pretty);
jsp = Top = ParseJson(g, memory, len, &Pretty);
Txfp->CloseTableFile(g, false);
Mode = mode; // Restore saved Mode
......@@ -1540,7 +1540,7 @@ int TDBJSON::MakeDocument(PGLOBAL g)
if (*objpath != '[') { // objpass is a key
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;
} // endif Type
......@@ -1556,7 +1556,7 @@ int TDBJSON::MakeDocument(PGLOBAL g)
} else if (objpath[strlen(objpath)-1] == ']') {
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;
} // endif Type
......@@ -1837,7 +1837,6 @@ void TDBJSON::CloseDB(PGLOBAL g)
// Save the modified document
char filename[_MAX_PATH];
PSZ msg;
FILE *fop;
Doc->InitArray(g);
......@@ -1845,11 +1844,7 @@ void TDBJSON::CloseDB(PGLOBAL g)
PlugSetPath(filename, ((PJDEF)To_Def)->Fn, GetPath());
// Serialize the modified table
if (!(fop = fopen(filename, "wb"))) {
sprintf(g->Message, MSG(OPEN_MODE_ERROR),
"w", (int)errno, filename);
strcat(strcat(g->Message, ": "), strerror(errno));
} else if ((msg = Serialize(g, Top, fop, Pretty)))
if ((msg = Serialize(g, Top, filename, Pretty)))
puts(msg);
} // end of CloseDB
......
......@@ -1054,32 +1054,14 @@ int TDBMYSQL::SendCommand(PGLOBAL g)
/***********************************************************************/
/* 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();
PHC hc = To_Def->GetHandler();
if (op == OP_FIRST && hc->end_range) {
#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 ||
if (!(kr || hc->end_range) || op == OP_NEXT ||
Mode == MODE_UPDATE || Mode == MODE_DELETE) {
if (!key && Mode == MODE_READX) {
if (!kr && Mode == MODE_READX) {
// This is a false indexed read
m_Rc = Myc.ExecSQL(g, Query->GetStr());
Mode = MODE_READ;
......@@ -1091,22 +1073,34 @@ bool TDBMYSQL::ReadKey(PGLOBAL g, OPVAL op, const void *key, int len)
if (Myc.m_Res)
Myc.FreeResult();
if (hc->MakeKeyWhere(g, Query, op, '`', key, len))
if (hc->MakeKeyWhere(g, Query, op, '`', kr))
return true;
if (To_CondFil) {
oom = Query->Append(" AND (");
oom |= Query->Append(To_CondFil->Body);
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);
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");
return true;
} // endif oom
} // endif Append
} // endif To_Condfil
Mode = MODE_READ;
} // endif's op
if (trace)
htrc("MYSQL ReadKey: Query=%s\n", Query->GetStr());
m_Rc = Myc.ExecSQL(g, Query->GetStr());
Query->Truncate(oldlen);
return (m_Rc == RC_FX) ? true : false;
......
......@@ -99,7 +99,7 @@ class TDBMYSQL : public TDBASE {
virtual int WriteDB(PGLOBAL g);
virtual int DeleteDB(PGLOBAL g, int irc);
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
bool SetColumnRanks(PGLOBAL g);
......
/************* Tabodbc C++ Program Source Code File (.CPP) *************/
/* PROGRAM NAME: TABODBC */
/* ------------- */
/* Version 2.9 */
/* Version 3.0 */
/* */
/* COPYRIGHT: */
/* ---------- */
......@@ -35,6 +35,7 @@
/* Include relevant MariaDB header file. */
/***********************************************************************/
#include "my_global.h"
#include "sql_class.h"
#if defined(__WIN__)
#include <io.h>
#include <fcntl.h>
......@@ -72,6 +73,7 @@
#include "reldef.h"
#include "tabcol.h"
#include "valblk.h"
#include "ha_connect.h"
#include "sql_string.h"
......@@ -397,176 +399,209 @@ int TDBODBC::Decode(char *txt, char *buf, size_t n)
/* Note: when implementing EOM filtering, column only used in local */
/* 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];
LPCSTR schmp = NULL, catp = NULL;
int len, ncol = 0;
bool first = true;
char *schmp = NULL, *catp = NULL, buf[NAM_LEN * 3];
int len;
bool oom = false, first = true;
PTABLE tablep = To_Table;
PCOL colp;
if (Srcdef)
return Srcdef;
if (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 (Columns) {
// 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())
if (!colp->IsSpecial()) {
// Column name can be in UTF-8 encoding
/*rc=*/ Decode(colp->GetName(), buf, sizeof(buf));
if (Quote) {
if (first) {
strcat(strcat(strcpy(colist, Quote), buf), Quote);
if (!first)
oom |= Query->Append(", ");
else
first = false;
} else
strcat(strcat(strcat(strcat(colist, ", "),
Quote), buf), Quote);
} else {
if (first) {
strcpy(colist, buf);
first = false;
} else
strcat(strcat(colist, ", "), buf);
// Column name can be encoded in UTF-8
Decode(colp->GetName(), buf, sizeof(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 {
// ncol == 0 can occur for queries such that sql count(*) from...
} else
// !Columns can occur for queries such that sql count(*) from...
// for which we will count the rows from sql * from...
colist = (char*)PlugSubAlloc(g, NULL, 2);
strcpy(colist, "*");
} // endif ncol
oom |= Query->Append('*');
} else {
} else
// SQL statement used to retrieve the size of the result
colist = (char*)PlugSubAlloc(g, NULL, 9);
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);
oom |= Query->Append("count(*)");
// Below 14 is length of 'select ' + length of ' from ' + 1
len = (strlen(colist) + strlen(buf) + 14);
len += (To_CondFil ? strlen(To_CondFil->Body) + 7 : 0);
oom |= Query->Append(" FROM ");
if (Catalog && *Catalog)
catp = Catalog;
if (catp)
len += (strlen(catp) + 2);
if (tablep->GetSchema())
schmp = tablep->GetSchema();
schmp = (char*)tablep->GetSchema();
else if (Schema && *Schema)
schmp = Schema;
if (schmp)
len += (strlen(schmp) + 1);
if (catp) {
oom |= Query->Append(catp);
sql = (char*)PlugSubAlloc(g, NULL, len);
strcat(strcat(strcpy(sql, "SELECT "), colist), " FROM ");
if (schmp) {
oom |= Query->Append('.');
oom |= Query->Append(schmp);
} // endif schmp
if (catp) {
strcat(sql, catp);
oom |= Query->Append('.');
} else if (schmp) {
oom |= Query->Append(schmp);
oom |= Query->Append('.');
} // endif schmp
if (schmp)
strcat(strcat(sql, "."), schmp);
else
strcat(sql, ".");
// Table name can be encoded in UTF-8
Decode(TableName, buf, sizeof(buf));
strcat(sql, ".");
} else if (schmp)
strcat(strcat(sql, 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
oom |= Query->Append(buf);
strcat(sql, tabname);
len = Query->GetLength();
if (To_CondFil)
strcat(strcat(sql, " WHERE "), To_CondFil->Body);
if (To_CondFil) {
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)
htrc("sql: '%s'\n", sql);
htrc("Query=%s\n", Query->GetStr());
return sql;
return false;
} // end of MakeSQL
/***********************************************************************/
/* 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 *tk = "`";
char *schmp = NULL, *catp = NULL, buf[NAM_LEN * 3];
int len = 0;
bool b = FALSE;
bool b = false, oom = false;
PTABLE tablep = To_Table;
PCOL colp;
for (colp = Columns; colp; colp = colp->GetNext())
if (colp->IsSpecial()) {
strcpy(g->Message, MSG(NO_ODBC_SPECOL));
return NULL;
return true;
} 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;
} // endif colp
colist = (char*)PlugSubAlloc(g, NULL, len);
*colist = '\0';
valist = (char*)PlugSubAlloc(g, NULL, 2 * Nparm);
*valist = '\0';
// Below 32 is enough to contain the fixed part of the query
if (Catalog && *Catalog)
catp = Catalog;
for (colp = Columns; colp; colp = colp->GetNext()) {
if (b) {
strcat(colist, ", ");
strcat(valist, ",");
if (catp)
len += strlen(catp) + 1;
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
oom |= Query->Append(buf);
oom |= Query->Append('(');
for (colp = Columns; colp; colp = colp->GetNext()) {
if (b)
oom |= Query->Append(", ");
else
b = true;
// Column name can be in UTF-8 encoding
Decode(colp->GetName(), buf, sizeof(buf));
if (Quote)
strcat(strcat(strcat(colist, Quote), buf), Quote);
else
strcat(colist, buf);
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);
strcat(valist, "?"); // Parameter marker
} // endfor colp
// Below 32 is enough to contain the fixed part of the query
len = (strlen(TableName) + strlen(colist) + strlen(valist) + 32);
stmt = (char*)PlugSubAlloc(g, NULL, len);
strcpy(stmt, "INSERT INTO ");
oom |= Query->Append(") VALUES (");
if (Quote)
strcat(strcat(strcat(stmt, Quote), TableName), Quote);
else
strcat(stmt, TableName);
for (int i = 0; i < Nparm; i++)
oom |= Query->Append("?,");
strcat(strcat(strcat(stmt, " ("), colist), ") VALUES (");
strcat(strcat(stmt, valist), ")");
if (oom)
strcpy(g->Message, "MakeInsert: Out of memory");
else
Query->RepLast(')');
return stmt;
return oom;
} // end of MakeInsert
/***********************************************************************/
......@@ -591,7 +626,7 @@ bool TDBODBC::BindParameters(PGLOBAL g)
/* MakeCommand: make the Update or Delete statement to send to the */
/* 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 *qrystr = (char*)PlugSubAlloc(g, NULL, strlen(Qrystr) + 1);
......@@ -649,7 +684,8 @@ char *TDBODBC::MakeCommand(PGLOBAL g)
return NULL;
} // endif p
return stmt;
Query = new(g) STRING(g, 0, stmt);
return (!Query->GetSize());
} // end of MakeCommand
#if 0
......@@ -826,10 +862,12 @@ bool TDBODBC::OpenDB(PGLOBAL g)
if (Memory < 3) {
// 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();
return true;
} // endif Rewind
} else
Rbuf = 0;
} else
Rbuf = Qrp->Nblin;
......@@ -864,15 +902,14 @@ bool TDBODBC::OpenDB(PGLOBAL g)
/*********************************************************************/
if (Mode == MODE_READ || Mode == MODE_READX) {
if (Memory > 1 && !Srcdef) {
char *Sql;
int n;
if ((Sql = MakeSQL(g, true))) {
if (!MakeSQL(g, true)) {
// Allocate a Count(*) column
Cnp = new(g) ODBCCOL;
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");
return true;
} // endif n
......@@ -882,36 +919,36 @@ bool TDBODBC::OpenDB(PGLOBAL g)
if ((Qrp = Ocp->AllocateResult(g)))
Memory = 2; // Must be filled
else {
strcpy(g->Message, "Memory allocation failed");
strcpy(g->Message, "Result set memory allocation failed");
return true;
} // endif n
Ocp->m_Rows = 0;
} else {
strcpy(g->Message, "MakeSQL failed");
} else
return true;
} // endif Sql
} // endif Memory
if ((Query = MakeSQL(g, false))) {
if (!(rc = MakeSQL(g, false))) {
for (PODBCCOL colp = (PODBCCOL)Columns; colp;
colp = (PODBCCOL)colp->GetNext())
if (!colp->IsSpecial())
colp->AllocateBuffers(g, Rows);
rc = ((Rows = Ocp->ExecDirectSQL(Query, (PODBCCOL)Columns)) < 0);
} // endif Query
rc = (Mode == MODE_READ)
? ((Rows = Ocp->ExecDirectSQL(Query->GetStr(), (PODBCCOL)Columns)) < 0)
: false;
} // endif rc
} else if (Mode == MODE_INSERT) {
if ((Query = MakeInsert(g))) {
if (Nparm != Ocp->PrepareSQL(Query)) {
if (!(rc = MakeInsert(g))) {
if (Nparm != Ocp->PrepareSQL(Query->GetStr())) {
strcpy(g->Message, MSG(PARM_CNT_MISS));
rc = true;
} else
rc = BindParameters(g);
} // endif Query
} // endif rc
} else if (Mode == MODE_UPDATE || Mode == MODE_DELETE) {
rc = false; // wait for CheckCond before calling MakeCommand(g);
......@@ -969,6 +1006,59 @@ bool TDBODBC::SetRecpos(PGLOBAL g, int recpos)
return false;
} // 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. */
/***********************************************************************/
......@@ -981,11 +1071,11 @@ int TDBODBC::ReadDB(PGLOBAL g)
GetTdb_No(), Mode, To_Key_Col, To_Link, To_Kindex);
if (Mode == MODE_UPDATE || Mode == MODE_DELETE) {
if (!Query && !(Query = MakeCommand(g)))
if (!Query && MakeCommand(g))
return RC_FX;
// 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);
if (trace)
......@@ -1063,11 +1153,11 @@ int TDBODBC::WriteDB(PGLOBAL g)
int TDBODBC::DeleteDB(PGLOBAL g, int irc)
{
if (irc == RC_FX) {
if (!Query && !(Query = MakeCommand(g)))
if (!Query && MakeCommand(g))
return RC_FX;
// 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);
if (trace)
......@@ -1279,12 +1369,7 @@ void ODBCCOL::ReadColumn(PGLOBAL g)
} // endif Buf_Type
// Nulls are handled by StrLen[n] == SQL_NULL_DATA
// MDEV-8561
//if (Value->IsZero())
// Value->SetNull(Nullable);
if (trace) {
if (trace > 1) {
char buf[64];
htrc("ODBC Column %s: rows=%d buf=%p type=%d value=%s\n",
......@@ -1572,9 +1657,12 @@ bool TDBXDBC::OpenDB(PGLOBAL g)
int TDBXDBC::ReadDB(PGLOBAL g)
{
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++;
Fpos++; // Used for progress info
......@@ -1632,7 +1720,7 @@ void XSRCCOL::ReadColumn(PGLOBAL g)
PTDBXDBC tdbp = (PTDBXDBC)To_Tdb;
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 2: Value->SetValue_psz(g->Message); break;
default: Value->SetValue_psz("Invalid Flag"); break;
......
......@@ -42,6 +42,7 @@ class DllExport ODBCDEF : public TABDEF { /* Logical table description */
int GetOptions(void) {return Options;}
// Methods
virtual int Indexable(void) {return 2;}
virtual bool DefineAM(PGLOBAL g, LPCSTR am, int poff);
virtual PTDB GetTable(PGLOBAL g, MODE m);
......@@ -111,15 +112,14 @@ class TDBODBC : public TDBASE {
virtual int WriteDB(PGLOBAL g);
virtual int DeleteDB(PGLOBAL g, int irc);
virtual void CloseDB(PGLOBAL g);
virtual bool ReadKey(PGLOBAL g, OPVAL op, const void *key, int len)
{return true;}
virtual bool ReadKey(PGLOBAL g, OPVAL op, const key_range *kr);
protected:
// Internal functions
int Decode(char *utf, char *buf, size_t n);
char *MakeSQL(PGLOBAL g, bool cnt);
char *MakeInsert(PGLOBAL g);
char *MakeCommand(PGLOBAL g);
bool MakeSQL(PGLOBAL g, bool cnt);
bool MakeInsert(PGLOBAL g);
bool MakeCommand(PGLOBAL g);
//bool MakeFilter(PGLOBAL g, bool c);
bool BindParameters(PGLOBAL g);
//char *MakeUpdate(PGLOBAL g);
......@@ -129,6 +129,7 @@ class TDBODBC : public TDBASE {
ODBConn *Ocp; // Points to an ODBC connection class
ODBCCOL *Cnp; // Points to count(*) column
ODBCPARM Ops; // Additional parameters
PSTRG Query; // Constructed SQL query
char *Connect; // Points to connection string
char *TableName; // Points to ODBC table name
char *Schema; // Points to ODBC table Schema
......@@ -136,7 +137,6 @@ class TDBODBC : public TDBASE {
char *Pwd; // Password connect info
char *Catalog; // Points to ODBC table Catalog
char *Srcdef; // The source table SQL definition
char *Query; // Points to SQL statement
char *Count; // Points to count(*) SQL statement
//char *Where; // Points to local where clause
char *Quote; // The identifier quoting character
......
......@@ -60,6 +60,7 @@ extern "C" char version[];
#endif // !__WIN__
#define TYPE_UNKNOWN 12 /* Must be greater than other types */
#define XSTR(M) sizeof(M) - strlen(M) - 1 /* To avoid overflow*/
/***********************************************************************/
/* Class and structure used by XMLColumns. */
......@@ -225,30 +226,30 @@ PQRYRES XMLColumns(PGLOBAL g, char *db, char *tab, PTOS topt, bool info)
more:
if (vp->atp) {
strncpy(colname, vp->atp->GetName(g), sizeof(colname));
strncat(xcol->Name, colname, 64);
strncat(xcol->Name, colname, XSTR(xcol->Name));
switch (vp->atp->GetText(g, buf, sizeof(buf))) {
case RC_INFO:
PushWarning(g, txmp);
case RC_OK:
strncat(fmt, "@", sizeof(fmt));
strncat(fmt, "@", XSTR(fmt));
break;
default:
goto err;
} // enswitch rc
if (j)
strncat(fmt, colname, sizeof(fmt));
strncat(fmt, colname, XSTR(fmt));
} else {
if (tdp->Usedom && node->GetType() != 1)
continue;
strncpy(colname, node->GetName(g), sizeof(colname));
strncat(xcol->Name, colname, 64);
strncat(xcol->Name, colname, XSTR(xcol->Name));
if (j)
strncat(fmt, colname, sizeof(fmt));
strncat(fmt, colname, XSTR(fmt));
if (j < lvl && ok) {
vp = lvlp[j+1];
......@@ -266,8 +267,9 @@ PQRYRES XMLColumns(PGLOBAL g, char *db, char *tab, PTOS topt, bool info)
if (!vp->atp)
node = vp->nl->GetItem(g, vp->k++, node);
strncat(strncat(fmt, colname, 125), "/", 125);
strncat(xcol->Name, "_", 64);
strncat(fmt, colname, XSTR(fmt));
strncat(fmt, "/", XSTR(fmt));
strncat(xcol->Name, "_", XSTR(xcol->Name));
j++;
vp->n = (int)strlen(xcol->Name);
vp->m = (int)strlen(fmt);
......
......@@ -340,7 +340,7 @@ PVAL AllocateValue(PGLOBAL g, void *value, short type, short prec)
switch (type) {
case TYPE_STRING:
valp = new(g) TYPVAL<PSZ>((PSZ)value);
valp = new(g) TYPVAL<PSZ>((PSZ)value, prec);
break;
case 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)
/***********************************************************************/
/* 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;
Len = strlen(s);
Clen = Len;
Ci = false;
Ci = (c == 1);
} // end of STRING constructor
/***********************************************************************/
......@@ -2440,6 +2440,7 @@ void DTVAL::SetTimeShift(void)
} // end of SetTimeShift
#if defined(connect_EXPORTS)
// Added by Alexander Barkov
static void TIME_to_localtime(struct tm *tm, const MYSQL_TIME *ltime)
{
......@@ -2461,6 +2462,9 @@ static struct tm *gmtime_mysql(const time_t *timep, struct tm *tm)
TIME_to_localtime(tm, &ltime);
return tm;
} // end of gmtime_mysql
#else
#define gmtime_mysql(T,B) gmtime((const time_t *)T)
#endif
/***********************************************************************/
/* GetGmTime: returns a pointer to a static tm structure obtained */
......@@ -2489,6 +2493,7 @@ struct tm *DTVAL::GetGmTime(struct tm *tm_buffer)
return datm;
} // end of GetGmTime
#if defined(connect_EXPORTS)
// Added by Alexander Barkov
static time_t mktime_mysql(struct tm *ptm)
{
......@@ -2499,6 +2504,9 @@ static time_t mktime_mysql(struct tm *ptm)
time_t t= TIME_to_timestamp(current_thd, &ltime, &error_code);
return error_code ? (time_t) -1 : t;
}
#else
#define mktime_mysql mktime
#endif
/***********************************************************************/
/* MakeTime: calculates a date value from a tm structures using the */
......
......@@ -236,7 +236,7 @@ template <>
class DllExport TYPVAL<PSZ>: public VALUE {
public:
// Constructors
TYPVAL(PSZ s);
TYPVAL(PSZ s, short c = 0);
TYPVAL(PGLOBAL g, PSZ s, int n, int c);
// Implementation
......
......@@ -293,12 +293,12 @@ bool STRING::Set(char *s, uint n)
/***********************************************************************/
/* 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)
return false;
uint len = Length + ln + 1;
uint i, len = Length + ln + 1;
if (len > Size) {
char *p = Realloc(len);
......@@ -312,8 +312,22 @@ bool STRING::Append(const char *s, uint ln)
} // endif n
strncpy(Strp + Length, s, ln);
Length = len - 1;
if (nq) {
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;
return false;
} // end of Append
......
......@@ -134,7 +134,7 @@ class DllExport STRING : public BLOCK {
inline void Reset(void) {*Strp = 0;}
bool Set(PSZ s);
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(STRING &str);
bool Append(char c);
......
......@@ -19,6 +19,7 @@
#include "m_ctype.h"
typedef class CMD *PCMD;
typedef struct st_key_range key_range;
// Commands executed by XDBC and MYX tables
class CMD : public BLOCK {
......@@ -32,12 +33,24 @@ class CMD : public BLOCK {
}; // end of class CMD
// 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;
OPVAL Op;
PCMD Cmds;
} CONDFIL, *PCFIL;
}; // end of class CONDFIL
typedef class CONDFIL *PCFIL;
typedef class TDBCAT *PTDBCAT;
typedef class CATCOL *PCATCOL;
......@@ -109,7 +122,7 @@ class DllExport TDB: public BLOCK { // Table Descriptor Block.
virtual int DeleteDB(PGLOBAL, int) = 0;
virtual void CloseDB(PGLOBAL) = 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:
// Members
......@@ -188,7 +201,7 @@ class DllExport TDBASE : public TDB {
virtual void MarkDB(PGLOBAL g, PTDB tdb2);
virtual int MakeIndex(PGLOBAL g, PIXDEF, bool)
{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;}
protected:
......
......@@ -112,6 +112,7 @@ UNIV_INTERN ulint os_innodb_umask = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP;
#else
/** Umask for creating files */
UNIV_INTERN ulint os_innodb_umask = 0;
#define ECANCELED 125
#endif /* __WIN__ */
#ifndef UNIV_HOTBACKUP
......
......@@ -117,6 +117,7 @@ UNIV_INTERN ulint os_innodb_umask = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP;
#else
/** Umask for creating files */
UNIV_INTERN ulint os_innodb_umask = 0;
#define ECANCELED 125
#endif /* __WIN__ */
#ifndef UNIV_HOTBACKUP
......
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