mirror of
https://github.com/MariaDB/server.git
synced 2025-08-08 11:22:35 +03:00
- 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
This commit is contained in:
@@ -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;
|
||||||
|
@@ -1,163 +1,163 @@
|
|||||||
-- 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 = */
|
|||||||
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,
|
|||||||
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)
|
|||||||
// 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)
|
|||||||
// 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)
|
|||||||
// 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)
|
|||||||
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)
|
|||||||
: 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)
|
|||||||
/* 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)
|
|||||||
} // 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)
|
|||||||
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;
|
break;
|
||||||
default: // Should OP_EQ
|
case OP_PREV: // Read previous
|
||||||
|
if (PrevVal())
|
||||||
|
return -1; // End of indexed file
|
||||||
|
|
||||||
|
break;
|
||||||
|
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 {
|
|||||||
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 {
|
|||||||
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 {
|
|||||||
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 {
|
|||||||
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);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user