Commit 43362bc9 authored by Olivier Bertrand's avatar Olivier Bertrand

- Fix bug MDEV-5734

modified:
  storage/connect/mysql-test/connect/r/pivot.result
  storage/connect/mysql-test/connect/t/pivot.test
  storage/connect/tabmysql.cpp
  storage/connect/tabpivot.cpp

- Implement a first experimental support of MRR
  (compiled only if MRRBKA_SUPPORT is defined)
modified:
  storage/connect/colblk.h
  storage/connect/connect.cc
  storage/connect/connect.h
  storage/connect/global.h
  storage/connect/ha_connect.cc
  storage/connect/ha_connect.h
  storage/connect/plugutil.c
  storage/connect/user_connect.cc
parent 1699947e
...@@ -49,6 +49,9 @@ class DllExport COLBLK : public XOBJECT { ...@@ -49,6 +49,9 @@ class DllExport COLBLK : public XOBJECT {
void AddColUse(ushort u) {ColUse |= u;} void AddColUse(ushort u) {ColUse |= u;}
void AddStatus(ushort u) {Status |= u;} void AddStatus(ushort u) {Status |= u;}
void SetNext(PCOL cp) {Next = cp;} void SetNext(PCOL cp) {Next = cp;}
#if defined(MRRBKA_SUPPORT)
PXCOL GetKcol(void) {return To_Kcol;}
#endif // MRRBKA_SUPPORT
void SetKcol(PXCOL kcp) {To_Kcol = kcp;} void SetKcol(PXCOL kcp) {To_Kcol = kcp;}
PCOLDEF GetCdp(void) {return Cdp;} PCOLDEF GetCdp(void) {return Cdp;}
PSZ GetDomain(void) {return (Cdp) ? Cdp->Decode : NULL;} PSZ GetDomain(void) {return (Cdp) ? Cdp->Decode : NULL;}
......
...@@ -57,7 +57,7 @@ extern int xtrace; ...@@ -57,7 +57,7 @@ extern int xtrace;
/* Routines called internally by semantic routines. */ /* Routines called internally by semantic routines. */
/***********************************************************************/ /***********************************************************************/
void CntEndDB(PGLOBAL); void CntEndDB(PGLOBAL);
RCODE EvalColumns(PGLOBAL g, PTDB tdbp); RCODE EvalColumns(PGLOBAL g, PTDB tdbp, bool mrr= false);
/***********************************************************************/ /***********************************************************************/
/* MySQL routines called externally by semantic routines. */ /* MySQL routines called externally by semantic routines. */
...@@ -187,7 +187,7 @@ bool CntInfo(PGLOBAL g, PTDB tp, PXF info) ...@@ -187,7 +187,7 @@ bool CntInfo(PGLOBAL g, PTDB tp, PXF info)
/***********************************************************************/ /***********************************************************************/
PTDB CntGetTDB(PGLOBAL g, LPCSTR name, MODE mode, PHC h) PTDB CntGetTDB(PGLOBAL g, LPCSTR name, MODE mode, PHC h)
{ {
int rc; int rc;
PTDB tdbp; PTDB tdbp;
PTABLE tabp; PTABLE tabp;
PDBUSER dup= PlgGetUser(g); PDBUSER dup= PlgGetUser(g);
...@@ -237,7 +237,8 @@ bool CntOpenTable(PGLOBAL g, PTDB tdbp, MODE mode, char *c1, char *c2, ...@@ -237,7 +237,8 @@ bool CntOpenTable(PGLOBAL g, PTDB tdbp, MODE mode, char *c1, char *c2,
bool del, PHC h) bool del, PHC h)
{ {
char *p; char *p;
int i, n; int i, n, rc;
bool rcop= true;
PCOL colp; PCOL colp;
//PCOLUMN cp; //PCOLUMN cp;
PDBUSER dup= PlgGetUser(g); PDBUSER dup= PlgGetUser(g);
...@@ -251,7 +252,15 @@ bool CntOpenTable(PGLOBAL g, PTDB tdbp, MODE mode, char *c1, char *c2, ...@@ -251,7 +252,15 @@ bool CntOpenTable(PGLOBAL g, PTDB tdbp, MODE mode, char *c1, char *c2,
return true; return true;
} // endif tdbp } // endif tdbp
//tdbp->SetMode(mode); done in ha_connect::GetTDB // Save stack and allocation environment and prepare error return
if (g->jump_level == MAX_JUMP) {
strcpy(g->Message, MSG(TOO_MANY_JUMPS));
return true;
} // endif jump_level
if ((rc= setjmp(g->jumper[++g->jump_level])) != 0) {
goto err;
} // endif rc
if (!c1) { if (!c1) {
if (mode == MODE_INSERT) if (mode == MODE_INSERT)
...@@ -273,7 +282,7 @@ bool CntOpenTable(PGLOBAL g, PTDB tdbp, MODE mode, char *c1, char *c2, ...@@ -273,7 +282,7 @@ bool CntOpenTable(PGLOBAL g, PTDB tdbp, MODE mode, char *c1, char *c2,
if (!colp) { if (!colp) {
sprintf(g->Message, "Column %s not found in %s", p, tdbp->GetName()); sprintf(g->Message, "Column %s not found in %s", p, tdbp->GetName());
return true; goto err;
} // endif colp } // endif colp
n= strlen(p) + 1; n= strlen(p) + 1;
...@@ -281,12 +290,12 @@ bool CntOpenTable(PGLOBAL g, PTDB tdbp, MODE mode, char *c1, char *c2, ...@@ -281,12 +290,12 @@ bool CntOpenTable(PGLOBAL g, PTDB tdbp, MODE mode, char *c1, char *c2,
for (i= 0, colp= tdbp->GetColumns(); colp; i++, colp= colp->GetNext()) { for (i= 0, colp= tdbp->GetColumns(); colp; i++, colp= colp->GetNext()) {
if (colp->InitValue(g)) if (colp->InitValue(g))
return true; goto err;
if (mode == MODE_INSERT) if (mode == MODE_INSERT)
// Allow type conversion // Allow type conversion
if (colp->SetBuffer(g, colp->GetValue(), true, false)) if (colp->SetBuffer(g, colp->GetValue(), true, false))
return true; goto err;
colp->AddColUse(U_P); // For PLG tables colp->AddColUse(U_P); // For PLG tables
} // endfor colp } // endfor colp
...@@ -301,7 +310,7 @@ bool CntOpenTable(PGLOBAL g, PTDB tdbp, MODE mode, char *c1, char *c2, ...@@ -301,7 +310,7 @@ bool CntOpenTable(PGLOBAL g, PTDB tdbp, MODE mode, char *c1, char *c2,
if (!(utp= (PTDBASE)tdbp->Duplicate(g))) { if (!(utp= (PTDBASE)tdbp->Duplicate(g))) {
sprintf(g->Message, MSG(INV_UPDT_TABLE), tdbp->GetName()); sprintf(g->Message, MSG(INV_UPDT_TABLE), tdbp->GetName());
return true; goto err;
} // endif tp } // endif tp
if (!c2) if (!c2)
...@@ -315,10 +324,10 @@ bool CntOpenTable(PGLOBAL g, PTDB tdbp, MODE mode, char *c1, char *c2, ...@@ -315,10 +324,10 @@ bool CntOpenTable(PGLOBAL g, PTDB tdbp, MODE mode, char *c1, char *c2,
for (i= 0, colp= utp->GetColumns(); colp; i++, colp= colp->GetNext()) { for (i= 0, colp= utp->GetColumns(); colp; i++, colp= colp->GetNext()) {
if (colp->InitValue(g)) if (colp->InitValue(g))
return true; goto err;
if (colp->SetBuffer(g, colp->GetValue(), true, false)) if (colp->SetBuffer(g, colp->GetValue(), true, false))
return true; goto err;
} // endfor colp } // endfor colp
...@@ -350,13 +359,17 @@ bool CntOpenTable(PGLOBAL g, PTDB tdbp, MODE mode, char *c1, char *c2, ...@@ -350,13 +359,17 @@ bool CntOpenTable(PGLOBAL g, PTDB tdbp, MODE mode, char *c1, char *c2,
if (mode != MODE_ANY && mode != MODE_ALTER) { if (mode != MODE_ANY && mode != MODE_ALTER) {
if (tdbp->OpenDB(g)) { if (tdbp->OpenDB(g)) {
printf("%s\n", g->Message); printf("%s\n", g->Message);
return true; goto err;
} else } else
tdbp->SetNext(NULL); tdbp->SetNext(NULL);
} // endif mode } // endif mode
return false; rcop= false;
err:
g->jump_level--;
return rcop;
} // end of CntOpenTable } // end of CntOpenTable
/***********************************************************************/ /***********************************************************************/
...@@ -374,7 +387,7 @@ bool CntRewindTable(PGLOBAL g, PTDB tdbp) ...@@ -374,7 +387,7 @@ bool CntRewindTable(PGLOBAL g, PTDB tdbp)
/***********************************************************************/ /***********************************************************************/
/* Evaluate all columns after a record is read. */ /* Evaluate all columns after a record is read. */
/***********************************************************************/ /***********************************************************************/
RCODE EvalColumns(PGLOBAL g, PTDB tdbp) RCODE EvalColumns(PGLOBAL g, PTDB tdbp, bool mrr)
{ {
RCODE rc= RC_OK; RCODE rc= RC_OK;
PCOL colp; PCOL colp;
...@@ -402,7 +415,11 @@ RCODE EvalColumns(PGLOBAL g, PTDB tdbp) ...@@ -402,7 +415,11 @@ RCODE EvalColumns(PGLOBAL g, PTDB tdbp)
colp->Reset(); colp->Reset();
// Virtual columns are computed by MariaDB // Virtual columns are computed by MariaDB
#if defined(MRRBKA_SUPPORT)
if (!colp->GetColUse(U_VIRTUAL) && (!mrr || colp->GetKcol()))
#else // !MRRBKA_SUPPORT
if (!colp->GetColUse(U_VIRTUAL)) if (!colp->GetColUse(U_VIRTUAL))
#endif // !MRRBKA_SUPPORT
if (colp->Eval(g)) if (colp->Eval(g))
rc= RC_FX; rc= RC_FX;
...@@ -680,7 +697,7 @@ int CntIndexInit(PGLOBAL g, PTDB ptdb, int id) ...@@ -680,7 +697,7 @@ int CntIndexInit(PGLOBAL g, PTDB ptdb, int id)
/* IndexRead: fetch a record having the index value. */ /* IndexRead: fetch a record having the index value. */
/***********************************************************************/ /***********************************************************************/
RCODE CntIndexRead(PGLOBAL g, PTDB ptdb, OPVAL op, RCODE CntIndexRead(PGLOBAL g, PTDB ptdb, OPVAL op,
const void *key, int len) const void *key, int len, bool mrr)
{ {
char *kp= (char*)key; char *kp= (char*)key;
int n; int n;
...@@ -757,7 +774,7 @@ RCODE CntIndexRead(PGLOBAL g, PTDB ptdb, OPVAL op, ...@@ -757,7 +774,7 @@ RCODE CntIndexRead(PGLOBAL g, PTDB ptdb, OPVAL op,
xbp->SetNth(0); xbp->SetNth(0);
if ((rc= (RCODE)tdbp->ReadDB(g)) == RC_OK) if ((rc= (RCODE)tdbp->ReadDB(g)) == RC_OK)
rc= EvalColumns(g, tdbp); rc= EvalColumns(g, tdbp, mrr);
return rc; return rc;
} // end of CntIndexRead } // end of CntIndexRead
......
...@@ -37,7 +37,8 @@ bool CntRewindTable(PGLOBAL g, PTDB tdbp); ...@@ -37,7 +37,8 @@ bool CntRewindTable(PGLOBAL g, PTDB tdbp);
int CntCloseTable(PGLOBAL g, PTDB tdbp); int CntCloseTable(PGLOBAL g, PTDB tdbp);
int CntIndexInit(PGLOBAL g, PTDB tdbp, int id); int CntIndexInit(PGLOBAL g, PTDB tdbp, int id);
RCODE CntReadNext(PGLOBAL g, PTDB tdbp); RCODE CntReadNext(PGLOBAL g, PTDB tdbp);
RCODE CntIndexRead(PGLOBAL g, PTDB, OPVAL op, const void *k, int n); RCODE CntIndexRead(PGLOBAL g, PTDB, OPVAL op, const void *k, int n,
bool mrr = false);
RCODE CntWriteRow(PGLOBAL g, PTDB tdbp); RCODE CntWriteRow(PGLOBAL g, PTDB tdbp);
RCODE CntUpdateRow(PGLOBAL g, PTDB tdbp); RCODE CntUpdateRow(PGLOBAL g, PTDB tdbp);
RCODE CntDeleteRow(PGLOBAL g, PTDB tdbp, bool all); RCODE CntDeleteRow(PGLOBAL g, PTDB tdbp, bool all);
...@@ -63,7 +64,7 @@ class TDBDOX: public TDBDOS { ...@@ -63,7 +64,7 @@ class TDBDOX: public TDBDOS {
friend int MakeIndex(PGLOBAL, PTDB, PIXDEF); friend int MakeIndex(PGLOBAL, PTDB, PIXDEF);
friend int CntCloseTable(PGLOBAL, PTDB); friend int CntCloseTable(PGLOBAL, PTDB);
friend int CntIndexInit(PGLOBAL, PTDB, int); friend int CntIndexInit(PGLOBAL, PTDB, int);
friend RCODE CntIndexRead(PGLOBAL, PTDB, OPVAL, const void*, int); friend RCODE CntIndexRead(PGLOBAL, PTDB, OPVAL, const void*, int, bool);
friend RCODE CntDeleteRow(PGLOBAL, PTDB, bool); friend RCODE CntDeleteRow(PGLOBAL, PTDB, bool);
friend int CntIndexRange(PGLOBAL, PTDB, const uchar**, uint*, friend int CntIndexRange(PGLOBAL, PTDB, const uchar**, uint*,
bool*, key_part_map*); bool*, key_part_map*);
......
...@@ -222,6 +222,9 @@ typedef struct _global { /* Global structure */ ...@@ -222,6 +222,9 @@ typedef struct _global { /* Global structure */
int Createas; /* To pass info to created table */ int Createas; /* To pass info to created table */
void *Xchk; /* indexes in create/alter */ void *Xchk; /* indexes in create/alter */
short Alchecked; /* Checked for ALTER */ short Alchecked; /* Checked for ALTER */
#if defined(MRRBKA_SUPPORT)
short Mrr; /* True when doing mrr */
#endif // MRRBKA_SUPPORT
short Trace; short Trace;
int jump_level; int jump_level;
jmp_buf jumper[MAX_JUMP + 2]; jmp_buf jumper[MAX_JUMP + 2];
......
...@@ -481,6 +481,7 @@ ha_connect::ha_connect(handlerton *hton, TABLE_SHARE *table_arg) ...@@ -481,6 +481,7 @@ ha_connect::ha_connect(handlerton *hton, TABLE_SHARE *table_arg)
creat_query_id= (table && table->in_use) ? table->in_use->query_id : 0; creat_query_id= (table && table->in_use) ? table->in_use->query_id : 0;
stop= false; stop= false;
alter= false; alter= false;
mrr= false;
indexing= -1; indexing= -1;
locked= 0; locked= 0;
data_file_name= NULL; data_file_name= NULL;
...@@ -1357,10 +1358,20 @@ int ha_connect::MakeRecord(char *buf) ...@@ -1357,10 +1358,20 @@ int ha_connect::MakeRecord(char *buf)
if (bitmap_is_set(map, fp->field_index) || alter) { if (bitmap_is_set(map, fp->field_index) || alter) {
// This is a used field, fill the buffer with value // This is a used field, fill the buffer with value
for (colp= tdbp->GetColumns(); colp; colp= colp->GetNext()) for (colp= tdbp->GetColumns(); colp; colp= colp->GetNext())
#if defined(MRRBKA_SUPPORT)
if ((!mrr || colp->GetKcol()) &&
!stricmp(colp->GetName(), (char*)fp->field_name))
break;
#else // !MRRBKA_SUPPORT
if (!stricmp(colp->GetName(), (char*)fp->field_name)) if (!stricmp(colp->GetName(), (char*)fp->field_name))
break; break;
#endif // !MRRBKA_SUPPORT
if (!colp) { if (!colp) {
#if defined(MRRBKA_SUPPORT)
if (mrr)
continue;
#endif // MRRBKA_SUPPORT
printf("Column %s not found\n", fp->field_name); printf("Column %s not found\n", fp->field_name);
dbug_tmp_restore_column_map(table->write_set, org_bitmap); dbug_tmp_restore_column_map(table->write_set, org_bitmap);
DBUG_RETURN(HA_ERR_WRONG_IN_RECORD); DBUG_RETURN(HA_ERR_WRONG_IN_RECORD);
...@@ -2020,9 +2031,17 @@ int ha_connect::open(const char *name, int mode, uint test_if_locked) ...@@ -2020,9 +2031,17 @@ int ha_connect::open(const char *name, int mode, uint test_if_locked)
PGLOBAL g= (xp) ? xp->g : NULL; PGLOBAL g= (xp) ? xp->g : NULL;
// Try to set the database environment // Try to set the database environment
if (g) if (g) {
rc= (CntCheckDB(g, this, name)) ? (-2) : 0; rc= (CntCheckDB(g, this, name)) ? (-2) : 0;
else #if defined(MRRBKA_SUPPORT)
if (g->Mrr) {
// This should only happen for the mrr secondary handler
mrr= true;
g->Mrr= false;
} else
mrr= false;
#endif // MRRBKA_SUPPORT
} else
rc= HA_ERR_INTERNAL_ERROR; rc= HA_ERR_INTERNAL_ERROR;
DBUG_RETURN(rc); DBUG_RETURN(rc);
...@@ -2317,7 +2336,7 @@ int ha_connect::ReadIndexed(uchar *buf, OPVAL op, const uchar *key, uint key_len ...@@ -2317,7 +2336,7 @@ int ha_connect::ReadIndexed(uchar *buf, OPVAL op, const uchar *key, uint key_len
//statistic_increment(ha_read_key_count, &LOCK_status); //statistic_increment(ha_read_key_count, &LOCK_status);
switch (CntIndexRead(xp->g, tdbp, op, key, (int)key_len)) { switch (CntIndexRead(xp->g, tdbp, op, key, (int)key_len, mrr)) {
case RC_OK: case RC_OK:
xp->fnd++; xp->fnd++;
rc= MakeRecord((char*)buf); rc= MakeRecord((char*)buf);
...@@ -5401,7 +5420,7 @@ bool ha_connect::check_if_incompatible_data(HA_CREATE_INFO *info, ...@@ -5401,7 +5420,7 @@ bool ha_connect::check_if_incompatible_data(HA_CREATE_INFO *info,
#if defined(MRRBKA_SUPPORT) #if defined(MRRBKA_SUPPORT)
#error This is not implemented yet //#error This is not implemented yet
/**************************************************************************** /****************************************************************************
* CONNECT MRR implementation: use DS-MRR * CONNECT MRR implementation: use DS-MRR
This is just copied from myisam This is just copied from myisam
...@@ -5433,10 +5452,12 @@ ha_rows ha_connect::multi_range_read_info_const(uint keyno, RANGE_SEQ_IF *seq, ...@@ -5433,10 +5452,12 @@ ha_rows ha_connect::multi_range_read_info_const(uint keyno, RANGE_SEQ_IF *seq,
// MMR is implemented for "local" file based tables only // MMR is implemented for "local" file based tables only
if (!IsFileType(GetRealType(GetTableOptionStruct(table)))) if (!IsFileType(GetRealType(GetTableOptionStruct(table))))
*flags |= HA_MRR_USE_DEFAULT_IMPL; *flags|= HA_MRR_USE_DEFAULT_IMPL;
return ds_mrr.dsmrr_info_const(keyno, seq, seq_init_param, n_ranges, bufsz, ha_rows rows= ds_mrr.dsmrr_info_const(keyno, seq, seq_init_param, n_ranges,
flags, cost); bufsz, flags, cost);
xp->g->Mrr= !(*flags & HA_MRR_USE_DEFAULT_IMPL);
return rows;
} // end of multi_range_read_info_const } // end of multi_range_read_info_const
ha_rows ha_connect::multi_range_read_info(uint keyno, uint n_ranges, uint keys, ha_rows ha_connect::multi_range_read_info(uint keyno, uint n_ranges, uint keys,
...@@ -5444,7 +5465,15 @@ ha_rows ha_connect::multi_range_read_info(uint keyno, uint n_ranges, uint keys, ...@@ -5444,7 +5465,15 @@ ha_rows ha_connect::multi_range_read_info(uint keyno, uint n_ranges, uint keys,
uint *flags, Cost_estimate *cost) uint *flags, Cost_estimate *cost)
{ {
ds_mrr.init(this, table); ds_mrr.init(this, table);
return ds_mrr.dsmrr_info(keyno, n_ranges, keys, key_parts, bufsz, flags, cost);
// MMR is implemented for "local" file based tables only
if (!IsFileType(GetRealType(GetTableOptionStruct(table))))
*flags|= HA_MRR_USE_DEFAULT_IMPL;
ha_rows rows= ds_mrr.dsmrr_info(keyno, n_ranges, keys, key_parts, bufsz,
flags, cost);
xp->g->Mrr= !(*flags & HA_MRR_USE_DEFAULT_IMPL);
return rows;
} // end of multi_range_read_info } // end of multi_range_read_info
......
...@@ -243,8 +243,12 @@ public: ...@@ -243,8 +243,12 @@ public:
*/ */
ulong index_flags(uint inx, uint part, bool all_parts) const ulong index_flags(uint inx, uint part, bool all_parts) const
{ {
return HA_READ_NEXT | HA_READ_RANGE | HA_READ_ORDER; return HA_READ_NEXT | HA_READ_RANGE | HA_READ_ORDER
} #if defined(MRRBKA_SUPPORT)
| HA_KEYREAD_ONLY
#endif // MRRBKA_SUPPORT
;
} // end of index_flags
/** @brief /** @brief
unireg.cc will call max_supported_record_length(), max_supported_keys(), unireg.cc will call max_supported_record_length(), max_supported_keys(),
...@@ -484,6 +488,7 @@ protected: ...@@ -484,6 +488,7 @@ protected:
bool valid_info; // True if xinfo is valid bool valid_info; // True if xinfo is valid
bool stop; // Used when creating index bool stop; // Used when creating index
bool alter; // True when converting to other engine bool alter; // True when converting to other engine
bool mrr; // True when getting index positions
int indexing; // Type of indexing for CONNECT int indexing; // Type of indexing for CONNECT
int locked; // Table lock int locked; // Table lock
THR_LOCK_DATA lock_data; THR_LOCK_DATA lock_data;
......
...@@ -224,3 +224,30 @@ Kevin 0 2 6 ...@@ -224,3 +224,30 @@ Kevin 0 2 6
Donald 1 0 3 Donald 1 0 3
DROP TABLE pivet; DROP TABLE pivet;
DROP TABLE pets; DROP TABLE pets;
#
# MDEV-5734
#
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;
id name cnt
1 apple 1
2 banana 1
3 apple 2
4 cherry 4
5 durazno 2
CREATE TABLE fruit_pivot ENGINE=CONNECT TABLE_TYPE=pivot TABNAME=fruit;
SELECT * FROM fruit_pivot;
id apple banana cherry durazno
1 1 0 0 0
2 0 1 0 0
3 2 0 0 0
4 0 0 4 0
5 0 0 0 2
DROP TABLE fruit_pivot;
DROP TABLE fruit;
-- source include/not_embedded.inc -- source include/not_embedded.inc
let $MYSQLD_DATADIR= `select @@datadir`; let $MYSQLD_DATADIR= `select @@datadir`;
let $PORT= `select @@port`; let $PORT= `select @@port`;
--copy_file $MTR_SUITE_DIR/std_data/expenses.txt $MYSQLD_DATADIR/test/expenses.txt --copy_file $MTR_SUITE_DIR/std_data/expenses.txt $MYSQLD_DATADIR/test/expenses.txt
--echo # --echo #
--echo # Testing the PIVOT table type --echo # Testing the PIVOT table type
--echo # --echo #
CREATE TABLE expenses ( CREATE TABLE expenses (
Who CHAR(10) NOT NULL, Who CHAR(10) NOT NULL,
Week INT(2) NOT NULL, Week INT(2) NOT NULL,
What CHAR(12) NOT NULL, What CHAR(12) NOT NULL,
Amount DOUBLE(8,2)) Amount DOUBLE(8,2))
ENGINE=CONNECT TABLE_TYPE=FIX FILE_NAME='expenses.txt' ENDING=2; ENGINE=CONNECT TABLE_TYPE=FIX FILE_NAME='expenses.txt' ENDING=2;
SELECT * FROM expenses; SELECT * FROM expenses;
--echo # --echo #
--echo # Pivoting from What --echo # Pivoting from What
--echo # --echo #
CREATE TABLE pivex ( CREATE TABLE pivex (
Who CHAR(10) NOT NULL, Who CHAR(10) NOT NULL,
Week INT(2) NOT NULL, Week INT(2) NOT NULL,
Beer DOUBLE(8,2) FLAG=1, Beer DOUBLE(8,2) FLAG=1,
Car DOUBLE(8,2) FLAG=1, Car DOUBLE(8,2) FLAG=1,
Food DOUBLE(8,2) FLAG=1) Food DOUBLE(8,2) FLAG=1)
ENGINE=CONNECT TABLE_TYPE=PIVOT TABNAME=expenses; ENGINE=CONNECT TABLE_TYPE=PIVOT TABNAME=expenses;
--replace_result $PORT PORT --replace_result $PORT PORT
--eval ALTER TABLE pivex OPTION_LIST='port=$PORT' --eval ALTER TABLE pivex OPTION_LIST='port=$PORT'
SELECT * FROM pivex; SELECT * FROM pivex;
--echo # --echo #
--echo # Restricting the columns in a Pivot Table --echo # Restricting the columns in a Pivot Table
--echo # --echo #
ALTER TABLE pivex DROP COLUMN week; ALTER TABLE pivex DROP COLUMN week;
SELECT * FROM pivex; SELECT * FROM pivex;
--echo # --echo #
--echo # Using a source definition --echo # Using a source definition
--echo # --echo #
DROP TABLE pivex; DROP TABLE pivex;
CREATE TABLE pivex ( CREATE TABLE pivex (
Who CHAR(10) NOT NULL, Who CHAR(10) NOT NULL,
Week INT(2) NOT NULL, Week INT(2) NOT NULL,
Beer DOUBLE(8,2) FLAG=1, Beer DOUBLE(8,2) FLAG=1,
Car DOUBLE(8,2) FLAG=1, Car DOUBLE(8,2) FLAG=1,
Food DOUBLE(8,2) FLAG=1) Food DOUBLE(8,2) FLAG=1)
ENGINE=CONNECT TABLE_TYPE=PIVOT 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'; 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 --replace_result $PORT PORT
--eval ALTER TABLE pivex OPTION_LIST='PivotCol=what,FncCol=amount,port=$PORT' --eval ALTER TABLE pivex OPTION_LIST='PivotCol=what,FncCol=amount,port=$PORT'
SELECT * FROM pivex; SELECT * FROM pivex;
--echo # --echo #
--echo # Pivoting from Week --echo # Pivoting from Week
--echo # --echo #
DROP TABLE pivex; DROP TABLE pivex;
CREATE TABLE pivex ( CREATE TABLE pivex (
Who CHAR(10) NOT NULL, Who CHAR(10) NOT NULL,
What CHAR(12) NOT NULL, What CHAR(12) NOT NULL,
`3` DOUBLE(8,2) FLAG=1, `3` DOUBLE(8,2) FLAG=1,
`4` DOUBLE(8,2) FLAG=1, `4` DOUBLE(8,2) FLAG=1,
`5` DOUBLE(8,2) FLAG=1) `5` DOUBLE(8,2) FLAG=1)
ENGINE=CONNECT TABLE_TYPE=PIVOT TABNAME=expenses; ENGINE=CONNECT TABLE_TYPE=PIVOT TABNAME=expenses;
--replace_result $PORT PORT --replace_result $PORT PORT
--eval ALTER TABLE pivex OPTION_LIST='PivotCol=Week,port=$PORT' --eval ALTER TABLE pivex OPTION_LIST='PivotCol=Week,port=$PORT'
SELECT * FROM pivex; SELECT * FROM pivex;
--echo # --echo #
--echo # Using scalar functions and expresssions --echo # Using scalar functions and expresssions
--echo # --echo #
DROP TABLE pivex; DROP TABLE pivex;
CREATE TABLE pivex ( CREATE TABLE pivex (
Who CHAR(10) NOT NULL, Who CHAR(10) NOT NULL,
What CHAR(12) NOT NULL, What CHAR(12) NOT NULL,
First DOUBLE(8,2) FLAG=1, First DOUBLE(8,2) FLAG=1,
Middle DOUBLE(8,2) FLAG=1, Middle DOUBLE(8,2) FLAG=1,
Last DOUBLE(8,2) FLAG=1) Last DOUBLE(8,2) FLAG=1)
ENGINE=CONNECT TABLE_TYPE=PIVOT 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'; 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 --replace_result $PORT PORT
--eval ALTER TABLE pivex OPTION_LIST='PivotCol=wk,FncCol=amnt,port=$PORT' --eval ALTER TABLE pivex OPTION_LIST='PivotCol=wk,FncCol=amnt,port=$PORT'
SELECT * FROM pivex; SELECT * FROM pivex;
DROP TABLE pivex; DROP TABLE pivex;
DROP TABLE expenses; DROP TABLE expenses;
--echo # --echo #
--echo # Make the PETS table --echo # Make the PETS table
--echo # --echo #
CREATE TABLE pets ( CREATE TABLE pets (
Name VARCHAR(12) NOT NULL, Name VARCHAR(12) NOT NULL,
Race CHAR(6) NOT NULL, Race CHAR(6) NOT NULL,
Number INT NOT NULL) ENGINE=MYISAM; Number INT NOT NULL) ENGINE=MYISAM;
INSERT INTO pets VALUES('John','dog',2); INSERT INTO pets VALUES('John','dog',2);
INSERT INTO pets VALUES('Bill','cat',1); INSERT INTO pets VALUES('Bill','cat',1);
INSERT INTO pets VALUES('Mary','dog',1); INSERT INTO pets VALUES('Mary','dog',1);
INSERT INTO pets VALUES('Mary','cat',1); INSERT INTO pets VALUES('Mary','cat',1);
INSERT INTO pets VALUES('Lisbeth','rabbit',2); INSERT INTO pets VALUES('Lisbeth','rabbit',2);
INSERT INTO pets VALUES('Kevin','cat',2); INSERT INTO pets VALUES('Kevin','cat',2);
INSERT INTO pets VALUES('Kevin','bird',6); INSERT INTO pets VALUES('Kevin','bird',6);
INSERT INTO pets VALUES('Donald','dog',1); INSERT INTO pets VALUES('Donald','dog',1);
INSERT INTO pets VALUES('Donald','fish',3); INSERT INTO pets VALUES('Donald','fish',3);
SELECT * FROM pets; SELECT * FROM pets;
--echo # --echo #
--echo # Pivot the PETS table --echo # Pivot the PETS table
--echo # --echo #
CREATE TABLE pivet ( CREATE TABLE pivet (
name VARCHAR(12) NOT NULL, name VARCHAR(12) NOT NULL,
dog INT NOT NULL DEFAULT 0 FLAG=1, dog INT NOT NULL DEFAULT 0 FLAG=1,
cat INT NOT NULL DEFAULT 0 FLAG=1, cat INT NOT NULL DEFAULT 0 FLAG=1,
rabbit INT NOT NULL DEFAULT 0 FLAG=1, rabbit INT NOT NULL DEFAULT 0 FLAG=1,
bird INT NOT NULL DEFAULT 0 FLAG=1, bird INT NOT NULL DEFAULT 0 FLAG=1,
fish 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'; ENGINE=CONNECT TABLE_TYPE=PIVOT TABNAME=pets OPTION_LIST='PivotCol=race,groupby=1';
SELECT * FROM pivet; SELECT * FROM pivet;
DROP TABLE pivet; DROP TABLE pivet;
--echo # --echo #
--echo # Testing the "data" column list --echo # Testing the "data" column list
--echo # --echo #
CREATE TABLE pivet ( CREATE TABLE pivet (
name VARCHAR(12) NOT NULL, name VARCHAR(12) NOT NULL,
dog INT NOT NULL DEFAULT 0 FLAG=1, dog INT NOT NULL DEFAULT 0 FLAG=1,
cat 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'; ENGINE=CONNECT TABLE_TYPE=PIVOT TABNAME=pets OPTION_LIST='PivotCol=race,groupby=1';
--error ER_GET_ERRMSG --error ER_GET_ERRMSG
SELECT * FROM pivet; SELECT * FROM pivet;
ALTER TABLE pivet OPTION_LIST='PivotCol=race,groupby=1,accept=1'; ALTER TABLE pivet OPTION_LIST='PivotCol=race,groupby=1,accept=1';
SELECT * FROM pivet; SELECT * FROM pivet;
DROP TABLE pivet; DROP TABLE pivet;
--echo # --echo #
--echo # Adding a "dump" column --echo # Adding a "dump" column
--echo # --echo #
CREATE TABLE pivet ( CREATE TABLE pivet (
name VARCHAR(12) NOT NULL, name VARCHAR(12) NOT NULL,
dog INT NOT NULL DEFAULT 0 FLAG=1, dog INT NOT NULL DEFAULT 0 FLAG=1,
cat INT NOT NULL DEFAULT 0 FLAG=1, cat INT NOT NULL DEFAULT 0 FLAG=1,
other INT NOT NULL DEFAULT 0 FLAG=2) other INT NOT NULL DEFAULT 0 FLAG=2)
ENGINE=CONNECT TABLE_TYPE=PIVOT TABNAME=pets OPTION_LIST='PivotCol=race,groupby=1'; ENGINE=CONNECT TABLE_TYPE=PIVOT TABNAME=pets OPTION_LIST='PivotCol=race,groupby=1';
SELECT * FROM pivet; SELECT * FROM pivet;
DROP TABLE pivet; DROP TABLE pivet;
DROP TABLE pets; DROP TABLE pets;
--remove_file $MYSQLD_DATADIR/test/expenses.txt
--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
...@@ -153,6 +153,9 @@ PGLOBAL PlugInit(LPCSTR Language, uint worksize) ...@@ -153,6 +153,9 @@ PGLOBAL PlugInit(LPCSTR Language, uint worksize)
g->Trace = 0; g->Trace = 0;
g->Createas = 0; g->Createas = 0;
g->Alchecked = 0; g->Alchecked = 0;
#if defined(MRRBKA_SUPPORT)
g->Mrr = 0;
#endif // MRRBKA_SUPPORT
g->Activityp = g->ActivityStart = NULL; g->Activityp = g->ActivityStart = NULL;
g->Xchk = NULL; g->Xchk = NULL;
strcpy(g->Message, ""); strcpy(g->Message, "");
......
...@@ -1144,9 +1144,6 @@ MYSQLCOL::MYSQLCOL(MYSQL_FIELD *fld, PTDB tdbp, int i, PSZ am) ...@@ -1144,9 +1144,6 @@ MYSQLCOL::MYSQLCOL(MYSQL_FIELD *fld, PTDB tdbp, int i, PSZ am)
ColUse = U_P; ColUse = U_P;
Nullable = !IS_NOT_NULL(fld->flags); Nullable = !IS_NOT_NULL(fld->flags);
if (Buf_Type == TYPE_DECIM)
Precision = ((Field_new_decimal*)fld)->precision;
// Set additional MySQL access method information for column. // Set additional MySQL access method information for column.
Bind = NULL; Bind = NULL;
To_Val = NULL; To_Val = NULL;
......
...@@ -405,7 +405,7 @@ bool TDBPIVOT::GetSourceTable(PGLOBAL g) ...@@ -405,7 +405,7 @@ bool TDBPIVOT::GetSourceTable(PGLOBAL g)
strcat(colist, Picol); strcat(colist, Picol);
// Now we know how much was suballocated // Now we know how much was suballocated
PlugSubAlloc(g, NULL, strlen(colist)); PlugSubAlloc(g, NULL, strlen(colist) + 1);
// Locate the source string (size is not known yet) // Locate the source string (size is not known yet)
Tabsrc = (char*)PlugSubAlloc(g, NULL, 0); Tabsrc = (char*)PlugSubAlloc(g, NULL, 0);
...@@ -423,7 +423,7 @@ bool TDBPIVOT::GetSourceTable(PGLOBAL g) ...@@ -423,7 +423,7 @@ bool TDBPIVOT::GetSourceTable(PGLOBAL g)
strcat(strcat(Tabsrc, " ORDER BY "), colist); strcat(strcat(Tabsrc, " ORDER BY "), colist);
// Now we know how much was suballocated // Now we know how much was suballocated
PlugSubAlloc(g, NULL, strlen(Tabsrc)); PlugSubAlloc(g, NULL, strlen(Tabsrc) + 1);
} // endif !GBdone } // endif !GBdone
} else if (!Tabsrc) { } else if (!Tabsrc) {
......
...@@ -147,6 +147,9 @@ bool user_connect::CheckCleanup(void) ...@@ -147,6 +147,9 @@ bool user_connect::CheckCleanup(void)
g->Xchk = NULL; g->Xchk = NULL;
g->Createas = 0; g->Createas = 0;
g->Alchecked = 0; g->Alchecked = 0;
#if defined(MRRBKA_SUPPORT)
g->Mrr = 0;
#endif // MRRBKA_SUPPORT
last_query_id= thdp->query_id; last_query_id= thdp->query_id;
if (xtrace) if (xtrace)
......
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