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) ...@@ -872,7 +872,18 @@ void BJSON::SubSet(bool b)
} // end of SubSet } // 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. */ /* Sub-allocate and initialize a BPAIR. */
...@@ -1187,18 +1198,17 @@ void BJSON::MergeArray(PBVAL bap1, PBVAL bap2) ...@@ -1187,18 +1198,17 @@ void BJSON::MergeArray(PBVAL bap1, PBVAL bap2)
void BJSON::SetArrayValue(PBVAL bap, PBVAL nvp, int n) void BJSON::SetArrayValue(PBVAL bap, PBVAL nvp, int n)
{ {
CheckType(bap, TYPE_JAR); CheckType(bap, TYPE_JAR);
int i = 0;
PBVAL bvp = NULL, pvp = NULL; PBVAL bvp = NULL, pvp = NULL;
if (bap->To_Val) { if (bap->To_Val)
for (int i = 0; bvp = GetArray(bap); i++, bvp = GetNext(bvp)) for (bvp = GetArray(bap); bvp; i++, bvp = GetNext(bvp))
if (i == n) { if (i == n) {
SetValueVal(bvp, nvp); SetValueVal(bvp, nvp);
return; return;
} else } else
pvp = bvp; pvp = bvp;
} // endif bap
if (!bvp) if (!bvp)
AddArrayValue(bap, MOF(nvp)); AddArrayValue(bap, MOF(nvp));
...@@ -1264,7 +1274,8 @@ void BJSON::DeleteValue(PBVAL bap, int n) ...@@ -1264,7 +1274,8 @@ void BJSON::DeleteValue(PBVAL bap, int n)
bap->Nd--; bap->Nd--;
break; break;
} // endif i } else
pvp = bvp;
} // end of DeleteValue } // end of DeleteValue
...@@ -1587,17 +1598,17 @@ PBVAL BJSON::SetValue(PBVAL vlp, PVAL valp) ...@@ -1587,17 +1598,17 @@ PBVAL BJSON::SetValue(PBVAL vlp, PVAL valp)
} else switch (valp->GetType()) { } else switch (valp->GetType()) {
case TYPE_DATE: case TYPE_DATE:
if (((DTVAL*)valp)->IsFormatted()) if (((DTVAL*)valp)->IsFormatted())
vlp->To_Val = MOF(PlugDup(G, valp->GetCharValue())); vlp->To_Val = DupStr(valp->GetCharValue());
else { else {
char buf[32]; char buf[32];
vlp->To_Val = MOF(PlugDup(G, valp->GetCharString(buf))); vlp->To_Val = DupStr(valp->GetCharString(buf));
} // endif Formatted } // endif Formatted
vlp->Type = TYPE_DTM; vlp->Type = TYPE_DTM;
break; break;
case TYPE_STRING: case TYPE_STRING:
vlp->To_Val = MOF(PlugDup(G, valp->GetCharValue())); vlp->To_Val = DupStr(valp->GetCharValue());
vlp->Type = TYPE_STRG; vlp->Type = TYPE_STRG;
break; break;
case TYPE_DOUBLE: case TYPE_DOUBLE:
...@@ -1608,7 +1619,7 @@ PBVAL BJSON::SetValue(PBVAL vlp, PVAL valp) ...@@ -1608,7 +1619,7 @@ PBVAL BJSON::SetValue(PBVAL vlp, PVAL valp)
vlp->F = (float)valp->GetFloatValue(); vlp->F = (float)valp->GetFloatValue();
vlp->Type = TYPE_FLOAT; vlp->Type = TYPE_FLOAT;
} else { } else {
double *dp = (double*)PlugSubAlloc(G, NULL, sizeof(double)); double *dp = (double*)BsonSubAlloc(sizeof(double));
*dp = valp->GetFloatValue(); *dp = valp->GetFloatValue();
vlp->To_Val = MOF(dp); vlp->To_Val = MOF(dp);
...@@ -1629,7 +1640,7 @@ PBVAL BJSON::SetValue(PBVAL vlp, PVAL valp) ...@@ -1629,7 +1640,7 @@ PBVAL BJSON::SetValue(PBVAL vlp, PVAL valp)
vlp->N = valp->GetIntValue(); vlp->N = valp->GetIntValue();
vlp->Type = TYPE_INTG; vlp->Type = TYPE_INTG;
} else { } else {
longlong* llp = (longlong*)PlugSubAlloc(G, NULL, sizeof(longlong)); longlong* llp = (longlong*)BsonSubAlloc(sizeof(longlong));
*llp = valp->GetBigintValue(); *llp = valp->GetBigintValue();
vlp->To_Val = MOF(llp); vlp->To_Val = MOF(llp);
......
...@@ -76,6 +76,7 @@ class BJSON : public BLOCK { ...@@ -76,6 +76,7 @@ class BJSON : public BLOCK {
void* GetBase(void) { return Base; } void* GetBase(void) { return Base; }
void SubSet(bool b = false); void SubSet(bool b = false);
void MemSave(void) {G->Saved_Size = ((PPOOLHEADER)G->Sarea)->To_Free;} 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); } void GetMsg(PGLOBAL g) { if (g != G) strcpy(g->Message, G->Message); }
// SubAlloc functions // SubAlloc functions
......
...@@ -805,8 +805,8 @@ int DOSFAM::ReadBuffer(PGLOBAL g) ...@@ -805,8 +805,8 @@ int DOSFAM::ReadBuffer(PGLOBAL g)
Placed = false; Placed = false;
if (trace(2)) if (trace(2))
htrc(" About to read: stream=%p To_Buf=%p Buflen=%d\n", htrc(" About to read: stream=%p To_Buf=%p Buflen=%d Fpos=%d\n",
Stream, To_Buf, Buflen); Stream, To_Buf, Buflen, Fpos);
if (fgets(To_Buf, Buflen, Stream)) { if (fgets(To_Buf, Buflen, Stream)) {
p = To_Buf + strlen(To_Buf) - 1; p = To_Buf + strlen(To_Buf) - 1;
...@@ -1665,6 +1665,7 @@ void BLKFAM::Rewind(void) ...@@ -1665,6 +1665,7 @@ void BLKFAM::Rewind(void)
/* --------------------------- Class BINFAM -------------------------- */ /* --------------------------- Class BINFAM -------------------------- */
#if 0
/***********************************************************************/ /***********************************************************************/
/* BIN GetFileLength: returns file size in number of bytes. */ /* BIN GetFileLength: returns file size in number of bytes. */
/***********************************************************************/ /***********************************************************************/
...@@ -1692,7 +1693,6 @@ int BINFAM::Cardinality(PGLOBAL g) ...@@ -1692,7 +1693,6 @@ int BINFAM::Cardinality(PGLOBAL g)
return (g) ? -1 : 0; return (g) ? -1 : 0;
} // end of Cardinality } // end of Cardinality
#if 0
/***********************************************************************/ /***********************************************************************/
/* OpenTableFile: Open a DOS/UNIX table file using C standard I/Os. */ /* OpenTableFile: Open a DOS/UNIX table file using C standard I/Os. */
/***********************************************************************/ /***********************************************************************/
...@@ -1747,11 +1747,29 @@ bool BINFAM::AllocateBuffer(PGLOBAL g) ...@@ -1747,11 +1747,29 @@ bool BINFAM::AllocateBuffer(PGLOBAL g)
// Lrecl is Ok // Lrecl is Ok
Buflen = Lrecl; Buflen = Lrecl;
// 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
return false;
#if 0
MODE mode = Tdbp->GetMode();
// Lrecl is Ok
Dbflen = Buflen = Lrecl;
if (trace(1)) if (trace(1))
htrc("SubAllocating a buffer of %d bytes\n", Buflen); htrc("SubAllocating a buffer of %d bytes\n", Buflen);
To_Buf = (char*)PlugSubAlloc(g, NULL, Buflen); DelBuf = To_Buf = (char*)PlugSubAlloc(g, NULL, Buflen);
return false; return false;
#endif // 0
} // end of AllocateBuffer } // end of AllocateBuffer
#if 0 #if 0
...@@ -1830,8 +1848,8 @@ int BINFAM::ReadBuffer(PGLOBAL g) ...@@ -1830,8 +1848,8 @@ int BINFAM::ReadBuffer(PGLOBAL g)
} else } else
Placed = false; Placed = false;
xtrc(2, " About to read: bstream=%p To_Buf=%p Buflen=%d\n", xtrc(2, " About to read: bstream=%p To_Buf=%p Buflen=%d Fpos=%d\n",
Stream, To_Buf, Buflen); Stream, To_Buf, Buflen, Fpos);
// Read the prefix giving the row length // Read the prefix giving the row length
if (!fread(&Recsize, sizeof(size_t), 1, Stream)) { if (!fread(&Recsize, sizeof(size_t), 1, Stream)) {
...@@ -1848,7 +1866,6 @@ int BINFAM::ReadBuffer(PGLOBAL g) ...@@ -1848,7 +1866,6 @@ int BINFAM::ReadBuffer(PGLOBAL g)
if (fread(To_Buf, Recsize, 1, Stream)) { if (fread(To_Buf, Recsize, 1, Stream)) {
xtrc(2, " Read: To_Buf=%p Recsize=%zd\n", To_Buf, Recsize); xtrc(2, " Read: To_Buf=%p Recsize=%zd\n", To_Buf, Recsize);
// memcpy(Tdbp->GetLine(), To_Buf, Recsize);
num_read++; num_read++;
rc = RC_OK; rc = RC_OK;
} else if (feof(Stream)) { } else if (feof(Stream)) {
...@@ -1876,6 +1893,50 @@ int BINFAM::WriteBuffer(PGLOBAL g) ...@@ -1876,6 +1893,50 @@ int BINFAM::WriteBuffer(PGLOBAL g)
int curpos = 0; int curpos = 0;
bool moved = true; 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. */ /* Prepare writing the line. */
/*********************************************************************/ /*********************************************************************/
...@@ -1884,17 +1945,23 @@ int BINFAM::WriteBuffer(PGLOBAL g) ...@@ -1884,17 +1945,23 @@ int BINFAM::WriteBuffer(PGLOBAL g)
/*********************************************************************/ /*********************************************************************/
/* Now start the writing process. */ /* 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", sprintf(g->Message, "Error %d writing prefix to %s",
errno, To_File); errno, To_File);
return RC_FX; 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", sprintf(g->Message, "Error %d writing %zd bytes to %s",
errno, Recsize, To_File); errno, Recsize, To_File);
return RC_FX; return RC_FX;
} // endif fwrite } // 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; return RC_OK;
} // end of WriteBuffer } // end of WriteBuffer
...@@ -2023,7 +2090,6 @@ int DOSFAM::DeleteRecords(PGLOBAL g, int irc) ...@@ -2023,7 +2090,6 @@ int DOSFAM::DeleteRecords(PGLOBAL g, int irc)
return RC_OK; // All is correct return RC_OK; // All is correct
} // end of DeleteRecords } // end of DeleteRecords
#endif // 0
/***********************************************************************/ /***********************************************************************/
/* Table file close routine for DOS access method. */ /* Table file close routine for DOS access method. */
...@@ -2049,4 +2115,4 @@ void BINFAM::Rewind(void) ...@@ -2049,4 +2115,4 @@ void BINFAM::Rewind(void)
Rows = 0; Rows = 0;
OldBlk = CurBlk = -1; OldBlk = CurBlk = -1;
} // end of Rewind } // end of Rewind
#endif // 0
...@@ -229,20 +229,20 @@ class DllExport BINFAM : public DOSFAM { ...@@ -229,20 +229,20 @@ class DllExport BINFAM : public DOSFAM {
// Methods // Methods
//virtual void Reset(void) {TXTFAM::Reset();} //virtual void Reset(void) {TXTFAM::Reset();}
virtual int GetFileLength(PGLOBAL g); //virtual int GetFileLength(PGLOBAL g);
virtual int Cardinality(PGLOBAL g); //virtual int Cardinality(PGLOBAL g);
virtual int MaxBlkSize(PGLOBAL g, int s) {return s;} virtual int MaxBlkSize(PGLOBAL g, int s) {return s;}
virtual bool AllocateBuffer(PGLOBAL g); virtual bool AllocateBuffer(PGLOBAL g);
//virtual int GetRowID(void); //virtual int GetRowID(void);
//virtual bool RecordPos(PGLOBAL g); //virtual bool RecordPos(PGLOBAL g);
//virtual bool SetPos(PGLOBAL g, int recpos); //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 bool OpenTableFile(PGLOBAL g);
virtual int ReadBuffer(PGLOBAL g); virtual int ReadBuffer(PGLOBAL g);
virtual int WriteBuffer(PGLOBAL g); virtual int WriteBuffer(PGLOBAL g);
//virtual int DeleteRecords(PGLOBAL g, int irc); //virtual int DeleteRecords(PGLOBAL g, int irc);
virtual void CloseTableFile(PGLOBAL g, bool abort); //virtual void CloseTableFile(PGLOBAL g, bool abort);
virtual void Rewind(void); //virtual void Rewind(void);
//protected: //protected:
//virtual int InitDelete(PGLOBAL g, int fpos, int spos); //virtual int InitDelete(PGLOBAL g, int fpos, int spos);
......
...@@ -1665,7 +1665,7 @@ void JVALUE::SetValue(PGLOBAL g, PVAL valp) ...@@ -1665,7 +1665,7 @@ void JVALUE::SetValue(PGLOBAL g, PVAL valp)
} else switch (valp->GetType()) { } else switch (valp->GetType()) {
case TYPE_DATE: case TYPE_DATE:
if (((DTVAL*)valp)->IsFormatted()) if (((DTVAL*)valp)->IsFormatted())
Strp = valp->GetCharValue(); Strp = PlugDup(g, valp->GetCharValue());
else { else {
char buf[32]; char buf[32];
...@@ -1675,7 +1675,7 @@ void JVALUE::SetValue(PGLOBAL g, PVAL valp) ...@@ -1675,7 +1675,7 @@ void JVALUE::SetValue(PGLOBAL g, PVAL valp)
DataType = TYPE_DTM; DataType = TYPE_DTM;
break; break;
case TYPE_STRING: case TYPE_STRING:
Strp = valp->GetCharValue(); Strp = PlugDup(g, valp->GetCharValue());
DataType = TYPE_STRG; DataType = TYPE_STRG;
break; break;
case TYPE_DOUBLE: 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) ...@@ -634,29 +634,28 @@ PBVAL BTUTIL::ParseLine(PGLOBAL g, int *pretty, bool *comma)
/***********************************************************************/ /***********************************************************************/
/* Make the top tree from the object path. */ /* 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->Objname) {
if (!Tp->Val) { if (!Tp->Row) {
// Parse and allocate Objname item(s) // Parse and allocate Objpath item(s)
char* p; char* p;
char* objpath = PlugDup(g, Tp->Objname); char *objpath = PlugDup(g, Tp->Objname);
int i; int i;
PBVAL objp = NULL; PBVAL objp = NULL;
PBVAL arp = NULL; PBVAL arp = NULL;
PBVAL val = NULL;
for (; objpath; objpath = p) { for (; objpath; objpath = p) {
if ((p = strchr(objpath, Tp->Sep))) if ((p = strchr(objpath, Tp->Sep)))
*p++ = 0; *p++ = 0;
if (*objpath != '[' && !IsNum(objpath)) { if (*objpath != '[' && !IsNum(objpath)) {
// objp = new(g) JOBJECT; objp = NewVal(TYPE_JOB);
if (!top) if (!top)
top = NewVal(TYPE_JOB); top = objp;
if (val) if (val)
SetValueObj(val, objp); SetValueObj(val, objp);
...@@ -687,12 +686,12 @@ PBVAL BTUTIL::MakeTopTree(PGLOBAL g, PBVAL jsp) ...@@ -687,12 +686,12 @@ PBVAL BTUTIL::MakeTopTree(PGLOBAL g, PBVAL jsp)
} // endfor p } // endfor p
Tp->Val = val;
} // endif Val } // endif Val
SetValueVal(Tp->Val, jsp); Tp->Row = val;
Tp->Row->Type = type;
} else } else
top = jsp; top = Tp->Row = NewVal(type);
return top; return top;
} // end of MakeTopTree } // end of MakeTopTree
...@@ -1270,7 +1269,6 @@ TDBBSN::TDBBSN(PGLOBAL g, PBDEF tdp, PTXF txfp) : TDBDOS(tdp, txfp) ...@@ -1270,7 +1269,6 @@ TDBBSN::TDBBSN(PGLOBAL g, PBDEF tdp, PTXF txfp) : TDBDOS(tdp, txfp)
Bp = new(g) BTUTIL(tdp->G, this); Bp = new(g) BTUTIL(tdp->G, this);
Top = NULL; Top = NULL;
Row = NULL; Row = NULL;
Val = NULL;
Colp = NULL; Colp = NULL;
if (tdp) { if (tdp) {
...@@ -1306,7 +1304,6 @@ TDBBSN::TDBBSN(TDBBSN* tdbp) : TDBDOS(NULL, tdbp) ...@@ -1306,7 +1304,6 @@ TDBBSN::TDBBSN(TDBBSN* tdbp) : TDBDOS(NULL, tdbp)
Bp = tdbp->Bp; Bp = tdbp->Bp;
Top = tdbp->Top; Top = tdbp->Top;
Row = tdbp->Row; Row = tdbp->Row;
Val = tdbp->Val;
Colp = tdbp->Colp; Colp = tdbp->Colp;
Jmode = tdbp->Jmode; Jmode = tdbp->Jmode;
Objname = tdbp->Objname; Objname = tdbp->Objname;
...@@ -1413,11 +1410,6 @@ bool TDBBSN::OpenDB(PGLOBAL g) ...@@ -1413,11 +1410,6 @@ bool TDBBSN::OpenDB(PGLOBAL g)
{ {
TUSE use = Use; 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) { if (Use == USE_OPEN) {
/*******************************************************************/ /*******************************************************************/
/* Table already open replace it at its beginning. ??? */ /* Table already open replace it at its beginning. ??? */
...@@ -1437,19 +1429,20 @@ bool TDBBSN::OpenDB(PGLOBAL g) ...@@ -1437,19 +1429,20 @@ bool TDBBSN::OpenDB(PGLOBAL g)
return false; return false;
if (Pretty < 0) { if (Pretty < 0) {
/*******************************************************************/ /*********************************************************************/
/* Binary BJSON table. */ /* Binary BJSON table. */
/*******************************************************************/ /*********************************************************************/
xtrc(1, "JSN OpenDB: tdbp=%p tdb=R%d use=%d mode=%d\n", xtrc(1, "JSN OpenDB: tdbp=%p tdb=R%d use=%d mode=%d\n",
this, Tdb_No, Use, Mode); this, Tdb_No, Use, Mode);
/*********************************************************************/ // Lrecl is Ok
/* Lrecl is Ok. */
/*********************************************************************/
size_t linelen = Lrecl; 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); Txfp->AllocateBuffer(Bp->G);
Mode = mode;
if (Mode == MODE_INSERT) if (Mode == MODE_INSERT)
Bp->SubSet(true); Bp->SubSet(true);
...@@ -1465,23 +1458,25 @@ bool TDBBSN::OpenDB(PGLOBAL g) ...@@ -1465,23 +1458,25 @@ bool TDBBSN::OpenDB(PGLOBAL g)
/* First opening. */ /* First opening. */
/***********************************************************************/ /***********************************************************************/
if (Mode == MODE_INSERT) { if (Mode == MODE_INSERT) {
int type;
switch (Jmode) { switch (Jmode) {
case MODE_OBJECT: Row = Bp->NewVal(TYPE_JOB); break; case MODE_OBJECT: type = TYPE_JOB; break;
case MODE_ARRAY: Row = Bp->NewVal(TYPE_JAR); break; case MODE_ARRAY: type = TYPE_JAR; break;
case MODE_VALUE: Row = Bp->NewVal(TYPE_JVAL); break; case MODE_VALUE: type = TYPE_JVAL; break;
default: default:
sprintf(g->Message, "Invalid Jmode %d", Jmode); sprintf(g->Message, "Invalid Jmode %d", Jmode);
return true; return true;
} // endswitch Jmode } // endswitch Jmode
Top = Bp->MakeTopTree(g, type);
Bp->MemSave(); Bp->MemSave();
} // endif Mode } // endif Mode
if (Xcol) if (Xcol)
To_Filter = NULL; // Imcompatible To_Filter = NULL; // Not compatible
return false; return false;
} // end of OpenDB } // end of OpenDB
/***********************************************************************/ /***********************************************************************/
...@@ -1534,6 +1529,7 @@ int TDBBSN::ReadDB(PGLOBAL g) ...@@ -1534,6 +1529,7 @@ int TDBBSN::ReadDB(PGLOBAL g)
Bp->SubSet(); Bp->SubSet();
if ((Row = Bp->ParseLine(g, &Pretty, &Comma))) { if ((Row = Bp->ParseLine(g, &Pretty, &Comma))) {
Top = Row;
Row = Bp->FindRow(g); Row = Bp->FindRow(g);
SameRow = 0; SameRow = 0;
Fpos++; Fpos++;
...@@ -1545,10 +1541,9 @@ int TDBBSN::ReadDB(PGLOBAL g) ...@@ -1545,10 +1541,9 @@ int TDBBSN::ReadDB(PGLOBAL g)
} else } else
rc = RC_EF; rc = RC_EF;
} else { } else { // Here we get a movable Json binary tree
// Here we get a movable Json binary tree Bp->MemSet(((BINFAM*)Txfp)->Recsize); // Useful when updating
Bp->SubSet(); // Perhaps Useful when updating Row = Top = (PBVAL)To_Line;
Row = (PBVAL)To_Line;
Row = Bp->FindRow(g); Row = Bp->FindRow(g);
SameRow = 0; SameRow = 0;
Fpos++; Fpos++;
...@@ -1569,8 +1564,8 @@ bool TDBBSN::PrepareWriting(PGLOBAL g) ...@@ -1569,8 +1564,8 @@ bool TDBBSN::PrepareWriting(PGLOBAL g)
if (Pretty >= 0) { if (Pretty >= 0) {
PSZ s; PSZ s;
if (!(Top = Bp->MakeTopTree(g, Row))) // if (!(Top = Bp->MakeTopTree(g, Row->Type)))
return true; // return true;
if ((s = Bp->SerialVal(g, Top, Pretty))) { if ((s = Bp->SerialVal(g, Top, Pretty))) {
if (Comma) if (Comma)
...@@ -2030,6 +2025,25 @@ void BSONCOL::WriteColumn(PGLOBAL g) ...@@ -2030,6 +2025,25 @@ void BSONCOL::WriteColumn(PGLOBAL g)
throw 666; throw 666;
} // endif jsp } // 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 } else
jsp = Cp->NewVal(Value); jsp = Cp->NewVal(Value);
...@@ -2103,9 +2117,10 @@ int TDBBSON::MakeNewDoc(PGLOBAL g) ...@@ -2103,9 +2117,10 @@ int TDBBSON::MakeNewDoc(PGLOBAL g)
// Create a void table that will be populated // Create a void table that will be populated
Docp = Bp->NewVal(TYPE_JAR); Docp = Bp->NewVal(TYPE_JAR);
if (!(Top = Bp->MakeTopTree(g, Docp))) if (!(Top = Bp->MakeTopTree(g, TYPE_JAR)))
return RC_FX; return RC_FX;
Docp = Row;
Done = true; Done = true;
return RC_OK; return RC_OK;
} // end of MakeNewDoc } // end of MakeNewDoc
......
...@@ -111,7 +111,7 @@ class BTUTIL : public BDOC { ...@@ -111,7 +111,7 @@ class BTUTIL : public BDOC {
// Utility functions // Utility functions
PBVAL FindRow(PGLOBAL g); PBVAL FindRow(PGLOBAL g);
PBVAL ParseLine(PGLOBAL g, int *pretty, bool *comma); 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); PSZ SerialVal(PGLOBAL g, PBVAL top, int pretty);
protected: protected:
...@@ -199,7 +199,6 @@ class DllExport TDBBSN : public TDBDOS { ...@@ -199,7 +199,6 @@ class DllExport TDBBSN : public TDBDOS {
PBTUT Bp; // The BSUTIL handling class PBTUT Bp; // The BSUTIL handling class
PBVAL Top; // The top JSON tree PBVAL Top; // The top JSON tree
PBVAL Row; // The current row PBVAL Row; // The current row
PBVAL Val; // The value of the current row
PBSCOL Colp; // The multiple column PBSCOL Colp; // The multiple column
JMODE Jmode; // MODE_OBJECT by default JMODE Jmode; // MODE_OBJECT by default
PCSZ Objname; // The table object name PCSZ Objname; // The table object name
......
...@@ -1925,7 +1925,7 @@ PJSON JSONCOL::GetRow(PGLOBAL g) ...@@ -1925,7 +1925,7 @@ PJSON JSONCOL::GetRow(PGLOBAL g)
PJSON nwr, row = Tjp->Row; PJSON nwr, row = Tjp->Row;
for (int i = 0; i < Nod && row; i++) { 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; break;
else switch (row->GetType()) { else switch (row->GetType()) {
case TYPE_JOB: 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