1
0
mirror of https://github.com/mariadb-corporation/mariadb-columnstore-engine.git synced 2025-07-01 06:21:41 +03:00
Files
Sergey Zefirov b53c231ca6 MCOL-271 empty strings should not be NULLs (#2794)
This patch improves handling of NULLs in textual fields in ColumnStore.
Previously empty strings were considered NULLs and it could be a problem
if data scheme allows for empty strings. It was also one of major
reasons of behavior difference between ColumnStore and other engines in
MariaDB family.

Also, this patch fixes some other bugs and incorrect behavior, for
example, incorrect comparison for "column <= ''" which evaluates to
constant True for all purposes before this patch.
2023-03-30 21:18:29 +03:00

1047 lines
21 KiB
C++

/* Copyright (C) 2014 InfiniDB, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2 of
the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA. */
/***********************************************************************
* $Id: dmlpkg.h 9210 2013-01-21 14:10:42Z rdempsey $
*
*
***********************************************************************/
/** @file */
#pragma once
#include <vector>
#include <string>
#include <map>
#include <utility>
#include <iostream>
#include <bitset>
#include <stdint.h>
#include "nullstring.h"
namespace dmlpackage
{
class DeleteSqlStatement;
class UpdateSqlStatement;
class InsertSqlStatement;
class SqlStatement;
class SqlStatementList;
class TableName;
class ValuesOrQuery;
class QuerySpec;
class TableExpression;
class WhereClause;
class SearchCondition;
class ExistanceTestPredicate;
class AllOrAnyPredicate;
class InPredicate;
class NullTestPredicate;
class LikePredicate;
class BetweenPredicate;
class ComparisonPredicate;
class Predicate;
class FromClause;
class SelectFilter;
class GroupByClause;
class HavingClause;
class Escape;
class ColumnAssignment;
typedef std::vector<TableName*> TableNameList;
typedef std::vector<ColumnAssignment*> ColumnAssignmentList;
typedef std::vector<std::string> ColumnNameList;
typedef std::vector<std::string> ValuesList;
typedef std::vector<std::string> AtomList;
typedef std::vector<char*> QueryBuffer;
typedef std::vector<utils::NullString> ColValuesList;
typedef std::vector<std::string> ColNameList;
typedef std::map<uint32_t, ColValuesList> TableValuesMap;
typedef std::bitset<4096> NullValuesBitset;
std::ostream& operator<<(std::ostream& os, const SqlStatementList& ct);
std::ostream& operator<<(std::ostream& os, const SqlStatement& stmt);
/** @brief Predicate types
*/
enum PREDICATE_TYPE
{
COMPARE_PREDICATE,
BETWEEN_PREDICATE,
LIKE_PREDICATE,
NULLTEST_PREDICATE,
IN_PREDICATE,
ALLORANY_PREDICATE,
EXIST_PREDICATE,
INVALID_PREDICATE
};
/** @brief DML Statement types
*/
enum DML_TYPE
{
DML_INSERT,
DML_UPDATE,
DML_DELETE,
DML_COMMAND,
DML_INVALID_TYPE
};
/** @brief SqlStatement represents a toplevel
* syntactic element such as a insert, update or delete SQL
* statement.
*
* SqlStatements are containers for the various structures
* manufactured by the parsing process for a single SQL
* statement.
*/
class SqlStatement
{
public:
/** @brief ctor
*/
SqlStatement();
/** @brief dtor
*/
virtual ~SqlStatement();
/** @brief dump to stdout.
*/
virtual std::ostream& put(std::ostream& os) const = 0;
/** @brief get the query string associated with the
* SqlStatement
*/
virtual std::string getQueryString() const = 0;
/** @brief get the statement type
*/
virtual int getStatementType() const = 0;
/** @brief get the schema name from the
* TableName data member
*/
virtual std::string getSchemaName() const;
/** @brief get the table name from the
* TableName data member
*/
virtual std::string getTableName() const;
TableName* fNamePtr;
};
/** @brief Collects SqlStatements so that we can support the
* parsing of sqltext containing multiple statements.
*
* The SqlParser also accepts empty statements (a mixture of
* whitespace and semicolons) in which case the result can be a
* SqlStatementList of zero items.
*/
class SqlStatementList
{
public:
/** @brief ctor
*/
SqlStatementList()
{
}
/** @brief dtor
*/
virtual ~SqlStatementList();
/** @brief get the SqlStatement at the given index
*
* @param i the index
*/
SqlStatement* operator[](int i) const
{
return fList[i];
}
/** @brief push the supplied SqlStatement pointer onto the list
*
* @param v a pointer to a SqlStatement
*/
void push_back(SqlStatement* v);
std::vector<SqlStatement*> fList;
std::string fSqlText;
private:
SqlStatementList(const SqlStatementList& x);
};
/** @brief The representation of a parsed
* INSERT statement
*
* insert_statement:
* INSERT INTO table opt_column_commalist values_or_query_spec
*/
class InsertSqlStatement : public SqlStatement
{
public:
/** @brief ctor
*/
InsertSqlStatement();
/** @brief ctor
*
* @param tableNamePtr pointer to a TableName object
* @param valsOrQueryPtr pointer to a ValuesOrQueryObject
*/
InsertSqlStatement(TableName* tableNamePtr, ValuesOrQuery* valsOrQueryPtr);
/** @brief ctor
*
* @param tableNamePtr pointer to a TableName object
* @param columnNamesPtr pointer to ColumnNamesList object
* @param valsOrQueryPtr pointer to ValuesOrQueryObject
*/
InsertSqlStatement(TableName* tableNamePtr, ColumnNameList* columnNamesPtr, ValuesOrQuery* valsOrQueryPtr);
/** @brief dtor
*/
virtual ~InsertSqlStatement();
/** @brief dump to stdout
*/
virtual std::ostream& put(std::ostream& os) const;
/** @brief get a string representation of the query spec
*/
virtual std::string getQueryString() const;
/** @brief get the statement type - DML_INSERT
*/
inline virtual int getStatementType() const
{
return DML_INSERT;
}
ValuesOrQuery* fValuesOrQueryPtr;
ColumnNameList fColumnList;
};
/** @brief The representation of a parsed
* UPDATE statement
*
* update_statement_searched:
* UPDATE table SET assignment_commalist opt_where_clause
*/
class UpdateSqlStatement : public SqlStatement
{
public:
/** @brief ctor
*/
UpdateSqlStatement();
/** @brief ctor
*
* @param tableNamePtr pointer to a TableName object
* @param colAssignmentPtr pointer to a ColumnAssignmentList object
* @param whereClausePtr pointer to a WhereClause object - default 0
*/
UpdateSqlStatement(TableName* tableNamePtr, ColumnAssignmentList* colAssignmentListPtr,
WhereClause* whereClausePtr = 0);
/** @brief dtor
*/
virtual ~UpdateSqlStatement();
/** @brief dump to stdout
*/
virtual std::ostream& put(std::ostream& os) const;
/** @brief get the string representation of the
* SET assignment_commalist opt_where_clause
* statement
*/
virtual std::string getQueryString() const;
/** @brief get the statement type - DML_UPDATE
*/
inline virtual int getStatementType() const
{
return DML_UPDATE;
}
ColumnAssignmentList* fColAssignmentListPtr;
WhereClause* fWhereClausePtr;
};
/** @brief The representation of a parsed
* DELETE statement
*
* delete_statement_searched:
* DELETE FROM table opt_where_clause
*/
class DeleteSqlStatement : public SqlStatement
{
public:
/** @brief ctor
*/
DeleteSqlStatement();
/** @brief ctor
*
* @param tableNamePtr pointer to a TableName object
* @param whereClausePtr pointer to a WhereClause object - default = 0
*/
DeleteSqlStatement(TableName* tableNamePtr, WhereClause* whereClausePtr = 0);
/** @brief dtor
*/
virtual ~DeleteSqlStatement();
/** @brief dump to stdout
*/
virtual std::ostream& put(std::ostream& os) const;
/** @brief get the string representation of the WHERE clause
*/
virtual std::string getQueryString() const;
/** @brief get the statement type - DML_DELETE
*/
inline virtual int getStatementType() const
{
return DML_DELETE;
}
WhereClause* fWhereClausePtr;
};
/** @brief The representation of a parsed
* COMMIT or ROLLBACK statement
*
* commit_statement:
* COMMIT WORK
* | COMMIT
*
* rollback_statement:
* ROLLBACK WORK
`* | ROLLBACK
*/
class CommandSqlStatement : public SqlStatement
{
public:
/** @brief ctor
*
* @param command the COMMIT or ROLLBACK string
*/
CommandSqlStatement(std::string command);
/** @brief get the statement type - DML_COMMAND
*/
inline virtual int getStatementType() const
{
return DML_COMMAND;
}
/** @brief dump to stdout
*/
virtual std::ostream& put(std::ostream& os) const;
/** @brief get the COMMIT or ROLLBACK string
*/
virtual std::string getQueryString() const;
std::string fCommandText;
};
/** @brief Stores schema, object names.
*
*/
class TableName
{
public:
/** @brief ctor
*/
TableName();
/** @brief ctor
*
* @param name the table name
*/
TableName(char* name);
/** @brief ctor
*
* @param schema the schema name
* @param name the table name
*/
TableName(char* shema, char* name);
/** @brief dump to stdout
*/
std::ostream& put(std::ostream& os) const;
std::string fName;
std::string fSchema;
};
/** @brief Stores a column assignment
*
* assignment:
* column '=' scalar_exp
* | column '=' NULLX
*/
class ColumnAssignment
{
public:
explicit ColumnAssignment(std::string const& column, std::string const& op = "=",
std::string const& expr = "")
: fColumn(column)
, fOperator(op)
, fScalarExpression(expr)
, fFromCol(false)
, fFuncScale(0)
, fIsNull(false){};
/** @brief dump to stdout
*/
std::ostream& put(std::ostream& os) const;
/** @brief get the string representation of
* the column assignment
*/
std::string getColumnAssignmentString() const;
std::string fColumn;
std::string fOperator;
std::string fScalarExpression;
bool fFromCol;
uint32_t fFuncScale;
bool fIsNull;
};
/** @brief Stores a value list or a query specification
*
* values_or_query_spec:
* VALUES '(' insert_atom_commalist ')'
* | query_spec
*/
class ValuesOrQuery
{
public:
/** @brief ctor
*/
ValuesOrQuery();
/** @brief ctor
*
* @param valuesPtr pointer to a ValuesList object
*/
ValuesOrQuery(ValuesList* valuesPtr);
/** @brief ctor
*
* @param querySpecPtr pointer to a QuerySpec object
*/
ValuesOrQuery(QuerySpec* querySpecPtr);
/** @brief dtor
*/
~ValuesOrQuery();
/** @brief dump to stdout
*/
std::ostream& put(std::ostream& os) const;
/** @brief get the string reperesentation of
* the ValuesList or the QuerySpec
*/
std::string getQueryString() const;
ValuesList fValuesList;
QuerySpec* fQuerySpecPtr;
};
/** @brief Stores a SELECT filter
*
* selection:
* scalar_exp_commalist
* | '*'
*/
class SelectFilter
{
public:
/** @brief ctor
*/
SelectFilter();
/** @brief ctor
*
* @param columnListPtr pointer to a ColumnNameList object
*/
SelectFilter(ColumnNameList* columnListPtr);
/** @brief dtor
*/
~SelectFilter();
/** @brief dump to stdout
*/
std::ostream& put(std::ostream& os) const;
/** @brief get the string represntation of the SELECT statement
*/
std::string getSelectString() const;
ColumnNameList fColumnList;
};
/** @brief Stores a FROM clause
*
* from_clause:
* FROM table_ref_commalist
*/
class FromClause
{
public:
/** @brief ctor
*/
FromClause();
/** @brief ctor
*
* @param tableNameList pointer to a TableNameList object
*/
FromClause(TableNameList* tableNameList);
/** @brief dtor
*/
~FromClause();
/** @brief dump to stdout
*/
std::ostream& put(std::ostream& os) const;
/** @brief get the string representation of the FROM clause
*/
std::string getFromClauseString() const;
TableNameList* fTableListPtr;
};
/** @brief Stores a WHERE clause
*
* where_clause:
* WHERE search_condition
*/
class WhereClause
{
public:
/** @brief ctor
*/
WhereClause();
/** @brief dtor
*/
~WhereClause();
/** @brief dump to stdout
*/
std::ostream& put(std::ostream& os) const;
/** @brief get the string representation of the WHERE clause
*/
std::string getWhereClauseString() const;
SearchCondition* fSearchConditionPtr;
};
/** @brief Stores a GROUP BY clause
*
* opt_group_by_clause:
* empty
* | GROUP BY column_ref_commalist
*/
class GroupByClause
{
public:
/** @brief ctor
*/
GroupByClause();
/** @brief dtor
*/
~GroupByClause();
/** @brief dump to stdout
*/
std::ostream& put(std::ostream& os) const;
/** @brief get the string representation of the GROUP BY clause
*/
std::string getGroupByClauseString() const;
ColumnNameList* fColumnNamesListPtr;
};
/** @brief Stores a HAVING clause
*
* opt_having_clause:
* empty
* | HAVING search_condition
*/
class HavingClause
{
public:
/** @brief ctor
*/
HavingClause();
/** @brief dtor
*/
~HavingClause();
/** @brief dump to stdout
*/
std::ostream& put(std::ostream& os) const;
/** @brief get the string representation of the HAVING clause
*/
std::string getHavingClauseString() const;
SearchCondition* fSearchConditionPtr;
};
/** @brief Stores an ESCAPE sequence
*
*
* opt_escape:
* empty
* | ESCAPE atom
*/
class Escape
{
public:
/** @brief dump to stdout
*/
std::ostream& put(std::ostream& os) const;
std::string fEscapeChar;
};
/** @brief The base class representaion of a parsed SQL predicate
*
* predicate:
* comparison_predicate
* | between_predicate
* | like_predicate
* | test_for_null
* | in_predicate
* | all_or_any_predicate
* | existence_test
*/
class Predicate
{
public:
/** @brief ctor
*/
Predicate();
/** @brief ctor
*
* @param predicateType the PREDICATE_TYPE
*/
Predicate(PREDICATE_TYPE predicateType);
/** @brief dtor
*/
virtual ~Predicate();
/** @brief dump to stdout
*/
virtual std::ostream& put(std::ostream& os) const;
/** @param get the string representation of the predicate
*/
virtual std::string getPredicateString() const;
PREDICATE_TYPE fPredicateType;
};
/** @brief The representation of a parsed
* Comparison Predicate:
*
* comparison_predicate:
* scalar_exp COMPARISON scalar_exp
* | scalar_exp COMPARISON subquery
*/
class ComparisonPredicate : public Predicate
{
public:
/** @brief ctor
*/
ComparisonPredicate();
/** @brief dtor
*/
~ComparisonPredicate();
/** @brief dump to stdout
*/
virtual std::ostream& put(std::ostream& os) const;
/** @brief get the string representation of the COMPARISON
* predicate
*/
virtual std::string getPredicateString() const;
std::string fLHScalarExpression;
std::string fRHScalarExpression;
std::string fOperator;
QuerySpec* fSubQuerySpec;
};
/** @brief The representation of a parsed
* Between Predicate:
*
* between_predicate:
* scalar_exp NOT BETWEEN scalar_exp AND scalar_exp
* | scalar_exp BETWEEN scalar_exp AND scalar_exp
*/
class BetweenPredicate : public Predicate
{
public:
/** @brief ctor
*/
BetweenPredicate();
/** @brief dtor
*/
~BetweenPredicate();
/** @brief dump to stdout
*/
virtual std::ostream& put(std::ostream& os) const;
/** @brief get the string representation of the BETWEEN
* predicate
*/
virtual std::string getPredicateString() const;
std::string fLHScalarExpression;
std::string fRH1ScalarExpression;
std::string fRH2ScalarExpression;
std::string fOperator1;
std::string fOperator2;
};
/** @brief The representation of a parsed
* Like Predicate:
*
* like_predicate:
* scalar_exp NOT LIKE atom opt_escape
* | scalar_exp LIKE atom opt_escape
*/
class LikePredicate : public Predicate
{
public:
/** @brief ctor
*/
LikePredicate();
/** @brief dtor
*/
~LikePredicate();
/** @brief dump to stdout
*/
virtual std::ostream& put(std::ostream& os) const;
/** @brief get the string representation of the LIKE
* predicate
*/
virtual std::string getPredicateString() const;
std::string fLHScalarExpression;
std::string fAtom;
std::string fOperator;
Escape* fOptionalEscapePtr;
};
/** @brief The representation of a parsed
* Null test Predicate:
*
* test_for_null:
* column_ref IS NOT NULLX
* | column_ref IS NULLX
*/
class NullTestPredicate : public Predicate
{
public:
/** @brief ctor
*/
NullTestPredicate();
/** @brief dtor
*/
~NullTestPredicate();
/** @brief dump to stdout
*/
virtual std::ostream& put(std::ostream& os) const;
/** @brief get the string representation of the NULL test
* predicate
*/
std::string getPredicateString() const;
std::string fColumnRef;
std::string fOperator;
};
/** @brief The representation of a parsed
* In Predicate:
*
* in_predicate:
* scalar_exp NOT IN '(' subquery ')'
* | scalar_exp IN '(' subquery ')'
* | scalar_exp NOT IN '(' atom_commalist ')'
* | scalar_exp IN '(' atom_commalist ')'
*/
class InPredicate : public Predicate
{
public:
/** @brief ctor
*/
InPredicate();
/** @brief dtor
*/
~InPredicate();
/** @brief dump to stdout
*/
virtual std::ostream& put(std::ostream& os) const;
/** @brief get the string representation of the IN
* predicate
*/
virtual std::string getPredicateString() const;
std::string fScalarExpression;
std::string fOperator;
AtomList fAtomList;
QuerySpec* fSubQuerySpecPtr;
};
/** @brief The representation of a parsed
* All Or Any Predicate:
*
* all_or_any_predicate:
* scalar_exp COMPARISON any_all_some subquery
*/
class AllOrAnyPredicate : public Predicate
{
public:
/** @brief ctor
*/
AllOrAnyPredicate();
/** @brief dtor
*/
~AllOrAnyPredicate();
/** @brief dump to stdout
*/
virtual std::ostream& put(std::ostream& os) const;
/** @brief get the string representation of the
* ALL or ANY predicate
*/
virtual std::string getPredicateString() const;
std::string fScalarExpression;
std::string fOperator;
std::string fAnyAllSome;
QuerySpec* fSubQuerySpecPtr;
};
/** @brief The representation of a parsed
* Existance test Predicate:
*
* existence_test:
* EXISTS subquery
*/
class ExistanceTestPredicate : public Predicate
{
public:
/** @brief ctor
*/
ExistanceTestPredicate();
/** @brief dtor
*/
~ExistanceTestPredicate();
/** @brief dump to stdout
*/
virtual std::ostream& put(std::ostream& os) const;
/** @brief get the string representation of the EXISTS
* predicate
*/
virtual std::string getPredicateString() const;
QuerySpec* fSubQuerySpecPtr;
};
/** @brief The representation of a parsed
* Search Condition:
*
* search_condition:
* | search_condition OR search_condition
* | search_condition AND search_condition
* | NOT search_condition
* | '(' search_condition ')'
* | predicate
*/
class SearchCondition
{
public:
/** @brief ctor
*/
SearchCondition();
/** @brief dtor
*/
~SearchCondition();
/** @brief dump to stdout
*/
std::ostream& put(std::ostream& os) const;
/** @brief get the striong representation of the
* search condition
*/
std::string getSearchConditionString() const;
Predicate* fPredicatePtr;
SearchCondition* fLHSearchConditionPtr;
SearchCondition* fRHSearchConditionPtr;
std::string fOperator;
};
/** @brief The representation of a parsed
* Table Expression:
*
* table_exp:
* from_clause
* opt_where_clause
* opt_group_by_clause
* opt_having_clause
*/
class TableExpression
{
public:
/** @brief ctor
*/
TableExpression();
/** @brief ctor
*
* @param fromClausePtr pointer to a FromClause object
* @param whereClausePtr pointer to a WhereClause object
* @param groupByPtr pointer to a GroupByClause object
* @param havingPtr pointer to a HavingClause object
*/
TableExpression(FromClause* fromClausePtr, WhereClause* whereClausePtr, GroupByClause* groupByPtr,
HavingClause* havingPtr);
/** @brief dtor
*/
~TableExpression();
/** @brief dump to stdout
*/
std::ostream& put(std::ostream& os) const;
/** @brief get the string representation of the
* table expression
*/
std::string getTableExpressionString() const;
FromClause* fFromClausePtr;
WhereClause* fWhereClausePtr;
GroupByClause* fGroupByPtr;
HavingClause* fHavingPtr;
};
/** @brief The representation of a parsed
* Query Specification:
*
* query_spec:
* SELECT opt_all_distinct selection table_exp
*/
class QuerySpec
{
public:
/** @brief ctor
*/
QuerySpec();
/** @brief ctor
*
* @param selectFilter pointer to a SelectFilter object
* @param tableExpression pointer to a TableExpression object
*/
QuerySpec(SelectFilter* selectFilter, TableExpression* tableExpression);
/** @brief ctor
*
* @param selectFilter pointer to a SelectFilter object
* @param tableExpression pointer to a TableExpression object
* @param allOrDistinct pointer to a ALL or DISTINCT string
*/
QuerySpec(SelectFilter* selectFilter, TableExpression* tableExpression, char* allOrDistinct);
/** @brief dtor
*/
~QuerySpec();
/** @brief dump to stdout
*/
std::ostream& put(std::ostream& os) const;
/** @brief get the string representation of the
* query specification
*/
std::string getQueryString() const;
SelectFilter* fSelectFilterPtr;
TableExpression* fTableExpressionPtr;
std::string fOptionAllOrDistinct;
};
} // namespace dmlpackage