Commit d95e797c authored by Olivier Bertrand's avatar Olivier Bertrand

- FIX MDEV-6019 and MDEV-6021

  Exhausted memory cause un-prepared long jump
  Issue proper message when PIVOT column is nullable
modified:
  storage/connect/mysql-test/connect/r/pivot.result
  storage/connect/mysql-test/connect/t/pivot.test
  storage/connect/plgdbsem.h
  storage/connect/tabpivot.cpp

- Prepare adding index_prev (not used yet)
modified:
  storage/connect/plgdbsem.h
  storage/connect/xindex.cpp
  storage/connect/xindex.h
parent 3f361af7
...@@ -229,7 +229,7 @@ DROP TABLE pets; ...@@ -229,7 +229,7 @@ DROP TABLE pets;
# #
CREATE TABLE fruit ( CREATE TABLE fruit (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT, `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(32) DEFAULT NULL, `name` varchar(32) NOT NULL,
`cnt` int(11) DEFAULT NULL, `cnt` int(11) DEFAULT NULL,
PRIMARY KEY (`id`) PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=6 DEFAULT CHARSET=latin1; ) ENGINE=MyISAM AUTO_INCREMENT=6 DEFAULT CHARSET=latin1;
......
-- 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;
--echo # --echo #
--echo # MDEV-5734 --echo # MDEV-5734
--echo # --echo #
CREATE TABLE fruit ( CREATE TABLE fruit (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT, `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(32) DEFAULT NULL, `name` varchar(32) NOT NULL,
`cnt` int(11) DEFAULT NULL, `cnt` int(11) DEFAULT NULL,
PRIMARY KEY (`id`) PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=6 DEFAULT CHARSET=latin1; ) 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); INSERT INTO fruit VALUES (1,'apple',1),(2,'banana',1),(3,'apple',2),(4,'cherry',4),(5,'durazno',2);
SELECT * FROM fruit; SELECT * FROM fruit;
CREATE TABLE fruit_pivot ENGINE=CONNECT TABLE_TYPE=pivot TABNAME=fruit; CREATE TABLE fruit_pivot ENGINE=CONNECT TABLE_TYPE=pivot TABNAME=fruit;
SELECT * FROM fruit_pivot; SELECT * FROM fruit_pivot;
DROP TABLE fruit_pivot; DROP TABLE fruit_pivot;
DROP TABLE fruit; DROP TABLE fruit;
--remove_file $MYSQLD_DATADIR/test/expenses.txt --remove_file $MYSQLD_DATADIR/test/expenses.txt
...@@ -291,6 +291,7 @@ enum OPVAL {OP_EQ = 1, /* Filtering operator = */ ...@@ -291,6 +291,7 @@ enum OPVAL {OP_EQ = 1, /* Filtering operator = */
OP_CURDT = 113, /* Scalar function Op CurDate */ OP_CURDT = 113, /* Scalar function Op CurDate */
OP_NWEEK = 114, /* Scalar function Op Week number*/ OP_NWEEK = 114, /* Scalar function Op Week number*/
OP_ROW = 115, /* Scalar function Op Row */ OP_ROW = 115, /* Scalar function Op Row */
OP_PREV = 116, /* Index operator Find Previous */
OP_SYSTEM = 200, /* Scalar function Op System */ OP_SYSTEM = 200, /* Scalar function Op System */
OP_REMOVE = 201, /* Scalar function Op Remove */ OP_REMOVE = 201, /* Scalar function Op Remove */
OP_RENAME = 202, /* Scalar function Op Rename */ OP_RENAME = 202, /* Scalar function Op Rename */
......
...@@ -96,10 +96,21 @@ PIVAID::PIVAID(const char *tab, const char *src, const char *picol, ...@@ -96,10 +96,21 @@ PIVAID::PIVAID(const char *tab, const char *src, const char *picol,
PQRYRES PIVAID::MakePivotColumns(PGLOBAL g) PQRYRES PIVAID::MakePivotColumns(PGLOBAL g)
{ {
char *query, *colname, buf[64]; char *query, *colname, buf[64];
int ndif, nblin, w = 0; int rc, ndif, nblin, w = 0;
bool b = false;
PVAL valp; PVAL valp;
PCOLRES *pcrp, crp, fncrp = NULL; 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) { if (!Tabsrc && Tabname) {
// Locate the query // Locate the query
query = (char*)PlugSubAlloc(g, NULL, strlen(Tabname) + 16); query = (char*)PlugSubAlloc(g, NULL, strlen(Tabname) + 16);
...@@ -113,16 +124,17 @@ PQRYRES PIVAID::MakePivotColumns(PGLOBAL g) ...@@ -113,16 +124,17 @@ PQRYRES PIVAID::MakePivotColumns(PGLOBAL g)
// Open a MySQL connection for this table // Open a MySQL connection for this table
if (Myc.Open(g, Host, Database, User, Pwd, Port)) if (Myc.Open(g, Host, Database, User, Pwd, Port))
return NULL; return NULL;
else
b = true;
// Send the source command to MySQL // Send the source command to MySQL
if (Myc.ExecSQL(g, query, &w) == RC_FX) { if (Myc.ExecSQL(g, query, &w) == RC_FX)
Myc.Close(); goto err;
return NULL;
} // endif Exec
// We must have a storage query to get pivot column values // We must have a storage query to get pivot column values
Qryp = Myc.GetResult(g, true); Qryp = Myc.GetResult(g, true);
Myc.Close(); Myc.Close();
b = false;
if (!Fncol) { if (!Fncol) {
for (crp = Qryp->Colresp; crp; crp = crp->Next) for (crp = Qryp->Colresp; crp; crp = crp->Next)
...@@ -152,6 +164,11 @@ PQRYRES PIVAID::MakePivotColumns(PGLOBAL g) ...@@ -152,6 +164,11 @@ PQRYRES PIVAID::MakePivotColumns(PGLOBAL g)
// Prepare the column list // Prepare the column list
for (pcrp = &Qryp->Colresp; crp = *pcrp; ) for (pcrp = &Qryp->Colresp; crp = *pcrp; )
if (!stricmp(Picol, crp->Name)) { 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; Rblkp = crp->Kdata;
*pcrp = crp->Next; *pcrp = crp->Next;
} else if (!stricmp(Fncol, crp->Name)) { } else if (!stricmp(Fncol, crp->Name)) {
...@@ -218,6 +235,12 @@ PQRYRES PIVAID::MakePivotColumns(PGLOBAL g) ...@@ -218,6 +235,12 @@ PQRYRES PIVAID::MakePivotColumns(PGLOBAL g)
// We added ndif columns and removed 2 (picol and fncol) // We added ndif columns and removed 2 (picol and fncol)
Qryp->Nbcol += (ndif - 2); Qryp->Nbcol += (ndif - 2);
return Qryp; return Qryp;
err:
if (b)
Myc.Close();
return NULL;
} // end of MakePivotColumns } // end of MakePivotColumns
/***********************************************************************/ /***********************************************************************/
......
...@@ -1574,6 +1574,46 @@ bool XINDEX::NextVal(bool eq) ...@@ -1574,6 +1574,46 @@ bool XINDEX::NextVal(bool eq)
return (Cur_K == Num_K || (eq && neq <= Nval)); return (Cur_K == Num_K || (eq && neq <= Nval));
} // end of NextVal } // end of NextVal
/***********************************************************************/
/* XINDEX: Find Cur_K and Val_K's of previous index entry. */
/* Returns false if Ok, true if there are no more values. */
/***********************************************************************/
bool XINDEX::PrevVal(void)
{
int n, neq = Nk + 1, curk;
PXCOL kcp;
if (Cur_K == 0)
return true;
else
curk = --Cur_K;
for (n = Nk, kcp = To_LastCol; kcp; n--, kcp = kcp->Previous) {
if (kcp->Kof) {
if (curk < kcp->Kof[kcp->Val_K])
neq = n;
} else {
#ifdef _DEBUG
assert(curk == kcp->Val_K -1);
#endif // _DEBUG
neq = n;
} // endif Kof
#ifdef _DEBUG
assert(kcp->Val_K >= 0);
#endif // _DEBUG
// If this is not a break...
if (neq > n)
break; // all previous columns have same value
curk = --kcp->Val_K; // This is a break, get new column value
} // endfor kcp
return false;
} // end of PrevVal
/***********************************************************************/ /***********************************************************************/
/* XINDEX: Fetch a physical or logical record. */ /* XINDEX: Fetch a physical or logical record. */
/***********************************************************************/ /***********************************************************************/
...@@ -1870,6 +1910,25 @@ int XINDXS::GroupSize(void) ...@@ -1870,6 +1910,25 @@ int XINDXS::GroupSize(void)
: 1; : 1;
} // end of GroupSize } // end of GroupSize
/***********************************************************************/
/* XINDXS: Find Cur_K and Val_K of previous index value. */
/* Returns false if Ok, true if there are no more values. */
/***********************************************************************/
bool XINDXS::PrevVal(void)
{
if (--Cur_K < 0)
return true;
if (Mul) {
if (Cur_K < Pof[To_KeyCol->Val_K])
To_KeyCol->Val_K--;
} else
To_KeyCol->Val_K = Cur_K;
return false;
} // end of PrevVal
/***********************************************************************/ /***********************************************************************/
/* XINDXS: Find Cur_K and Val_K of next index value. */ /* XINDXS: Find Cur_K and Val_K of next index value. */
/* If b is true next value must be equal to last one. */ /* If b is true next value must be equal to last one. */
...@@ -1914,16 +1973,16 @@ int XINDXS::Fetch(PGLOBAL g) ...@@ -1914,16 +1973,16 @@ int XINDXS::Fetch(PGLOBAL g)
/* Table read through a sorted index. */ /* Table read through a sorted index. */
/*********************************************************************/ /*********************************************************************/
switch (Op) { switch (Op) {
case OP_NEXT: // Read next case OP_NEXT: // Read next
if (NextVal(false)) if (NextVal(false))
return -1; // End of indexed file return -1; // End of indexed file
break; break;
case OP_FIRST: // Read first case OP_FIRST: // Read first
To_KeyCol->Val_K = Cur_K = 0; To_KeyCol->Val_K = Cur_K = 0;
Op = OP_NEXT; Op = OP_NEXT;
break; break;
case OP_SAME: // Read next same case OP_SAME: // Read next same
#if defined(TRACE) #if defined(TRACE)
// printf("looking for next same value\n"); // printf("looking for next same value\n");
#endif // TRACE #endif // TRACE
...@@ -1934,7 +1993,7 @@ int XINDXS::Fetch(PGLOBAL g) ...@@ -1934,7 +1993,7 @@ int XINDXS::Fetch(PGLOBAL g)
} // endif Mul } // endif Mul
break; break;
case OP_NXTDIF: // Read next dif case OP_NXTDIF: // Read next dif
if (++To_KeyCol->Val_K == Ndif) if (++To_KeyCol->Val_K == Ndif)
return -1; // End of indexed file return -1; // End of indexed file
...@@ -1946,10 +2005,15 @@ int XINDXS::Fetch(PGLOBAL g) ...@@ -1946,10 +2005,15 @@ int XINDXS::Fetch(PGLOBAL g)
break; break;
case OP_LAST: // Read first case OP_LAST: // Read first
Cur_K = Num_K - 1; Cur_K = Num_K - 1;
To_KeyCol->Val_K = To_KeyCol->Kblp->GetNval() - 1; To_KeyCol->Val_K = Ndif - 1;
Op = OP_NEXT; Op = OP_PREV;
break;
case OP_PREV: // Read previous
if (PrevVal())
return -1; // End of indexed file
break; break;
default: // Should OP_EQ default: // Should be OP_EQ
/*****************************************************************/ /*****************************************************************/
/* Look for the first key equal to the link column values */ /* Look for the first key equal to the link column values */
/* and return its rank whithin the index table. */ /* and return its rank whithin the index table. */
......
...@@ -198,6 +198,7 @@ class DllExport XXBASE : public CSORT, public BLOCK { ...@@ -198,6 +198,7 @@ class DllExport XXBASE : public CSORT, public BLOCK {
virtual int MaxRange(void) {return 1;} virtual int MaxRange(void) {return 1;}
virtual int Fetch(PGLOBAL g) = 0; virtual int Fetch(PGLOBAL g) = 0;
virtual bool NextVal(bool eq) {return true;} virtual bool NextVal(bool eq) {return true;}
virtual bool PrevVal(void) {return true;}
virtual int FastFind(int nk) = 0; virtual int FastFind(int nk) = 0;
virtual bool Reorder(PGLOBAL g) {return true;} virtual bool Reorder(PGLOBAL g) {return true;}
virtual int Range(PGLOBAL g, int limit = 0, bool incl = true) virtual int Range(PGLOBAL g, int limit = 0, bool incl = true)
...@@ -209,22 +210,22 @@ class DllExport XXBASE : public CSORT, public BLOCK { ...@@ -209,22 +210,22 @@ class DllExport XXBASE : public CSORT, public BLOCK {
protected: protected:
// Members // Members
PTDBASE Tbxp; // Points to calling table TDB PTDBASE Tbxp; // Points to calling table TDB
PXCOL To_KeyCol; // To KeyCol class list PXCOL To_KeyCol; // To KeyCol class list
MBLOCK Record; // Record allocation block MBLOCK Record; // Record allocation block
int* &To_Rec; // We are using ftell, fseek int* &To_Rec; // We are using ftell, fseek
int Cur_K; // Index of current record int Cur_K; // Index of current record
int Old_K; // Index of last record int Old_K; // Index of last record
int Num_K; // Size of Rec_K pointer array int Num_K; // Size of Rec_K pointer array
int Ndif; // Number of distinct values int Ndif; // Number of distinct values
int Bot; // Bottom of research index int Bot; // Bottom of research index
int Top; // Top of research index int Top; // Top of research index
int Inf, Sup; // Used for block optimization int Inf, Sup; // Used for block optimization
OPVAL Op; // Search operator OPVAL Op; // Search operator
bool Mul; // true if multiple bool Mul; // true if multiple
bool Srtd; // true for sorted column bool Srtd; // true for sorted column
int Val_K; // Index of current value int Val_K; // Index of current value
int Nblk; // Number of blocks int Nblk; // Number of blocks
int Sblk; // Block size int Sblk; // Block size
int Thresh; // Thresh for sorting join indexes int Thresh; // Thresh for sorting join indexes
int ID; // Index ID number int ID; // Index ID number
int Nth; // Nth constant to fetch int Nth; // Nth constant to fetch
...@@ -263,6 +264,7 @@ class DllExport XINDEX : public XXBASE { ...@@ -263,6 +264,7 @@ class DllExport XINDEX : public XXBASE {
virtual int ColMaxSame(PXCOL kp); virtual int ColMaxSame(PXCOL kp);
virtual void Close(void); virtual void Close(void);
virtual bool NextVal(bool eq); virtual bool NextVal(bool eq);
virtual bool PrevVal(void);
virtual bool Make(PGLOBAL g, PIXDEF sxp); virtual bool Make(PGLOBAL g, PIXDEF sxp);
virtual bool SaveIndex(PGLOBAL g, PIXDEF sxp); virtual bool SaveIndex(PGLOBAL g, PIXDEF sxp);
virtual bool Reorder(PGLOBAL g); virtual bool Reorder(PGLOBAL g);
...@@ -302,6 +304,7 @@ class DllExport XINDXS : public XINDEX { ...@@ -302,6 +304,7 @@ class DllExport XINDXS : public XINDEX {
virtual int Fetch(PGLOBAL g); virtual int Fetch(PGLOBAL g);
virtual int FastFind(int nk); virtual int FastFind(int nk);
virtual bool NextVal(bool eq); virtual bool NextVal(bool eq);
virtual bool PrevVal(void);
virtual int Range(PGLOBAL g, int limit = 0, bool incl = true); virtual int Range(PGLOBAL g, int limit = 0, bool incl = true);
virtual int GroupSize(void); virtual int GroupSize(void);
......
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