Commit ceacffbb authored by Olivier Bertrand's avatar Olivier Bertrand

- Fix pretty=2 Tabjson bug on INSERT.

  Occuring when inserting more than one line in one statement.
  modified:   storage/connect/json.cpp

- Fix a wrong if statement
  modified:   storage/connect/tabjson.cpp

- Continue BSON implementation
  modified:   storage/connect/bson.cpp
  modified:   storage/connect/bson.h
  modified:   storage/connect/filamtxt.cpp
  modified:   storage/connect/filamtxt.h
  modified:   storage/connect/tabbson.cpp
  modified:   storage/connect/tabbson.h

- No need anymore
  deleted:    storage/connect/mysql-test/connect/r/bson.result
  deleted:    storage/connect/mysql-test/connect/t/bson.test
parent aa10789f
......@@ -872,7 +872,18 @@ void BJSON::SubSet(bool b)
} // end of SubSet
/* ------------------------ Bobject functions ------------------------ */
/*********************************************************************************/
/* Set the beginning of suballocations. */
/*********************************************************************************/
void BJSON::MemSet(size_t size)
{
PPOOLHEADER pph = (PPOOLHEADER)G->Sarea;
pph->To_Free = size + sizeof(POOLHEADER);
pph->FreeBlk = G->Sarea_Size - pph->To_Free;
} // end of MemSet
/* ------------------------ Bobject functions ------------------------ */
/***********************************************************************/
/* Sub-allocate and initialize a BPAIR. */
......@@ -1187,18 +1198,17 @@ void BJSON::MergeArray(PBVAL bap1, PBVAL bap2)
void BJSON::SetArrayValue(PBVAL bap, PBVAL nvp, int n)
{
CheckType(bap, TYPE_JAR);
int i = 0;
PBVAL bvp = NULL, pvp = NULL;
if (bap->To_Val) {
for (int i = 0; bvp = GetArray(bap); i++, bvp = GetNext(bvp))
if (bap->To_Val)
for (bvp = GetArray(bap); bvp; i++, bvp = GetNext(bvp))
if (i == n) {
SetValueVal(bvp, nvp);
return;
} else
pvp = bvp;
} // endif bap
if (!bvp)
AddArrayValue(bap, MOF(nvp));
......@@ -1264,7 +1274,8 @@ void BJSON::DeleteValue(PBVAL bap, int n)
bap->Nd--;
break;
} // endif i
} else
pvp = bvp;
} // end of DeleteValue
......@@ -1587,17 +1598,17 @@ PBVAL BJSON::SetValue(PBVAL vlp, PVAL valp)
} else switch (valp->GetType()) {
case TYPE_DATE:
if (((DTVAL*)valp)->IsFormatted())
vlp->To_Val = MOF(PlugDup(G, valp->GetCharValue()));
vlp->To_Val = DupStr(valp->GetCharValue());
else {
char buf[32];
vlp->To_Val = MOF(PlugDup(G, valp->GetCharString(buf)));
vlp->To_Val = DupStr(valp->GetCharString(buf));
} // endif Formatted
vlp->Type = TYPE_DTM;
break;
case TYPE_STRING:
vlp->To_Val = MOF(PlugDup(G, valp->GetCharValue()));
vlp->To_Val = DupStr(valp->GetCharValue());
vlp->Type = TYPE_STRG;
break;
case TYPE_DOUBLE:
......@@ -1608,7 +1619,7 @@ PBVAL BJSON::SetValue(PBVAL vlp, PVAL valp)
vlp->F = (float)valp->GetFloatValue();
vlp->Type = TYPE_FLOAT;
} else {
double *dp = (double*)PlugSubAlloc(G, NULL, sizeof(double));
double *dp = (double*)BsonSubAlloc(sizeof(double));
*dp = valp->GetFloatValue();
vlp->To_Val = MOF(dp);
......@@ -1629,7 +1640,7 @@ PBVAL BJSON::SetValue(PBVAL vlp, PVAL valp)
vlp->N = valp->GetIntValue();
vlp->Type = TYPE_INTG;
} else {
longlong* llp = (longlong*)PlugSubAlloc(G, NULL, sizeof(longlong));
longlong* llp = (longlong*)BsonSubAlloc(sizeof(longlong));
*llp = valp->GetBigintValue();
vlp->To_Val = MOF(llp);
......
......@@ -76,6 +76,7 @@ class BJSON : public BLOCK {
void* GetBase(void) { return Base; }
void SubSet(bool b = false);
void MemSave(void) {G->Saved_Size = ((PPOOLHEADER)G->Sarea)->To_Free;}
void MemSet(size_t size);
void GetMsg(PGLOBAL g) { if (g != G) strcpy(g->Message, G->Message); }
// SubAlloc functions
......
......@@ -805,8 +805,8 @@ int DOSFAM::ReadBuffer(PGLOBAL g)
Placed = false;
if (trace(2))
htrc(" About to read: stream=%p To_Buf=%p Buflen=%d\n",
Stream, To_Buf, Buflen);
htrc(" About to read: stream=%p To_Buf=%p Buflen=%d Fpos=%d\n",
Stream, To_Buf, Buflen, Fpos);
if (fgets(To_Buf, Buflen, Stream)) {
p = To_Buf + strlen(To_Buf) - 1;
......@@ -1665,6 +1665,7 @@ void BLKFAM::Rewind(void)
/* --------------------------- Class BINFAM -------------------------- */
#if 0
/***********************************************************************/
/* BIN GetFileLength: returns file size in number of bytes. */
/***********************************************************************/
......@@ -1692,7 +1693,6 @@ int BINFAM::Cardinality(PGLOBAL g)
return (g) ? -1 : 0;
} // end of Cardinality
#if 0
/***********************************************************************/
/* OpenTableFile: Open a DOS/UNIX table file using C standard I/Os. */
/***********************************************************************/
......@@ -1742,16 +1742,34 @@ bool BINFAM::OpenTableFile(PGLOBAL g) {
/***********************************************************************/
bool BINFAM::AllocateBuffer(PGLOBAL g)
{
MODE mode = Tdbp->GetMode();
MODE mode = Tdbp->GetMode();
// Lrecl is Ok
Buflen = Lrecl;
// Lrecl is Ok
Buflen = Lrecl;
if (trace(1))
htrc("SubAllocating a buffer of %d bytes\n", Buflen);
// Buffer will be allocated separately
if (mode == MODE_ANY) {
xtrc(1, "SubAllocating a buffer of %d bytes\n", Buflen);
To_Buf = (char*)PlugSubAlloc(g, NULL, Buflen);
} else if (UseTemp || mode == MODE_DELETE) {
// Have a big buffer to move lines
Dbflen = Buflen * DOS_BUFF_LEN;
DelBuf = PlugSubAlloc(g, NULL, Dbflen);
} // endif mode
To_Buf = (char*)PlugSubAlloc(g, NULL, Buflen);
return false;
return false;
#if 0
MODE mode = Tdbp->GetMode();
// Lrecl is Ok
Dbflen = Buflen = Lrecl;
if (trace(1))
htrc("SubAllocating a buffer of %d bytes\n", Buflen);
DelBuf = To_Buf = (char*)PlugSubAlloc(g, NULL, Buflen);
return false;
#endif // 0
} // end of AllocateBuffer
#if 0
......@@ -1830,8 +1848,8 @@ int BINFAM::ReadBuffer(PGLOBAL g)
} else
Placed = false;
xtrc(2, " About to read: bstream=%p To_Buf=%p Buflen=%d\n",
Stream, To_Buf, Buflen);
xtrc(2, " About to read: bstream=%p To_Buf=%p Buflen=%d Fpos=%d\n",
Stream, To_Buf, Buflen, Fpos);
// Read the prefix giving the row length
if (!fread(&Recsize, sizeof(size_t), 1, Stream)) {
......@@ -1848,7 +1866,6 @@ int BINFAM::ReadBuffer(PGLOBAL g)
if (fread(To_Buf, Recsize, 1, Stream)) {
xtrc(2, " Read: To_Buf=%p Recsize=%zd\n", To_Buf, Recsize);
// memcpy(Tdbp->GetLine(), To_Buf, Recsize);
num_read++;
rc = RC_OK;
} else if (feof(Stream)) {
......@@ -1876,7 +1893,51 @@ int BINFAM::WriteBuffer(PGLOBAL g)
int curpos = 0;
bool moved = true;
/*********************************************************************/
// T_Stream is the temporary stream or the table file stream itself
if (!T_Stream) {
if (UseTemp && Tdbp->GetMode() == MODE_UPDATE) {
if (OpenTempFile(g))
return RC_FX;
} else
T_Stream = Stream;
} // endif T_Stream
if (Tdbp->GetMode() == MODE_UPDATE) {
/*******************************************************************/
/* Here we simply rewrite a record on itself. There are two cases */
/* were another method should be used, a/ when Update apply to */
/* the whole file, b/ when updating the last field of a variable */
/* length file. The method could be to rewrite a new file, then */
/* to erase the old one and rename the new updated file. */
/*******************************************************************/
curpos = ftell(Stream);
if (trace(1))
htrc("Last : %d cur: %d\n", Fpos, curpos);
if (UseTemp) {
/*****************************************************************/
/* We are using a temporary file. */
/* Before writing the updated record, we must eventually copy */
/* all the intermediate records that have not been updated. */
/*****************************************************************/
if (MoveIntermediateLines(g, &moved))
return RC_FX;
Spos = curpos; // New start position
} else
// Update is directly written back into the file,
// with this (fast) method, record size cannot change.
if (fseek(Stream, Fpos, SEEK_SET)) {
sprintf(g->Message, MSG(FSETPOS_ERROR), 0);
return RC_FX;
} // endif
} // endif mode
/*********************************************************************/
/* Prepare writing the line. */
/*********************************************************************/
//memcpy(To_Buf, Tdbp->GetLine(), Recsize);
......@@ -1884,17 +1945,23 @@ int BINFAM::WriteBuffer(PGLOBAL g)
/*********************************************************************/
/* Now start the writing process. */
/*********************************************************************/
if (fwrite(&Recsize, sizeof(size_t), 1, Stream) != 1) {
if (fwrite(&Recsize, sizeof(size_t), 1, T_Stream) != 1) {
sprintf(g->Message, "Error %d writing prefix to %s",
errno, To_File);
return RC_FX;
} else if (fwrite(To_Buf, Recsize, 1, Stream) != 1) {
} else if (fwrite(To_Buf, Recsize, 1, T_Stream) != 1) {
sprintf(g->Message, "Error %d writing %zd bytes to %s",
errno, Recsize, To_File);
return RC_FX;
} // endif fwrite
xtrc(1, "write done\n");
if (Tdbp->GetMode() == MODE_UPDATE && moved)
if (fseek(Stream, curpos, SEEK_SET)) {
sprintf(g->Message, MSG(FSEEK_ERROR), strerror(errno));
return RC_FX;
} // endif
xtrc(1, "Binary write done\n");
return RC_OK;
} // end of WriteBuffer
......@@ -2023,7 +2090,6 @@ int DOSFAM::DeleteRecords(PGLOBAL g, int irc)
return RC_OK; // All is correct
} // end of DeleteRecords
#endif // 0
/***********************************************************************/
/* Table file close routine for DOS access method. */
......@@ -2049,4 +2115,4 @@ void BINFAM::Rewind(void)
Rows = 0;
OldBlk = CurBlk = -1;
} // end of Rewind
#endif // 0
......@@ -229,20 +229,20 @@ class DllExport BINFAM : public DOSFAM {
// Methods
//virtual void Reset(void) {TXTFAM::Reset();}
virtual int GetFileLength(PGLOBAL g);
virtual int Cardinality(PGLOBAL g);
//virtual int GetFileLength(PGLOBAL g);
//virtual int Cardinality(PGLOBAL g);
virtual int MaxBlkSize(PGLOBAL g, int s) {return s;}
virtual bool AllocateBuffer(PGLOBAL g);
//virtual int GetRowID(void);
//virtual bool RecordPos(PGLOBAL g);
//virtual bool SetPos(PGLOBAL g, int recpos);
virtual int SkipRecord(PGLOBAL g, bool header) {return 0;}
virtual int SkipRecord(PGLOBAL g, bool header) {return RC_OK;}
//virtual bool OpenTableFile(PGLOBAL g);
virtual int ReadBuffer(PGLOBAL g);
virtual int WriteBuffer(PGLOBAL g);
//virtual int DeleteRecords(PGLOBAL g, int irc);
virtual void CloseTableFile(PGLOBAL g, bool abort);
virtual void Rewind(void);
//virtual void CloseTableFile(PGLOBAL g, bool abort);
//virtual void Rewind(void);
//protected:
//virtual int InitDelete(PGLOBAL g, int fpos, int spos);
......
......@@ -1665,7 +1665,7 @@ void JVALUE::SetValue(PGLOBAL g, PVAL valp)
} else switch (valp->GetType()) {
case TYPE_DATE:
if (((DTVAL*)valp)->IsFormatted())
Strp = valp->GetCharValue();
Strp = PlugDup(g, valp->GetCharValue());
else {
char buf[32];
......@@ -1675,7 +1675,7 @@ void JVALUE::SetValue(PGLOBAL g, PVAL valp)
DataType = TYPE_DTM;
break;
case TYPE_STRING:
Strp = valp->GetCharValue();
Strp = PlugDup(g, valp->GetCharValue());
DataType = TYPE_STRG;
break;
case TYPE_DOUBLE:
......
This diff is collapsed.
--source include/not_embedded.inc
--source include/have_partition.inc
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
--copy_file $MTR_SUITE_DIR/std_data/mulexp5.json $MYSQLD_DATADIR/test/mulexp5.json
--echo #
--echo # Testing doc samples
--echo #
CREATE TABLE t1
(
ISBN CHAR(15),
LANG CHAR(2),
SUBJECT CHAR(32),
AUTHOR CHAR(64),
TITLE CHAR(32),
TRANSLATION CHAR(32),
TRANSLATOR CHAR(80),
PUBLISHER CHAR(32),
DATEPUB int(4)
) ENGINE=CONNECT TABLE_TYPE=BSON FILE_NAME='biblio.json';
SELECT * FROM t1;
DROP TABLE t1;
--echo #
--echo # Testing Jpath. Get the number of authors
--echo #
CREATE TABLE t1
(
ISBN CHAR(15),
Language CHAR(2) JPATH='$.LANG',
Subject CHAR(32) JPATH='$.SUBJECT',
Authors INT(2) JPATH='$.AUTHOR[#]',
Title CHAR(32) JPATH='$.TITLE',
Translation CHAR(32) JPATH='$.TRANSLATION',
Translator CHAR(80) JPATH='$.TRANSLATOR',
Publisher CHAR(20) JPATH='$.PUBLISHER.NAME',
Location CHAR(16) JPATH='$.PUBLISHER.PLACE',
Year int(4) JPATH='$.DATEPUB'
)
ENGINE=CONNECT TABLE_TYPE=BSON FILE_NAME='biblio.json';
SELECT * FROM t1;
DROP TABLE t1;
--echo #
--echo # Concatenates the authors
--echo #
CREATE TABLE t1
(
ISBN CHAR(15),
Language CHAR(2) JPATH='$.LANG',
Subject CHAR(32) JPATH='$.SUBJECT',
AuthorFN CHAR(128) JPATH='$.AUTHOR[" and "].FIRSTNAME',
AuthorLN CHAR(128) JPATH='$.AUTHOR[" and "].LASTNAME',
Title CHAR(32) JPATH='$.TITLE',
Translation CHAR(32) JPATH='$.TRANSLATION',
Translator CHAR(80) JPATH='$.TRANSLATOR',
Publisher CHAR(20) JPATH='$.PUBLISHER.NAME',
Location CHAR(16) JPATH='$.PUBLISHER.PLACE',
Year int(4) JPATH='$.DATEPUB'
)
ENGINE=CONNECT TABLE_TYPE=BSON FILE_NAME='biblio.json';
SELECT * FROM t1;
DROP TABLE t1;
--echo #
--echo # Testing expanding authors
--echo #
CREATE TABLE t1
(
ISBN CHAR(15),
Language CHAR(2) JPATH='$.LANG',
Subject CHAR(32) JPATH='$.SUBJECT',
AuthorFN CHAR(128) JPATH='$.AUTHOR[*].FIRSTNAME',
AuthorLN CHAR(128) JPATH='$.AUTHOR[*].LASTNAME',
Title CHAR(32) JPATH='$.TITLE',
Translation CHAR(32) JPATH='$.TRANSLATION',
Translator CHAR(80) JPATH='$.TRANSLATOR',
Publisher CHAR(20) JPATH='$.PUBLISHER.NAME',
Location CHAR(16) JPATH='$.PUBLISHER.PLACE',
Year int(4) JPATH='$.DATEPUB'
)
ENGINE=CONNECT TABLE_TYPE=BSON FILE_NAME='biblio.json';
SELECT * FROM t1;
UPDATE t1 SET AuthorFN = 'Philippe' WHERE AuthorLN = 'Knab';
SELECT * FROM t1 WHERE ISBN = '9782212090819';
--echo #
--echo # To add an author a new table must be created
--echo #
CREATE TABLE t2 (
FIRSTNAME CHAR(32),
LASTNAME CHAR(32))
ENGINE=CONNECT TABLE_TYPE=BSON FILE_NAME='biblio.json' OPTION_LIST='Object=$[1].AUTHOR';
SELECT * FROM t2;
INSERT INTO t2 VALUES('Charles','Dickens');
SELECT * FROM t1;
DROP TABLE t1;
DROP TABLE t2;
--echo #
--echo # Check the biblio file has the good format
--echo #
CREATE TABLE t1
(
line char(255)
)
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) JPATH='$.LANG',
Subject CHAR(32) JPATH='$.SUBJECT',
AuthorFN CHAR(128) JPATH='$.AUTHOR[*].FIRSTNAME',
AuthorLN CHAR(128) JPATH='$.AUTHOR[*].LASTNAME',
Title CHAR(32) JPATH='$.TITLE',
Translation CHAR(32) JPATH='$.TRANSLATED.PREFIX',
TranslatorFN CHAR(80) JPATH='$.TRANSLATED.TRANSLATOR.FIRSTNAME',
TranslatorLN CHAR(80) JPATH='$.TRANSLATED.TRANSLATOR.LASTNAME',
Publisher CHAR(20) JPATH='$.PUBLISHER.NAME',
Location CHAR(16) JPATH='$.PUBLISHER.PLACE',
Year int(4) JPATH='$.DATEPUB',
INDEX IX(ISBN)
)
ENGINE=CONNECT TABLE_TYPE=BSON FILE_NAME='bib0.json' LRECL=320 OPTION_LIST='Pretty=0';
SHOW INDEX FROM t1;
SELECT * FROM t1;
DESCRIBE SELECT * FROM t1 WHERE ISBN = '9782212090819';
--error ER_GET_ERRMSG
UPDATE t1 SET AuthorFN = 'Philippe' WHERE ISBN = '9782212090819';
DROP TABLE t1;
--echo #
--echo # A file with 2 arrays
--echo #
CREATE TABLE t1 (
WHO CHAR(12),
WEEK INT(2) JPATH='$.WEEK[*].NUMBER',
WHAT CHAR(32) JPATH='$.WEEK[].EXPENSE["+"].WHAT',
AMOUNT DOUBLE(8,2) JPATH='$.WEEK[].EXPENSE[+].AMOUNT')
ENGINE=CONNECT TABLE_TYPE=BSON FILE_NAME='expense.json';
SELECT * FROM t1;
DROP TABLE t1;
--echo #
--echo # Now it can be fully expanded
--echo #
CREATE TABLE t1 (
WHO CHAR(12),
WEEK INT(2) JPATH='$.WEEK[*].NUMBER',
WHAT CHAR(32) JPATH='$.WEEK[*].EXPENSE[*].WHAT',
AMOUNT DOUBLE(8,2) JPATH='$.WEEK[*].EXPENSE[*].AMOUNT')
ENGINE=CONNECT TABLE_TYPE=BSON FILE_NAME='expense.json';
#--error ER_GET_ERRMSG
SELECT * FROM t1;
DROP TABLE t1;
--echo #
--echo # A table showing many calculated results
--echo #
CREATE TABLE t1 (
WHO CHAR(12) NOT NULL,
WEEKS CHAR(12) NOT NULL JPATH='$.WEEK[", "].NUMBER',
SUMS CHAR(64) NOT NULL JPATH='$.WEEK["+"].EXPENSE[+].AMOUNT',
SUM DOUBLE(8,2) NOT NULL JPATH='$.WEEK[+].EXPENSE[+].AMOUNT',
AVGS CHAR(64) NOT NULL JPATH='$.WEEK["+"].EXPENSE[!].AMOUNT',
SUMAVG DOUBLE(8,2) NOT NULL JPATH='$.WEEK[+].EXPENSE[!].AMOUNT',
AVGSUM DOUBLE(8,2) NOT NULL JPATH='$.WEEK[!].EXPENSE[+].AMOUNT',
AVGAVG DOUBLE(8,2) NOT NULL JPATH='$.WEEK[!].EXPENSE[!].AMOUNT',
AVERAGE DOUBLE(8,2) NOT NULL JPATH='$.WEEK[!].EXPENSE[*].AMOUNT')
ENGINE=CONNECT TABLE_TYPE=BSON FILE_NAME='expense.json';
SELECT * FROM t1;
DROP TABLE t1;
--echo #
--echo # Expand expense in 3 one week tables
--echo #
CREATE TABLE t2 (
WHO CHAR(12),
WEEK INT(2) JPATH='$.WEEK[0].NUMBER',
WHAT CHAR(32) JPATH='$.WEEK[0].EXPENSE[*].WHAT',
AMOUNT DOUBLE(8,2) JPATH='$.WEEK[0].EXPENSE[*].AMOUNT')
ENGINE=CONNECT TABLE_TYPE=BSON FILE_NAME='expense.json';
SELECT * FROM t2;
CREATE TABLE t3 (
WHO CHAR(12),
WEEK INT(2) JPATH='$.WEEK[1].NUMBER',
WHAT CHAR(32) JPATH='$.WEEK[1].EXPENSE[*].WHAT',
AMOUNT DOUBLE(8,2) JPATH='$.WEEK[1].EXPENSE[*].AMOUNT')
ENGINE=CONNECT TABLE_TYPE=BSON FILE_NAME='expense.json';
SELECT * FROM t3;
CREATE TABLE t4 (
WHO CHAR(12),
WEEK INT(2) JPATH='$.WEEK[2].NUMBER',
WHAT CHAR(32) JPATH='$.WEEK[2].EXPENSE[*].WHAT',
AMOUNT DOUBLE(8,2) JPATH='$.WEEK[2].EXPENSE[*].AMOUNT')
ENGINE=CONNECT TABLE_TYPE=BSON FILE_NAME='expense.json';
SELECT * FROM t4;
--echo #
--echo # The expanded table is made as a TBL table
--echo #
CREATE TABLE t1 (
WHO CHAR(12),
WEEK INT(2),
WHAT CHAR(32),
AMOUNT DOUBLE(8,2))
ENGINE=CONNECT TABLE_TYPE=TBL TABLE_LIST='t2,t3,t4';
SELECT * FROM t1;
DROP TABLE t1, t2, t3, t4;
--echo #
--echo # Three partial JSON tables
--echo #
CREATE TABLE t2 (
WHO CHAR(12),
WEEK INT(2),
WHAT CHAR(32) JPATH='$.EXPENSE[*].WHAT',
AMOUNT DOUBLE(8,2) JPATH='$.EXPENSE.[*].AMOUNT')
ENGINE=CONNECT TABLE_TYPE=BSON FILE_NAME='mulexp3.json';
SELECT * FROM t2;
CREATE TABLE t3 (
WHO CHAR(12),
WEEK INT(2),
WHAT CHAR(32) JPATH='$.EXPENSE[*].WHAT',
AMOUNT DOUBLE(8,2) JPATH='$.EXPENSE.[*].AMOUNT')
ENGINE=CONNECT TABLE_TYPE=BSON FILE_NAME='mulexp4.json';
SELECT * FROM t3;
CREATE TABLE t4 (
WHO CHAR(12),
WEEK INT(2),
WHAT CHAR(32) JPATH='$.EXPENSE[*].WHAT',
AMOUNT DOUBLE(8,2) JPATH='$.EXPENSE.[*].AMOUNT')
ENGINE=CONNECT TABLE_TYPE=BSON FILE_NAME='mulexp5.json';
SELECT * FROM t4;
--echo #
--echo # The complete table can be a multiple JSON table
--echo #
CREATE TABLE t1 (
WHO CHAR(12),
WEEK INT(2),
WHAT CHAR(32) JPATH='$.EXPENSE[*].WHAT',
AMOUNT DOUBLE(8,2) JPATH='$.EXPENSE.[*].AMOUNT')
ENGINE=CONNECT TABLE_TYPE=BSON FILE_NAME='mulexp*.json' MULTIPLE=1;
SELECT * FROM t1 ORDER BY WHO, WEEK, WHAT, AMOUNT;
DROP TABLE t1;
--echo #
--echo # Or also a partition JSON table
--echo #
CREATE TABLE t1 (
WHO CHAR(12),
WEEK INT(2),
WHAT CHAR(32) JPATH='$.EXPENSE[*].WHAT',
AMOUNT DOUBLE(8,2) JPATH='$.EXPENSE.[*].AMOUNT')
ENGINE=CONNECT TABLE_TYPE=BSON FILE_NAME='mulexp%s.json';
ALTER TABLE t1
PARTITION BY LIST COLUMNS(WEEK) (
PARTITION `3` VALUES IN(3),
PARTITION `4` VALUES IN(4),
PARTITION `5` VALUES IN(5));
SHOW WARNINGS;
SELECT * FROM t1;
SELECT * FROM t1 WHERE WEEK = 4;
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
--remove_file $MYSQLD_DATADIR/test/mulexp5.json
......@@ -634,29 +634,28 @@ PBVAL BTUTIL::ParseLine(PGLOBAL g, int *pretty, bool *comma)
/***********************************************************************/
/* Make the top tree from the object path. */
/***********************************************************************/
PBVAL BTUTIL::MakeTopTree(PGLOBAL g, PBVAL jsp)
PBVAL BTUTIL::MakeTopTree(PGLOBAL g, int type)
{
PBVAL top = NULL;
PBVAL top = NULL, val = NULL;
if (Tp->Objname) {
if (!Tp->Val) {
// Parse and allocate Objname item(s)
if (!Tp->Row) {
// Parse and allocate Objpath item(s)
char* p;
char* objpath = PlugDup(g, Tp->Objname);
char *objpath = PlugDup(g, Tp->Objname);
int i;
PBVAL objp = NULL;
PBVAL arp = NULL;
PBVAL val = NULL;
for (; objpath; objpath = p) {
if ((p = strchr(objpath, Tp->Sep)))
*p++ = 0;
if (*objpath != '[' && !IsNum(objpath)) {
// objp = new(g) JOBJECT;
objp = NewVal(TYPE_JOB);
if (!top)
top = NewVal(TYPE_JOB);
top = objp;
if (val)
SetValueObj(val, objp);
......@@ -687,12 +686,12 @@ PBVAL BTUTIL::MakeTopTree(PGLOBAL g, PBVAL jsp)
} // endfor p
Tp->Val = val;
} // endif Val
SetValueVal(Tp->Val, jsp);
Tp->Row = val;
Tp->Row->Type = type;
} else
top = jsp;
top = Tp->Row = NewVal(type);
return top;
} // end of MakeTopTree
......@@ -1270,7 +1269,6 @@ TDBBSN::TDBBSN(PGLOBAL g, PBDEF tdp, PTXF txfp) : TDBDOS(tdp, txfp)
Bp = new(g) BTUTIL(tdp->G, this);
Top = NULL;
Row = NULL;
Val = NULL;
Colp = NULL;
if (tdp) {
......@@ -1306,7 +1304,6 @@ TDBBSN::TDBBSN(TDBBSN* tdbp) : TDBDOS(NULL, tdbp)
Bp = tdbp->Bp;
Top = tdbp->Top;
Row = tdbp->Row;
Val = tdbp->Val;
Colp = tdbp->Colp;
Jmode = tdbp->Jmode;
Objname = tdbp->Objname;
......@@ -1413,11 +1410,6 @@ bool TDBBSN::OpenDB(PGLOBAL g)
{
TUSE use = Use;
if (Pretty < 0 && Mode == MODE_UPDATE) {
sprintf(g->Message, "Mode %d NIY for Bjson", Mode);
return true;
} // endif Mode
if (Use == USE_OPEN) {
/*******************************************************************/
/* Table already open replace it at its beginning. ??? */
......@@ -1437,19 +1429,20 @@ bool TDBBSN::OpenDB(PGLOBAL g)
return false;
if (Pretty < 0) {
/*******************************************************************/
/* Binary BJSON table. */
/*******************************************************************/
/*********************************************************************/
/* Binary BJSON table. */
/*********************************************************************/
xtrc(1, "JSN OpenDB: tdbp=%p tdb=R%d use=%d mode=%d\n",
this, Tdb_No, Use, Mode);
/*********************************************************************/
/* Lrecl is Ok. */
/*********************************************************************/
// Lrecl is Ok
size_t linelen = Lrecl;
MODE mode = Mode;
// Buffer must be set to G->Sarea
// Buffer must be allocated in G->Sarea
Mode = MODE_ANY;
Txfp->AllocateBuffer(Bp->G);
Mode = mode;
if (Mode == MODE_INSERT)
Bp->SubSet(true);
......@@ -1461,27 +1454,29 @@ bool TDBBSN::OpenDB(PGLOBAL g)
xtrc(1, "OpenJSN: R%hd mode=%d To_Line=%p\n", Tdb_No, Mode, To_Line);
} // endif Pretty
/***********************************************************************/
/* First opening. */
/***********************************************************************/
/***********************************************************************/
/* First opening. */
/***********************************************************************/
if (Mode == MODE_INSERT) {
int type;
switch (Jmode) {
case MODE_OBJECT: Row = Bp->NewVal(TYPE_JOB); break;
case MODE_ARRAY: Row = Bp->NewVal(TYPE_JAR); break;
case MODE_VALUE: Row = Bp->NewVal(TYPE_JVAL); break;
default:
sprintf(g->Message, "Invalid Jmode %d", Jmode);
return true;
case MODE_OBJECT: type = TYPE_JOB; break;
case MODE_ARRAY: type = TYPE_JAR; break;
case MODE_VALUE: type = TYPE_JVAL; break;
default:
sprintf(g->Message, "Invalid Jmode %d", Jmode);
return true;
} // endswitch Jmode
Top = Bp->MakeTopTree(g, type);
Bp->MemSave();
} // endif Mode
if (Xcol)
To_Filter = NULL; // Imcompatible
To_Filter = NULL; // Not compatible
return false;
} // end of OpenDB
/***********************************************************************/
......@@ -1534,6 +1529,7 @@ int TDBBSN::ReadDB(PGLOBAL g)
Bp->SubSet();
if ((Row = Bp->ParseLine(g, &Pretty, &Comma))) {
Top = Row;
Row = Bp->FindRow(g);
SameRow = 0;
Fpos++;
......@@ -1545,10 +1541,9 @@ int TDBBSN::ReadDB(PGLOBAL g)
} else
rc = RC_EF;
} else {
// Here we get a movable Json binary tree
Bp->SubSet(); // Perhaps Useful when updating
Row = (PBVAL)To_Line;
} else { // Here we get a movable Json binary tree
Bp->MemSet(((BINFAM*)Txfp)->Recsize); // Useful when updating
Row = Top = (PBVAL)To_Line;
Row = Bp->FindRow(g);
SameRow = 0;
Fpos++;
......@@ -1569,8 +1564,8 @@ bool TDBBSN::PrepareWriting(PGLOBAL g)
if (Pretty >= 0) {
PSZ s;
if (!(Top = Bp->MakeTopTree(g, Row)))
return true;
// if (!(Top = Bp->MakeTopTree(g, Row->Type)))
// return true;
if ((s = Bp->SerialVal(g, Top, Pretty))) {
if (Comma)
......@@ -2030,25 +2025,44 @@ void BSONCOL::WriteColumn(PGLOBAL g)
throw 666;
} // endif jsp
switch (row->Type) {
case TYPE_JAR:
if (Nod > 1 && Nodes[Nod - 2].Op == OP_EQ)
Cp->SetArrayValue(row, jsp, Nodes[Nod - 2].Rank);
else
Cp->AddArrayValue(row, jsp);
break;
case TYPE_JOB:
if (Nod > 1 && Nodes[Nod - 2].Key)
Cp->SetKeyValue(row, jsp, Nodes[Nod - 2].Key);
break;
case TYPE_JVAL:
default:
Cp->SetValueVal(row, jsp);
} // endswitch Type
break;
} else
jsp = Cp->NewVal(Value);
switch (row->Type) {
case TYPE_JAR:
if (Nodes[Nod - 1].Op == OP_EQ)
Cp->SetArrayValue(row, jsp, Nodes[Nod - 1].Rank);
else
Cp->AddArrayValue(row, jsp);
case TYPE_JAR:
if (Nodes[Nod - 1].Op == OP_EQ)
Cp->SetArrayValue(row, jsp, Nodes[Nod - 1].Rank);
else
Cp->AddArrayValue(row, jsp);
break;
case TYPE_JOB:
if (Nodes[Nod - 1].Key)
Cp->SetKeyValue(row, jsp, Nodes[Nod - 1].Key);
break;
case TYPE_JOB:
if (Nodes[Nod - 1].Key)
Cp->SetKeyValue(row, jsp, Nodes[Nod - 1].Key);
break;
case TYPE_JVAL:
default:
Cp->SetValueVal(row, jsp);
break;
case TYPE_JVAL:
default:
Cp->SetValueVal(row, jsp);
} // endswitch Type
break;
......@@ -2103,9 +2117,10 @@ int TDBBSON::MakeNewDoc(PGLOBAL g)
// Create a void table that will be populated
Docp = Bp->NewVal(TYPE_JAR);
if (!(Top = Bp->MakeTopTree(g, Docp)))
if (!(Top = Bp->MakeTopTree(g, TYPE_JAR)))
return RC_FX;
Docp = Row;
Done = true;
return RC_OK;
} // end of MakeNewDoc
......
......@@ -111,7 +111,7 @@ class BTUTIL : public BDOC {
// Utility functions
PBVAL FindRow(PGLOBAL g);
PBVAL ParseLine(PGLOBAL g, int *pretty, bool *comma);
PBVAL MakeTopTree(PGLOBAL g, PBVAL jsp);
PBVAL MakeTopTree(PGLOBAL g, int type);
PSZ SerialVal(PGLOBAL g, PBVAL top, int pretty);
protected:
......@@ -196,10 +196,9 @@ class DllExport TDBBSN : public TDBDOS {
//int MakeTopTree(PGLOBAL g, PBVAL jsp);
// Members
PBTUT Bp; // The BSUTIL handling class
PBTUT Bp; // The BSUTIL handling class
PBVAL Top; // The top JSON tree
PBVAL Row; // The current row
PBVAL Val; // The value of the current row
PBSCOL Colp; // The multiple column
JMODE Jmode; // MODE_OBJECT by default
PCSZ Objname; // The table object name
......
......@@ -1925,7 +1925,7 @@ PJSON JSONCOL::GetRow(PGLOBAL g)
PJSON nwr, row = Tjp->Row;
for (int i = 0; i < Nod && row; i++) {
if (Nodes[i+1].Op == OP_XX)
if (i < Nod-1 && Nodes[i+1].Op == OP_XX)
break;
else switch (row->GetType()) {
case TYPE_JOB:
......
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