Commit 81252031 authored by Olivier Bertrand's avatar Olivier Bertrand

- Commit merged files

modified:
  storage/connect/CMakeLists.txt
  storage/connect/connect.h
  storage/connect/global.h
  storage/connect/ha_connect.cc
  storage/connect/ha_connect.h
  storage/connect/myconn.cpp
  storage/connect/myconn.h
  storage/connect/mysql-test/connect/r/pivot.result
  storage/connect/mysql-test/connect/suite.pm
  storage/connect/mysql-test/connect/t/pivot.test
  storage/connect/myutil.cpp
  storage/connect/osutil.c
  storage/connect/plgdbsem.h
  storage/connect/plugutil.c
  storage/connect/tabmysql.cpp
  storage/connect/tabpivot.cpp
  storage/connect/tabutil.cpp
  storage/connect/user_connect.cc
  storage/connect/valblk.cpp
  storage/connect/valblk.h
  storage/connect/value.cpp
  storage/connect/value.h
  storage/connect/xindex.cpp
  storage/connect/xindex.h
parents cc7a08c9 b43e82dc
......@@ -123,7 +123,7 @@ IF(WIN32)
# /MP option of the Microsoft compiler does not work well with COM #import
string(REPLACE "/MP" "" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}")
string(REPLACE "/MP" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
OPTION(CONNECT_WITH_MSXML "Compile CONNECT storage engine with MSXML support" ON)
IF(CONNECT_WITH_MSXML)
find_library(MSXML_LIBRARY
......@@ -264,6 +264,17 @@ int main() {
ENDIF(UNIX)
ENDIF(CONNECT_WITH_ODBC)
#
# XMAP
#
OPTION(CONNECT_WITH_XMAP "Compile CONNECT storage engine with index file mapping support" ON)
IF(CONNECT_WITH_XMAP)
add_definitions(-DXMAP)
ENDIF(CONNECT_WITH_XMAP)
#
# Plugin definition
#
......@@ -271,6 +282,7 @@ ENDIF(CONNECT_WITH_ODBC)
MYSQL_ADD_PLUGIN(connect ${CONNECT_SOURCES}
STORAGE_ENGINE
COMPONENT connect-engine
RECOMPILE_FOR_EMBEDDED
LINK_LIBRARIES ${ZLIB_LIBRARY} ${XML_LIBRARY} ${ICONV_LIBRARY}
${ODBC_LIBRARY} ${IPHLPAPI_LIBRARY})
......@@ -36,8 +36,7 @@ bool CntRewindTable(PGLOBAL g, PTDB tdbp);
int CntCloseTable(PGLOBAL g, PTDB tdbp);
int CntIndexInit(PGLOBAL g, PTDB tdbp, int id);
RCODE CntReadNext(PGLOBAL g, PTDB tdbp);
RCODE CntIndexRead(PGLOBAL g, PTDB, OPVAL op, const void *k, int n,
bool mrr = false);
RCODE CntIndexRead(PGLOBAL g, PTDB, OPVAL op, const void *k, int n, bool mrr);
RCODE CntWriteRow(PGLOBAL g, PTDB tdbp);
RCODE CntUpdateRow(PGLOBAL g, PTDB tdbp);
RCODE CntDeleteRow(PGLOBAL g, PTDB tdbp, bool all);
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -47,9 +47,12 @@
#include "myconn.h"
extern "C" int trace;
extern "C" int zconv;
extern MYSQL_PLUGIN_IMPORT uint mysqld_port;
extern MYSQL_PLUGIN_IMPORT char *mysqld_unix_port;
DllExport void PushWarning(PGLOBAL, THD*, int level = 1);
// Returns the current used port
uint GetDefaultPort(void)
{
......@@ -61,7 +64,7 @@ uint GetDefaultPort(void)
/* of a MySQL table or view. */
/* info = TRUE to get catalog column informations. */
/************************************************************************/
PQRYRES MyColumns(PGLOBAL g, const char *host, const char *db,
PQRYRES MyColumns(PGLOBAL g, THD *thd, const char *host, const char *db,
const char *user, const char *pwd,
const char *table, const char *colpat,
int port, bool info)
......@@ -75,7 +78,7 @@ PQRYRES MyColumns(PGLOBAL g, const char *host, const char *db,
FLD_REM, FLD_NO, FLD_DEFAULT, FLD_EXTRA,
FLD_CHARSET};
unsigned int length[] = {0, 4, 16, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0};
char *fld, *fmt, v, cmd[128], uns[16], zero[16];
char *fld, *colname, *chset, *fmt, v, cmd[128], uns[16], zero[16];
int i, n, nf, ncol = sizeof(buftyp) / sizeof(int);
int len, type, prec, rc, k = 0;
PQRYRES qrp;
......@@ -144,23 +147,24 @@ PQRYRES MyColumns(PGLOBAL g, const char *host, const char *db,
/**********************************************************************/
/* Now get the results into blocks. */
/**********************************************************************/
for (i = 0; i < n; i++) {
if ((rc = myc.Fetch(g, -1) == RC_FX)) {
for (i = 0; i < n; /*i++*/) {
if ((rc = myc.Fetch(g, -1)) == RC_FX) {
myc.Close();
return NULL;
} else if (rc == RC_NF)
} else if (rc == RC_EF)
break;
// Get column name
fld = myc.GetCharField(0);
colname = myc.GetCharField(0);
crp = qrp->Colresp; // Column_Name
crp->Kdata->SetValue(fld, i);
crp->Kdata->SetValue(colname, i);
// Get type, type name, precision, unsigned and zerofill
chset = myc.GetCharField(2);
fld = myc.GetCharField(1);
prec = 0;
len = 0;
v = 0;
v = (chset && !strcmp(chset, "binary")) ? 'B' : 0;
*uns = 0;
*zero = 0;
......@@ -181,11 +185,28 @@ PQRYRES MyColumns(PGLOBAL g, const char *host, const char *db,
} // endswitch nf
if ((type = MYSQLtoPLG(cmd, &v)) == TYPE_ERROR) {
sprintf(g->Message, "Unsupported column type %s", cmd);
if (v == 'K') {
// Skip this column
sprintf(g->Message, "Column %s skipped (unsupported type %s)",
colname, cmd);
PushWarning(g, thd);
continue;
} // endif v
sprintf(g->Message, "Column %s unsupported type %s", colname, cmd);
myc.Close();
return NULL;
} else if (type == TYPE_STRING)
len = min(len, 4096);
} else if (type == TYPE_STRING) {
if (v == 'X') {
len = zconv;
sprintf(g->Message, "Column %s converted to varchar(%d)",
colname, len);
PushWarning(g, thd);
v = 'V';
} else
len = min(len, 4096);
} // endif type
qrp->Nblin++;
crp = crp->Next; // Data_Type
......@@ -241,8 +262,10 @@ PQRYRES MyColumns(PGLOBAL g, const char *host, const char *db,
crp->Kdata->SetValue(fld, i);
crp = crp->Next; // New (charset)
fld = myc.GetCharField(2);
fld = chset;
crp->Kdata->SetValue(fld, i);
i++; // Can be skipped
} // endfor i
#if 0
......@@ -284,7 +307,7 @@ PQRYRES SrcColumns(PGLOBAL g, const char *host, const char *db,
if (!port)
port = mysqld_port;
if (!strnicmp(srcdef, "select ", 7)) {
if (!strnicmp(srcdef, "select ", 7)) {
query = (char *)PlugSubAlloc(g, NULL, strlen(srcdef) + 9);
strcat(strcpy(query, srcdef), " LIMIT 0");
} else
......@@ -608,7 +631,7 @@ if (w)
/***********************************************************************/
void MYSQLC::DataSeek(my_ulonglong row)
{
MYSQL_ROWS *tmp=0;
MYSQL_ROWS *tmp=0;
//DBUG_PRINT("info",("mysql_data_seek(%ld)",(long) row));
if (m_Res->data)
......@@ -783,7 +806,7 @@ PQRYRES MYSQLC::GetResult(PGLOBAL g, bool pdb)
else {
if (!*row && crp->Nulls)
crp->Nulls[n] = '*'; // Null value
crp->Kdata->Reset(n);
} // endelse *row
}
......@@ -880,7 +903,7 @@ void MYSQLC::DiscardResults(void)
while (!mysql_next_result(m_DB)) {
res = mysql_store_result(m_DB);
mysql_free_result(res);
} // endwhile next result
} // endwhile next result
} // end of DiscardResults
#endif // 0
......@@ -34,7 +34,7 @@ typedef class MYSQLC *PMYC;
/***********************************************************************/
/* Prototypes of info functions. */
/***********************************************************************/
PQRYRES MyColumns(PGLOBAL g, const char *host, const char *db,
PQRYRES MyColumns(PGLOBAL g, THD *thd, const char *host, const char *db,
const char *user, const char *pwd,
const char *table, const char *colpat,
int port, bool info);
......
......@@ -229,7 +229,7 @@ DROP TABLE pets;
#
CREATE TABLE fruit (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(32) DEFAULT NULL,
`name` varchar(32) NOT NULL,
`cnt` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=6 DEFAULT CHARSET=latin1;
......
......@@ -5,6 +5,11 @@ package My::Suite::Connect;
return "No CONNECT engine" unless $ENV{HA_CONNECT_SO} or
$::mysqld_variables{'connect'} eq "ON";
# RECOMPILE_FOR_EMBEDDED also means that a plugin
# cannot be dynamically loaded into embedded
return "Not run for embedded server" if $::opt_embedded_server and
$ENV{HA_CONNECT_SO};
sub is_default { 1 }
bless { };
......
-- source include/not_embedded.inc
let $MYSQLD_DATADIR= `select @@datadir`;
let $PORT= `select @@port`;
--copy_file $MTR_SUITE_DIR/std_data/expenses.txt $MYSQLD_DATADIR/test/expenses.txt
--echo #
--echo # Testing the PIVOT table type
--echo #
CREATE TABLE expenses (
Who CHAR(10) NOT NULL,
Week INT(2) NOT NULL,
What CHAR(12) NOT NULL,
Amount DOUBLE(8,2))
ENGINE=CONNECT TABLE_TYPE=FIX FILE_NAME='expenses.txt' ENDING=2;
SELECT * FROM expenses;
--echo #
--echo # Pivoting from What
--echo #
CREATE TABLE pivex (
Who CHAR(10) NOT NULL,
Week INT(2) NOT NULL,
Beer DOUBLE(8,2) FLAG=1,
Car DOUBLE(8,2) FLAG=1,
Food DOUBLE(8,2) FLAG=1)
ENGINE=CONNECT TABLE_TYPE=PIVOT TABNAME=expenses;
--replace_result $PORT PORT
--eval ALTER TABLE pivex OPTION_LIST='port=$PORT'
SELECT * FROM pivex;
--echo #
--echo # Restricting the columns in a Pivot Table
--echo #
ALTER TABLE pivex DROP COLUMN week;
SELECT * FROM pivex;
--echo #
--echo # Using a source definition
--echo #
DROP TABLE pivex;
CREATE TABLE pivex (
Who CHAR(10) NOT NULL,
Week INT(2) NOT NULL,
Beer DOUBLE(8,2) FLAG=1,
Car DOUBLE(8,2) FLAG=1,
Food DOUBLE(8,2) FLAG=1)
ENGINE=CONNECT TABLE_TYPE=PIVOT
SRCDEF='select who, week, what, sum(amount) as amount from expenses where week in (4,5) group by who, week, what';
--replace_result $PORT PORT
--eval ALTER TABLE pivex OPTION_LIST='PivotCol=what,FncCol=amount,port=$PORT'
SELECT * FROM pivex;
--echo #
--echo # Pivoting from Week
--echo #
DROP TABLE pivex;
CREATE TABLE pivex (
Who CHAR(10) NOT NULL,
What CHAR(12) NOT NULL,
`3` DOUBLE(8,2) FLAG=1,
`4` DOUBLE(8,2) FLAG=1,
`5` DOUBLE(8,2) FLAG=1)
ENGINE=CONNECT TABLE_TYPE=PIVOT TABNAME=expenses;
--replace_result $PORT PORT
--eval ALTER TABLE pivex OPTION_LIST='PivotCol=Week,port=$PORT'
SELECT * FROM pivex;
--echo #
--echo # Using scalar functions and expresssions
--echo #
DROP TABLE pivex;
CREATE TABLE pivex (
Who CHAR(10) NOT NULL,
What CHAR(12) NOT NULL,
First DOUBLE(8,2) FLAG=1,
Middle DOUBLE(8,2) FLAG=1,
Last DOUBLE(8,2) FLAG=1)
ENGINE=CONNECT TABLE_TYPE=PIVOT
SRCDEF='select who, what, case when week=3 then ''First'' when week=5 then ''Last'' else ''Middle'' end as wk, sum(amount) * 6.56 as amnt from expenses group by who, what, wk';
--replace_result $PORT PORT
--eval ALTER TABLE pivex OPTION_LIST='PivotCol=wk,FncCol=amnt,port=$PORT'
SELECT * FROM pivex;
DROP TABLE pivex;
DROP TABLE expenses;
--echo #
--echo # Make the PETS table
--echo #
CREATE TABLE pets (
Name VARCHAR(12) NOT NULL,
Race CHAR(6) NOT NULL,
Number INT NOT NULL) ENGINE=MYISAM;
INSERT INTO pets VALUES('John','dog',2);
INSERT INTO pets VALUES('Bill','cat',1);
INSERT INTO pets VALUES('Mary','dog',1);
INSERT INTO pets VALUES('Mary','cat',1);
INSERT INTO pets VALUES('Lisbeth','rabbit',2);
INSERT INTO pets VALUES('Kevin','cat',2);
INSERT INTO pets VALUES('Kevin','bird',6);
INSERT INTO pets VALUES('Donald','dog',1);
INSERT INTO pets VALUES('Donald','fish',3);
SELECT * FROM pets;
--echo #
--echo # Pivot the PETS table
--echo #
CREATE TABLE pivet (
name VARCHAR(12) NOT NULL,
dog INT NOT NULL DEFAULT 0 FLAG=1,
cat INT NOT NULL DEFAULT 0 FLAG=1,
rabbit INT NOT NULL DEFAULT 0 FLAG=1,
bird INT NOT NULL DEFAULT 0 FLAG=1,
fish INT NOT NULL DEFAULT 0 FLAG=1)
ENGINE=CONNECT TABLE_TYPE=PIVOT TABNAME=pets OPTION_LIST='PivotCol=race,groupby=1';
SELECT * FROM pivet;
DROP TABLE pivet;
--echo #
--echo # Testing the "data" column list
--echo #
CREATE TABLE pivet (
name VARCHAR(12) NOT NULL,
dog INT NOT NULL DEFAULT 0 FLAG=1,
cat INT NOT NULL DEFAULT 0 FLAG=1)
ENGINE=CONNECT TABLE_TYPE=PIVOT TABNAME=pets OPTION_LIST='PivotCol=race,groupby=1';
--error ER_GET_ERRMSG
SELECT * FROM pivet;
ALTER TABLE pivet OPTION_LIST='PivotCol=race,groupby=1,accept=1';
SELECT * FROM pivet;
DROP TABLE pivet;
--echo #
--echo # Adding a "dump" column
--echo #
CREATE TABLE pivet (
name VARCHAR(12) NOT NULL,
dog INT NOT NULL DEFAULT 0 FLAG=1,
cat INT NOT NULL DEFAULT 0 FLAG=1,
other INT NOT NULL DEFAULT 0 FLAG=2)
ENGINE=CONNECT TABLE_TYPE=PIVOT TABNAME=pets OPTION_LIST='PivotCol=race,groupby=1';
SELECT * FROM pivet;
DROP TABLE pivet;
DROP TABLE pets;
--echo #
--echo # MDEV-5734
--echo #
CREATE TABLE fruit (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(32) DEFAULT NULL,
`cnt` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=6 DEFAULT CHARSET=latin1;
INSERT INTO fruit VALUES (1,'apple',1),(2,'banana',1),(3,'apple',2),(4,'cherry',4),(5,'durazno',2);
SELECT * FROM fruit;
CREATE TABLE fruit_pivot ENGINE=CONNECT TABLE_TYPE=pivot TABNAME=fruit;
SELECT * FROM fruit_pivot;
DROP TABLE fruit_pivot;
DROP TABLE fruit;
--remove_file $MYSQLD_DATADIR/test/expenses.txt
-- source include/not_embedded.inc
let $MYSQLD_DATADIR= `select @@datadir`;
let $PORT= `select @@port`;
--copy_file $MTR_SUITE_DIR/std_data/expenses.txt $MYSQLD_DATADIR/test/expenses.txt
--echo #
--echo # Testing the PIVOT table type
--echo #
CREATE TABLE expenses (
Who CHAR(10) NOT NULL,
Week INT(2) NOT NULL,
What CHAR(12) NOT NULL,
Amount DOUBLE(8,2))
ENGINE=CONNECT TABLE_TYPE=FIX FILE_NAME='expenses.txt' ENDING=2;
SELECT * FROM expenses;
--echo #
--echo # Pivoting from What
--echo #
CREATE TABLE pivex (
Who CHAR(10) NOT NULL,
Week INT(2) NOT NULL,
Beer DOUBLE(8,2) FLAG=1,
Car DOUBLE(8,2) FLAG=1,
Food DOUBLE(8,2) FLAG=1)
ENGINE=CONNECT TABLE_TYPE=PIVOT TABNAME=expenses;
--replace_result $PORT PORT
--eval ALTER TABLE pivex OPTION_LIST='port=$PORT'
SELECT * FROM pivex;
--echo #
--echo # Restricting the columns in a Pivot Table
--echo #
ALTER TABLE pivex DROP COLUMN week;
SELECT * FROM pivex;
--echo #
--echo # Using a source definition
--echo #
DROP TABLE pivex;
CREATE TABLE pivex (
Who CHAR(10) NOT NULL,
Week INT(2) NOT NULL,
Beer DOUBLE(8,2) FLAG=1,
Car DOUBLE(8,2) FLAG=1,
Food DOUBLE(8,2) FLAG=1)
ENGINE=CONNECT TABLE_TYPE=PIVOT
SRCDEF='select who, week, what, sum(amount) as amount from expenses where week in (4,5) group by who, week, what';
--replace_result $PORT PORT
--eval ALTER TABLE pivex OPTION_LIST='PivotCol=what,FncCol=amount,port=$PORT'
SELECT * FROM pivex;
--echo #
--echo # Pivoting from Week
--echo #
DROP TABLE pivex;
CREATE TABLE pivex (
Who CHAR(10) NOT NULL,
What CHAR(12) NOT NULL,
`3` DOUBLE(8,2) FLAG=1,
`4` DOUBLE(8,2) FLAG=1,
`5` DOUBLE(8,2) FLAG=1)
ENGINE=CONNECT TABLE_TYPE=PIVOT TABNAME=expenses;
--replace_result $PORT PORT
--eval ALTER TABLE pivex OPTION_LIST='PivotCol=Week,port=$PORT'
SELECT * FROM pivex;
--echo #
--echo # Using scalar functions and expresssions
--echo #
DROP TABLE pivex;
CREATE TABLE pivex (
Who CHAR(10) NOT NULL,
What CHAR(12) NOT NULL,
First DOUBLE(8,2) FLAG=1,
Middle DOUBLE(8,2) FLAG=1,
Last DOUBLE(8,2) FLAG=1)
ENGINE=CONNECT TABLE_TYPE=PIVOT
SRCDEF='select who, what, case when week=3 then ''First'' when week=5 then ''Last'' else ''Middle'' end as wk, sum(amount) * 6.56 as amnt from expenses group by who, what, wk';
--replace_result $PORT PORT
--eval ALTER TABLE pivex OPTION_LIST='PivotCol=wk,FncCol=amnt,port=$PORT'
SELECT * FROM pivex;
DROP TABLE pivex;
DROP TABLE expenses;
--echo #
--echo # Make the PETS table
--echo #
CREATE TABLE pets (
Name VARCHAR(12) NOT NULL,
Race CHAR(6) NOT NULL,
Number INT NOT NULL) ENGINE=MYISAM;
INSERT INTO pets VALUES('John','dog',2);
INSERT INTO pets VALUES('Bill','cat',1);
INSERT INTO pets VALUES('Mary','dog',1);
INSERT INTO pets VALUES('Mary','cat',1);
INSERT INTO pets VALUES('Lisbeth','rabbit',2);
INSERT INTO pets VALUES('Kevin','cat',2);
INSERT INTO pets VALUES('Kevin','bird',6);
INSERT INTO pets VALUES('Donald','dog',1);
INSERT INTO pets VALUES('Donald','fish',3);
SELECT * FROM pets;
--echo #
--echo # Pivot the PETS table
--echo #
CREATE TABLE pivet (
name VARCHAR(12) NOT NULL,
dog INT NOT NULL DEFAULT 0 FLAG=1,
cat INT NOT NULL DEFAULT 0 FLAG=1,
rabbit INT NOT NULL DEFAULT 0 FLAG=1,
bird INT NOT NULL DEFAULT 0 FLAG=1,
fish INT NOT NULL DEFAULT 0 FLAG=1)
ENGINE=CONNECT TABLE_TYPE=PIVOT TABNAME=pets OPTION_LIST='PivotCol=race,groupby=1';
SELECT * FROM pivet;
DROP TABLE pivet;
--echo #
--echo # Testing the "data" column list
--echo #
CREATE TABLE pivet (
name VARCHAR(12) NOT NULL,
dog INT NOT NULL DEFAULT 0 FLAG=1,
cat INT NOT NULL DEFAULT 0 FLAG=1)
ENGINE=CONNECT TABLE_TYPE=PIVOT TABNAME=pets OPTION_LIST='PivotCol=race,groupby=1';
--error ER_GET_ERRMSG
SELECT * FROM pivet;
ALTER TABLE pivet OPTION_LIST='PivotCol=race,groupby=1,accept=1';
SELECT * FROM pivet;
DROP TABLE pivet;
--echo #
--echo # Adding a "dump" column
--echo #
CREATE TABLE pivet (
name VARCHAR(12) NOT NULL,
dog INT NOT NULL DEFAULT 0 FLAG=1,
cat INT NOT NULL DEFAULT 0 FLAG=1,
other INT NOT NULL DEFAULT 0 FLAG=2)
ENGINE=CONNECT TABLE_TYPE=PIVOT TABNAME=pets OPTION_LIST='PivotCol=race,groupby=1';
SELECT * FROM pivet;
DROP TABLE pivet;
DROP TABLE pets;
--echo #
--echo # MDEV-5734
--echo #
CREATE TABLE fruit (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(32) NOT NULL,
`cnt` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=6 DEFAULT CHARSET=latin1;
INSERT INTO fruit VALUES (1,'apple',1),(2,'banana',1),(3,'apple',2),(4,'cherry',4),(5,'durazno',2);
SELECT * FROM fruit;
CREATE TABLE fruit_pivot ENGINE=CONNECT TABLE_TYPE=pivot TABNAME=fruit;
SELECT * FROM fruit_pivot;
DROP TABLE fruit_pivot;
DROP TABLE fruit;
--remove_file $MYSQLD_DATADIR/test/expenses.txt
/************** MyUtil C++ Program Source Code File (.CPP) **************/
/* PROGRAM NAME: MYUTIL */
/* ------------- */
/* Version 1.1 */
/* Version 1.2 */
/* */
/* Author Olivier BERTRAND 2013 */
/* Author Olivier BERTRAND 2014 */
/* */
/* WHAT THIS PROGRAM DOES: */
/* ----------------------- */
......@@ -26,6 +26,8 @@
#include "myutil.h"
#define DLL_EXPORT // Items are exported from this DLL
extern "C" int xconv;
/************************************************************************/
/* Convert from MySQL type name to PlugDB type number */
/************************************************************************/
......@@ -38,8 +40,7 @@ int MYSQLtoPLG(char *typname, char *var)
type = TYPE_INT;
else if (!stricmp(typname, "smallint"))
type = TYPE_SHORT;
else if (!stricmp(typname, "char") || !stricmp(typname, "varchar") ||
!stricmp(typname, "text") || !stricmp(typname, "blob"))
else if (!stricmp(typname, "char") || !stricmp(typname, "varchar"))
type = TYPE_STRING;
else if (!stricmp(typname, "double") || !stricmp(typname, "float") ||
!stricmp(typname, "real"))
......@@ -54,7 +55,20 @@ int MYSQLtoPLG(char *typname, char *var)
type = TYPE_BIGINT;
else if (!stricmp(typname, "tinyint"))
type = TYPE_TINY;
else
else if (!stricmp(typname, "text") && var) {
switch (xconv) {
case 1:
type = TYPE_STRING;
*var = 'X';
break;
case 2:
*var = 'K';
default:
type = TYPE_ERROR;
} // endswitch xconv
return type;
} else
type = TYPE_ERROR;
if (var) {
......@@ -71,9 +85,11 @@ int MYSQLtoPLG(char *typname, char *var)
else if (!stricmp(typname, "year"))
*var = 'Y';
} else if (type == TYPE_STRING && stricmp(typname, "char"))
} 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)
*var = 'K';
else
*var = 0;
......@@ -196,34 +212,50 @@ int MYSQLtoPLG(int mytype, char *var)
#if !defined(ALPHA)
case MYSQL_TYPE_VARCHAR:
#endif // !ALPHA)
case MYSQL_TYPE_STRING:
type = TYPE_STRING;
break;
case MYSQL_TYPE_BLOB:
case MYSQL_TYPE_TINY_BLOB:
case MYSQL_TYPE_MEDIUM_BLOB:
case MYSQL_TYPE_LONG_BLOB:
case MYSQL_TYPE_STRING:
type = TYPE_STRING;
break;
if (var) {
switch (xconv) {
case 1:
if (*var != 'B') {
// This is a TEXT column
type = TYPE_STRING;
*var = 'X';
} else
type = TYPE_ERROR;
break;
case 2:
*var = 'K'; // Skip
default:
type = TYPE_ERROR;
} // endswitch xconv
return type;
} // endif var
default:
type = TYPE_ERROR;
} // endswitch mytype
if (var) switch (mytype) {
// This is to make the difference between CHAR and VARCHAR
case MYSQL_TYPE_VAR_STRING:
#if !defined(ALPHA)
case MYSQL_TYPE_VARCHAR:
#endif // !ALPHA)
case MYSQL_TYPE_BLOB:
case MYSQL_TYPE_TINY_BLOB:
case MYSQL_TYPE_MEDIUM_BLOB:
case MYSQL_TYPE_LONG_BLOB: *var = 'V'; break;
case MYSQL_TYPE_VAR_STRING: *var = 'V'; break;
// This is to make the difference between temporal values
case MYSQL_TYPE_TIMESTAMP: *var = 'S'; break;
case MYSQL_TYPE_DATE: *var = 'D'; break;
case MYSQL_TYPE_DATETIME: *var = 'A'; break;
case MYSQL_TYPE_YEAR: *var = 'Y'; break;
case MYSQL_TYPE_TIME: *var = 'T'; break;
default: *var = 0;
case MYSQL_TYPE_TIMESTAMP: *var = 'S'; break;
case MYSQL_TYPE_DATE: *var = 'D'; break;
case MYSQL_TYPE_DATETIME: *var = 'A'; break;
case MYSQL_TYPE_YEAR: *var = 'Y'; break;
case MYSQL_TYPE_TIME: *var = 'T'; break;
default: *var = 0;
} // endswitch mytype
return type;
......
......@@ -16,6 +16,7 @@ my_bool CloseFileHandle(HANDLE h)
#include <sys/stat.h>
#include <ctype.h>
#include <fcntl.h>
#include <pwd.h>
extern FILE *debug;
......@@ -172,16 +173,23 @@ char *_fullpath(char *absPath, const char *relPath, size_t maxLength)
// Fixme
char *p;
if( *relPath == '\\' || *relPath == '/' ) {
if ( *relPath == '\\' || *relPath == '/' ) {
strncpy(absPath, relPath, maxLength);
} else if(*relPath == '~') {
} else if (*relPath == '~') {
// get the path to the home directory
// Fixme
strncpy(absPath, relPath, maxLength);
} else {
struct passwd *pw = getpwuid(getuid());
const char *homedir = pw->pw_dir;
if (homedir)
strcat(strncpy(absPath, homedir, maxLength), relPath + 1);
else
strncpy(absPath, relPath, maxLength);
} else {
char buff[2*_MAX_PATH];
assert(getcwd(buff, _MAX_PATH) != NULL);
p= getcwd(buff, _MAX_PATH);
assert(p);
strcat(buff,"/");
strcat(buff, relPath);
strncpy(absPath, buff, maxLength);
......
This diff is collapsed.
......@@ -115,11 +115,6 @@ void htrc(char const *fmt, ...)
va_list ap;
va_start (ap, fmt);
//if (trace == 0 || (trace == 1 && !debug) || !fmt) {
// printf("In %s wrong trace=%d debug=%p fmt=%p\n",
// __FILE__, trace, debug, fmt);
// trace = 0;
// } // endif trace
//if (trace == 1)
// vfprintf(debug, fmt, ap);
......@@ -256,7 +251,20 @@ LPCSTR PlugSetPath(LPSTR pBuff, LPCSTR prefix, LPCSTR FileName, LPCSTR defpath)
strcpy(pBuff, FileName); // FileName includes absolute path
return pBuff;
} // endif
#if !defined(WIN32)
if (*FileName == '~') {
if (_fullpath(pBuff, FileName, _MAX_PATH)) {
if (trace > 1)
htrc("pbuff='%s'\n", pBuff);
return pBuff;
} else
return FileName; // Error, return unchanged name
} // endif FileName
#endif // !WIN32
if (strcmp(prefix, ".") && !PlugIsAbsolutePath(defpath))
{
char tmp[_MAX_PATH];
......@@ -478,10 +486,9 @@ void *PlugSubAlloc(PGLOBAL g, void *memp, size_t size)
size = ((size + 7) / 8) * 8; /* Round up size to multiple of 8 */
pph = (PPOOLHEADER)memp;
#if defined(DEBUG2) || defined(DEBUG3)
htrc("SubAlloc in %p size=%d used=%d free=%d\n",
memp, size, pph->To_Free, pph->FreeBlk);
#endif
if (trace > 2)
htrc("SubAlloc in %p size=%d used=%d free=%d\n",
memp, size, pph->To_Free, pph->FreeBlk);
if ((uint)size > pph->FreeBlk) { /* Not enough memory left in pool */
char *pname = "Work";
......@@ -490,9 +497,8 @@ void *PlugSubAlloc(PGLOBAL g, void *memp, size_t size)
"Not enough memory in %s area for request of %u (used=%d free=%d)",
pname, (uint) size, pph->To_Free, pph->FreeBlk);
#if defined(DEBUG2) || defined(DEBUG3)
htrc("%s\n", g->Message);
#endif
if (trace)
htrc("PlugSubAlloc: %s\n", g->Message);
longjmp(g->jumper[g->jump_level], 1);
} /* endif size OS32 code */
......@@ -503,10 +509,11 @@ void *PlugSubAlloc(PGLOBAL g, void *memp, size_t size)
memp = MakePtr(memp, pph->To_Free); /* Points to suballocated block */
pph->To_Free += size; /* New offset of pool free block */
pph->FreeBlk -= size; /* New size of pool free block */
#if defined(DEBUG2) || defined(DEBUG3)
htrc("Done memp=%p used=%d free=%d\n",
memp, pph->To_Free, pph->FreeBlk);
#endif
if (trace > 2)
htrc("Done memp=%p used=%d free=%d\n",
memp, pph->To_Free, pph->FreeBlk);
return (memp);
} /* end of PlugSubAlloc */
......
......@@ -1134,10 +1134,13 @@ MYSQLCOL::MYSQLCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am)
MYSQLCOL::MYSQLCOL(MYSQL_FIELD *fld, PTDB tdbp, int i, PSZ am)
: COLBLK(NULL, tdbp, i)
{
const char *chset = get_charset_name(fld->charsetnr);
char v = (!strcmp(chset, "binary")) ? 'B' : 0;
Name = fld->name;
Opt = 0;
Precision = Long = fld->length;
Buf_Type = MYSQLtoPLG(fld->type);
Buf_Type = MYSQLtoPLG(fld->type, &v);
strcpy(Format.Type, GetFormatType(Buf_Type));
Format.Length = Long;
Format.Prec = fld->decimals;
......@@ -1616,5 +1619,5 @@ TDBMCL::TDBMCL(PMYDEF tdp) : TDBCAT(tdp)
/***********************************************************************/
PQRYRES TDBMCL::GetResult(PGLOBAL g)
{
return MyColumns(g, Host, Db, User, Pwd, Tab, NULL, Port, false);
return MyColumns(g, NULL, Host, Db, User, Pwd, Tab, NULL, Port, false);
} // end of GetResult
......@@ -96,10 +96,21 @@ PIVAID::PIVAID(const char *tab, const char *src, const char *picol,
PQRYRES PIVAID::MakePivotColumns(PGLOBAL g)
{
char *query, *colname, buf[64];
int ndif, nblin, w = 0;
int rc, ndif, nblin, w = 0;
bool b = false;
PVAL valp;
PCOLRES *pcrp, crp, fncrp = NULL;
// 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
if (!Tabsrc && Tabname) {
// Locate the query
query = (char*)PlugSubAlloc(g, NULL, strlen(Tabname) + 16);
......@@ -113,16 +124,17 @@ PQRYRES PIVAID::MakePivotColumns(PGLOBAL g)
// Open a MySQL connection for this table
if (Myc.Open(g, Host, Database, User, Pwd, Port))
return NULL;
else
b = true;
// Send the source command to MySQL
if (Myc.ExecSQL(g, query, &w) == RC_FX) {
Myc.Close();
return NULL;
} // endif Exec
if (Myc.ExecSQL(g, query, &w) == RC_FX)
goto err;
// We must have a storage query to get pivot column values
Qryp = Myc.GetResult(g, true);
Myc.Close();
b = false;
if (!Fncol) {
for (crp = Qryp->Colresp; crp; crp = crp->Next)
......@@ -152,6 +164,11 @@ PQRYRES PIVAID::MakePivotColumns(PGLOBAL g)
// Prepare the column list
for (pcrp = &Qryp->Colresp; crp = *pcrp; )
if (!stricmp(Picol, crp->Name)) {
if (crp->Nulls) {
sprintf(g->Message, "Pivot column %s cannot be nullable", Picol);
return NULL;
} // endif Nulls
Rblkp = crp->Kdata;
*pcrp = crp->Next;
} else if (!stricmp(Fncol, crp->Name)) {
......@@ -218,6 +235,12 @@ PQRYRES PIVAID::MakePivotColumns(PGLOBAL g)
// We added ndif columns and removed 2 (picol and fncol)
Qryp->Nbcol += (ndif - 2);
return Qryp;
err:
if (b)
Myc.Close();
return NULL;
} // end of MakePivotColumns
/***********************************************************************/
......
......@@ -55,6 +55,7 @@
#include "ha_connect.h"
extern "C" int trace;
extern "C" int zconv;
/************************************************************************/
/* Used by MYSQL tables to get MySQL parameters from the calling proxy */
......@@ -129,7 +130,7 @@ PQRYRES TabColumns(PGLOBAL g, THD *thd, const char *db,
FLD_LENGTH, FLD_SCALE, FLD_RADIX, FLD_NULL,
FLD_REM, FLD_NO, FLD_CHARSET};
unsigned int length[] = {0, 4, 16, 4, 4, 4, 4, 4, 0, 32, 32};
char *fld, *fmt, v;
char *fld, *colname, *chset, *fmt, v;
int i, n, ncol = sizeof(buftyp) / sizeof(int);
int prec, len, type, scale;
bool mysql;
......@@ -176,21 +177,37 @@ PQRYRES TabColumns(PGLOBAL g, THD *thd, const char *db,
/**********************************************************************/
/* Now get the results into blocks. */
/**********************************************************************/
for (i = 0, field= s->field; *field; i++, field++) {
for (i = 0, field= s->field; *field; field++) {
fp= *field;
// Get column name
crp = qrp->Colresp; // Column_Name
fld = (char *)fp->field_name;
crp->Kdata->SetValue(fld, i);
v = 0;
colname = (char *)fp->field_name;
crp->Kdata->SetValue(colname, i);
chset = (char *)fp->charset()->name;
v = (!strcmp(chset, "binary")) ? 'B' : 0;
if ((type = MYSQLtoPLG(fp->type(), &v)) == TYPE_ERROR) {
sprintf(g->Message, "Unsupported column type %s", GetTypeName(type));
if (v == 'K') {
// Skip this column
sprintf(g->Message, "Column %s skipped (unsupported type)", colname);
push_warning(thd, Sql_condition::WARN_LEVEL_WARN, 0, g->Message);
continue;
} // endif v
sprintf(g->Message, "Column %s unsupported type", colname);
qrp = NULL;
break;
} // endif type
if (v == 'X') {
len = zconv;
sprintf(g->Message, "Column %s converted to varchar(%d)",
colname, len);
push_warning(thd, Sql_condition::WARN_LEVEL_WARN, 0, g->Message);
} // endif v
crp = crp->Next; // Data_Type
crp->Kdata->SetValue(type, i);
......@@ -198,11 +215,12 @@ PQRYRES TabColumns(PGLOBAL g, THD *thd, const char *db,
crp->Nulls[i] = 'Z';
else if (fp->flags & UNSIGNED_FLAG)
crp->Nulls[i] = 'U';
else
crp->Nulls[i] = v;
else // X means TEXT field
crp->Nulls[i] = (v == 'X') ? 'V' : v;
crp = crp->Next; // Type_Name
crp->Kdata->SetValue(GetTypeName(type), i);
fmt = NULL;
if (type == TYPE_DATE) {
// When creating tables we do need info about date columns
......@@ -214,7 +232,7 @@ PQRYRES TabColumns(PGLOBAL g, THD *thd, const char *db,
prec = len = fp->field_length;
} // endif mysql
} else {
} else if (v != 'X') {
if (type == TYPE_DECIM)
prec = ((Field_new_decimal*)fp)->precision;
else
......@@ -222,8 +240,8 @@ PQRYRES TabColumns(PGLOBAL g, THD *thd, const char *db,
// prec = (prec(???) == NOT_FIXED_DEC) ? 0 : fp->field_length;
len = fp->char_length();
fmt = NULL;
} // endif type
} else
prec = len = zconv;
crp = crp->Next; // Precision
crp->Kdata->SetValue(prec, i);
......@@ -259,6 +277,7 @@ PQRYRES TabColumns(PGLOBAL g, THD *thd, const char *db,
// Add this item
qrp->Nblin++;
i++; // Can be skipped
} // endfor field
/**********************************************************************/
......
......@@ -48,6 +48,7 @@
#include "mycat.h"
extern "C" int trace;
extern uint worksize;
/****************************************************************************/
/* Initialize the user_connect static member. */
......@@ -94,8 +95,9 @@ bool user_connect::user_init()
PDBUSER dup= NULL;
// Areasize= 64M because of VEC tables. Should be parameterisable
g= PlugInit(NULL, 67108864);
//g= PlugInit(NULL, 67108864);
//g= PlugInit(NULL, 134217728); // 128M was because of old embedded tests
g= PlugInit(NULL, worksize);
// Check whether the initialization is complete
if (!g || !g->Sarea || PlugSubSet(g, g->Sarea, g->Sarea_Size)
......@@ -142,6 +144,20 @@ bool user_connect::CheckCleanup(void)
{
if (thdp->query_id > last_query_id) {
PlugCleanup(g, true);
if (g->Sarea_Size != worksize) {
if (g->Sarea)
free(g->Sarea);
// Check whether the work area size was changed
if (!(g->Sarea = PlugAllocMem(g, worksize))) {
g->Sarea = PlugAllocMem(g, g->Sarea_Size);
worksize = g->Sarea_Size; // Was too big
} else
g->Sarea_Size = worksize; // Ok
} // endif worksize
PlugSubSet(g, g->Sarea, g->Sarea_Size);
g->Xchk = NULL;
g->Createas = 0;
......
......@@ -44,6 +44,7 @@
#define CheckParms(V, N) ChkIndx(N); ChkTyp(V);
extern "C" int trace;
extern MBLOCK Nmblk; /* Used to initialize MBLOCK's */
/***********************************************************************/
/* AllocValBlock: allocate a VALBLK according to type. */
......@@ -105,8 +106,7 @@ PVBLK AllocValBlock(PGLOBAL g, void *mp, int type, int nval, int len,
return NULL;
} // endswitch Type
blkp->Init(g, check);
return blkp;
return (blkp->Init(g, check)) ? NULL : blkp;
} // end of AllocValBlock
/* -------------------------- Class VALBLK --------------------------- */
......@@ -116,6 +116,7 @@ PVBLK AllocValBlock(PGLOBAL g, void *mp, int type, int nval, int len,
/***********************************************************************/
VALBLK::VALBLK(void *mp, int type, int nval, bool un)
{
Mblk = Nmblk;
Blkp = mp;
To_Nulls = NULL;
Check = true;
......@@ -179,6 +180,22 @@ void VALBLK::SetNullable(bool b)
} // end of SetNullable
/***********************************************************************/
/* Buffer allocation routine. */
/***********************************************************************/
bool VALBLK::AllocBuff(PGLOBAL g, size_t size)
{
Mblk.Size = size;
if (!(Blkp = PlgDBalloc(g, NULL, Mblk))) {
sprintf(g->Message, MSG(MEM_ALLOC_ERR), "Blkp", Mblk.Size);
fprintf(stderr, "%s\n", g->Message);
return true;
} // endif Blkp
return false;
} // end of AllocBuff
/***********************************************************************/
/* Check functions. */
/***********************************************************************/
......@@ -229,13 +246,15 @@ TYPBLK<TYPE>::TYPBLK(void *mp, int nval, int type, int prec, bool un)
/* Initialization routine. */
/***********************************************************************/
template <class TYPE>
void TYPBLK<TYPE>::Init(PGLOBAL g, bool check)
bool TYPBLK<TYPE>::Init(PGLOBAL g, bool check)
{
if (!Blkp)
Blkp = PlugSubAlloc(g, NULL, Nval * sizeof(TYPE));
if (AllocBuff(g, Nval * sizeof(TYPE)))
return true;
Check = check;
Global = g;
return false;
} // end of Init
/***********************************************************************/
......@@ -606,16 +625,18 @@ CHRBLK::CHRBLK(void *mp, int nval, int len, int prec, bool blank)
/***********************************************************************/
/* Initialization routine. */
/***********************************************************************/
void CHRBLK::Init(PGLOBAL g, bool check)
bool CHRBLK::Init(PGLOBAL g, bool check)
{
Valp = (char*)PlugSubAlloc(g, NULL, Long + 1);
Valp[Long] = '\0';
if (!Blkp)
Blkp = PlugSubAlloc(g, NULL, Nval * Long);
if (AllocBuff(g, Nval * Long))
return true;
Check = check;
Global = g;
return false;
} // end of Init
/***********************************************************************/
......@@ -996,13 +1017,15 @@ STRBLK::STRBLK(PGLOBAL g, void *mp, int nval)
/***********************************************************************/
/* Initialization routine. */
/***********************************************************************/
void STRBLK::Init(PGLOBAL g, bool check)
bool STRBLK::Init(PGLOBAL g, bool check)
{
if (!Blkp)
Blkp = PlugSubAlloc(g, NULL, Nval * sizeof(PSZ));
if (AllocBuff(g, Nval * sizeof(PSZ)))
return true;
Check = check;
Global = g;
return false;
} // end of Init
/***********************************************************************/
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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