Commit 56114a41 authored by Sergei Golubchik's avatar Sergei Golubchik

merge 10.0-connect

parents 174bccd3 d9175f38
......@@ -21,9 +21,9 @@ ha_connect.cc connect.cc user_connect.cc mycat.cc
fmdlex.c osutil.c plugutil.c rcmsg.c rcmsg.h
array.cpp blkfil.cpp colblk.cpp csort.cpp
filamap.cpp filamdbf.cpp filamfix.cpp filamtxt.cpp filamvct.cpp filamzip.cpp
filter.cpp json.cpp maputil.cpp myutil.cpp plgdbutl.cpp reldef.cpp tabcol.cpp
tabdos.cpp tabfix.cpp tabfmt.cpp tabjson.cpp table.cpp tabmul.cpp taboccur.cpp
tabpivot.cpp tabsys.cpp tabtbl.cpp tabutil.cpp tabvct.cpp tabvir.cpp
filter.cpp json.cpp jsonudf.cpp maputil.cpp myutil.cpp plgdbutl.cpp reldef.cpp
tabcol.cpp tabdos.cpp tabfix.cpp tabfmt.cpp tabjson.cpp table.cpp tabmul.cpp
taboccur.cpp tabpivot.cpp tabsys.cpp tabtbl.cpp tabutil.cpp tabvct.cpp tabvir.cpp
tabxcl.cpp valblk.cpp value.cpp xindex.cpp xobject.cpp
array.h blkfil.h block.h catalog.h checklvl.h colblk.h connect.h csort.h
......@@ -72,11 +72,6 @@ IF(UNIX)
message(STATUS "CONNECT: GCC: Some warnings disabled")
endif(WITH_WARNINGS)
# Avoid compilation failure in maintainer mode
IF(CMAKE_COMPILER_IS_GNUCXX)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-overloaded-virtual -Wno-error=type-limits")
ENDIF(CMAKE_COMPILER_IS_GNUCXX)
add_definitions( -DUNIX -DLINUX -DUBUNTU )
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fpermissive -fexceptions -fPIC ")
......
......@@ -50,6 +50,7 @@ class DllExport ARRAY : public XOBJECT, public CSORT { // Array descblock
// void SetCorrel(bool b) {Correlated = b;}
// Methods
using XOBJECT::GetIntValue;
virtual void Reset(void) {Bot = -1;}
virtual int Qcompare(int *, int *);
virtual bool Compare(PXOB) {assert(FALSE); return FALSE;}
......
......@@ -40,4 +40,11 @@ enum USETEMP {TMP_NO = 0, /* Never */
TMP_FORCE = 3, /* Forced for MAP tables */
TMP_TEST = 4}; /* Testing value */
/***********************************************************************/
/* Following definitions indicate conversion of TEXT columns. */
/***********************************************************************/
enum TYPCONV {TPC_NO = 0, /* Never */
TPC_YES = 1, /* Always */
TPC_SKIP = 2}; /* Skip TEXT columns */
#endif // _CHKLVL_DEFINED_
......@@ -469,9 +469,12 @@ RCODE CntReadNext(PGLOBAL g, PTDB tdbp)
} while (rc == RC_NF);
if (rc == RC_OK)
rc= EvalColumns(g, tdbp, false);
err:
g->jump_level--;
return (rc != RC_OK) ? rc : EvalColumns(g, tdbp, false);
return rc;
} // end of CntReadNext
/***********************************************************************/
......
This diff is collapsed.
......@@ -34,7 +34,7 @@
/***********************************************************************/
PJSON ParseJson(PGLOBAL g, char *s, int len, int pretty, bool *comma)
{
int i;
int i, rc;
bool b = false;
PJSON jsp = NULL;
STRG src;
......@@ -48,22 +48,32 @@ PJSON ParseJson(PGLOBAL g, char *s, int len, int pretty, bool *comma)
src.str = s;
src.len = len;
// Save stack and allocation environment and prepare error return
if (g->jump_level == MAX_JUMP) {
strcpy(g->Message, MSG(TOO_MANY_JUMPS));
return NULL;
} // endif jump_level
if ((rc= setjmp(g->jumper[++g->jump_level])) != 0) {
goto err;
} // endif rc
for (i = 0; i < len; i++)
switch (s[i]) {
case '[':
if (jsp) {
strcpy(g->Message, "More than one item in file");
return NULL;
goto err;
} else if (!(jsp = ParseArray(g, ++i, src)))
return NULL;
goto err;
break;
case '{':
if (jsp) {
strcpy(g->Message, "More than one item in file");
return NULL;
goto err;
} else if (!(jsp = ParseObject(g, ++i, src)))
return NULL;
goto err;
break;
case ' ':
case '\t':
......@@ -79,7 +89,7 @@ PJSON ParseJson(PGLOBAL g, char *s, int len, int pretty, bool *comma)
} // endif pretty
sprintf(g->Message, "Unexpected ',' (pretty=%d)", pretty);
return NULL;
goto err;
case '(':
b = true;
break;
......@@ -92,13 +102,18 @@ PJSON ParseJson(PGLOBAL g, char *s, int len, int pretty, bool *comma)
default:
sprintf(g->Message, "Bad '%c' character near %.*s",
s[i], ARGS);
return NULL;
goto err;
}; // endswitch s[i]
if (!jsp)
sprintf(g->Message, "Invalid Json string '%.*s'", 50, s);
g->jump_level--;
return jsp;
err:
g->jump_level--;
return NULL;
} // end of ParseJson
/***********************************************************************/
......@@ -312,18 +327,25 @@ err:
/***********************************************************************/
char *ParseString(PGLOBAL g, int& i, STRG& src)
{
char *p, *s = src.str;
char *s = src.str;
uchar *p;
int n = 0, len = src.len;
// Be sure of memory availability
if (len + 1 - i > (signed)((PPOOLHEADER)g->Sarea)->FreeBlk) {
strcpy(g->Message, "ParseString: Out of memory");
return NULL;
} // endif len
// The size to allocate is not known yet
p = (char*)PlugSubAlloc(g, NULL, 0);
p = (uchar*)PlugSubAlloc(g, NULL, 0);
for (; i < len; i++)
switch (s[i]) {
case '"':
p[n++] = 0;
PlugSubAlloc(g, NULL, n);
return p;
return (char*)p;
case '\\':
if (++i < len) {
if (s[i] == 'u') {
......@@ -504,8 +526,11 @@ PSZ Serialize(PGLOBAL g, PJSON jsp, FILE *fs, int pretty)
err = (b && jp->WriteChr('\t'));
err |= SerializeObject(jp, (PJOB)jsp);
break;
case TYPE_JVAL:
err = SerializeValue(jp, (PJVAL)jsp);
break;
default:
strcpy(g->Message, "json tree is not an Array or an Object");
strcpy(g->Message, "Invalid json tree");
} // endswitch Type
if (fs) {
......@@ -575,9 +600,9 @@ bool SerializeObject(JOUT *js, PJOB jobp)
else if (js->WriteChr(','))
return true;
if (js->WriteChr('\"') ||
if (js->WriteChr('"') ||
js->WriteStr(pair->Key) ||
js->WriteChr('\"') ||
js->WriteChr('"') ||
js->WriteChr(':') ||
SerializeValue(js, pair->Val))
return true;
......@@ -675,12 +700,13 @@ bool JOUTSTR::Escape(const char *s)
for (unsigned int i = 0; i < strlen(s); i++)
switch (s[i]) {
case '"':
case '\\':
case '\t':
case '\n':
case '\r':
case '\b':
case '\f':
case '"': WriteChr('\\');
case '\f': WriteChr('\\');
// passthru
default:
WriteChr(s[i]);
......@@ -723,12 +749,13 @@ bool JOUTFILE::Escape(const char *s)
for (unsigned int i = 0; i < strlen(s); i++)
switch (s[i]) {
case '"': fputs("\\\"", Stream); break;
case '\\': fputs("\\\\", Stream); break;
case '\t': fputs("\\t", Stream); break;
case '\n': fputs("\\n", Stream); break;
case '\r': fputs("\\r", Stream); break;
case '\b': fputs("\\b", Stream); break;
case '\f': fputs("\\f", Stream); break;
case '"': fputs("\\\"", Stream); break;
default:
fputc(s[i], Stream);
break;
......@@ -1053,3 +1080,27 @@ PSZ JVALUE::GetString(void)
return (Value) ? Value->GetCharString(buf) : NULL;
} // end of GetString
/***********************************************************************/
/* Set the Value's value as the given integer. */
/***********************************************************************/
void JVALUE::SetInteger(PGLOBAL g, int n)
{
Value = AllocateValue(g, &n, TYPE_INT);
} // end of AddInteger
/***********************************************************************/
/* Set the Value's value as the given DOUBLE. */
/***********************************************************************/
void JVALUE::SetFloat(PGLOBAL g, double f)
{
Value = AllocateValue(g, &f, TYPE_DOUBLE, 6);
} // end of AddFloat
/***********************************************************************/
/* Set the Value's value as the given string. */
/***********************************************************************/
void JVALUE::SetString(PGLOBAL g, PSZ s)
{
Value = AllocateValue(g, s, TYPE_STRING);
} // end of AddFloat
......@@ -18,7 +18,8 @@ enum JTYP {TYPE_STRG = 1,
TYPE_BOOL = 4,
TYPE_INTG = 7,
TYPE_JSON = 12,
TYPE_JAR, TYPE_JOB,
TYPE_JAR,
TYPE_JOB,
TYPE_JVAL};
class JOUT;
......@@ -156,6 +157,9 @@ class JSON : public BLOCK {
virtual void SetValue(PGLOBAL g, PJVAL jvp, PSZ key) {X}
virtual void SetValue(PVAL valp) {X}
virtual void SetValue(PJSON jsp) {X}
virtual void SetString(PGLOBAL g, PSZ s) {X}
virtual void SetInteger(PGLOBAL g, int n) {X}
virtual void SetFloat(PGLOBAL g, double f) {X}
virtual bool DeleteValue(int i) {X return true;}
protected:
......@@ -171,6 +175,8 @@ class JOBJECT : public JSON {
public:
JOBJECT(void) : JSON() {First = Last = NULL;}
using JSON::GetValue;
using JSON::SetValue;
virtual void Clear(void) {First = Last = NULL; Size = 0;}
virtual JTYP GetType(void) {return TYPE_JOB;}
virtual PJPR AddPair(PGLOBAL g, PSZ key);
......@@ -192,6 +198,8 @@ class JARRAY : public JSON {
public:
JARRAY(void) : JSON() {Alloc = 0; First = Last = NULL; Mvals = NULL;}
using JSON::GetValue;
using JSON::SetValue;
virtual void Clear(void) {First = Last = NULL; Size = 0;}
virtual JTYP GetType(void) {return TYPE_JAR;}
virtual PJAR GetArray(void) {return this;}
......@@ -223,6 +231,8 @@ class JVALUE : public JSON {
{Jsp = jsp; Value = NULL; Next = NULL; Del = false;}
JVALUE(PGLOBAL g, PVAL valp);
using JSON::GetValue;
using JSON::SetValue;
virtual void Clear(void)
{Jsp = NULL; Value = NULL; Next = NULL; Del = false; Size = 0;}
virtual JTYP GetType(void) {return TYPE_JVAL;}
......@@ -236,6 +246,9 @@ class JVALUE : public JSON {
virtual PSZ GetString(void);
virtual void SetValue(PVAL valp) {Value = valp;}
virtual void SetValue(PJSON jsp) {Jsp = jsp;}
virtual void SetString(PGLOBAL g, PSZ s);
virtual void SetInteger(PGLOBAL g, int n);
virtual void SetFloat(PGLOBAL g, double f);
protected:
PJSON Jsp; // To the json value
......
This diff is collapsed.
......@@ -51,7 +51,8 @@
#define DLL_EXPORT // Items are exported from this DLL
#include "myconn.h"
extern "C" int zconv;
//extern "C" int zconv;
int GetConvSize(void);
extern MYSQL_PLUGIN_IMPORT uint mysqld_port;
extern MYSQL_PLUGIN_IMPORT char *mysqld_unix_port;
......@@ -265,7 +266,7 @@ PQRYRES MyColumns(PGLOBAL g, THD *thd, const char *host, const char *db,
return NULL;
} else if (type == TYPE_STRING) {
if (v == 'X') {
len = zconv;
len = GetConvSize();
sprintf(g->Message, "Column %s converted to varchar(%d)",
colname, len);
PushWarning(g, thd);
......
......@@ -89,8 +89,8 @@ ISBN Language Subject AuthorFN AuthorLN Title Translation Translator Publisher L
UPDATE t1 SET AuthorFN = 'Philippe' WHERE AuthorLN = 'Knab';
SELECT * FROM t1 WHERE ISBN = '9782212090819';
ISBN Language Subject AuthorFN AuthorLN Title Translation Translator Publisher Location Year
9782212090819 fr applications Jean-Christophe Bernadac Construire une application XML Eyrolles Paris 1999
9782212090819 fr applications Philippe Knab Construire une application XML Eyrolles Paris 1999
9782212090819 fr applications Philippe Bernadac Construire une application XML Eyrolles Paris 1999
9782212090819 fr applications Franois Knab Construire une application XML Eyrolles Paris 1999
#
# To add an author a new table must be created
#
......@@ -104,8 +104,8 @@ William J. Pardi
INSERT INTO t2 VALUES('Charles','Dickens');
SELECT * FROM t1;
ISBN Language Subject AuthorFN AuthorLN Title Translation Translator Publisher Location Year
9782212090819 fr applications Jean-Christophe Bernadac Construire une application XML Eyrolles Paris 1999
9782212090819 fr applications Philippe Knab Construire une application XML Eyrolles Paris 1999
9782212090819 fr applications Philippe Bernadac Construire une application XML Eyrolles Paris 1999
9782212090819 fr applications Franois Knab Construire une application XML Eyrolles Paris 1999
9782840825685 fr applications William J. Pardi XML en Action adapt de l'anglais par James Guerin Microsoft Press Paris 1999
9782840825685 fr applications Charles Dickens XML en Action adapt de l'anglais par James Guerin Microsoft Press Paris 1999
DROP TABLE t1;
......@@ -127,11 +127,11 @@ line
"SUBJECT": "applications",
"AUTHOR": [
{
"FIRSTNAME": "Jean-Christophe",
"FIRSTNAME": "Philippe",
"LASTNAME": "Bernadac"
},
{
"FIRSTNAME": "Philippe",
"FIRSTNAME": "Franois",
"LASTNAME": "Knab"
}
],
......@@ -192,7 +192,7 @@ Janet 4 Car 17.00
Janet 5 Beer+Car+Beer+Food 57.00
DROP TABLE t1;
#
# Cannot be fully expanded
# Now it can be fully expanded
#
CREATE TABLE t1 (
WHO CHAR(12),
......@@ -201,7 +201,31 @@ WHAT CHAR(32) FIELD_FORMAT='WEEK:[X]:EXPENSE:[X]:WHAT',
AMOUNT DOUBLE(8,2) FIELD_FORMAT='WEEK:[X]:EXPENSE:[X]:AMOUNT')
ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='expense.jsn';
SELECT * FROM t1;
ERROR HY000: Got error 174 'Cannot expand more than one array' from CONNECT
WHO WEEK WHAT AMOUNT
Joe 3 Beer 18.00
Joe 3 Food 12.00
Joe 3 Food 19.00
Joe 3 Car 20.00
Joe 4 Beer 19.00
Joe 4 Beer 16.00
Joe 4 Food 17.00
Joe 4 Food 17.00
Joe 4 Beer 14.00
Joe 5 Beer 14.00
Joe 5 Food 12.00
Beth 3 Beer 16.00
Beth 4 Food 17.00
Beth 4 Beer 15.00
Beth 5 Food 12.00
Beth 5 Beer 20.00
Janet 3 Car 19.00
Janet 3 Food 18.00
Janet 3 Beer 18.00
Janet 4 Car 17.00
Janet 5 Beer 14.00
Janet 5 Car 12.00
Janet 5 Beer 19.00
Janet 5 Food 12.00
DROP TABLE t1;
#
# Expand expense in 3 one week tables
......
......@@ -128,7 +128,7 @@ SELECT * FROM t1;
DROP TABLE t1;
--echo #
--echo # Cannot be fully expanded
--echo # Now it can be fully expanded
--echo #
CREATE TABLE t1 (
WHO CHAR(12),
......@@ -136,7 +136,7 @@ WEEK INT(2) FIELD_FORMAT='WEEK:[X]:NUMBER',
WHAT CHAR(32) FIELD_FORMAT='WEEK:[X]:EXPENSE:[X]:WHAT',
AMOUNT DOUBLE(8,2) FIELD_FORMAT='WEEK:[X]:EXPENSE:[X]:AMOUNT')
ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='expense.jsn';
--error ER_GET_ERRMSG
#--error ER_GET_ERRMSG
SELECT * FROM t1;
DROP TABLE t1;
......
......@@ -26,7 +26,8 @@
#include "myutil.h"
#define DLL_EXPORT // Items are exported from this DLL
extern "C" int xconv;
//extern "C" int xconv;
TYPCONV GetTypeConv(void);
/************************************************************************/
/* Convert from MySQL type name to PlugDB type number */
......@@ -34,6 +35,7 @@ extern "C" int xconv;
int MYSQLtoPLG(char *typname, char *var)
{
int type;
TYPCONV xconv = GetTypeConv();
if (!stricmp(typname, "int") || !stricmp(typname, "mediumint") ||
!stricmp(typname, "integer"))
......@@ -57,13 +59,13 @@ int MYSQLtoPLG(char *typname, char *var)
type = TYPE_TINY;
else if (!stricmp(typname, "text") && var) {
switch (xconv) {
case 1:
case TPC_YES:
type = TYPE_STRING;
*var = 'X';
break;
case 2:
case TPC_SKIP:
*var = 'K';
default:
default: // TPC_NO
type = TYPE_ERROR;
} // endswitch xconv
......@@ -88,7 +90,7 @@ int MYSQLtoPLG(char *typname, char *var)
} else if (type == TYPE_STRING && !stricmp(typname, "varchar"))
// This is to make the difference between CHAR and VARCHAR
*var = 'V';
else if (type == TYPE_ERROR && xconv == 2)
else if (type == TYPE_ERROR && xconv == TPC_SKIP)
*var = 'K';
else
*var = 0;
......@@ -174,7 +176,7 @@ const char *PLGtoMYSQLtype(int type, bool dbf, char v)
/************************************************************************/
int MYSQLtoPLG(int mytype, char *var)
{
int type;
int type, xconv = GetTypeConv();
switch (mytype) {
case MYSQL_TYPE_SHORT:
......@@ -221,7 +223,7 @@ int MYSQLtoPLG(int mytype, char *var)
case MYSQL_TYPE_LONG_BLOB:
if (var) {
switch (xconv) {
case 1:
case TPC_YES:
if (*var != 'B') {
// This is a TEXT column
type = TYPE_STRING;
......@@ -230,9 +232,9 @@ int MYSQLtoPLG(int mytype, char *var)
type = TYPE_ERROR;
break;
case 2:
case TPC_SKIP:
*var = 'K'; // Skip
default:
default: // TPC_NO
type = TYPE_ERROR;
} // endswitch xconv
......
......@@ -2,6 +2,14 @@
#define DEFAULT_LOGIN_TIMEOUT -1 // means do not set
#define DEFAULT_QUERY_TIMEOUT -1 // means do not set
typedef struct odbc_parms {
char *User; // User connect info
char *Pwd; // Password connect info
int Cto; // Connect timeout
int Qto; // Query timeout
bool UseCnc; // Use SQLConnect (!SQLDriverConnect)
} ODBCPARM, *POPARM;
/***********************************************************************/
/* ODBC catalog function prototypes. */
/***********************************************************************/
......@@ -10,8 +18,8 @@ char *ODBCCheckConnection(PGLOBAL g, char *dsn, int cop);
#endif // PROMPT_OK
PQRYRES ODBCDataSources(PGLOBAL g, int maxres, bool info);
PQRYRES ODBCColumns(PGLOBAL g, char *dsn, char *db, char *table,
char *colpat, int maxres, int cto, int qto, bool info);
PQRYRES ODBCSrcCols(PGLOBAL g, char *dsn, char *src, int cto, int qto);
char *colpat, int maxres, bool info, POPARM sop);
PQRYRES ODBCSrcCols(PGLOBAL g, char *dsn, char *src, POPARM sop);
PQRYRES ODBCTables(PGLOBAL g, char *dsn, char *db, char *tabpat,
int maxres, int cto, int qto, bool info);
int maxres, bool info, POPARM sop);
PQRYRES ODBCDrivers(PGLOBAL g, int maxres, bool info);
......@@ -37,8 +37,8 @@
#include "xobject.h"
//#include "kindex.h"
#include "xtable.h"
#include "tabodbc.h"
#include "odbccat.h"
#include "tabodbc.h"
#include "plgcnx.h" // For DB types
#include "resource.h"
#include "valblk.h"
......@@ -53,6 +53,8 @@
extern "C" HINSTANCE s_hModule; // Saved module handle
#endif // WIN32
int GetConvSize();
/***********************************************************************/
/* Some macro's (should be defined elsewhere to be more accessible) */
/***********************************************************************/
......@@ -122,7 +124,7 @@ int TranslateSQLType(int stp, int prec, int& len, char& v)
case SQL_LONGVARCHAR: // (-1)
v = 'V';
type = TYPE_STRING;
len = MY_MIN(abs(len), 256);
len = MY_MIN(abs(len), GetConvSize());
break;
case SQL_NUMERIC: // 2
case SQL_DECIMAL: // 3
......@@ -291,7 +293,7 @@ static void ResetNullValues(CATPARM *cap)
/* of an ODBC table that will be retrieved by GetData commands. */
/***********************************************************************/
PQRYRES ODBCColumns(PGLOBAL g, char *dsn, char *db, char *table,
char *colpat, int maxres, int cto, int qto, bool info)
char *colpat, int maxres, bool info, POPARM sop)
{
int buftyp[] = {TYPE_STRING, TYPE_STRING, TYPE_STRING, TYPE_STRING,
TYPE_SHORT, TYPE_STRING, TYPE_INT, TYPE_INT,
......@@ -310,10 +312,8 @@ PQRYRES ODBCColumns(PGLOBAL g, char *dsn, char *db, char *table,
/************************************************************************/
if (!info) {
ocp = new(g) ODBConn(g, NULL);
ocp->SetLoginTimeout((DWORD)cto);
ocp->SetQueryTimeout((DWORD)qto);
if (ocp->Open(dsn, 10) < 1) // openReadOnly + noODBCdialog
if (ocp->Open(dsn, sop, 10) < 1) // openReadOnly + noODBCdialog
return NULL;
if (table && !strchr(table, '%')) {
......@@ -342,7 +342,7 @@ PQRYRES ODBCColumns(PGLOBAL g, char *dsn, char *db, char *table,
} // endif ocp
if (trace)
htrc("ODBCColumns: max=%d len=%d,%d,%d\n",
htrc("ODBCColumns: max=%d len=%d,%d,%d,%d\n",
maxres, length[0], length[1], length[2], length[3]);
/************************************************************************/
......@@ -388,12 +388,13 @@ PQRYRES ODBCColumns(PGLOBAL g, char *dsn, char *db, char *table,
/* ODBCSrcCols: constructs the result blocks containing the */
/* description of all the columns of a Srcdef option. */
/**************************************************************************/
PQRYRES ODBCSrcCols(PGLOBAL g, char *dsn, char *src, int cto, int qto)
PQRYRES ODBCSrcCols(PGLOBAL g, char *dsn, char *src, POPARM sop)
{
ODBConn *ocp = new(g) ODBConn(g, NULL);
ocp->SetLoginTimeout((DWORD)cto);
ocp->SetQueryTimeout((DWORD)qto);
if (ocp->Open(dsn, sop, 10) < 1) // openReadOnly + noOdbcDialog
return NULL;
return ocp->GetMetaData(g, dsn, src);
} // end of ODBCSrcCols
......@@ -574,7 +575,7 @@ PQRYRES ODBCDataSources(PGLOBAL g, int maxres, bool info)
/* an ODBC database that will be retrieved by GetData commands. */
/**************************************************************************/
PQRYRES ODBCTables(PGLOBAL g, char *dsn, char *db, char *tabpat,
int maxres, int cto, int qto, bool info)
int maxres, bool info, POPARM sop)
{
int buftyp[] = {TYPE_STRING, TYPE_STRING, TYPE_STRING,
TYPE_STRING, TYPE_STRING};
......@@ -594,10 +595,8 @@ PQRYRES ODBCTables(PGLOBAL g, char *dsn, char *db, char *tabpat,
/* Open the connection with the ODBC data source. */
/**********************************************************************/
ocp = new(g) ODBConn(g, NULL);
ocp->SetLoginTimeout((DWORD)cto);
ocp->SetQueryTimeout((DWORD)qto);
if (ocp->Open(dsn, 2) < 1) // 2 is openReadOnly
if (ocp->Open(dsn, sop, 2) < 1) // 2 is openReadOnly
return NULL;
if (!maxres)
......@@ -925,11 +924,14 @@ ODBConn::ODBConn(PGLOBAL g, TDBODBC *tdbp)
m_Catver = (tdbp) ? tdbp->Catver : 0;
m_Rows = 0;
m_Connect = NULL;
m_User = NULL;
m_Pwd = NULL;
m_Updatable = true;
m_Transact = false;
m_Scrollable = (tdbp) ? tdbp->Scrollable : false;
m_First = true;
m_Full = false;
m_UseCnc = false;
m_IDQuoteChar[0] = '"';
m_IDQuoteChar[1] = 0;
//*m_ErrMsg = '\0';
......@@ -1061,7 +1063,7 @@ void ODBConn::OnSetOptions(HSTMT hstmt)
/***********************************************************************/
/* Open: connect to a data source. */
/***********************************************************************/
int ODBConn::Open(PSZ ConnectString, DWORD options)
int ODBConn::Open(PSZ ConnectString, POPARM sop, DWORD options)
{
PGLOBAL& g = m_G;
//ASSERT_VALID(this);
......@@ -1070,6 +1072,11 @@ int ODBConn::Open(PSZ ConnectString, DWORD options)
m_Updatable = !(options & openReadOnly);
m_Connect = ConnectString;
m_User = sop->User;
m_Pwd = sop->Pwd;
m_LoginTimeout = sop->Cto;
m_QueryTimeout = sop->Qto;
m_UseCnc = sop->UseCnc;
// Allocate the HDBC and make connection
try {
......@@ -1078,11 +1085,15 @@ int ODBConn::Open(PSZ ConnectString, DWORD options)
AllocConnect(options);
/*ver = GetStringInfo(SQL_ODBC_VER);*/
if (Connect(options)) {
if (!m_UseCnc) {
if (DriverConnect(options)) {
strcpy(g->Message, MSG(CONNECT_CANCEL));
return 0;
} // endif
} else // Connect using SQLConnect
Connect();
/*ver = GetStringInfo(SQL_DRIVER_ODBC_VER);*/
// Verify support for required functionality and cache info
// VerifyConnect(); Deprecated
......@@ -1163,10 +1174,27 @@ void ODBConn::AllocConnect(DWORD Options)
return;
} // end of AllocConnect
/***********************************************************************/
/* Connect to data source using SQLConnect. */
/***********************************************************************/
void ODBConn::Connect(void)
{
SQLRETURN rc;
SQLSMALLINT ul = (m_User ? SQL_NTS : 0);
SQLSMALLINT pl = (m_Pwd ? SQL_NTS : 0);
rc = SQLConnect(m_hdbc, (SQLCHAR*)m_Connect, SQL_NTS,
(SQLCHAR*)m_User, ul, (SQLCHAR*)m_Pwd, pl);
if (!Check(rc))
ThrowDBX(rc, "SQLConnect");
} // end of Connect
/***********************************************************************/
/* Connect to data source using SQLDriverConnect. */
/***********************************************************************/
bool ODBConn::Connect(DWORD Options)
bool ODBConn::DriverConnect(DWORD Options)
{
RETCODE rc;
SWORD nResult;
......@@ -1213,7 +1241,7 @@ bool ODBConn::Connect(DWORD Options)
// All done
return false;
} // end of Connect
} // end of DriverConnect
void ODBConn::VerifyConnect()
{
......@@ -1712,6 +1740,8 @@ bool ODBConn::BindParam(ODBCCOL *colp)
strcpy(m_G->Message, x->GetErrorMessage(0));
colsize = colp->GetPrecision();
sqlt = GetSQLType(buftype);
dec = IsTypeChar(buftype) ? 0 : colp->GetScale();
nul = SQL_NULLABLE_UNKNOWN;
} // end try/catch
buf = colp->GetBuffer(0);
......@@ -1865,9 +1895,6 @@ PQRYRES ODBConn::GetMetaData(PGLOBAL g, char *dsn, char *src)
RETCODE rc;
HSTMT hstmt;
if (Open(dsn, 10) < 1) // openReadOnly + noOdbcDialog
return NULL;
try {
rc = SQLAllocStmt(m_hdbc, &hstmt);
......
......@@ -119,7 +119,7 @@ class ODBConn : public BLOCK {
noOdbcDialog = 0x0008, // Don't display ODBC Connect dialog
forceOdbcDialog = 0x0010}; // Always display ODBC connect dialog
int Open(PSZ ConnectString, DWORD Options = 0);
int Open(PSZ ConnectString, POPARM sop, DWORD Options = 0);
int Rewind(char *sql, ODBCCOL *tocols);
void Close(void);
PQRYRES AllocateResult(PGLOBAL g);
......@@ -135,8 +135,10 @@ class ODBConn : public BLOCK {
public:
// Operations
void SetLoginTimeout(DWORD sec) {m_LoginTimeout = sec;}
void SetQueryTimeout(DWORD sec) {m_QueryTimeout = sec;}
//void SetLoginTimeout(DWORD sec) {m_LoginTimeout = sec;}
//void SetQueryTimeout(DWORD sec) {m_QueryTimeout = sec;}
//void SetUserName(PSZ user) {m_User = user;}
//void SetUserPwd(PSZ pwd) {m_Pwd = pwd;}
int GetResultSize(char *sql, ODBCCOL *colp);
int ExecDirectSQL(char *sql, ODBCCOL *tocols);
int Fetch(void);
......@@ -155,7 +157,7 @@ class ODBConn : public BLOCK {
// Implementation
public:
// virtual ~ODBConn();
//virtual ~ODBConn();
// ODBC operations
protected:
......@@ -163,7 +165,8 @@ class ODBConn : public BLOCK {
void ThrowDBX(RETCODE rc, PSZ msg, HSTMT hstmt = SQL_NULL_HSTMT);
void ThrowDBX(PSZ msg);
void AllocConnect(DWORD dwOptions);
bool Connect(DWORD Options);
void Connect(void);
bool DriverConnect(DWORD Options);
void VerifyConnect(void);
void GetConnectInfo(void);
void Free(void);
......@@ -185,11 +188,14 @@ class ODBConn : public BLOCK {
DWORD m_RowsetSize;
char m_IDQuoteChar[2];
PSZ m_Connect;
PSZ m_User;
PSZ m_Pwd;
int m_Catver;
int m_Rows;
bool m_Updatable;
bool m_Transact;
bool m_Scrollable;
bool m_UseCnc;
bool m_First;
bool m_Full;
}; // end of ODBConn class definition
......@@ -222,6 +222,7 @@ class DllExport DOSCOL : public COLBLK {
virtual PVBLK GetDval(void) {return Dval;}
// Methods
using COLBLK::Print;
virtual bool VarSize(void);
virtual bool SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check);
virtual void ReadColumn(PGLOBAL g);
......
This diff is collapsed.
......@@ -16,8 +16,6 @@ typedef class JSONDEF *PJDEF;
typedef class TDBJSON *PJTDB;
typedef class JSONCOL *PJCOL;
class TDBJSN;
/***********************************************************************/
/* The JSON tree node. Can be an Object or an Array. */
/***********************************************************************/
......@@ -25,7 +23,9 @@ typedef struct _jnode {
PSZ Key; // The key used for object
OPVAL Op; // Operator used for this node
PVAL CncVal; // To cont value used for OP_CNC
PVAL Valp; // The internal array VALUE
int Rank; // The rank in array
int Nx; // Same row number
} JNODE, *PJNODE;
/***********************************************************************/
......@@ -77,7 +77,7 @@ class TDBJSN : public TDBDOS {
virtual PTDB CopyOne(PTABS t);
virtual PCOL MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n);
virtual PCOL InsertSpecialColumn(PGLOBAL g, PCOL colp);
virtual int RowNumber(PGLOBAL g, BOOL b = FALSE)
virtual int RowNumber(PGLOBAL g, bool b = FALSE)
{return (b) ? N : Fpos + 1;}
// Database routines
......@@ -98,11 +98,11 @@ class TDBJSN : public TDBDOS {
int N; // The current Rownum
int Limit; // Limit of multiple values
int Pretty; // Depends on file structure
bool Strict; // Strict syntax checking
bool NextSame; // Same next row
bool Comma; // Row has final comma
int NextSame; // Same next row
int SameRow; // Same row nb
int Xval; // Index of expandable array
bool Strict; // Strict syntax checking
bool Comma; // Row has final comma
}; // end of class TDBJSN
/* -------------------------- JSONCOL class -------------------------- */
......@@ -130,8 +130,12 @@ class JSONCOL : public DOSCOL {
protected:
bool CheckExpand(PGLOBAL g, int i, PSZ nm, bool b);
bool SetArrayOptions(PGLOBAL g, char *p, int i, PSZ nm);
PJSON GetRow(PGLOBAL g, int mode);
PVAL GetColumnValue(PGLOBAL g, PJSON row, int i);
PVAL ExpandArray(PGLOBAL g, PJAR arp, int n);
PVAL CalculateArray(PGLOBAL g, PJAR arp, int n);
PVAL MakeJson(PGLOBAL g, PJSON jsp);
void SetJsonValue(PGLOBAL g, PVAL vp, PJVAL val, int n);
PJSON GetRow(PGLOBAL g);
// Default constructor not to be used
JSONCOL(void) {}
......@@ -139,12 +143,10 @@ class JSONCOL : public DOSCOL {
// Members
TDBJSN *Tjp; // To the JSN table block
PVAL MulVal; // To value used by multiple column
PJAR Arp; // The intermediate array
char *Jpath; // The json path
JNODE *Nodes ; // The intermediate objects
JNODE *Nodes; // The intermediate objects
int Nod; // The number of intermediate objects
int Ival; // Index of multiple values
int Nx; // The last read sub-row
int Xnod; // Index of multiple values
bool Xpd; // True for expandable column
bool Parsed; // True when parsed
}; // end of class JSONCOL
......
......@@ -1141,20 +1141,17 @@ int TDBMYSQL::WriteDB(PGLOBAL g)
int rc;
uint len = Query->GetLength();
char buf[64];
bool b, oom = false;
bool oom = false;
// Make the Insert command value list
for (PCOL colp = Columns; colp; colp = colp->GetNext()) {
if (!colp->GetValue()->IsNull()) {
if ((b = colp->GetResultType() == TYPE_STRING ||
colp->GetResultType() == TYPE_DATE))
oom |= Query->Append('\'');
if (colp->GetResultType() == TYPE_STRING ||
colp->GetResultType() == TYPE_DATE)
oom |= Query->Append_quoted(colp->GetValue()->GetCharString(buf));
else
oom |= Query->Append(colp->GetValue()->GetCharString(buf));
if (b)
oom |= Query->Append('\'');
} else
oom |= Query->Append("NULL");
......
......@@ -355,7 +355,7 @@ bool TDBOCCUR::MakeColumnList(PGLOBAL g)
for (colp = Columns; colp; colp = colp->GetNext())
if (colp->GetAmType() == TYPE_AM_PRX)
if (((PPRXCOL)colp)->Init(g))
if (((PPRXCOL)colp)->Init(g, NULL))
return true;
Col = (PCOL*)PlugSubAlloc(g, NULL, Mult * sizeof(PCOL));
......
This diff is collapsed.
......@@ -50,6 +50,8 @@ class DllExport ODBCDEF : public TABDEF { /* Logical table description */
PSZ Connect; /* ODBC connection string */
PSZ Tabname; /* External table name */
PSZ Tabschema; /* External table schema */
PSZ Username; /* User connect name */
PSZ Password; /* Password connect info */
PSZ Tabcat; /* External table catalog */
PSZ Srcdef; /* The source table SQL definition */
PSZ Qchar; /* Identifier quoting character */
......@@ -65,6 +67,7 @@ class DllExport ODBCDEF : public TABDEF { /* Logical table description */
bool Scrollable; /* Use scrollable cursor */
bool Memory; /* Put result set in memory */
bool Xsrc; /* Execution type */
bool UseCnc; /* Use SQLConnect (!SQLDriverConnect) */
}; // end of ODBCDEF
#if !defined(NODBC)
......@@ -124,9 +127,12 @@ class TDBODBC : public TDBASE {
// Members
ODBConn *Ocp; // Points to an ODBC connection class
ODBCCOL *Cnp; // Points to count(*) column
ODBCPARM Ops; // Additional parameters
char *Connect; // Points to connection string
char *TableName; // Points to ODBC table name
char *Schema; // Points to ODBC table Schema
char *User; // User connect info
char *Pwd; // Password connect info
char *Catalog; // Points to ODBC table Catalog
char *Srcdef; // The source table SQL definition
char *Query; // Points to SQL statement
......@@ -151,6 +157,7 @@ class TDBODBC : public TDBASE {
int Nparm; // The number of statement parameters
int Memory; // 0: No 1: Alloc 2: Put 3: Get
bool Scrollable; // Use scrollable cursor
bool UseCnc; // Use SQLConnect (!SQLDriverConnect)
PQRYRES Qrp; // Points to storage result
}; // end of class TDBODBC
......@@ -316,8 +323,7 @@ class TDBOTB : public TDBDRV {
char *Dsn; // Points to connection string
char *Schema; // Points to schema name or NULL
char *Tab; // Points to ODBC table name or pattern
int Cto; // Connect timeout
int Qto; // Query timeout
ODBCPARM Ops; // Additional parameters
}; // end of class TDBOTB
/***********************************************************************/
......
......@@ -558,7 +558,7 @@ bool TDBPIVOT::MakePivotColumns(PGLOBAL g)
// Check and initialize the subtable columns
for (PCOL cp = Columns; cp; cp = cp->GetNext())
if (cp->GetAmType() == TYPE_AM_SRC) {
if (((PSRCCOL)cp)->Init(g))
if (((PSRCCOL)cp)->Init(g, NULL))
return TRUE;
} else if (cp->GetAmType() == TYPE_AM_FNC)
......@@ -874,9 +874,9 @@ SRCCOL::SRCCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int n)
/***********************************************************************/
/* Initialize the column as pointing to the source column. */
/***********************************************************************/
bool SRCCOL::Init(PGLOBAL g)
bool SRCCOL::Init(PGLOBAL g, PTDBASE tp)
{
if (PRXCOL::Init(g))
if (PRXCOL::Init(g, tp))
return true;
AddStatus(BUF_READ); // All is done here
......
......@@ -180,9 +180,10 @@ class SRCCOL : public PRXCOL {
virtual int GetAmType(void) {return TYPE_AM_SRC;}
// Methods
using PRXCOL::Init;
virtual void Reset(void) {}
void SetColumn(void);
bool Init(PGLOBAL g);
virtual bool Init(PGLOBAL g, PTDBASE tp);
bool CompareLast(void);
protected:
......
......@@ -266,7 +266,7 @@ bool TDBTBL::InitTableList(PGLOBAL g)
// Real initialization will be done later.
for (colp = Columns; colp; colp = colp->GetNext())
if (!colp->IsSpecial())
if (((PPRXCOL)colp)->Init(g) && !Accept)
if (((PPRXCOL)colp)->Init(g, NULL) && !Accept)
return TRUE;
if (Tablist)
......@@ -352,7 +352,9 @@ bool TDBTBL::TestFil(PGLOBAL g, PCFIL filp, PTABLE tabp)
/***********************************************************************/
int TDBTBL::Cardinality(PGLOBAL g)
{
if (Cardinal < 0) {
if (!g)
return 0; // Cannot make the table list
else if (Cardinal < 0) {
int tsz;
if (!Tablist && InitTableList(g))
......@@ -468,7 +470,7 @@ bool TDBTBL::OpenDB(PGLOBAL g)
for (PCOL cp = Columns; cp; cp = cp->GetNext())
if (cp->GetAmType() == TYPE_AM_TABID)
cp->COLBLK::Reset();
else if (((PPRXCOL)cp)->Init(g) && !Accept)
else if (((PPRXCOL)cp)->Init(g, NULL) && !Accept)
return TRUE;
if (trace)
......@@ -523,7 +525,7 @@ int TDBTBL::ReadDB(PGLOBAL g)
if (cp->GetAmType() == TYPE_AM_TABID ||
cp->GetAmType() == TYPE_AM_SRVID)
cp->COLBLK::Reset();
else if (((PPRXCOL)cp)->Init(g) && !Accept)
else if (((PPRXCOL)cp)->Init(g, NULL) && !Accept)
return RC_FX;
if (trace)
......@@ -716,7 +718,7 @@ bool TDBTBM::OpenDB(PGLOBAL g)
for (PCOL cp = Columns; cp; cp = cp->GetNext())
if (cp->GetAmType() == TYPE_AM_TABID)
cp->COLBLK::Reset();
else if (((PPRXCOL)cp)->Init(g) && !Accept)
else if (((PPRXCOL)cp)->Init(g, NULL) && !Accept)
return TRUE;
if (trace)
......@@ -807,7 +809,7 @@ int TDBTBM::ReadNextRemote(PGLOBAL g)
for (PCOL cp = Columns; cp; cp = cp->GetNext())
if (cp->GetAmType() == TYPE_AM_TABID)
cp->COLBLK::Reset();
else if (((PPRXCOL)cp)->Init(g) && !Accept)
else if (((PPRXCOL)cp)->Init(g, NULL) && !Accept)
return RC_FX;
if (trace)
......
......@@ -54,7 +54,8 @@
#include "tabutil.h"
#include "ha_connect.h"
extern "C" int zconv;
//extern "C" int zconv;
int GetConvSize(void);
/************************************************************************/
/* Used by MYSQL tables to get MySQL parameters from the calling proxy */
......@@ -132,6 +133,7 @@ PQRYRES TabColumns(PGLOBAL g, THD *thd, const char *db,
char *fld, *colname, *chset, *fmt, v;
int i, n, ncol = sizeof(buftyp) / sizeof(int);
int prec, len, type, scale;
int zconv = GetConvSize();
bool mysql;
TABLE_SHARE *s = NULL;
Field* *field;
......@@ -668,6 +670,22 @@ PRXCOL::PRXCOL(PRXCOL *col1, PTDB tdbp) : COLBLK(col1, tdbp)
Colnum = col1->Colnum;
} // end of PRXCOL copy constructor
/***********************************************************************/
/* Convert an UTF-8 name to latin characters. */
/***********************************************************************/
char *PRXCOL::Decode(PGLOBAL g, const char *cnm)
{
char *buf= (char*)PlugSubAlloc(g, NULL, strlen(cnm) + 1);
uint dummy_errors;
uint32 len= copy_and_convert(buf, strlen(cnm) + 1,
&my_charset_latin1,
cnm, strlen(cnm),
&my_charset_utf8_general_ci,
&dummy_errors);
buf[len]= '\0';
return buf;
} // end of Decode
/***********************************************************************/
/* PRXCOL initialization routine. */
/* Look for the matching column in the object table. */
......@@ -683,6 +701,9 @@ bool PRXCOL::Init(PGLOBAL g, PTDBASE tp)
if (Colp) {
MODE mode = To_Tdb->GetMode();
// Needed for MYSQL subtables
((XCOLBLK*)Colp)->Name = Decode(g, Colp->GetName());
// May not have been done elsewhere
Colp->InitValue(g);
To_Val = Colp->GetValue();
......
......@@ -108,15 +108,18 @@ class DllExport PRXCOL : public COLBLK {
virtual int GetAmType(void) {return TYPE_AM_PRX;}
// Methods
using COLBLK::Init;
virtual void Reset(void);
virtual bool IsSpecial(void) {return Pseudo;}
virtual bool SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check)
{return false;}
virtual void ReadColumn(PGLOBAL g);
virtual void WriteColumn(PGLOBAL g);
virtual bool Init(PGLOBAL g, PTDBASE tp = NULL);
virtual bool Init(PGLOBAL g, PTDBASE tp);
protected:
char *Decode(PGLOBAL g, const char *cnm);
// Default constructor not to be used
PRXCOL(void) {}
......@@ -144,4 +147,8 @@ class TDBTBC : public TDBCAT {
PSZ Tab; // Table name
}; // end of class TDBMCL
class XCOLBLK : public COLBLK {
friend class PRXCOL;
}; // end of class XCOLBLK
#endif // TABUTIL
......@@ -183,7 +183,7 @@ bool TDBXCL::OpenDB(PGLOBAL g)
/*********************************************************************/
for (PCOL cp = Columns; cp; cp = cp->GetNext())
if (!cp->IsSpecial())
if (((PPRXCOL)cp)->Init(g))
if (((PPRXCOL)cp)->Init(g, NULL))
return TRUE;
/*********************************************************************/
......
......@@ -88,6 +88,7 @@ class XCLCOL : public PRXCOL {
XCLCOL(PGLOBAL g, PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i);
// Methods
using PRXCOL::Init;
virtual void Reset(void) {} // Evaluated only by TDBXCL
virtual void ReadColumn(PGLOBAL g);
virtual bool Init(PGLOBAL g, PTDBASE tp = NULL);
......
......@@ -163,6 +163,7 @@ class TYPBLK : public VALBLK {
virtual void Reset(int n) {Typp[n] = 0;}
// Methods
using VALBLK::SetValue;
virtual void SetValue(PSZ sp, int n);
virtual void SetValue(char *sp, uint len, int n);
virtual void SetValue(short sval, int n)
......@@ -233,6 +234,7 @@ class CHRBLK : public VALBLK {
virtual bool IsCi(void) {return Ci;}
// Methods
using VALBLK::SetValue;
virtual void SetValue(PSZ sp, int n);
virtual void SetValue(char *sp, uint len, int n);
virtual void SetValue(PVAL valp, int n);
......@@ -286,6 +288,7 @@ class STRBLK : public VALBLK {
virtual void Reset(int n) {Strp[n] = NULL;}
// Methods
using VALBLK::SetValue;
virtual void SetValue(PSZ sp, int n);
virtual void SetValue(char *sp, uint len, int n);
virtual void SetValue(PVAL valp, int n);
......@@ -322,6 +325,7 @@ class DATBLK : public TYPBLK<int> {
virtual char *GetCharString(char *p, int n);
// Methods
using TYPBLK<int>::SetValue;
virtual void SetValue(PSZ sp, int n);
protected:
......@@ -345,6 +349,8 @@ class PTRBLK : public STRBLK {
// Implementation
// Methods
using STRBLK::SetValue;
using STRBLK::CompVal;
virtual void SetValue(PSZ p, int n) {Strp[n] = p;}
virtual int CompVal(int i1, int i2);
......
......@@ -436,6 +436,9 @@ PVAL AllocateValue(PGLOBAL g, PVAL valp, int newtype, int uns)
bool un = (uns < 0) ? false : (uns > 0) ? true : valp->IsUnsigned();
PVAL vp;
if (!valp)
return NULL;
if (newtype == TYPE_VOID) // Means allocate a value of the same type
newtype = valp->GetType();
......@@ -443,8 +446,8 @@ PVAL AllocateValue(PGLOBAL g, PVAL valp, int newtype, int uns)
case TYPE_STRING:
p = (PSZ)PlugSubAlloc(g, NULL, 1 + valp->GetValLen());
if ((sp = valp->GetCharString(p)) != p)
strcpy (p, sp);
if ((sp = valp->GetCharString(p)) != p && sp)
strcpy(p, sp);
vp = new(g) TYPVAL<PSZ>(g, p, valp->GetValLen(), valp->GetValPrec());
break;
......@@ -1216,12 +1219,12 @@ TYPVAL<PSZ>::TYPVAL(PSZ s) : VALUE(TYPE_STRING)
TYPVAL<PSZ>::TYPVAL(PGLOBAL g, PSZ s, int n, int c)
: VALUE(TYPE_STRING)
{
Len = (g) ? n : strlen(s);
Len = (g) ? n : (s) ? strlen(s) : 0;
if (!s) {
if (g) {
if ((Strp = (char *)PlgDBSubAlloc(g, NULL, Len + 1)))
Strp[Len] = '\0';
memset(Strp, 0, Len + 1);
else
Len = 0;
......
......@@ -391,6 +391,7 @@ class DllExport XHUGE : public XLOAD {
XHUGE(void) : XLOAD() {}
// Methods
using XLOAD::Close;
virtual bool Open(PGLOBAL g, char *filename, int id, MODE mode);
virtual bool Seek(PGLOBAL g, int low, int high, int origin);
virtual bool Read(PGLOBAL g, void *buf, int n, int size);
......
......@@ -346,6 +346,31 @@ bool STRING::Append(char c)
return false;
} // end of Append
/***********************************************************************/
/* Append a quoted PSZ to a STRING. */
/***********************************************************************/
bool STRING::Append_quoted(PSZ s)
{
bool b = Append('\'');
if (s) for (char *p = s; !b && *p; p++)
switch (*p) {
case '\'':
case '\\':
case '\t':
case '\n':
case '\r':
case '\b':
case '\f': b |= Append('\\');
// passthru
default:
b |= Append(*p);
break;
} // endswitch *p
return (b |= Append('\''));
} // end of Append_quoted
/***********************************************************************/
/* Resize to given length but only when last suballocated. */
/* New size should be greater than string length. */
......
......@@ -138,6 +138,7 @@ class DllExport STRING : public BLOCK {
bool Append(STRING &str);
bool Append(char c);
bool Resize(uint n);
bool Append_quoted(PSZ s);
inline void Trim(void) {(void)Resize(Length + 1);}
inline void Chop(void) {if (Length) Strp[--Length] = 0;}
inline void RepLast(char c) {if (Length) Strp[Length-1] = c;}
......
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