00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "expression.h"
00024 #include "utils.h"
00025 #include "parser/sqlparser.h"
00026 #include "parser/parser_p.h"
00027
00028 #include <ctype.h>
00029
00030 #include <kdebug.h>
00031 #include <klocale.h>
00032
00033 #include <qdatetime.h>
00034
00035 KEXI_DB_EXPORT QString KexiDB::exprClassName(int c)
00036 {
00037 if (c==KexiDBExpr_Unary)
00038 return "Unary";
00039 else if (c==KexiDBExpr_Arithm)
00040 return "Arithm";
00041 else if (c==KexiDBExpr_Logical)
00042 return "Logical";
00043 else if (c==KexiDBExpr_Relational)
00044 return "Relational";
00045 else if (c==KexiDBExpr_SpecialBinary)
00046 return "SpecialBinary";
00047 else if (c==KexiDBExpr_Const)
00048 return "Const";
00049 else if (c==KexiDBExpr_Variable)
00050 return "Variable";
00051 else if (c==KexiDBExpr_Function)
00052 return "Function";
00053 else if (c==KexiDBExpr_Aggregation)
00054 return "Aggregation";
00055 else if (c==KexiDBExpr_TableList)
00056 return "TableList";
00057 else if (c==KexiDBExpr_QueryParameter)
00058 return "QueryParameter";
00059
00060 return "Unknown";
00061 }
00062
00063 using namespace KexiDB;
00064
00065
00066
00067 BaseExpr::BaseExpr(int token)
00068 : m_cl(KexiDBExpr_Unknown)
00069 , m_par(0)
00070 , m_token(token)
00071 {
00072
00073 }
00074
00075 BaseExpr::~BaseExpr()
00076 {
00077 }
00078
00079 Field::Type BaseExpr::type()
00080 {
00081 return Field::InvalidType;
00082 }
00083
00084 QString BaseExpr::debugString()
00085 {
00086 return QString("BaseExpr(%1,type=%1)").arg(m_token).arg(Driver::defaultSQLTypeName(type()));
00087 }
00088
00089 bool BaseExpr::validate(ParseInfo& )
00090 {
00091 return true;
00092 }
00093
00094 extern const char * const tname(int offset);
00095 #define safe_tname(token) ((token>=255 && token<=__LAST_TOKEN) ? tname(token-255) : "")
00096
00097 QString BaseExpr::tokenToDebugString(int token)
00098 {
00099 if (token < 254) {
00100 if (isprint(token))
00101 return QString(QChar(uchar(token)));
00102 else
00103 return QString::number(token);
00104 }
00105 return QString(safe_tname(token));
00106 }
00107
00108 QString BaseExpr::tokenToString()
00109 {
00110 if (m_token < 255 && isprint(m_token))
00111 return tokenToDebugString();
00112 return QString::null;
00113 }
00114
00115 NArgExpr* BaseExpr::toNArg() { return dynamic_cast<NArgExpr*>(this); }
00116 UnaryExpr* BaseExpr::toUnary() { return dynamic_cast<UnaryExpr*>(this); }
00117 BinaryExpr* BaseExpr::toBinary() { return dynamic_cast<BinaryExpr*>(this); }
00118 ConstExpr* BaseExpr::toConst() { return dynamic_cast<ConstExpr*>(this); }
00119 VariableExpr* BaseExpr::toVariable() { return dynamic_cast<VariableExpr*>(this); }
00120 FunctionExpr* BaseExpr::toFunction() { return dynamic_cast<FunctionExpr*>(this); }
00121 QueryParameterExpr* BaseExpr::toQueryParameter() { return dynamic_cast<QueryParameterExpr*>(this); }
00122
00123
00124
00125 NArgExpr::NArgExpr(int aClass, int token)
00126 : BaseExpr(token)
00127 {
00128 m_cl = aClass;
00129 list.setAutoDelete(true);
00130 }
00131
00132 NArgExpr::~NArgExpr()
00133 {
00134 }
00135
00136 QString NArgExpr::debugString()
00137 {
00138 QString s = QString("NArgExpr(")
00139 + "class=" + exprClassName(m_cl);
00140 for ( BaseExpr::ListIterator it(list); it.current(); ++it ) {
00141 s+=", ";
00142 s+=it.current()->debugString();
00143 }
00144 s+=")";
00145 return s;
00146 }
00147
00148 QString NArgExpr::toString( QuerySchemaParameterValueListIterator* params )
00149 {
00150 QString s;
00151 s.reserve(256);
00152 foreach_list( BaseExpr::ListIterator, it, list) {
00153 if (!s.isEmpty())
00154 s+=", ";
00155 s+=it.current()->toString(params);
00156 }
00157 return s;
00158 }
00159
00160 void NArgExpr::getQueryParameters(QuerySchemaParameterList& params)
00161 {
00162 foreach_list( BaseExpr::ListIterator, it, list)
00163 it.current()->getQueryParameters(params);
00164 }
00165
00166 BaseExpr* NArgExpr::arg(int nr)
00167 {
00168 return list.at(nr);
00169 }
00170
00171 void NArgExpr::add(BaseExpr *expr)
00172 {
00173 list.append(expr);
00174 expr->setParent(this);
00175 }
00176
00177 void NArgExpr::prepend(BaseExpr *expr)
00178 {
00179 list.prepend(expr);
00180 expr->setParent(this);
00181 }
00182
00183 int NArgExpr::args()
00184 {
00185 return list.count();
00186 }
00187
00188 bool NArgExpr::validate(ParseInfo& parseInfo)
00189 {
00190 if (!BaseExpr::validate(parseInfo))
00191 return false;
00192
00193 foreach_list(BaseExpr::ListIterator, it, list) {
00194 if (!it.current()->validate(parseInfo))
00195 return false;
00196 }
00197 return true;
00198 }
00199
00200
00201 UnaryExpr::UnaryExpr(int token, BaseExpr *arg)
00202 : BaseExpr(token)
00203 , m_arg(arg)
00204 {
00205 m_cl = KexiDBExpr_Unary;
00206 if (m_arg)
00207 m_arg->setParent(this);
00208 }
00209
00210 UnaryExpr::~UnaryExpr()
00211 {
00212 delete m_arg;
00213 }
00214
00215 QString UnaryExpr::debugString()
00216 {
00217 return "UnaryExpr('"
00218 + tokenToDebugString() + "', "
00219 + (m_arg ? m_arg->debugString() : QString("<NONE>"))
00220 + QString(",type=%1)").arg(Driver::defaultSQLTypeName(type()));
00221 }
00222
00223 QString UnaryExpr::toString(QuerySchemaParameterValueListIterator* params)
00224 {
00225 if (m_token=='(')
00226 return "(" + (m_arg ? m_arg->toString(params) : "<NULL>") + ")";
00227 if (m_token < 255 && isprint(m_token))
00228 return tokenToDebugString() + (m_arg ? m_arg->toString(params) : "<NULL>");
00229 if (m_token==NOT)
00230 return "NOT " + (m_arg ? m_arg->toString(params) : "<NULL>");
00231 if (m_token==SQL_IS_NULL)
00232 return (m_arg ? m_arg->toString(params) : "<NULL>") + " IS NULL";
00233 if (m_token==SQL_IS_NOT_NULL)
00234 return (m_arg ? m_arg->toString(params) : "<NULL>") + " IS NOT NULL";
00235 return QString("{INVALID_OPERATOR#%1} ").arg(m_token) + (m_arg ? m_arg->toString(params) : "<NULL>");
00236 }
00237
00238 void UnaryExpr::getQueryParameters(QuerySchemaParameterList& params)
00239 {
00240 if (m_arg)
00241 m_arg->getQueryParameters(params);
00242 }
00243
00244 Field::Type UnaryExpr::type()
00245 {
00246
00247
00248 switch (m_token) {
00249 case SQL_IS_NULL:
00250 case SQL_IS_NOT_NULL:
00251 return Field::Boolean;
00252 }
00253 const Field::Type t = m_arg->type();
00254 if (t==Field::Null)
00255 return Field::Null;
00256 if (m_token==NOT)
00257 return Field::Boolean;
00258
00259 return t;
00260 }
00261
00262 bool UnaryExpr::validate(ParseInfo& parseInfo)
00263 {
00264 if (!BaseExpr::validate(parseInfo))
00265 return false;
00266
00267 if (!m_arg->validate(parseInfo))
00268 return false;
00269
00271
00272
00273 if (m_arg->toQueryParameter()) {
00274 m_arg->toQueryParameter()->setType(type());
00275 }
00276
00277 return true;
00278 #if 0
00279 BaseExpr *n = l.at(0);
00280
00281 n->check();
00282
00283
00284
00285
00286
00287 if (is(NOT) && n->nodeTypeIs(TYP_BOOL)) {
00288 node_type=new NConstType(TYP_BOOL);
00289 }
00290 else if (is('#') && n->nodeTypeIs(TYP_STR)) {
00291 node_type=new NConstType(TYP_INT);
00292 }
00293 else if ((is('+') || is('-')) && n->nodeTypeIs(TYP_INT)) {
00294 node_type=new NConstType(TYP_INT);
00295 }
00296 else {
00297 ERR("Niepoprawny argument typu '%s' dla operatora '%s'",
00298 n->nodeTypeName(),is(NOT)?QString("not"):QChar(typ()));
00299 }
00300 #endif
00301 }
00302
00303
00304 BinaryExpr::BinaryExpr(int aClass, BaseExpr *left_expr, int token, BaseExpr *right_expr)
00305 : BaseExpr(token)
00306 , m_larg(left_expr)
00307 , m_rarg(right_expr)
00308 {
00309 m_cl = aClass;
00310 if (m_larg)
00311 m_larg->setParent(this);
00312 if (m_rarg)
00313 m_rarg->setParent(this);
00314 }
00315
00316 BinaryExpr::~BinaryExpr()
00317 {
00318 delete m_larg;
00319 delete m_rarg;
00320 }
00321
00322 bool BinaryExpr::validate(ParseInfo& parseInfo)
00323 {
00324 if (!BaseExpr::validate(parseInfo))
00325 return false;
00326
00327 if (!m_larg->validate(parseInfo))
00328 return false;
00329 if (!m_rarg->validate(parseInfo))
00330 return false;
00331
00333
00334
00335 QueryParameterExpr * queryParameter = m_larg->toQueryParameter();
00336 if (queryParameter)
00337 queryParameter->setType(m_rarg->type());
00338 queryParameter = m_rarg->toQueryParameter();
00339 if (queryParameter)
00340 queryParameter->setType(m_larg->type());
00341
00342 return true;
00343 }
00344
00345 Field::Type BinaryExpr::type()
00346 {
00347 const Field::Type lt = m_larg->type(), rt = m_rarg->type();
00348 if (lt==Field::InvalidType || rt == Field::InvalidType)
00349 return Field::InvalidType;
00350 if (lt==Field::Null || rt == Field::Null) {
00351 if (m_token!=OR)
00352 return Field::Null;
00353 }
00354
00355 switch (m_token) {
00356 case BITWISE_SHIFT_RIGHT:
00357 case BITWISE_SHIFT_LEFT:
00358 case CONCATENATION:
00359 return lt;
00360 }
00361
00362 const bool ltInt = Field::isIntegerType(lt);
00363 const bool rtInt = Field::isIntegerType(rt);
00364 if (ltInt && rtInt)
00365 return KexiDB::maximumForIntegerTypes(lt, rt);
00366
00367 if (Field::isFPNumericType(lt) && rtInt)
00368 return lt;
00369 if (Field::isFPNumericType(rt) && ltInt)
00370 return rt;
00371 if ((lt==Field::Double || lt==Field::Float) && rtInt)
00372 return lt;
00373 if ((rt==Field::Double || rt==Field::Float) && ltInt)
00374 return rt;
00375
00376 return Field::Boolean;
00377 }
00378
00379 QString BinaryExpr::debugString()
00380 {
00381 return QString("BinaryExpr(")
00382 + "class=" + exprClassName(m_cl)
00383 + "," + (m_larg ? m_larg->debugString() : QString("<NONE>"))
00384 + ",'" + tokenToDebugString() + "',"
00385 + (m_rarg ? m_rarg->debugString() : QString("<NONE>"))
00386 + QString(",type=%1)").arg(Driver::defaultSQLTypeName(type()));
00387 }
00388
00389 QString BinaryExpr::tokenToString()
00390 {
00391 if (m_token < 255 && isprint(m_token))
00392 return tokenToDebugString();
00393
00394 switch (m_token) {
00395 case BITWISE_SHIFT_RIGHT: return ">>";
00396 case BITWISE_SHIFT_LEFT: return "<<";
00397
00398 case NOT_EQUAL: return "<>";
00399 case NOT_EQUAL2: return "!=";
00400 case LESS_OR_EQUAL: return "<=";
00401 case GREATER_OR_EQUAL: return ">=";
00402 case LIKE: return "LIKE";
00403 case SQL_IN: return "IN";
00404
00405 case SIMILAR_TO: return "SIMILAR TO";
00406 case NOT_SIMILAR_TO: return "NOT SIMILAR TO";
00407 case OR: return "OR";
00408 case AND: return "AND";
00409 case XOR: return "XOR";
00410
00411 case CONCATENATION: return "||";
00412
00413
00414 default:;
00415 }
00416 return QString("{INVALID_BINARY_OPERATOR#%1} ").arg(m_token);
00417 }
00418
00419 QString BinaryExpr::toString(QuerySchemaParameterValueListIterator* params)
00420 {
00421 #define INFIX(a) \
00422 (m_larg ? m_larg->toString(params) : "<NULL>") + " " + a + " " + (m_rarg ? m_rarg->toString(params) : "<NULL>")
00423 return INFIX(tokenToString());
00424 }
00425
00426 void BinaryExpr::getQueryParameters(QuerySchemaParameterList& params)
00427 {
00428 if (m_larg)
00429 m_larg->getQueryParameters(params);
00430 if (m_rarg)
00431 m_rarg->getQueryParameters(params);
00432 }
00433
00434
00435 ConstExpr::ConstExpr( int token, const QVariant& val)
00436 : BaseExpr( token )
00437 , value(val)
00438 {
00439 m_cl = KexiDBExpr_Const;
00440 }
00441
00442 ConstExpr::~ConstExpr()
00443 {
00444 }
00445
00446 Field::Type ConstExpr::type()
00447 {
00448 if (m_token==SQL_NULL)
00449 return Field::Null;
00450 else if (m_token==INTEGER_CONST) {
00451
00452
00453 if (value.type() == QVariant::Int || value.type() == QVariant::UInt) {
00454 Q_LLONG v = value.toInt();
00455 if (v <= 0xff && v > -0x80)
00456 return Field::Byte;
00457 if (v <= 0xffff && v > -0x8000)
00458 return Field::ShortInteger;
00459 return Field::Integer;
00460 }
00461 return Field::BigInteger;
00462 }
00463 else if (m_token==CHARACTER_STRING_LITERAL) {
00464
00465 if (value.toString().length() > Field::defaultTextLength())
00466 return Field::LongText;
00467 else
00468 return Field::Text;
00469 }
00470 else if (m_token==REAL_CONST)
00471 return Field::Double;
00472 else if (m_token==DATE_CONST)
00473 return Field::Date;
00474 else if (m_token==DATETIME_CONST)
00475 return Field::DateTime;
00476 else if (m_token==TIME_CONST)
00477 return Field::Time;
00478
00479 return Field::InvalidType;
00480 }
00481
00482 QString ConstExpr::debugString()
00483 {
00484 return QString("ConstExpr('") + tokenToDebugString() +"'," + toString()
00485 + QString(",type=%1)").arg(Driver::defaultSQLTypeName(type()));
00486 }
00487
00488 QString ConstExpr::toString(QuerySchemaParameterValueListIterator* params)
00489 {
00490 Q_UNUSED(params);
00491 if (m_token==SQL_NULL)
00492 return "NULL";
00493 else if (m_token==CHARACTER_STRING_LITERAL)
00494
00495 return "'" + value.toString() + "'";
00496 else if (m_token==REAL_CONST)
00497 return QString::number(value.toPoint().x())+"."+QString::number(value.toPoint().y());
00498 else if (m_token==DATE_CONST)
00499 return "'" + value.toDate().toString(Qt::ISODate) + "'";
00500 else if (m_token==DATETIME_CONST)
00501 return "'" + value.toDateTime().date().toString(Qt::ISODate)
00502 + " " + value.toDateTime().time().toString(Qt::ISODate) + "'";
00503 else if (m_token==TIME_CONST)
00504 return "'" + value.toTime().toString(Qt::ISODate) + "'";
00505
00506 return value.toString();
00507 }
00508
00509 void ConstExpr::getQueryParameters(QuerySchemaParameterList& params)
00510 {
00511 Q_UNUSED(params);
00512 }
00513
00514 bool ConstExpr::validate(ParseInfo& parseInfo)
00515 {
00516 if (!BaseExpr::validate(parseInfo))
00517 return false;
00518
00519 return type()!=Field::InvalidType;
00520 }
00521
00522
00523 QueryParameterExpr::QueryParameterExpr(const QString& message)
00524 : ConstExpr( QUERY_PARAMETER, message )
00525 , m_type(Field::Text)
00526 {
00527 m_cl = KexiDBExpr_QueryParameter;
00528 }
00529
00530 QueryParameterExpr::~QueryParameterExpr()
00531 {
00532 }
00533
00534 Field::Type QueryParameterExpr::type()
00535 {
00536 return m_type;
00537 }
00538
00539 void QueryParameterExpr::setType(Field::Type type)
00540 {
00541 m_type = type;
00542 }
00543
00544 QString QueryParameterExpr::debugString()
00545 {
00546 return QString("QueryParameterExpr('") + QString::fromLatin1("[%2]").arg(value.toString())
00547 + QString("',type=%1)").arg(Driver::defaultSQLTypeName(type()));
00548 }
00549
00550 QString QueryParameterExpr::toString(QuerySchemaParameterValueListIterator* params)
00551 {
00552 return params ? params->getPreviousValueAsString(type()) : QString::fromLatin1("[%2]").arg(value.toString());
00553 }
00554
00555 void QueryParameterExpr::getQueryParameters(QuerySchemaParameterList& params)
00556 {
00557 QuerySchemaParameter param;
00558 param.message = value.toString();
00559 param.type = type();
00560 params.append( param );
00561 }
00562
00563 bool QueryParameterExpr::validate(ParseInfo& parseInfo)
00564 {
00565 Q_UNUSED(parseInfo);
00566 return type()!=Field::InvalidType;
00567 }
00568
00569
00570 VariableExpr::VariableExpr(const QString& _name)
00571 : BaseExpr( 0 )
00572 , name(_name)
00573 , field(0)
00574 , tablePositionForField(-1)
00575 , tableForQueryAsterisk(0)
00576 {
00577 m_cl = KexiDBExpr_Variable;
00578 }
00579
00580 VariableExpr::~VariableExpr()
00581 {
00582 }
00583
00584 QString VariableExpr::debugString()
00585 {
00586 return QString("VariableExpr(") + name
00587 + QString(",type=%1)").arg(field ? Driver::defaultSQLTypeName(type()) : QString("FIELD NOT DEFINED YET"));
00588 }
00589
00590 QString VariableExpr::toString(QuerySchemaParameterValueListIterator* params)
00591 {
00592 Q_UNUSED(params);
00593 return name;
00594 }
00595
00596 void VariableExpr::getQueryParameters(QuerySchemaParameterList& params)
00597 {
00598 Q_UNUSED(params);
00599 }
00600
00602 Field::Type VariableExpr::type()
00603 {
00604 if (field)
00605 return field->type();
00606
00607
00608 return Field::InvalidType;
00609 }
00610
00611 #define IMPL_ERROR(errmsg) parseInfo.errMsg = "Implementation error"; parseInfo.errDescr = errmsg
00612
00613 bool VariableExpr::validate(ParseInfo& parseInfo)
00614 {
00615 if (!BaseExpr::validate(parseInfo))
00616 return false;
00617 field = 0;
00618 tablePositionForField = -1;
00619 tableForQueryAsterisk = 0;
00620
00621
00622 KexiDBDbg << "checking variable name: " << name << endl;
00623 int dotPos = name.find('.');
00624 QString tableName, fieldName;
00625
00626 if (dotPos>0) {
00627 tableName = name.left(dotPos);
00628 fieldName = name.mid(dotPos+1);
00629 }
00630 if (tableName.isEmpty()) {
00631 fieldName = name;
00632 if (fieldName=="*") {
00633
00634 return true;
00635 }
00636
00637
00638 Field *firstField = 0;
00639 foreach_list(TableSchema::ListIterator, it, *parseInfo.querySchema->tables()) {
00640 Field *f = it.current()->field(fieldName);
00641 if (f) {
00642 if (!firstField) {
00643 firstField = f;
00644 }
00645 else if (f->table()!=firstField->table()) {
00646
00647 parseInfo.errMsg = i18n("Ambiguous field name");
00648 parseInfo.errDescr = i18n("Both table \"%1\" and \"%2\" have defined \"%3\" field. "
00649 "Use \"<tableName>.%4\" notation to specify table name.")
00650 .arg(firstField->table()->name()).arg(f->table()->name())
00651 .arg(fieldName).arg(fieldName);
00652 return false;
00653 }
00654 }
00655 }
00656 if (!firstField) {
00657 parseInfo.errMsg = i18n("Field not found");
00658 parseInfo.errDescr = i18n("Table containing \"%1\" field not found").arg(fieldName);
00659 return false;
00660 }
00661
00662 field = firstField;
00663
00664 return true;
00665 }
00666
00667
00668 tableName = tableName.lower();
00669 TableSchema *ts = parseInfo.querySchema->table( tableName );
00670 if (ts) {
00671
00672 const QValueList<int> tPositions = parseInfo.querySchema->tablePositions(tableName);
00673 QValueList<int>::ConstIterator it = tPositions.constBegin();
00674 QCString tableAlias;
00675 bool covered = true;
00676 for (; it!=tPositions.constEnd() && covered; ++it) {
00677 tableAlias = parseInfo.querySchema->tableAlias(*it);
00678 if (tableAlias.isEmpty() || tableAlias.lower()==tableName.latin1())
00679 covered = false;
00680 KexiDBDbg << " --" << "covered by " << tableAlias << " alias" << endl;
00681 }
00682 if (covered) {
00683 parseInfo.errMsg = i18n("Could not access the table directly using its name");
00684 parseInfo.errDescr = i18n("Table \"%1\" is covered by aliases. Instead of \"%2\", "
00685 "you can write \"%3\"").arg(tableName)
00686 .arg(tableName+"."+fieldName).arg(tableAlias+"."+fieldName.latin1());
00687 return false;
00688 }
00689 }
00690
00691 int tablePosition = -1;
00692 if (!ts) {
00693 tablePosition = parseInfo.querySchema->tablePositionForAlias( tableName.latin1() );
00694 if (tablePosition>=0) {
00695 ts = parseInfo.querySchema->tables()->at(tablePosition);
00696 if (ts) {
00697
00698 }
00699 }
00700 }
00701
00702 if (!ts) {
00703 parseInfo.errMsg = i18n("Table not found");
00704 parseInfo.errDescr = i18n("Unknown table \"%1\"").arg(tableName);
00705 return false;
00706 }
00707
00708 QValueList<int> *positionsList = parseInfo.repeatedTablesAndAliases[ tableName ];
00709 if (!positionsList) {
00710 IMPL_ERROR(tableName + "." + fieldName + ", !positionsList ");
00711 return false;
00712 }
00713
00714
00715 if (fieldName=="*") {
00716 if (positionsList->count()>1) {
00717 parseInfo.errMsg = i18n("Ambiguous \"%1.*\" expression").arg(tableName);
00718 parseInfo.errDescr = i18n("More than one \"%1\" table or alias defined").arg(tableName);
00719 return false;
00720 }
00721 tableForQueryAsterisk = ts;
00722
00723 return true;
00724 }
00725
00726
00727 Field *realField = ts->field(fieldName);
00728 if (!realField) {
00729 parseInfo.errMsg = i18n("Field not found");
00730 parseInfo.errDescr = i18n("Table \"%1\" has no \"%2\" field")
00731 .arg(tableName).arg(fieldName);
00732 return false;
00733 }
00734
00735
00736
00737 int numberOfTheSameFields = 0;
00738 for (QValueList<int>::iterator it = positionsList->begin();
00739 it!=positionsList->end();++it)
00740 {
00741 TableSchema *otherTS = parseInfo.querySchema->tables()->at(*it);
00742 if (otherTS->field(fieldName))
00743 numberOfTheSameFields++;
00744 if (numberOfTheSameFields>1) {
00745 parseInfo.errMsg = i18n("Ambiguous \"%1.%2\" expression")
00746 .arg(tableName).arg(fieldName);
00747 parseInfo.errDescr = i18n("More than one \"%1\" table or alias defined containing \"%2\" field")
00748 .arg(tableName).arg(fieldName);
00749 return false;
00750 }
00751 }
00752 field = realField;
00753 tablePositionForField = tablePosition;
00754
00755
00756 return true;
00757 }
00758
00759
00760 static QValueList<QCString> FunctionExpr_builtIns;
00761 static const char* FunctionExpr_builtIns_[] =
00762 {"SUM", "MIN", "MAX", "AVG", "COUNT", "STD", "STDDEV", "VARIANCE", 0 };
00763
00764 QValueList<QCString> FunctionExpr::builtInAggregates()
00765 {
00766 if (FunctionExpr_builtIns.isEmpty()) {
00767 for (const char **p = FunctionExpr_builtIns_; *p; p++)
00768 FunctionExpr_builtIns << *p;
00769 }
00770 return FunctionExpr_builtIns;
00771 }
00772
00773 FunctionExpr::FunctionExpr( const QString& _name, NArgExpr* args_ )
00774 : BaseExpr( 0 )
00775 , name(_name)
00776 , args(args_)
00777 {
00778 if (isBuiltInAggregate(name.latin1()))
00779 m_cl = KexiDBExpr_Aggregation;
00780 else
00781 m_cl = KexiDBExpr_Function;
00782 if (args)
00783 args->setParent( this );
00784 }
00785
00786 FunctionExpr::~FunctionExpr()
00787 {
00788 delete args;
00789 }
00790
00791 QString FunctionExpr::debugString()
00792 {
00793 QString res;
00794 res.append( QString("FunctionExpr(") + name );
00795 if (args)
00796 res.append(QString(",") + args->debugString());
00797 res.append(QString(",type=%1)").arg(Driver::defaultSQLTypeName(type())));
00798 return res;
00799 }
00800
00801 QString FunctionExpr::toString(QuerySchemaParameterValueListIterator* params)
00802 {
00803 return name + "(" + (args ? args->toString(params) : QString::null) + ")";
00804 }
00805
00806 void FunctionExpr::getQueryParameters(QuerySchemaParameterList& params)
00807 {
00808 args->getQueryParameters(params);
00809 }
00810
00811 Field::Type FunctionExpr::type()
00812 {
00813
00814 return Field::InvalidType;
00815 }
00816
00817 bool FunctionExpr::validate(ParseInfo& parseInfo)
00818 {
00819 if (!BaseExpr::validate(parseInfo))
00820 return false;
00821
00822 return args ? args->validate(parseInfo) : true;
00823 }
00824
00825 bool FunctionExpr::isBuiltInAggregate(const QCString& fname)
00826 {
00827 return builtInAggregates().find(fname.upper())!=FunctionExpr_builtIns.end();
00828 }