Browse Source

Merge branch 'Buggynours:10.0' into 10.0

pull/61/head
Sergei Golubchik 11 years ago
parent
commit
5dcb111c38
  1. 20
      .gitattributes
  2. 233
      .gitignore
  3. 41
      storage/connect/CMakeLists.txt
  4. 1
      storage/connect/connect.cc
  5. 95
      storage/connect/domdoc.cpp
  6. 19
      storage/connect/domdoc.h
  7. 5
      storage/connect/filamap.cpp
  8. 1
      storage/connect/filamap.h
  9. 8
      storage/connect/filamtxt.cpp
  10. 1
      storage/connect/filamtxt.h
  11. 8
      storage/connect/filamvct.cpp
  12. 157
      storage/connect/ha_connect.cc
  13. 20
      storage/connect/ha_connect.h
  14. 4
      storage/connect/json.cpp
  15. 534
      storage/connect/json.h
  16. 71
      storage/connect/libdoc.cpp
  17. 13
      storage/connect/mycat.cc
  18. 40
      storage/connect/mycat.h
  19. 18
      storage/connect/mysql-test/connect/r/json.result
  20. 11
      storage/connect/odbconn.cpp
  21. 10
      storage/connect/plgdbsem.h
  22. 25
      storage/connect/plgdbutl.cpp
  23. 15
      storage/connect/plgxml.h
  24. 26
      storage/connect/plugutil.c
  25. 44
      storage/connect/reldef.cpp
  26. 2
      storage/connect/reldef.h
  27. 630
      storage/connect/tabjson.cpp
  28. 66
      storage/connect/tabjson.h
  29. 6
      storage/connect/table.cpp
  30. 11
      storage/connect/tabmul.cpp
  31. 4
      storage/connect/tabmysql.cpp
  32. 11
      storage/connect/taboccur.cpp
  33. 23
      storage/connect/tabpivot.cpp
  34. 3
      storage/connect/tabtbl.cpp
  35. 21
      storage/connect/tabutil.cpp
  36. 3
      storage/connect/tabxcl.cpp
  37. 376
      storage/connect/tabxml.cpp
  38. 23
      storage/connect/tabxml.h
  39. 9
      storage/connect/valblk.cpp
  40. 80
      storage/connect/value.cpp
  41. 28
      storage/connect/xobject.cpp
  42. 1
      storage/connect/xobject.h
  43. 6
      storage/connect/xtable.h
  44. 2
      storage/innobase/dict/dict0mem.cc
  45. 1
      storage/innobase/include/dict0mem.h
  46. 2
      storage/xtradb/dict/dict0mem.cc
  47. 1
      storage/xtradb/include/dict0mem.h

20
.gitattributes

@ -1,3 +1,23 @@
# Set the default behavior, in case people don't have core.autocrlf set.
* text=auto
# Explicitly declare text files you want to always be normalized and converted
# to native line endings on checkout.
*.c text
*.cc text
*.cpp text
*.h text
*.test text
# Declare files that will always have LF line endings on checkout.
*.result text eol=lf
storage/connect/mysql-test/connect/std_data/*.txt text eol=lf
storage/connect/mysql-test/connect/std_data/*.dat text eol=lf
# Denote all files that are truly binary and should not be modified.
*.png binary
*.jpg binary
*.c diff=cpp
*.h diff=cpp
*.cc diff=cpp

233
.gitignore

@ -1,3 +1,4 @@
# Edited by Olivier Bertrand
*-t
*.a
*.ctest
@ -7,6 +8,8 @@
*.so.*
*.spec
*~
*.bak
*.log
.*.swp
*.ninja
.ninja_*
@ -15,6 +18,9 @@ errmsg.sys
typescript
CMakeCache.txt
CMakeFiles/
MakeFile
cmake_install.cmake
install_manifest.txt
CPackConfig.cmake
CPackSourceConfig.cmake
CTestTestfile.cmake
@ -230,3 +236,230 @@ storage/mroonga/vendor/groonga/src/grnslap
storage/mroonga/vendor/groonga/src/groonga
storage/mroonga/vendor/groonga/src/groonga-benchmark
storage/mroonga/vendor/groonga/src/suggest/groonga-suggest-create-dataset
# C and C++
# Compiled Object files
*.slo
*.lo
*.o
*.ko
*.obj
*.elf
# Precompiled Headers
*.gch
*.pch
# Compiled Static libraries
*.lib
*.a
*.la
*.lai
*.lo
# Compiled Dynamic libraries
*.so
*.so.*
*.dylib
*.dll
# Executables
*.exe
*.out
*.app
*.i*86
*.x86_64
*.hex
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
# User-specific files
*.suo
*.user
*.userosscache
*.sln.docstates
*.ncb
*.sln
*.vcproj
*.vcproj.*
*.vcproj.*.*
*.vcproj.*.*.*
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
build/
bld/
[Bb]in/
[Oo]bj/
# Roslyn cache directories
*.ide/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
#NUNIT
*.VisualState.xml
TestResult.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
*_i.c
*_p.c
*_i.h
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opensdf
*.sdf
*.cachefile
# Visual Studio profiler
*.psess
*.vsp
*.vspx
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# JustCode is a .NET coding addin-in
.JustCode
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# NCrunch
_NCrunch_*
.*crunch*.local.xml
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# TODO: Comment the next line if you want to checkin your web deploy settings
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# NuGet Packages
*.nupkg
# The packages folder can be ignored because of Package Restore
**/packages/*
# except build/, which is used as an MSBuild target.
!**/packages/build/
# If using the old MSBuild-Integrated Package Restore, uncomment this:
#!**/packages/repositories.config
# Windows Azure Build Output
csx/
*.build.csdef
# Windows Store app package directory
AppPackages/
# Others
# sql/
*.Cache
ClientBin/
[Ss]tyle[Cc]op.*
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.pfx
*.publishsettings
node_modules/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
# SQL Server files
*.mdf
*.ldf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
# Microsoft Fakes
FakesAssemblies/

41
storage/connect/CMakeLists.txt

@ -21,18 +21,18 @@ ha_connect.cc connect.cc user_connect.cc mycat.cc
fmdlex.c osutil.c plugutil.c rcmsg.c rcmsg.h
array.cpp blkfil.cpp colblk.cpp csort.cpp
filamap.cpp filamdbf.cpp filamfix.cpp filamtxt.cpp filamvct.cpp filamzip.cpp
filter.cpp json.cpp jsonudf.cpp maputil.cpp myutil.cpp plgdbutl.cpp reldef.cpp
tabcol.cpp tabdos.cpp tabfix.cpp tabfmt.cpp tabjson.cpp table.cpp tabmul.cpp
taboccur.cpp tabpivot.cpp tabsys.cpp tabtbl.cpp tabutil.cpp tabvct.cpp tabvir.cpp
tabxcl.cpp valblk.cpp value.cpp xindex.cpp xobject.cpp
filter.cpp json.cpp jsonudf.cpp maputil.cpp myconn.cpp myutil.cpp plgdbutl.cpp
reldef.cpp tabcol.cpp tabdos.cpp tabfix.cpp tabfmt.cpp tabjson.cpp table.cpp
tabmul.cpp tabmysql.cpp taboccur.cpp tabpivot.cpp tabsys.cpp tabtbl.cpp tabutil.cpp
tabvct.cpp tabvir.cpp tabxcl.cpp valblk.cpp value.cpp xindex.cpp xobject.cpp
array.h blkfil.h block.h catalog.h checklvl.h colblk.h connect.h csort.h
engmsg.h filamap.h filamdbf.h filamfix.h filamtxt.h filamvct.h filamzip.h
filter.h global.h ha_connect.h inihandl.h json.h maputil.h msgid.h mycat.h
myutil.h os.h osutil.h plgcnx.h plgdbsem.h preparse.h reldef.h resource.h
tabcol.h tabdos.h tabfix.h tabfmt.h tabjson.h tabmul.h taboccur.h tabpivot.h
tabsys.h tabtbl.h tabutil.h tabvct.h tabvir.h tabxcl.h user_connect.h
valblk.h value.h xindex.h xobject.h xtable.h)
myconn.h myutil.h os.h osutil.h plgcnx.h plgdbsem.h preparse.h reldef.h
resource.h tabcol.h tabdos.h tabfix.h tabfmt.h tabjson.h tabmul.h tabmysql.h
taboccur.h tabpivot.h tabsys.h tabtbl.h tabutil.h tabvct.h tabvir.h tabxcl.h
user_connect.h valblk.h value.h xindex.h xobject.h xtable.h)
#
# Definitions that are shared for all OSes
@ -166,24 +166,15 @@ IF(LIBXML2_FOUND OR MSXML_FOUND)
ENDIF()
#
# MySQL
# MySQL is now included unconditionnally
#
OPTION(CONNECT_WITH_MYSQL
"Compile CONNECT storage engine with remote MySQL connection support"
ON)
IF(CONNECT_WITH_MYSQL)
SET(CONNECT_SOURCES ${CONNECT_SOURCES}
myconn.cpp myconn.h tabmysql.cpp tabmysql.h)
add_definitions(-DMYSQL_SUPPORT)
IF(NOT UNIX)
#
# TODO: remove this
# change to use "#include "../../include/mysql.h" in the sources.
INCLUDE_DIRECTORIES("../../include/mysql")
ENDIF(NOT UNIX)
ENDIF(CONNECT_WITH_MYSQL)
IF(NOT UNIX)
#
# TODO: remove this
# change to use "#include "../../include/mysql.h" in the sources.
INCLUDE_DIRECTORIES("../../include/mysql")
ENDIF(NOT UNIX)
#
@ -232,6 +223,8 @@ IF(CONNECT_WITH_ODBC)
DOC "Specify the ODBC driver manager library here."
)
mark_as_advanced(ODBC_LIBRARY ODBC_INCLUDE_DIR)
IF(ODBC_INCLUDE_DIR AND ODBC_LIBRARY)
set(CMAKE_REQUIRED_LIBRARIES ${ODBC_LIBRARY})
set(CMAKE_REQUIRED_INCLUDES ${ODBC_INCLUDE_DIR})

1
storage/connect/connect.cc

@ -42,7 +42,6 @@
#include "tabcol.h"
#include "catalog.h"
#include "ha_connect.h"
#include "mycat.h"
#define my_strupr(p) my_caseup_str(default_charset_info, (p));
#define my_strlwr(p) my_casedn_str(default_charset_info, (p));

95
storage/connect/domdoc.cpp

@ -275,7 +275,7 @@ PXNODE DOMNODE::GetNext(PGLOBAL g)
{
if (Nodep->nextSibling == NULL)
Next = NULL;
else if (!Next)
else // if (!Next)
Next = new(g) DOMNODE(Doc, Nodep->nextSibling);
return Next;
@ -288,7 +288,7 @@ PXNODE DOMNODE::GetChild(PGLOBAL g)
{
if (Nodep->firstChild == NULL)
Children = NULL;
else if (!Children)
else // if (!Children)
Children = new(g) DOMNODE(Doc, Nodep->firstChild);
return Children;
@ -441,15 +441,27 @@ PXNODE DOMNODE::SelectSingleNode(PGLOBAL g, char *xp, PXNODE np)
/******************************************************************/
PXATTR DOMNODE::GetAttribute(PGLOBAL g, char *name, PXATTR ap)
{
MSXML2::IXMLDOMElementPtr ep = Nodep;
MSXML2::IXMLDOMAttributePtr atp = ep->getAttributeNode(name);
MSXML2::IXMLDOMElementPtr ep;
MSXML2::IXMLDOMNamedNodeMapPtr nmp;
MSXML2::IXMLDOMAttributePtr atp;
if (name) {
ep = Nodep;
atp = ep->getAttributeNode(name);
nmp = NULL;
} else {
nmp = Nodep->Getattributes();
atp = nmp->Getitem(0);
} // endif name
if (atp) {
if (ap) {
((PDOMATTR)ap)->Atrp = atp;
((PDOMATTR)ap)->Nmp = nmp;
((PDOMATTR)ap)->K = 0;
return ap;
} else
return new(g) DOMATTR(Doc, atp);
return new(g) DOMATTR(Doc, atp, nmp);
} else
return NULL;
@ -617,14 +629,85 @@ bool DOMNODELIST::DropItem(PGLOBAL g, int n)
/******************************************************************/
/* DOMATTR constructor. */
/******************************************************************/
DOMATTR::DOMATTR(PXDOC dp, MSXML2::IXMLDOMAttributePtr ap)
DOMATTR::DOMATTR(PXDOC dp, MSXML2::IXMLDOMAttributePtr ap,
MSXML2::IXMLDOMNamedNodeMapPtr nmp)
: XMLATTRIBUTE(dp)
{
Atrp = ap;
Nmp = nmp;
Ws = NULL;
Len = 0;
K = 0;
} // end of DOMATTR constructor
/******************************************************************/
/* Return the attribute name. */
/******************************************************************/
char *DOMATTR::GetName(PGLOBAL g)
{
if (!WideCharToMultiByte(CP_ACP, 0, Atrp->nodeName, -1,
Name, sizeof(Name), NULL, NULL)) {
strcpy(g->Message, MSG(NAME_CONV_ERR));
return NULL;
} // endif
return Name;
} // end of GetName
/******************************************************************/
/* Return the next attribute node. */
/* This funtion is implemented as needed by XMLColumns. */
/******************************************************************/
PXATTR DOMATTR::GetNext(PGLOBAL g)
{
if (!Nmp)
return NULL;
if (++K >= Nmp->Getlength()) {
Nmp->reset();
Nmp = NULL;
K = 0;
return NULL;
} // endif K
Atrp = Nmp->Getitem(K);
return this;
} // end of GetNext
/******************************************************************/
/* Return the content of a node and subnodes. */
/******************************************************************/
RCODE DOMATTR::GetText(PGLOBAL g, char *buf, int len)
{
RCODE rc = RC_OK;
if (!WideCharToMultiByte(CP_UTF8, 0, Atrp->text, -1,
buf, len, NULL, NULL)) {
DWORD lsr = GetLastError();
switch (lsr) {
case 0:
case ERROR_INSUFFICIENT_BUFFER: // 122L
sprintf(g->Message, "Truncated %s content", GetName(g));
rc = RC_INFO;
break;
case ERROR_NO_UNICODE_TRANSLATION: // 1113L
sprintf(g->Message, "Invalid character(s) in %s content",
GetName(g));
rc = RC_INFO;
break;
default:
sprintf(g->Message, "System error getting %s content",
GetName(g));
rc = RC_FX;
break;
} // endswitch
} // endif
return rc;
} // end of GetText
/******************************************************************/
/* Set the text content of an attribute. */
/******************************************************************/

19
storage/connect/domdoc.h

@ -122,15 +122,24 @@ class DOMATTR : public XMLATTRIBUTE {
friend class DOMDOC;
friend class DOMNODE;
public:
// Properties
virtual char *GetName(PGLOBAL g);
virtual PXATTR GetNext(PGLOBAL);
// Methods
virtual bool SetText(PGLOBAL g, char *txtp, int len);
virtual RCODE GetText(PGLOBAL g, char *bufp, int len);
virtual bool SetText(PGLOBAL g, char *txtp, int len);
protected:
// Constructor
DOMATTR(PXDOC dp, MSXML2::IXMLDOMAttributePtr ap);
DOMATTR(PXDOC dp, MSXML2::IXMLDOMAttributePtr ap,
MSXML2::IXMLDOMNamedNodeMapPtr nmp = NULL);
// Members
MSXML2::IXMLDOMAttributePtr Atrp;
WCHAR *Ws;
int Len;
MSXML2::IXMLDOMAttributePtr Atrp;
MSXML2::IXMLDOMNamedNodeMapPtr Nmp;
char Name[64];
WCHAR *Ws;
int Len;
long K;
}; // end of class DOMATTR

5
storage/connect/filamap.cpp

@ -5,7 +5,7 @@
/* */
/* COPYRIGHT: */
/* ---------- */
/* (C) Copyright to the author Olivier BERTRAND 2005-2014 */
/* (C) Copyright to the author Olivier BERTRAND 2005-2015 */
/* */
/* WHAT THIS PROGRAM DOES: */
/* ----------------------- */
@ -207,8 +207,7 @@ bool MAPFAM::OpenTableFile(PGLOBAL g)
/*******************************************************************/
fp = (PFBLOCK)PlugSubAlloc(g, NULL, sizeof(FBLOCK));
fp->Type = TYPE_FB_MAP;
fp->Fname = (char*)PlugSubAlloc(g, NULL, strlen(filename) + 1);
strcpy((char*)fp->Fname, filename);
fp->Fname = PlugDup(g, filename);
fp->Next = dbuserp->Openlist;
dbuserp->Openlist = fp;
fp->Count = 1;

1
storage/connect/filamap.h

@ -17,6 +17,7 @@ typedef class MAPFAM *PMAPFAM;
/* This is the variable file access method using file mapping. */
/***********************************************************************/
class DllExport MAPFAM : public TXTFAM {
friend class TDBJSON;
public:
// Constructor
MAPFAM(PDOSDEF tdp);

8
storage/connect/filamtxt.cpp

@ -5,7 +5,7 @@
/* */
/* COPYRIGHT: */
/* ---------- */
/* (C) Copyright to the author Olivier BERTRAND 2005-2014 */
/* (C) Copyright to the author Olivier BERTRAND 2005-2015 */
/* */
/* WHAT THIS PROGRAM DOES: */
/* ----------------------- */
@ -289,8 +289,7 @@ bool TXTFAM::AddListValue(PGLOBAL g, int type, void *val, PPARM *top)
pp->Intval = *(int*)val;
break;
// case TYPE_STRING:
// pp->Value = PlugSubAlloc(g, NULL, strlen((char*)val) + 1);
// strcpy((char*)pp->Value, (char*)val);
// pp->Value = PlugDup(g, (char*)val);
// break;
case TYPE_PCHAR:
pp->Value = val;
@ -325,8 +324,7 @@ int TXTFAM::StoreValues(PGLOBAL g, bool upd)
if (Tdbp->PrepareWriting(g))
return RC_FX;
buf = (char*)PlugSubAlloc(g, NULL, strlen(Tdbp->GetLine()) + 1);
strcpy(buf, Tdbp->GetLine());
buf = PlugDup(g, Tdbp->GetLine());
rc = AddListValue(g, TYPE_PCHAR, buf, &To_Upd);
} // endif upd

1
storage/connect/filamtxt.h

@ -42,6 +42,7 @@ class DllExport TXTFAM : public BLOCK {
virtual PTXF Duplicate(PGLOBAL g) = 0;
virtual bool GetUseTemp(void) {return false;}
virtual int GetDelRows(void) {return DelRows;}
PFBLOCK GetTo_Fb(void) {return To_Fb;}
int GetCurBlk(void) {return CurBlk;}
void SetTdbp(PTDBDOS tdbp) {Tdbp = tdbp;}
int GetBlock(void) {return Block;}

8
storage/connect/filamvct.cpp

@ -5,7 +5,7 @@
/* */
/* COPYRIGHT: */
/* ---------- */
/* (C) Copyright to the author Olivier BERTRAND 2005-2014 */
/* (C) Copyright to the author Olivier BERTRAND 2005-2015 */
/* */
/* WHAT THIS PROGRAM DOES: */
/* ----------------------- */
@ -1451,8 +1451,7 @@ bool VCMFAM::OpenTableFile(PGLOBAL g)
/*******************************************************************/
fp = (PFBLOCK)PlugSubAlloc(g, NULL, sizeof(FBLOCK));
fp->Type = TYPE_FB_MAP;
fp->Fname = (char*)PlugSubAlloc(g, NULL, strlen(filename) + 1);
strcpy((char*)fp->Fname, filename);
fp->Fname = PlugDup(g, filename);
fp->Next = dbuserp->Openlist;
dbuserp->Openlist = fp;
fp->Count = 1;
@ -2844,8 +2843,7 @@ bool VMPFAM::MapColumnFile(PGLOBAL g, MODE mode, int i)
/*******************************************************************/
fp = (PFBLOCK)PlugSubAlloc(g, NULL, sizeof(FBLOCK));
fp->Type = TYPE_FB_MAP;
fp->Fname = (char*)PlugSubAlloc(g, NULL, strlen(filename) + 1);
strcpy((char*)fp->Fname, filename);
fp->Fname = PlugDup(g, filename);
fp->Next = dup->Openlist;
dup->Openlist = fp;
fp->Count = 1;

157
storage/connect/ha_connect.cc

@ -130,10 +130,8 @@
#if defined(ODBC_SUPPORT)
#include "odbccat.h"
#endif // ODBC_SUPPORT
#if defined(MYSQL_SUPPORT)
#include "xtable.h"
#include "tabmysql.h"
#endif // MYSQL_SUPPORT
#include "filamdbf.h"
#include "tabxcl.h"
#include "tabfmt.h"
@ -147,7 +145,6 @@
#include "connect.h"
#include "user_connect.h"
#include "ha_connect.h"
#include "mycat.h"
#include "myutil.h"
#include "preparse.h"
#include "inihandl.h"
@ -171,7 +168,7 @@
#define JSONMAX 10 // JSON Default max grp size
extern "C" {
char version[]= "Version 1.03.0006 February 06, 2015";
char version[]= "Version 1.03.0006 April 12, 2015";
#if defined(WIN32)
char compver[]= "Version 1.03.0006 " __DATE__ " " __TIME__;
@ -211,6 +208,9 @@ extern "C" {
/***********************************************************************/
PQRYRES OEMColumns(PGLOBAL g, PTOS topt, char *tab, char *db, bool info);
PQRYRES VirColumns(PGLOBAL g, char *tab, char *db, bool info);
PQRYRES JSONColumns(PGLOBAL g, char *dp, const char *fn, char *objn,
int pretty, int lvl, int mxr, bool info);
PQRYRES XMLColumns(PGLOBAL g, char *dp, char *tab, PTOS topt, bool info);
void PushWarning(PGLOBAL g, THD *thd, int level);
bool CheckSelf(PGLOBAL g, TABLE_SHARE *s, const char *host,
const char *db, char *tab, const char *src, int port);
@ -1020,8 +1020,7 @@ char *GetListOption(PGLOBAL g, const char *opname,
} // endif pv
if (!stricmp(opname, key)) {
opval= (char*)PlugSubAlloc(g, NULL, strlen(val) + 1);
strcpy(opval, val);
opval= PlugDup(g, val);
break;
} else if (!pn)
break;
@ -1506,8 +1505,7 @@ PIXDEF ha_connect::GetIndexInfo(TABLE_SHARE *s)
// Now get index information
pn= (char*)s->keynames.type_names[n];
name= (char*)PlugSubAlloc(g, NULL, strlen(pn) + 1);
strcpy(name, pn); // This is probably unuseful
name= PlugDup(g, pn);
unique= (kp.flags & 1) != 0;
pkp= NULL;
@ -1517,8 +1515,7 @@ PIXDEF ha_connect::GetIndexInfo(TABLE_SHARE *s)
// Get the the key parts info
for (int k= 0; (unsigned)k < kp.user_defined_key_parts; k++) {
pn= (char*)kp.key_part[k].field->field_name;
name= (char*)PlugSubAlloc(g, NULL, strlen(pn) + 1);
strcpy(name, pn); // This is probably unuseful
name= PlugDup(g, pn);
// Allocate the key part description block
kpp= new(g) KPARTDEF(name, k + 1);
@ -2176,12 +2173,12 @@ int ha_connect::CheckRecord(PGLOBAL g, const uchar *oldbuf, uchar *newbuf)
/***********************************************************************/
/* Return the where clause for remote indexed read. */
/***********************************************************************/
bool ha_connect::MakeKeyWhere(PGLOBAL g, char *qry, OPVAL op, char *q,
bool ha_connect::MakeKeyWhere(PGLOBAL g, PSTRG qry, OPVAL op, char q,
const void *key, int klen)
{
const uchar *ptr;
uint rem, len, stlen; //, prtlen;
bool nq, b= false;
bool nq, oom, b= false;
Field *fp;
KEY *kfp;
KEY_PART_INFO *kpart;
@ -2193,7 +2190,7 @@ bool ha_connect::MakeKeyWhere(PGLOBAL g, char *qry, OPVAL op, char *q,
return true;
} // endif key
strcat(qry, " WHERE (");
oom= qry->Append(" WHERE (");
kfp= &table->key_info[active_index];
rem= kfp->user_defined_key_parts,
len= klen,
@ -2206,24 +2203,26 @@ bool ha_connect::MakeKeyWhere(PGLOBAL g, char *qry, OPVAL op, char *q,
nq= fp->str_needs_quotes();
if (b)
strcat(qry, " AND ");
oom|= qry->Append(" AND ");
else
b= true;
strcat(strncat(strcat(qry, q), fp->field_name, strlen(fp->field_name)), q);
oom|= qry->Append(q);
oom|= qry->Append((PSZ)fp->field_name);
oom|= qry->Append(q);
switch (op) {
case OP_EQ:
case OP_GT:
case OP_GE:
strcat(qry, GetValStr(op, false));
oom|= qry->Append((PSZ)GetValStr(op, false));
break;
default:
strcat(qry, " ??? ");
oom|= qry->Append(" ??? ");
} // endwitch op
if (nq)
strcat(qry, "'");
oom|= qry->Append('\'');
if (kpart->key_part_flag & HA_VAR_LENGTH_PART) {
String varchar;
@ -2231,17 +2230,17 @@ bool ha_connect::MakeKeyWhere(PGLOBAL g, char *qry, OPVAL op, char *q,
varchar.set_quick((char*) ptr+HA_KEY_BLOB_LENGTH,
var_length, &my_charset_bin);
strncat(qry, varchar.ptr(), varchar.length());
oom|= qry->Append(varchar.ptr(), varchar.length());
} else {
char strbuff[MAX_FIELD_WIDTH];
String str(strbuff, sizeof(strbuff), kpart->field->charset()), *res;
res= fp->val_str(&str, ptr);
strncat(qry, res->ptr(), res->length());
oom|= qry->Append(res->ptr(), res->length());
} // endif flag
if (nq)
strcat(qry, "'");
oom|= qry->Append('\'');
if (stlen >= len)
break;
@ -2254,8 +2253,10 @@ bool ha_connect::MakeKeyWhere(PGLOBAL g, char *qry, OPVAL op, char *q,
ptr+= stlen - MY_TEST(kpart->null_bit);
} // endfor kpart
strcat(qry, ")");
return false;
if ((oom|= qry->Append(")")))
strcpy(g->Message, "Out of memory");
return oom;
} // end of MakeKeyWhere
@ -2717,7 +2718,12 @@ PCFIL ha_connect::CheckCond(PGLOBAL g, PCFIL filp, AMT tty, Item *cond)
case MYSQL_TYPE_DATETIME:
if (tty == TYPE_AM_ODBC) {
strcat(body, "{ts '");
strcat(strncat(body, res->ptr(), res->length()), "'}");
strncat(body, res->ptr(), res->length());
if (res->length() < 19)
strcat(body, "1970-01-01 00:00:00" + res->length());
strcat(body, "'}");
break;
} // endif ODBC
@ -2742,6 +2748,10 @@ PCFIL ha_connect::CheckCond(PGLOBAL g, PCFIL filp, AMT tty, Item *cond)
case MYSQL_TYPE_DATETIME:
strcat(body, "{ts '");
strncat(body, res->ptr(), res->length());
if (res->length() < 19)
strcat(body, "1970-01-01 00:00:00" + res->length());
strcat(body, "'}");
break;
case MYSQL_TYPE_DATE:
@ -4137,6 +4147,10 @@ MODE ha_connect::CheckMode(PGLOBAL g, THD *thd,
break;
// } // endif partitioned
case SQLCOM_END:
// Met in procedures: IF(EXISTS(SELECT...
newmode= MODE_READ;
break;
default:
htrc("Unsupported sql_command=%d\n", thd_sql_command(thd));
strcpy(g->Message, "CONNECT Unsupported command");
@ -4738,9 +4752,9 @@ static char *encode(PGLOBAL g, const char *cnm)
@return
Return 0 if ok
*/
static bool add_field(String *sql, const char *field_name, int typ,
int len, int dec, char *key, uint tm, const char *rem,
char *dft, char *xtra, int flag, bool dbf, char v)
static bool add_field(String *sql, const char *field_name, int typ, int len,
int dec, char *key, uint tm, const char *rem, char *dft,
char *xtra, char *fmt, int flag, bool dbf, char v)
{
char var = (len > 255) ? 'V' : v;
bool q, error= false;
@ -4809,6 +4823,12 @@ static bool add_field(String *sql, const char *field_name, int typ,
error|= sql->append("'");
} // endif rem
if (fmt && *fmt) {
error|= sql->append(" FIELD_FORMAT='");
error|= sql->append_for_single_quote(fmt, strlen(fmt));
error|= sql->append("'");
} // endif flag
if (flag) {
error|= sql->append(" FLAG=");
error|= sql->append_ulonglong(flag);
@ -4952,12 +4972,12 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
const char *fncn= "?";
const char *user, *fn, *db, *host, *pwd, *sep, *tbl, *src;
const char *col, *ocl, *rnk, *pic, *fcl, *skc;
char *tab, *dsn, *shm, *dpath;
char *tab, *dsn, *shm, *dpath, *objn;
#if defined(WIN32)
char *nsp= NULL, *cls= NULL;
#endif // WIN32
int port= 0, hdr= 0, mxr __attribute__((unused))= 0, mxe= 0, rc= 0;
int cop __attribute__((unused)) = 0;
int cop __attribute__((unused))= 0, pty= 2, lrecl= 0, lvl= 0;
#if defined(ODBC_SUPPORT)
POPARM sop = NULL;
char *ucnc = NULL;
@ -4987,7 +5007,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
if (!g)
return HA_ERR_INTERNAL_ERROR;
user= host= pwd= tbl= src= col= ocl= pic= fcl= skc= rnk= dsn= NULL;
user= host= pwd= tbl= src= col= ocl= pic= fcl= skc= rnk= dsn= objn= NULL;
// Get the useful create options
ttp= GetTypeID(topt->type);
@ -5003,6 +5023,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
hdr= (int)topt->header;
tbl= topt->tablist;
col= topt->colist;
lrecl= (int)topt->lrecl;
if (topt->oplist) {
host= GetListOption(g, "host", topt->oplist, "localhost");
@ -5017,6 +5038,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
skc= GetListOption(g, "skipcol", topt->oplist, NULL);
rnk= GetListOption(g, "rankcol", topt->oplist, NULL);
pwd= GetListOption(g, "password", topt->oplist);
objn= GetListOption(g, "Object", topt->oplist, NULL);
#if defined(WIN32)
nsp= GetListOption(g, "namespace", topt->oplist);
cls= GetListOption(g, "class", topt->oplist);
@ -5034,6 +5056,8 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
#if defined(PROMPT_OK)
cop= atoi(GetListOption(g, "checkdsn", topt->oplist, "0"));
#endif // PROMPT_OK
pty= atoi(GetListOption(g,"Pretty", topt->oplist, "2"));
lvl= atoi(GetListOption(g,"Level", topt->oplist, "0"));
} else {
host= "localhost";
user= (ttp == TAB_ODBC ? NULL : "root");
@ -5077,8 +5101,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
goto err;
} // endif tbl
tab= (char*)PlugSubAlloc(g, NULL, strlen(tbl) + 1);
strcpy(tab, tbl);
tab= PlugDup(g, tbl);
if ((p= strchr(tab, ',')))
*p= 0;
@ -5139,7 +5162,6 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
ok= true;
break;
#if defined(MYSQL_SUPPORT)
case TAB_MYSQL:
ok= true;
@ -5179,14 +5201,15 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
ok= false;
break;
#endif // MYSQL_SUPPORT
#if defined(WIN32)
case TAB_WMI:
ok= true;
break;
#endif // WIN32
#if defined(PIVOT_SUPPORT)
case TAB_PIVOT:
supfnc= FNC_NO;
#endif // PIVOT_SUPPORT
case TAB_PRX:
case TAB_TBL:
case TAB_XCL:
@ -5204,6 +5227,16 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
else
strcpy(g->Message, "Missing OEM module or subtype");
break;
#if defined(LIBXML2_SUPPORT) || defined(DOMDOC_SUPPORT)
case TAB_XML:
#endif // LIBXML2_SUPPORT || DOMDOC_SUPPORT
case TAB_JSON:
if (!fn)
sprintf(g->Message, "Missing %s file name", topt->type);
else
ok= true;
break;
case TAB_VIR:
ok= true;
@ -5226,7 +5259,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
} // endif src
if (ok) {
char *cnm, *rem, *dft, *xtra, *key;
char *cnm, *rem, *dft, *xtra, *key, *fmt;
int i, len, prec, dec, typ, flg;
// if (cat)
@ -5278,12 +5311,10 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
break;
#endif // ODBC_SUPPORT
#if defined(MYSQL_SUPPORT)
case TAB_MYSQL:
qrp= MyColumns(g, thd, host, db, user, pwd, tab,
NULL, port, fnc == FNC_COL);
break;
#endif // MYSQL_SUPPORT
case TAB_CSV:
qrp= CSVColumns(g, dpath, fn, spc, qch, hdr, mxe, fnc == FNC_COL);
break;
@ -5309,12 +5340,22 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
} // endif OcrColumns
break;
#if defined(PIVOT_SUPPORT)
case TAB_PIVOT:
qrp= PivotColumns(g, tab, src, pic, fcl, skc, host, db, user, pwd, port);
break;
#endif // PIVOT_SUPPORT
case TAB_VIR:
qrp= VirColumns(g, tab, (char*)db, fnc == FNC_COL);
break;
case TAB_JSON:
qrp= JSONColumns(g, (char*)db, fn, objn, pty, lrecl, lvl, fnc == FNC_COL);
break;
#if defined(LIBXML2_SUPPORT) || defined(DOMDOC_SUPPORT)
case TAB_XML:
qrp= XMLColumns(g, (char*)db, tab, topt, fnc == FNC_COL);
break;
#endif // LIBXML2_SUPPORT || DOMDOC_SUPPORT
case TAB_OEM:
qrp= OEMColumns(g, topt, tab, (char*)db, fnc == FNC_COL);
break;
@ -5331,7 +5372,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
if (fnc != FNC_NO || src || ttp == TAB_PIVOT) {
// Catalog like table
for (crp= qrp->Colresp; !rc && crp; crp= crp->Next) {
cnm= encode(g, crp->Name);
cnm= (ttp == TAB_PIVOT) ? crp->Name : encode(g, crp->Name);
typ= crp->Type;
len= crp->Length;
dec= crp->Prec;
@ -5347,12 +5388,14 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
NOT_NULL_FLAG, "", flg, dbf, v);
#else // !NEW_WAY
if (add_field(&sql, cnm, typ, len, dec, NULL, NOT_NULL_FLAG,
NULL, NULL, NULL, flg, dbf, v))
NULL, NULL, NULL, NULL, flg, dbf, v))
rc= HA_ERR_OUT_OF_MEM;
#endif // !NEW_WAY
} // endfor crp
} else {
} else {
char *schem= NULL;
// Not a catalog table
if (!qrp->Nblin) {
if (tab)
@ -5368,7 +5411,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
typ= len= prec= dec= 0;
tm= NOT_NULL_FLAG;
cnm= (char*)"noname";
dft= xtra= key= NULL;
dft= xtra= key= fmt= NULL;
v= ' ';
#if defined(NEW_WAY)
rem= "";
@ -5407,6 +5450,9 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
if (crp->Kdata->GetIntValue(i))
tm= 0; // Nullable
break;
case FLD_FORMAT:
fmt= (crp->Kdata) ? crp->Kdata->GetCharValue(i) : NULL;
break;
case FLD_REM:
rem= crp->Kdata->GetCharValue(i);
@ -5433,6 +5479,19 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
key= crp->Kdata->GetCharValue(i);
break;
case FLD_SCHEM:
#if defined(ODBC_SUPPORT)
if (ttp == TAB_ODBC && crp->Kdata) {
if (schem && stricmp(schem, crp->Kdata->GetCharValue(i))) {
sprintf(g->Message,
"Several %s tables found, specify DBNAME", tab);
my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0));
goto err;
} else if (!schem)
schem= crp->Kdata->GetCharValue(i);
} // endif ttp
#endif // ODBC_SUPPORT
default:
break; // Ignore
} // endswitch Fld
@ -5485,7 +5544,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
tm, rem, 0, dbf, v);
#else // !NEW_WAY
if (add_field(&sql, cnm, typ, prec, dec, key, tm, rem, dft, xtra,
0, dbf, v))
fmt, 0, dbf, v))
rc= HA_ERR_OUT_OF_MEM;
#endif // !NEW_WAY
} // endfor i
@ -5754,6 +5813,18 @@ int ha_connect::create(const char *name, TABLE *table_arg,
} // endif type
if (type == TAB_JSON) {
int pretty= atoi(GetListOption(g, "Pretty", options->oplist, "2"));
if (!options->lrecl && pretty != 2) {
sprintf(g->Message, "LRECL must be specified for pretty=%d", pretty);
my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0));
rc= HA_ERR_INTERNAL_ERROR;
DBUG_RETURN(rc);
} // endif lrecl
} // endif type
// Check column types
for (field= table_arg->field; *field; field++) {
fp= *field;
@ -6545,7 +6616,7 @@ maria_declare_plugin(connect)
0x0103, /* version number (1.03) */
NULL, /* status variables */
connect_system_variables, /* system variables */
"1.03.0005", /* string version */
"1.03.0006", /* string version */
MariaDB_PLUGIN_MATURITY_BETA /* maturity */
}
maria_declare_plugin_end;

20
storage/connect/ha_connect.h

@ -1,4 +1,4 @@
/* Copyright (C) Olivier Bertrand 2004 - 2014
/* Copyright (C) Olivier Bertrand 2004 - 2015
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -26,6 +26,11 @@
#pragma interface /* gcc class implementation */
#endif
/****************************************************************************/
/* mycat.h contains the TOS, PTOS, ha_table_option_struct declarations. */
/****************************************************************************/
#include "mycat.h"
static char *strz(PGLOBAL g, LEX_STRING &ls);
/****************************************************************************/
@ -56,11 +61,7 @@ public:
oldopn= newopn= NULL;
oldpix= newpix= NULL;}
inline char *SetName(PGLOBAL g, char *name) {
char *nm= NULL;
if (name) {nm= (char*)PlugSubAlloc(g, NULL, strlen(name) + 1);
strcpy(nm, name);}
return nm;}
inline char *SetName(PGLOBAL g, char *name) {return PlugDup(g, name);}
bool oldsep; // Sepindex before create/alter
bool newsep; // Sepindex after create/alter
@ -72,7 +73,6 @@ public:
typedef class XCHK *PCHK;
typedef class user_connect *PCONNECT;
typedef struct ha_table_option_struct TOS, *PTOS;
typedef struct ha_field_option_struct FOS, *PFOS;
typedef struct ha_index_option_struct XOS, *PXOS;
@ -84,6 +84,9 @@ extern handlerton *connect_hton;
These can be specified in the CREATE TABLE:
CREATE TABLE ( ... ) {...here...}
*/
#if 0 // moved to mycat.h
typedef struct ha_table_option_struct TOS, *PTOS;
struct ha_table_option_struct {
const char *type;
const char *filename;
@ -115,6 +118,7 @@ struct ha_table_option_struct {
bool readonly;
bool sepindex;
};
#endif // 0
/**
structure for CREATE TABLE options (field options)
@ -239,7 +243,7 @@ public:
int CheckRecord(PGLOBAL g, const uchar *oldbuf, uchar *newbuf);
int ReadIndexed(uchar *buf, OPVAL op, const uchar* key= NULL,
uint key_len= 0);
bool MakeKeyWhere(PGLOBAL g, char *qry, OPVAL op, char *q,
bool MakeKeyWhere(PGLOBAL g, PSTRG qry, OPVAL op, char q,
const void *key, int klen);
inline char *Strz(LEX_STRING &ls);

4
storage/connect/json.cpp

@ -1,5 +1,5 @@
/*************** json CPP Declares Source Code File (.H) ***************/
/* Name: json.cpp Version 1.0 */
/* Name: json.cpp Version 1.1 */
/* */
/* (C) Copyright to the author Olivier BERTRAND 2014 - 2015 */
/* */
@ -1157,6 +1157,6 @@ void JVALUE::SetString(PGLOBAL g, PSZ s)
/***********************************************************************/
bool JVALUE::IsNull(void)
{
return (Jsp) ? Jsp->IsNull() : (Value) ? Value->IsNull() : true;
return (Jsp) ? Jsp->IsNull() : (Value) ? Value->IsZero() : true;
} // end of IsNull

534
storage/connect/json.h

@ -1,264 +1,270 @@
/**************** json H Declares Source Code File (.H) ****************/
/* Name: json.h Version 1.0 */
/* */
/* (C) Copyright to the author Olivier BERTRAND 2014 - 2015 */
/* */
/* This file contains the JSON classes declares. */
/***********************************************************************/
#include "value.h"
#if defined(_DEBUG)
#define X assert(false);
#else
#define X
#endif
enum JTYP {TYPE_STRG = 1,
TYPE_DBL = 2,
TYPE_BOOL = 4,
TYPE_INTG = 7,
TYPE_JSON = 12,
TYPE_JAR,
TYPE_JOB,
TYPE_JVAL};
class JOUT;
class JSON;
class JMAP;
class JVALUE;
class JOBJECT;
class JARRAY;
typedef class JPAIR *PJPR;
typedef class JSON *PJSON;
typedef class JVALUE *PJVAL;
typedef class JOBJECT *PJOB;
typedef class JARRAY *PJAR;
typedef struct {
char *str;
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);
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);
bool SerializeArray(JOUT *js, PJAR jarp, bool b);
bool SerializeObject(JOUT *js, PJOB jobp);
bool SerializeValue(JOUT *js, PJVAL jvp);
/***********************************************************************/
/* Class JOUT. Used by Serialize. */
/***********************************************************************/
class JOUT : public BLOCK {
public:
JOUT(PGLOBAL gp) : BLOCK() {g = gp;}
virtual bool WriteStr(const char *s) = 0;
virtual bool WriteChr(const char c) = 0;
virtual bool Escape(const char *s) = 0;
// Member
PGLOBAL g;
}; // end of class JOUT
/***********************************************************************/
/* Class JOUTSTR. Used to Serialize to a string. */
/***********************************************************************/
class JOUTSTR : public JOUT {
public:
JOUTSTR(PGLOBAL g);
virtual bool WriteStr(const char *s);
virtual bool WriteChr(const char c);
virtual bool Escape(const char *s);
// Member
char *Strp; // The serialized string
size_t N; // Position of next char
size_t Max; // String max size
}; // end of class JOUTSTR
/***********************************************************************/
/* Class JOUTFILE. Used to Serialize to a file. */
/***********************************************************************/
class JOUTFILE : public JOUT {
public:
JOUTFILE(PGLOBAL g, FILE *str) : JOUT(g) {Stream = str;}
virtual bool WriteStr(const char *s);
virtual bool WriteChr(const char c);
virtual bool Escape(const char *s);
// Member
FILE *Stream;
}; // end of class JOUTFILE
/***********************************************************************/
/* Class JOUTPRT. Used to Serialize to a pretty file. */
/***********************************************************************/
class JOUTPRT : public JOUTFILE {
public:
JOUTPRT(PGLOBAL g, FILE *str) : JOUTFILE(g, str) {M = 0; B = false;}
virtual bool WriteStr(const char *s);
virtual bool WriteChr(const char c);
// Member
int M;
bool B;
}; // end of class JOUTPRT
/***********************************************************************/
/* Class PAIR. The pairs of a json Object. */
/***********************************************************************/
class JPAIR : public BLOCK {
friend class JOBJECT;
friend PJOB ParseObject(PGLOBAL, int&, STRG&);
friend bool SerializeObject(JOUT *, PJOB);
public:
JPAIR(PSZ key) : BLOCK() {Key = key; Val = NULL; Next = NULL;}
protected:
PSZ Key; // This pair key name
PJVAL Val; // To the value of the pair
PJPR Next; // To the next pair
}; // end of class JPAIR
/***********************************************************************/
/* Class JSON. The base class for all other json classes. */
/***********************************************************************/
class JSON : public BLOCK {
public:
JSON(void) {Size = 0;}
int size(void) {return Size;}
virtual void Clear(void) {Size = 0;}
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 PJPR AddPair(PGLOBAL g, PSZ key) {X return NULL;}
virtual PJVAL GetValue(const char *key) {X return NULL;}
virtual PJOB GetObject(void) {X return NULL;}
virtual PJAR GetArray(void) {X 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 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 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 SetInteger(PGLOBAL g, int n) {X}
virtual void SetFloat(PGLOBAL g, double f) {X}
virtual bool DeleteValue(int i) {X return true;}
virtual bool IsNull(void) {X return true;}
protected:
int Size;
}; // end of class JSON
/***********************************************************************/
/* Class JOBJECT: contains a list of value pairs. */
/***********************************************************************/
class JOBJECT : public JSON {
friend PJOB ParseObject(PGLOBAL, int&, STRG&);
friend bool SerializeObject(JOUT *, PJOB);
public:
JOBJECT(void) : JSON() {First = Last = NULL;}
using JSON::GetValue;
using JSON::SetValue;
virtual void Clear(void) {First = Last = NULL; Size = 0;}
virtual JTYP GetType(void) {return TYPE_JOB;}
virtual PJPR AddPair(PGLOBAL g, PSZ key);
virtual PJOB GetObject(void) {return this;}
virtual PJVAL GetValue(const char* key);
virtual PSZ GetText(PGLOBAL g, PSZ text);
virtual void SetValue(PGLOBAL g, PJVAL jvp, PSZ key);
virtual bool IsNull(void);
protected:
PJPR First;
PJPR Last;
}; // end of class JOBJECT
/***********************************************************************/
/* Class JARRAY. */
/***********************************************************************/
class JARRAY : public JSON {
friend PJAR ParseArray(PGLOBAL, int&, STRG&);
public:
JARRAY(void) : JSON() {Alloc = 0; First = Last = NULL; Mvals = NULL;}
using JSON::GetValue;
using JSON::SetValue;
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 void InitArray(PGLOBAL g);
virtual PJVAL GetValue(int i);
virtual bool SetValue(PGLOBAL g, PJVAL jvp, int i);
virtual bool DeleteValue(int n);
virtual bool IsNull(void);
protected:
// Members
int Alloc; // The Mvals allocated size
PJVAL First; // Used when constructing
PJVAL Last; // Last constructed value
PJVAL *Mvals; // Allocated when finished
}; // end of class JARRAY
/***********************************************************************/
/* Class JVALUE. */
/***********************************************************************/
class JVALUE : public JSON {
friend class JARRAY;
friend PJVAL ParseValue(PGLOBAL, int&, STRG&);
friend bool SerializeValue(JOUT *, PJVAL);
public:
JVALUE(void) : JSON()
{Jsp = NULL; Value = NULL; Next = NULL; Del = false;}
JVALUE(PJSON jsp) : JSON()
{Jsp = jsp; Value = NULL; Next = NULL; Del = false;}
JVALUE(PGLOBAL g, PVAL valp);
using JSON::GetValue;
using JSON::SetValue;
virtual void Clear(void)
{Jsp = NULL; Value = NULL; Next = NULL; Del = false; Size = 0;}
virtual JTYP GetType(void) {return TYPE_JVAL;}
virtual JTYP GetValType(void);
virtual PJOB GetObject(void);
virtual PJAR GetArray(void);
virtual PVAL GetValue(void) {return Value;}
virtual PJSON GetJson(void) {return (Jsp ? Jsp : this);}
virtual int GetInteger(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 SetInteger(PGLOBAL g, int n);
virtual void SetFloat(PGLOBAL g, double f);
virtual bool IsNull(void);
protected:
PJSON Jsp; // To the json value
PVAL Value; // The numeric value
PJVAL Next; // Next value in array
bool Del; // True when deleted
}; // end of class JVALUE
/**************** json H Declares Source Code File (.H) ****************/
/* Name: json.h Version 1.1 */
/* */
/* (C) Copyright to the author Olivier BERTRAND 2014 - 2015 */
/* */
/* This file contains the JSON classes declares. */
/***********************************************************************/
#include "value.h"
#if defined(_DEBUG)
#define X assert(false);
#else
#define X
#endif
enum JTYP {TYPE_STRG = 1,
TYPE_DBL = 2,
TYPE_BOOL = 4,
TYPE_INTG = 7,
TYPE_JSON = 12,
TYPE_JAR,
TYPE_JOB,
TYPE_JVAL};
class JOUT;
class JSON;
class JMAP;
class JVALUE;
class JOBJECT;
class JARRAY;
typedef class JPAIR *PJPR;
typedef class JSON *PJSON;
typedef class JVALUE *PJVAL;
typedef class JOBJECT *PJOB;
typedef class JARRAY *PJAR;
typedef struct {
char *str;
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);
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);
bool SerializeArray(JOUT *js, PJAR jarp, bool b);
bool SerializeObject(JOUT *js, PJOB jobp);
bool SerializeValue(JOUT *js, PJVAL jvp);
/***********************************************************************/
/* Class JOUT. Used by Serialize. */
/***********************************************************************/
class JOUT : public BLOCK {
public:
JOUT(PGLOBAL gp) : BLOCK() {g = gp;}
virtual bool WriteStr(const char *s) = 0;
virtual bool WriteChr(const char c) = 0;
virtual bool Escape(const char *s) = 0;
// Member
PGLOBAL g;
}; // end of class JOUT
/***********************************************************************/
/* Class JOUTSTR. Used to Serialize to a string. */
/***********************************************************************/
class JOUTSTR : public JOUT {
public:
JOUTSTR(PGLOBAL g);
virtual bool WriteStr(const char *s);
virtual bool WriteChr(const char c);
virtual bool Escape(const char *s);
// Member
char *Strp; // The serialized string
size_t N; // Position of next char
size_t Max; // String max size
}; // end of class JOUTSTR
/***********************************************************************/
/* Class JOUTFILE. Used to Serialize to a file. */
/***********************************************************************/
class JOUTFILE : public JOUT {
public:
JOUTFILE(PGLOBAL g, FILE *str) : JOUT(g) {Stream = str;}
virtual bool WriteStr(const char *s);
virtual bool WriteChr(const char c);
virtual bool Escape(const char *s);
// Member
FILE *Stream;
}; // end of class JOUTFILE
/***********************************************************************/
/* Class JOUTPRT. Used to Serialize to a pretty file. */
/***********************************************************************/
class JOUTPRT : public JOUTFILE {
public:
JOUTPRT(PGLOBAL g, FILE *str) : JOUTFILE(g, str) {M = 0; B = false;}
virtual bool WriteStr(const char *s);
virtual bool WriteChr(const char c);
// Member
int M;
bool B;
}; // end of class JOUTPRT
/***********************************************************************/
/* Class PAIR. The pairs of a json Object. */
/***********************************************************************/
class JPAIR : public BLOCK {
friend class JOBJECT;
friend PJOB ParseObject(PGLOBAL, int&, STRG&);
friend bool SerializeObject(JOUT *, PJOB);
public:
JPAIR(PSZ key) : BLOCK() {Key = key; Val = NULL; Next = NULL;}
inline PSZ GetKey(void) {return Key;}
inline PJVAL GetVal(void) {return Val;}
inline PJPR GetNext(void) {return Next;}
protected:
PSZ Key; // This pair key name
PJVAL Val; // To the value of the pair
PJPR Next; // To the next pair
}; // end of class JPAIR
/***********************************************************************/
/* Class JSON. The base class for all other json classes. */
/***********************************************************************/
class JSON : public BLOCK {
public:
JSON(void) {Size = 0;}
int size(void) {return Size;}
virtual void Clear(void) {Size = 0;}
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 PJPR AddPair(PGLOBAL g, PSZ key) {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 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 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 SetInteger(PGLOBAL g, int n) {X}
virtual void SetFloat(PGLOBAL g, double f) {X}
virtual bool DeleteValue(int i) {X return true;}
virtual bool IsNull(void) {X return true;}
protected:
int Size;
}; // end of class JSON
/***********************************************************************/
/* Class JOBJECT: contains a list of value pairs. */
/***********************************************************************/
class JOBJECT : public JSON {
friend PJOB ParseObject(PGLOBAL, int&, STRG&);
friend bool SerializeObject(JOUT *, PJOB);
public:
JOBJECT(void) : JSON() {First = Last = NULL;}
using JSON::GetValue;
using JSON::SetValue;
virtual void Clear(void) {First = Last = NULL; Size = 0;}
virtual JTYP GetType(void) {return TYPE_JOB;}
virtual PJPR GetFirst(void) {return First;}
virtual PJPR AddPair(PGLOBAL g, PSZ key);
virtual PJOB GetObject(void) {return this;}
virtual PJVAL GetValue(const char* key);
virtual PSZ GetText(PGLOBAL g, PSZ text);
virtual void SetValue(PGLOBAL g, PJVAL jvp, PSZ key);
virtual bool IsNull(void);
protected:
PJPR First;
PJPR Last;
}; // end of class JOBJECT
/***********************************************************************/
/* Class JARRAY. */
/***********************************************************************/
class JARRAY : public JSON {
friend PJAR ParseArray(PGLOBAL, int&, STRG&);
public:
JARRAY(void) : JSON() {Alloc = 0; First = Last = NULL; Mvals = NULL;}
using JSON::GetValue;
using JSON::SetValue;
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 void InitArray(PGLOBAL g);
virtual PJVAL GetValue(int i);
virtual bool SetValue(PGLOBAL g, PJVAL jvp, int i);
virtual bool DeleteValue(int n);
virtual bool IsNull(void);
protected:
// Members
int Alloc; // The Mvals allocated size
PJVAL First; // Used when constructing
PJVAL Last; // Last constructed value
PJVAL *Mvals; // Allocated when finished
}; // end of class JARRAY
/***********************************************************************/
/* Class JVALUE. */
/***********************************************************************/
class JVALUE : public JSON {
friend class JARRAY;
friend PJVAL ParseValue(PGLOBAL, int&, STRG&);
friend bool SerializeValue(JOUT *, PJVAL);
public:
JVALUE(void) : JSON()
{Jsp = NULL; Value = NULL; Next = NULL; Del = false;}
JVALUE(PJSON jsp) : JSON()
{Jsp = jsp; Value = NULL; Next = NULL; Del = false;}
JVALUE(PGLOBAL g, PVAL valp);
using JSON::GetValue;
using JSON::SetValue;
virtual void Clear(void)
{Jsp = NULL; Value = NULL; Next = NULL; Del = false; Size = 0;}
virtual JTYP GetType(void) {return TYPE_JVAL;}
virtual JTYP GetValType(void);
virtual PJOB GetObject(void);
virtual PJAR GetArray(void);
virtual PVAL GetValue(void) {return Value;}
virtual PJSON GetJson(void) {return (Jsp ? Jsp : this);}
virtual int GetInteger(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 SetInteger(PGLOBAL g, int n);
virtual void SetFloat(PGLOBAL g, double f);
virtual bool IsNull(void);
protected:
PJSON Jsp; // To the json value
PVAL Value; // The numeric value
PJVAL Next; // Next value in array
bool Del; // True when deleted
}; // end of class JVALUE

71
storage/connect/libdoc.cpp

@ -1,6 +1,6 @@
/******************************************************************/
/* Implementation of XML document processing using libxml2 */
/* Author: Olivier Bertrand 2007-2013 */
/* Author: Olivier Bertrand 2007-2015 */
/******************************************************************/
#include "my_global.h"
#include <string.h>
@ -162,10 +162,12 @@ class XML2ATTR : public XMLATTRIBUTE {
friend class XML2NODE;
public:
// Properties
//virtual char *GetText(void);
virtual char *GetName(PGLOBAL g) {return (char*)Atrp->name;}
virtual PXATTR GetNext(PGLOBAL g);
// Methods
virtual bool SetText(PGLOBAL g, char *txtp, int len);
virtual RCODE GetText(PGLOBAL g, char *bufp, int len);
virtual bool SetText(PGLOBAL g, char *txtp, int len);
protected:
// Constructor
@ -408,8 +410,7 @@ PFBLOCK LIBXMLDOC::LinkXblock(PGLOBAL g, MODE m, int rc, char *fn)
xp->Next = (PX2BLOCK)dup->Openlist;
dup->Openlist = (PFBLOCK)xp;
xp->Type = TYPE_FB_XML2;
xp->Fname = (LPCSTR)PlugSubAlloc(g, NULL, strlen(fn) + 1);
strcpy((char*)xp->Fname, fn);
xp->Fname = (LPCSTR)PlugDup(g, fn);
xp->Count = 1;
xp->Length = (m == MODE_READ) ? 1 : 0;
xp->Retcode = rc;
@ -813,7 +814,7 @@ PXNODE XML2NODE::GetNext(PGLOBAL g)
if (!Nodep->next)
Next = NULL;
else if (!Next)
else // if (!Next)
Next = new(g) XML2NODE(Doc, Nodep->next);
return Next;
@ -829,7 +830,7 @@ PXNODE XML2NODE::GetChild(PGLOBAL g)
if (!Nodep->children)
Children = NULL;
else if (!Children)
else // if (!Children)
Children = new(g) XML2NODE(Doc, Nodep->children);
return Children;
@ -979,10 +980,16 @@ PXNODE XML2NODE::SelectSingleNode(PGLOBAL g, char *xp, PXNODE np)
/******************************************************************/
PXATTR XML2NODE::GetAttribute(PGLOBAL g, char *name, PXATTR ap)
{
xmlAttrPtr atp;
if (trace)
htrc("GetAttribute: %s\n", name);
htrc("GetAttribute: %s\n", SVP(name));
if (name)
atp = xmlHasProp(Nodep, BAD_CAST name);
else
atp = Nodep->properties;
xmlAttrPtr atp = xmlHasProp(Nodep, BAD_CAST name);
if (atp) {
if (ap) {
@ -1210,6 +1217,52 @@ XML2ATTR::XML2ATTR(PXDOC dp, xmlAttrPtr ap, xmlNodePtr np)
Parent = np;
} // end of XML2ATTR constructor
/******************************************************************/
/* Return the next sibling of the attribute. */
/******************************************************************/
PXATTR XML2ATTR::GetNext(PGLOBAL g)
{
if (trace)
htrc("Attr GetNext\n");
if (!Atrp->next)
return NULL;
else
return new(g) XML2ATTR(Doc, Atrp->next, Atrp->parent);
} // end of GetNext
/******************************************************************/
/* Return the text of an attribute. */
/******************************************************************/
RCODE XML2ATTR::GetText(PGLOBAL g, char *buf, int len)
{
RCODE rc = RC_OK;
xmlChar *txt;
if (trace)
htrc("GetText\n");
if ((txt = xmlGetProp(Atrp->parent, Atrp->name))) {
// Copy the text to the buffer
if (strlen((char*)txt) >= (unsigned)len) {
memcpy(buf, txt, len - 1);
buf[len - 1] = 0;
sprintf(g->Message, "Truncated %s content", Atrp->name);
rc = RC_INFO;
} else
strcpy(buf, (const char*)txt);
xmlFree(txt);
} else
*buf = '\0';
if (trace)
htrc("GetText: %s\n", buf);
return rc;
} // end of GetText
/******************************************************************/
/* Set the content of an attribute. */
/******************************************************************/

13
storage/connect/mycat.cc

@ -74,13 +74,8 @@
#include "tabxcl.h"
#include "tabtbl.h"
#include "taboccur.h"
#if defined(XML_SUPPORT)
#include "tabxml.h"
#endif // XML_SUPPORT
#include "tabmul.h"
#if defined(MYSQL_SUPPORT)
#include "tabmysql.h"
#endif // MYSQL_SUPPORT
#if defined(ODBC_SUPPORT)
#define NODBC
#include "tabodbc.h"
@ -91,7 +86,9 @@
#include "tabvir.h"
#include "tabjson.h"
#include "ha_connect.h"
#include "mycat.h"
#if defined(XML_SUPPORT)
#include "tabxml.h"
#endif // XML_SUPPORT
/***********************************************************************/
/* Extern static variables. */
@ -122,10 +119,8 @@ TABTYPE GetTypeID(const char *type)
#ifdef ODBC_SUPPORT
: (!stricmp(type, "ODBC")) ? TAB_ODBC
#endif
#ifdef MYSQL_SUPPORT
: (!stricmp(type, "MYSQL")) ? TAB_MYSQL
: (!stricmp(type, "MYPRX")) ? TAB_MYSQL
#endif
: (!stricmp(type, "DIR")) ? TAB_DIR
#ifdef WIN32
: (!stricmp(type, "MAC")) ? TAB_MAC
@ -537,9 +532,7 @@ PRELDEF MYCAT::MakeTableDesc(PGLOBAL g, LPCSTR name, LPCSTR am)
case TAB_XCL: tdp= new(g) XCLDEF; break;
case TAB_PRX: tdp= new(g) PRXDEF; break;
case TAB_OCCUR: tdp= new(g) OCCURDEF; break;
#if defined(MYSQL_SUPPORT)
case TAB_MYSQL: tdp= new(g) MYSQLDEF; break;
#endif // MYSQL_SUPPORT
#if defined(PIVOT_SUPPORT)
case TAB_PIVOT: tdp= new(g) PIVOTDEF; break;
#endif // PIVOT_SUPPORT

40
storage/connect/mycat.h

@ -24,6 +24,46 @@
#include "block.h"
#include "catalog.h"
typedef struct ha_table_option_struct TOS, *PTOS;
/**
structure for CREATE TABLE options (table options)
These can be specified in the CREATE TABLE:
CREATE TABLE ( ... ) {...here...}
*/
struct ha_table_option_struct {
const char *type;
const char *filename;
const char *optname;
const char *tabname;
const char *tablist;
const char *dbname;
const char *separator;
//const char *connect;
const char *qchar;
const char *module;
const char *subtype;
const char *catfunc;
const char *srcdef;
const char *colist;
const char *oplist;
const char *data_charset;
ulonglong lrecl;
ulonglong elements;
//ulonglong estimate;
ulonglong multiple;
ulonglong header;
ulonglong quoted;
ulonglong ending;
ulonglong compressed;
bool mapped;
bool huge;
bool split;
bool readonly;
bool sepindex;
};
// Possible value for catalog functions
#define FNC_NO (1 << 0) // Not a catalog table
#define FNC_COL (1 << 1) // Column catalog function

18
storage/connect/mysql-test/connect/r/json.result

@ -15,7 +15,7 @@ DATEPUB int(4)
) ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='biblio.json';
SELECT * FROM t1;
ISBN LANG SUBJECT AUTHOR TITLE TRANSLATION TRANSLATOR PUBLISHER DATEPUB
9782212090819 fr applications Jean-Christophe Bernadac Construire une application XML Eyrolles Paris 1999
9782212090819 fr applications Jean-Christophe Bernadac Construire une application XML NULL NULL Eyrolles Paris 1999
9782840825685 fr applications William J. Pardi XML en Action adapté de l'anglais par James Guerin Microsoft Press Paris 1999
DROP TABLE t1;
#
@ -37,7 +37,7 @@ Year int(4) FIELD_FORMAT='DATEPUB'
ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='biblio.json';
SELECT * FROM t1;
ISBN Language Subject Authors Title Translation Translator Publisher Location Year
9782212090819 fr applications 2 Construire une application XML Eyrolles Paris 1999
9782212090819 fr applications 2 Construire une application XML NULL NULL Eyrolles Paris 1999
9782840825685 fr applications 1 XML en Action adapté de l'anglais par James Guerin Microsoft Press Paris 1999
DROP TABLE t1;
#
@ -60,7 +60,7 @@ Year int(4) FIELD_FORMAT='DATEPUB'
ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='biblio.json';
SELECT * FROM t1;
ISBN Language Subject AuthorFN AuthorLN Title Translation Translator Publisher Location Year
9782212090819 fr applications Jean-Christophe and François Bernadac and Knab Construire une application XML Eyrolles Paris 1999
9782212090819 fr applications Jean-Christophe and François Bernadac and Knab Construire une application XML NULL NULL Eyrolles Paris 1999
9782840825685 fr applications William J. Pardi XML en Action adapté de l'anglais par James Guerin Microsoft Press Paris 1999
DROP TABLE t1;
#
@ -83,14 +83,14 @@ Year int(4) FIELD_FORMAT='DATEPUB'
ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='biblio.json';
SELECT * FROM t1;
ISBN Language Subject AuthorFN AuthorLN Title Translation Translator Publisher Location Year
9782212090819 fr applications Jean-Christophe Bernadac Construire une application XML Eyrolles Paris 1999
9782212090819 fr applications François Knab Construire une application XML Eyrolles Paris 1999
9782212090819 fr applications Jean-Christophe Bernadac Construire une application XML NULL NULL Eyrolles Paris 1999
9782212090819 fr applications François Knab Construire une application XML NULL NULL Eyrolles Paris 1999
9782840825685 fr applications William J. Pardi XML en Action adapté de l'anglais par James Guerin Microsoft Press Paris 1999
UPDATE t1 SET AuthorFN = 'Philippe' WHERE AuthorLN = 'Knab';
SELECT * FROM t1 WHERE ISBN = '9782212090819';
ISBN Language Subject AuthorFN AuthorLN Title Translation Translator Publisher Location Year
9782212090819 fr applications Philippe Bernadac Construire une application XML Eyrolles Paris 1999
9782212090819 fr applications François Knab Construire une application XML Eyrolles Paris 1999
9782212090819 fr applications Philippe Bernadac Construire une application XML NULL NULL Eyrolles Paris 1999
9782212090819 fr applications François Knab Construire une application XML NULL NULL Eyrolles Paris 1999
#
# To add an author a new table must be created
#
@ -104,8 +104,8 @@ William J. Pardi
INSERT INTO t2 VALUES('Charles','Dickens');
SELECT * FROM t1;
ISBN Language Subject AuthorFN AuthorLN Title Translation Translator Publisher Location Year
9782212090819 fr applications Philippe Bernadac Construire une application XML Eyrolles Paris 1999
9782212090819 fr applications François Knab Construire une application XML Eyrolles Paris 1999
9782212090819 fr applications Philippe Bernadac Construire une application XML NULL NULL Eyrolles Paris 1999
9782212090819 fr applications François Knab Construire une application XML NULL NULL Eyrolles Paris 1999
9782840825685 fr applications William J. Pardi XML en Action adapté de l'anglais par James Guerin Microsoft Press Paris 1999
9782840825685 fr applications Charles Dickens XML en Action adapté de l'anglais par James Guerin Microsoft Press Paris 1999
DROP TABLE t1;

11
storage/connect/odbconn.cpp

@ -1,5 +1,5 @@
/************ Odbconn C++ Functions Source Code File (.CPP) ************/
/* Name: ODBCONN.CPP Version 2.1 */
/* Name: ODBCONN.CPP Version 2.2 */
/* */
/* (C) Copyright to the author Olivier BERTRAND 1998-2015 */
/* */
@ -867,8 +867,7 @@ bool DBX::BuildErrorMessage(ODBConn* pdb, HSTMT hstmt)
for (int i = 0; i < MAX_NUM_OF_MSG
&& (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO)
&& strcmp((char*)state, "00000"); i++) {
m_ErrMsg[i] = (PSZ)PlugSubAlloc(g, NULL, strlen((char*)msg) + 1);
strcpy(m_ErrMsg[i], (char*)msg);
m_ErrMsg[i] = (PSZ)PlugDup(g, (char*)msg);
if (trace)
htrc("%s: %s, Native=%d\n", state, msg, native);
@ -882,8 +881,7 @@ bool DBX::BuildErrorMessage(ODBConn* pdb, HSTMT hstmt)
} else {
snprintf((char*)msg, SQL_MAX_MESSAGE_LENGTH + 1, "%s: %s", m_Msg,
MSG(BAD_HANDLE_VAL));
m_ErrMsg[0] = (PSZ)PlugSubAlloc(g, NULL, strlen((char*)msg) + 1);
strcpy(m_ErrMsg[0], (char*)msg);
m_ErrMsg[0] = (PSZ)PlugDup(g, (char*)msg);
if (trace)
htrc("%s: rc=%hd\n", SVP(m_ErrMsg[0]), m_RC);
@ -1012,8 +1010,7 @@ PSZ ODBConn::GetStringInfo(ushort infotype)
// *buffer = '\0';
} // endif rc
p = (char *)PlugSubAlloc(m_G, NULL, strlen(buffer) + 1);
strcpy(p, buffer);
p = PlugDup(m_G, buffer);
return p;
} // end of GetStringInfo

10
storage/connect/plgdbsem.h

@ -1,7 +1,7 @@
/************** PlgDBSem H Declares Source Code File (.H) **************/
/* Name: PLGDBSEM.H Version 3.6 */
/* */
/* (C) Copyright to the author Olivier BERTRAND 1998-2014 */
/* (C) Copyright to the author Olivier BERTRAND 1998-2015 */
/* */
/* This file contains the PlugDB++ application type definitions. */
/***********************************************************************/
@ -504,9 +504,10 @@ enum XFLD {FLD_NO = 0, /* Not a field definition item */
FLD_EXTRA = 13, /* Field extra info */
FLD_PRIV = 14, /* Field priviledges */
FLD_DATEFMT = 15, /* Field date format */
FLD_CAT = 16, /* Table catalog */
FLD_SCHEM = 17, /* Table schema */
FLD_TABNAME = 18}; /* Column Table name */
FLD_FORMAT = 16, /* Field format */
FLD_CAT = 17, /* Table catalog */
FLD_SCHEM = 18, /* Table schema */
FLD_TABNAME = 19}; /* Column Table name */
/***********************************************************************/
/* Result of last SQL noconv query. */
@ -584,6 +585,7 @@ DllExport PCATLG PlgGetCatalog(PGLOBAL g, bool jump = true);
DllExport bool PlgSetXdbPath(PGLOBAL g, PSZ, PSZ, char *, int, char *, int);
DllExport void PlgDBfree(MBLOCK&);
DllExport void *PlgDBSubAlloc(PGLOBAL g, void *memp, size_t size);
DllExport char *PlgDBDup(PGLOBAL g, const char *str);
DllExport void *PlgDBalloc(PGLOBAL, void *, MBLOCK&);
DllExport void *PlgDBrealloc(PGLOBAL, void *, MBLOCK&, size_t);
DllExport void NewPointer(PTABS, void *, void *);

25
storage/connect/plgdbutl.cpp

@ -5,7 +5,7 @@
/* */
/* COPYRIGHT: */
/* ---------- */
/* (C) Copyright to the author Olivier BERTRAND 1998-2014 */
/* (C) Copyright to the author Olivier BERTRAND 1998-2015 */
/* */
/* WHAT THIS PROGRAM DOES: */
/* ----------------------- */
@ -294,8 +294,7 @@ PQRYRES PlgAllocResult(PGLOBAL g, int ncol, int maxres, int ids,
#else // !XMSG
GetRcString(ids + crp->Ncol, cname, sizeof(cname));
#endif // !XMSG
crp->Name = (PSZ)PlugSubAlloc(g, NULL, strlen(cname) + 1);
strcpy(crp->Name, cname);
crp->Name = (PSZ)PlugDup(g, cname);
} else
crp->Name = NULL; // Will be set by caller
@ -853,8 +852,7 @@ FILE *PlugOpenFile(PGLOBAL g, LPCSTR fname, LPCSTR ftype)
htrc(" fp=%p\n", fp);
// fname may be in volatile memory such as stack
fp->Fname = (char*)PlugSubAlloc(g, NULL, strlen(fname) + 1);
strcpy((char*)fp->Fname, fname);
fp->Fname = PlugDup(g, fname);
fp->Count = 1;
fp->Type = TYPE_FB_FILE;
fp->File = fop;
@ -1400,6 +1398,23 @@ void *PlgDBSubAlloc(PGLOBAL g, void *memp, size_t size)
return (memp);
} // end of PlgDBSubAlloc
/***********************************************************************/
/* Program for sub-allocating and copying a string in a storage area. */
/***********************************************************************/
char *PlgDBDup(PGLOBAL g, const char *str)
{
if (str) {
char *sm = (char*)PlgDBSubAlloc(g, NULL, strlen(str) + 1);
if (sm)
strcpy(sm, str);
return sm;
} else
return NULL;
} // end of PlgDBDup
/***********************************************************************/
/* PUTOUT: Plug DB object typing routine. */
/***********************************************************************/

15
storage/connect/plgxml.h

@ -1,5 +1,5 @@
/******************************************************************/
/* Dual XML implementation base classes defines. */
/* Dual XML implementation base classes defines. */
/******************************************************************/
#if !defined(BASE_BUFFER_SIZE)
enum ElementType { // libxml2
@ -43,7 +43,7 @@ enum NodeType { // MS DOM
NODE_NOTATION = 12};
#endif // !NODE_TYPE_LIST
typedef class XMLDOCUMENT *PXDOC; // Document
typedef class XMLDOCUMENT *PXDOC; // Document
typedef class XMLNODE *PXNODE; // Node (Element)
typedef class XMLNODELIST *PXLIST; // Node list
typedef class XMLATTRIBUTE *PXATTR; // Attribute
@ -93,9 +93,9 @@ class XMLDOCUMENT : public BLOCK {
bool MakeNSlist(PGLOBAL g);
// Members
PNS Namespaces; /* To the namespaces */
PNS Namespaces; /* To the namespaces */
char *Encoding; /* The document encoding */
char *Nslist; /* Namespace list */
char *Nslist; /* Namespace list */
char *DefNs; /* Default namespace */
}; // end of class XMLDOCUMENT
@ -109,6 +109,7 @@ class XMLNODE : public BLOCK {
virtual int GetType(void) = 0;
virtual PXNODE GetNext(PGLOBAL) = 0;
virtual PXNODE GetChild(PGLOBAL) = 0;
virtual int GetLen(void) {return Len;}
// Methods
virtual RCODE GetContent(PGLOBAL, char *, int) = 0;
@ -163,10 +164,12 @@ class XMLNODELIST : public BLOCK {
class XMLATTRIBUTE : public BLOCK {
public:
// Properties
//virtual char *GetText(void) = 0;
virtual char *GetName(PGLOBAL) = 0;
virtual PXATTR GetNext(PGLOBAL) = 0;
// Methods
virtual bool SetText(PGLOBAL, char *, int) = 0;
virtual RCODE GetText(PGLOBAL, char *, int) = 0;
virtual bool SetText(PGLOBAL, char *, int) = 0;
protected:
// Constructor

26
storage/connect/plugutil.c

@ -6,7 +6,7 @@
/* */
/* COPYRIGHT: */
/* ---------- */
/* (C) Copyright to the author Olivier BERTRAND 1993-2014 */
/* (C) Copyright to the author Olivier BERTRAND 1993-2015 */
/* */
/* WHAT THIS PROGRAM DOES: */
/* ----------------------- */
@ -228,7 +228,6 @@ BOOL PlugIsAbsolutePath(LPCSTR path)
#endif
}
/***********************************************************************/
/* Set the full path of a file relatively to a given path. */
/* Note: this routine is not really implemented for Unix. */
@ -385,8 +384,7 @@ char *PlugReadMessage(PGLOBAL g, int mid, char *m)
err:
if (g) {
// Called by STEP
msg = (char *)PlugSubAlloc(g, NULL, strlen(stmsg) + 1);
strcpy(msg, stmsg);
msg = PlugDup(g, stmsg);
} else // Called by MSG or PlgGetErrorMsg
msg = stmsg;
@ -421,8 +419,7 @@ char *PlugGetMessage(PGLOBAL g, int mid)
if (g) {
// Called by STEP
msg = (char *)PlugSubAlloc(g, NULL, strlen(stmsg) + 1);
strcpy(msg, stmsg);
msg = PlugDup(g, stmsg);
} else // Called by MSG or PlgGetErrorMsg
msg = stmsg;
@ -536,6 +533,22 @@ void *PlugSubAlloc(PGLOBAL g, void *memp, size_t size)
return (memp);
} /* end of PlugSubAlloc */
/***********************************************************************/
/* Program for sub-allocating and copying a string in a storage area. */
/***********************************************************************/
char *PlugDup(PGLOBAL g, const char *str)
{
if (str) {
char *sm = (char*)PlugSubAlloc(g, NULL, strlen(str) + 1);
strcpy(sm, str);
return sm;
} else
return NULL;
} // end of PlugDup
#if 0
/***********************************************************************/
/* This routine suballocate a copy of the passed string. */
/***********************************************************************/
@ -552,6 +565,7 @@ char *PlugDup(PGLOBAL g, const char *str)
return(buf);
} /* end of PlugDup */
#endif // 0
/***********************************************************************/
/* This routine makes a pointer from an offset to a memory pointer. */

44
storage/connect/reldef.cpp

@ -1,11 +1,11 @@
/************* RelDef CPP Program Source Code File (.CPP) **************/
/* PROGRAM NAME: REFDEF */
/* PROGRAM NAME: RELDEF */
/* ------------- */
/* Version 1.4 */
/* */
/* COPYRIGHT: */
/* ---------- */
/* (C) Copyright to the author Olivier BERTRAND 2004-2014 */
/* (C) Copyright to the author Olivier BERTRAND 2004-2015 */
/* */
/* WHAT THIS PROGRAM DOES: */
/* ----------------------- */
@ -35,7 +35,6 @@
/***********************************************************************/
#include "global.h"
#include "plgdbsem.h"
#include "mycat.h"
#include "reldef.h"
#include "colblk.h"
#include "filamap.h"
@ -73,6 +72,14 @@ RELDEF::RELDEF(void)
Hc = NULL;
} // end of RELDEF constructor
/***********************************************************************/
/* This function return a pointer to the Table Option Struct. */
/***********************************************************************/
PTOS RELDEF::GetTopt(void)
{
return Hc->GetTableOptionStruct();
} // end of GetTopt
/***********************************************************************/
/* This function sets an integer table information. */
/***********************************************************************/
@ -153,10 +160,9 @@ char *RELDEF::GetStringCatInfo(PGLOBAL g, PSZ what, PSZ sdef)
if (s) {
if (!Hc->IsPartitioned() ||
(stricmp(what, "filename") && stricmp(what, "tabname")
&& stricmp(what, "connect"))) {
sval= (char*)PlugSubAlloc(g, NULL, strlen(s) + 1);
strcpy(sval, s);
} else
&& stricmp(what, "connect")))
sval= PlugDup(g, s);
else
sval= s;
} else if (!stricmp(what, "filename")) {
@ -213,8 +219,7 @@ bool TABDEF::Define(PGLOBAL g, PCATLG cat, LPCSTR name, LPCSTR am)
{
int poff = 0;
Name = (PSZ)PlugSubAlloc(g, NULL, strlen(name) + 1);
strcpy(Name, name);
Name = (PSZ)PlugDup(g, name);
Cat = cat;
Hc = ((MYCAT*)cat)->GetHandler();
Catfunc = GetFuncID(GetStringCatInfo(g, "Catfunc", NULL));
@ -712,8 +717,7 @@ COLDEF::COLDEF(void) : COLCRT()
/***********************************************************************/
int COLDEF::Define(PGLOBAL g, void *memp, PCOLINFO cfp, int poff)
{
Name = (PSZ)PlugSubAlloc(g, memp, strlen(cfp->Name) + 1);
strcpy(Name, cfp->Name);
Name = (PSZ)PlugDup(g, cfp->Name);
if (!(cfp->Flags & U_SPECIAL)) {
Poff = poff;
@ -735,22 +739,16 @@ int COLDEF::Define(PGLOBAL g, void *memp, PCOLINFO cfp, int poff)
Key = cfp->Key;
Freq = cfp->Freq;
if (cfp->Remark && *cfp->Remark) {
Desc = (PSZ)PlugSubAlloc(g, memp, strlen(cfp->Remark) + 1);
strcpy(Desc, cfp->Remark);
} // endif Remark
if (cfp->Remark && *cfp->Remark)
Desc = (PSZ)PlugDup(g, cfp->Remark);
if (cfp->Datefmt) {
Decode = (PSZ)PlugSubAlloc(g, memp, strlen(cfp->Datefmt) + 1);
strcpy(Decode, cfp->Datefmt);
} // endif Datefmt
if (cfp->Datefmt)
Decode = (PSZ)PlugDup(g, cfp->Datefmt);
} // endif special
if (cfp->Fieldfmt) {
Fmt = (PSZ)PlugSubAlloc(g, memp, strlen(cfp->Fieldfmt) + 1);
strcpy(Fmt, cfp->Fieldfmt);
} // endif Fieldfmt
if (cfp->Fieldfmt)
Fmt = (PSZ)PlugDup(g, cfp->Fieldfmt);
Flags = cfp->Flags;
return (Flags & (U_VIRTUAL|U_SPECIAL)) ? 0 : Long;

2
storage/connect/reldef.h

@ -12,6 +12,7 @@
#include "block.h"
#include "catalog.h"
#include "my_sys.h"
#include "mycat.h"
typedef class INDEXDEF *PIXDEF;
typedef class ha_connect *PHC;
@ -40,6 +41,7 @@ class DllExport RELDEF : public BLOCK { // Relation definition block
void SetCat(PCATLG cat) { Cat=cat; }
// Methods
PTOS GetTopt(void);
bool GetBoolCatInfo(PSZ what, bool bdef);
bool SetIntCatInfo(PSZ what, int ival);
bool Partitioned(void);

630
storage/connect/tabjson.cpp

@ -1,5 +1,5 @@
/************* tabjson C++ Program Source Code File (.CPP) *************/
/* PROGRAM NAME: tabjson Version 1.0 */
/* PROGRAM NAME: tabjson Version 1.1 */
/* (C) Copyright to the author Olivier BERTRAND 2014 - 2015 */
/* This program are the JSON class DB execution routines. */
/***********************************************************************/
@ -19,7 +19,6 @@
#include "global.h"
#include "plgdbsem.h"
//#include "xtable.h"
//#include "mycat.h" // for FNC_COL
#include "maputil.h"
#include "filamtxt.h"
#include "tabdos.h"
@ -31,12 +30,321 @@
#endif // ZIP_SUPPORT
#include "tabmul.h"
#include "checklvl.h"
#include "resource.h"
#include "mycat.h" // for FNC_COL
/***********************************************************************/
/* This should be an option. */
/***********************************************************************/
#define MAXCOL 200 /* Default max column nb in result */
#define TYPE_UNKNOWN 12 /* Must be greater than other types */
/***********************************************************************/
/* External function. */
/***********************************************************************/
USETEMP UseTemp(void);
typedef struct _jncol {
struct _jncol *Next;
char *Name;
char *Fmt;
int Type;
int Len;
int Scale;
bool Cbn;
bool Found;
} JCOL, *PJCL;
/***********************************************************************/
/* JSONColumns: construct the result blocks containing the description */
/* of all the columns of a table contained inside a JSON file. */
/***********************************************************************/
PQRYRES JSONColumns(PGLOBAL g, char *dp, const char *fn, char *objn,
int pretty, int lrecl, int lvl, bool info)
{
static int buftyp[] = {TYPE_STRING, TYPE_SHORT, TYPE_STRING, TYPE_INT,
TYPE_INT, TYPE_SHORT, TYPE_SHORT, TYPE_STRING};
static XFLD fldtyp[] = {FLD_NAME, FLD_TYPE, FLD_TYPENAME, FLD_PREC,
FLD_LENGTH, FLD_SCALE, FLD_NULL, FLD_FORMAT};
static unsigned int length[] = {0, 6, 8, 10, 10, 6, 6, 0};
char filename[_MAX_PATH], colname[65], fmt[129];
int i, j, n = 0;
int ncol = sizeof(buftyp) / sizeof(int);
PVAL valp;
JCOL jcol;
PJCL jcp, fjcp = NULL, pjcp = NULL;
PJPR *jrp, jpp;
PJSON jsp;
PJVAL jvp;
PJOB row;
PJDEF tdp;
TDBJSN *tjnp;
PJTDB tjsp;
PQRYRES qrp;
PCOLRES crp;
if (info) {
length[0] = 128;
length[7] = 256;
goto skipit;
} // endif info
if (trace)
htrc("File %s pretty=%d lvl=%d lrecl=%d\n",
SVP(fn), pretty, lvl, lrecl);
/*********************************************************************/
/* Open the input file. */
/*********************************************************************/
if (!fn) {
strcpy(g->Message, MSG(MISSING_FNAME));
return NULL;
} else
PlugSetPath(filename, fn, dp);
tdp = new(g) JSONDEF;
tdp->Database = dp;
tdp->Fn = filename;
tdp->Objname = objn;
tdp->Pretty = pretty;
if (pretty == 2) {
tjsp = new(g) TDBJSON(tdp, new(g) MAPFAM(tdp));
if (tjsp->MakeDocument(g))
return NULL;
jsp = (tjsp->GetDoc()) ? tjsp->GetDoc()->GetValue(0) : NULL;
} else {
if (!lrecl) {
sprintf(g->Message, "LRECL must be specified for pretty=%d", pretty);
return NULL;
} // endif lrecl
tdp->Lrecl = lrecl;
tdp->Ending = CRLF;
tjnp = new(g) TDBJSN(tdp, new(g) DOSFAM(tdp));
tjnp->SetMode(MODE_READ);
if (tjnp->OpenDB(g))
return NULL;
switch (tjnp->ReadDB(g)) {
case RC_EF:
strcpy(g->Message, "Void json table");
case RC_FX:
goto err;
default:
jsp = tjnp->GetRow();
} // endswitch ReadDB
} // endif pretty
if (!(row = (jsp) ? jsp->GetObject() : NULL)) {
strcpy(g->Message, "Can only retrieve columns from object rows");
goto err;
} // endif row
jcol.Next = NULL;
jcol.Found = true;
colname[64] = 0;
fmt[128] = 0;
jrp = (PJPR*)PlugSubAlloc(g, NULL, sizeof(PJPR) * lvl);
/*********************************************************************/
/* Analyse the JSON tree and define columns. */
/*********************************************************************/
for (i = 1; ; i++) {
for (jpp = row->GetFirst(); jpp; jpp = jpp->GetNext()) {
for (j = 0; j < lvl; j++)
jrp[j] = NULL;
more:
strncpy(colname, jpp->GetKey(), 64);
*fmt = 0;
j = 0;
jvp = jpp->GetVal();
retry:
if ((valp = jvp ? jvp->GetValue() : NULL)) {
jcol.Type = valp->GetType();
jcol.Len = valp->GetValLen();
jcol.Scale = valp->GetValPrec();
jcol.Cbn = valp->IsNull();
} else if (!jvp || jvp->IsNull()) {
jcol.Type = TYPE_UNKNOWN;
jcol.Len = jcol.Scale = 0;
jcol.Cbn = true;
} else if (j < lvl) {
if (!*fmt)
strcpy(fmt, colname);
jsp = jvp->GetJson();
switch (jsp->GetType()) {
case TYPE_JOB:
if (!jrp[j])
jrp[j] = jsp->GetFirst();
strncat(strncat(fmt, ":", 128), jrp[j]->GetKey(), 128);
strncat(strncat(colname, "_", 64), jrp[j]->GetKey(), 64);
jvp = jrp[j]->GetVal();
j++;
break;
case TYPE_JAR:
strncat(fmt, ":", 128);
jvp = jsp->GetValue(0);
break;
default:
sprintf(g->Message, "Logical error after %s", fmt);
goto err;
} // endswitch jsp
goto retry;
} else {
jcol.Type = TYPE_STRING;
jcol.Len = 256;
jcol.Scale = 0;
jcol.Cbn = true;
} // endif's
// Check whether this column was already found
for (jcp = fjcp; jcp; jcp = jcp->Next)
if (!strcmp(colname, jcp->Name))
break;
if (jcp) {
if (jcp->Type != jcol.Type)
jcp->Type = TYPE_STRING;
if (*fmt && (!jcp->Fmt || strlen(jcp->Fmt) < strlen(fmt))) {
jcp->Fmt = PlugDup(g, fmt);
length[7] = MY_MAX(length[7], strlen(fmt));
} // endif *fmt
jcp->Len = MY_MAX(jcp->Len, jcol.Len);
jcp->Scale = MY_MAX(jcp->Scale, jcol.Scale);
jcp->Cbn |= jcol.Cbn;
jcp->Found = true;
} else {
// New column
jcp = (PJCL)PlugSubAlloc(g, NULL, sizeof(JCOL));
*jcp = jcol;
jcp->Cbn |= (i > 1);
jcp->Name = PlugDup(g, colname);
length[0] = MY_MAX(length[0], strlen(colname));
if (*fmt) {
jcp->Fmt = PlugDup(g, fmt);
length[7] = MY_MAX(length[7], strlen(fmt));
} else
jcp->Fmt = NULL;
if (pjcp) {
jcp->Next = pjcp->Next;
pjcp->Next = jcp;
} else
fjcp = jcp;
n++;
} // endif jcp
pjcp = jcp;
for (j = lvl - 1; j >= 0; j--)
if (jrp[j] && (jrp[j] = jrp[j]->GetNext()))
goto more;
} // endfor jpp
// Missing column can be null
for (jcp = fjcp; jcp; jcp = jcp->Next) {
jcp->Cbn |= !jcp->Found;
jcp->Found = false;
} // endfor jcp
if (pretty != 2) {
// Read next record
switch (tjnp->ReadDB(g)) {
case RC_EF:
jsp = NULL;
break;
case RC_FX:
goto err;
default:
jsp = tjnp->GetRow();
} // endswitch ReadDB
} else
jsp = tjsp->GetDoc()->GetValue(i);
if (!(row = (jsp) ? jsp->GetObject() : NULL))
break;
} // endor i
if (pretty != 2)
tjnp->CloseDB(g);
skipit:
if (trace)
htrc("CSVColumns: n=%d len=%d\n", n, length[0]);
/*********************************************************************/
/* Allocate the structures used to refer to the result set. */
/*********************************************************************/
qrp = PlgAllocResult(g, ncol, n, IDS_COLUMNS + 3,
buftyp, fldtyp, length, false, false);
crp = qrp->Colresp->Next->Next->Next->Next->Next->Next;
crp->Name = "Nullable";
crp->Next->Name = "Jpath";
if (info || !qrp)
return qrp;
qrp->Nblin = n;
/*********************************************************************/
/* Now get the results into blocks. */
/*********************************************************************/
for (i = 0, jcp = fjcp; jcp; i++, jcp = jcp->Next) {
if (jcp->Type == TYPE_UNKNOWN) // Void column
jcp->Type = TYPE_STRING;
crp = qrp->Colresp; // Column Name
crp->Kdata->SetValue(jcp->Name, i);
crp = crp->Next; // Data Type
crp->Kdata->SetValue(jcp->Type, i);
crp = crp->Next; // Type Name
crp->Kdata->SetValue(GetTypeName(jcp->Type), i);
crp = crp->Next; // Precision
crp->Kdata->SetValue(jcp->Len, i);
crp = crp->Next; // Length
crp->Kdata->SetValue(jcp->Len, i);
crp = crp->Next; // Scale (precision)
crp->Kdata->SetValue(jcp->Scale, i);
crp = crp->Next; // Nullable
crp->Kdata->SetValue(jcp->Cbn ? 1 : 0, i);
crp = crp->Next; // Field format
if (crp->Kdata)
crp->Kdata->SetValue(jcp->Fmt, i);
} // endfor i
/*********************************************************************/
/* Return the result pointer. */
/*********************************************************************/
return qrp;
err:
if (pretty != 2)
tjnp->CloseDB(g);
return NULL;
} // end of JSONColumns
/* -------------------------- Class JSONDEF -------------------------- */
JSONDEF::JSONDEF(void)
@ -44,8 +352,11 @@ JSONDEF::JSONDEF(void)
Jmode = MODE_OBJECT;
Objname = NULL;
Xcol = NULL;
Pretty = 2;
Limit = 1;
Level = 0;
ReadMode = 0;
Strict = false;
} // end of JSONDEF constructor
/***********************************************************************/
@ -57,6 +368,7 @@ bool JSONDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
Objname = GetStringCatInfo(g, "Object", NULL);
Xcol = GetStringCatInfo(g, "Expand", NULL);
Pretty = GetIntCatInfo("Pretty", 2);
Level = GetIntCatInfo("Level", 0);
Limit = GetIntCatInfo("Limit", 10);
return DOSDEF::DefineAM(g, "DOS", poff);
} // end of DefineAM
@ -66,6 +378,9 @@ bool JSONDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
/***********************************************************************/
PTDB JSONDEF::GetTable(PGLOBAL g, MODE m)
{
if (Catfunc == FNC_COL)
return new(g)TDBJCL(this);
PTDBASE tdbp;
PTXF txfp = NULL;
@ -95,7 +410,7 @@ PTDB JSONDEF::GetTable(PGLOBAL g, MODE m)
// Txfp must be set for TDBDOS
tdbp = new(g) TDBJSN(this, txfp);
} else {
txfp = new(g) DOSFAM(this);
txfp = new(g) MAPFAM(this);
tdbp = new(g) TDBJSON(this, txfp);
} // endif Pretty
@ -112,30 +427,45 @@ PTDB JSONDEF::GetTable(PGLOBAL g, MODE m)
/***********************************************************************/
TDBJSN::TDBJSN(PJDEF tdp, PTXF txfp) : TDBDOS(tdp, txfp)
{
Top = NULL;
Row = NULL;
Val = NULL;
Colp = NULL;
Jmode = tdp->Jmode;
Xcol = tdp->Xcol;
if (tdp) {
Jmode = tdp->Jmode;
Objname = tdp->Objname;
Xcol = tdp->Xcol;
Limit = tdp->Limit;
Pretty = tdp->Pretty;
Strict = tdp->Strict;
} else {
Jmode = MODE_OBJECT;
Objname = NULL;
Xcol = NULL;
Limit = 1;
Pretty = 0;
Strict = false;
} // endif tdp
Fpos = -1;
//Spos = 0;
N = 0;
Limit = tdp->Limit;
NextSame = 0;
SameRow = 0;
Xval = -1;
Pretty = tdp->Pretty;
Strict = tdp->Strict;
Comma = false;
} // end of TDBJSN standard constructor
TDBJSN::TDBJSN(TDBJSN *tdbp) : TDBDOS(NULL, tdbp)
{
Top = tdbp->Top;
Row = tdbp->Row;
Val = tdbp->Val;
Colp = tdbp->Colp;
Jmode = tdbp->Jmode;
Objname = tdbp->Objname;
Xcol = tdbp->Xcol;
Fpos = tdbp->Fpos;
//Spos = tdbp->Spos;
N = tdbp->N;
Limit = tdbp->Limit;
NextSame = tdbp->NextSame;
@ -213,6 +543,34 @@ int TDBJSN::GetMaxSize(PGLOBAL g)
return MaxSize;
} // end of GetMaxSize
/***********************************************************************/
/* Find the row in the tree structure. */
/***********************************************************************/
PJSON TDBJSN::FindRow(PGLOBAL g)
{
char *p, *objpath;
PJSON jsp = Row;
PJVAL val = NULL;
for (objpath = PlugDup(g, Objname); jsp && objpath; objpath = p) {
if ((p = strchr(objpath, ':')))
*p++ = 0;
if (*objpath != '[') { // objpass is a key
val = (jsp->GetType() == TYPE_JOB) ?
jsp->GetObject()->GetValue(objpath) : NULL;
} else if (objpath[strlen(objpath)-1] == ']') {
val = (jsp->GetType() == TYPE_JAR) ?
jsp->GetArray()->GetValue(atoi(objpath+1) - 1) : NULL;
} else
val = NULL;
jsp = (val) ? val->GetJson() : NULL;
} // endfor objpath
return jsp;
} // end of FindRow
/***********************************************************************/
/* OpenDB: Data Base open routine for JSN access method. */
/***********************************************************************/
@ -223,7 +581,6 @@ bool TDBJSN::OpenDB(PGLOBAL g)
/* Table already open replace it at its beginning. */
/*******************************************************************/
Fpos= -1;
// Spos = 0;
NextSame = 0;
SameRow = 0;
} else {
@ -298,6 +655,7 @@ int TDBJSN::ReadDB(PGLOBAL g)
strlen(To_Line), Pretty, &Comma))) {
rc = (Pretty == 1 && !strcmp(To_Line, "]")) ? RC_EF : RC_FX;
} else {
Row = FindRow(g);
SameRow = 0;
Fpos++;
rc = RC_OK;
@ -306,20 +664,86 @@ int TDBJSN::ReadDB(PGLOBAL g)
return rc;
} // end of ReadDB
/***********************************************************************/
/* Make the top tree from the object path. */
/***********************************************************************/
int TDBJSN::MakeTopTree(PGLOBAL g, PJSON jsp)
{
if (Objname) {
if (!Val) {
// Parse and allocate Objname item(s)
char *p;
char *objpath = PlugDup(g, Objname);
int i;
PJOB objp;
PJAR arp;
PJVAL val = NULL;
Top = NULL;
for (; objpath; objpath = p) {
if ((p = strchr(objpath, ':')))
*p++ = 0;
if (*objpath != '[') {
objp = new(g) JOBJECT;
if (!Top)
Top = objp;
if (val)
val->SetValue(objp);
val = new(g) JVALUE;
objp->SetValue(g, val, objpath);
} else if (objpath[strlen(objpath)-1] == ']') {
arp = new(g) JARRAY;
if (!Top)
Top = arp;
if (val)
val->SetValue(arp);
val = new(g) JVALUE;
i = atoi(objpath+1) - 1;
arp->SetValue(g, val, i);
arp->InitArray(g);
} else {
sprintf(g->Message, "Invalid Table path %s", Objname);
return RC_FX;
} // endif objpath
} // endfor p
Val = val;
} // endif Val
Val->SetValue(jsp);
} else
Top = jsp;
return RC_OK;
} // end of MakeTopTree
/***********************************************************************/
/* PrepareWriting: Prepare the line for WriteDB. */
/***********************************************************************/
bool TDBJSN::PrepareWriting(PGLOBAL g)
{
PSZ s = Serialize(g, Row, NULL, Pretty);
PSZ s;
if (MakeTopTree(g, Row))
return true;
if (s) {
if ((s = Serialize(g, Top, NULL, Pretty))) {
if (Comma)
strcat(s, ",");
if ((signed)strlen(s) > Lrecl) {
sprintf(g->Message, "Line would be truncated (lrecl=%d)", Lrecl);
return true;
strncpy(To_Line, s, Lrecl);
sprintf(g->Message, "Line truncated (lrecl=%d)", Lrecl);
return PushWarning(g, this);
} else
strcpy(To_Line, s);
@ -403,7 +827,7 @@ bool JSONCOL::CheckExpand(PGLOBAL g, int i, PSZ nm, bool b)
bool JSONCOL::SetArrayOptions(PGLOBAL g, char *p, int i, PSZ nm)
{
int n = (int)strlen(p);
bool dg = true;
bool dg = true, b = false;
PJNODE jnp = &Nodes[i];
if (*p) {
@ -417,7 +841,8 @@ bool JSONCOL::SetArrayOptions(PGLOBAL g, char *p, int i, PSZ nm)
return true;
} // endif p
} // endif *p
} else
b = true;
// To check whether a numeric Rank was specified
for (int k = 0; dg && p[k]; k++)
@ -427,13 +852,19 @@ bool JSONCOL::SetArrayOptions(PGLOBAL g, char *p, int i, PSZ nm)
// Default specifications
if (CheckExpand(g, i, nm, false))
return true;
else if (jnp->Op != OP_EXP)
if (!Value->IsTypeNum()) {
else if (jnp->Op != OP_EXP) {
if (b) {
// Return 1st value
jnp->Rank = 1;
jnp->Op = OP_EQ;
} else if (!Value->IsTypeNum()) {
jnp->CncVal = AllocateValue(g, (void*)", ", TYPE_STRING);
jnp->Op = OP_CNC;
} else
jnp->Op = OP_ADD;
} // endif OP
} else if (dg) {
if (atoi(p) > 0) {
// Return nth value
@ -537,8 +968,7 @@ bool JSONCOL::ParseJpath(PGLOBAL g)
else if (!Jpath)
Jpath = Name;
pbuf = (char*)PlugSubAlloc(g, NULL, strlen(Jpath) + 1);
strcpy(pbuf, Jpath);
pbuf = PlugDup(g, Jpath);
// The Jpath must be analyzed
for (i = 0, p = pbuf; (p = strchr(p, ':')); i++, p++)
@ -632,6 +1062,10 @@ void JSONCOL::ReadColumn(PGLOBAL g)
if (!Tjp->SameRow || Xnod >= Tjp->SameRow)
Value->SetValue_pval(GetColumnValue(g, Tjp->Row, 0));
// Set null when applicable
if (Nullable)
Value->SetNull(Value->IsZero());
} // end of ReadColumn
/***********************************************************************/
@ -821,7 +1255,7 @@ PVAL JSONCOL::CalculateArray(PGLOBAL g, PJAR arp, int n)
/***********************************************************************/
PJSON JSONCOL::GetRow(PGLOBAL g)
{
PJVAL val;
PJVAL val = NULL;
PJAR arp;
PJSON nwr, row = Tjp->Row;
@ -987,18 +1421,14 @@ void JSONCOL::WriteColumn(PGLOBAL g)
/***********************************************************************/
TDBJSON::TDBJSON(PJDEF tdp, PTXF txfp) : TDBJSN(tdp, txfp)
{
Top = NULL;
Doc = NULL;
Objname = tdp->Objname;
Multiple = tdp->Multiple;
Done = Changed = false;
} // end of TDBJSON standard constructor
TDBJSON::TDBJSON(PJTDB tdbp) : TDBJSN(tdbp)
{
Top = tdbp->Top;
Doc = tdbp->Doc;
Objname = tdbp->Objname;
Multiple = tdbp->Multiple;
Done = tdbp->Done;
Changed = tdbp->Changed;
@ -1022,64 +1452,17 @@ PTDB TDBJSON::CopyOne(PTABS t)
} // end of CopyOne
/***********************************************************************/
/* Make the document tree from a file. */
/* Make the document tree from the object path. */
/***********************************************************************/
int TDBJSON::MakeNewDoc(PGLOBAL g)
{
// Create a void table that will be populated
Doc = new(g) JARRAY;
if (Objname) {
// Parse and allocate Objname item(s)
char *p;
char *objpath = (char*)PlugSubAlloc(g, NULL, strlen(Objname)+1);
int i;
PJOB objp;
PJAR arp;
PJVAL val = NULL;
strcpy(objpath, Objname);
Top = NULL;
for (; objpath; objpath = p) {
if ((p = strchr(objpath, ':')))
*p++ = 0;
if (*objpath != '[') {
objp = new(g) JOBJECT;
if (!Top)
Top = objp;
if (val)
val->SetValue(objp);
val = new(g) JVALUE;
objp->SetValue(g, val, objpath);
} else if (objpath[strlen(objpath)-1] == ']') {
arp = new(g) JARRAY;
if (!Top)
Top = arp;
if (val)
val->SetValue(arp);
val = new(g) JVALUE;
i = atoi(objpath+1) - 1;
arp->SetValue(g, val, i);
arp->InitArray(g);
} else {
sprintf(g->Message, "Invalid Table path %s", Objname);
return RC_FX;
} // endif objpath
} // endfor p
val->SetValue(Doc);
} else
Top = Doc;
if (MakeTopTree(g, Doc))
return RC_FX;
Done = true;
return RC_OK;
} // end of MakeNewDoc
@ -1088,10 +1471,9 @@ int TDBJSON::MakeNewDoc(PGLOBAL g)
/***********************************************************************/
int TDBJSON::MakeDocument(PGLOBAL g)
{
char *p, *memory, *objpath, *key, filename[_MAX_PATH];
char *p, *memory, *objpath, *key;
int len, i = 0;
HANDLE hFile;
MEMMAP mm;
MODE mode = Mode;
PJSON jsp;
PJOB objp = NULL;
PJAR arp = NULL;
@ -1099,70 +1481,38 @@ int TDBJSON::MakeDocument(PGLOBAL g)
if (Done)
return RC_OK;
else
Done = true;
// Now open the JSON file
PlugSetPath(filename, Txfp->To_File, GetPath());
/*********************************************************************/
/* Create the mapping file object. */
/*********************************************************************/
hFile = CreateFileMap(g, filename, &mm, MODE_READ, false);
if (hFile == INVALID_HANDLE_VALUE) {
DWORD drc = GetLastError();
if (drc != ENOENT || Mode != MODE_INSERT) {
if (!(*g->Message))
sprintf(g->Message, MSG(OPEN_MODE_ERROR),
"map", (int)drc, filename);
return RC_FX;
} else
return MakeNewDoc(g);
} // endif hFile
/*********************************************************************/
/* Get the file size (assuming file is smaller than 4 GB) */
/* Create the mapping file object in mode read. */
/*********************************************************************/
len = mm.lenL;
memory = (char *)mm.memory;
Mode = MODE_READ;
if (!len) { // Empty file
CloseFileHandle(hFile);
CloseMemMap(memory, len);
if (!Txfp->OpenTableFile(g)) {
PFBLOCK fp = Txfp->GetTo_Fb();
if (Mode == MODE_INSERT)
return MakeNewDoc(g);
} // endif len
if (fp) {
len = fp->Length;
memory = fp->Memory;
} else {
Mode = mode; // Restore saved Mode
return MakeNewDoc(g);
} // endif fp
if (!memory) {
CloseFileHandle(hFile);
sprintf(g->Message, MSG(MAP_VIEW_ERROR), filename, GetLastError());
} else
return RC_FX;
} // endif Memory
CloseFileHandle(hFile); // Not used anymore
hFile = INVALID_HANDLE_VALUE; // For Fblock
/*********************************************************************/
/* Parse the json file and allocate its tree structure. */
/*********************************************************************/
g->Message[0] = 0;
jsp = Top = ParseJson(g, memory, len, Pretty);
CloseMemMap(memory, len);
Txfp->CloseTableFile(g, false);
Mode = mode; // Restore saved Mode
if (!jsp && g->Message[0])
return RC_FX;
if (Objname) {
objpath = (char*)PlugSubAlloc(g, NULL, strlen(Objname) + 1);
strcpy(objpath, Objname);
} else
objpath = NULL;
objpath = PlugDup(g, Objname);
/*********************************************************************/
/* Find the table in the tree structure. */
@ -1234,6 +1584,7 @@ int TDBJSON::MakeDocument(PGLOBAL g)
} // endif jsp
Done = true;
return RC_OK;
} // end of MakeDocument
@ -1484,4 +1835,27 @@ void TDBJSON::CloseDB(PGLOBAL g)
} // end of CloseDB
/* -------------------------- End of json --------------------------- */
/* ---------------------------TDBJCL class --------------------------- */
/***********************************************************************/
/* TDBJCL class constructor. */
/***********************************************************************/
TDBJCL::TDBJCL(PJDEF tdp) : TDBCAT(tdp)
{
Fn = tdp->GetFn();
Objn = tdp->Objname;
Pretty = tdp->Pretty;
Lrecl = tdp->Lrecl;
lvl = tdp->Level;
} // end of TDBJCL constructor
/***********************************************************************/
/* GetResult: Get the list the JSON file columns. */
/***********************************************************************/
PQRYRES TDBJCL::GetResult(PGLOBAL g)
{
return JSONColumns(g, ((PTABDEF)To_Def)->GetPath(), Fn, Objn,
Pretty, Lrecl, lvl, false);
} // end of GetResult
/* --------------------------- End of json --------------------------- */

66
storage/connect/tabjson.h

@ -1,5 +1,5 @@
/*************** tabjson H Declares Source Code File (.H) **************/
/* Name: tabjson.h Version 1.0 */
/* Name: tabjson.h Version 1.1 */
/* */
/* (C) Copyright to the author Olivier BERTRAND 2014 - 2015 */
/* */
@ -34,6 +34,9 @@ typedef struct _jnode {
class JSONDEF : public DOSDEF { /* Table description */
friend class TDBJSON;
friend class TDBJSN;
friend class TDBJCL;
friend PQRYRES JSONColumns(PGLOBAL, char *, const char *, char *,
int, int, int, bool);
public:
// Constructor
JSONDEF(void);
@ -52,6 +55,7 @@ class JSONDEF : public DOSDEF { /* Table description */
char *Xcol; /* Name of expandable column */
int Limit; /* Limit of multiple values */
int Pretty; /* Depends on file structure */
int Level; /* Used for catalog table */
bool Strict; /* Strict syntax checking */
}; // end of JSONDEF
@ -69,29 +73,36 @@ class TDBJSN : public TDBDOS {
TDBJSN(TDBJSN *tdbp);
// Implementation
virtual AMT GetAmType(void) {return TYPE_AM_JSN;}
virtual bool SkipHeader(PGLOBAL g);
virtual PTDB Duplicate(PGLOBAL g) {return (PTDB)new(g) TDBJSN(this);}
virtual AMT GetAmType(void) {return TYPE_AM_JSN;}
virtual bool SkipHeader(PGLOBAL g);
virtual PTDB Duplicate(PGLOBAL g) {return (PTDB)new(g) TDBJSN(this);}
PJSON GetRow(void) {return Row;}
// Methods
virtual PTDB CopyOne(PTABS t);
virtual PCOL MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n);
virtual PCOL InsertSpecialColumn(PGLOBAL g, PCOL colp);
virtual int RowNumber(PGLOBAL g, bool b = FALSE)
{return (b) ? N : Fpos + 1;}
virtual PTDB CopyOne(PTABS t);
virtual PCOL MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n);
virtual PCOL InsertSpecialColumn(PGLOBAL g, PCOL colp);
virtual int RowNumber(PGLOBAL g, bool b = FALSE)
{return (b) ? N : Fpos + 1;}
// Database routines
virtual int Cardinality(PGLOBAL g);
virtual int GetMaxSize(PGLOBAL g);
virtual bool OpenDB(PGLOBAL g);
virtual bool PrepareWriting(PGLOBAL g);
virtual int ReadDB(PGLOBAL g);
virtual int Cardinality(PGLOBAL g);
virtual int GetMaxSize(PGLOBAL g);
virtual bool OpenDB(PGLOBAL g);
virtual bool PrepareWriting(PGLOBAL g);
virtual int ReadDB(PGLOBAL g);
protected:
PJSON FindRow(PGLOBAL g);
int MakeTopTree(PGLOBAL g, PJSON jsp);
// Members
PJSON Top; // The top JSON tree
PJSON Row; // The current row
PJSON Val; // The value of the current row
PJCOL Colp; // The multiple column
JMODE Jmode; // MODE_OBJECT by default
char *Objname; // The table object name
char *Xcol; // Name of expandable column
int Fpos; // The current row index
//int Spos; // DELETE start index
@ -166,6 +177,7 @@ class TDBJSON : public TDBJSN {
// Implementation
virtual AMT GetAmType(void) {return TYPE_AM_JSON;}
virtual PTDB Duplicate(PGLOBAL g) {return (PTDB)new(g) TDBJSON(this);}
PJAR GetDoc(void) {return Doc;}
// Methods
virtual PTDB CopyOne(PTABS t);
@ -183,19 +195,39 @@ class TDBJSON : public TDBJSN {
virtual int WriteDB(PGLOBAL g);
virtual int DeleteDB(PGLOBAL g, int irc);
virtual void CloseDB(PGLOBAL g);
int MakeDocument(PGLOBAL g);
// Optimization routines
virtual int MakeIndex(PGLOBAL g, PIXDEF pxdf, bool add);
protected:
int MakeNewDoc(PGLOBAL g);
int MakeDocument(PGLOBAL g);
// Members
PJSON Top; // The file JSON tree
PJAR Doc; // The document array
char *Objname; // The table object name
int Multiple; // 0: No 1: DIR 2: Section 3: filelist
bool Done; // True when document parsing is done
bool Changed; // After Update, Insert or Delete
}; // end of class TDBJSON
/***********************************************************************/
/* This is the class declaration for the JSON catalog table. */
/***********************************************************************/
class TDBJCL : public TDBCAT {
public:
// Constructor
TDBJCL(PJDEF tdp);
protected:
// Specific routines
virtual PQRYRES GetResult(PGLOBAL g);
// Members
//char *Dp;
const char *Fn;
char *Objn;
int Pretty;
int Lrecl;
int lvl;
}; // end of class TDBJCL

6
storage/connect/table.cpp

@ -587,6 +587,10 @@ CATCOL::CATCOL(PCOLDEF cdp, PTDB tdbp, int n)
void CATCOL::ReadColumn(PGLOBAL g)
{
// Get the value of the Name or Description property
Value->SetValue_pvblk(Crp->Kdata, Tdbp->N);
if (Crp->Kdata)
Value->SetValue_pvblk(Crp->Kdata, Tdbp->N);
else
Value->Reset();
} // end of ReadColumn

11
storage/connect/tabmul.cpp

@ -5,7 +5,7 @@
/* */
/* COPYRIGHT: */
/* ---------- */
/* (C) Copyright to PlugDB Software Development 2003 - 2012 */
/* (C) Copyright to PlugDB Software Development 2003 - 2015 */
/* Author: Olivier BERTRAND */
/* */
/* WHAT THIS PROGRAM DOES: */
@ -172,8 +172,7 @@ bool TDBMUL::InitFileNames(PGLOBAL g)
while (n < PFNZ) {
strcat(strcat(strcpy(filename, drive), direc), FileData.cFileName);
pfn[n] = (char*)PlugSubAlloc(g, NULL, strlen(filename) + 1);
strcpy(pfn[n++], filename);
pfn[n++] = PlugDup(g, filename);
if (!FindNextFile(hSearch, &FileData)) {
rc = GetLastError();
@ -239,8 +238,7 @@ bool TDBMUL::InitFileNames(PGLOBAL g)
continue; // Not a match
strcat(strcpy(filename, direc), entry->d_name);
pfn[n] = (char*)PlugSubAlloc(g, NULL, strlen(filename) + 1);
strcpy(pfn[n++], filename);
pfn[n++] = PlugDup(g, filename);
if (trace)
htrc("Adding pfn[%d] %s\n", n, filename);
@ -292,8 +290,7 @@ bool TDBMUL::InitFileNames(PGLOBAL g)
*(++p) = '\0';
// Suballocate the file name
pfn[n] = (char*)PlugSubAlloc(g, NULL, strlen(filename) + 1);
strcpy(pfn[n++], filename);
pfn[n++] = PlugDup(g, filename);
} // endfor n
} // endif Mul

4
storage/connect/tabmysql.cpp

@ -56,7 +56,6 @@
#include "xtable.h"
#include "tabcol.h"
#include "colblk.h"
#include "mycat.h"
#include "reldef.h"
#include "tabmysql.h"
#include "valblk.h"
@ -1078,8 +1077,7 @@ bool TDBMYSQL::ReadKey(PGLOBAL g, OPVAL op, const void *key, int len)
if (Myc.m_Res)
Myc.FreeResult();
To_Def->GetHandler()->MakeKeyWhere(g, Query->GetStr(),
op, "`", key, len);
To_Def->GetHandler()->MakeKeyWhere(g, Query, op, '`', key, len);
if (To_CondFil) {
oom = Query->Append(" AND (");

11
storage/connect/taboccur.cpp

@ -1,7 +1,7 @@
/************ TabOccur CPP Declares Source Code File (.CPP) ************/
/* Name: TABOCCUR.CPP Version 1.1 */
/* */
/* (C) Copyright to the author Olivier BERTRAND 2013 */
/* (C) Copyright to the author Olivier BERTRAND 2013 - 2015 */
/* */
/* OCCUR: Table that provides a view of a source table where the */
/* contain of several columns of the source table is placed in only */
@ -45,11 +45,8 @@
#include "tabcol.h"
#include "taboccur.h"
#include "xtable.h"
#if defined(MYSQL_SUPPORT)
#include "tabmysql.h"
#endif // MYSQL_SUPPORT
#include "ha_connect.h"
#include "mycat.h"
/***********************************************************************/
/* Prepare and count columns in the column list. */
@ -93,8 +90,7 @@ bool OcrColumns(PGLOBAL g, PQRYRES qrp, const char *col,
} // endif col
// Prepare the column list
colist = (char*)PlugSubAlloc(g, NULL, strlen(col) + 1);
strcpy(colist, col);
colist = PlugDup(g, col);
m = PrepareColist(colist);
if ((rk = (rank && *rank))) {
@ -191,8 +187,7 @@ bool OcrSrcCols(PGLOBAL g, PQRYRES qrp, const char *col,
} // endif col
// Prepare the column list
colist = (char*)PlugSubAlloc(g, NULL, strlen(col) + 1);
strcpy(colist, col);
colist = PlugDup(g, col);
m = PrepareColist(colist);
if ((rk = (rank && *rank)))

23
storage/connect/tabpivot.cpp

@ -5,7 +5,7 @@
/* */
/* COPYRIGHT: */
/* ---------- */
/* (C) Copyright to the author Olivier BERTRAND 2005-2013 */
/* (C) Copyright to the author Olivier BERTRAND 2005-2015 */
/* */
/* WHAT THIS PROGRAM DOES: */
/* ----------------------- */
@ -49,7 +49,6 @@
#include "tabpivot.h"
#include "valblk.h"
#include "ha_connect.h"
#include "mycat.h" // For GetHandler
/***********************************************************************/
/* Make the Pivot table column list. */
@ -150,11 +149,18 @@ PQRYRES PIVAID::MakePivotColumns(PGLOBAL g)
query = Tabsrc;
// Open a MySQL connection for this table
if (Myc.Open(g, Host, Database, User, Pwd, Port))
return NULL;
else
if (!Myc.Open(g, Host, Database, User, Pwd, Port)) {
b = true;
// Returned values must be in their original character set
if (Myc.ExecSQL(g, "SET character_set_results=NULL", &w) == RC_FX)
goto err;
else
Myc.FreeResult();
} else
return NULL;
// Send the source command to MySQL
if (Myc.ExecSQL(g, query, &w) == RC_FX)
goto err;
@ -241,6 +247,10 @@ PQRYRES PIVAID::MakePivotColumns(PGLOBAL g)
} else {
// The query was limited, we must get pivot column values
// Returned values must be in their original character set
// if (Myc.ExecSQL(g, "SET character_set_results=NULL", &w) == RC_FX)
// goto err;
query = (char*)PlugSubAlloc(g, NULL, 0);
sprintf(query, "SELECT DISTINCT `%s` FROM `%s`", Picol, Tabname);
PlugSubAlloc(g, NULL, strlen(query) + 1);
@ -284,8 +294,7 @@ PQRYRES PIVAID::MakePivotColumns(PGLOBAL g)
valp->SetValue_pvblk(Rblkp, i);
colname = valp->GetCharString(buf);
crp->Name = (char*)PlugSubAlloc(g, NULL, strlen(colname) + 1);
strcpy(crp->Name, colname);
crp->Name = PlugDup(g, colname);
crp->Flag = 1;
// Add this column

3
storage/connect/tabtbl.cpp

@ -70,11 +70,8 @@
#include "tabcol.h"
#include "tabdos.h" // TDBDOS and DOSCOL class dcls
#include "tabtbl.h"
#if defined(MYSQL_SUPPORT)
#include "tabmysql.h"
#endif // MYSQL_SUPPORT
#include "ha_connect.h"
#include "mycat.h" // For GetHandler
#if defined(WIN32)
#if defined(__BORLANDC__)

21
storage/connect/tabutil.cpp

@ -43,14 +43,11 @@
#include "plgdbsem.h"
#include "plgcnx.h" // For DB types
#include "myutil.h"
#include "mycat.h"
#include "valblk.h"
#include "resource.h"
#include "reldef.h"
#include "xtable.h"
#if defined(MYSQL_SUPPORT)
#include "tabmysql.h"
#endif // MYSQL_SUPPORT
#include "tabcol.h"
#include "tabutil.h"
#include "ha_connect.h"
@ -94,19 +91,13 @@ TABLE_SHARE *GetTableShare(PGLOBAL g, THD *thd, const char *db,
if (!open_table_def(thd, s, GTS_TABLE | GTS_VIEW)) {
if (!s->is_view) {
if (stricmp(plugin_name(s->db_plugin)->str, "connect")) {
#if defined(MYSQL_SUPPORT)
if (stricmp(plugin_name(s->db_plugin)->str, "connect"))
mysql = true;
#else // !MYSQL_SUPPORT
sprintf(g->Message, "%s.%s is not a CONNECT table", db, name);
return NULL;
#endif // MYSQL_SUPPORT
} else
else
mysql = false;
} else {
} else
mysql = true;
} // endif is_view
} else {
if (thd->is_error())
@ -428,7 +419,6 @@ PTDBASE TDBPRX::GetSubTable(PGLOBAL g, PTABLE tabp, bool b)
} // endif srcdef
if (mysql) {
#if defined(MYSQL_SUPPORT)
// Access sub-table via MySQL API
if (!(tdbp= cat->GetTable(g, tabp, Mode, "MYPRX"))) {
char buf[MAX_STR];
@ -445,11 +435,6 @@ PTDBASE TDBPRX::GetSubTable(PGLOBAL g, PTABLE tabp, bool b)
if (Mode == MODE_UPDATE || Mode == MODE_DELETE)
tdbp->SetName(Name); // For Make_Command
#else // !MYSQL_SUPPORT
sprintf(g->Message, "%s.%s is not a CONNECT table",
db, tblp->Name);
goto err;
#endif // MYSQL_SUPPORT
} else {
// Sub-table is a CONNECT table
tabp->Next = To_Table; // For loop checking

3
storage/connect/tabxcl.cpp

@ -51,11 +51,8 @@
#include "tabcol.h"
#include "tabxcl.h"
#include "xtable.h"
#if defined(MYSQL_SUPPORT)
#include "tabmysql.h"
#endif // MYSQL_SUPPORT
#include "ha_connect.h"
#include "mycat.h"
/* -------------- Implementation of the XCOL classes ---------------- */

376
storage/connect/tabxml.cpp

@ -1,9 +1,9 @@
/************* Tabxml C++ Program Source Code File (.CPP) **************/
/* PROGRAM NAME: TABXML */
/* ------------- */
/* Version 2.7 */
/* Version 2.8 */
/* */
/* Author Olivier BERTRAND 2007 - 2014 */
/* Author Olivier BERTRAND 2007 - 2015 */
/* */
/* This program are the XML tables classes using MS-DOM or libxml2. */
/***********************************************************************/
@ -29,6 +29,7 @@
#include "osutil.h"
#define _O_RDONLY O_RDONLY
#endif // !WIN32
#include "resource.h" // for IDS_COLUMNS
#define INCLUDE_TDBXML
#define NODE_TYPE_LIST
@ -44,6 +45,7 @@
#include "reldef.h"
#include "xtable.h"
#include "colblk.h"
#include "mycat.h"
#include "xindex.h"
#include "plgxml.h"
#include "tabxml.h"
@ -57,6 +59,336 @@ extern "C" char version[];
#define XMLSUP "libxml2"
#endif // !WIN32
#define TYPE_UNKNOWN 12 /* Must be greater than other types */
/***********************************************************************/
/* Class and structure used by XMLColumns. */
/***********************************************************************/
typedef class XMCOL *PXCL;
class XMCOL : public BLOCK {
public:
// Constructors
XMCOL(void) {Next = NULL;
Name[0] = 0;
Fmt = NULL;
Type = 1;
Len = Scale = 0;
Cbn = false;
Found = true;}
XMCOL(PGLOBAL g, PXCL xp, char *fmt, int i) {
Next = NULL;
strcpy(Name, xp->Name);
Fmt = (*fmt) ? PlugDup(g, fmt) : NULL;
Type = xp->Type;
Len = xp->Len;
Scale = xp->Scale;
Cbn = (xp->Cbn || i > 1);
Found = true;}
// Members
PXCL Next;
char Name[64];
char *Fmt;
int Type;
int Len;
int Scale;
bool Cbn;
bool Found;
}; // end of class XMCOL
typedef struct LVL {
PXNODE pn;
PXLIST nl;
PXATTR atp;
bool b;
long k;
int m, n;
} *PLVL;
/***********************************************************************/
/* XMLColumns: construct the result blocks containing the description */
/* of all the columns of a table contained inside an XML file. */
/***********************************************************************/
PQRYRES XMLColumns(PGLOBAL g, char *dp, char *tab, PTOS topt, bool info)
{
static int buftyp[] = {TYPE_STRING, TYPE_SHORT, TYPE_STRING, TYPE_INT,
TYPE_INT, TYPE_SHORT, TYPE_SHORT, TYPE_STRING};
static XFLD fldtyp[] = {FLD_NAME, FLD_TYPE, FLD_TYPENAME, FLD_PREC,
FLD_LENGTH, FLD_SCALE, FLD_NULL, FLD_FORMAT};
static unsigned int length[] = {0, 6, 8, 10, 10, 6, 6, 0};
char *op, colname[65], fmt[129], buf[512];
int i, j, lvl, rc, n = 0;
int ncol = sizeof(buftyp) / sizeof(int);
bool ok = true;
PXCL xcol, xcp, fxcp = NULL, pxcp = NULL;
PLVL *lvlp, vp;
PXNODE node = NULL;
PXMLDEF tdp;
PTDBXML txmp;
PQRYRES qrp;
PCOLRES crp;
if (info) {
length[0] = 128;
length[7] = 256;
goto skipit;
} // endif info
/*********************************************************************/
/* Open the input file. */
/*********************************************************************/
if (!topt->filename) {
strcpy(g->Message, MSG(MISSING_FNAME));
return NULL;
} else
lvl = atoi(GetListOption(g, "Level", topt->oplist, "0"));
if (trace)
htrc("File %s lvl=%d\n", topt->filename, lvl);
tdp = new(g) XMLDEF;
tdp->Database = dp;
tdp->Fn = (char*)topt->filename;
tdp->Tabname = tab;
if (!(op = GetListOption(g, "Xmlsup", topt->oplist, NULL)))
#if defined(WIN32)
tdp->Usedom = true;
#else // !WIN32
tdp->Usedom = false;
#endif // !WIN32
else
tdp->Usedom = (toupper(*op) == 'M' || toupper(*op) == 'D');
txmp = new(g) TDBXML(tdp);
if (txmp->Initialize(g))
return NULL;
xcol = new(g) XMCOL;
colname[64] = 0;
fmt[128] = 0;
lvlp = (PLVL*)PlugSubAlloc(g, NULL, sizeof(PLVL) * (lvl + 1));
for (j = 0; j <= lvl; j++)
lvlp[j] = (PLVL)PlugSubAlloc(g, NULL, sizeof(LVL));
/*********************************************************************/
/* Analyse the XML tree and define columns. */
/*********************************************************************/
for (i = 1; ; i++) {
// Get next row
switch (txmp->ReadDB(g)) {
case RC_EF:
vp = NULL;
break;
case RC_FX:
goto err;
default:
vp = lvlp[0];
vp->pn = txmp->RowNode;
vp->atp = vp->pn->GetAttribute(g, NULL);
vp->nl = vp->pn->GetChildElements(g);
vp->b = true;
vp->k = 0;
vp->m = vp->n = 0;
j = 0;
} // endswitch ReadDB
if (!vp)
break;
while (true) {
if (!vp->atp &&
!(node = (vp->nl) ? vp->nl->GetItem(g, vp->k++, node) : NULL))
if (j) {
vp = lvlp[--j];
if (!tdp->Usedom) // nl was destroyed
vp->nl = vp->pn->GetChildElements(g);
if (!lvlp[j+1]->b) {
vp->k--;
ok = false;
} // endif b
continue;
} else
break;
xcol->Name[vp->n] = 0;
fmt[vp->m] = 0;
more:
if (vp->atp) {
strncpy(colname, vp->atp->GetName(g), sizeof(colname));
strncat(xcol->Name, colname, 64);
rc = vp->atp->GetText(g, buf, sizeof(buf));
strncat(fmt, "@", sizeof(fmt));
if (j)
strncat(fmt, colname, sizeof(fmt));
} else {
if (tdp->Usedom && node->GetType() != 1)
continue;
strncpy(colname, node->GetName(g), sizeof(colname));
strncat(xcol->Name, colname, 64);
if (j)
strncat(fmt, colname, sizeof(fmt));
if (j < lvl && ok) {
vp = lvlp[j+1];
vp->k = 0;
vp->atp = node->GetAttribute(g, NULL);
vp->nl = node->GetChildElements(g);
if (tdp->Usedom && vp->nl->GetLength() == 1) {
node = vp->nl->GetItem(g, 0, node);
vp->b = (node->GetType() == 1); // Must be ab element
} else
vp->b = (vp->nl && vp->nl->GetLength());
if (vp->atp || vp->b) {
if (!vp->atp)
node = vp->nl->GetItem(g, vp->k++, node);
strncat(strncat(fmt, colname, 125), "/", 125);
strncat(xcol->Name, "_", 64);
j++;
vp->n = (int)strlen(xcol->Name);
vp->m = (int)strlen(fmt);
goto more;
} else {
vp = lvlp[j];
if (!tdp->Usedom) // nl was destroyed
vp->nl = vp->pn->GetChildElements(g);
} // endif vp
} else
ok = true;
rc = node->GetContent(g, buf, sizeof(buf));
} // endif atp;
xcol->Len = strlen(buf);
// Check whether this column was already found
for (xcp = fxcp; xcp; xcp = xcp->Next)
if (!strcmp(xcol->Name, xcp->Name))
break;
if (xcp) {
if (xcp->Type != xcol->Type)
xcp->Type = TYPE_STRING;
if (*fmt && (!xcp->Fmt || strlen(xcp->Fmt) < strlen(fmt))) {
xcp->Fmt = PlugDup(g, fmt);
length[7] = MY_MAX(length[7], strlen(fmt));
} // endif *fmt
xcp->Len = MY_MAX(xcp->Len, xcol->Len);
xcp->Scale = MY_MAX(xcp->Scale, xcol->Scale);
xcp->Cbn |= xcol->Cbn;
xcp->Found = true;
} else {
// New column
xcp = new(g) XMCOL(g, xcol, fmt, i);
length[0] = MY_MAX(length[0], strlen(xcol->Name));
length[7] = MY_MAX(length[7], strlen(fmt));
if (pxcp) {
xcp->Next = pxcp->Next;
pxcp->Next = xcp;
} else
fxcp = xcp;
n++;
} // endif xcp
pxcp = xcp;
// for (j = lvl - 1; j >= 0; j--)
// if (jrp[j] && (jrp[j] = jrp[j]->GetNext()))
// goto more;
if (vp->atp)
vp->atp = vp->atp->GetNext(g);
} // endwhile
// Missing column can be null
for (xcp = fxcp; xcp; xcp = xcp->Next) {
xcp->Cbn |= !xcp->Found;
xcp->Found = false;
} // endfor xcp
} // endor i
txmp->CloseDB(g);
skipit:
if (trace)
htrc("CSVColumns: n=%d len=%d\n", n, length[0]);
/*********************************************************************/
/* Allocate the structures used to refer to the result set. */
/*********************************************************************/
qrp = PlgAllocResult(g, ncol, n, IDS_COLUMNS + 3,
buftyp, fldtyp, length, false, false);
crp = qrp->Colresp->Next->Next->Next->Next->Next->Next;
crp->Name = "Nullable";
crp->Next->Name = "Xpath";
if (info || !qrp)
return qrp;
qrp->Nblin = n;
/*********************************************************************/
/* Now get the results into blocks. */
/*********************************************************************/
for (i = 0, xcp = fxcp; xcp; i++, xcp = xcp->Next) {
if (xcp->Type == TYPE_UNKNOWN) // Void column
xcp->Type = TYPE_STRING;
crp = qrp->Colresp; // Column Name
crp->Kdata->SetValue(xcp->Name, i);
crp = crp->Next; // Data Type
crp->Kdata->SetValue(xcp->Type, i);
crp = crp->Next; // Type Name
crp->Kdata->SetValue(GetTypeName(xcp->Type), i);
crp = crp->Next; // Precision
crp->Kdata->SetValue(xcp->Len, i);
crp = crp->Next; // Length
crp->Kdata->SetValue(xcp->Len, i);
crp = crp->Next; // Scale (precision)
crp->Kdata->SetValue(xcp->Scale, i);
crp = crp->Next; // Nullable
crp->Kdata->SetValue(xcp->Cbn ? 1 : 0, i);
crp = crp->Next; // Field format
if (crp->Kdata)
crp->Kdata->SetValue(xcp->Fmt, i);
} // endfor i
/*********************************************************************/
/* Return the result pointer. */
/*********************************************************************/
return qrp;
err:
txmp->CloseDB(g);
return NULL;
} // end of XMLColumns
/* -------------- Implementation of the XMLDEF class ---------------- */
/***********************************************************************/
@ -176,6 +508,9 @@ bool XMLDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
/***********************************************************************/
PTDB XMLDEF::GetTable(PGLOBAL g, MODE m)
{
if (Catfunc == FNC_COL)
return new(g) TDBXCT(this);
PTDBASE tdbp = new(g) TDBXML(this);
if (Multiple)
@ -229,14 +564,14 @@ TDBXML::TDBXML(PXMLDEF tdp) : TDBASE(tdp)
Xfile = tdp->Fn;
Enc = tdp->Encoding;
Tabname = tdp->Tabname;
Rowname = (*tdp->Rowname) ? tdp->Rowname : NULL;
Colname = (*tdp->Colname) ? tdp->Colname : NULL;
Mulnode = (*tdp->Mulnode) ? tdp->Mulnode : NULL;
XmlDB = (*tdp->XmlDB) ? tdp->XmlDB : NULL;
Nslist = (*tdp->Nslist) ? tdp->Nslist : NULL;
DefNs = (*tdp->DefNs) ? tdp->DefNs : NULL;
Attrib = (*tdp->Attrib) ? tdp->Attrib : NULL;
Hdattr = (*tdp->Hdattr) ? tdp->Hdattr : NULL;
Rowname = (tdp->Rowname && *tdp->Rowname) ? tdp->Rowname : NULL;
Colname = (tdp->Colname && *tdp->Colname) ? tdp->Colname : NULL;
Mulnode = (tdp->Mulnode && *tdp->Mulnode) ? tdp->Mulnode : NULL;
XmlDB = (tdp->XmlDB && *tdp->XmlDB) ? tdp->XmlDB : NULL;
Nslist = (tdp->Nslist && *tdp->Nslist) ? tdp->Nslist : NULL;
DefNs = (tdp->DefNs && *tdp->DefNs) ? tdp->DefNs : NULL;
Attrib = (tdp->Attrib && *tdp->Attrib) ? tdp->Attrib : NULL;
Hdattr = (tdp->Hdattr && *tdp->Hdattr) ? tdp->Hdattr : NULL;
Coltype = tdp->Coltype;
Limit = tdp->Limit;
Xpand = tdp->Xpand;
@ -771,7 +1106,6 @@ bool TDBXML::OpenDB(PGLOBAL g)
NewRow = (Mode == MODE_INSERT);
Nsub = 0;
Use = USE_OPEN; // Do it now in case we are recursively called
return false;
} // end of OpenDB
@ -1847,4 +2181,24 @@ void XPOSCOL::WriteColumn(PGLOBAL g)
} // end of WriteColumn
/* ---------------------------TDBXCT class --------------------------- */
/***********************************************************************/
/* TDBXCT class constructor. */
/***********************************************************************/
TDBXCT::TDBXCT(PXMLDEF tdp) : TDBCAT(tdp)
{
Topt = tdp->GetTopt();
Dp = tdp->GetPath();
Tabn = tdp->Tabname;
} // end of TDBXCT constructor
/***********************************************************************/
/* GetResult: Get the list the JSON file columns. */
/***********************************************************************/
PQRYRES TDBXCT::GetResult(PGLOBAL g)
{
return XMLColumns(g, Dp, Tabn, Topt, false);
} // end of GetResult
/* ------------------------ End of Tabxml ---------------------------- */

23
storage/connect/tabxml.h

@ -16,6 +16,8 @@ typedef class XMLCOL *PXMLCOL;
/***********************************************************************/
class DllExport XMLDEF : public TABDEF { /* Logical table description */
friend class TDBXML;
friend class TDBXCT;
friend PQRYRES XMLColumns(PGLOBAL, char*, char*, PTOS, bool);
public:
// Constructor
XMLDEF(void);
@ -55,6 +57,7 @@ class DllExport TDBXML : public TDBASE {
friend class XMLCOL;
friend class XMULCOL;
friend class XPOSCOL;
friend PQRYRES XMLColumns(PGLOBAL, char*, char*, PTOS, bool);
public:
// Constructor
TDBXML(PXMLDEF tdp);
@ -237,4 +240,24 @@ class XPOSCOL : public XMLCOLX {
virtual void ReadColumn(PGLOBAL g);
virtual void WriteColumn(PGLOBAL g);
}; // end of class XPOSCOL
/***********************************************************************/
/* This is the class declaration for the XML catalog table. */
/***********************************************************************/
class TDBXCT : public TDBCAT {
public:
// Constructor
TDBXCT(PXMLDEF tdp);
protected:
// Specific routines
virtual PQRYRES GetResult(PGLOBAL g);
// Members
PTOS Topt;
char *Dp;
//const char *Fn;
char *Tabn;
}; // end of class TDBXCT
#endif // INCLUDE_TDBXML

9
storage/connect/valblk.cpp

@ -1,7 +1,7 @@
/************ Valblk C++ Functions Source Code File (.CPP) *************/
/* Name: VALBLK.CPP Version 2.1 */
/* */
/* (C) Copyright to the author Olivier BERTRAND 2005-2014 */
/* (C) Copyright to the author Olivier BERTRAND 2005-2015 */
/* */
/* This file contains the VALBLK and derived classes functions. */
/* Second family is VALBLK, representing simple suballocated arrays */
@ -1155,10 +1155,9 @@ void STRBLK::SetValue(PVAL valp, int n)
void STRBLK::SetValue(PSZ p, int n)
{
if (p) {
if (!Sorted || !n || !Strp[n-1] || strcmp(p, Strp[n-1])) {
Strp[n] = (PSZ)PlugSubAlloc(Global, NULL, strlen(p) + 1);
strcpy(Strp[n], p);
} else
if (!Sorted || !n || !Strp[n-1] || strcmp(p, Strp[n-1]))
Strp[n] = (PSZ)PlugDup(Global, p);
else
Strp[n] = Strp[n-1];
} else

80
storage/connect/value.cpp

@ -627,13 +627,16 @@ int TYPVAL<double>::GetValLen(void)
template <class TYPE>
bool TYPVAL<TYPE>::SetValue_pval(PVAL valp, bool chktype)
{
if (chktype && Type != valp->GetType())
return true;
if (valp != this) {
if (chktype && Type != valp->GetType())
return true;
if (!(Null = valp->IsNull() && Nullable))
Tval = GetTypedValue(valp);
else
Reset();
if (!(Null = valp->IsNull() && Nullable))
Tval = GetTypedValue(valp);
else
Reset();
} // endif valp
return false;
} // end of SetValue
@ -1319,15 +1322,18 @@ ulonglong TYPVAL<PSZ>::GetUBigintValue(void)
/***********************************************************************/
bool TYPVAL<PSZ>::SetValue_pval(PVAL valp, bool chktype)
{
if (chktype && (valp->GetType() != Type || valp->GetSize() > Len))
return true;
if (valp != this) {
if (chktype && (valp->GetType() != Type || valp->GetSize() > Len))
return true;
char buf[64];
char buf[64];
if (!(Null = valp->IsNull() && Nullable))
strncpy(Strp, valp->GetCharString(buf), Len);
else
Reset();
if (!(Null = valp->IsNull() && Nullable))
strncpy(Strp, valp->GetCharString(buf), Len);
else
Reset();
} // endif valp
return false;
} // end of SetValue_pval
@ -2063,18 +2069,21 @@ double BINVAL::GetFloatValue(void)
/***********************************************************************/
bool BINVAL::SetValue_pval(PVAL valp, bool chktype)
{
if (chktype && (valp->GetType() != Type || valp->GetSize() > Clen))
return true;
bool rc = false;
if (!(Null = valp->IsNull() && Nullable)) {
if ((rc = (Len = valp->GetSize()) > Clen))
Len = Clen;
if (valp != this) {
if (chktype && (valp->GetType() != Type || valp->GetSize() > Clen))
return true;
memcpy(Binp, valp->GetTo_Val(), Len);
} else
Reset();
if (!(Null = valp->IsNull() && Nullable)) {
if ((rc = (Len = valp->GetSize()) > Clen))
Len = Clen;
memcpy(Binp, valp->GetTo_Val(), Len);
} else
Reset();
} // endif valp
return rc;
} // end of SetValue_pval
@ -2629,21 +2638,24 @@ bool DTVAL::MakeDate(PGLOBAL g, int *val, int nval)
/***********************************************************************/
bool DTVAL::SetValue_pval(PVAL valp, bool chktype)
{
if (chktype && Type != valp->GetType())
return true;
if (valp != this) {
if (chktype && Type != valp->GetType())
return true;
if (!(Null = valp->IsNull() && Nullable)) {
if (Pdtp && !valp->IsTypeNum()) {
int ndv;
int dval[6];
if (!(Null = valp->IsNull() && Nullable)) {
if (Pdtp && !valp->IsTypeNum()) {
int ndv;
int dval[6];
ndv = ExtractDate(valp->GetCharValue(), Pdtp, DefYear, dval);
MakeDate(NULL, dval, ndv);
} else
Tval = valp->GetIntValue();
ndv = ExtractDate(valp->GetCharValue(), Pdtp, DefYear, dval);
MakeDate(NULL, dval, ndv);
} else
Tval = valp->GetIntValue();
Reset();
} else
Reset();
} // endif valp
return false;
} // end of SetValue

28
storage/connect/xobject.cpp

@ -289,6 +289,34 @@ bool STRING::Set(char *s, uint n)
return false;
} // end of Set
/***********************************************************************/
/* Append a char* to a STRING. */
/***********************************************************************/
bool STRING::Append(const char *s, uint ln)
{
if (!s)
return false;
uint len = Length + ln + 1;
if (len > Size) {
char *p = Realloc(len);
if (!p)
return true;
else if (p != Strp) {
strcpy(p, Strp);
Strp = p;
} // endif p
} // endif n
strncpy(Strp + Length, s, ln);
Length = len - 1;
Strp[Length] = 0;
return false;
} // end of Append
/***********************************************************************/
/* Append a PSZ to a STRING. */
/***********************************************************************/

1
storage/connect/xobject.h

@ -134,6 +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(PSZ s);
bool Append(STRING &str);
bool Append(char c);

6
storage/connect/xtable.h

@ -1,7 +1,7 @@
/**************** Table H Declares Source Code File (.H) ***************/
/* Name: TABLE.H Version 2.3 */
/* */
/* (C) Copyright to the author Olivier BERTRAND 1999-2014 */
/* (C) Copyright to the author Olivier BERTRAND 1999-2015 */
/* */
/* This file contains the TBX, OPJOIN and TDB class definitions. */
/***********************************************************************/
@ -24,9 +24,7 @@ typedef class CMD *PCMD;
class CMD : public BLOCK {
public:
// Constructor
CMD(PGLOBAL g, char *cmd) {
Cmd = (char*)PlugSubAlloc(g, NULL, strlen(cmd) + 1);
strcpy(Cmd, cmd); Next = NULL; }
CMD(PGLOBAL g, char *cmd) {Cmd = PlugDup(g, cmd); Next = NULL;}
// Members
PCMD Next;

2
storage/innobase/dict/dict0mem.cc

@ -770,7 +770,7 @@ dict_foreign_set_validate(
{
dict_foreign_not_exists not_exists(fk_set);
dict_foreign_set::iterator it = std::find_if(
dict_foreign_set::const_iterator it = std::find_if(
fk_set.begin(), fk_set.end(), not_exists);
if (it == fk_set.end()) {

1
storage/innobase/include/dict0mem.h

@ -50,6 +50,7 @@ Created 1/8/1996 Heikki Tuuri
#include <set>
#include <algorithm>
#include <iterator>
#include <ostream>
/* Forward declaration. */
struct ib_rbt_t;

2
storage/xtradb/dict/dict0mem.cc

@ -788,7 +788,7 @@ dict_foreign_set_validate(
{
dict_foreign_not_exists not_exists(fk_set);
dict_foreign_set::iterator it = std::find_if(
dict_foreign_set::const_iterator it = std::find_if(
fk_set.begin(), fk_set.end(), not_exists);
if (it == fk_set.end()) {

1
storage/xtradb/include/dict0mem.h

@ -53,6 +53,7 @@ Created 1/8/1996 Heikki Tuuri
#include <set>
#include <algorithm>
#include <iterator>
#include <ostream>
/* Forward declaration. */
struct ib_rbt_t;

Loading…
Cancel
Save