Commit 4d93c7f3 authored by Olivier Bertrand's avatar Olivier Bertrand

In CONNECT version 1.6.10 NOSQL facility is enhanced by a new way to retrieve NOSQL data.

In addition to files and Mongo collections, JSON as well as XML and CSV data can be retrieved
from the net as answers from REST queries. Because it uses and external package (cpprestsdk)
this is currently available only to MariaDB servers compiled from source.

-- Add compile flags needed on Windows /MD or /MDd (debug)
-- Also include some changes needed on Linux
  modified:   storage/connect/CMakeLists.txt

- Add the xtrc tracing function
  modified:   storage/connect/global.h
  modified:   storage/connect/plugutil.cpp

- Modify tracing to use xtrc and some typo
  modified:   storage/connect/array.cpp
  modified:   storage/connect/block.h
  modified:   storage/connect/restget.cpp

- Fix compilation error when ZIP is not supported
  modified:   storage/connect/ha_connect.cc
  modified:   storage/connect/tabfmt.cpp

- Add some tracing + typo
  modified:   storage/connect/mycat.cc
  modified:   storage/connect/tabjson.cpp

- Add conditional code based on MARIADB
  This to be able to use the same code in CONNECT and EOM modules
  modified:   storage/connect/osutil.h
  modified:   storage/connect/tabrest.cpp

- Replace PlugSetPath by some concat (crashed on Fedora) + typo
  modified:   storage/connect/reldef.cpp

- Try to fix test failures
  modified:   zlib/CMakeLists.txt
parent d302cb35
...@@ -68,6 +68,10 @@ ELSE(NOT UNIX) ...@@ -68,6 +68,10 @@ ELSE(NOT UNIX)
tabwmi.cpp tabwmi.h tabmac.cpp tabmac.h macutil.cpp macutil.h) tabwmi.cpp tabwmi.h tabmac.cpp tabmac.h macutil.cpp macutil.h)
# Add exception handling to the CONNECT project) # Add exception handling to the CONNECT project)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /EHsc") SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /EHsc")
SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MD")
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MDd")
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /MD")
SET(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL} /MD")
SET(IPHLPAPI_LIBRARY iphlpapi.lib) SET(IPHLPAPI_LIBRARY iphlpapi.lib)
IF(MSVC AND (CMAKE_CXX_COMPILER_ID MATCHES Clang)) IF(MSVC AND (CMAKE_CXX_COMPILER_ID MATCHES Clang))
# Connect does not work with clang-cl # Connect does not work with clang-cl
...@@ -315,6 +319,12 @@ IF(CONNECT_WITH_REST) ...@@ -315,6 +319,12 @@ IF(CONNECT_WITH_REST)
FIND_PACKAGE(cpprestsdk) FIND_PACKAGE(cpprestsdk)
IF (cpprestsdk_FOUND) IF (cpprestsdk_FOUND)
MESSAGE(STATUS "=====> cpprestsdk found") MESSAGE(STATUS "=====> cpprestsdk found")
IF(UNIX)
# INCLUDE_DIRECTORIES(${CPPRESTSDK_INCLUDE_DIR})
# Edit next line to set the path to libcpprest.so
SET(REST_LIBRARY -L/usr/lib64 -lcpprest)
MESSAGE (STATUS ${REST_LIBRARY})
ENDIF(UNIX)
SET(CONNECT_SOURCES ${CONNECT_SOURCES} tabrest.cpp restget.cpp tabrest.h) SET(CONNECT_SOURCES ${CONNECT_SOURCES} tabrest.cpp restget.cpp tabrest.h)
add_definitions(-DREST_SUPPORT) add_definitions(-DREST_SUPPORT)
ELSE(NOT cpprestsdk_FOUND) ELSE(NOT cpprestsdk_FOUND)
...@@ -341,7 +351,7 @@ MYSQL_ADD_PLUGIN(connect ${CONNECT_SOURCES} ...@@ -341,7 +351,7 @@ MYSQL_ADD_PLUGIN(connect ${CONNECT_SOURCES}
COMPONENT connect-engine COMPONENT connect-engine
RECOMPILE_FOR_EMBEDDED RECOMPILE_FOR_EMBEDDED
LINK_LIBRARIES ${ZLIB_LIBRARY} ${XML_LIBRARY} ${ICONV_LIBRARY} LINK_LIBRARIES ${ZLIB_LIBRARY} ${XML_LIBRARY} ${ICONV_LIBRARY}
${ODBC_LIBRARY} ${JDBC_LIBRARY} ${MONGOC_LIBRARY} ${IPHLPAPI_LIBRARY}) ${ODBC_LIBRARY} ${JDBC_LIBRARY} ${MONGOC_LIBRARY} ${IPHLPAPI_LIBRARY} ${REST_LIBRARY})
IF(NOT TARGET connect) IF(NOT TARGET connect)
RETURN() RETURN()
...@@ -349,8 +359,8 @@ ENDIF() ...@@ -349,8 +359,8 @@ ENDIF()
IF(WIN32) IF(WIN32)
IF (libmongoc-1.0_FOUND) IF (libmongoc-1.0_FOUND)
SET_TARGET_PROPERTIES(connect PROPERTIES LINK_FLAGS SET_TARGET_PROPERTIES(connect PROPERTIES LINK_FLAGS
"/DELAYLOAD:libbson-1.0.dll /DELAYLOAD:libmongoc-1.0.dll") "/DELAYLOAD:libbson-1.0.dll /DELAYLOAD:libmongoc-1.0.dll")
ENDIF(libmongoc-1.0_FOUND) ENDIF(libmongoc-1.0_FOUND)
ENDIF(WIN32) ENDIF(WIN32)
...@@ -377,3 +387,4 @@ IF(CONNECT_WITH_JDBC AND JAVA_FOUND AND JNI_FOUND) ...@@ -377,3 +387,4 @@ IF(CONNECT_WITH_JDBC AND JAVA_FOUND AND JNI_FOUND)
${CMAKE_CURRENT_BINARY_DIR}/JdbcInterface.jar ${CMAKE_CURRENT_BINARY_DIR}/JdbcInterface.jar
DESTINATION ${INSTALL_PLUGINDIR} COMPONENT connect-engine) DESTINATION ${INSTALL_PLUGINDIR} COMPONENT connect-engine)
ENDIF() ENDIF()
/************* Array C++ Functions Source Code File (.CPP) *************/ /************* Array C++ Functions Source Code File (.CPP) *************/
/* Name: ARRAY.CPP Version 2.3 */ /* Name: ARRAY.CPP Version 2.3 */
/* */ /* */
/* (C) Copyright to the author Olivier BERTRAND 2005-2017 */ /* (C) Copyright to the author Olivier BERTRAND 2005-2019 */
/* */ /* */
/* This file contains the XOBJECT derived class ARRAY functions. */ /* This file contains the XOBJECT derived class ARRAY functions. */
/* ARRAY is used for elaborate type of processing, such as sorting */ /* ARRAY is used for elaborate type of processing, such as sorting */
...@@ -67,7 +67,7 @@ PARRAY MakeValueArray(PGLOBAL g, PPARM pp); // avoid gcc warning ...@@ -67,7 +67,7 @@ PARRAY MakeValueArray(PGLOBAL g, PPARM pp); // avoid gcc warning
/* MakeValueArray: Makes a value array from a value list. */ /* MakeValueArray: Makes a value array from a value list. */
/***********************************************************************/ /***********************************************************************/
PARRAY MakeValueArray(PGLOBAL g, PPARM pp) PARRAY MakeValueArray(PGLOBAL g, PPARM pp)
{ {
int n, valtyp = 0; int n, valtyp = 0;
size_t len = 0; size_t len = 0;
PARRAY par; PARRAY par;
...@@ -82,8 +82,7 @@ PARRAY MakeValueArray(PGLOBAL g, PPARM pp) ...@@ -82,8 +82,7 @@ PARRAY MakeValueArray(PGLOBAL g, PPARM pp)
if ((valtyp = pp->Type) != TYPE_STRING) if ((valtyp = pp->Type) != TYPE_STRING)
len = 1; len = 1;
if (trace(1)) xtrc(1, "valtyp=%d len=%d\n", valtyp, len);
htrc("valtyp=%d len=%d\n", valtyp, len);
/*********************************************************************/ /*********************************************************************/
/* Firstly check the list and count the number of values in it. */ /* Firstly check the list and count the number of values in it. */
...@@ -127,13 +126,13 @@ PARRAY MakeValueArray(PGLOBAL g, PPARM pp) ...@@ -127,13 +126,13 @@ PARRAY MakeValueArray(PGLOBAL g, PPARM pp)
// Integer stored inside pp->Value // Integer stored inside pp->Value
par->AddValue(g, parmp->Intval); par->AddValue(g, parmp->Intval);
break; break;
} // endswitch valtyp } // endswitch valtyp
/*********************************************************************/ /*********************************************************************/
/* Send back resulting array. */ /* Send back resulting array. */
/*********************************************************************/ /*********************************************************************/
return par; return par;
} // end of MakeValueArray } // end of MakeValueArray
/* -------------------------- Class ARRAY ---------------------------- */ /* -------------------------- Class ARRAY ---------------------------- */
...@@ -151,6 +150,9 @@ ARRAY::ARRAY(PGLOBAL g, int type, int size, int length, int prec) ...@@ -151,6 +150,9 @@ ARRAY::ARRAY(PGLOBAL g, int type, int size, int length, int prec)
Type = type; Type = type;
Xsize = -1; Xsize = -1;
Len = 1; Len = 1;
X = 0;
Inf = 0;
Sup = 0;
switch (type) { switch (type) {
case TYPE_STRING: case TYPE_STRING:
...@@ -281,130 +283,109 @@ void ARRAY::Empty(void) ...@@ -281,130 +283,109 @@ void ARRAY::Empty(void)
/* Add a string element to an array. */ /* Add a string element to an array. */
/***********************************************************************/ /***********************************************************************/
bool ARRAY::AddValue(PGLOBAL g, PSZ strp) bool ARRAY::AddValue(PGLOBAL g, PSZ strp)
{ {
if (Type != TYPE_STRING) { if (Type != TYPE_STRING) {
sprintf(g->Message, MSG(ADD_BAD_TYPE), GetTypeName(Type), "CHAR"); sprintf(g->Message, MSG(ADD_BAD_TYPE), GetTypeName(Type), "CHAR");
return true; return true;
} // endif Type } // endif Type
if (trace(1))
htrc(" adding string(%d): '%s'\n", Nval, strp);
//Value->SetValue_psz(strp); xtrc(1, " adding string(%d): '%s'\n", Nval, strp);
//Vblp->SetValue(valp, Nval++);
Vblp->SetValue(strp, Nval++); Vblp->SetValue(strp, Nval++);
return false; return false;
} // end of AddValue } // end of AddValue
/***********************************************************************/ /***********************************************************************/
/* Add a char pointer element to an array. */ /* Add a char pointer element to an array. */
/***********************************************************************/ /***********************************************************************/
bool ARRAY::AddValue(PGLOBAL g, void *p) bool ARRAY::AddValue(PGLOBAL g, void *p)
{ {
if (Type != TYPE_PCHAR) { if (Type != TYPE_PCHAR) {
sprintf(g->Message, MSG(ADD_BAD_TYPE), GetTypeName(Type), "PCHAR"); sprintf(g->Message, MSG(ADD_BAD_TYPE), GetTypeName(Type), "PCHAR");
return true; return true;
} // endif Type } // endif Type
if (trace(1))
htrc(" adding pointer(%d): %p\n", Nval, p);
xtrc(1, " adding pointer(%d): %p\n", Nval, p);
Vblp->SetValue((PSZ)p, Nval++); Vblp->SetValue((PSZ)p, Nval++);
return false; return false;
} // end of AddValue } // end of AddValue
/***********************************************************************/ /***********************************************************************/
/* Add a short integer element to an array. */ /* Add a short integer element to an array. */
/***********************************************************************/ /***********************************************************************/
bool ARRAY::AddValue(PGLOBAL g, short n) bool ARRAY::AddValue(PGLOBAL g, short n)
{ {
if (Type != TYPE_SHORT) { if (Type != TYPE_SHORT) {
sprintf(g->Message, MSG(ADD_BAD_TYPE), GetTypeName(Type), "SHORT"); sprintf(g->Message, MSG(ADD_BAD_TYPE), GetTypeName(Type), "SHORT");
return true; return true;
} // endif Type } // endif Type
if (trace(1))
htrc(" adding SHORT(%d): %hd\n", Nval, n);
//Value->SetValue(n); xtrc(1, " adding SHORT(%d): %hd\n", Nval, n);
//Vblp->SetValue(valp, Nval++);
Vblp->SetValue(n, Nval++); Vblp->SetValue(n, Nval++);
return false; return false;
} // end of AddValue } // end of AddValue
/***********************************************************************/ /***********************************************************************/
/* Add an integer element to an array. */ /* Add an integer element to an array. */
/***********************************************************************/ /***********************************************************************/
bool ARRAY::AddValue(PGLOBAL g, int n) bool ARRAY::AddValue(PGLOBAL g, int n)
{ {
if (Type != TYPE_INT) { if (Type != TYPE_INT) {
sprintf(g->Message, MSG(ADD_BAD_TYPE), GetTypeName(Type), "INTEGER"); sprintf(g->Message, MSG(ADD_BAD_TYPE), GetTypeName(Type), "INTEGER");
return true; return true;
} // endif Type } // endif Type
if (trace(1)) xtrc(1, " adding int(%d): %d\n", Nval, n);
htrc(" adding int(%d): %d\n", Nval, n);
//Value->SetValue(n);
//Vblp->SetValue(valp, Nval++);
Vblp->SetValue(n, Nval++); Vblp->SetValue(n, Nval++);
return false; return false;
} // end of AddValue } // end of AddValue
/***********************************************************************/ /***********************************************************************/
/* Add a double float element to an array. */ /* Add a double float element to an array. */
/***********************************************************************/ /***********************************************************************/
bool ARRAY::AddValue(PGLOBAL g, double d) bool ARRAY::AddValue(PGLOBAL g, double d)
{ {
if (Type != TYPE_DOUBLE) { if (Type != TYPE_DOUBLE) {
sprintf(g->Message, MSG(ADD_BAD_TYPE), GetTypeName(Type), "DOUBLE"); sprintf(g->Message, MSG(ADD_BAD_TYPE), GetTypeName(Type), "DOUBLE");
return true; return true;
} // endif Type } // endif Type
if (trace(1))
htrc(" adding float(%d): %lf\n", Nval, d);
xtrc(1, " adding float(%d): %lf\n", Nval, d);
Value->SetValue(d); Value->SetValue(d);
Vblp->SetValue(Value, Nval++); Vblp->SetValue(Value, Nval++);
return false; return false;
} // end of AddValue } // end of AddValue
/***********************************************************************/ /***********************************************************************/
/* Add the value of a XOBJECT block to an array. */ /* Add the value of a XOBJECT block to an array. */
/***********************************************************************/ /***********************************************************************/
bool ARRAY::AddValue(PGLOBAL g, PXOB xp) bool ARRAY::AddValue(PGLOBAL g, PXOB xp)
{ {
if (Type != xp->GetResultType()) { if (Type != xp->GetResultType()) {
sprintf(g->Message, MSG(ADD_BAD_TYPE), sprintf(g->Message, MSG(ADD_BAD_TYPE),
GetTypeName(xp->GetResultType()), GetTypeName(Type)); GetTypeName(xp->GetResultType()), GetTypeName(Type));
return true; return true;
} // endif Type } // endif Type
if (trace(1))
htrc(" adding (%d) from xp=%p\n", Nval, xp);
//AddValue(xp->GetValue()); xtrc(1, " adding (%d) from xp=%p\n", Nval, xp);
Vblp->SetValue(xp->GetValue(), Nval++); Vblp->SetValue(xp->GetValue(), Nval++);
return false; return false;
} // end of AddValue } // end of AddValue
/***********************************************************************/ /***********************************************************************/
/* Add a value to an array. */ /* Add a value to an array. */
/***********************************************************************/ /***********************************************************************/
bool ARRAY::AddValue(PGLOBAL g, PVAL vp) bool ARRAY::AddValue(PGLOBAL g, PVAL vp)
{ {
if (Type != vp->GetType()) { if (Type != vp->GetType()) {
sprintf(g->Message, MSG(ADD_BAD_TYPE), sprintf(g->Message, MSG(ADD_BAD_TYPE),
GetTypeName(vp->GetType()), GetTypeName(Type)); GetTypeName(vp->GetType()), GetTypeName(Type));
return true; return true;
} // endif Type } // endif Type
if (trace(1))
htrc(" adding (%d) from vp=%p\n", Nval, vp);
xtrc(1, " adding (%d) from vp=%p\n", Nval, vp);
Vblp->SetValue(vp, Nval++); Vblp->SetValue(vp, Nval++);
return false; return false;
} // end of AddValue } // end of AddValue
/***********************************************************************/ /***********************************************************************/
/* Retrieve the nth value of the array. */ /* Retrieve the nth value of the array. */
...@@ -973,7 +954,7 @@ int ARRAY::BlockTest(PGLOBAL, int opc, int opm, ...@@ -973,7 +954,7 @@ int ARRAY::BlockTest(PGLOBAL, int opc, int opm,
/* MakeArrayList: Makes a value list from an SQL IN array (in work). */ /* MakeArrayList: Makes a value list from an SQL IN array (in work). */
/***********************************************************************/ /***********************************************************************/
PSZ ARRAY::MakeArrayList(PGLOBAL g) PSZ ARRAY::MakeArrayList(PGLOBAL g)
{ {
char *p, *tp; char *p, *tp;
int i; int i;
size_t z, len = 2; size_t z, len = 2;
...@@ -988,11 +969,9 @@ PSZ ARRAY::MakeArrayList(PGLOBAL g) ...@@ -988,11 +969,9 @@ PSZ ARRAY::MakeArrayList(PGLOBAL g)
Value->SetValue_pvblk(Vblp, i); Value->SetValue_pvblk(Vblp, i);
Value->Prints(g, tp, z); Value->Prints(g, tp, z);
len += strlen(tp); len += strlen(tp);
} // enfor i } // enfor i
if (trace(1))
htrc("Arraylist: len=%d\n", len);
xtrc(1, "Arraylist: len=%d\n", len);
p = (char *)PlugSubAlloc(g, NULL, len); p = (char *)PlugSubAlloc(g, NULL, len);
strcpy(p, "("); strcpy(p, "(");
...@@ -1001,19 +980,17 @@ PSZ ARRAY::MakeArrayList(PGLOBAL g) ...@@ -1001,19 +980,17 @@ PSZ ARRAY::MakeArrayList(PGLOBAL g)
Value->Prints(g, tp, z); Value->Prints(g, tp, z);
strcat(p, tp); strcat(p, tp);
strcat(p, (++i == Nval) ? ")" : ","); strcat(p, (++i == Nval) ? ")" : ",");
} // enfor i } // enfor i
if (trace(1))
htrc("Arraylist: newlen=%d\n", strlen(p));
xtrc(1, "Arraylist: newlen=%d\n", strlen(p));
return p; return p;
} // end of MakeArrayList } // end of MakeArrayList
/***********************************************************************/ /***********************************************************************/
/* Make file output of ARRAY contents. */ /* Make file output of ARRAY contents. */
/***********************************************************************/ /***********************************************************************/
void ARRAY::Printf(PGLOBAL g, FILE *f, uint n) void ARRAY::Printf(PGLOBAL g, FILE *f, uint n)
{ {
char m[64]; char m[64];
int lim = MY_MIN(Nval,10); int lim = MY_MIN(Nval,10);
...@@ -1035,19 +1012,19 @@ void ARRAY::Printf(PGLOBAL g, FILE *f, uint n) ...@@ -1035,19 +1012,19 @@ void ARRAY::Printf(PGLOBAL g, FILE *f, uint n)
} else } else
fprintf(f, "%sVALLST: numval=%d\n", m, Nval); fprintf(f, "%sVALLST: numval=%d\n", m, Nval);
} // end of Printf } // end of Printf
/***********************************************************************/ /***********************************************************************/
/* Make string output of ARRAY contents. */ /* Make string output of ARRAY contents. */
/***********************************************************************/ /***********************************************************************/
void ARRAY::Prints(PGLOBAL, char *ps, uint z) void ARRAY::Prints(PGLOBAL, char *ps, uint z)
{ {
if (z < 16) if (z < 16)
return; return;
sprintf(ps, "ARRAY: type=%d\n", Type); sprintf(ps, "ARRAY: type=%d\n", Type);
// More to be implemented later // More to be implemented later
} // end of Prints } // end of Prints
/* -------------------------- Class MULAR ---------------------------- */ /* -------------------------- Class MULAR ---------------------------- */
......
...@@ -38,9 +38,7 @@ typedef class BLOCK *PBLOCK; ...@@ -38,9 +38,7 @@ typedef class BLOCK *PBLOCK;
class DllExport BLOCK { class DllExport BLOCK {
public: public:
void * operator new(size_t size, PGLOBAL g, void *p = NULL) { void * operator new(size_t size, PGLOBAL g, void *p = NULL) {
if (trace(256)) xtrc(256, "New BLOCK: size=%d g=%p p=%p\n", size, g, p);
htrc("New BLOCK: size=%d g=%p p=%p\n", size, g, p);
return (PlugSubAlloc(g, p, size)); return (PlugSubAlloc(g, p, size));
} // end of new } // end of new
......
...@@ -224,6 +224,7 @@ DllExport void *PlugSubAlloc(PGLOBAL, void *, size_t); ...@@ -224,6 +224,7 @@ DllExport void *PlugSubAlloc(PGLOBAL, void *, size_t);
DllExport char *PlugDup(PGLOBAL g, const char *str); DllExport char *PlugDup(PGLOBAL g, const char *str);
DllExport void *MakePtr(void *, OFFSET); DllExport void *MakePtr(void *, OFFSET);
DllExport void htrc(char const *fmt, ...); DllExport void htrc(char const *fmt, ...);
DllExport void xtrc(uint, char const* fmt, ...);
DllExport uint GetTraceValue(void); DllExport uint GetTraceValue(void);
#if defined(__cplusplus) #if defined(__cplusplus)
......
...@@ -241,7 +241,9 @@ int TranslateJDBCType(int stp, char *tn, int prec, int& len, char& v); ...@@ -241,7 +241,9 @@ int TranslateJDBCType(int stp, char *tn, int prec, int& len, char& v);
void PushWarning(PGLOBAL g, THD *thd, int level); void PushWarning(PGLOBAL g, THD *thd, int level);
bool CheckSelf(PGLOBAL g, TABLE_SHARE *s, PCSZ host, PCSZ db, bool CheckSelf(PGLOBAL g, TABLE_SHARE *s, PCSZ host, PCSZ db,
PCSZ tab, PCSZ src, int port); PCSZ tab, PCSZ src, int port);
#if defined(ZIP_SUPPORT)
bool ZipLoadFile(PGLOBAL, PCSZ, PCSZ, PCSZ, bool, bool); bool ZipLoadFile(PGLOBAL, PCSZ, PCSZ, PCSZ, bool, bool);
#endif // ZIP_SUPPORT
bool ExactInfo(void); bool ExactInfo(void);
#if defined(CMGO_SUPPORT) #if defined(CMGO_SUPPORT)
//void mongo_init(bool); //void mongo_init(bool);
...@@ -6730,6 +6732,7 @@ int ha_connect::create(const char *name, TABLE *table_arg, ...@@ -6730,6 +6732,7 @@ int ha_connect::create(const char *name, TABLE *table_arg,
if (trace(1)) if (trace(1))
htrc("xchk=%p createas=%d\n", g->Xchk, g->Createas); htrc("xchk=%p createas=%d\n", g->Xchk, g->Createas);
#if defined(ZIP_SUPPORT)
if (options->zipped) { if (options->zipped) {
// Check whether the zip entry must be made from a file // Check whether the zip entry must be made from a file
PCSZ fn= GetListOption(g, "Load", options->oplist, NULL); PCSZ fn= GetListOption(g, "Load", options->oplist, NULL);
...@@ -6759,6 +6762,7 @@ int ha_connect::create(const char *name, TABLE *table_arg, ...@@ -6759,6 +6762,7 @@ int ha_connect::create(const char *name, TABLE *table_arg,
} // endif fn } // endif fn
} // endif zipped } // endif zipped
#endif // ZIP_SUPPORT
// To check whether indexes have to be made or remade // To check whether indexes have to be made or remade
if (!g->Xchk) { if (!g->Xchk) {
......
/***********************************************************************/
/* Definitions needed by the included files. */
/***********************************************************************/
#if !defined(MY_GLOBAL_H)
#define MY_GLOBAL_H
typedef unsigned int uint;
typedef unsigned int uint32;
typedef unsigned short ushort;
typedef unsigned long ulong;
typedef unsigned long DWORD;
typedef char *LPSTR;
typedef const char *LPCSTR;
typedef int BOOL;
#if defined(_WINDOWS)
typedef void *HANDLE;
#else
typedef int HANDLE;
#endif
typedef char *PSZ;
typedef const char *PCSZ;
typedef unsigned char BYTE;
typedef unsigned char uchar;
typedef long long longlong;
typedef unsigned long long ulonglong;
typedef char my_bool;
struct charset_info_st {};
typedef const charset_info_st CHARSET_INFO;
#define FALSE 0
#define TRUE 1
#define Item char
#define MY_MAX(a,b) ((a>b)?(a):(b))
#define MY_MIN(a,b) ((a<b)?(a):(b))
#endif // MY_GLOBAL_H
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */
/*************** Mycat CC Program Source Code File (.CC) ***************/ /*************** Mycat CC Program Source Code File (.CC) ***************/
/* PROGRAM NAME: MYCAT */ /* PROGRAM NAME: MYCAT */
...@@ -95,7 +95,7 @@ ...@@ -95,7 +95,7 @@
#endif // ZIP_SUPPORT #endif // ZIP_SUPPORT
#if defined(REST_SUPPORT) #if defined(REST_SUPPORT)
#include "tabrest.h" #include "tabrest.h"
#endif // REST_SUPPORT #endif // Rest_SUPPORT
#include "mycat.h" #include "mycat.h"
/***********************************************************************/ /***********************************************************************/
...@@ -104,11 +104,9 @@ ...@@ -104,11 +104,9 @@
#if defined(__WIN__) #if defined(__WIN__)
extern "C" HINSTANCE s_hModule; // Saved module handle extern "C" HINSTANCE s_hModule; // Saved module handle
#endif // !__WIN__ #endif // !__WIN__
#if defined(JAVA_SUPPORT) || defined(CMGO_SUPPORT) #if defined(JAVA_SUPPORT) || defined(CMGO_SUPPORT)
bool MongoEnabled(void); bool MongoEnabled(void);
#endif // JAVA_SUPPORT || CMGO_SUPPORT #endif // JAVA_SUPPORT || CMGO_SUPPORT
PQRYRES OEMColumns(PGLOBAL g, PTOS topt, char *tab, char *db, bool info); PQRYRES OEMColumns(PGLOBAL g, PTOS topt, char *tab, char *db, bool info);
/***********************************************************************/ /***********************************************************************/
...@@ -124,11 +122,11 @@ char *GetPluginDir(void) ...@@ -124,11 +122,11 @@ char *GetPluginDir(void)
/***********************************************************************/ /***********************************************************************/
TABTYPE GetTypeID(const char *type) TABTYPE GetTypeID(const char *type)
{ {
return (!type) ? TAB_UNDEF return (!type) ? TAB_UNDEF
: (!stricmp(type, "DOS")) ? TAB_DOS : (!stricmp(type, "DOS")) ? TAB_DOS
: (!stricmp(type, "FIX")) ? TAB_FIX : (!stricmp(type, "FIX")) ? TAB_FIX
: (!stricmp(type, "BIN")) ? TAB_BIN : (!stricmp(type, "BIN")) ? TAB_BIN
: (!stricmp(type, "CSV")) ? TAB_CSV : (!stricmp(type, "CSV")) ? TAB_CSV
: (!stricmp(type, "FMT")) ? TAB_FMT : (!stricmp(type, "FMT")) ? TAB_FMT
: (!stricmp(type, "DBF")) ? TAB_DBF : (!stricmp(type, "DBF")) ? TAB_DBF
#if defined(XML_SUPPORT) #if defined(XML_SUPPORT)
...@@ -140,30 +138,30 @@ TABTYPE GetTypeID(const char *type) ...@@ -140,30 +138,30 @@ TABTYPE GetTypeID(const char *type)
: (!stricmp(type, "ODBC")) ? TAB_ODBC : (!stricmp(type, "ODBC")) ? TAB_ODBC
#endif #endif
#if defined(JAVA_SUPPORT) #if defined(JAVA_SUPPORT)
: (!stricmp(type, "JDBC")) ? TAB_JDBC : (!stricmp(type, "JDBC")) ? TAB_JDBC
#endif #endif
#if defined(JAVA_SUPPORT) || defined(CMGO_SUPPORT) #if defined(JAVA_SUPPORT) || defined(CMGO_SUPPORT)
: (!stricmp(type, "MONGO") && MongoEnabled()) ? TAB_MONGO : (!stricmp(type, "MONGO") && MongoEnabled()) ? TAB_MONGO
#endif #endif
: (!stricmp(type, "MYSQL")) ? TAB_MYSQL : (!stricmp(type, "MYSQL")) ? TAB_MYSQL
: (!stricmp(type, "MYPRX")) ? TAB_MYSQL : (!stricmp(type, "MYPRX")) ? TAB_MYSQL
: (!stricmp(type, "DIR")) ? TAB_DIR : (!stricmp(type, "DIR")) ? TAB_DIR
#if defined(__WIN__) #if defined(__WIN__)
: (!stricmp(type, "MAC")) ? TAB_MAC : (!stricmp(type, "MAC")) ? TAB_MAC
: (!stricmp(type, "WMI")) ? TAB_WMI : (!stricmp(type, "WMI")) ? TAB_WMI
#endif #endif
: (!stricmp(type, "TBL")) ? TAB_TBL : (!stricmp(type, "TBL")) ? TAB_TBL
: (!stricmp(type, "XCOL")) ? TAB_XCL : (!stricmp(type, "XCOL")) ? TAB_XCL
: (!stricmp(type, "OCCUR")) ? TAB_OCCUR : (!stricmp(type, "OCCUR")) ? TAB_OCCUR
: (!stricmp(type, "CATLG")) ? TAB_PRX // Legacy : (!stricmp(type, "CATLG")) ? TAB_PRX // Legacy
: (!stricmp(type, "PROXY")) ? TAB_PRX : (!stricmp(type, "PROXY")) ? TAB_PRX
: (!stricmp(type, "PIVOT")) ? TAB_PIVOT : (!stricmp(type, "PIVOT")) ? TAB_PIVOT
: (!stricmp(type, "VIR")) ? TAB_VIR : (!stricmp(type, "VIR")) ? TAB_VIR
: (!stricmp(type, "JSON")) ? TAB_JSON : (!stricmp(type, "JSON")) ? TAB_JSON
#if defined(ZIP_SUPPORT) #if defined(ZIP_SUPPORT)
: (!stricmp(type, "ZIP")) ? TAB_ZIP : (!stricmp(type, "ZIP")) ? TAB_ZIP
#endif #endif
: (!stricmp(type, "OEM")) ? TAB_OEM : TAB_NIY; : (!stricmp(type, "OEM")) ? TAB_OEM : TAB_NIY;
} // end of GetTypeID } // end of GetTypeID
/***********************************************************************/ /***********************************************************************/
...@@ -173,19 +171,19 @@ bool IsFileType(TABTYPE type) ...@@ -173,19 +171,19 @@ bool IsFileType(TABTYPE type)
{ {
bool isfile; bool isfile;
switch (type) { switch (type) {
case TAB_DOS: case TAB_DOS:
case TAB_FIX: case TAB_FIX:
case TAB_BIN: case TAB_BIN:
case TAB_CSV: case TAB_CSV:
case TAB_FMT: case TAB_FMT:
case TAB_DBF: case TAB_DBF:
case TAB_XML: case TAB_XML:
case TAB_INI: case TAB_INI:
case TAB_VEC: case TAB_VEC:
case TAB_JSON: case TAB_JSON:
case TAB_REST: case TAB_REST:
// case TAB_ZIP: // case TAB_ZIP:
isfile= true; isfile= true;
break; break;
default: default:
...@@ -203,7 +201,7 @@ bool IsExactType(TABTYPE type) ...@@ -203,7 +201,7 @@ bool IsExactType(TABTYPE type)
{ {
bool exact; bool exact;
switch (type) { switch (type) {
case TAB_FIX: case TAB_FIX:
case TAB_BIN: case TAB_BIN:
case TAB_DBF: case TAB_DBF:
...@@ -228,7 +226,7 @@ bool IsTypeNullable(TABTYPE type) ...@@ -228,7 +226,7 @@ bool IsTypeNullable(TABTYPE type)
{ {
bool nullable; bool nullable;
switch (type) { switch (type) {
case TAB_MAC: case TAB_MAC:
case TAB_DIR: case TAB_DIR:
nullable= false; nullable= false;
...@@ -248,7 +246,7 @@ bool IsTypeFixed(TABTYPE type) ...@@ -248,7 +246,7 @@ bool IsTypeFixed(TABTYPE type)
{ {
bool fix; bool fix;
switch (type) { switch (type) {
case TAB_FIX: case TAB_FIX:
case TAB_BIN: case TAB_BIN:
case TAB_VEC: case TAB_VEC:
...@@ -270,7 +268,7 @@ bool IsTypeIndexable(TABTYPE type) ...@@ -270,7 +268,7 @@ bool IsTypeIndexable(TABTYPE type)
{ {
bool idx; bool idx;
switch (type) { switch (type) {
case TAB_DOS: case TAB_DOS:
case TAB_CSV: case TAB_CSV:
case TAB_FMT: case TAB_FMT:
...@@ -296,7 +294,7 @@ int GetIndexType(TABTYPE type) ...@@ -296,7 +294,7 @@ int GetIndexType(TABTYPE type)
{ {
int xtyp; int xtyp;
switch (type) { switch (type) {
case TAB_DOS: case TAB_DOS:
case TAB_CSV: case TAB_CSV:
case TAB_FMT: case TAB_FMT:
...@@ -309,9 +307,9 @@ int GetIndexType(TABTYPE type) ...@@ -309,9 +307,9 @@ int GetIndexType(TABTYPE type)
break; break;
case TAB_MYSQL: case TAB_MYSQL:
case TAB_ODBC: case TAB_ODBC:
case TAB_JDBC: case TAB_JDBC:
case TAB_MONGO: case TAB_MONGO:
xtyp= 2; xtyp= 2;
break; break;
case TAB_VIR: case TAB_VIR:
xtyp= 3; xtyp= 3;
...@@ -383,7 +381,7 @@ PQRYRES OEMColumns(PGLOBAL g, PTOS topt, char *tab, char *db, bool info) ...@@ -383,7 +381,7 @@ PQRYRES OEMColumns(PGLOBAL g, PTOS topt, char *tab, char *db, bool info)
return NULL; return NULL;
} else } else
PlugSetPath(soname, module, GetPluginDir()); PlugSetPath(soname, module, GetPluginDir());
// The exported name is always in uppercase // The exported name is always in uppercase
for (int i = 0; ; i++) { for (int i = 0; ; i++) {
c = subtype[i]; c = subtype[i];
...@@ -460,7 +458,7 @@ CATALOG::CATALOG(void) ...@@ -460,7 +458,7 @@ CATALOG::CATALOG(void)
memset(&Ctb, 0, sizeof(CURTAB)); memset(&Ctb, 0, sizeof(CURTAB));
Cbuf= NULL; Cbuf= NULL;
Cblen= 0; Cblen= 0;
DefHuge= false; DefHuge= false;
} // end of CATALOG constructor } // end of CATALOG constructor
/* -------------------------- Class MYCAT ---------------------------- */ /* -------------------------- Class MYCAT ---------------------------- */
...@@ -470,7 +468,7 @@ CATALOG::CATALOG(void) ...@@ -470,7 +468,7 @@ CATALOG::CATALOG(void)
/***********************************************************************/ /***********************************************************************/
MYCAT::MYCAT(PHC hc) : CATALOG() MYCAT::MYCAT(PHC hc) : CATALOG()
{ {
Hc= hc; Hc= hc;
DefHuge= false; DefHuge= false;
} // end of MYCAT constructor } // end of MYCAT constructor
...@@ -487,16 +485,23 @@ void MYCAT::Reset(void) ...@@ -487,16 +485,23 @@ void MYCAT::Reset(void)
/***********************************************************************/ /***********************************************************************/
PRELDEF MYCAT::GetTableDesc(PGLOBAL g, PTABLE tablep, PRELDEF MYCAT::GetTableDesc(PGLOBAL g, PTABLE tablep,
LPCSTR type, PRELDEF *) LPCSTR type, PRELDEF *)
{ {
if (trace(1)) PRELDEF tdp= NULL;
printf("GetTableDesc: name=%s am=%s\n", tablep->GetName(), SVP(type));
// If not specified get the type of this table if (trace(1))
htrc("GetTableDesc: name=%s am=%s\n", tablep->GetName(), SVP(type));
// If not specified get the type of this table
//if (!type) //if (!type)
// type= Hc->GetStringOption("Type","*"); // type= Hc->GetStringOption("Type","*");
return MakeTableDesc(g, tablep, type); tdp= MakeTableDesc(g, tablep, type);
} // end of GetTableDesc
if (trace(1))
htrc("GetTableDesc: tdp=%p\n", tdp);
return tdp;
} // end of GetTableDesc
/***********************************************************************/ /***********************************************************************/
/* MakeTableDesc: make a table/view description. */ /* MakeTableDesc: make a table/view description. */
...@@ -505,22 +510,22 @@ PRELDEF MYCAT::GetTableDesc(PGLOBAL g, PTABLE tablep, ...@@ -505,22 +510,22 @@ PRELDEF MYCAT::GetTableDesc(PGLOBAL g, PTABLE tablep,
PRELDEF MYCAT::MakeTableDesc(PGLOBAL g, PTABLE tablep, LPCSTR am) PRELDEF MYCAT::MakeTableDesc(PGLOBAL g, PTABLE tablep, LPCSTR am)
{ {
TABTYPE tc; TABTYPE tc;
LPCSTR name= (PSZ)PlugDup(g, tablep->GetName()); LPCSTR name= (PSZ)PlugDup(g, tablep->GetName());
LPCSTR schema= (PSZ)PlugDup(g, tablep->GetSchema()); LPCSTR schema= (PSZ)PlugDup(g, tablep->GetSchema());
PRELDEF tdp= NULL; PRELDEF tdp= NULL;
if (trace(1)) if (trace(1))
printf("MakeTableDesc: name=%s schema=%s am=%s\n", htrc("MakeTableDesc: name=%s schema=%s am=%s\n",
name, SVP(schema), SVP(am)); name, SVP(schema), SVP(am));
/*********************************************************************/ /*********************************************************************/
/* Get a unique enum identifier for types. */ /* Get a unique enum identifier for types. */
/*********************************************************************/ /*********************************************************************/
if (!am) { if (!am) {
tc = Hc->GetRealType(); tc= Hc->GetRealType();
am = Hc->GetStringOption("Type", "*"); am= Hc->GetStringOption("Type","*");
} else } else
tc = GetTypeID(am); tc= GetTypeID(am);
switch (tc) { switch (tc) {
case TAB_FIX: case TAB_FIX:
...@@ -535,49 +540,52 @@ PRELDEF MYCAT::MakeTableDesc(PGLOBAL g, PTABLE tablep, LPCSTR am) ...@@ -535,49 +540,52 @@ PRELDEF MYCAT::MakeTableDesc(PGLOBAL g, PTABLE tablep, LPCSTR am)
case TAB_XML: tdp= new(g) XMLDEF; break; case TAB_XML: tdp= new(g) XMLDEF; break;
#endif // XML_SUPPORT #endif // XML_SUPPORT
#if defined(VCT_SUPPORT) #if defined(VCT_SUPPORT)
case TAB_VEC: tdp = new(g) VCTDEF; break; case TAB_VEC: tdp = new(g) VCTDEF; break;
#endif // VCT_SUPPORT #endif // VCT_SUPPORT
#if defined(ODBC_SUPPORT) #if defined(ODBC_SUPPORT)
case TAB_ODBC: tdp= new(g) ODBCDEF; break; case TAB_ODBC: tdp= new(g) ODBCDEF; break;
#endif // ODBC_SUPPORT #endif // ODBC_SUPPORT
#if defined(JAVA_SUPPORT) #if defined(JAVA_SUPPORT)
case TAB_JDBC: tdp= new(g) JDBCDEF; break; case TAB_JDBC: tdp= new(g) JDBCDEF; break;
#endif // JAVA_SUPPORT #endif // JAVA_SUPPORT
#if defined(__WIN__) #if defined(__WIN__)
case TAB_MAC: tdp= new(g) MACDEF; break; case TAB_MAC: tdp= new(g) MACDEF; break;
case TAB_WMI: tdp= new(g) WMIDEF; break; case TAB_WMI: tdp= new(g) WMIDEF; break;
#endif // __WIN__ #endif // __WIN__
case TAB_OEM: tdp= new(g) OEMDEF; break; case TAB_OEM: tdp= new(g) OEMDEF; break;
case TAB_TBL: tdp= new(g) TBLDEF; break; case TAB_TBL: tdp= new(g) TBLDEF; break;
case TAB_XCL: tdp= new(g) XCLDEF; break; case TAB_XCL: tdp= new(g) XCLDEF; break;
case TAB_PRX: tdp= new(g) PRXDEF; break; case TAB_PRX: tdp= new(g) PRXDEF; break;
case TAB_OCCUR: tdp= new(g) OCCURDEF; break; case TAB_OCCUR: tdp= new(g) OCCURDEF; break;
case TAB_MYSQL: tdp= new(g) MYSQLDEF; break; case TAB_MYSQL: tdp= new(g) MYSQLDEF; break;
case TAB_PIVOT: tdp= new(g) PIVOTDEF; break; case TAB_PIVOT: tdp= new(g) PIVOTDEF; break;
case TAB_VIR: tdp= new(g) VIRDEF; break; case TAB_VIR: tdp= new(g) VIRDEF; break;
case TAB_JSON: tdp= new(g) JSONDEF; break; case TAB_JSON: tdp= new(g) JSONDEF; break;
#if defined(ZIP_SUPPORT) #if defined(ZIP_SUPPORT)
case TAB_ZIP: tdp= new(g) ZIPDEF; break; case TAB_ZIP: tdp = new(g) ZIPDEF; break;
#endif // ZIP_SUPPORT #endif // ZIP_SUPPORT
#if defined(REST_SUPPORT) #if defined(REST_SUPPORT)
case TAB_REST: tdp= new(g) RESTDEF; break; case TAB_REST: tdp= new (g) RESTDEF; break;
#endif // REST_SUPPORT #endif // REST_SUPPORT
#if defined(JAVA_SUPPORT) || defined(CMGO_SUPPORT) #if defined(JAVA_SUPPORT) || defined(CMGO_SUPPORT)
case TAB_MONGO: case TAB_MONGO:
if (MongoEnabled()) { if (MongoEnabled()) {
tdp = new(g) MGODEF; tdp = new(g) MGODEF;
break; break;
} // endif enabled } // endif enabled
// fall through // fall through
#endif // JAVA_SUPPORT || CMGO_SUPPORT #endif // JAVA_SUPPORT || CMGO_SUPPORT
default: default:
sprintf(g->Message, MSG(BAD_TABLE_TYPE), am, name); sprintf(g->Message, MSG(BAD_TABLE_TYPE), am, name);
} // endswitch } // endswitch
// Do make the table/view definition // Do make the table/view definition
if (tdp && tdp->Define(g, this, name, schema, am)) if (tdp && tdp->Define(g, this, name, schema, am))
tdp= NULL; tdp= NULL;
if (trace(1))
htrc("Table %s made\n", am);
return tdp; return tdp;
} // end of MakeTableDesc } // end of MakeTableDesc
...@@ -590,26 +598,29 @@ PTDB MYCAT::GetTable(PGLOBAL g, PTABLE tablep, MODE mode, LPCSTR type) ...@@ -590,26 +598,29 @@ PTDB MYCAT::GetTable(PGLOBAL g, PTABLE tablep, MODE mode, LPCSTR type)
PTDB tdbp= NULL; PTDB tdbp= NULL;
// LPCSTR name= tablep->GetName(); // LPCSTR name= tablep->GetName();
if (trace(1)) if (trace(1))
printf("GetTableDB: name=%s\n", tablep->GetName()); htrc("GetTableDB: name=%s\n", tablep->GetName());
// Look for the description of the requested table // Look for the description of the requested table
tdp= GetTableDesc(g, tablep, type); tdp= GetTableDesc(g, tablep, type);
if (tdp) { if (tdp) {
if (trace(1)) if (trace(1))
printf("tdb=%p type=%s\n", tdp, tdp->GetType()); htrc("tdb=%p type=%s\n", tdp, tdp->GetType());
if (tablep->GetSchema())
tdp->Database = SetPath(g, tablep->GetSchema());
if (trace(2))
htrc("Going to get table...\n");
if (tablep->GetSchema())
tdp->Database = SetPath(g, tablep->GetSchema());
tdbp= tdp->GetTable(g, mode); tdbp= tdp->GetTable(g, mode);
} // endif tdp } // endif tdp
if (tdbp) { if (tdbp) {
if (trace(1)) if (trace(1))
printf("tdbp=%p name=%s amtype=%d\n", tdbp, tdbp->GetName(), htrc("tdbp=%p name=%s amtype=%d\n", tdbp, tdbp->GetName(),
tdbp->GetAmType()); tdbp->GetAmType());
tablep->SetTo_Tdb(tdbp); tablep->SetTo_Tdb(tdbp);
tdbp->SetTable(tablep); tdbp->SetTable(tablep);
tdbp->SetMode(mode); tdbp->SetMode(mode);
......
...@@ -3,7 +3,11 @@ ...@@ -3,7 +3,11 @@
#define __OSUTIL_H__ #define __OSUTIL_H__
#if defined(UNIX) || defined(UNIV_LINUX) #if defined(UNIX) || defined(UNIV_LINUX)
#if defined(MARIADB)
#include "my_global.h" #include "my_global.h"
#else
#include "mini-global.h"
#endif
#include <errno.h> #include <errno.h>
#include <stddef.h> #include <stddef.h>
#include "os.h" #include "os.h"
......
...@@ -2,11 +2,11 @@ ...@@ -2,11 +2,11 @@
/* */ /* */
/* PROGRAM NAME: PLUGUTIL */ /* PROGRAM NAME: PLUGUTIL */
/* ------------- */ /* ------------- */
/* Version 3.0 */ /* Version 3.1 */
/* */ /* */
/* COPYRIGHT: */ /* COPYRIGHT: */
/* ---------- */ /* ---------- */
/* (C) Copyright to the author Olivier BERTRAND 1993-2017 */ /* (C) Copyright to the author Olivier BERTRAND 1993-2019 */
/* */ /* */
/* WHAT THIS PROGRAM DOES: */ /* WHAT THIS PROGRAM DOES: */
/* ----------------------- */ /* ----------------------- */
...@@ -111,21 +111,31 @@ ACTIVITY defActivity = { /* Describes activity and language */ ...@@ -111,21 +111,31 @@ ACTIVITY defActivity = { /* Describes activity and language */
#endif // UNIX #endif // UNIX
/**************************************************************************/ /**************************************************************************/
/* Tracing output function. */ /* Conditional tracing output function. */
/**************************************************************************/ /**************************************************************************/
void htrc(char const *fmt, ...) void xtrc(uint x, char const *fmt, ...)
{ {
va_list ap; if (GetTraceValue() & x) {
va_start (ap, fmt); va_list ap;
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
} // endif x
} // end of xtrc
//if (trace == 1) /**************************************************************************/
// vfprintf(debug, fmt, ap); /* Tracing output function. */
//else /**************************************************************************/
vfprintf(stderr, fmt, ap); void htrc(char const* fmt, ...)
{
va_list ap;
va_start(ap, fmt);
va_end (ap); vfprintf(stderr, fmt, ap);
} // end of htrc va_end(ap);
} // end of htrc
/***********************************************************************/ /***********************************************************************/
/* Plug initialization routine. */ /* Plug initialization routine. */
......
...@@ -81,51 +81,51 @@ RELDEF::RELDEF(void) ...@@ -81,51 +81,51 @@ RELDEF::RELDEF(void)
/* This function return a pointer to the Table Option Struct. */ /* This function return a pointer to the Table Option Struct. */
/***********************************************************************/ /***********************************************************************/
PTOS RELDEF::GetTopt(void) PTOS RELDEF::GetTopt(void)
{ {
return Hc->GetTableOptionStruct(); return Hc->GetTableOptionStruct();
} // end of GetTopt } // end of GetTopt
/***********************************************************************/ /***********************************************************************/
/* This function sets an integer table information. */ /* This function sets an integer table information. */
/***********************************************************************/ /***********************************************************************/
bool RELDEF::SetIntCatInfo(PCSZ what, int n) bool RELDEF::SetIntCatInfo(PCSZ what, int n)
{ {
return Hc->SetIntegerOption(what, n); return Hc->SetIntegerOption(what, n);
} // end of SetIntCatInfo } // end of SetIntCatInfo
/***********************************************************************/ /***********************************************************************/
/* This function returns integer table information. */ /* This function returns integer table information. */
/***********************************************************************/ /***********************************************************************/
int RELDEF::GetIntCatInfo(PCSZ what, int idef) int RELDEF::GetIntCatInfo(PCSZ what, int idef)
{ {
int n= Hc->GetIntegerOption(what); int n= Hc->GetIntegerOption(what);
return (n == NO_IVAL) ? idef : n; return (n == NO_IVAL) ? idef : n;
} // end of GetIntCatInfo } // end of GetIntCatInfo
/***********************************************************************/ /***********************************************************************/
/* This function returns Boolean table information. */ /* This function returns Boolean table information. */
/***********************************************************************/ /***********************************************************************/
bool RELDEF::GetBoolCatInfo(PCSZ what, bool bdef) bool RELDEF::GetBoolCatInfo(PCSZ what, bool bdef)
{ {
bool b= Hc->GetBooleanOption(what, bdef); bool b= Hc->GetBooleanOption(what, bdef);
return b; return b;
} // end of GetBoolCatInfo } // end of GetBoolCatInfo
/***********************************************************************/ /***********************************************************************/
/* This function returns size catalog information. */ /* This function returns size catalog information. */
/***********************************************************************/ /***********************************************************************/
int RELDEF::GetSizeCatInfo(PCSZ what, PCSZ sdef) int RELDEF::GetSizeCatInfo(PCSZ what, PCSZ sdef)
{ {
char c; char c;
PCSZ s; PCSZ s;
int i, n= 0; int i, n= 0;
if (!(s= Hc->GetStringOption(what))) if (!(s= Hc->GetStringOption(what)))
s= sdef; s= sdef;
if ((i= sscanf(s, " %d %c ", &n, &c)) == 2) if ((i= sscanf(s, " %d %c ", &n, &c)) == 2)
switch (toupper(c)) { switch (toupper(c)) {
case 'M': case 'M':
n *= 1024; n *= 1024;
...@@ -141,41 +141,41 @@ int RELDEF::GetSizeCatInfo(PCSZ what, PCSZ sdef) ...@@ -141,41 +141,41 @@ int RELDEF::GetSizeCatInfo(PCSZ what, PCSZ sdef)
/* This function sets char table information in buf. */ /* This function sets char table information in buf. */
/***********************************************************************/ /***********************************************************************/
int RELDEF::GetCharCatInfo(PCSZ what, PCSZ sdef, char *buf, int size) int RELDEF::GetCharCatInfo(PCSZ what, PCSZ sdef, char *buf, int size)
{ {
PCSZ s= Hc->GetStringOption(what); PCSZ s= Hc->GetStringOption(what);
strncpy(buf, ((s) ? s : sdef), size); strncpy(buf, ((s) ? s : sdef), size);
return size; return size;
} // end of GetCharCatInfo } // end of GetCharCatInfo
/***********************************************************************/ /***********************************************************************/
/* To be used by any TDB's. */ /* To be used by any TDB's. */
/***********************************************************************/ /***********************************************************************/
bool RELDEF::Partitioned(void) bool RELDEF::Partitioned(void)
{ {
return Hc->IsPartitioned(); return Hc->IsPartitioned();
} // end of Partitioned } // end of Partitioned
/***********************************************************************/ /***********************************************************************/
/* This function returns string table information. */ /* This function returns string table information. */
/* Default parameter is "*" to get the handler default. */ /* Default parameter is "*" to get the handler default. */
/***********************************************************************/ /***********************************************************************/
char *RELDEF::GetStringCatInfo(PGLOBAL g, PCSZ what, PCSZ sdef) char *RELDEF::GetStringCatInfo(PGLOBAL g, PCSZ what, PCSZ sdef)
{ {
char *sval = NULL; char *sval = NULL;
PCSZ name, s= Hc->GetStringOption(what, sdef); PCSZ name, s= Hc->GetStringOption(what, sdef);
if (s) { if (s) {
if (!Hc->IsPartitioned() || if (!Hc->IsPartitioned() ||
(stricmp(what, "filename") && stricmp(what, "tabname") (stricmp(what, "filename") && stricmp(what, "tabname")
&& stricmp(what, "connect"))) && stricmp(what, "connect")))
sval= PlugDup(g, s); sval= PlugDup(g, s);
else else
sval= (char*)s; sval= (char*)s;
} else if (!stricmp(what, "filename")) { } else if (!stricmp(what, "filename")) {
// Return default file name // Return default file name
PCSZ ftype= Hc->GetStringOption("Type", "*"); PCSZ ftype= Hc->GetStringOption("Type", "*");
int i, n; int i, n;
if (IsFileType(GetTypeID(ftype))) { if (IsFileType(GetTypeID(ftype))) {
...@@ -183,7 +183,7 @@ char *RELDEF::GetStringCatInfo(PGLOBAL g, PCSZ what, PCSZ sdef) ...@@ -183,7 +183,7 @@ char *RELDEF::GetStringCatInfo(PGLOBAL g, PCSZ what, PCSZ sdef)
sval= (char*)PlugSubAlloc(g, NULL, strlen(name) + 12); sval= (char*)PlugSubAlloc(g, NULL, strlen(name) + 12);
strcat(strcpy(sval, name), "."); strcat(strcpy(sval, name), ".");
n= strlen(sval); n= strlen(sval);
// Fold ftype to lower case // Fold ftype to lower case
for (i= 0; i < 12; i++) for (i= 0; i < 12; i++)
if (!ftype[i]) { if (!ftype[i]) {
...@@ -196,8 +196,8 @@ char *RELDEF::GetStringCatInfo(PGLOBAL g, PCSZ what, PCSZ sdef) ...@@ -196,8 +196,8 @@ char *RELDEF::GetStringCatInfo(PGLOBAL g, PCSZ what, PCSZ sdef)
} // endif s } // endif s
return sval; return sval;
} // end of GetStringCatInfo } // end of GetStringCatInfo
/* --------------------------- Class TABDEF -------------------------- */ /* --------------------------- Class TABDEF -------------------------- */
...@@ -223,14 +223,14 @@ TABDEF::TABDEF(void) ...@@ -223,14 +223,14 @@ TABDEF::TABDEF(void)
/***********************************************************************/ /***********************************************************************/
/* Define: initialize the table definition block from XDB file. */ /* Define: initialize the table definition block from XDB file. */
/***********************************************************************/ /***********************************************************************/
bool TABDEF::Define(PGLOBAL g, PCATLG cat, bool TABDEF::Define(PGLOBAL g, PCATLG cat,
LPCSTR name, LPCSTR schema, LPCSTR am) LPCSTR name, LPCSTR schema, LPCSTR am)
{ {
int poff = 0; int poff = 0;
Hc = ((MYCAT*)cat)->GetHandler(); Hc = ((MYCAT*)cat)->GetHandler();
Name = (PSZ)name; Name = (PSZ)name;
Schema = (PSZ)Hc->GetDBName(schema); Schema = (PSZ)Hc->GetDBName(schema);
Cat = cat; Cat = cat;
Catfunc = GetFuncID(GetStringCatInfo(g, "Catfunc", NULL)); Catfunc = GetFuncID(GetStringCatInfo(g, "Catfunc", NULL));
Elemt = GetIntCatInfo("Elements", 0); Elemt = GetIntCatInfo("Elements", 0);
...@@ -263,14 +263,14 @@ PCSZ TABDEF::GetPath(void) ...@@ -263,14 +263,14 @@ PCSZ TABDEF::GetPath(void)
/* This function returns column table information. */ /* This function returns column table information. */
/***********************************************************************/ /***********************************************************************/
int TABDEF::GetColCatInfo(PGLOBAL g) int TABDEF::GetColCatInfo(PGLOBAL g)
{ {
char *type= GetStringCatInfo(g, "Type", "*"); char *type= GetStringCatInfo(g, "Type", "*");
char c, fty, eds; char c, fty, eds;
int i, n, loff, poff, nof, nlg; int i, n, loff, poff, nof, nlg;
void *field= NULL; void *field= NULL;
TABTYPE tc; TABTYPE tc;
PCOLDEF cdp, lcdp= NULL, tocols= NULL; PCOLDEF cdp, lcdp= NULL, tocols= NULL;
PCOLINFO pcf= (PCOLINFO)PlugSubAlloc(g, NULL, sizeof(COLINFO)); PCOLINFO pcf= (PCOLINFO)PlugSubAlloc(g, NULL, sizeof(COLINFO));
memset(pcf, 0, sizeof(COLINFO)); memset(pcf, 0, sizeof(COLINFO));
...@@ -278,33 +278,33 @@ int TABDEF::GetColCatInfo(PGLOBAL g) ...@@ -278,33 +278,33 @@ int TABDEF::GetColCatInfo(PGLOBAL g)
tc= (Catfunc == FNC_NO) ? GetTypeID(type) : TAB_PRX; tc= (Catfunc == FNC_NO) ? GetTypeID(type) : TAB_PRX;
// Take care of the column definitions // Take care of the column definitions
i= poff= nof= nlg= 0; i= poff= nof= nlg= 0;
#if defined(__WIN__) #if defined(__WIN__)
// Offsets of HTML and DIR tables start from 0, DBF at 1 // Offsets of HTML and DIR tables start from 0, DBF at 1
loff= (tc == TAB_DBF) ? 1 : (tc == TAB_XML || tc == TAB_DIR) ? -1 : 0; loff= (tc == TAB_DBF) ? 1 : (tc == TAB_XML || tc == TAB_DIR) ? -1 : 0;
#else // !__WIN__ #else // !__WIN__
// Offsets of HTML tables start from 0, DIR and DBF at 1 // Offsets of HTML tables start from 0, DIR and DBF at 1
loff = (tc == TAB_DBF || tc == TAB_DIR) ? 1 : (tc == TAB_XML) ? -1 : 0; loff = (tc == TAB_DBF || tc == TAB_DIR) ? 1 : (tc == TAB_XML) ? -1 : 0;
#endif // !__WIN__ #endif // !__WIN__
while (true) { while (true) {
// Default Offset depends on table type // Default Offset depends on table type
switch (tc) { switch (tc) {
case TAB_DOS: case TAB_DOS:
case TAB_FIX: case TAB_FIX:
case TAB_BIN: case TAB_BIN:
case TAB_VEC: case TAB_VEC:
case TAB_DBF: case TAB_DBF:
poff= loff + nof; // Default next offset poff= loff + nof; // Default next offset
nlg= MY_MAX(nlg, poff); // Default lrecl nlg= MY_MAX(nlg, poff); // Default lrecl
break; break;
case TAB_CSV: case TAB_CSV:
case TAB_FMT: case TAB_FMT:
nlg+= nof; nlg+= nof;
case TAB_DIR: case TAB_DIR:
case TAB_XML: case TAB_XML:
poff= loff + (pcf->Flags & U_VIRTUAL ? 0 : 1); poff= loff + (pcf->Flags & U_VIRTUAL ? 0 : 1);
break; break;
case TAB_INI: case TAB_INI:
case TAB_MAC: case TAB_MAC:
...@@ -316,39 +316,39 @@ int TABDEF::GetColCatInfo(PGLOBAL g) ...@@ -316,39 +316,39 @@ int TABDEF::GetColCatInfo(PGLOBAL g)
poff = 0; // Offset represents an independant flag poff = 0; // Offset represents an independant flag
break; break;
default: // VCT PLG ODBC JDBC MYSQL WMI... default: // VCT PLG ODBC JDBC MYSQL WMI...
poff = 0; // NA poff = 0; // NA
break; break;
} // endswitch tc } // endswitch tc
// do { // do {
field= Hc->GetColumnOption(g, field, pcf); field= Hc->GetColumnOption(g, field, pcf);
// } while (field && (*pcf->Name =='*' /*|| pcf->Flags & U_VIRTUAL*/)); // } while (field && (*pcf->Name =='*' /*|| pcf->Flags & U_VIRTUAL*/));
if (tc == TAB_DBF && pcf->Type == TYPE_DATE && !pcf->Datefmt) { if (tc == TAB_DBF && pcf->Type == TYPE_DATE && !pcf->Datefmt) {
// DBF date format defaults to 'YYYMMDD' // DBF date format defaults to 'YYYMMDD'
pcf->Datefmt= "YYYYMMDD"; pcf->Datefmt= "YYYYMMDD";
pcf->Length= 8; pcf->Length= 8;
} // endif tc } // endif tc
if (!field) if (!field)
break; break;
// Allocate the column description block // Allocate the column description block
cdp= new(g) COLDEF; cdp= new(g) COLDEF;
if ((nof= cdp->Define(g, NULL, pcf, poff)) < 0) if ((nof= cdp->Define(g, NULL, pcf, poff)) < 0)
return -1; // Error, probably unhandled type return -1; // Error, probably unhandled type
else else
loff= cdp->GetOffset(); loff= cdp->GetOffset();
switch (tc) { switch (tc) {
case TAB_VEC: case TAB_VEC:
cdp->SetOffset(0); // Not to have shift cdp->SetOffset(0); // Not to have shift
case TAB_BIN: case TAB_BIN:
// BIN/VEC are packed by default // BIN/VEC are packed by default
if (nof) { if (nof) {
// Field width is the internal representation width // Field width is the internal representation width
// that can also depend on the column format // that can also depend on the column format
fty = cdp->Decode ? 'C' : 'X'; fty = cdp->Decode ? 'C' : 'X';
eds = 0; eds = 0;
n = 0; n = 0;
...@@ -371,38 +371,38 @@ int TABDEF::GetColCatInfo(PGLOBAL g) ...@@ -371,38 +371,38 @@ int TABDEF::GetColCatInfo(PGLOBAL g)
if (n) if (n)
nof = n; nof = n;
else switch (fty) { else switch (fty) {
case 'X': case 'X':
if (eds && IsTypeChar(cdp->Buf_Type)) if (eds && IsTypeChar(cdp->Buf_Type))
nof = sizeof(longlong); nof = sizeof(longlong);
else else
nof= cdp->Clen; nof= cdp->Clen;
break; break;
case 'C': break; case 'C': break;
case 'R': case 'R':
case 'F': nof = sizeof(float); break; case 'F': nof = sizeof(float); break;
case 'I': nof = sizeof(int); break; case 'I': nof = sizeof(int); break;
case 'D': nof = sizeof(double); break; case 'D': nof = sizeof(double); break;
case 'S': nof = sizeof(short); break; case 'S': nof = sizeof(short); break;
case 'T': nof = sizeof(char); break; case 'T': nof = sizeof(char); break;
case 'G': nof = sizeof(longlong); break; case 'G': nof = sizeof(longlong); break;
default: /* Wrong format */ default: /* Wrong format */
sprintf(g->Message, "Invalid format %c", fty); sprintf(g->Message, "Invalid format %c", fty);
return -1; return -1;
} // endswitch fty } // endswitch fty
} // endif nof } // endif nof
default: default:
break; break;
} // endswitch tc } // endswitch tc
if (lcdp) if (lcdp)
lcdp->SetNext(cdp); lcdp->SetNext(cdp);
else else
tocols= cdp; tocols= cdp;
lcdp= cdp; lcdp= cdp;
i++; i++;
} // endwhile } // endwhile
...@@ -410,31 +410,31 @@ int TABDEF::GetColCatInfo(PGLOBAL g) ...@@ -410,31 +410,31 @@ int TABDEF::GetColCatInfo(PGLOBAL g)
if (i != GetDegree()) if (i != GetDegree())
SetDegree(i); SetDegree(i);
if (GetDefType() == TYPE_AM_DOS) { if (GetDefType() == TYPE_AM_DOS) {
int ending, recln= 0; int ending, recln= 0;
// Was commented because sometimes ending is 0 even when // Was commented because sometimes ending is 0 even when
// not specified (for instance if quoted is specified) // not specified (for instance if quoted is specified)
// if ((ending= Hc->GetIntegerOption("Ending")) < 0) { // if ((ending= Hc->GetIntegerOption("Ending")) < 0) {
if ((ending= Hc->GetIntegerOption("Ending")) <= 0) { if ((ending= Hc->GetIntegerOption("Ending")) <= 0) {
ending= (tc == TAB_BIN || tc == TAB_VEC) ? 0 : CRLF; ending= (tc == TAB_BIN || tc == TAB_VEC) ? 0 : CRLF;
Hc->SetIntegerOption("Ending", ending); Hc->SetIntegerOption("Ending", ending);
} // endif ending } // endif ending
// Calculate the default record size // Calculate the default record size
switch (tc) { switch (tc) {
case TAB_FIX: case TAB_FIX:
case TAB_BIN: case TAB_BIN:
recln= nlg + ending; // + length of line ending recln= nlg + ending; // + length of line ending
break; break;
case TAB_VEC: case TAB_VEC:
recln= nlg; recln= nlg;
// if ((k= (pak < 0) ? 8 : pak) > 1) // if ((k= (pak < 0) ? 8 : pak) > 1)
// See above for detailed comment // See above for detailed comment
// Round up lrecl to multiple of 8 or pak // Round up lrecl to multiple of 8 or pak
// recln= ((recln + k - 1) / k) * k; // recln= ((recln + k - 1) / k) * k;
break; break;
case TAB_DOS: case TAB_DOS:
case TAB_DBF: case TAB_DBF:
...@@ -443,26 +443,30 @@ int TABDEF::GetColCatInfo(PGLOBAL g) ...@@ -443,26 +443,30 @@ int TABDEF::GetColCatInfo(PGLOBAL g)
case TAB_CSV: case TAB_CSV:
case TAB_FMT: case TAB_FMT:
// The number of separators (assuming an extra one can exist) // The number of separators (assuming an extra one can exist)
// recln= poff * ((qotd) ? 3 : 1); to be investigated // recln= poff * ((qotd) ? 3 : 1); to be investigated
recln= nlg + poff * 3; // To be safe recln= nlg + poff * 3; // To be safe
default: default:
break; break;
} // endswitch tc } // endswitch tc
// lrecl must be at least recln to avoid buffer overflow // lrecl must be at least recln to avoid buffer overflow
if (trace(1)) if (trace(1))
htrc("Lrecl: Calculated=%d defined=%d\n", htrc("Lrecl: Calculated=%d defined=%d\n",
recln, Hc->GetIntegerOption("Lrecl")); recln, Hc->GetIntegerOption("Lrecl"));
recln = MY_MAX(recln, Hc->GetIntegerOption("Lrecl")); recln = MY_MAX(recln, Hc->GetIntegerOption("Lrecl"));
Hc->SetIntegerOption("Lrecl", recln); Hc->SetIntegerOption("Lrecl", recln);
((PDOSDEF)this)->SetLrecl(recln); ((PDOSDEF)this)->SetLrecl(recln);
} // endif Lrecl
// Attach the column definition to the tabdef if (trace(1))
SetCols(tocols); htrc("Lrecl set to %d\n", recln);
return poff;
} // end of GetColCatInfo } // endif Lrecl
// Attach the column definition to the tabdef
SetCols(tocols);
return poff;
} // end of GetColCatInfo
/***********************************************************************/ /***********************************************************************/
/* SetIndexInfo: retrieve index description from the table structure. */ /* SetIndexInfo: retrieve index description from the table structure. */
...@@ -487,16 +491,17 @@ PTABDEF OEMDEF::GetXdef(PGLOBAL g) ...@@ -487,16 +491,17 @@ PTABDEF OEMDEF::GetXdef(PGLOBAL g)
PCATLG cat = Cat; PCATLG cat = Cat;
/*********************************************************************/ /*********************************************************************/
/* Ensure that the .dll doesn't have a path. */ /* Ensure that the module name doesn't have a path. */
/* This is done to ensure that only approved dll from the system */ /* This is done to ensure that only approved libs from the system */
/* directories are used (to make this even remotely secure). */ /* directories are used (to make this even remotely secure). */
/*********************************************************************/ /*********************************************************************/
if (check_valid_path(Module, strlen(Module))) { if (check_valid_path(Module, strlen(Module))) {
strcpy(g->Message, "Module cannot contain a path"); strcpy(g->Message, "Module cannot contain a path");
return NULL; return NULL;
} else } else
PlugSetPath(soname, Module, GetPluginDir()); // PlugSetPath(soname, Module, GetPluginDir()); // Crashes on Fedora
strncat(strcpy(soname, GetPluginDir()), Module, _MAX_PATH);
#if defined(__WIN__) #if defined(__WIN__)
// Is the DLL already loaded? // Is the DLL already loaded?
if (!Hdll && !(Hdll = GetModuleHandle(soname))) if (!Hdll && !(Hdll = GetModuleHandle(soname)))
...@@ -522,31 +527,31 @@ PTABDEF OEMDEF::GetXdef(PGLOBAL g) ...@@ -522,31 +527,31 @@ PTABDEF OEMDEF::GetXdef(PGLOBAL g)
// Get the function returning an instance of the external DEF class // Get the function returning an instance of the external DEF class
if (!(getdef = (XGETDEF)GetProcAddress((HINSTANCE)Hdll, getname))) { if (!(getdef = (XGETDEF)GetProcAddress((HINSTANCE)Hdll, getname))) {
char buf[256]; char buf[256];
DWORD rc = GetLastError(); DWORD rc = GetLastError();
sprintf(g->Message, MSG(PROCADD_ERROR), rc, getname); sprintf(g->Message, MSG(PROCADD_ERROR), rc, getname);
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS, NULL, rc, 0, FORMAT_MESSAGE_IGNORE_INSERTS, NULL, rc, 0,
(LPTSTR)buf, sizeof(buf), NULL); (LPTSTR)buf, sizeof(buf), NULL);
strcat(strcat(g->Message, ": "), buf); strcat(strcat(g->Message, ": "), buf);
FreeLibrary((HMODULE)Hdll); FreeLibrary((HMODULE)Hdll);
return NULL; return NULL;
} // endif getdef } // endif getdef
#else // !__WIN__ #else // !__WIN__
const char *error = NULL; const char *error = NULL;
#if 0 // Don't know what all this stuff does #if 0 // Don't know what all this stuff does
Dl_info dl_info; Dl_info dl_info;
// The OEM lib must retrieve exported CONNECT variables // The OEM lib must retrieve exported CONNECT variables
if (dladdr(&connect_hton, &dl_info)) { if (dladdr(&connect_hton, &dl_info)) {
if (dlopen(dl_info.dli_fname, RTLD_NOLOAD | RTLD_NOW | RTLD_GLOBAL) == 0) { if (dlopen(dl_info.dli_fname, RTLD_NOLOAD | RTLD_NOW | RTLD_GLOBAL) == 0) {
error = dlerror(); error = dlerror();
sprintf(g->Message, "dlopen failed: %s, OEM not supported", SVP(error)); sprintf(g->Message, "dlopen failed: %s, OEM not supported", SVP(error));
return NULL; return NULL;
} // endif dlopen } // endif dlopen
} else { } else {
error = dlerror(); error = dlerror();
sprintf(g->Message, "dladdr failed: %s, OEM not supported", SVP(error)); sprintf(g->Message, "dladdr failed: %s, OEM not supported", SVP(error));
...@@ -626,7 +631,7 @@ bool OEMDEF::DefineAM(PGLOBAL g, LPCSTR, int) ...@@ -626,7 +631,7 @@ bool OEMDEF::DefineAM(PGLOBAL g, LPCSTR, int)
char *desc = (char*)PlugSubAlloc(g, NULL, strlen(Module) char *desc = (char*)PlugSubAlloc(g, NULL, strlen(Module)
+ strlen(Subtype) + 3); + strlen(Subtype) + 3);
sprintf(desc, "%s(%s)", Module, Subtype); sprintf(desc, "%s(%s)", Module, Subtype);
Desc = desc; Desc = desc;
return false; return false;
} // end of DefineAM } // end of DefineAM
...@@ -701,17 +706,17 @@ PTDB OEMDEF::GetTable(PGLOBAL g, MODE mode) ...@@ -701,17 +706,17 @@ PTDB OEMDEF::GetTable(PGLOBAL g, MODE mode)
txfp = new(g) FIXFAM(defp); txfp = new(g) FIXFAM(defp);
} else if (rfm == RECFM_VCT) { } else if (rfm == RECFM_VCT) {
#if defined(VCT_SUPPORT) #if defined(VCT_SUPPORT)
assert(Pxdef->GetDefType() == TYPE_AM_VCT); assert(Pxdef->GetDefType() == TYPE_AM_VCT);
if (map) if (map)
txfp = new(g) VCMFAM((PVCTDEF)defp); txfp = new(g) VCMFAM((PVCTDEF)defp);
else else
txfp = new(g) VCTFAM((PVCTDEF)defp); txfp = new(g) VCTFAM((PVCTDEF)defp);
#else // !VCT_SUPPORT #else // !VCT_SUPPORT
strcpy(g->Message, "VCT no more supported"); strcpy(g->Message, "VCT no more supported");
return NULL; return NULL;
#endif // !VCT_SUPPORT #endif // !VCT_SUPPORT
} // endif's } // endif's
((PTDBDOS)tdbp)->SetTxfp(txfp); ((PTDBDOS)tdbp)->SetTxfp(txfp);
} // endif Txfp } // endif Txfp
......
LIBRARY REST2
EXPORTS
GetREST @1
ColREST @2
/***********************************************************************/
/* Definitions needed by the included files. */
/***********************************************************************/
#if !defined(MY_GLOBAL_H)
#define MY_GLOBAL_H
typedef unsigned int uint;
typedef unsigned int uint32;
typedef unsigned short ushort;
typedef unsigned long ulong;
typedef unsigned long DWORD;
typedef char *LPSTR;
typedef const char *LPCSTR;
typedef int BOOL;
#if defined(_WINDOWS)
typedef void *HANDLE;
#else
typedef int HANDLE;
#endif
typedef char *PSZ;
typedef const char *PCSZ;
typedef unsigned char BYTE;
typedef unsigned char uchar;
typedef long long longlong;
typedef unsigned long long ulonglong;
typedef char my_bool;
struct charset_info_st {};
typedef const charset_info_st CHARSET_INFO;
#define FALSE 0
#define TRUE 1
#define Item char
#define MY_MAX(a,b) ((a>b)?(a):(b))
#define MY_MIN(a,b) ((a<b)?(a):(b))
#endif // MY_GLOBAL_H
\ No newline at end of file
...@@ -7,7 +7,8 @@ ...@@ -7,7 +7,8 @@
#if defined(MARIADB) #if defined(MARIADB)
#include <my_global.h> #include <my_global.h>
#else #else
#include "mini_global.h" #include "mini-global.h"
#define _OS_H_INCLUDED // Prevent os.h to be called
#endif #endif
using namespace utility::conversions; // String conversions utilities using namespace utility::conversions; // String conversions utilities
...@@ -18,70 +19,71 @@ using namespace concurrency::streams; // Asynchronous streams ...@@ -18,70 +19,71 @@ using namespace concurrency::streams; // Asynchronous streams
#include "global.h" #include "global.h"
static uint xt = 0; // Used by lamda expressions
/***********************************************************************/ /***********************************************************************/
/* Make a local copy of the requested file. */ /* Make a local copy of the requested file. */
/***********************************************************************/ /***********************************************************************/
int restGetFile(PGLOBAL g, PCSZ http, PCSZ uri, PCSZ fn) int restGetFile(PGLOBAL g, PCSZ http, PCSZ uri, PCSZ fn)
{ {
int rc= 0; int rc = 0;
auto fileStream= std::make_shared<ostream>(); auto fileStream = std::make_shared<ostream>();
if (!http || !fn) { if (!http || !fn) {
strcpy(g->Message, "Missing http or filename"); strcpy(g->Message, "Missing http or filename");
return 2; return 2;
} // endif } // endif
//std::string sfn(fn); xt = GetTraceValue();
//auto wfn= to_string_t(sfn); xtrc(515, "restGetFile: fn=%s\n", fn);
//rc= 0;
// Open stream to output file. // Open stream to output file.
pplx::task<void> requestTask= pplx::task<void> requestTask = fstream::open_ostream(to_string_t(fn))
fstream::open_ostream(to_string_t(fn)) .then([=](ostream outFile) {
.then([=](ostream outFile) { *fileStream= outFile;
*fileStream= outFile;
if (xt & 515)
// Create http_client to send the request. htrc("Outfile isopen=%d\n", outFile.is_open());
http_client client(to_string_t(http));
// Create http_client to send the request.
if (uri) http_client client(to_string_t(http));
{
// Build request URI and start the request. if (uri) {
uri_builder builder(to_string_t(uri)); // Build request URI and start the request.
return client.request(methods::GET, builder.to_string()); uri_builder builder(to_string_t(uri));
} return client.request(methods::GET, builder.to_string());
else } else
return client.request(methods::GET); return client.request(methods::GET);
}) })
// Handle response headers arriving. // Handle response headers arriving.
.then([=](http_response response) { .then([=](http_response response) {
#if defined(DEVELOPMENT) if (xt & 515)
fprintf(stderr, "Received response status code:%u\n", htrc("Received response status code:%u\n",
response.status_code()); response.status_code());
#endif // DEVELOPMENT
// Write response body into the file.
// Write response body into the file. return response.body().read_to_end(fileStream->streambuf());
return response.body().read_to_end(fileStream->streambuf()); })
})
// Close the file stream.
// Close the file stream. .then([=](size_t n) {
.then([=](size_t) { return fileStream->close(); }); if (xt & 515)
htrc("Return size=%u\n", n);
return fileStream->close();
});
// Wait for all the outstanding I/O to complete and handle any exceptions // Wait for all the outstanding I/O to complete and handle any exceptions
try try {
{
requestTask.wait(); requestTask.wait();
} xtrc(515, "In Wait\n");
catch (const std::exception &e) } catch (const std::exception &e) {
{ xtrc(515, "Error exception: %s\n", e.what());
#if defined(DEVELOPMENT) sprintf(g->Message, "Error exception: %s", e.what());
fprintf(stderr, "Error exception: %s\n", e.what());
#endif // DEVELOPMENT
sprintf(g->Message, "Error exception: %s", e.what());
rc= 1; rc= 1;
} // end try/catch } // end try/catch
xtrc(515, "restget done: rc=%d\n", rc);
return rc; return rc;
} // end of restGetFile } // end of restGetFile
\ No newline at end of file
...@@ -189,9 +189,11 @@ PQRYRES CSVColumns(PGLOBAL g, PCSZ dp, PTOS topt, bool info) ...@@ -189,9 +189,11 @@ PQRYRES CSVColumns(PGLOBAL g, PCSZ dp, PTOS topt, bool info)
htrc("File %s Sep=%c Qot=%c Header=%d maxerr=%d\n", htrc("File %s Sep=%c Qot=%c Header=%d maxerr=%d\n",
SVP(tdp->Fn), tdp->Sep, tdp->Qot, tdp->Header, tdp->Maxerr); SVP(tdp->Fn), tdp->Sep, tdp->Qot, tdp->Header, tdp->Maxerr);
#if defined(ZIP_SUPPORT)
if (tdp->Zipped) if (tdp->Zipped)
tcvp = new(g)TDBCSV(tdp, new(g)UNZFAM(tdp)); tcvp = new(g)TDBCSV(tdp, new(g)UNZFAM(tdp));
else else
#endif // ZIP_SUPPORT
tcvp = new(g) TDBCSV(tdp, new(g) DOSFAM(tdp)); tcvp = new(g) TDBCSV(tdp, new(g) DOSFAM(tdp));
tcvp->SetMode(MODE_READ); tcvp->SetMode(MODE_READ);
......
...@@ -71,15 +71,15 @@ char *GetJsonNull(void); ...@@ -71,15 +71,15 @@ char *GetJsonNull(void);
/***********************************************************************/ /***********************************************************************/
PQRYRES JSONColumns(PGLOBAL g, PCSZ db, PCSZ dsn, PTOS topt, bool info) PQRYRES JSONColumns(PGLOBAL g, PCSZ db, PCSZ dsn, PTOS topt, bool info)
{ {
static int buftyp[] = {TYPE_STRING, TYPE_SHORT, TYPE_STRING, TYPE_INT, static int buftyp[] = {TYPE_STRING, TYPE_SHORT, TYPE_STRING, TYPE_INT,
TYPE_INT, TYPE_SHORT, TYPE_SHORT, TYPE_STRING}; TYPE_INT, TYPE_SHORT, TYPE_SHORT, TYPE_STRING};
static XFLD fldtyp[] = {FLD_NAME, FLD_TYPE, FLD_TYPENAME, FLD_PREC, static XFLD fldtyp[] = {FLD_NAME, FLD_TYPE, FLD_TYPENAME, FLD_PREC,
FLD_LENGTH, FLD_SCALE, FLD_NULL, FLD_FORMAT}; FLD_LENGTH, FLD_SCALE, FLD_NULL, FLD_FORMAT};
static unsigned int length[] = {0, 6, 8, 10, 10, 6, 6, 0}; static unsigned int length[] = {0, 6, 8, 10, 10, 6, 6, 0};
int i, n = 0; int i, n = 0;
int ncol = sizeof(buftyp) / sizeof(int); int ncol = sizeof(buftyp) / sizeof(int);
PJCL jcp; PJCL jcp;
JSONDISC *pjdc = NULL; JSONDISC *pjdc = NULL;
PQRYRES qrp; PQRYRES qrp;
PCOLRES crp; PCOLRES crp;
...@@ -89,15 +89,15 @@ PQRYRES JSONColumns(PGLOBAL g, PCSZ db, PCSZ dsn, PTOS topt, bool info) ...@@ -89,15 +89,15 @@ PQRYRES JSONColumns(PGLOBAL g, PCSZ db, PCSZ dsn, PTOS topt, bool info)
goto skipit; goto skipit;
} // endif info } // endif info
if (GetIntegerTableOption(g, topt, "Multiple", 0)) { if (GetIntegerTableOption(g, topt, "Multiple", 0)) {
strcpy(g->Message, "Cannot find column definition for multiple table"); strcpy(g->Message, "Cannot find column definition for multiple table");
return NULL; return NULL;
} // endif Multiple } // endif Multiple
pjdc = new(g) JSONDISC(g, length); pjdc = new(g) JSONDISC(g, length);
if (!(n = pjdc->GetColumns(g, db, dsn, topt))) if (!(n = pjdc->GetColumns(g, db, dsn, topt)))
return NULL; return NULL;
skipit: skipit:
if (trace(1)) if (trace(1))
...@@ -110,8 +110,8 @@ PQRYRES JSONColumns(PGLOBAL g, PCSZ db, PCSZ dsn, PTOS topt, bool info) ...@@ -110,8 +110,8 @@ PQRYRES JSONColumns(PGLOBAL g, PCSZ db, PCSZ dsn, PTOS topt, bool info)
buftyp, fldtyp, length, false, false); buftyp, fldtyp, length, false, false);
crp = qrp->Colresp->Next->Next->Next->Next->Next->Next; crp = qrp->Colresp->Next->Next->Next->Next->Next->Next;
crp->Name = PlugDup(g, "Nullable"); crp->Name = PlugDup(g, "Nullable");
crp->Next->Name = PlugDup(g, "Jpath"); crp->Next->Name = PlugDup(g, "Jpath");
if (info || !qrp) if (info || !qrp)
return qrp; return qrp;
...@@ -122,8 +122,8 @@ PQRYRES JSONColumns(PGLOBAL g, PCSZ db, PCSZ dsn, PTOS topt, bool info) ...@@ -122,8 +122,8 @@ PQRYRES JSONColumns(PGLOBAL g, PCSZ db, PCSZ dsn, PTOS topt, bool info)
/* Now get the results into blocks. */ /* Now get the results into blocks. */
/*********************************************************************/ /*********************************************************************/
for (i = 0, jcp = pjdc->fjcp; jcp; i++, jcp = jcp->Next) { for (i = 0, jcp = pjdc->fjcp; jcp; i++, jcp = jcp->Next) {
if (jcp->Type == TYPE_UNKNOWN) if (jcp->Type == TYPE_UNKNOWN)
jcp->Type = TYPE_STRING; // Void column jcp->Type = TYPE_STRING; // Void column
crp = qrp->Colresp; // Column Name crp = qrp->Colresp; // Column Name
crp->Kdata->SetValue(jcp->Name, i); crp->Kdata->SetValue(jcp->Name, i);
...@@ -159,380 +159,380 @@ PQRYRES JSONColumns(PGLOBAL g, PCSZ db, PCSZ dsn, PTOS topt, bool info) ...@@ -159,380 +159,380 @@ PQRYRES JSONColumns(PGLOBAL g, PCSZ db, PCSZ dsn, PTOS topt, bool info)
/***********************************************************************/ /***********************************************************************/
JSONDISC::JSONDISC(PGLOBAL g, uint *lg) JSONDISC::JSONDISC(PGLOBAL g, uint *lg)
{ {
length = lg; length = lg;
jcp = fjcp = pjcp = NULL; jcp = fjcp = pjcp = NULL;
tjnp = NULL; tjnp = NULL;
jpp = NULL; jpp = NULL;
tjsp = NULL; tjsp = NULL;
jsp = NULL; jsp = NULL;
row = NULL; row = NULL;
sep = NULL; sep = NULL;
i = n = bf = ncol = lvl = 0; i = n = bf = ncol = lvl = 0;
all = false; all = false;
} // end of JSONDISC constructor } // end of JSONDISC constructor
int JSONDISC::GetColumns(PGLOBAL g, PCSZ db, PCSZ dsn, PTOS topt) int JSONDISC::GetColumns(PGLOBAL g, PCSZ db, PCSZ dsn, PTOS topt)
{ {
char filename[_MAX_PATH]; char filename[_MAX_PATH];
bool mgo = (GetTypeID(topt->type) == TAB_MONGO); bool mgo = (GetTypeID(topt->type) == TAB_MONGO);
PCSZ level = GetStringTableOption(g, topt, "Level", NULL); PCSZ level = GetStringTableOption(g, topt, "Level", NULL);
if (level) { if (level) {
lvl = atoi(level); lvl = atoi(level);
lvl = (lvl > 16) ? 16 : lvl; lvl = (lvl > 16) ? 16 : lvl;
} else } else
lvl = 0; lvl = 0;
sep = GetStringTableOption(g, topt, "Separator", "."); sep = GetStringTableOption(g, topt, "Separator", ".");
/*********************************************************************/ /*********************************************************************/
/* Open the input file. */ /* Open the input file. */
/*********************************************************************/ /*********************************************************************/
tdp = new(g) JSONDEF; tdp = new(g) JSONDEF;
#if defined(ZIP_SUPPORT) #if defined(ZIP_SUPPORT)
tdp->Entry = GetStringTableOption(g, topt, "Entry", NULL); tdp->Entry = GetStringTableOption(g, topt, "Entry", NULL);
tdp->Zipped = GetBooleanTableOption(g, topt, "Zipped", false); tdp->Zipped = GetBooleanTableOption(g, topt, "Zipped", false);
#endif // ZIP_SUPPORT #endif // ZIP_SUPPORT
tdp->Fn = GetStringTableOption(g, topt, "Filename", NULL); tdp->Fn = GetStringTableOption(g, topt, "Filename", NULL);
if (!(tdp->Database = SetPath(g, db))) if (!(tdp->Database = SetPath(g, db)))
return 0; return 0;
tdp->Objname = GetStringTableOption(g, topt, "Object", NULL); tdp->Objname = GetStringTableOption(g, topt, "Object", NULL);
tdp->Base = GetIntegerTableOption(g, topt, "Base", 0) ? 1 : 0; tdp->Base = GetIntegerTableOption(g, topt, "Base", 0) ? 1 : 0;
tdp->Pretty = GetIntegerTableOption(g, topt, "Pretty", 2); tdp->Pretty = GetIntegerTableOption(g, topt, "Pretty", 2);
tdp->Xcol = GetStringTableOption(g, topt, "Expand", NULL); tdp->Xcol = GetStringTableOption(g, topt, "Expand", NULL);
tdp->Accept = GetBooleanTableOption(g, topt, "Accept", false); tdp->Accept = GetBooleanTableOption(g, topt, "Accept", false);
tdp->Uri = (dsn && *dsn ? dsn : NULL); tdp->Uri = (dsn && *dsn ? dsn : NULL);
if (!tdp->Fn && !tdp->Uri) { if (!tdp->Fn && !tdp->Uri) {
strcpy(g->Message, MSG(MISSING_FNAME)); strcpy(g->Message, MSG(MISSING_FNAME));
return 0; return 0;
} // endif Fn } // endif Fn
if (tdp->Fn) { if (tdp->Fn) {
// We used the file name relative to recorded datapath // We used the file name relative to recorded datapath
PlugSetPath(filename, tdp->Fn, tdp->GetPath()); PlugSetPath(filename, tdp->Fn, tdp->GetPath());
tdp->Fn = PlugDup(g, filename); tdp->Fn = PlugDup(g, filename);
} // endif Fn } // endif Fn
if (trace(1)) if (trace(1))
htrc("File %s objname=%s pretty=%d lvl=%d\n", htrc("File %s objname=%s pretty=%d lvl=%d\n",
tdp->Fn, tdp->Objname, tdp->Pretty, lvl); tdp->Fn, tdp->Objname, tdp->Pretty, lvl);
if (tdp->Uri) { if (tdp->Uri) {
#if defined(JAVA_SUPPORT) || defined(CMGO_SUPPORT) #if defined(JAVA_SUPPORT) || defined(CMGO_SUPPORT)
tdp->Collname = GetStringTableOption(g, topt, "Name", NULL); tdp->Collname = GetStringTableOption(g, topt, "Name", NULL);
tdp->Collname = GetStringTableOption(g, topt, "Tabname", tdp->Collname); tdp->Collname = GetStringTableOption(g, topt, "Tabname", tdp->Collname);
tdp->Schema = GetStringTableOption(g, topt, "Dbname", "test"); tdp->Schema = GetStringTableOption(g, topt, "Dbname", "test");
tdp->Options = (PSZ)GetStringTableOption(g, topt, "Colist", "all"); tdp->Options = (PSZ)GetStringTableOption(g, topt, "Colist", "all");
tdp->Pipe = GetBooleanTableOption(g, topt, "Pipeline", false); tdp->Pipe = GetBooleanTableOption(g, topt, "Pipeline", false);
tdp->Driver = (PSZ)GetStringTableOption(g, topt, "Driver", NULL); tdp->Driver = (PSZ)GetStringTableOption(g, topt, "Driver", NULL);
tdp->Version = GetIntegerTableOption(g, topt, "Version", 3); tdp->Version = GetIntegerTableOption(g, topt, "Version", 3);
tdp->Wrapname = (PSZ)GetStringTableOption(g, topt, "Wrapper", tdp->Wrapname = (PSZ)GetStringTableOption(g, topt, "Wrapper",
(tdp->Version == 2) ? "Mongo2Interface" : "Mongo3Interface"); (tdp->Version == 2) ? "Mongo2Interface" : "Mongo3Interface");
tdp->Pretty = 0; tdp->Pretty = 0;
#else // !MONGO_SUPPORT #else // !MONGO_SUPPORT
sprintf(g->Message, MSG(NO_FEAT_SUPPORT), "MONGO"); sprintf(g->Message, MSG(NO_FEAT_SUPPORT), "MONGO");
return 0; return 0;
#endif // !MONGO_SUPPORT #endif // !MONGO_SUPPORT
} // endif Uri } // endif Uri
if (tdp->Pretty == 2) { if (tdp->Pretty == 2) {
if (tdp->Zipped) { if (tdp->Zipped) {
#if defined(ZIP_SUPPORT) #if defined(ZIP_SUPPORT)
tjsp = new(g) TDBJSON(tdp, new(g) UNZFAM(tdp)); tjsp = new(g) TDBJSON(tdp, new(g) UNZFAM(tdp));
#else // !ZIP_SUPPORT #else // !ZIP_SUPPORT
sprintf(g->Message, MSG(NO_FEAT_SUPPORT), "ZIP"); sprintf(g->Message, MSG(NO_FEAT_SUPPORT), "ZIP");
return 0; return 0;
#endif // !ZIP_SUPPORT #endif // !ZIP_SUPPORT
} else } else
tjsp = new(g) TDBJSON(tdp, new(g) MAPFAM(tdp)); tjsp = new(g) TDBJSON(tdp, new(g) MAPFAM(tdp));
if (tjsp->MakeDocument(g)) if (tjsp->MakeDocument(g))
return 0; return 0;
jsp = (tjsp->GetDoc()) ? tjsp->GetDoc()->GetValue(0) : NULL; jsp = (tjsp->GetDoc()) ? tjsp->GetDoc()->GetValue(0) : NULL;
} else { } else {
if (!(tdp->Lrecl = GetIntegerTableOption(g, topt, "Lrecl", 0))) if (!(tdp->Lrecl = GetIntegerTableOption(g, topt, "Lrecl", 0)))
if (!mgo) { if (!mgo) {
sprintf(g->Message, "LRECL must be specified for pretty=%d", tdp->Pretty); sprintf(g->Message, "LRECL must be specified for pretty=%d", tdp->Pretty);
return 0; return 0;
} else } else
tdp->Lrecl = 8192; // Should be enough tdp->Lrecl = 8192; // Should be enough
tdp->Ending = GetIntegerTableOption(g, topt, "Ending", CRLF); tdp->Ending = GetIntegerTableOption(g, topt, "Ending", CRLF);
if (tdp->Zipped) { if (tdp->Zipped) {
#if defined(ZIP_SUPPORT) #if defined(ZIP_SUPPORT)
tjnp = new(g)TDBJSN(tdp, new(g) UNZFAM(tdp)); tjnp = new(g)TDBJSN(tdp, new(g) UNZFAM(tdp));
#else // !ZIP_SUPPORT #else // !ZIP_SUPPORT
sprintf(g->Message, MSG(NO_FEAT_SUPPORT), "ZIP"); sprintf(g->Message, MSG(NO_FEAT_SUPPORT), "ZIP");
return NULL; return NULL;
#endif // !ZIP_SUPPORT #endif // !ZIP_SUPPORT
} else if (tdp->Uri) { } else if (tdp->Uri) {
if (tdp->Driver && toupper(*tdp->Driver) == 'C') { if (tdp->Driver && toupper(*tdp->Driver) == 'C') {
#if defined(CMGO_SUPPORT) #if defined(CMGO_SUPPORT)
tjnp = new(g) TDBJSN(tdp, new(g) CMGFAM(tdp)); tjnp = new(g) TDBJSN(tdp, new(g) CMGFAM(tdp));
#else #else
sprintf(g->Message, "Mongo %s Driver not available", "C"); sprintf(g->Message, "Mongo %s Driver not available", "C");
return 0; return 0;
#endif #endif
} else if (tdp->Driver && toupper(*tdp->Driver) == 'J') { } else if (tdp->Driver && toupper(*tdp->Driver) == 'J') {
#if defined(JAVA_SUPPORT) #if defined(JAVA_SUPPORT)
tjnp = new(g) TDBJSN(tdp, new(g) JMGFAM(tdp)); tjnp = new(g) TDBJSN(tdp, new(g) JMGFAM(tdp));
#else #else
sprintf(g->Message, "Mongo %s Driver not available", "Java"); sprintf(g->Message, "Mongo %s Driver not available", "Java");
return 0; return 0;
#endif #endif
} else { // Driver not specified } else { // Driver not specified
#if defined(CMGO_SUPPORT) #if defined(CMGO_SUPPORT)
tjnp = new(g) TDBJSN(tdp, new(g) CMGFAM(tdp)); tjnp = new(g) TDBJSN(tdp, new(g) CMGFAM(tdp));
#elif defined(JAVA_SUPPORT) #elif defined(JAVA_SUPPORT)
tjnp = new(g) TDBJSN(tdp, new(g) JMGFAM(tdp)); tjnp = new(g) TDBJSN(tdp, new(g) JMGFAM(tdp));
#else #else
sprintf(g->Message, MSG(NO_FEAT_SUPPORT), "MONGO"); sprintf(g->Message, MSG(NO_FEAT_SUPPORT), "MONGO");
return 0; return 0;
#endif #endif
} // endif Driver } // endif Driver
} else } else
tjnp = new(g) TDBJSN(tdp, new(g) DOSFAM(tdp)); tjnp = new(g) TDBJSN(tdp, new(g) DOSFAM(tdp));
tjnp->SetMode(MODE_READ); tjnp->SetMode(MODE_READ);
// Allocate the parse work memory // Allocate the parse work memory
PGLOBAL G = (PGLOBAL)PlugSubAlloc(g, NULL, sizeof(GLOBAL)); PGLOBAL G = (PGLOBAL)PlugSubAlloc(g, NULL, sizeof(GLOBAL));
memset(G, 0, sizeof(GLOBAL)); memset(G, 0, sizeof(GLOBAL));
G->Sarea_Size = tdp->Lrecl * 10; G->Sarea_Size = tdp->Lrecl * 10;
G->Sarea = PlugSubAlloc(g, NULL, G->Sarea_Size); G->Sarea = PlugSubAlloc(g, NULL, G->Sarea_Size);
PlugSubSet(G->Sarea, G->Sarea_Size); PlugSubSet(G->Sarea, G->Sarea_Size);
G->jump_level = 0; G->jump_level = 0;
tjnp->SetG(G); tjnp->SetG(G);
if (tjnp->OpenDB(g)) if (tjnp->OpenDB(g))
return 0; return 0;
switch (tjnp->ReadDB(g)) { switch (tjnp->ReadDB(g)) {
case RC_EF: case RC_EF:
strcpy(g->Message, "Void json table"); strcpy(g->Message, "Void json table");
case RC_FX: case RC_FX:
goto err; goto err;
default: default:
jsp = tjnp->GetRow(); jsp = tjnp->GetRow();
} // endswitch ReadDB } // endswitch ReadDB
} // endif pretty } // endif pretty
if (!(row = (jsp) ? jsp->GetObject() : NULL)) { if (!(row = (jsp) ? jsp->GetObject() : NULL)) {
strcpy(g->Message, "Can only retrieve columns from object rows"); strcpy(g->Message, "Can only retrieve columns from object rows");
goto err; goto err;
} // endif row } // endif row
all = GetBooleanTableOption(g, topt, "Fullarray", false); all = GetBooleanTableOption(g, topt, "Fullarray", false);
jcol.Name = jcol.Fmt = NULL; jcol.Name = jcol.Fmt = NULL;
jcol.Next = NULL; jcol.Next = NULL;
jcol.Found = true; jcol.Found = true;
colname[0] = 0; colname[0] = 0;
if (!tdp->Uri) { if (!tdp->Uri) {
fmt[0] = '$'; fmt[0] = '$';
fmt[1] = '.'; fmt[1] = '.';
bf = 2; bf = 2;
} // endif Uri } // endif Uri
/*********************************************************************/ /*********************************************************************/
/* Analyse the JSON tree and define columns. */ /* Analyse the JSON tree and define columns. */
/*********************************************************************/ /*********************************************************************/
for (i = 1; ; i++) { for (i = 1; ; i++) {
for (jpp = row->GetFirst(); jpp; jpp = jpp->GetNext()) { for (jpp = row->GetFirst(); jpp; jpp = jpp->GetNext()) {
strncpy(colname, jpp->GetKey(), 64); strncpy(colname, jpp->GetKey(), 64);
fmt[bf] = 0; fmt[bf] = 0;
if (Find(g, jpp->GetVal(), colname, MY_MIN(lvl, 0))) if (Find(g, jpp->GetVal(), colname, MY_MIN(lvl, 0)))
goto err; goto err;
} // endfor jpp } // endfor jpp
// Missing column can be null // Missing column can be null
for (jcp = fjcp; jcp; jcp = jcp->Next) { for (jcp = fjcp; jcp; jcp = jcp->Next) {
jcp->Cbn |= !jcp->Found; jcp->Cbn |= !jcp->Found;
jcp->Found = false; jcp->Found = false;
} // endfor jcp } // endfor jcp
if (tdp->Pretty != 2) { if (tdp->Pretty != 2) {
// Read next record // Read next record
switch (tjnp->ReadDB(g)) { switch (tjnp->ReadDB(g)) {
case RC_EF: case RC_EF:
jsp = NULL; jsp = NULL;
break; break;
case RC_FX: case RC_FX:
goto err; goto err;
default: default:
jsp = tjnp->GetRow(); jsp = tjnp->GetRow();
} // endswitch ReadDB } // endswitch ReadDB
} else } else
jsp = tjsp->GetDoc()->GetValue(i); jsp = tjsp->GetDoc()->GetValue(i);
if (!(row = (jsp) ? jsp->GetObject() : NULL)) if (!(row = (jsp) ? jsp->GetObject() : NULL))
break; break;
} // endfor i } // endfor i
if (tdp->Pretty != 2) if (tdp->Pretty != 2)
tjnp->CloseDB(g); tjnp->CloseDB(g);
return n; return n;
err: err:
if (tdp->Pretty != 2) if (tdp->Pretty != 2)
tjnp->CloseDB(g); tjnp->CloseDB(g);
return 0; return 0;
} // end of GetColumns } // end of GetColumns
bool JSONDISC::Find(PGLOBAL g, PJVAL jvp, PCSZ key, int j) bool JSONDISC::Find(PGLOBAL g, PJVAL jvp, PCSZ key, int j)
{ {
char *p, *pc = colname + strlen(colname); char *p, *pc = colname + strlen(colname);
int ars; int ars;
PJOB job; PJOB job;
PJAR jar; PJAR jar;
if ((valp = jvp ? jvp->GetValue() : NULL)) { if ((valp = jvp ? jvp->GetValue() : NULL)) {
jcol.Type = valp->GetType(); jcol.Type = valp->GetType();
jcol.Len = valp->GetValLen(); jcol.Len = valp->GetValLen();
jcol.Scale = valp->GetValPrec(); jcol.Scale = valp->GetValPrec();
jcol.Cbn = valp->IsNull(); jcol.Cbn = valp->IsNull();
} else if (!jvp || jvp->IsNull()) { } else if (!jvp || jvp->IsNull()) {
jcol.Type = TYPE_UNKNOWN; jcol.Type = TYPE_UNKNOWN;
jcol.Len = jcol.Scale = 0; jcol.Len = jcol.Scale = 0;
jcol.Cbn = true; jcol.Cbn = true;
} else if (j < lvl) { } else if (j < lvl) {
if (!fmt[bf]) if (!fmt[bf])
strcat(fmt, colname); strcat(fmt, colname);
p = fmt + strlen(fmt); p = fmt + strlen(fmt);
jsp = jvp->GetJson(); jsp = jvp->GetJson();
switch (jsp->GetType()) { switch (jsp->GetType()) {
case TYPE_JOB: case TYPE_JOB:
job = (PJOB)jsp; job = (PJOB)jsp;
for (PJPR jrp = job->GetFirst(); jrp; jrp = jrp->GetNext()) { for (PJPR jrp = job->GetFirst(); jrp; jrp = jrp->GetNext()) {
PCSZ k = jrp->GetKey(); PCSZ k = jrp->GetKey();
if (*k != '$') { if (*k != '$') {
strncat(strncat(fmt, sep, 128), k, 128); strncat(strncat(fmt, sep, 128), k, 128);
strncat(strncat(colname, "_", 64), k, 64); strncat(strncat(colname, "_", 64), k, 64);
} // endif Key } // endif Key
if (Find(g, jrp->GetVal(), k, j + 1)) if (Find(g, jrp->GetVal(), k, j + 1))
return true; return true;
*p = *pc = 0; *p = *pc = 0;
} // endfor jrp } // endfor jrp
return false; return false;
case TYPE_JAR: case TYPE_JAR:
jar = (PJAR)jsp; jar = (PJAR)jsp;
if (all || (tdp->Xcol && !stricmp(tdp->Xcol, key))) if (all || (tdp->Xcol && !stricmp(tdp->Xcol, key)))
ars = jar->GetSize(false); ars = jar->GetSize(false);
else else
ars = MY_MIN(jar->GetSize(false), 1); ars = MY_MIN(jar->GetSize(false), 1);
for (int k = 0; k < ars; k++) { for (int k = 0; k < ars; k++) {
if (!tdp->Xcol || stricmp(tdp->Xcol, key)) { if (!tdp->Xcol || stricmp(tdp->Xcol, key)) {
sprintf(buf, "%d", k); sprintf(buf, "%d", k);
if (tdp->Uri) if (tdp->Uri)
strncat(strncat(fmt, sep, 128), buf, 128); strncat(strncat(fmt, sep, 128), buf, 128);
else else
strncat(strncat(strncat(fmt, "[", 128), buf, 128), "]", 128); strncat(strncat(strncat(fmt, "[", 128), buf, 128), "]", 128);
if (all) if (all)
strncat(strncat(colname, "_", 64), buf, 64); strncat(strncat(colname, "_", 64), buf, 64);
} else } else
strncat(fmt, (tdp->Uri ? sep : "[*]"), 128); strncat(fmt, (tdp->Uri ? sep : "[*]"), 128);
if (Find(g, jar->GetValue(k), "", j)) if (Find(g, jar->GetValue(k), "", j))
return true; return true;
*p = *pc = 0; *p = *pc = 0;
} // endfor k } // endfor k
return false; return false;
default: default:
sprintf(g->Message, "Logical error after %s", fmt); sprintf(g->Message, "Logical error after %s", fmt);
return true; return true;
} // endswitch Type } // endswitch Type
} else if (lvl >= 0) { } else if (lvl >= 0) {
jcol.Type = TYPE_STRING; jcol.Type = TYPE_STRING;
jcol.Len = 256; jcol.Len = 256;
jcol.Scale = 0; jcol.Scale = 0;
jcol.Cbn = true; jcol.Cbn = true;
} else } else
return false; return false;
AddColumn(g); AddColumn(g);
return false; return false;
} // end of Find } // end of Find
void JSONDISC::AddColumn(PGLOBAL g) void JSONDISC::AddColumn(PGLOBAL g)
{ {
bool b = fmt[bf] != 0; // True if formatted bool b = fmt[bf] != 0; // True if formatted
// Check whether this column was already found // Check whether this column was already found
for (jcp = fjcp; jcp; jcp = jcp->Next) for (jcp = fjcp; jcp; jcp = jcp->Next)
if (!strcmp(colname, jcp->Name)) if (!strcmp(colname, jcp->Name))
break; break;
if (jcp) { if (jcp) {
if (jcp->Type != jcol.Type) { if (jcp->Type != jcol.Type) {
if (jcp->Type == TYPE_UNKNOWN) if (jcp->Type == TYPE_UNKNOWN)
jcp->Type = jcol.Type; jcp->Type = jcol.Type;
else if (jcol.Type != TYPE_UNKNOWN) else if (jcol.Type != TYPE_UNKNOWN)
jcp->Type = TYPE_STRING; jcp->Type = TYPE_STRING;
} // endif Type } // endif Type
if (b && (!jcp->Fmt || strlen(jcp->Fmt) < strlen(fmt))) { if (b && (!jcp->Fmt || strlen(jcp->Fmt) < strlen(fmt))) {
jcp->Fmt = PlugDup(g, fmt); jcp->Fmt = PlugDup(g, fmt);
length[7] = MY_MAX(length[7], strlen(fmt)); length[7] = MY_MAX(length[7], strlen(fmt));
} // endif fmt } // endif fmt
jcp->Len = MY_MAX(jcp->Len, jcol.Len); jcp->Len = MY_MAX(jcp->Len, jcol.Len);
jcp->Scale = MY_MAX(jcp->Scale, jcol.Scale); jcp->Scale = MY_MAX(jcp->Scale, jcol.Scale);
jcp->Cbn |= jcol.Cbn; jcp->Cbn |= jcol.Cbn;
jcp->Found = true; jcp->Found = true;
} else if (jcol.Type != TYPE_UNKNOWN || tdp->Accept) { } else if (jcol.Type != TYPE_UNKNOWN || tdp->Accept) {
// New column // New column
jcp = (PJCL)PlugSubAlloc(g, NULL, sizeof(JCOL)); jcp = (PJCL)PlugSubAlloc(g, NULL, sizeof(JCOL));
*jcp = jcol; *jcp = jcol;
jcp->Cbn |= (i > 1); jcp->Cbn |= (i > 1);
jcp->Name = PlugDup(g, colname); jcp->Name = PlugDup(g, colname);
length[0] = MY_MAX(length[0], strlen(colname)); length[0] = MY_MAX(length[0], strlen(colname));
if (b) { if (b) {
jcp->Fmt = PlugDup(g, fmt); jcp->Fmt = PlugDup(g, fmt);
length[7] = MY_MAX(length[7], strlen(fmt)); length[7] = MY_MAX(length[7], strlen(fmt));
} else } else
jcp->Fmt = NULL; jcp->Fmt = NULL;
if (pjcp) { if (pjcp) {
jcp->Next = pjcp->Next; jcp->Next = pjcp->Next;
pjcp->Next = jcp; pjcp->Next = jcp;
} else } else
fjcp = jcp; fjcp = jcp;
n++; n++;
} // endif jcp } // endif jcp
if (jcp) if (jcp)
pjcp = jcp; pjcp = jcp;
} // end of AddColumn } // end of AddColumn
...@@ -548,13 +548,13 @@ JSONDEF::JSONDEF(void) ...@@ -548,13 +548,13 @@ JSONDEF::JSONDEF(void)
Limit = 1; Limit = 1;
Base = 0; Base = 0;
Strict = false; Strict = false;
Sep = '.'; Sep = '.';
Uri = NULL; Uri = NULL;
Collname = Options = Filter = NULL; Collname = Options = Filter = NULL;
Pipe = false; Pipe = false;
Driver = NULL; Driver = NULL;
Version = 0; Version = 0;
Wrapname = NULL; Wrapname = NULL;
} // end of JSONDEF constructor } // end of JSONDEF constructor
/***********************************************************************/ /***********************************************************************/
...@@ -562,41 +562,41 @@ JSONDEF::JSONDEF(void) ...@@ -562,41 +562,41 @@ JSONDEF::JSONDEF(void)
/***********************************************************************/ /***********************************************************************/
bool JSONDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff) bool JSONDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
{ {
Schema = GetStringCatInfo(g, "DBname", Schema); Schema = GetStringCatInfo(g, "DBname", Schema);
Jmode = (JMODE)GetIntCatInfo("Jmode", MODE_OBJECT); Jmode = (JMODE)GetIntCatInfo("Jmode", MODE_OBJECT);
Objname = GetStringCatInfo(g, "Object", NULL); Objname = GetStringCatInfo(g, "Object", NULL);
Xcol = GetStringCatInfo(g, "Expand", NULL); Xcol = GetStringCatInfo(g, "Expand", NULL);
Pretty = GetIntCatInfo("Pretty", 2); Pretty = GetIntCatInfo("Pretty", 2);
Limit = GetIntCatInfo("Limit", 10); Limit = GetIntCatInfo("Limit", 10);
Base = GetIntCatInfo("Base", 0) ? 1 : 0; Base = GetIntCatInfo("Base", 0) ? 1 : 0;
Sep = *GetStringCatInfo(g, "Separator", "."); Sep = *GetStringCatInfo(g, "Separator", ".");
Accept = GetBoolCatInfo("Accept", false); Accept = GetBoolCatInfo("Accept", false);
// Don't use url as MONGO uri when called from REST // Don't use url as MONGO uri when called from REST
if (stricmp(am, "REST") && (Uri = GetStringCatInfo(g, "Connect", NULL))) { if (stricmp(am, "REST") && (Uri = GetStringCatInfo(g, "Connect", NULL))) {
#if defined(JAVA_SUPPORT) || defined(CMGO_SUPPORT) #if defined(JAVA_SUPPORT) || defined(CMGO_SUPPORT)
Collname = GetStringCatInfo(g, "Name", Collname = GetStringCatInfo(g, "Name",
(Catfunc & (FNC_TABLE | FNC_COL)) ? NULL : Name); (Catfunc & (FNC_TABLE | FNC_COL)) ? NULL : Name);
Collname = GetStringCatInfo(g, "Tabname", Collname); Collname = GetStringCatInfo(g, "Tabname", Collname);
Options = GetStringCatInfo(g, "Colist", NULL); Options = GetStringCatInfo(g, "Colist", NULL);
Filter = GetStringCatInfo(g, "Filter", NULL); Filter = GetStringCatInfo(g, "Filter", NULL);
Pipe = GetBoolCatInfo("Pipeline", false); Pipe = GetBoolCatInfo("Pipeline", false);
Driver = GetStringCatInfo(g, "Driver", NULL); Driver = GetStringCatInfo(g, "Driver", NULL);
Version = GetIntCatInfo("Version", 3); Version = GetIntCatInfo("Version", 3);
Pretty = 0; Pretty = 0;
#if defined(JAVA_SUPPORT) #if defined(JAVA_SUPPORT)
if (Version == 2) if (Version == 2)
Wrapname = GetStringCatInfo(g, "Wrapper", "Mongo2Interface"); Wrapname = GetStringCatInfo(g, "Wrapper", "Mongo2Interface");
else else
Wrapname = GetStringCatInfo(g, "Wrapper", "Mongo3Interface"); Wrapname = GetStringCatInfo(g, "Wrapper", "Mongo3Interface");
#endif // JAVA_SUPPORT #endif // JAVA_SUPPORT
#else // !MONGO_SUPPORT #else // !MONGO_SUPPORT
sprintf(g->Message, MSG(NO_FEAT_SUPPORT), "MONGO"); sprintf(g->Message, MSG(NO_FEAT_SUPPORT), "MONGO");
return true; return true;
#endif // !MONGO_SUPPORT #endif // !MONGO_SUPPORT
} // endif Uri } // endif Uri
return DOSDEF::DefineAM(g, (Uri ? "XMGO" : "DOS"), poff); return DOSDEF::DefineAM(g, (Uri ? "XMGO" : "DOS"), poff);
} // end of DefineAM } // end of DefineAM
/***********************************************************************/ /***********************************************************************/
...@@ -604,6 +604,9 @@ bool JSONDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff) ...@@ -604,6 +604,9 @@ bool JSONDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
/***********************************************************************/ /***********************************************************************/
PTDB JSONDEF::GetTable(PGLOBAL g, MODE m) PTDB JSONDEF::GetTable(PGLOBAL g, MODE m)
{ {
if (trace(1))
htrc("JSON GetTable Pretty=%d Uri=%s\n", Pretty, SVP(Uri));
if (Catfunc == FNC_COL) if (Catfunc == FNC_COL)
return new(g)TDBJCL(this); return new(g)TDBJCL(this);
...@@ -618,47 +621,47 @@ PTDB JSONDEF::GetTable(PGLOBAL g, MODE m) ...@@ -618,47 +621,47 @@ PTDB JSONDEF::GetTable(PGLOBAL g, MODE m)
!(tmp == TMP_FORCE && !(tmp == TMP_FORCE &&
(m == MODE_UPDATE || m == MODE_DELETE)); (m == MODE_UPDATE || m == MODE_DELETE));
if (Uri) { if (Uri) {
if (Driver && toupper(*Driver) == 'C') { if (Driver && toupper(*Driver) == 'C') {
#if defined(CMGO_SUPPORT) #if defined(CMGO_SUPPORT)
txfp = new(g) CMGFAM(this); txfp = new(g) CMGFAM(this);
#else #else
sprintf(g->Message, "Mongo %s Driver not available", "C"); sprintf(g->Message, "Mongo %s Driver not available", "C");
return NULL; return NULL;
#endif #endif
} else if (Driver && toupper(*Driver) == 'J') { } else if (Driver && toupper(*Driver) == 'J') {
#if defined(JAVA_SUPPORT) #if defined(JAVA_SUPPORT)
txfp = new(g) JMGFAM(this); txfp = new(g) JMGFAM(this);
#else #else
sprintf(g->Message, "Mongo %s Driver not available", "Java"); sprintf(g->Message, "Mongo %s Driver not available", "Java");
return NULL; return NULL;
#endif #endif
} else { // Driver not specified } else { // Driver not specified
#if defined(CMGO_SUPPORT) #if defined(CMGO_SUPPORT)
txfp = new(g) CMGFAM(this); txfp = new(g) CMGFAM(this);
#elif defined(JAVA_SUPPORT) #elif defined(JAVA_SUPPORT)
txfp = new(g) JMGFAM(this); txfp = new(g) JMGFAM(this);
#else // !MONGO_SUPPORT #else // !MONGO_SUPPORT
sprintf(g->Message, MSG(NO_FEAT_SUPPORT), "MONGO"); sprintf(g->Message, MSG(NO_FEAT_SUPPORT), "MONGO");
return NULL; return NULL;
#endif // !MONGO_SUPPORT #endif // !MONGO_SUPPORT
} // endif Driver } // endif Driver
} else if (Zipped) { } else if (Zipped) {
#if defined(ZIP_SUPPORT) #if defined(ZIP_SUPPORT)
if (m == MODE_READ || m == MODE_ANY || m == MODE_ALTER) { if (m == MODE_READ || m == MODE_ANY || m == MODE_ALTER) {
txfp = new(g) UNZFAM(this); txfp = new(g) UNZFAM(this);
} else if (m == MODE_INSERT) { } else if (m == MODE_INSERT) {
txfp = new(g) ZIPFAM(this); txfp = new(g) ZIPFAM(this);
} else { } else {
strcpy(g->Message, "UPDATE/DELETE not supported for ZIP"); strcpy(g->Message, "UPDATE/DELETE not supported for ZIP");
return NULL; return NULL;
} // endif's m } // endif's m
#else // !ZIP_SUPPORT #else // !ZIP_SUPPORT
sprintf(g->Message, MSG(NO_FEAT_SUPPORT), "ZIP"); sprintf(g->Message, MSG(NO_FEAT_SUPPORT), "ZIP");
return NULL; return NULL;
#endif // !ZIP_SUPPORT #endif // !ZIP_SUPPORT
} else if (Compressed) { } else if (Compressed) {
#if defined(GZ_SUPPORT) #if defined(GZ_SUPPORT)
if (Compressed == 1) if (Compressed == 1)
txfp = new(g) GZFAM(this); txfp = new(g) GZFAM(this);
...@@ -668,7 +671,7 @@ PTDB JSONDEF::GetTable(PGLOBAL g, MODE m) ...@@ -668,7 +671,7 @@ PTDB JSONDEF::GetTable(PGLOBAL g, MODE m)
sprintf(g->Message, MSG(NO_FEAT_SUPPORT), "GZ"); sprintf(g->Message, MSG(NO_FEAT_SUPPORT), "GZ");
return NULL; return NULL;
#endif // !GZ_SUPPORT #endif // !GZ_SUPPORT
} else if (map) } else if (map)
txfp = new(g) MAPFAM(this); txfp = new(g) MAPFAM(this);
else else
txfp = new(g) DOSFAM(this); txfp = new(g) DOSFAM(this);
...@@ -676,41 +679,41 @@ PTDB JSONDEF::GetTable(PGLOBAL g, MODE m) ...@@ -676,41 +679,41 @@ PTDB JSONDEF::GetTable(PGLOBAL g, MODE m)
// Txfp must be set for TDBDOS // Txfp must be set for TDBDOS
tdbp = new(g) TDBJSN(this, txfp); tdbp = new(g) TDBJSN(this, txfp);
if (Lrecl) { if (Lrecl) {
// Allocate the parse work memory // Allocate the parse work memory
PGLOBAL G = (PGLOBAL)PlugSubAlloc(g, NULL, sizeof(GLOBAL)); PGLOBAL G = (PGLOBAL)PlugSubAlloc(g, NULL, sizeof(GLOBAL));
memset(G, 0, sizeof(GLOBAL)); memset(G, 0, sizeof(GLOBAL));
G->Sarea_Size = Lrecl * 10; G->Sarea_Size = Lrecl * 10;
G->Sarea = PlugSubAlloc(g, NULL, G->Sarea_Size); G->Sarea = PlugSubAlloc(g, NULL, G->Sarea_Size);
PlugSubSet(G->Sarea, G->Sarea_Size); PlugSubSet(G->Sarea, G->Sarea_Size);
G->jump_level = 0; G->jump_level = 0;
((TDBJSN*)tdbp)->G = G; ((TDBJSN*)tdbp)->G = G;
} else { } else {
strcpy(g->Message, "LRECL is not defined"); strcpy(g->Message, "LRECL is not defined");
return NULL; return NULL;
} // endif Lrecl } // endif Lrecl
} else { } else {
if (Zipped) { if (Zipped) {
#if defined(ZIP_SUPPORT) #if defined(ZIP_SUPPORT)
if (m == MODE_READ || m == MODE_ANY || m == MODE_ALTER) { if (m == MODE_READ || m == MODE_ANY || m == MODE_ALTER) {
txfp = new(g) UNZFAM(this); txfp = new(g) UNZFAM(this);
} else if (m == MODE_INSERT) { } else if (m == MODE_INSERT) {
strcpy(g->Message, "INSERT supported only for zipped JSON when pretty=0"); strcpy(g->Message, "INSERT supported only for zipped JSON when pretty=0");
return NULL; return NULL;
} else { } else {
strcpy(g->Message, "UPDATE/DELETE not supported for ZIP"); strcpy(g->Message, "UPDATE/DELETE not supported for ZIP");
return NULL; return NULL;
} // endif's m } // endif's m
#else // !ZIP_SUPPORT #else // !ZIP_SUPPORT
sprintf(g->Message, MSG(NO_FEAT_SUPPORT), "ZIP"); sprintf(g->Message, MSG(NO_FEAT_SUPPORT), "ZIP");
return NULL; return NULL;
#endif // !ZIP_SUPPORT #endif // !ZIP_SUPPORT
} else } else
txfp = new(g) MAPFAM(this); txfp = new(g) MAPFAM(this);
tdbp = new(g) TDBJSON(this, txfp); tdbp = new(g) TDBJSON(this, txfp);
((TDBJSON*)tdbp)->G = g; ((TDBJSON*)tdbp)->G = g;
} // endif Pretty } // endif Pretty
if (Multiple) if (Multiple)
...@@ -738,16 +741,16 @@ TDBJSN::TDBJSN(PJDEF tdp, PTXF txfp) : TDBDOS(tdp, txfp) ...@@ -738,16 +741,16 @@ TDBJSN::TDBJSN(PJDEF tdp, PTXF txfp) : TDBDOS(tdp, txfp)
Limit = tdp->Limit; Limit = tdp->Limit;
Pretty = tdp->Pretty; Pretty = tdp->Pretty;
B = tdp->Base ? 1 : 0; B = tdp->Base ? 1 : 0;
Sep = tdp->Sep; Sep = tdp->Sep;
Strict = tdp->Strict; Strict = tdp->Strict;
} else { } else {
Jmode = MODE_OBJECT; Jmode = MODE_OBJECT;
Objname = NULL; Objname = NULL;
Xcol = NULL; Xcol = NULL;
Limit = 1; Limit = 1;
Pretty = 0; Pretty = 0;
B = 0; B = 0;
Sep = '.'; Sep = '.';
Strict = false; Strict = false;
} // endif tdp } // endif tdp
...@@ -761,7 +764,7 @@ TDBJSN::TDBJSN(PJDEF tdp, PTXF txfp) : TDBDOS(tdp, txfp) ...@@ -761,7 +764,7 @@ TDBJSN::TDBJSN(PJDEF tdp, PTXF txfp) : TDBDOS(tdp, txfp)
TDBJSN::TDBJSN(TDBJSN *tdbp) : TDBDOS(NULL, tdbp) TDBJSN::TDBJSN(TDBJSN *tdbp) : TDBDOS(NULL, tdbp)
{ {
G = NULL; G = NULL;
Top = tdbp->Top; Top = tdbp->Top;
Row = tdbp->Row; Row = tdbp->Row;
Val = tdbp->Val; Val = tdbp->Val;
...@@ -777,7 +780,7 @@ TDBJSN::TDBJSN(TDBJSN *tdbp) : TDBDOS(NULL, tdbp) ...@@ -777,7 +780,7 @@ TDBJSN::TDBJSN(TDBJSN *tdbp) : TDBDOS(NULL, tdbp)
SameRow = tdbp->SameRow; SameRow = tdbp->SameRow;
Xval = tdbp->Xval; Xval = tdbp->Xval;
B = tdbp->B; B = tdbp->B;
Sep = tdbp->Sep; Sep = tdbp->Sep;
Pretty = tdbp->Pretty; Pretty = tdbp->Pretty;
Strict = tdbp->Strict; Strict = tdbp->Strict;
Comma = tdbp->Comma; Comma = tdbp->Comma;
...@@ -786,7 +789,7 @@ TDBJSN::TDBJSN(TDBJSN *tdbp) : TDBDOS(NULL, tdbp) ...@@ -786,7 +789,7 @@ TDBJSN::TDBJSN(TDBJSN *tdbp) : TDBDOS(NULL, tdbp)
// Used for update // Used for update
PTDB TDBJSN::Clone(PTABS t) PTDB TDBJSN::Clone(PTABS t)
{ {
G = NULL; G = NULL;
PTDB tp; PTDB tp;
PJCOL cp1, cp2; PJCOL cp1, cp2;
PGLOBAL g = t->G; PGLOBAL g = t->G;
...@@ -860,33 +863,33 @@ PJSON TDBJSN::FindRow(PGLOBAL g) ...@@ -860,33 +863,33 @@ PJSON TDBJSN::FindRow(PGLOBAL g)
PJSON jsp = Row; PJSON jsp = Row;
PJVAL val = NULL; PJVAL val = NULL;
for (objpath = PlugDup(g, Objname); jsp && objpath; objpath = p) { for (objpath = PlugDup(g, Objname); jsp && objpath; objpath = p) {
if ((p = strchr(objpath, Sep))) if ((p = strchr(objpath, Sep)))
*p++ = 0; *p++ = 0;
if (*objpath != '[' && !IsNum(objpath)) { // objpass is a key if (*objpath != '[' && !IsNum(objpath)) { // objpass is a key
val = (jsp->GetType() == TYPE_JOB) ? val = (jsp->GetType() == TYPE_JOB) ?
jsp->GetObject()->GetValue(objpath) : NULL; jsp->GetObject()->GetValue(objpath) : NULL;
} else { } else {
if (*objpath == '[') { if (*objpath == '[') {
if (objpath[strlen(objpath) - 1] == ']') if (objpath[strlen(objpath) - 1] == ']')
objpath++; objpath++;
else else
return NULL; return NULL;
} // endif [ } // endif [
val = (jsp->GetType() == TYPE_JAR) ? val = (jsp->GetType() == TYPE_JAR) ?
jsp->GetArray()->GetValue(atoi(objpath) - B) : NULL; jsp->GetArray()->GetValue(atoi(objpath) - B) : NULL;
} // endif objpath } // endif objpath
jsp = (val) ? val->GetJson() : NULL; jsp = (val) ? val->GetJson() : NULL;
} // endfor objpath } // endfor objpath
return jsp; return jsp;
} // end of FindRow } // end of FindRow
/***********************************************************************/ /***********************************************************************/
/* OpenDB: Data Base open routine for JSN access method. */ /* OpenDB: Data Base open routine for JSN access method. */
/***********************************************************************/ /***********************************************************************/
bool TDBJSN::OpenDB(PGLOBAL g) bool TDBJSN::OpenDB(PGLOBAL g)
{ {
...@@ -911,15 +914,15 @@ bool TDBJSN::OpenDB(PGLOBAL g) ...@@ -911,15 +914,15 @@ bool TDBJSN::OpenDB(PGLOBAL g)
return true; return true;
} // endswitch Jmode } // endswitch Jmode
} // endif Use } // endif Use
if (TDBDOS::OpenDB(g)) if (TDBDOS::OpenDB(g))
return true; return true;
if (Xcol) if (Xcol)
To_Filter = NULL; // Imcompatible To_Filter = NULL; // Imcompatible
return false; return false;
} // end of OpenDB } // end of OpenDB
/***********************************************************************/ /***********************************************************************/
...@@ -969,27 +972,27 @@ int TDBJSN::ReadDB(PGLOBAL g) ...@@ -969,27 +972,27 @@ int TDBJSN::ReadDB(PGLOBAL g)
NextSame = 0; NextSame = 0;
M++; M++;
return RC_OK; return RC_OK;
} else if ((rc = TDBDOS::ReadDB(g)) == RC_OK) { } else if ((rc = TDBDOS::ReadDB(g)) == RC_OK) {
if (!IsRead() && ((rc = ReadBuffer(g)) != RC_OK)) if (!IsRead() && ((rc = ReadBuffer(g)) != RC_OK))
// Deferred reading failed // Deferred reading failed
return rc; return rc;
// Recover the memory used for parsing // Recover the memory used for parsing
PlugSubSet(G->Sarea, G->Sarea_Size); PlugSubSet(G->Sarea, G->Sarea_Size);
if ((Row = ParseJson(G, To_Line, strlen(To_Line), &Pretty, &Comma))) { if ((Row = ParseJson(G, To_Line, strlen(To_Line), &Pretty, &Comma))) {
Row = FindRow(g); Row = FindRow(g);
SameRow = 0; SameRow = 0;
Fpos++; Fpos++;
M = 1; M = 1;
rc = RC_OK; rc = RC_OK;
} else if (Pretty != 1 || strcmp(To_Line, "]")) { } else if (Pretty != 1 || strcmp(To_Line, "]")) {
strcpy(g->Message, G->Message); strcpy(g->Message, G->Message);
rc = RC_FX; rc = RC_FX;
} else } else
rc = RC_EF; rc = RC_EF;
} // endif ReadDB } // endif ReadDB
return rc; return rc;
} // end of ReadDB } // end of ReadDB
...@@ -999,68 +1002,68 @@ int TDBJSN::ReadDB(PGLOBAL g) ...@@ -999,68 +1002,68 @@ int TDBJSN::ReadDB(PGLOBAL g)
/***********************************************************************/ /***********************************************************************/
int TDBJSN::MakeTopTree(PGLOBAL g, PJSON jsp) int TDBJSN::MakeTopTree(PGLOBAL g, PJSON jsp)
{ {
if (Objname) { if (Objname) {
if (!Val) { if (!Val) {
// Parse and allocate Objname item(s) // Parse and allocate Objname item(s)
char *p; char *p;
char *objpath = PlugDup(g, Objname); char *objpath = PlugDup(g, Objname);
int i; int i;
PJOB objp; PJOB objp;
PJAR arp; PJAR arp;
PJVAL val = NULL; PJVAL val = NULL;
Top = NULL; Top = NULL;
for (; objpath; objpath = p) { for (; objpath; objpath = p) {
if ((p = strchr(objpath, Sep))) if ((p = strchr(objpath, Sep)))
*p++ = 0; *p++ = 0;
if (*objpath != '[' && !IsNum(objpath)) { if (*objpath != '[' && !IsNum(objpath)) {
objp = new(g) JOBJECT; objp = new(g) JOBJECT;
if (!Top) if (!Top)
Top = objp; Top = objp;
if (val) if (val)
val->SetValue(objp); val->SetValue(objp);
val = new(g) JVALUE; val = new(g) JVALUE;
objp->SetValue(g, val, objpath); objp->SetValue(g, val, objpath);
} else { } else {
if (*objpath == '[') { if (*objpath == '[') {
// Old style // Old style
if (objpath[strlen(objpath) - 1] != ']') { if (objpath[strlen(objpath) - 1] != ']') {
sprintf(g->Message, "Invalid Table path %s", Objname); sprintf(g->Message, "Invalid Table path %s", Objname);
return RC_FX; return RC_FX;
} else } else
objpath++; objpath++;
} // endif objpath } // endif objpath
arp = new(g) JARRAY; arp = new(g) JARRAY;
if (!Top) if (!Top)
Top = arp; Top = arp;
if (val) if (val)
val->SetValue(arp); val->SetValue(arp);
val = new(g) JVALUE; val = new(g) JVALUE;
i = atoi(objpath) - B; i = atoi(objpath) - B;
arp->SetValue(g, val, i); arp->SetValue(g, val, i);
arp->InitArray(g); arp->InitArray(g);
} // endif objpath } // endif objpath
} // endfor p } // endfor p
Val = val; Val = val;
} // endif Val } // endif Val
Val->SetValue(jsp); Val->SetValue(jsp);
} else } else
Top = jsp; Top = jsp;
return RC_OK; return RC_OK;
} // end of MakeTopTree } // end of MakeTopTree
/***********************************************************************/ /***********************************************************************/
...@@ -1095,11 +1098,11 @@ int TDBJSN::MakeTopTree(PGLOBAL g, PJSON jsp) ...@@ -1095,11 +1098,11 @@ int TDBJSN::MakeTopTree(PGLOBAL g, PJSON jsp)
/***********************************************************************/ /***********************************************************************/
int TDBJSN::WriteDB(PGLOBAL g) int TDBJSN::WriteDB(PGLOBAL g)
{ {
int rc = TDBDOS::WriteDB(g); int rc = TDBDOS::WriteDB(g);
PlugSubSet(G->Sarea, G->Sarea_Size); PlugSubSet(G->Sarea, G->Sarea_Size);
Row->Clear(); Row->Clear();
return rc; return rc;
} // end of WriteDB } // end of WriteDB
/* ---------------------------- JSONCOL ------------------------------ */ /* ---------------------------- JSONCOL ------------------------------ */
...@@ -1111,12 +1114,12 @@ JSONCOL::JSONCOL(PGLOBAL g, PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i) ...@@ -1111,12 +1114,12 @@ JSONCOL::JSONCOL(PGLOBAL g, PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i)
: DOSCOL(g, cdp, tdbp, cprec, i, "DOS") : DOSCOL(g, cdp, tdbp, cprec, i, "DOS")
{ {
Tjp = (TDBJSN *)(tdbp->GetOrig() ? tdbp->GetOrig() : tdbp); Tjp = (TDBJSN *)(tdbp->GetOrig() ? tdbp->GetOrig() : tdbp);
G = Tjp->G; G = Tjp->G;
Jpath = cdp->GetFmt(); Jpath = cdp->GetFmt();
MulVal = NULL; MulVal = NULL;
Nodes = NULL; Nodes = NULL;
Nod = 0; Nod = 0;
Sep = Tjp->Sep; Sep = Tjp->Sep;
Xnod = -1; Xnod = -1;
Xpd = false; Xpd = false;
Parsed = false; Parsed = false;
...@@ -1128,14 +1131,14 @@ JSONCOL::JSONCOL(PGLOBAL g, PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i) ...@@ -1128,14 +1131,14 @@ JSONCOL::JSONCOL(PGLOBAL g, PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i)
/***********************************************************************/ /***********************************************************************/
JSONCOL::JSONCOL(JSONCOL *col1, PTDB tdbp) : DOSCOL(col1, tdbp) JSONCOL::JSONCOL(JSONCOL *col1, PTDB tdbp) : DOSCOL(col1, tdbp)
{ {
G = col1->G; G = col1->G;
Tjp = col1->Tjp; Tjp = col1->Tjp;
Jpath = col1->Jpath; Jpath = col1->Jpath;
MulVal = col1->MulVal; MulVal = col1->MulVal;
Nodes = col1->Nodes; Nodes = col1->Nodes;
Nod = col1->Nod; Nod = col1->Nod;
Sep = col1->Sep; Sep = col1->Sep;
Xnod = col1->Xnod; Xnod = col1->Xnod;
Xpd = col1->Xpd; Xpd = col1->Xpd;
Parsed = col1->Parsed; Parsed = col1->Parsed;
} // end of JSONCOL copy constructor } // end of JSONCOL copy constructor
...@@ -1153,7 +1156,7 @@ bool JSONCOL::SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check) ...@@ -1153,7 +1156,7 @@ bool JSONCOL::SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check)
return true; return true;
Tjp = (TDBJSN*)To_Tdb; Tjp = (TDBJSN*)To_Tdb;
G = Tjp->G; G = Tjp->G;
return false; return false;
} // end of SetBuffer } // end of SetBuffer
...@@ -1179,130 +1182,130 @@ bool JSONCOL::CheckExpand(PGLOBAL g, int i, PSZ nm, bool b) ...@@ -1179,130 +1182,130 @@ bool JSONCOL::CheckExpand(PGLOBAL g, int i, PSZ nm, bool b)
/***********************************************************************/ /***********************************************************************/
bool JSONCOL::SetArrayOptions(PGLOBAL g, char *p, int i, PSZ nm) bool JSONCOL::SetArrayOptions(PGLOBAL g, char *p, int i, PSZ nm)
{ {
int n; int n;
bool dg = true, b = false; bool dg = true, b = false;
PJNODE jnp = &Nodes[i]; PJNODE jnp = &Nodes[i];
//if (*p == '[') p++; // Old syntax .[ or :[ //if (*p == '[') p++; // Old syntax .[ or :[
n = (int)strlen(p); n = (int)strlen(p);
if (*p) { if (*p) {
if (p[n - 1] == ']') { if (p[n - 1] == ']') {
p[--n] = 0; p[--n] = 0;
} else if (!IsNum(p)) { } else if (!IsNum(p)) {
// Wrong array specification // Wrong array specification
sprintf(g->Message, "Invalid array specification %s for %s", p, Name); sprintf(g->Message, "Invalid array specification %s for %s", p, Name);
return true; return true;
} // endif p } // endif p
} else } else
b = true; b = true;
// To check whether a numeric Rank was specified // To check whether a numeric Rank was specified
dg = IsNum(p); dg = IsNum(p);
if (!n) { if (!n) {
// Default specifications // Default specifications
if (CheckExpand(g, i, nm, false)) if (CheckExpand(g, i, nm, false))
return true; return true;
else if (jnp->Op != OP_EXP) { else if (jnp->Op != OP_EXP) {
if (b) { if (b) {
// Return 1st value (B is the index base) // Return 1st value (B is the index base)
jnp->Rank = Tjp->B; jnp->Rank = Tjp->B;
jnp->Op = OP_EQ; jnp->Op = OP_EQ;
} else if (!Value->IsTypeNum()) { } else if (!Value->IsTypeNum()) {
jnp->CncVal = AllocateValue(g, (void*)", ", TYPE_STRING); jnp->CncVal = AllocateValue(g, (void*)", ", TYPE_STRING);
jnp->Op = OP_CNC; jnp->Op = OP_CNC;
} else } else
jnp->Op = OP_ADD; jnp->Op = OP_ADD;
} // endif OP } // endif OP
} else if (dg) { } else if (dg) {
// Return nth value // Return nth value
jnp->Rank = atoi(p) - Tjp->B; jnp->Rank = atoi(p) - Tjp->B;
jnp->Op = OP_EQ; jnp->Op = OP_EQ;
} else if (n == 1) { } else if (n == 1) {
// Set the Op value; // Set the Op value;
if (Sep == ':') if (Sep == ':')
switch (*p) { switch (*p) {
case '*': *p = 'x'; break; case '*': *p = 'x'; break;
case 'x': case 'x':
case 'X': *p = '*'; break; // Expand this array case 'X': *p = '*'; break; // Expand this array
default: break; default: break;
} // endswitch p } // endswitch p
switch (*p) { switch (*p) {
case '+': jnp->Op = OP_ADD; break; case '+': jnp->Op = OP_ADD; break;
case 'x': jnp->Op = OP_MULT; break; case 'x': jnp->Op = OP_MULT; break;
case '>': jnp->Op = OP_MAX; break; case '>': jnp->Op = OP_MAX; break;
case '<': jnp->Op = OP_MIN; break; case '<': jnp->Op = OP_MIN; break;
case '!': jnp->Op = OP_SEP; break; // Average case '!': jnp->Op = OP_SEP; break; // Average
case '#': jnp->Op = OP_NUM; break; case '#': jnp->Op = OP_NUM; break;
case '*': // Expand this array case '*': // Expand this array
if (!Tjp->Xcol && nm) { if (!Tjp->Xcol && nm) {
Xpd = true; Xpd = true;
jnp->Op = OP_EXP; jnp->Op = OP_EXP;
Tjp->Xval = i; Tjp->Xval = i;
Tjp->Xcol = nm; Tjp->Xcol = nm;
} else if (CheckExpand(g, i, nm, true)) } else if (CheckExpand(g, i, nm, true))
return true; return true;
break; break;
default: default:
sprintf(g->Message, sprintf(g->Message,
"Invalid function specification %c for %s", *p, Name); "Invalid function specification %c for %s", *p, Name);
return true; return true;
} // endswitch *p } // endswitch *p
} else if (*p == '"' && p[n - 1] == '"') { } else if (*p == '"' && p[n - 1] == '"') {
// This is a concat specification // This is a concat specification
jnp->Op = OP_CNC; jnp->Op = OP_CNC;
if (n > 2) { if (n > 2) {
// Set concat intermediate string // Set concat intermediate string
p[n - 1] = 0; p[n - 1] = 0;
jnp->CncVal = AllocateValue(g, p + 1, TYPE_STRING); jnp->CncVal = AllocateValue(g, p + 1, TYPE_STRING);
} // endif n } // endif n
} else { } else {
sprintf(g->Message, "Wrong array specification for %s", Name); sprintf(g->Message, "Wrong array specification for %s", Name);
return true; return true;
} // endif's } // endif's
// For calculated arrays, a local Value must be used // For calculated arrays, a local Value must be used
switch (jnp->Op) { switch (jnp->Op) {
case OP_NUM: case OP_NUM:
jnp->Valp = AllocateValue(g, TYPE_INT); jnp->Valp = AllocateValue(g, TYPE_INT);
break; break;
case OP_ADD: case OP_ADD:
case OP_MULT: case OP_MULT:
case OP_SEP: case OP_SEP:
if (!IsTypeChar(Buf_Type)) if (!IsTypeChar(Buf_Type))
jnp->Valp = AllocateValue(g, Buf_Type, 0, GetPrecision()); jnp->Valp = AllocateValue(g, Buf_Type, 0, GetPrecision());
else else
jnp->Valp = AllocateValue(g, TYPE_DOUBLE, 0, 2); jnp->Valp = AllocateValue(g, TYPE_DOUBLE, 0, 2);
break; break;
case OP_MIN: case OP_MIN:
case OP_MAX: case OP_MAX:
jnp->Valp = AllocateValue(g, Buf_Type, Long, GetPrecision()); jnp->Valp = AllocateValue(g, Buf_Type, Long, GetPrecision());
break; break;
case OP_CNC: case OP_CNC:
if (IsTypeChar(Buf_Type)) if (IsTypeChar(Buf_Type))
jnp->Valp = AllocateValue(g, TYPE_STRING, Long, GetPrecision()); jnp->Valp = AllocateValue(g, TYPE_STRING, Long, GetPrecision());
else else
jnp->Valp = AllocateValue(g, TYPE_STRING, 512); jnp->Valp = AllocateValue(g, TYPE_STRING, 512);
break; break;
default: default:
break; break;
} // endswitch Op } // endswitch Op
if (jnp->Valp) if (jnp->Valp)
MulVal = AllocateValue(g, jnp->Valp); MulVal = AllocateValue(g, jnp->Valp);
return false; return false;
} // end of SetArrayOptions } // end of SetArrayOptions
/***********************************************************************/ /***********************************************************************/
...@@ -1313,87 +1316,87 @@ bool JSONCOL::SetArrayOptions(PGLOBAL g, char *p, int i, PSZ nm) ...@@ -1313,87 +1316,87 @@ bool JSONCOL::SetArrayOptions(PGLOBAL g, char *p, int i, PSZ nm)
/***********************************************************************/ /***********************************************************************/
bool JSONCOL::ParseJpath(PGLOBAL g) bool JSONCOL::ParseJpath(PGLOBAL g)
{ {
char *p, *p1 = NULL, *p2 = NULL, *pbuf = NULL; char *p, *p1 = NULL, *p2 = NULL, *pbuf = NULL;
int i; int i;
bool a, mul = false; bool a, mul = false;
if (Parsed) if (Parsed)
return false; // Already done return false; // Already done
else if (InitValue(g)) else if (InitValue(g))
return true; return true;
else if (!Jpath) else if (!Jpath)
Jpath = Name; Jpath = Name;
if (To_Tdb->GetOrig()) { if (To_Tdb->GetOrig()) {
// This is an updated column, get nodes from origin // This is an updated column, get nodes from origin
for (PJCOL colp = (PJCOL)Tjp->GetColumns(); colp; for (PJCOL colp = (PJCOL)Tjp->GetColumns(); colp;
colp = (PJCOL)colp->GetNext()) colp = (PJCOL)colp->GetNext())
if (!stricmp(Name, colp->GetName())) { if (!stricmp(Name, colp->GetName())) {
Nod = colp->Nod; Nod = colp->Nod;
Nodes = colp->Nodes; Nodes = colp->Nodes;
Xpd = colp->Xpd; Xpd = colp->Xpd;
goto fin; goto fin;
} // endif Name } // endif Name
sprintf(g->Message, "Cannot parse updated column %s", Name); sprintf(g->Message, "Cannot parse updated column %s", Name);
return true; return true;
} // endif To_Orig } // endif To_Orig
pbuf = PlugDup(g, Jpath); pbuf = PlugDup(g, Jpath);
if (*pbuf == '$') pbuf++; if (*pbuf == '$') pbuf++;
if (*pbuf == Sep) pbuf++; if (*pbuf == Sep) pbuf++;
if (*pbuf == '[') p1 = pbuf++; if (*pbuf == '[') p1 = pbuf++;
// Estimate the required number of nodes // Estimate the required number of nodes
for (i = 0, p = pbuf; (p = NextChr(p, Sep)); i++, p++) for (i = 0, p = pbuf; (p = NextChr(p, Sep)); i++, p++)
Nod++; // One path node found Nod++; // One path node found
Nodes = (PJNODE)PlugSubAlloc(g, NULL, (++Nod) * sizeof(JNODE)); Nodes = (PJNODE)PlugSubAlloc(g, NULL, (++Nod) * sizeof(JNODE));
memset(Nodes, 0, (Nod) * sizeof(JNODE)); memset(Nodes, 0, (Nod) * sizeof(JNODE));
// Analyze the Jpath for this column // Analyze the Jpath for this column
for (i = 0, p = pbuf; p && i < Nod; i++, p = (p2 ? p2 : NULL)) { for (i = 0, p = pbuf; p && i < Nod; i++, p = (p2 ? p2 : NULL)) {
a = (p1 != NULL); a = (p1 != NULL);
p1 = strchr(p, '['); p1 = strchr(p, '[');
p2 = strchr(p, Sep); p2 = strchr(p, Sep);
if (!p2) if (!p2)
p2 = p1; p2 = p1;
else if (p1) { else if (p1) {
if (p1 < p2) if (p1 < p2)
p2 = p1; p2 = p1;
else if (p1 == p2 + 1) else if (p1 == p2 + 1)
*p2++ = 0; // Old syntax .[ or :[ *p2++ = 0; // Old syntax .[ or :[
else else
p1 = NULL; p1 = NULL;
} // endif p1 } // endif p1
if (p2) if (p2)
*p2++ = 0; *p2++ = 0;
// Jpath must be explicit // Jpath must be explicit
if (a || *p == 0 || *p == '[' || IsNum(p)) { if (a || *p == 0 || *p == '[' || IsNum(p)) {
// Analyse intermediate array processing // Analyse intermediate array processing
if (SetArrayOptions(g, p, i, Nodes[i - 1].Key)) if (SetArrayOptions(g, p, i, Nodes[i - 1].Key))
return true; return true;
} else if (*p == '*') { } else if (*p == '*') {
// Return JSON // Return JSON
Nodes[i].Op = OP_XX; Nodes[i].Op = OP_XX;
} else { } else {
Nodes[i].Key = p; Nodes[i].Key = p;
Nodes[i].Op = OP_EXIST; Nodes[i].Op = OP_EXIST;
} // endif's } // endif's
} // endfor i, p } // endfor i, p
Nod = i; Nod = i;
fin: fin:
MulVal = AllocateValue(g, Value); MulVal = AllocateValue(g, Value);
Parsed = true; Parsed = true;
return false; return false;
} // end of ParseJpath } // end of ParseJpath
/***********************************************************************/ /***********************************************************************/
...@@ -1401,66 +1404,66 @@ bool JSONCOL::ParseJpath(PGLOBAL g) ...@@ -1401,66 +1404,66 @@ bool JSONCOL::ParseJpath(PGLOBAL g)
/***********************************************************************/ /***********************************************************************/
PSZ JSONCOL::GetJpath(PGLOBAL g, bool proj) PSZ JSONCOL::GetJpath(PGLOBAL g, bool proj)
{ {
if (Jpath) { if (Jpath) {
char *p1, *p2, *mgopath; char *p1, *p2, *mgopath;
int i = 0; int i = 0;
if (strcmp(Jpath, "*")) { if (strcmp(Jpath, "*")) {
p1 = Jpath; p1 = Jpath;
if (*p1 == '$') p1++; if (*p1 == '$') p1++;
if (*p1 == '.') p1++; if (*p1 == '.') p1++;
mgopath = PlugDup(g, p1); mgopath = PlugDup(g, p1);
} else } else
return NULL; return NULL;
for (p1 = p2 = mgopath; *p1; p1++) for (p1 = p2 = mgopath; *p1; p1++)
if (i) { // Inside [] if (i) { // Inside []
if (isdigit(*p1)) { if (isdigit(*p1)) {
if (!proj) if (!proj)
*p2++ = *p1; *p2++ = *p1;
} else if (*p1 == ']' && i == 1) { } else if (*p1 == ']' && i == 1) {
if (proj && p1[1] == '.') if (proj && p1[1] == '.')
p1++; p1++;
i = 0; i = 0;
} else if (*p1 == '.' && i == 2) { } else if (*p1 == '.' && i == 2) {
if (!proj) if (!proj)
*p2++ = '.'; *p2++ = '.';
i = 0; i = 0;
} else if (!proj) } else if (!proj)
return NULL; return NULL;
} else switch (*p1) { } else switch (*p1) {
case ':': case ':':
case '.': case '.':
if (isdigit(p1[1])) if (isdigit(p1[1]))
i = 2; i = 2;
*p2++ = '.'; *p2++ = '.';
break; break;
case '[': case '[':
if (*(p2 - 1) != '.') if (*(p2 - 1) != '.')
*p2++ = '.'; *p2++ = '.';
i = 1; i = 1;
break; break;
case '*': case '*':
if (*(p2 - 1) == '.' && !*(p1 + 1)) { if (*(p2 - 1) == '.' && !*(p1 + 1)) {
p2--; // Suppress last :* p2--; // Suppress last :*
break; break;
} // endif p2 } // endif p2
default: default:
*p2++ = *p1; *p2++ = *p1;
break; break;
} // endswitch p1; } // endswitch p1;
*p2 = 0; *p2 = 0;
return mgopath; return mgopath;
} else } else
return NULL; return NULL;
} // end of GetJpath } // end of GetJpath
...@@ -1469,7 +1472,7 @@ PSZ JSONCOL::GetJpath(PGLOBAL g, bool proj) ...@@ -1469,7 +1472,7 @@ PSZ JSONCOL::GetJpath(PGLOBAL g, bool proj)
/***********************************************************************/ /***********************************************************************/
PVAL JSONCOL::MakeJson(PGLOBAL g, PJSON jsp) PVAL JSONCOL::MakeJson(PGLOBAL g, PJSON jsp)
{ {
if (Value->IsTypeNum()) { if (Value->IsTypeNum()) {
strcpy(g->Message, "Cannot make Json for a numeric column"); strcpy(g->Message, "Cannot make Json for a numeric column");
Value->Reset(); Value->Reset();
} else } else
...@@ -1484,22 +1487,22 @@ PVAL JSONCOL::MakeJson(PGLOBAL g, PJSON jsp) ...@@ -1484,22 +1487,22 @@ PVAL JSONCOL::MakeJson(PGLOBAL g, PJSON jsp)
void JSONCOL::SetJsonValue(PGLOBAL g, PVAL vp, PJVAL val, int n) void JSONCOL::SetJsonValue(PGLOBAL g, PVAL vp, PJVAL val, int n)
{ {
if (val) { if (val) {
vp->SetNull(false); vp->SetNull(false);
switch (val->GetValType()) { switch (val->GetValType()) {
case TYPE_STRG: case TYPE_STRG:
case TYPE_INTG: case TYPE_INTG:
case TYPE_BINT: case TYPE_BINT:
case TYPE_DBL: case TYPE_DBL:
case TYPE_DTM: case TYPE_DTM:
vp->SetValue_pval(val->GetValue()); vp->SetValue_pval(val->GetValue());
break; break;
case TYPE_BOOL: case TYPE_BOOL:
if (vp->IsTypeNum()) if (vp->IsTypeNum())
vp->SetValue(val->GetInteger() ? 1 : 0); vp->SetValue(val->GetInteger() ? 1 : 0);
else else
vp->SetValue_psz((PSZ)(val->GetInteger() ? "true" : "false")); vp->SetValue_psz((PSZ)(val->GetInteger() ? "true" : "false"));
break; break;
case TYPE_JAR: case TYPE_JAR:
SetJsonValue(g, vp, val->GetArray()->GetValue(0), n); SetJsonValue(g, vp, val->GetArray()->GetValue(0), n);
...@@ -1509,16 +1512,16 @@ void JSONCOL::SetJsonValue(PGLOBAL g, PVAL vp, PJVAL val, int n) ...@@ -1509,16 +1512,16 @@ void JSONCOL::SetJsonValue(PGLOBAL g, PVAL vp, PJVAL val, int n)
vp->SetValue_psz(val->GetObject()->GetText(g, NULL)); vp->SetValue_psz(val->GetObject()->GetText(g, NULL));
break; break;
// } // endif Type // } // endif Type
default: default:
vp->Reset(); vp->Reset();
vp->SetNull(true); vp->SetNull(true);
} // endswitch Type } // endswitch Type
} else { } else {
vp->Reset(); vp->Reset();
vp->SetNull(true); vp->SetNull(true);
} // endif val } // endif val
} // end of SetJsonValue } // end of SetJsonValue
...@@ -1530,8 +1533,8 @@ void JSONCOL::ReadColumn(PGLOBAL g) ...@@ -1530,8 +1533,8 @@ void JSONCOL::ReadColumn(PGLOBAL g)
if (!Tjp->SameRow || Xnod >= Tjp->SameRow) if (!Tjp->SameRow || Xnod >= Tjp->SameRow)
Value->SetValue_pval(GetColumnValue(g, Tjp->Row, 0)); Value->SetValue_pval(GetColumnValue(g, Tjp->Row, 0));
if (Xpd && Value->IsNull() && !((PJDEF)Tjp->To_Def)->Accept) if (Xpd && Value->IsNull() && !((PJDEF)Tjp->To_Def)->Accept)
throw("Null expandable JSON value"); throw("Null expandable JSON value");
// Set null when applicable // Set null when applicable
if (!Nullable) if (!Nullable)
...@@ -1579,11 +1582,11 @@ PVAL JSONCOL::GetColumnValue(PGLOBAL g, PJSON row, int i) ...@@ -1579,11 +1582,11 @@ PVAL JSONCOL::GetColumnValue(PGLOBAL g, PJSON row, int i)
else else
return CalculateArray(g, arp, i); return CalculateArray(g, arp, i);
} else { } else {
// Unexpected array, unwrap it as [0] // Unexpected array, unwrap it as [0]
val = arp->GetValue(0); val = arp->GetValue(0);
i--; i--;
} // endif's } // endif's
break; break;
case TYPE_JVAL: case TYPE_JVAL:
...@@ -1612,17 +1615,17 @@ PVAL JSONCOL::ExpandArray(PGLOBAL g, PJAR arp, int n) ...@@ -1612,17 +1615,17 @@ PVAL JSONCOL::ExpandArray(PGLOBAL g, PJAR arp, int n)
PJVAL jvp; PJVAL jvp;
JVALUE jval; JVALUE jval;
if (!ars) { if (!ars) {
Value->Reset(); Value->Reset();
Value->SetNull(true); Value->SetNull(true);
Tjp->NextSame = 0; Tjp->NextSame = 0;
return Value; return Value;
} // endif ars } // endif ars
if (!(jvp = arp->GetValue((Nodes[n].Rx = Nodes[n].Nx)))) { if (!(jvp = arp->GetValue((Nodes[n].Rx = Nodes[n].Nx)))) {
strcpy(g->Message, "Logical error expanding array"); strcpy(g->Message, "Logical error expanding array");
throw 666; throw 666;
} // endif jvp } // endif jvp
if (n < Nod - 1 && jvp->GetJson()) { if (n < Nod - 1 && jvp->GetJson()) {
jval.SetValue(GetColumnValue(g, jvp->GetJson(), n + 1)); jval.SetValue(GetColumnValue(g, jvp->GetJson(), n + 1));
...@@ -1637,7 +1640,7 @@ PVAL JSONCOL::ExpandArray(PGLOBAL g, PJAR arp, int n) ...@@ -1637,7 +1640,7 @@ PVAL JSONCOL::ExpandArray(PGLOBAL g, PJAR arp, int n)
Xnod = n; Xnod = n;
Tjp->NextSame = Xnod; Tjp->NextSame = Xnod;
} // endif NextSame } // endif NextSame
SetJsonValue(g, Value, jvp, n); SetJsonValue(g, Value, jvp, n);
return Value; return Value;
...@@ -1648,58 +1651,58 @@ PVAL JSONCOL::ExpandArray(PGLOBAL g, PJAR arp, int n) ...@@ -1648,58 +1651,58 @@ PVAL JSONCOL::ExpandArray(PGLOBAL g, PJAR arp, int n)
/***********************************************************************/ /***********************************************************************/
PVAL JSONCOL::CalculateArray(PGLOBAL g, PJAR arp, int n) PVAL JSONCOL::CalculateArray(PGLOBAL g, PJAR arp, int n)
{ {
int i, ars, nv = 0, nextsame = Tjp->NextSame; int i, ars, nv = 0, nextsame = Tjp->NextSame;
bool err; bool err;
OPVAL op = Nodes[n].Op; OPVAL op = Nodes[n].Op;
PVAL val[2], vp = Nodes[n].Valp; PVAL val[2], vp = Nodes[n].Valp;
PJVAL jvrp, jvp; PJVAL jvrp, jvp;
JVALUE jval; JVALUE jval;
vp->Reset(); vp->Reset();
ars = MY_MIN(Tjp->Limit, arp->size()); ars = MY_MIN(Tjp->Limit, arp->size());
if (trace(1)) if (trace(1))
htrc("CalculateArray: size=%d op=%d nextsame=%d\n", htrc("CalculateArray: size=%d op=%d nextsame=%d\n",
ars, op, nextsame); ars, op, nextsame);
for (i = 0; i < ars; i++) { for (i = 0; i < ars; i++) {
jvrp = arp->GetValue(i); jvrp = arp->GetValue(i);
if (trace(1)) if (trace(1))
htrc("i=%d nv=%d\n", i, nv); htrc("i=%d nv=%d\n", i, nv);
if (!jvrp->IsNull() || (op == OP_CNC && GetJsonNull())) do { if (!jvrp->IsNull() || (op == OP_CNC && GetJsonNull())) do {
if (jvrp->IsNull()) { if (jvrp->IsNull()) {
jvrp->Value = AllocateValue(g, GetJsonNull(), TYPE_STRING); jvrp->Value = AllocateValue(g, GetJsonNull(), TYPE_STRING);
jvp = jvrp; jvp = jvrp;
} else if (n < Nod - 1 && jvrp->GetJson()) { } else if (n < Nod - 1 && jvrp->GetJson()) {
Tjp->NextSame = nextsame; Tjp->NextSame = nextsame;
jval.SetValue(GetColumnValue(g, jvrp->GetJson(), n + 1)); jval.SetValue(GetColumnValue(g, jvrp->GetJson(), n + 1));
jvp = &jval; jvp = &jval;
} else } else
jvp = jvrp; jvp = jvrp;
if (trace(1))
htrc("jvp=%s null=%d\n",
jvp->GetString(g), jvp->IsNull() ? 1 : 0);
if (!nv++) { if (trace(1))
htrc("jvp=%s null=%d\n",
jvp->GetString(g), jvp->IsNull() ? 1 : 0);
if (!nv++) {
SetJsonValue(g, vp, jvp, n); SetJsonValue(g, vp, jvp, n);
continue; continue;
} else } else
SetJsonValue(g, MulVal, jvp, n); SetJsonValue(g, MulVal, jvp, n);
if (!MulVal->IsNull()) { if (!MulVal->IsNull()) {
switch (op) { switch (op) {
case OP_CNC: case OP_CNC:
if (Nodes[n].CncVal) { if (Nodes[n].CncVal) {
val[0] = Nodes[n].CncVal; val[0] = Nodes[n].CncVal;
err = vp->Compute(g, val, 1, op); err = vp->Compute(g, val, 1, op);
} // endif CncVal } // endif CncVal
val[0] = MulVal; val[0] = MulVal;
err = vp->Compute(g, val, 1, op); err = vp->Compute(g, val, 1, op);
break; break;
// case OP_NUM: // case OP_NUM:
case OP_SEP: case OP_SEP:
val[0] = Nodes[n].Valp; val[0] = Nodes[n].Valp;
...@@ -1714,16 +1717,16 @@ PVAL JSONCOL::CalculateArray(PGLOBAL g, PJAR arp, int n) ...@@ -1714,16 +1717,16 @@ PVAL JSONCOL::CalculateArray(PGLOBAL g, PJAR arp, int n)
if (err) if (err)
vp->Reset(); vp->Reset();
if (trace(1)) {
char buf(32);
htrc("vp='%s' err=%d\n", if (trace(1)) {
vp->GetCharString(&buf), err ? 1 : 0); char buf(32);
} // endif trace htrc("vp='%s' err=%d\n",
vp->GetCharString(&buf), err ? 1 : 0);
} // endif Null } // endif trace
} // endif Null
} while (Tjp->NextSame > nextsame); } while (Tjp->NextSame > nextsame);
...@@ -1753,8 +1756,8 @@ PJSON JSONCOL::GetRow(PGLOBAL g) ...@@ -1753,8 +1756,8 @@ PJSON JSONCOL::GetRow(PGLOBAL g)
PJAR arp; PJAR arp;
PJSON nwr, row = Tjp->Row; PJSON nwr, row = Tjp->Row;
for (int i = 0; i < Nod && row; i++) { for (int i = 0; i < Nod && row; i++) {
if (Nodes[i+1].Op == OP_XX) if (Nodes[i+1].Op == OP_XX)
break; break;
else switch (row->GetType()) { else switch (row->GetType()) {
case TYPE_JOB: case TYPE_JOB:
...@@ -1765,19 +1768,19 @@ PJSON JSONCOL::GetRow(PGLOBAL g) ...@@ -1765,19 +1768,19 @@ PJSON JSONCOL::GetRow(PGLOBAL g)
val = ((PJOB)row)->GetValue(Nodes[i].Key); val = ((PJOB)row)->GetValue(Nodes[i].Key);
break; break;
case TYPE_JAR: case TYPE_JAR:
arp = (PJAR)row; arp = (PJAR)row;
if (!Nodes[i].Key) { if (!Nodes[i].Key) {
if (Nodes[i].Op == OP_EQ) if (Nodes[i].Op == OP_EQ)
val = arp->GetValue(Nodes[i].Rank); val = arp->GetValue(Nodes[i].Rank);
else else
val = arp->GetValue(Nodes[i].Rx); val = arp->GetValue(Nodes[i].Rx);
} else { } else {
// Unexpected array, unwrap it as [0] // Unexpected array, unwrap it as [0]
val = arp->GetValue(0); val = arp->GetValue(0);
i--; i--;
} // endif Nodes } // endif Nodes
break; break;
case TYPE_JVAL: case TYPE_JVAL:
...@@ -1827,10 +1830,10 @@ PJSON JSONCOL::GetRow(PGLOBAL g) ...@@ -1827,10 +1830,10 @@ PJSON JSONCOL::GetRow(PGLOBAL g)
/***********************************************************************/ /***********************************************************************/
void JSONCOL::WriteColumn(PGLOBAL g) void JSONCOL::WriteColumn(PGLOBAL g)
{ {
if (Xpd && Tjp->Pretty < 2) { if (Xpd && Tjp->Pretty < 2) {
strcpy(g->Message, "Cannot write expanded column when Pretty is not 2"); strcpy(g->Message, "Cannot write expanded column when Pretty is not 2");
throw 666; throw 666;
} // endif Xpd } // endif Xpd
/*********************************************************************/ /*********************************************************************/
/* Check whether this node must be written. */ /* Check whether this node must be written. */
...@@ -1864,8 +1867,8 @@ void JSONCOL::WriteColumn(PGLOBAL g) ...@@ -1864,8 +1867,8 @@ void JSONCOL::WriteColumn(PGLOBAL g)
if (!(jsp = ParseJson(G, s, (int)strlen(s)))) { if (!(jsp = ParseJson(G, s, (int)strlen(s)))) {
strcpy(g->Message, s); strcpy(g->Message, s);
throw 666; throw 666;
} // endif jsp } // endif jsp
if (arp) { if (arp) {
if (Nod > 1 && Nodes[Nod-2].Op == OP_EQ) if (Nod > 1 && Nodes[Nod-2].Op == OP_EQ)
...@@ -1887,10 +1890,10 @@ void JSONCOL::WriteColumn(PGLOBAL g) ...@@ -1887,10 +1890,10 @@ void JSONCOL::WriteColumn(PGLOBAL g)
// fall through // fall through
case TYPE_DATE: case TYPE_DATE:
case TYPE_INT: case TYPE_INT:
case TYPE_TINY: case TYPE_TINY:
case TYPE_SHORT: case TYPE_SHORT:
case TYPE_BIGINT: case TYPE_BIGINT:
case TYPE_DOUBLE: case TYPE_DOUBLE:
if (arp) { if (arp) {
if (Nodes[Nod-1].Op == OP_EQ) if (Nodes[Nod-1].Op == OP_EQ)
arp->SetValue(G, new(G) JVALUE(G, Value), Nodes[Nod-1].Rank); arp->SetValue(G, new(G) JVALUE(G, Value), Nodes[Nod-1].Rank);
...@@ -1981,7 +1984,7 @@ int TDBJSON::MakeDocument(PGLOBAL g) ...@@ -1981,7 +1984,7 @@ int TDBJSON::MakeDocument(PGLOBAL g)
return RC_OK; return RC_OK;
/*********************************************************************/ /*********************************************************************/
/* Create the mapping file object in mode read. */ /* Create the mapping file object in mode read. */
/*********************************************************************/ /*********************************************************************/
Mode = MODE_READ; Mode = MODE_READ;
...@@ -2010,70 +2013,70 @@ int TDBJSON::MakeDocument(PGLOBAL g) ...@@ -2010,70 +2013,70 @@ int TDBJSON::MakeDocument(PGLOBAL g)
if (!jsp && g->Message[0]) if (!jsp && g->Message[0])
return RC_FX; return RC_FX;
if ((objpath = PlugDup(g, Objname))) { if ((objpath = PlugDup(g, Objname))) {
if (*objpath == '$') objpath++; if (*objpath == '$') objpath++;
if (*objpath == '.') objpath++; if (*objpath == '.') objpath++;
/*********************************************************************/ /*********************************************************************/
/* Find the table in the tree structure. */ /* Find the table in the tree structure. */
/*********************************************************************/ /*********************************************************************/
for (; jsp && objpath; objpath = p) { for (; jsp && objpath; objpath = p) {
if ((p = strchr(objpath, Sep))) if ((p = strchr(objpath, Sep)))
*p++ = 0; *p++ = 0;
if (*objpath != '[' && !IsNum(objpath)) { if (*objpath != '[' && !IsNum(objpath)) {
// objpass is a key // objpass is a key
if (jsp->GetType() != TYPE_JOB) { if (jsp->GetType() != TYPE_JOB) {
strcpy(g->Message, "Table path does not match the json file"); strcpy(g->Message, "Table path does not match the json file");
return RC_FX; return RC_FX;
} // endif Type } // endif Type
key = objpath; key = objpath;
objp = jsp->GetObject(); objp = jsp->GetObject();
arp = NULL; arp = NULL;
val = objp->GetValue(key); val = objp->GetValue(key);
if (!val || !(jsp = val->GetJson())) { if (!val || !(jsp = val->GetJson())) {
sprintf(g->Message, "Cannot find object key %s", key); sprintf(g->Message, "Cannot find object key %s", key);
return RC_FX; return RC_FX;
} // endif val } // endif val
} else { } else {
if (*objpath == '[') { if (*objpath == '[') {
// Old style // Old style
if (objpath[strlen(objpath) - 1] != ']') { if (objpath[strlen(objpath) - 1] != ']') {
sprintf(g->Message, "Invalid Table path %s", Objname); sprintf(g->Message, "Invalid Table path %s", Objname);
return RC_FX; return RC_FX;
} else } else
objpath++; objpath++;
} // endif objpath } // endif objpath
if (jsp->GetType() != TYPE_JAR) { if (jsp->GetType() != TYPE_JAR) {
strcpy(g->Message, "Table path does not match the json file"); strcpy(g->Message, "Table path does not match the json file");
return RC_FX; return RC_FX;
} // endif Type } // endif Type
arp = jsp->GetArray(); arp = jsp->GetArray();
objp = NULL; objp = NULL;
i = atoi(objpath) - B; i = atoi(objpath) - B;
val = arp->GetValue(i); val = arp->GetValue(i);
if (!val) { if (!val) {
sprintf(g->Message, "Cannot find array value %d", i); sprintf(g->Message, "Cannot find array value %d", i);
return RC_FX; return RC_FX;
} // endif val } // endif val
} // endif } // endif
jsp = val->GetJson(); jsp = val->GetJson();
} // endfor objpath } // endfor objpath
} // endif objpath } // endif objpath
if (jsp && jsp->GetType() == TYPE_JAR) if (jsp && jsp->GetType() == TYPE_JAR)
Doc = jsp->GetArray(); Doc = jsp->GetArray();
else { else {
// The table is void or is just one object or one value // The table is void or is just one object or one value
Doc = new(g) JARRAY; Doc = new(g) JARRAY;
...@@ -2149,7 +2152,7 @@ int TDBJSON::MakeIndex(PGLOBAL g, PIXDEF pxdf, bool) ...@@ -2149,7 +2152,7 @@ int TDBJSON::MakeIndex(PGLOBAL g, PIXDEF pxdf, bool)
} else } else
return RC_OK; return RC_OK;
} // end of MakeIndex } // end of MakeIndex
/***********************************************************************/ /***********************************************************************/
/* Return the position in the table. */ /* Return the position in the table. */
...@@ -2227,11 +2230,11 @@ bool TDBJSON::OpenDB(PGLOBAL g) ...@@ -2227,11 +2230,11 @@ bool TDBJSON::OpenDB(PGLOBAL g)
return true; return true;
} // endswitch Jmode } // endswitch Jmode
if (Xcol) if (Xcol)
To_Filter = NULL; // Imcompatible To_Filter = NULL; // Imcompatible
Use = USE_OPEN; Use = USE_OPEN;
return false; return false;
} // end of OpenDB } // end of OpenDB
/***********************************************************************/ /***********************************************************************/
...@@ -2241,7 +2244,7 @@ int TDBJSON::ReadDB(PGLOBAL) ...@@ -2241,7 +2244,7 @@ int TDBJSON::ReadDB(PGLOBAL)
{ {
int rc; int rc;
N++; N++;
if (NextSame) { if (NextSame) {
SameRow = NextSame; SameRow = NextSame;
...@@ -2352,8 +2355,8 @@ void TDBJSON::CloseDB(PGLOBAL g) ...@@ -2352,8 +2355,8 @@ void TDBJSON::CloseDB(PGLOBAL g)
TDBJCL::TDBJCL(PJDEF tdp) : TDBCAT(tdp) TDBJCL::TDBJCL(PJDEF tdp) : TDBCAT(tdp)
{ {
Topt = tdp->GetTopt(); Topt = tdp->GetTopt();
Db = tdp->Schema; Db = tdp->Schema;
Dsn = tdp->Uri; Dsn = tdp->Uri;
} // end of TDBJCL constructor } // end of TDBJCL constructor
/***********************************************************************/ /***********************************************************************/
......
/*************** Rest C++ Program Source Code File (.CPP) **************/ /*************** Rest C++ Program Source Code File (.CPP) **************/
/* PROGRAM NAME: Rest Version 1.3 */ /* PROGRAM NAME: Rest Version 1.5 */
/* (C) Copyright to the author Olivier BERTRAND 2018 - 2019 */ /* (C) Copyright to the author Olivier BERTRAND 2018 - 2019 */
/* This program is the REST OEM (Web API support) module definition. */ /* This program is the REST Web API support for MariaDB. */
/* When compiled without MARIADB defined, it is the EOM module code. */
/***********************************************************************/ /***********************************************************************/
/***********************************************************************/ /***********************************************************************/
/* Definitions needed by the included files. */ /* Definitions needed by the included files. */
/***********************************************************************/ /***********************************************************************/
#if defined(MARIADB)
#include <my_global.h> // All MariaDB stuff #include <my_global.h> // All MariaDB stuff
#else // !MARIADB OEM module
#include "mini-global.h"
#define _MAX_PATH 260
#if !defined(__WIN__)
#define __stdcall
#endif // !__WIN__
#define _OS_H_INCLUDED // Prevent os.h to be called
#endif // !MARIADB
/***********************************************************************/ /***********************************************************************/
/* Include application header files: */ /* Include application header files: */
...@@ -19,12 +29,12 @@ ...@@ -19,12 +29,12 @@
#include "plgdbsem.h" #include "plgdbsem.h"
#include "xtable.h" #include "xtable.h"
#include "filamtxt.h" #include "filamtxt.h"
#include "plgxml.h"
#include "tabdos.h" #include "tabdos.h"
#include "tabfmt.h" #include "plgxml.h"
#include "tabxml.h"
#include "tabjson.h" #include "tabjson.h"
#include "tabfmt.h"
#include "tabrest.h" #include "tabrest.h"
#include "tabxml.h"
/***********************************************************************/ /***********************************************************************/
/* Get the file from the Web. */ /* Get the file from the Web. */
...@@ -32,25 +42,61 @@ ...@@ -32,25 +42,61 @@
int restGetFile(PGLOBAL g, PCSZ http, PCSZ uri, PCSZ fn); int restGetFile(PGLOBAL g, PCSZ http, PCSZ uri, PCSZ fn);
#if defined(__WIN__) #if defined(__WIN__)
static PCSZ slash= "\\"; static PCSZ slash = "\\";
#else // !__WIN__ #else // !__WIN__
static PCSZ slash= "/"; static PCSZ slash = "/";
#define stricmp strcasecmp #define stricmp strcasecmp
#endif // !__WIN__ #endif // !__WIN__
#if !defined(MARIADB)
/***********************************************************************/
/* DB static variables. */
/***********************************************************************/
int TDB::Tnum;
int DTVAL::Shift;
int CSORT::Limit = 0;
double CSORT::Lg2 = log(2.0);
size_t CSORT::Cpn[1000] = { 0 };
/***********************************************************************/
/* These functions are exported from the REST library. */
/***********************************************************************/
extern "C" {
PTABDEF __stdcall GetREST(PGLOBAL, void*);
PQRYRES __stdcall ColREST(PGLOBAL, PTOS, char*, char*, bool);
} // extern "C"
/***********************************************************************/
/* This function returns a table definition class. */
/***********************************************************************/
PTABDEF __stdcall GetREST(PGLOBAL g, void *memp)
{
return new(g, memp) RESTDEF;
} // end of GetREST
#endif // !MARIADB
/***********************************************************************/ /***********************************************************************/
/* Return the columns definition to MariaDB. */ /* Return the columns definition to MariaDB. */
/***********************************************************************/ /***********************************************************************/
#if defined(MARIADB)
PQRYRES RESTColumns(PGLOBAL g, PTOS tp, char *tab, char *db, bool info) PQRYRES RESTColumns(PGLOBAL g, PTOS tp, char *tab, char *db, bool info)
#else // !MARIADB
PQRYRES __stdcall ColREST(PGLOBAL g, PTOS tp, char *tab, char *db, bool info)
#endif // !MARIADB
{ {
PQRYRES qrp= NULL; PQRYRES qrp= NULL;
char filename[_MAX_PATH]; char filename[_MAX_PATH + 1]; // MAX PATH ???
PCSZ http, uri, fn, ftype; PCSZ http, uri, fn, ftype;
http= GetStringTableOption(g, tp, "Http", NULL); http = GetStringTableOption(g, tp, "Http", NULL);
uri= GetStringTableOption(g, tp, "Uri", NULL); uri = GetStringTableOption(g, tp, "Uri", NULL);
fn= GetStringTableOption(g, tp, "Filename", "rest.json"); fn = GetStringTableOption(g, tp, "Filename", "rest.json");
#if defined(MARIADB)
ftype = GetStringTableOption(g, tp, "Type", "JSON"); ftype = GetStringTableOption(g, tp, "Type", "JSON");
#else // !MARIADB
// OEM tables must specify the file type
ftype = GetStringTableOption(g, tp, "Ftype", "JSON");
#endif // !MARIADB
// We used the file name relative to recorded datapath // We used the file name relative to recorded datapath
strcat(strcat(strcat(strcpy(filename, "."), slash), db), slash); strcat(strcat(strcat(strcpy(filename, "."), slash), db), slash);
...@@ -60,11 +106,11 @@ PQRYRES RESTColumns(PGLOBAL g, PTOS tp, char *tab, char *db, bool info) ...@@ -60,11 +106,11 @@ PQRYRES RESTColumns(PGLOBAL g, PTOS tp, char *tab, char *db, bool info)
if (http && restGetFile(g, http, uri, filename)) { if (http && restGetFile(g, http, uri, filename)) {
// sprintf(g->Message, "Failed to get file at %s", http); // sprintf(g->Message, "Failed to get file at %s", http);
} else if (!stricmp(ftype, "XML")) } else if (!stricmp(ftype, "XML"))
qrp= XMLColumns(g, db, tab, tp, info); qrp = XMLColumns(g, db, tab, tp, info);
else if (!stricmp(ftype, "JSON")) else if (!stricmp(ftype, "JSON"))
qrp= JSONColumns(g, db, NULL, tp, info); qrp = JSONColumns(g, db, NULL, tp, info);
else if (!stricmp(ftype, "CSV")) else if (!stricmp(ftype, "CSV"))
qrp= CSVColumns(g, NULL, tp, info); qrp = CSVColumns(g, NULL, tp, info);
else else
sprintf(g->Message, "Usupported file type %s", ftype); sprintf(g->Message, "Usupported file type %s", ftype);
...@@ -78,40 +124,59 @@ PQRYRES RESTColumns(PGLOBAL g, PTOS tp, char *tab, char *db, bool info) ...@@ -78,40 +124,59 @@ PQRYRES RESTColumns(PGLOBAL g, PTOS tp, char *tab, char *db, bool info)
/***********************************************************************/ /***********************************************************************/
bool RESTDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff) bool RESTDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
{ {
char filename[_MAX_PATH]; char filename[_MAX_PATH + 1];
TABTYPE type= GetTypeID(am); int rc = 0, n;
LPCSTR ftype;
switch (type) {
case TAB_JSON: #if defined(MARIADB)
case TAB_XML: ftype = GetStringCatInfo(g, "Type", "JSON");
case TAB_CSV: #else // !MARIADB
break; // OEM tables must specify the file type
default: ftype = GetStringCatInfo(g, "Ftype", "JSON");
sprintf(g->Message, "Unsupported REST table type %s", am); #endif // !MARIADB
return true;
} // endswitch type if (trace(1))
htrc("ftype = %s am = %s\n", ftype, SVP(am));
Http= GetStringCatInfo(g, "Http", NULL);
Uri= GetStringCatInfo(g, "Uri", NULL); n = (!stricmp(ftype, "JSON")) ? 1
Fn= GetStringCatInfo(g, "Filename", "rest.json"); : (!stricmp(ftype, "XML")) ? 2
: (!stricmp(ftype, "CSV")) ? 3 : 0;
if (n == 0) {
htrc("DefineAM: Unsupported REST table type %s", am);
sprintf(g->Message, "Unsupported REST table type %s", am);
return true;
} // endif n
Http = GetStringCatInfo(g, "Http", NULL);
Uri = GetStringCatInfo(g, "Uri", NULL);
Fn = GetStringCatInfo(g, "Filename", "rest.json");
// We used the file name relative to recorded datapath // We used the file name relative to recorded datapath
PlugSetPath(filename, Fn, GetPath()); //PlugSetPath(filename, Fn, GetPath());
strncat(strcpy(filename, GetPath()), Fn, _MAX_PATH);
// Retrieve the file from the web and copy it locally // Retrieve the file from the web and copy it locally
if (Http && restGetFile(g, Http, Uri, filename)) {} rc = restGetFile(g, Http, Uri, filename);
else if (type == TAB_JSON)
Tdp= new (g) JSONDEF; if (trace(1))
else if (type == TAB_XML) htrc("Return from restGetFile: rc=%d\n", rc);
Tdp= new (g) XMLDEF;
else if (type == TAB_CSV) if (rc)
Tdp= new (g) CSVDEF; return true;
else else switch (n) {
sprintf(g->Message, "Unsupported REST table type %s", am); case 1: Tdp = new (g) JSONDEF; break;
case 2: Tdp = new (g) XMLDEF; break;
case 3: Tdp = new (g) CSVDEF; break;
default: Tdp = NULL;
} // endswitch n
// Do make the table/view definition // Do make the table/view definition
if (Tdp && Tdp->Define(g, Cat, Name, Schema, "REST")) if (Tdp && Tdp->Define(g, Cat, Name, Schema, "REST"))
Tdp= NULL; // Error occured Tdp = NULL; // Error occured
if (trace(1))
htrc("Tdp defined\n", rc);
// Return true in case of error // Return true in case of error
return (Tdp == NULL); return (Tdp == NULL);
...@@ -122,10 +187,12 @@ bool RESTDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff) ...@@ -122,10 +187,12 @@ bool RESTDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
/***********************************************************************/ /***********************************************************************/
PTDB RESTDEF::GetTable(PGLOBAL g, MODE m) PTDB RESTDEF::GetTable(PGLOBAL g, MODE m)
{ {
if (m != MODE_READ && m != MODE_READX) { xtrc(515, "REST GetTable mode=%d\n", m);
strcpy(g->Message, "REST tables are currently read only");
return NULL; if (m != MODE_READ && m != MODE_READX) {
} // endif m strcpy(g->Message, "REST tables are currently read only");
return NULL;
} // endif m
return Tdp->GetTable(g, m); // Leave file type do the job return Tdp->GetTable(g, m); // Leave file type do the job
} // end of GetTable } // end of GetTable
......
# Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved. # Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved.
# #
# This program is free software; you can redistribute it and/or modify # This program is free software; you can redistribute it and/or modify
...@@ -146,3 +145,6 @@ elseif(UNIX) ...@@ -146,3 +145,6 @@ elseif(UNIX)
set_target_properties(zlib PROPERTIES LINK_FLAGS "-Wl,--version-script,\"${CMAKE_CURRENT_SOURCE_DIR}/zlib.map\"") set_target_properties(zlib PROPERTIES LINK_FLAGS "-Wl,--version-script,\"${CMAKE_CURRENT_SOURCE_DIR}/zlib.map\"")
endif() endif()
endif() endif()
RESTRICT_SYMBOL_EXPORTS(zlib)
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment