kexi

expression.cpp

00001 /* This file is part of the KDE project
00002    Copyright (C) 2003-2004 Jaroslaw Staniek <js@iidea.pl>
00003 
00004    Based on nexp.cpp : Parser module of Python-like language
00005    (C) 2001 Jaroslaw Staniek, MIMUW (www.mimuw.edu.pl)
00006 
00007    This library is free software; you can redistribute it and/or
00008    modify it under the terms of the GNU Library General Public
00009    License as published by the Free Software Foundation; either
00010    version 2 of the License, or (at your option) any later version.
00011 
00012    This library is distributed in the hope that it will be useful,
00013    but WITHOUT ANY WARRANTY; without even the implied warranty of
00014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015    Library General Public License for more details.
00016 
00017    You should have received a copy of the GNU Library General Public License
00018    along with this library; see the file COPYING.LIB.  If not, write to
00019    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00020  * Boston, MA 02110-1301, USA.
00021  */
00022 
00023 #include "expression.h"
00024 #include "parser/sqlparser.h"
00025 #include "parser/parser_p.h"
00026 
00027 #include <ctype.h>
00028 
00029 #include <kdebug.h>
00030 #include <klocale.h>
00031 
00032 #include <qdatetime.h>
00033 
00034 KEXI_DB_EXPORT QString KexiDB::exprClassName(int c)
00035 {
00036     if (c==KexiDBExpr_Unary)
00037         return "Unary";
00038     else if (c==KexiDBExpr_Arithm)
00039         return "Arithm";
00040     else if (c==KexiDBExpr_Logical)
00041         return "Logical";
00042     else if (c==KexiDBExpr_Relational)
00043         return "Relational";
00044     else if (c==KexiDBExpr_SpecialBinary)
00045         return "SpecialBinary";
00046     else if (c==KexiDBExpr_Const)
00047         return "Const";
00048     else if (c==KexiDBExpr_Variable)
00049         return "Variable";
00050     else if (c==KexiDBExpr_Function)
00051         return "Function";
00052     else if (c==KexiDBExpr_Aggregation)
00053         return "Aggregation";
00054     else if (c==KexiDBExpr_TableList)
00055         return "TableList";
00056     
00057     return "Unknown";
00058 }
00059 
00060 using namespace KexiDB;
00061 
00062 //=========================================
00063 
00064 BaseExpr::BaseExpr(int token) 
00065  : m_cl(KexiDBExpr_Unknown)
00066  , m_par(0)
00067  , m_token(token)
00068 {
00069 
00070 }
00071 
00072 BaseExpr::~BaseExpr()
00073 {
00074 }
00075 
00076 Field::Type BaseExpr::type()
00077 {
00078     return Field::InvalidType;
00079 }
00080 
00081 QString BaseExpr::debugString()
00082 {
00083     return QString("BaseExpr(%1,type=%1)").arg(m_token).arg(Driver::defaultSQLTypeName(type()));
00084 }
00085 
00086 bool BaseExpr::validate(ParseInfo& /*parseInfo*/)
00087 {
00088     return true;
00089 }
00090 
00091 extern const char * const tname(int offset);
00092 #define safe_tname(token) ((token>=254 && token<=__LAST_TOKEN) ? tname(token-254) : "")
00093 
00094 QString BaseExpr::tokenToDebugString(int token)
00095 {
00096     if (token < 254) {
00097         if (isprint(token))
00098             return QString(QChar(uchar(token)));
00099         else
00100             return QString::number(token);
00101     }
00102     return QString(safe_tname(token));
00103 }
00104 
00105 QString BaseExpr::tokenToString()
00106 {
00107     if (m_token < 255 && isprint(m_token))
00108         return tokenToDebugString();
00109     return QString::null;
00110 }
00111 
00112 NArgExpr* BaseExpr::toNArg() { return dynamic_cast<NArgExpr*>(this); }
00113 UnaryExpr* BaseExpr::toUnary() { return dynamic_cast<UnaryExpr*>(this); }
00114 BinaryExpr* BaseExpr::toBinary() { return dynamic_cast<BinaryExpr*>(this); }
00115 ConstExpr* BaseExpr::toConst() { return dynamic_cast<ConstExpr*>(this); }
00116 VariableExpr* BaseExpr::toVariable() { return dynamic_cast<VariableExpr*>(this); }
00117 FunctionExpr* BaseExpr::toFunction() { return dynamic_cast<FunctionExpr*>(this); }
00118 
00119 //=========================================
00120 
00121 NArgExpr::NArgExpr(int aClass, int token)
00122  : BaseExpr(token)
00123 {
00124     m_cl = aClass;
00125     list.setAutoDelete(TRUE);
00126 }
00127 
00128 NArgExpr::~NArgExpr()
00129 {
00130 }
00131 
00132 QString NArgExpr::debugString()
00133 {
00134     QString s = QString("NArgExpr(")
00135         + "class=" + exprClassName(m_cl);
00136     for ( BaseExpr::ListIterator it(list); it.current(); ++it ) {
00137         s+=", ";
00138         s+=it.current()->debugString();
00139     }
00140     s+=")";
00141     return s;
00142 }
00143 
00144 QString NArgExpr::toString()
00145 {
00146     QString s;
00147     s.reserve(256);
00148     for ( BaseExpr::ListIterator it(list); it.current(); ++it ) {
00149         if (!s.isEmpty())
00150             s+=", ";
00151         s+=it.current()->toString();
00152     }
00153     return s;
00154 }
00155 
00156 BaseExpr* NArgExpr::arg(int nr)
00157 {
00158     return list.at(nr); 
00159 }
00160 
00161 void NArgExpr::add(BaseExpr *expr)
00162 {
00163     list.append(expr);
00164     expr->setParent(this);
00165 }
00166 
00167 void NArgExpr::prepend(BaseExpr *expr)
00168 {
00169     list.prepend(expr);
00170     expr->setParent(this);
00171 }
00172 
00173 int NArgExpr::args()
00174 {
00175     return list.count();
00176 }
00177 
00178 bool NArgExpr::validate(ParseInfo& parseInfo)
00179 {
00180     if (!BaseExpr::validate(parseInfo))
00181         return false;
00182 
00183     for (BaseExpr::ListIterator it(list); it.current(); ++it) {
00184         if (!it.current()->validate(parseInfo))
00185             return false;
00186     }
00187     return true;
00188 }
00189 
00190 //=========================================
00191 UnaryExpr::UnaryExpr(int token, BaseExpr *arg)
00192  : BaseExpr(token)
00193  , m_arg(arg)
00194 {
00195     m_cl = KexiDBExpr_Unary;
00196     //ustaw ojca
00197     if (m_arg)
00198         m_arg->setParent(this);
00199 }
00200 
00201 UnaryExpr::~UnaryExpr()
00202 {
00203     delete m_arg;
00204 }
00205 
00206 QString UnaryExpr::debugString()
00207 {
00208     return "UnaryExpr('" 
00209         + tokenToDebugString() + "', "
00210         + (m_arg ? m_arg->debugString() : QString("<NONE>")) 
00211         + QString(",type=%1)").arg(Driver::defaultSQLTypeName(type()));
00212 }
00213 
00214 QString UnaryExpr::toString()
00215 {
00216     if (m_token=='(') //parentheses (special case)
00217         return "(" + (m_arg ? m_arg->toString() : "<NULL>") + ")";
00218     if (m_token < 255 && isprint(m_token))
00219         return tokenToDebugString() + (m_arg ? m_arg->toString() : "<NULL>");
00220     if (m_token==NOT)
00221         return "NOT " + (m_arg ? m_arg->toString() : "<NULL>");
00222     if (m_token==SQL_IS_NULL)
00223         return (m_arg ? m_arg->toString() : "<NULL>") + " IS NULL";
00224     if (m_token==SQL_IS_NOT_NULL)
00225         return (m_arg ? m_arg->toString() : "<NULL>") + " IS NOT NULL";
00226     return QString("{INVALID_OPERATOR#%1} ").arg(m_token) + (m_arg ? m_arg->toString() : "<NULL>");
00227 }
00228 
00229 Field::Type UnaryExpr::type()
00230 {
00231     //NULL IS NOT NULL : BOOLEAN
00232     //NULL IS NULL : BOOLEAN
00233     switch (m_token) {
00234     case SQL_IS_NULL:
00235     case SQL_IS_NOT_NULL:
00236         return Field::Boolean;
00237     }
00238     const Field::Type t = m_arg->type();
00239     if (t==Field::Null)
00240         return Field::Null;
00241     if (m_token==NOT)
00242         return Field::Boolean;
00243 
00244     return t;
00245 }
00246 
00247 bool UnaryExpr::validate(ParseInfo& parseInfo)
00248 {
00249     if (!BaseExpr::validate(parseInfo))
00250         return false;
00251 
00252     if (!m_arg->validate(parseInfo))
00253         return false;
00254 
00255     return true;
00256 #if 0
00257     BaseExpr *n = l.at(0);
00258 
00259     n->check();
00260 /*typ wyniku:
00261         const bool dla "NOT <bool>" (negacja)
00262         int dla "# <str>" (dlugosc stringu)
00263         int dla "+/- <int>"
00264         */
00265     if (is(NOT) && n->nodeTypeIs(TYP_BOOL)) {
00266         node_type=new NConstType(TYP_BOOL);
00267     }
00268     else if (is('#') && n->nodeTypeIs(TYP_STR)) {
00269         node_type=new NConstType(TYP_INT);
00270     }
00271     else if ((is('+') || is('-')) && n->nodeTypeIs(TYP_INT)) {
00272         node_type=new NConstType(TYP_INT);
00273     }
00274     else {
00275         ERR("Niepoprawny argument typu '%s' dla operatora '%s'",
00276             n->nodeTypeName(),is(NOT)?QString("not"):QChar(typ()));
00277     }
00278 #endif
00279 }
00280     
00281 //=========================================
00282 BinaryExpr::BinaryExpr(int aClass, BaseExpr *left_expr, int token, BaseExpr *right_expr)
00283  : BaseExpr(token)
00284  , m_larg(left_expr)
00285  , m_rarg(right_expr)
00286 {
00287     m_cl = aClass;
00288     //ustaw ojca
00289     if (m_larg)
00290         m_larg->setParent(this);
00291     if (m_rarg)
00292         m_rarg->setParent(this);
00293 }
00294 
00295 BinaryExpr::~BinaryExpr()
00296 {
00297     delete m_larg;
00298     delete m_rarg;
00299 }
00300 
00301 bool BinaryExpr::validate(ParseInfo& parseInfo)
00302 {
00303     if (!BaseExpr::validate(parseInfo))
00304         return false;
00305 
00306     if (!m_larg->validate(parseInfo))
00307         return false;
00308     if (!m_rarg->validate(parseInfo))
00309         return false;
00310 
00311     return true;
00312 }
00313 
00314 Field::Type BinaryExpr::type()
00315 {
00316     const Field::Type lt = m_larg->type(), rt = m_rarg->type();
00317     if (lt==Field::Null || rt == Field::Null) {
00318         if (m_token!=OR) //note that NULL OR something   != NULL
00319             return Field::Null;
00320     }
00321 
00322     switch (m_token) {
00323     case AND:
00324     case OR:
00325     case XOR:
00326     case SIMILAR_TO:
00327         return Field::Boolean;
00328     }
00329 
00330     if (Field::isFPNumericType(lt) && Field::isIntegerType(rt))
00331         return lt;
00332     //case BITWISE_SHIFT_LEFT:
00333     //case BITWISE_SHIFT_RIGHT:
00334 //TODO
00335     return left()->type();
00336 }
00337 
00338 QString BinaryExpr::debugString()
00339 {
00340     return QString("BinaryExpr(")
00341         + "class=" + exprClassName(m_cl)
00342         + "," + (m_larg ? m_larg->debugString() : QString("<NONE>")) 
00343         + ",'" + tokenToDebugString() + "',"
00344         + (m_rarg ? m_rarg->debugString() : QString("<NONE>")) 
00345         + QString(",type=%1)").arg(Driver::defaultSQLTypeName(type()));
00346 }
00347 
00348 QString BinaryExpr::tokenToString()
00349 {
00350     if (m_token < 255 && isprint(m_token))
00351         return tokenToDebugString();
00352     // other arithmetic operations: << >>
00353     switch (m_token) {
00354     case BITWISE_SHIFT_RIGHT: return ">>";
00355     case BITWISE_SHIFT_LEFT: return "<<";
00356     // other relational operations: <= >= <> (or !=) LIKE IN
00357     case NOT_EQUAL: return "<>";
00358     case NOT_EQUAL2: return "!=";
00359     case LESS_OR_EQUAL: return "<=";
00360     case GREATER_OR_EQUAL: return ">=";
00361     case LIKE: return "LIKE";
00362     case SQL_IN: return "IN";
00363     // other logical operations: OR (or ||) AND (or &&) XOR
00364     case SIMILAR_TO: return "SIMILAR TO";
00365     case NOT_SIMILAR_TO: return "NOT SIMILAR TO";
00366     case OR: return "OR";
00367     case AND: return "AND";
00368     case XOR: return "XOR";
00369     // other string operations: || (as CONCATENATION)
00370     case CONCATENATION: return "||";
00371     // SpecialBinary "pseudo operators":
00372     /* not handled here */
00373     default:;
00374     }
00375     return QString("{INVALID_BINARY_OPERATOR#%1} ").arg(m_token);
00376 }
00377 
00378 QString BinaryExpr::toString()
00379 {
00380 #define INFIX(a) \
00381         (m_larg ? m_larg->toString() : "<NULL>") + " " + a + " " + (m_rarg ? m_rarg->toString() : "<NULL>")
00382 
00383     return INFIX(tokenToString());
00384 }
00385 
00386 //=========================================
00387 ConstExpr::ConstExpr( int token, const QVariant& val)
00388 : BaseExpr( token )
00389 , value(val)
00390 {
00391     m_cl = KexiDBExpr_Const;
00392 }
00393 
00394 ConstExpr::~ConstExpr()
00395 {
00396 }
00397 
00398 Field::Type ConstExpr::type()
00399 {
00400     if (m_token==SQL_NULL)
00401         return Field::Null;
00402     else if (m_token==INTEGER_CONST) {
00403 //TODO ok?
00404 //TODO: add sign info?
00405         if (value.type() == QVariant::Int || value.type() == QVariant::UInt) {
00406             Q_LLONG v = value.toInt();
00407             if (v <= 0xff && v > -0x80)
00408                 return Field::Byte;
00409             if (v <= 0xffff && v > -0x8000)
00410                 return Field::ShortInteger;
00411             return Field::Integer;
00412         }
00413         return Field::BigInteger;
00414     }
00415     else if (m_token==CHARACTER_STRING_LITERAL) {
00416 //TODO: Field::defaultTextLength() is hardcoded now!
00417         if (value.toString().length() > Field::defaultTextLength())
00418             return Field::LongText;
00419         else
00420             return Field::Text;
00421     }
00422     else if (m_token==REAL_CONST)
00423         return Field::Double;
00424     else if (m_token==DATE_CONST)
00425         return Field::Date;
00426     else if (m_token==DATETIME_CONST)
00427         return Field::DateTime;
00428     else if (m_token==TIME_CONST)
00429         return Field::Time;
00430 
00431     return Field::InvalidType;
00432 }
00433 
00434 QString ConstExpr::debugString()
00435 {
00436     return QString("ConstExpr('") + tokenToDebugString() +"'," + toString()
00437         + QString(",type=%1)").arg(Driver::defaultSQLTypeName(type()));
00438 }
00439 
00440 QString ConstExpr::toString()
00441 {
00442     if (m_token==SQL_NULL)
00443         return "NULL";
00444     else if (m_token==CHARACTER_STRING_LITERAL)
00445 //TODO: better escaping!
00446         return "'" + value.toString() + "'";
00447     else if (m_token==REAL_CONST)
00448         return QString::number(value.toPoint().x())+"."+QString::number(value.toPoint().y());
00449     else if (m_token==DATE_CONST)
00450         return "'" + value.toDate().toString(Qt::ISODate) + "'";
00451     else if (m_token==DATETIME_CONST)
00452         return "'" + value.toDateTime().date().toString(Qt::ISODate) + " " + value.toDateTime().time().toString(Qt::ISODate) + "'";
00453     else if (m_token==TIME_CONST)
00454         return "'" + value.toTime().toString(Qt::ISODate) + "'";
00455 
00456     return value.toString();
00457 }
00458 
00459 bool ConstExpr::validate(ParseInfo& parseInfo)
00460 {
00461     if (!BaseExpr::validate(parseInfo))
00462         return false;
00463 
00464     return type()!=Field::InvalidType;
00465 }
00466 
00467 //=========================================
00468 VariableExpr::VariableExpr( const QString& _name)
00469 : BaseExpr( 0/*undefined*/ )
00470 , name(_name)
00471 , field(0)
00472 , tablePositionForField(-1)
00473 , tableForQueryAsterisk(0)
00474 {
00475     m_cl = KexiDBExpr_Variable;
00476 }
00477 
00478 VariableExpr::~VariableExpr()
00479 {
00480 }
00481 
00482 QString VariableExpr::debugString()
00483 {
00484     return QString("VariableExpr(") + name
00485         + QString(",type=%1)").arg(Driver::defaultSQLTypeName(type()));
00486 }
00487 
00488 QString VariableExpr::toString()
00489 {
00490     return name;
00491 }
00492 
00494 Field::Type VariableExpr::type()
00495 {
00496     if (field)
00497         return field->type();
00498     
00499     //BTW, asterisks are not stored in VariableExpr outside of parser, so ok.
00500     return Field::InvalidType;
00501 }
00502 
00503 #define IMPL_ERROR(errmsg) parseInfo.errMsg = "Implementation error"; parseInfo.errDescr = errmsg
00504 
00505 bool VariableExpr::validate(ParseInfo& parseInfo)
00506 {
00507     if (!BaseExpr::validate(parseInfo))
00508         return false;
00509     field = 0;
00510     tablePositionForField = -1;
00511     tableForQueryAsterisk = 0;
00512 
00513 /* taken from parser's addColumn(): */
00514     KexiDBDbg << "checking variable name: " << name << endl;
00515     int dotPos = name.find('.');
00516     QString tableName, fieldName;
00517 //TODO: shall we also support db name?
00518     if (dotPos>0) {
00519         tableName = name.left(dotPos);
00520         fieldName = name.mid(dotPos+1);
00521     }
00522     if (tableName.isEmpty()) {//fieldname only
00523         fieldName = name;
00524         if (fieldName=="*") {
00525 //          querySchema->addAsterisk( new QueryAsterisk(querySchema) );
00526             return true;
00527         }
00528 
00529         //find first table that has this field
00530         Field *firstField = 0;
00531         for (TableSchema::ListIterator it(*parseInfo.querySchema->tables()); it.current(); ++it) {
00532             Field *f = it.current()->field(fieldName);
00533             if (f) {
00534                 if (!firstField) {
00535                     firstField = f;
00536                 }
00537                 else if (f->table()!=firstField->table()) {
00538                     //ambiguous field name
00539                     parseInfo.errMsg = i18n("Ambiguous field name");
00540                     parseInfo.errDescr = i18n("Both table \"%1\" and \"%2\" have defined \"%3\" field. "
00541                         "Use \"<tableName>.%4\" notation to specify table name.")
00542                         .arg(firstField->table()->name()).arg(f->table()->name())
00543                         .arg(fieldName).arg(fieldName);
00544                     return false;
00545                 }
00546             }
00547         }
00548         if (!firstField) {
00549             parseInfo.errMsg = i18n("Field not found");
00550             parseInfo.errDescr = i18n("Table containing \"%1\" field not found").arg(fieldName);
00551             return false;
00552         }
00553         //ok
00554         field = firstField; //store
00555 //      querySchema->addField(firstField);
00556         return true;
00557     }
00558 
00559     //table.fieldname or tableAlias.fieldname
00560     tableName = tableName.lower();
00561     TableSchema *ts = parseInfo.querySchema->table( tableName );
00562     if (ts) {//table.fieldname
00563         //check if "table" is covered by an alias
00564         const QValueList<int> tPositions = parseInfo.querySchema->tablePositions(tableName);
00565         QValueList<int>::ConstIterator it = tPositions.constBegin();
00566         QCString tableAlias;
00567         bool covered = true;
00568         for (; it!=tPositions.constEnd() && covered; ++it) {
00569             tableAlias = parseInfo.querySchema->tableAlias(*it);
00570             if (tableAlias.isEmpty() || tableAlias.lower()==tableName.latin1())
00571                 covered = false; //uncovered
00572             KexiDBDbg << " --" << "covered by " << tableAlias << " alias" << endl;
00573         }
00574         if (covered) {
00575             parseInfo.errMsg = i18n("Could not access the table directly using its name");
00576             parseInfo.errDescr = i18n("Table \"%1\" is covered by aliases. Instead of \"%2\", "
00577                 "you can write \"%3\"").arg(tableName)
00578                 .arg(tableName+"."+fieldName).arg(tableAlias+"."+fieldName.latin1());
00579             return false;
00580         }
00581     }
00582     
00583     int tablePosition = -1;
00584     if (!ts) {//try to find tableAlias
00585         tablePosition = parseInfo.querySchema->tablePositionForAlias( tableName.latin1() );
00586         if (tablePosition>=0) {
00587             ts = parseInfo.querySchema->tables()->at(tablePosition);
00588             if (ts) {
00589 //              KexiDBDbg << " --it's a tableAlias.name" << endl;
00590             }
00591         }
00592     }
00593 
00594     if (!ts) {
00595         parseInfo.errMsg = i18n("Table not found");
00596         parseInfo.errDescr = i18n("Unknown table \"%1\"").arg(tableName);
00597         return false;
00598     }
00599 
00600     QValueList<int> *positionsList = parseInfo.repeatedTablesAndAliases[ tableName ];
00601     if (!positionsList) { //for sanity
00602         IMPL_ERROR(tableName + "." + fieldName + ", !positionsList ");
00603         return false;
00604     }
00605 
00606     //it's a table.*
00607     if (fieldName=="*") {
00608         if (positionsList->count()>1) {
00609             parseInfo.errMsg = i18n("Ambiguous \"%1.*\" expression").arg(tableName);
00610             parseInfo.errDescr = i18n("More than one \"%1\" table or alias defined").arg(tableName);
00611             return false;
00612         }
00613         tableForQueryAsterisk = ts;
00614 //          querySchema->addAsterisk( new QueryAsterisk(querySchema, ts) );
00615         return true;
00616     }
00617 
00618 //  KexiDBDbg << " --it's a table.name" << endl;
00619     Field *realField = ts->field(fieldName);
00620     if (!realField) {
00621         parseInfo.errMsg = i18n("Field not found");
00622         parseInfo.errDescr = i18n("Table \"%1\" has no \"%2\" field")
00623             .arg(tableName).arg(fieldName);
00624         return false;
00625     }
00626 
00627     // check if table or alias is used twice and both have the same column
00628     // (so the column is ambiguous)
00629     int numberOfTheSameFields = 0;
00630     for (QValueList<int>::iterator it = positionsList->begin();
00631         it!=positionsList->end();++it)
00632     {
00633         TableSchema *otherTS = parseInfo.querySchema->tables()->at(*it);
00634         if (otherTS->field(fieldName))
00635             numberOfTheSameFields++;
00636         if (numberOfTheSameFields>1) {
00637             parseInfo.errMsg = i18n("Ambiguous \"%1.%2\" expression")
00638                 .arg(tableName).arg(fieldName);
00639             parseInfo.errDescr = i18n("More than one \"%1\" table or alias defined containing \"%2\" field")
00640                 .arg(tableName).arg(fieldName);
00641             return false;
00642         }
00643     }
00644     field = realField; //store
00645     tablePositionForField = tablePosition;
00646 //              querySchema->addField(realField, tablePosition);
00647 
00648     return true;
00649 }
00650 
00651 //=========================================
00652 static QValueList<QCString> FunctionExpr_builtIns;
00653 static const char* FunctionExpr_builtIns_[] = 
00654 {"SUM", "MIN", "MAX", "AVG", "COUNT", "STD", "STDDEV", "VARIANCE", 0 };
00655 
00656 QValueList<QCString> FunctionExpr::builtInAggregates()
00657 {
00658     if (FunctionExpr_builtIns.isEmpty()) {
00659         for (const char **p = FunctionExpr_builtIns_; *p; p++)
00660             FunctionExpr_builtIns << *p;
00661     }
00662     return FunctionExpr_builtIns;
00663 }
00664 
00665 FunctionExpr::FunctionExpr( const QString& _name, NArgExpr* args_ )
00666  : BaseExpr( 0/*undefined*/ )
00667  , name(_name)
00668  , args(args_)
00669 {
00670     if (isBuiltInAggregate(name.latin1()))
00671         m_cl = KexiDBExpr_Aggregation;
00672     else
00673         m_cl = KexiDBExpr_Function;
00674     args->setParent( this );
00675 }
00676 
00677 FunctionExpr::~FunctionExpr()
00678 {
00679     delete args;
00680 }
00681 
00682 QString FunctionExpr::debugString()
00683 {
00684     return QString("FunctionExpr(") + name + "," + args->debugString()
00685         + QString(",type=%1)").arg(Driver::defaultSQLTypeName(type()));
00686 }
00687 
00688 QString FunctionExpr::toString()
00689 {
00690     return name + "(" + args->toString() + ")";
00691 }
00692 
00693 Field::Type FunctionExpr::type()
00694 {
00695     //TODO
00696     return Field::InvalidType;
00697 }
00698 
00699 bool FunctionExpr::validate(ParseInfo& parseInfo)
00700 {
00701     if (!BaseExpr::validate(parseInfo))
00702         return false;
00703 
00704     return args->validate(parseInfo);
00705 }
00706 
00707 bool FunctionExpr::isBuiltInAggregate(const QCString& fname)
00708 {
00709     return builtInAggregates().find(fname.upper())!=FunctionExpr_builtIns.end();
00710 }
00711 
00712 #if 0
00713 //=========================================
00714 ArithmeticExpr::ArithmeticExpr(BaseExpr *l_n, int typ, BaseExpr *r_n)
00715      : BinaryExpr(l_n,typ,r_n)
00716 {
00717 }
00718 
00719 void ArithmeticExpr::check() {
00720     BinaryExpr::check();
00721 
00722     BaseExpr *l_n = l.at(0);
00723     BaseExpr *r_n = l.at(1);
00724     ASSERT(l_n!=NULL);
00725     ASSERT(r_n!=NULL);
00726 
00727     l_n->check();
00728     r_n->check();
00729 
00730 /*typ wyniku:
00731         oba argumenty musza miec rwartosc
00732         typu string lub int (stala albo zmienna) */
00733     if (l_n->nodeTypeIs(TYP_INT) && r_n->nodeTypeIs(TYP_INT)) {
00734         node_type=new NConstType(TYP_INT);
00735     }
00736     else if (l_n->nodeTypeIs(TYP_STR) && r_n->nodeTypeIs(TYP_STR) && is('+')) {
00737         node_type=new NConstType(TYP_STR);
00738     }
00739     else {
00740         ERR("Niepoprawne argumenty typu '%s' i '%s' dla operatora '%s'",
00741             l_n->nodeTypeName(),
00742             r_n->nodeTypeName(),
00743             QChar(typ()));
00744     }
00745 debug("ArithmeticExpr::check() OK");
00746 }
00747 
00748 //=========================================
00749 RelationalExpr::RelationalExpr(BaseExpr *l_n, int typ, BaseExpr *r_n)
00750  : BinaryExpr(l_n,typ,r_n)
00751 {
00752 }
00753 
00754 void RelationalExpr::check() 
00755 {
00756     BinaryExpr::check();
00757     BaseExpr *l_n = l.at(0);
00758     BaseExpr *r_n = l.at(1);
00759     ASSERT(l_n!=NULL);
00760     ASSERT(r_n!=NULL);
00761 
00762     l_n->check();
00763     r_n->check();
00764 
00765     char errop=0; //==1 gdy bledna oper.
00766 /*typ wyniku:
00767     const bool dla:
00768     "<int> =,<,>,<>,<=,>= <int>"
00769     "<string> =,<,>,<>,<=,>= <string>"
00770     "<bool> =,<> <bool>"
00771     "<class> =,<> <class>"
00772     "<dict> =,<> <dict>"
00773         */
00774     if ((l_n->nodeTypeIs(TYP_INT)   && r_n->nodeTypeIs(TYP_INT))
00775         ||(l_n->nodeTypeIs(TYP_STR) && r_n->nodeTypeIs(TYP_STR))) {
00776             switch (typ()) {
00777             case '=':
00778             case '<':
00779             case '>':
00780             case REL_ROZNE:
00781             case REL_MN_ROWNE:
00782             case REL_WIEK_ROWNE:
00783                 break;//ok
00784             default:
00785                 errop=1;//blad
00786             }
00787     }
00788 //  else if ((l_n->nodeTypeIs(TYP_BOOL) && r_n->nodeTypeIs(TYP_BOOL))
00789 //      ||(l_n->nodeTypeIs(TYP_CLASS) && r_n->nodeTypeIs(TYP_CLASS))
00790 //      ||(l_n->nodeTypeIs(TYP_DICT) && r_n->nodeTypeIs(TYP_DICT))) {
00791     else if ((l_n->nodeTypeIs(TYP_BOOL)
00792      || l_n->nodeTypeIs(TYP_DICT)
00793      || l_n->nodeTypeIs(TYP_CLASS)
00794      || l_n->nodeTypeIs(TYP_NIL))
00795      && r_n->nodeType()->like(l_n->nodeType())) {
00796             switch (typ()) {
00797             case '=':
00798             case REL_ROZNE:
00799                 break;//ok
00800             default:
00801                 errop=1;//blad
00802             }
00803     }
00804     else
00805         errop=1;
00806     
00807     if (errop) {
00808         ERR("Niepoprawne argumenty typu '%s' i '%s' dla operatora relacyjnego '%s'",
00809             l_n->nodeTypeName(),
00810             r_n->nodeTypeName(),
00811             tname());
00812     }
00813     else {//ok:
00814         node_type=new NConstType(TYP_BOOL);
00815     }
00816 }
00817 
00818 //=========================================
00819 LogicalExpr::LogicalExpr(BaseExpr *l_n, int typ, BaseExpr *r_n)
00820  : BinaryExpr(l_n,typ,r_n)
00821 {
00822 }
00823 
00824 void LogicalExpr::check()
00825 {
00826     BinaryExpr::check();
00827     BaseExpr *l_n = l.at(0);
00828     BaseExpr *r_n = l.at(1);
00829     ASSERT(l_n!=NULL);
00830     ASSERT(r_n!=NULL);
00831 
00832     l_n->check();
00833     r_n->check();
00834 
00835 /*typ wyniku: const bool dla "<bool> OR/AND <bool>"
00836         */
00837     if (l_n->nodeTypeIs(TYP_BOOL)
00838         && r_n->nodeTypeIs(TYP_BOOL)) {
00839         node_type = l_n->nodeType();
00840     }
00841     else {
00842         ERR("Niepoprawne argumenty typu '%s' i '%s' dla operacji logicznej '%s'",
00843             l_n->nodeTypeName(),
00844             r_n->nodeTypeName(),
00845             QString(is(AND)?"and":"or"));
00846     }
00847 }
00848 #endif
00849 
00850 #if 0
00851 NConstInt::NConstInt(int v)
00852     : BaseExpr(CONST_INT), val(v)
00853 {
00854     node_type = new NConstType(TYP_INT);
00855 }
00856 //-----------------------------------------
00857 const QString NConstInt::dump() {
00858     return QString(name()) + "(" + QString::number(val)+ ")";
00859 }
00860 //-----------------------------------------
00861 const QString NConstInt::name() { return "ConstInt"; }
00862 //-----------------------------------------
00863 int NConstInt::value() { return val; }
00864 //-----------------------------------------
00865 void NConstInt::check() {
00866     BaseExpr::check();
00867 }
00868 
00869 //=========================================
00870 //stala booleowska
00871 NConstBool::NConstBool(const char v)
00872     : BaseExpr(CONST_BOOL), val(v)
00873 {
00874     node_type = new NConstType(TYP_BOOL);
00875 }
00876 //-----------------------------------------
00877 const QString NConstBool::dump()    {
00878     return QString(name()) + "(" + QString::number(val) + ")";
00879 }
00880 //-----------------------------------------
00881 const QString NConstBool::name() { return "ConstBool"; }
00882 //-----------------------------------------
00883 const char NConstBool::value() { return val; }
00884 //-----------------------------------------
00885 void NConstBool::check() {
00886     BaseExpr::check();
00887 }
00888 
00889 //=========================================
00890 //stala znakowa
00891 NConstStr::NConstStr(const char *v)
00892     : BaseExpr(CONST_STR), val(v)
00893 {
00894     node_type = new NConstType(TYP_STR);
00895 }
00896 //-----------------------------------------
00897 const QString NConstStr::dump() {
00898     return QString(name()) + "(" + val + ")";
00899 }
00900 //-----------------------------------------
00901 const QString NConstStr::name() {
00902     return "ConstStr"; }
00903 //-----------------------------------------
00904 const QString NConstStr::value() {
00905     return val; }
00906 //-----------------------------------------
00907 void NConstStr::check() {
00908     BaseExpr::check();
00909 //dodaj etykiete i zapisz string
00910     lab=generateUniqueLabel("const");
00911     gen.mlabel(lab);
00912     gen.mcode(MN_TEXT,val);
00913 }
00914 
00915 #endif
00916 
00917 /* OLD
00918 Expression::Expression()
00919     :d(0)//unused
00920     ,m_field(0)
00921 {
00922 }
00923 
00924 Expression::~Expression()
00925 {
00926 }
00927 
00928 int Expression::type()
00929 {
00930     if (!m_field)
00931         return Field::InvalidType;
00932     return m_field->type();
00933 }
00934 */
00935 
KDE Home | KDE Accessibility Home | Description of Access Keys