23#include "expression.h"
25#include "parser/sqlparser.h"
26#include "parser/parser_p.h"
33#include <tqdatetime.h>
37 if (c==KexiDBExpr_Unary)
39 else if (c==KexiDBExpr_Arithm)
41 else if (c==KexiDBExpr_Logical)
43 else if (c==KexiDBExpr_Relational)
45 else if (c==KexiDBExpr_SpecialBinary)
46 return "SpecialBinary";
47 else if (c==KexiDBExpr_Const)
49 else if (c==KexiDBExpr_Variable)
51 else if (c==KexiDBExpr_Function)
53 else if (c==KexiDBExpr_Aggregation)
55 else if (c==KexiDBExpr_TableList)
57 else if (c==KexiDBExpr_QueryParameter)
58 return "QueryParameter";
67BaseExpr::BaseExpr(
int token)
68 : m_cl(KexiDBExpr_Unknown)
83TQString BaseExpr::debugString()
88bool BaseExpr::validate(ParseInfo& )
93extern const char *
const tname(
int offset);
94#define safe_tname(token) ((token>=255 && token<=__LAST_TOKEN) ? tname(token-255) : "")
100 return TQString(TQChar(uchar(token)));
102 return TQString::number(token);
104 return TQString(safe_tname(token));
109 if (m_token < 255 && isprint(m_token))
124NArgExpr::NArgExpr(
int aClass,
int token)
128 list.setAutoDelete(
true);
131NArgExpr::NArgExpr(
const NArgExpr& expr)
134 foreach_list (BaseExpr::ListIterator, it, expr.list)
135 add( it.current()->
copy() );
147TQString NArgExpr::debugString()
149 TQString s = TQString(
"NArgExpr(")
151 for ( BaseExpr::ListIterator it(list); it.current(); ++it ) {
153 s+=it.current()->debugString();
163 foreach_list( BaseExpr::ListIterator, it, list) {
166 s+=it.current()->toString(params);
173 foreach_list( BaseExpr::ListIterator, it, list)
174 it.current()->getQueryParameters(params);
185 expr->setParent(
this);
188void NArgExpr::prepend(
BaseExpr *expr)
191 expr->setParent(
this);
199bool NArgExpr::validate(ParseInfo& parseInfo)
201 if (!BaseExpr::validate(parseInfo))
204 foreach_list(BaseExpr::ListIterator, it, list) {
205 if (!it.current()->validate(parseInfo))
212UnaryExpr::UnaryExpr(
int token,
BaseExpr *arg)
216 m_cl = KexiDBExpr_Unary;
218 m_arg->setParent(
this);
221UnaryExpr::UnaryExpr(
const UnaryExpr& expr)
223 , m_arg( expr.m_arg ? expr.m_arg->copy() : 0 )
226 m_arg->setParent(
this);
229UnaryExpr::~UnaryExpr()
239TQString UnaryExpr::debugString()
243 + (m_arg ? m_arg->debugString() : TQString(
"<NONE>"))
250 return "(" + (m_arg ? m_arg->
toString(params) :
"<NULL>") +
")";
251 if (m_token < 255 && isprint(m_token))
254 return "NOT " + (m_arg ? m_arg->
toString(params) :
"<NULL>");
255 if (m_token==SQL_IS_NULL)
256 return (m_arg ? m_arg->
toString(params) :
"<NULL>") +
" IS NULL";
257 if (m_token==SQL_IS_NOT_NULL)
258 return (m_arg ? m_arg->
toString(params) :
"<NULL>") +
" IS NOT NULL";
259 return TQString(
"{INVALID_OPERATOR#%1} ").arg(m_token) + (m_arg ? m_arg->
toString(params) :
"<NULL>");
274 case SQL_IS_NOT_NULL:
288 if (!BaseExpr::validate(parseInfo))
291 if (!m_arg->validate(parseInfo))
297 if (m_arg->toQueryParameter()) {
298 m_arg->toQueryParameter()->
setType(type());
311 if (is(NOT) && n->nodeTypeIs(TYP_BOOL)) {
312 node_type=
new NConstType(TYP_BOOL);
314 else if (is(
'#') && n->nodeTypeIs(TYP_STR)) {
315 node_type=
new NConstType(TYP_INT);
317 else if ((is(
'+') || is(
'-')) && n->nodeTypeIs(TYP_INT)) {
318 node_type=
new NConstType(TYP_INT);
321 ERR(
"Niepoprawny argument typu '%s' dla operatora '%s'",
322 n->nodeTypeName(),is(NOT)?TQString(
"not"):TQChar(typ()));
328BinaryExpr::BinaryExpr(
int aClass,
BaseExpr *left_expr,
int token,
BaseExpr *right_expr)
335 m_larg->setParent(
this);
337 m_rarg->setParent(
this);
342 , m_larg( expr.m_larg ? expr.m_larg->copy() : 0 )
343 , m_rarg( expr.m_rarg ? expr.m_rarg->copy() : 0 )
347BinaryExpr::~BinaryExpr()
360 if (!BaseExpr::validate(parseInfo))
363 if (!m_larg->validate(parseInfo))
365 if (!m_rarg->validate(parseInfo))
373 queryParameter->
setType(m_rarg->type());
374 queryParameter = m_rarg->toQueryParameter();
376 queryParameter->
setType(m_larg->type());
383 const Field::Type lt = m_larg->type(), rt = m_rarg->type();
392 case BITWISE_SHIFT_RIGHT:
393 case BITWISE_SHIFT_LEFT:
411TQString BinaryExpr::debugString()
413 return TQString(
"BinaryExpr(")
415 +
"," + (m_larg ? m_larg->debugString() : TQString(
"<NONE>"))
417 + (m_rarg ? m_rarg->debugString() : TQString(
"<NONE>"))
423 if (m_token < 255 && isprint(m_token))
427 case BITWISE_SHIFT_RIGHT:
return ">>";
428 case BITWISE_SHIFT_LEFT:
return "<<";
430 case NOT_EQUAL:
return "<>";
431 case NOT_EQUAL2:
return "!=";
432 case LESS_OR_EQUAL:
return "<=";
433 case GREATER_OR_EQUAL:
return ">=";
434 case LIKE:
return "LIKE";
435 case SQL_IN:
return "IN";
437 case SIMILAR_TO:
return "SIMILAR TO";
438 case NOT_SIMILAR_TO:
return "NOT SIMILAR TO";
439 case OR:
return "OR";
440 case AND:
return "AND";
441 case XOR:
return "XOR";
443 case CONCATENATION:
return "||";
448 return TQString(
"{INVALID_BINARY_OPERATOR#%1} ").arg(m_token);
454 (m_larg ? m_larg->toString(params) : "<NULL>") + " " + a + " " + (m_rarg ? m_rarg->toString(params) : "<NULL>")
467ConstExpr::ConstExpr(
int token,
const TQVariant& val)
471 m_cl = KexiDBExpr_Const;
474ConstExpr::ConstExpr(
const ConstExpr& expr)
480ConstExpr::~ConstExpr()
491 if (m_token==SQL_NULL)
493 else if (m_token==INTEGER_CONST) {
496 if (value.type() == TQVariant::Int || value.type() == TQVariant::UInt) {
497 TQ_LLONG v = value.toInt();
498 if (v <= 0xff && v > -0x80)
500 if (v <= 0xffff && v > -0x8000)
506 else if (m_token==CHARACTER_STRING_LITERAL) {
508 if (value.toString().length() > Field::defaultTextLength())
513 else if (m_token==REAL_CONST)
515 else if (m_token==DATE_CONST)
517 else if (m_token==DATETIME_CONST)
518 return Field::DateTime;
519 else if (m_token==TIME_CONST)
525TQString ConstExpr::debugString()
534 if (m_token==SQL_NULL)
536 else if (m_token==CHARACTER_STRING_LITERAL)
538 return "'" + value.toString() +
"'";
539 else if (m_token==REAL_CONST)
540 return TQString::number(value.toPoint().x())+
"."+TQString::number(value.toPoint().y());
541 else if (m_token==DATE_CONST)
542 return "'" + value.toDate().toString(TQt::ISODate) +
"'";
543 else if (m_token==DATETIME_CONST)
544 return "'" + value.toDateTime().date().toString(TQt::ISODate)
545 +
" " + value.toDateTime().time().toString(TQt::ISODate) +
"'";
546 else if (m_token==TIME_CONST)
547 return "'" + value.toTime().toString(TQt::ISODate) +
"'";
549 return value.toString();
557bool ConstExpr::validate(ParseInfo& parseInfo)
559 if (!BaseExpr::validate(parseInfo))
566QueryParameterExpr::QueryParameterExpr(
const TQString& message)
570 m_cl = KexiDBExpr_QueryParameter;
575 , m_type(expr.m_type)
579QueryParameterExpr::~QueryParameterExpr()
598TQString QueryParameterExpr::debugString()
600 return TQString(
"QueryParameterExpr('") + TQString::fromLatin1(
"[%2]").arg(value.toString())
612 param.
message = value.toString();
614 params.append( param );
617bool QueryParameterExpr::validate(ParseInfo& parseInfo)
624VariableExpr::VariableExpr(
const TQString& _name)
628, tablePositionForField(-1)
629, tableForQueryAsterisk(0)
631 m_cl = KexiDBExpr_Variable;
638 , tablePositionForField(expr.tablePositionForField)
639 , tableForQueryAsterisk(expr.tableForQueryAsterisk)
643VariableExpr::~VariableExpr()
652TQString VariableExpr::debugString()
654 return TQString(
"VariableExpr(") +
name
673 return field->
type();
679#define IMPL_ERROR(errmsg) parseInfo.errMsg = "Implementation error"; parseInfo.errDescr = errmsg
683 if (!BaseExpr::validate(parseInfo))
686 tablePositionForField = -1;
690 KexiDBDbg <<
"checking variable name: " <<
name << endl;
691 int dotPos =
name.find(
'.');
692 TQString tableName, fieldName;
695 tableName =
name.left(dotPos);
696 fieldName =
name.mid(dotPos+1);
698 if (tableName.isEmpty()) {
700 if (fieldName==
"*") {
706 Field *firstField = 0;
708 Field *f = it.current()->field(fieldName);
715 parseInfo.errMsg = i18n(
"Ambiguous field name");
716 parseInfo.errDescr = i18n(
"Both table \"%1\" and \"%2\" have defined \"%3\" field. "
717 "Use \"<tableName>.%4\" notation to specify table name.")
718 .arg(firstField->
table()->name()).arg(f->
table()->name())
719 .arg(fieldName).arg(fieldName);
725 parseInfo.errMsg = i18n(
"Field not found");
726 parseInfo.errDescr = i18n(
"Table containing \"%1\" field not found").arg(fieldName);
736 tableName = tableName.lower();
737 TableSchema *ts = parseInfo.querySchema->table( tableName );
740 const TQValueList<int> tPositions = parseInfo.querySchema->tablePositions(tableName);
741 TQValueList<int>::ConstIterator it = tPositions.constBegin();
742 TQCString tableAlias;
744 for (; it!=tPositions.constEnd() && covered; ++it) {
745 tableAlias = parseInfo.querySchema->tableAlias(*it);
746 if (tableAlias.isEmpty() || tableAlias.lower()==tableName.latin1())
748 KexiDBDbg <<
" --" <<
"covered by " << tableAlias <<
" alias" << endl;
751 parseInfo.errMsg = i18n(
"Could not access the table directly using its name");
752 parseInfo.errDescr = i18n(
"Table \"%1\" is covered by aliases. Instead of \"%2\", "
753 "you can write \"%3\"").arg(tableName)
754 .arg(TQString(tableName+
"."+fieldName)).arg(TQString(tableAlias+
"."+fieldName.latin1()));
759 int tablePosition = -1;
761 tablePosition = parseInfo.querySchema->tablePositionForAlias( tableName.latin1() );
762 if (tablePosition>=0) {
763 ts = parseInfo.querySchema->tables()->at(tablePosition);
771 parseInfo.errMsg = i18n(
"Table not found");
772 parseInfo.errDescr = i18n(
"Unknown table \"%1\"").arg(tableName);
776 TQValueList<int> *positionsList = parseInfo.repeatedTablesAndAliases[ tableName ];
777 if (!positionsList) {
778 IMPL_ERROR(tableName +
"." + fieldName +
", !positionsList ");
783 if (fieldName==
"*") {
784 if (positionsList->count()>1) {
785 parseInfo.errMsg = i18n(
"Ambiguous \"%1.*\" expression").arg(tableName);
786 parseInfo.errDescr = i18n(
"More than one \"%1\" table or alias defined").arg(tableName);
797 parseInfo.errMsg = i18n(
"Field not found");
798 parseInfo.errDescr = i18n(
"Table \"%1\" has no \"%2\" field")
799 .arg(tableName).arg(fieldName);
805 int numberOfTheSameFields = 0;
806 for (TQValueList<int>::iterator it = positionsList->begin();
807 it!=positionsList->end();++it)
809 TableSchema *otherTS = parseInfo.querySchema->tables()->at(*it);
810 if (otherTS->
field(fieldName))
811 numberOfTheSameFields++;
812 if (numberOfTheSameFields>1) {
813 parseInfo.errMsg = i18n(
"Ambiguous \"%1.%2\" expression")
814 .arg(tableName).arg(fieldName);
815 parseInfo.errDescr = i18n(
"More than one \"%1\" table or alias defined containing \"%2\" field")
816 .arg(tableName).arg(fieldName);
821 tablePositionForField = tablePosition;
828static TQValueList<TQCString> FunctionExpr_builtIns;
829static const char* FunctionExpr_builtIns_[] =
830{
"SUM",
"MIN",
"MAX",
"AVG",
"COUNT",
"STD",
"STDDEV",
"VARIANCE", 0 };
832TQValueList<TQCString> FunctionExpr::builtInAggregates()
834 if (FunctionExpr_builtIns.isEmpty()) {
835 for (
const char **p = FunctionExpr_builtIns_; *p; p++)
836 FunctionExpr_builtIns << *p;
838 return FunctionExpr_builtIns;
841FunctionExpr::FunctionExpr(
const TQString& _name,
NArgExpr* args_ )
846 if (isBuiltInAggregate(
name.latin1()))
847 m_cl = KexiDBExpr_Aggregation;
849 m_cl = KexiDBExpr_Function;
851 args->setParent(
this );
857 , args(expr.args ? args->copy() : 0)
860 args->setParent(
this );
863FunctionExpr::~FunctionExpr()
873TQString FunctionExpr::debugString()
876 res.append( TQString(
"FunctionExpr(") + name );
878 res.append(TQString(
",") + args->debugString());
885 return name +
"(" + (args ? args->
toString(params) : TQString()) +
")";
899bool FunctionExpr::validate(ParseInfo& parseInfo)
901 if (!BaseExpr::validate(parseInfo))
904 return args ? args->validate(parseInfo) :
true;
907bool FunctionExpr::isBuiltInAggregate(
const TQCString& fname)
909 return builtInAggregates().find(fname.upper())!=FunctionExpr_builtIns.end();
A base class for all expressions.
virtual TQString toString(QuerySchemaParameterValueListIterator *params=0)=0
virtual void getQueryParameters(QuerySchemaParameterList ¶ms)=0
virtual BaseExpr * copy() const =0
virtual TQString tokenToString()
TQString tokenToDebugString()
virtual void getQueryParameters(QuerySchemaParameterList ¶ms)
virtual TQString toString(QuerySchemaParameterValueListIterator *params=0)
virtual BinaryExpr * copy() const
virtual TQString tokenToString()
virtual bool validate(ParseInfo &parseInfo)
virtual void getQueryParameters(QuerySchemaParameterList ¶ms)
virtual TQString toString(QuerySchemaParameterValueListIterator *params=0)
virtual ConstExpr * copy() const
static TQString defaultSQLTypeName(int id_t)
bool isFPNumericType() const
bool isIntegerType() const
virtual TableSchema * table() const
virtual TQString toString(QuerySchemaParameterValueListIterator *params=0)
virtual void getQueryParameters(QuerySchemaParameterList ¶ms)
virtual FunctionExpr * copy() const
A base class N-argument operation.
virtual void getQueryParameters(QuerySchemaParameterList ¶ms)
virtual TQString toString(QuerySchemaParameterValueListIterator *params=0)
virtual NArgExpr * copy() const
Query parameter used to getting user input of constant values.
virtual QueryParameterExpr * copy() const
virtual TQString toString(QuerySchemaParameterValueListIterator *params=0)
virtual void getQueryParameters(QuerySchemaParameterList ¶ms)
void setType(Field::Type type)
An iteratof for a list of values of query schema parameters providing Allows to iterate over paramete...
TQString getPreviousValueAsString(Field::Type type)
A single parameter of a query schema.
Field::Type type
A datatype of the parameter.
TQString message
A user-visible message that will be displayed to ask for value of the parameter.
TQPtrListIterator< TableSchema > ListIterator
Iterator for tables list.
An unary argument operation: + - NOT (or !) ~ "IS NULL" "IS NOT NULL".
virtual TQString toString(QuerySchemaParameterValueListIterator *params=0)
virtual UnaryExpr * copy() const
virtual void getQueryParameters(QuerySchemaParameterList ¶ms)
virtual bool validate(ParseInfo &parseInfo)
Variables like fieldname or tablename.fieldname
TableSchema * tableForQueryAsterisk
virtual void getQueryParameters(QuerySchemaParameterList ¶ms)
virtual TQString toString(QuerySchemaParameterValueListIterator *params=0)
virtual VariableExpr * copy() const
virtual Field::Type type()
We're assuming it's called after VariableExpr::validate()
virtual bool validate(ParseInfo &parseInfo)
High-level database connectivity library with database backend drivers.
KEXI_DB_EXPORT Field::Type maximumForIntegerTypes(Field::Type t1, Field::Type t2)
KEXI_DB_EXPORT TQString exprClassName(int c)
Custom tokens are not used in parser but used as extension in expression classes.