00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "kexidb/queryschema.h"
00021 #include "kexidb/driver.h"
00022 #include "kexidb/connection.h"
00023 #include "kexidb/expression.h"
00024 #include "kexidb/parser/sqlparser.h"
00025 #include "utils.h"
00026 #include "lookupfieldschema.h"
00027
00028 #include <assert.h>
00029
00030 #include <qvaluelist.h>
00031 #include <qasciidict.h>
00032 #include <qptrdict.h>
00033 #include <qintdict.h>
00034 #include <qbitarray.h>
00035
00036 #include <kdebug.h>
00037 #include <klocale.h>
00038
00039 using namespace KexiDB;
00040
00041 QueryColumnInfo::QueryColumnInfo(Field *f, QCString _alias, bool _visible)
00042 : field(f), alias(_alias), visible(_visible), m_indexForVisibleLookupValue(-1)
00043 {
00044 }
00045
00046 QueryColumnInfo::~QueryColumnInfo()
00047 {
00048 }
00049
00050 QString QueryColumnInfo::debugString() const
00051 {
00052 return field->name() +
00053 ( alias.isEmpty() ? QString::null
00054 : (QString::fromLatin1(" AS ") + QString(alias)) );
00055 }
00056
00057
00058 namespace KexiDB {
00060 class QuerySchemaPrivate
00061 {
00062 public:
00063 QuerySchemaPrivate(QuerySchema* q)
00064 : query(q)
00065 , masterTable(0)
00066 , fakeRowIDField(0)
00067 , fakeRowIDCol(0)
00068 , maxIndexWithAlias(-1)
00069 , visibility(64)
00070 , fieldsExpanded(0)
00071 , internalFields(0)
00072 , fieldsExpandedWithInternalAndRowID(0)
00073 , fieldsExpandedWithInternal(0)
00074 , autoincFields(0)
00075 , columnsOrder(0)
00076 , columnsOrderWithoutAsterisks(0)
00077 , columnsOrderExpanded(0)
00078 , pkeyFieldsOrder(0)
00079 , pkeyFieldsCount(0)
00080 , tablesBoundToColumns(64, -1)
00081 , tablePositionsForAliases(67, false)
00082 , columnPositionsForAliases(67, false)
00083 , whereExpr(0)
00084 , regenerateExprAliases(false)
00085 {
00086 columnAliases.setAutoDelete(true);
00087 tableAliases.setAutoDelete(true);
00088 asterisks.setAutoDelete(true);
00089 relations.setAutoDelete(true);
00090 tablePositionsForAliases.setAutoDelete(true);
00091 columnPositionsForAliases.setAutoDelete(true);
00092 visibility.fill(false);
00093 }
00094 ~QuerySchemaPrivate()
00095 {
00096 delete fieldsExpanded;
00097 delete internalFields;
00098 delete fieldsExpandedWithInternalAndRowID;
00099 delete fieldsExpandedWithInternal;
00100 delete autoincFields;
00101 delete columnsOrder;
00102 delete columnsOrderWithoutAsterisks;
00103 delete columnsOrderExpanded;
00104 delete pkeyFieldsOrder;
00105 delete whereExpr;
00106 delete fakeRowIDCol;
00107 delete fakeRowIDField;
00108 }
00109
00110 void clear()
00111 {
00112 columnAliases.clear();
00113 tableAliases.clear();
00114 asterisks.clear();
00115 relations.clear();
00116 masterTable = 0;
00117 tables.clear();
00118 clearCachedData();
00119 delete pkeyFieldsOrder;
00120 pkeyFieldsOrder=0;
00121 visibility.fill(false);
00122 tablesBoundToColumns = QValueVector<int>(64,-1);
00123 tablePositionsForAliases.clear();
00124 columnPositionsForAliases.clear();
00125 }
00126
00127 void clearCachedData()
00128 {
00129 orderByColumnList.clear();
00130 if (fieldsExpanded) {
00131 delete fieldsExpanded;
00132 fieldsExpanded = 0;
00133 delete internalFields;
00134 internalFields = 0;
00135 delete columnsOrder;
00136 columnsOrder = 0;
00137 delete columnsOrderWithoutAsterisks;
00138 columnsOrderWithoutAsterisks = 0;
00139 delete columnsOrderExpanded;
00140 columnsOrderExpanded = 0;
00141 delete autoincFields;
00142 autoincFields = 0;
00143 autoIncrementSQLFieldsList = QString::null;
00144 columnInfosByNameExpanded.clear();
00145 columnInfosByName.clear();
00146 }
00147 }
00148
00149 void setColumnAliasInternal(uint position, const QCString& alias)
00150 {
00151 columnAliases.replace(position, new QCString(alias));
00152 columnPositionsForAliases.replace(alias, new int(position));
00153 maxIndexWithAlias = QMAX( maxIndexWithAlias, (int)position );
00154 }
00155
00156 void setColumnAlias(uint position, const QCString& alias)
00157 {
00158 QCString *oldAlias = columnAliases.take(position);
00159 if (oldAlias) {
00160 tablePositionsForAliases.remove(*oldAlias);
00161 delete oldAlias;
00162 }
00163 if (alias.isEmpty()) {
00164 maxIndexWithAlias = -1;
00165 }
00166 else {
00167 setColumnAliasInternal(position, alias);
00168 }
00169 }
00170
00171 bool hasColumnAliases()
00172 {
00173 tryRegenerateExprAliases();
00174 return !columnAliases.isEmpty();
00175 }
00176
00177 QCString* columnAlias(uint position)
00178 {
00179 tryRegenerateExprAliases();
00180 return columnAliases[position];
00181 }
00182
00183 QuerySchema *query;
00184
00188 TableSchema *masterTable;
00189
00191 TableSchema::List tables;
00192
00193 Field *fakeRowIDField;
00194 QueryColumnInfo *fakeRowIDCol;
00195
00196 protected:
00197 void tryRegenerateExprAliases()
00198 {
00199 if (!regenerateExprAliases)
00200 return;
00201
00202 Field *f;
00203 uint p=0;
00204 uint colNum=0;
00205 QCString columnAlias;
00206 for (Field::ListIterator it(query->fieldsIterator()); (f = it.current()); ++it, p++) {
00207 if (f->isExpression() && !columnAliases[p]) {
00208
00209 for (;;) {
00210 colNum++;
00211 columnAlias = (i18n("short for 'expression' word (only latin letters, please)", "expr")
00212 + QString::number(colNum)).latin1();
00213 if (!tablePositionsForAliases[columnAlias])
00214 break;
00215 }
00216 setColumnAliasInternal(p, columnAlias);
00217 }
00218 }
00219 regenerateExprAliases = false;
00220 }
00221
00223 QIntDict<QCString> columnAliases;
00224
00225 public:
00227 QIntDict<QCString> tableAliases;
00228
00230 int maxIndexWithAlias;
00231
00233 int maxIndexWithTableAlias;
00234
00236 QBitArray visibility;
00237
00239 Field::List asterisks;
00240
00242
00243 QueryColumnInfo::Vector *fieldsExpanded;
00244
00246 QueryColumnInfo::Vector *internalFields;
00247
00250 QueryColumnInfo::Vector *fieldsExpandedWithInternalAndRowID;
00251
00254 QueryColumnInfo::Vector *fieldsExpandedWithInternal;
00255
00257 OrderByColumnList orderByColumnList;
00258
00260 QueryColumnInfo::List *autoincFields;
00261
00263 QString autoIncrementSQLFieldsList;
00264 QGuardedPtr<Driver> lastUsedDriverForAutoIncrementSQLFieldsList;
00265
00267 QMap<QueryColumnInfo*,int> *columnsOrder;
00268
00270 QMap<QueryColumnInfo*,int> *columnsOrderWithoutAsterisks;
00271
00275 QMap<QueryColumnInfo*,int> *columnsOrderExpanded;
00276
00277
00278
00280 QValueVector<int> *pkeyFieldsOrder;
00281
00283 uint pkeyFieldsCount;
00284
00286 QString statement;
00287
00289 Relationship::List relations;
00290
00306 QValueVector<int> tablesBoundToColumns;
00307
00309 QAsciiDict<int> tablePositionsForAliases;
00310
00312 QAsciiDict<int> columnPositionsForAliases;
00313
00315 BaseExpr *whereExpr;
00316
00317 QDict<QueryColumnInfo> columnInfosByNameExpanded;
00318
00319 QDict<QueryColumnInfo> columnInfosByName;
00320
00323 bool regenerateExprAliases : 1;
00324 };
00325 }
00326
00327
00328
00329 OrderByColumn::OrderByColumn()
00330 : m_column(0)
00331 , m_pos(-1)
00332 , m_field(0)
00333 , m_ascending(true)
00334 {
00335 }
00336
00337 OrderByColumn::OrderByColumn(QueryColumnInfo& column, bool ascending, int pos)
00338 : m_column(&column)
00339 , m_pos(pos)
00340 , m_field(0)
00341 , m_ascending(ascending)
00342 {
00343 }
00344
00345 OrderByColumn::OrderByColumn(Field& field, bool ascending)
00346 : m_column(0)
00347 , m_pos(-1)
00348 , m_field(&field)
00349 , m_ascending(ascending)
00350 {
00351 }
00352
00353 OrderByColumn::~OrderByColumn()
00354 {
00355 }
00356
00357 QString OrderByColumn::debugString() const
00358 {
00359 QString orderString( m_ascending ? "ascending" : "descending" );
00360 if (m_column) {
00361 if (m_pos>-1)
00362 return QString("COLUMN_AT_POSITION_%1(%2, %3)")
00363 .arg(m_pos+1).arg(m_column->debugString()).arg(orderString);
00364 else
00365 return QString("COLUMN(%1, %2)").arg(m_column->debugString()).arg(orderString);
00366 }
00367 return m_field ? QString("FIELD(%1, %2)").arg(m_field->debugString()).arg(orderString)
00368 : QString("NONE");
00369 }
00370
00371 QString OrderByColumn::toSQLString(bool includeTableName) const
00372 {
00373 QString orderString( m_ascending ? "" : " DESC" );
00374 if (m_column) {
00375 if (m_pos>-1)
00376 return QString::number(m_pos+1) + orderString;
00377 else
00378 return (includeTableName ? m_column->field->table()->name()+"." : QString::null)
00379 + QString(m_column->aliasOrName()) + orderString;
00380 }
00381 else {
00382 return
00383 (includeTableName ? m_field->table()->name()+"." : QString::null)
00384 + (m_field ? m_field->name() : "??") + orderString;
00385 }
00386 }
00387
00388
00389
00390 OrderByColumnList::OrderByColumnList()
00391 : OrderByColumnListBase()
00392 {
00393 }
00394
00395 bool OrderByColumnList::appendFields(QuerySchema& querySchema,
00396 const QString& field1, bool ascending1,
00397 const QString& field2, bool ascending2,
00398 const QString& field3, bool ascending3,
00399 const QString& field4, bool ascending4,
00400 const QString& field5, bool ascending5)
00401 {
00402 uint numAdded = 0;
00403 #define ADD_COL(fieldName, ascending) \
00404 if (ok && !fieldName.isEmpty()) { \
00405 if (!appendField( querySchema, fieldName, ascending )) \
00406 ok = false; \
00407 else \
00408 numAdded++; \
00409 }
00410 bool ok = true;
00411 ADD_COL(field1, ascending1);
00412 ADD_COL(field2, ascending2);
00413 ADD_COL(field3, ascending3);
00414 ADD_COL(field4, ascending4);
00415 ADD_COL(field5, ascending5);
00416 #undef ADD_COL
00417 if (ok)
00418 return true;
00419 for (uint i=0; i<numAdded; i++)
00420 pop_back();
00421 return false;
00422 }
00423
00424 OrderByColumnList::~OrderByColumnList()
00425 {
00426 }
00427
00428 void OrderByColumnList::appendColumn(QueryColumnInfo& columnInfo, bool ascending)
00429 {
00430 appendColumn( OrderByColumn(columnInfo, ascending) );
00431 }
00432
00433 bool OrderByColumnList::appendColumn(QuerySchema& querySchema, bool ascending, int pos)
00434 {
00435 QueryColumnInfo::Vector fieldsExpanded( querySchema.fieldsExpanded() );
00436 QueryColumnInfo* ci = (pos >= (int)fieldsExpanded.size()) ? 0 : fieldsExpanded[pos];
00437 if (!ci)
00438 return false;
00439 appendColumn( OrderByColumn(*ci, ascending, pos) );
00440 return true;
00441 }
00442
00443 void OrderByColumnList::appendField(Field& field, bool ascending)
00444 {
00445 appendColumn( OrderByColumn(field, ascending) );
00446 }
00447
00448 bool OrderByColumnList::appendField(QuerySchema& querySchema,
00449 const QString& fieldName, bool ascending)
00450 {
00451 QueryColumnInfo *columnInfo = querySchema.columnInfo( fieldName );
00452 if (columnInfo) {
00453 appendColumn( OrderByColumn(*columnInfo, ascending) );
00454 return true;
00455 }
00456 Field *field = querySchema.findTableField(fieldName);
00457 if (field) {
00458 appendColumn( OrderByColumn(*field, ascending) );
00459 return true;
00460 }
00461 KexiDBWarn << "OrderByColumnList::addColumn(QuerySchema& querySchema, "
00462 "const QString& column, bool ascending): no such field \"" << fieldName << "\"" << endl;
00463 return false;
00464 }
00465
00466 void OrderByColumnList::appendColumn(const OrderByColumn& column)
00467 {
00468 append( column );
00469 }
00470
00471 QString OrderByColumnList::debugString() const
00472 {
00473 if (isEmpty())
00474 return "NONE";
00475 QString dbg;
00476 for (OrderByColumn::ListConstIterator it=constBegin(); it!=constEnd(); ++it) {
00477 if (!dbg.isEmpty())
00478 dbg += "\n";
00479 dbg += (*it).debugString();
00480 }
00481 return dbg;
00482 }
00483
00484 QString OrderByColumnList::toSQLString(bool includeTableNames) const
00485 {
00486 QString string;
00487 for (OrderByColumn::ListConstIterator it=constBegin(); it!=constEnd(); ++it) {
00488 if (!string.isEmpty())
00489 string += ", ";
00490 string += (*it).toSQLString(includeTableNames);
00491 }
00492 return string;
00493 }
00494
00495
00496
00497 QuerySchema::QuerySchema()
00498 : FieldList(false)
00499 , SchemaData(KexiDB::QueryObjectType)
00500 , d( new QuerySchemaPrivate(this) )
00501 {
00502 init();
00503 }
00504
00505 QuerySchema::QuerySchema(TableSchema* tableSchema)
00506 : FieldList(false)
00507 , SchemaData(KexiDB::QueryObjectType)
00508 , d( new QuerySchemaPrivate(this) )
00509 {
00510 d->masterTable = tableSchema;
00511
00512 init();
00513 if (!d->masterTable) {
00514 KexiDBWarn << "QuerySchema(TableSchema*): !d->masterTable" << endl;
00515 m_name = QString::null;
00516 return;
00517 }
00518 addTable(d->masterTable);
00519
00520
00521 m_name = d->masterTable->name();
00522
00523 m_caption = d->masterTable->caption();
00524
00525
00526
00527
00528
00529 for (Field::ListIterator it( d->masterTable->fieldsIterator() ); it.current(); ++it) {
00530 addField( it.current() );
00531 }
00532 }
00533
00534 QuerySchema::~QuerySchema()
00535 {
00536 delete d;
00537 }
00538
00539 void QuerySchema::init()
00540 {
00541 m_type = KexiDB::QueryObjectType;
00542
00543 }
00544
00545 void QuerySchema::clear()
00546 {
00547 FieldList::clear();
00548 SchemaData::clear();
00549 d->clear();
00550 }
00551
00552 FieldList& QuerySchema::insertField(uint position, Field *field, bool visible)
00553 {
00554 return insertField(position, field, -1, visible);
00555 }
00556
00557
00558 FieldList& QuerySchema::insertField(uint position, Field *field)
00559 {
00560 return insertField( position, field, -1, true );
00561 }
00562
00563 FieldList& QuerySchema::insertField(uint position, Field *field,
00564 int bindToTable, bool visible)
00565 {
00566 if (!field) {
00567 KexiDBWarn << "QuerySchema::insertField(): !field" << endl;
00568 return *this;
00569 }
00570
00571 if (position>m_fields.count()) {
00572 KexiDBWarn << "QuerySchema::insertField(): position (" << position << ") out of range" << endl;
00573 return *this;
00574 }
00575 if (!field->isQueryAsterisk() && !field->isExpression() && !field->table()) {
00576 KexiDBWarn << "QuerySchema::insertField(): WARNING: field '"<<field->name()
00577 <<"' must contain table information!" <<endl;
00578 return *this;
00579 }
00580 if (fieldCount()>=d->visibility.size()) {
00581 d->visibility.resize(d->visibility.size()*2);
00582 d->tablesBoundToColumns.resize(d->tablesBoundToColumns.size()*2);
00583 }
00584 d->clearCachedData();
00585 FieldList::insertField(position, field);
00586 if (field->isQueryAsterisk()) {
00587 d->asterisks.append(field);
00588
00589
00590 if (field->table() && (d->tables.findRef(field->table())==-1))
00591 d->tables.append(field->table());
00592 }
00593 else if (field->table()) {
00594
00595 if (d->tables.findRef(field->table())==-1)
00596 d->tables.append(field->table());
00597 }
00598
00599
00600
00601
00602
00603 for (uint i=fieldCount()-1; i>position; i--)
00604 d->visibility.setBit(i, d->visibility.testBit(i-1));
00605 d->visibility.setBit(position, visible);
00606
00607
00608 if (bindToTable < -1 && bindToTable>(int)d->tables.count()) {
00609 KexiDBWarn << "QuerySchema::insertField(): bindToTable (" << bindToTable
00610 << ") out of range" << endl;
00611 bindToTable = -1;
00612 }
00613
00614 for (uint i=fieldCount()-1; i>position; i--)
00615 d->tablesBoundToColumns[i] = d->tablesBoundToColumns[i-1];
00616 d->tablesBoundToColumns[ position ] = bindToTable;
00617
00618 KexiDBDbg << "QuerySchema::insertField(): bound to table (" << bindToTable << "): " <<endl;
00619 if (bindToTable==-1)
00620 KexiDBDbg << " <NOT SPECIFIED>" << endl;
00621 else
00622 KexiDBDbg << " name=" << d->tables.at(bindToTable)->name()
00623 << " alias=" << tableAlias(bindToTable) << endl;
00624 QString s;
00625 for (uint i=0; i<fieldCount();i++)
00626 s+= (QString::number(d->tablesBoundToColumns[i]) + " ");
00627 KexiDBDbg << "tablesBoundToColumns == [" << s << "]" <<endl;
00628
00629 if (field->isExpression())
00630 d->regenerateExprAliases = true;
00631
00632 return *this;
00633 }
00634
00635 int QuerySchema::tableBoundToColumn(uint columnPosition) const
00636 {
00637 if (columnPosition > d->tablesBoundToColumns.count()) {
00638 KexiDBWarn << "QuerySchema::tableBoundToColumn(): columnPosition (" << columnPosition
00639 << ") out of range" << endl;
00640 return -1;
00641 }
00642 return d->tablesBoundToColumns[columnPosition];
00643 }
00644
00645 KexiDB::FieldList& QuerySchema::addField(KexiDB::Field* field, bool visible)
00646 {
00647 return insertField(m_fields.count(), field, visible);
00648 }
00649
00650 KexiDB::FieldList& QuerySchema::addField(KexiDB::Field* field, int bindToTable,
00651 bool visible)
00652 {
00653 return insertField(m_fields.count(), field, bindToTable, visible);
00654 }
00655
00656 void QuerySchema::removeField(KexiDB::Field *field)
00657 {
00658 if (!field)
00659 return;
00660 d->clearCachedData();
00661 if (field->isQueryAsterisk()) {
00662 d->asterisks.remove(field);
00663 }
00664
00665 FieldList::removeField(field);
00666 }
00667
00668 FieldList& QuerySchema::addExpression(BaseExpr* expr, bool visible)
00669 {
00670 return addField( new Field(this, expr), visible );
00671 }
00672
00673 bool QuerySchema::isColumnVisible(uint position) const
00674 {
00675 return (position < fieldCount()) ? d->visibility.testBit(position) : false;
00676 }
00677
00678 void QuerySchema::setColumnVisible(uint position, bool v)
00679 {
00680 if (position < fieldCount())
00681 d->visibility.setBit(position, v);
00682 }
00683
00684 FieldList& QuerySchema::addAsterisk(QueryAsterisk *asterisk, bool visible)
00685 {
00686 if (!asterisk)
00687 return *this;
00688
00689 asterisk->m_name = (asterisk->table() ? asterisk->table()->name() + ".*" : "*")
00690 + QString::number(asterisks()->count());
00691 return addField(asterisk, visible);
00692 }
00693
00694 Connection* QuerySchema::connection() const
00695 {
00696 TableSchema *mt = masterTable();
00697 return mt ? mt->connection() : 0;
00698 }
00699
00700 QString QuerySchema::debugString()
00701 {
00702 QString dbg;
00703 dbg.reserve(1024);
00704
00705 TableSchema *mt = masterTable();
00706 dbg = QString("QUERY ") + schemaDataDebugString() + "\n"
00707 + "-masterTable=" + (mt ? mt->name() :"<NULL>")
00708 + "\n-COLUMNS:\n"
00709 + ((fieldCount()>0) ? FieldList::debugString() : "<NONE>") + "\n"
00710 + "-FIELDS EXPANDED ";
00711
00712 QString dbg1;
00713 uint fieldsExpandedCount = 0;
00714 if (fieldCount()>0) {
00715 QueryColumnInfo::Vector fe( fieldsExpanded() );
00716 fieldsExpandedCount = fe.size();
00717 for ( uint i=0; i < fieldsExpandedCount; i++ ) {
00718 QueryColumnInfo *ci = fe[i];
00719 if (!dbg1.isEmpty())
00720 dbg1 += ",\n";
00721 dbg1 += ci->debugString();
00722 }
00723 dbg1 += "\n";
00724 }
00725 else {
00726 dbg1 = "<NONE>\n";
00727 }
00728 dbg1.prepend( QString("(%1):\n").arg(fieldsExpandedCount) );
00729 dbg += dbg1;
00730
00731
00732
00733
00734
00735
00736 QString dbg2;
00737 dbg2.reserve(512);
00738 for (uint i = 0; i<fieldCount(); i++) {
00739 int tablePos = tableBoundToColumn(i);
00740 if (tablePos>=0) {
00741 QCString tAlias = tableAlias(tablePos);
00742 if (!tAlias.isEmpty()) {
00743 dbg2 += (QString::fromLatin1(" field \"") + FieldList::field(i)->name()
00744 + "\" uses alias \"" + QString(tAlias) + "\" of table \""
00745 + d->tables.at(tablePos)->name() + "\"\n");
00746 }
00747 }
00748 }
00749 if (!dbg2.isEmpty()) {
00750 dbg += "\n-BINDINGS:\n";
00751 dbg += dbg2;
00752 }
00753
00754
00755 TableSchema *table;
00756 QString table_names;
00757 table_names.reserve(512);
00758 for ( table = d->tables.first(); table; table = d->tables.next() ) {
00759 if (!table_names.isEmpty())
00760 table_names += ", ";
00761 table_names += (QString("'") + table->name() + "'");
00762 }
00763 if (d->tables.isEmpty())
00764 table_names = "<NONE>";
00765 dbg += (QString("-TABLES:\n") + table_names);
00766 QString aliases;
00767 if (!d->hasColumnAliases())
00768 aliases = "<NONE>\n";
00769 else {
00770 Field::ListIterator it( m_fields );
00771 for (int i=0; it.current(); ++it, i++) {
00772 QCString *alias = d->columnAlias(i);
00773 if (alias)
00774 aliases += (QString("field #%1: ").arg(i)
00775 + (it.current()->name().isEmpty() ? "<noname>" : it.current()->name())
00776 + " -> " + (const char*)*alias + "\n");
00777 }
00778 }
00779
00780 dbg += QString("\n-COLUMN ALIASES:\n" + aliases);
00781 if (d->tableAliases.isEmpty())
00782 aliases = "<NONE>";
00783 else {
00784 aliases = "";
00785 TableSchema::ListIterator t_it(d->tables);
00786 for (int i=0; t_it.current(); ++t_it, i++) {
00787 QCString *alias = d->tableAliases[i];
00788 if (alias)
00789 aliases += (QString("table #%1: ").arg(i)
00790 + (t_it.current()->name().isEmpty() ? "<noname>" : t_it.current()->name())
00791 + " -> " + (const char*)*alias + "\n");
00792 }
00793 }
00794 dbg += QString("-TABLE ALIASES:\n" + aliases);
00795 QString where = d->whereExpr ? d->whereExpr->debugString() : QString::null;
00796 if (!where.isEmpty())
00797 dbg += (QString("\n-WHERE EXPRESSION:\n") + where);
00798 if (!orderByColumnList().isEmpty())
00799 dbg += (QString("\n-ORDER BY (%1):\n").arg(orderByColumnList().count())
00800 + orderByColumnList().debugString());
00801 return dbg;
00802 }
00803
00804 TableSchema* QuerySchema::masterTable() const
00805 {
00806 if (d->masterTable)
00807 return d->masterTable;
00808 if (d->tables.isEmpty())
00809 return 0;
00810
00811
00812 int num = 0;
00813 QString tableNameLower;
00814 for (TableSchema::ListIterator it(d->tables); it.current(); ++it, num++) {
00815 if (!tableNameLower.isEmpty() && it.current()->name().lower()!=tableNameLower) {
00816
00817 return 0;
00818 }
00819 tableNameLower = tableAlias(num);
00820 }
00821 return d->tables.first();
00822 }
00823
00824 void QuerySchema::setMasterTable(TableSchema *table)
00825 {
00826 if (table)
00827 d->masterTable=table;
00828 }
00829
00830 TableSchema::List* QuerySchema::tables() const
00831 {
00832 return &d->tables;
00833 }
00834
00835 void QuerySchema::addTable(TableSchema *table, const QCString& alias)
00836 {
00837 KexiDBDbg << "QuerySchema::addTable() " << (void *)table
00838 << " alias=" << alias << endl;
00839 if (!table)
00840 return;
00841
00842
00843
00844
00845 if (alias.isEmpty() && d->tables.findRef(table)!=-1) {
00846 const QString& tableNameLower = table->name().lower();
00847 const QString& aliasLower = QString(alias.lower());
00848 int num = 0;
00849 for (TableSchema::ListIterator it(d->tables); it.current(); ++it, num++) {
00850 if (it.current()->name().lower()==tableNameLower) {
00851 const QString& tAlias = tableAlias(num);
00852 if (tAlias == aliasLower) {
00853 KexiDBWarn << "QuerySchema::addTable(): table with \""
00854 << tAlias << "\" alias already added!" << endl;
00855 return;
00856 }
00857 }
00858 }
00859 }
00860
00861 d->tables.append(table);
00862
00863 if (!alias.isEmpty())
00864 setTableAlias(d->tables.count()-1, alias);
00865 }
00866
00867 void QuerySchema::removeTable(TableSchema *table)
00868 {
00869 if (!table)
00870 return;
00871 if (d->masterTable == table)
00872 d->masterTable = 0;
00873 d->tables.remove(table);
00874
00875 }
00876
00877 TableSchema* QuerySchema::table(const QString& tableName) const
00878 {
00879
00880 for (TableSchema::ListIterator it(d->tables); it.current(); ++it) {
00881 if (it.current()->name().lower()==tableName.lower())
00882 return it.current();
00883 }
00884 return 0;
00885 }
00886
00887 bool QuerySchema::contains(TableSchema *table) const
00888 {
00889 return d->tables.findRef(table)!=-1;
00890 }
00891
00892 Field* QuerySchema::findTableField(const QString &tableOrTableAndFieldName) const
00893 {
00894 QString tableName, fieldName;
00895 if (!KexiDB::splitToTableAndFieldParts(tableOrTableAndFieldName,
00896 tableName, fieldName, KexiDB::SetFieldNameIfNoTableName)) {
00897 return 0;
00898 }
00899 if (tableName.isEmpty()) {
00900 for (TableSchema::ListIterator it(d->tables); it.current(); ++it) {
00901 if (it.current()->field(fieldName))
00902 return it.current()->field(fieldName);
00903 }
00904 return 0;
00905 }
00906 TableSchema *tableSchema = table(tableName);
00907 if (!tableSchema)
00908 return 0;
00909 return tableSchema->field(fieldName);
00910 }
00911
00912 QCString QuerySchema::columnAlias(uint position) const
00913 {
00914 QCString *a = d->columnAlias(position);
00915 return a ? *a : QCString();
00916 }
00917
00918 bool QuerySchema::hasColumnAlias(uint position) const
00919 {
00920 return d->columnAlias(position)!=0;
00921 }
00922
00923 void QuerySchema::setColumnAlias(uint position, const QCString& alias)
00924 {
00925 if (position >= m_fields.count()) {
00926 KexiDBWarn << "QuerySchema::setColumnAlias(): position (" << position
00927 << ") out of range!" << endl;
00928 return;
00929 }
00930 QCString fixedAlias = alias.stripWhiteSpace();
00931 Field *f = FieldList::field(position);
00932 if (f->captionOrName().isEmpty() && fixedAlias.isEmpty()) {
00933 KexiDBWarn << "QuerySchema::setColumnAlias(): position (" << position
00934 << ") could not remove alias when no name is specified for expression column!" << endl;
00935 return;
00936 }
00937 d->setColumnAlias(position, fixedAlias);
00938 }
00939
00940 QCString QuerySchema::tableAlias(uint position) const
00941 {
00942 QCString *a = d->tableAliases[position];
00943 return a ? *a : QCString();
00944 }
00945
00946 int QuerySchema::tablePositionForAlias(const QCString& name) const
00947 {
00948 int *num = d->tablePositionsForAliases[name];
00949 if (!num)
00950 return -1;
00951 return *num;
00952 }
00953
00954 int QuerySchema::tablePosition(const QString& tableName) const
00955 {
00956 int num = 0;
00957 for (TableSchema::ListIterator it(d->tables); it.current(); ++it, num++) {
00958 if (it.current()->name().lower()==tableName.lower())
00959 return num;
00960 }
00961 return -1;
00962 }
00963
00964 QValueList<int> QuerySchema::tablePositions(const QString& tableName) const
00965 {
00966 int num = 0;
00967 QValueList<int> result;
00968 const QString& tableNameLower = tableName.lower();
00969 for (TableSchema::ListIterator it(d->tables); it.current(); ++it, num++) {
00970 if (it.current()->name().lower()==tableNameLower) {
00971 result += num;
00972 }
00973 }
00974 return result;
00975 }
00976
00977 bool QuerySchema::hasTableAlias(uint position) const
00978 {
00979 return d->tableAliases[position]!=0;
00980 }
00981
00982 int QuerySchema::columnPositionForAlias(const QCString& name) const
00983 {
00984 int *num = d->columnPositionsForAliases[name];
00985 if (!num)
00986 return -1;
00987 return *num;
00988 }
00989
00990 void QuerySchema::setTableAlias(uint position, const QCString& alias)
00991 {
00992 if (position >= d->tables.count()) {
00993 KexiDBWarn << "QuerySchema::setTableAlias(): position (" << position
00994 << ") out of range!" << endl;
00995 return;
00996 }
00997 QCString fixedAlias = alias.stripWhiteSpace();
00998 if (fixedAlias.isEmpty()) {
00999 QCString *oldAlias = d->tableAliases.take(position);
01000 if (oldAlias) {
01001 d->tablePositionsForAliases.remove(*oldAlias);
01002 delete oldAlias;
01003 }
01004
01005 }
01006 else {
01007 d->tableAliases.replace(position, new QCString(fixedAlias));
01008 d->tablePositionsForAliases.replace(fixedAlias, new int(position));
01009
01010 }
01011 }
01012
01013 Relationship::List* QuerySchema::relationships() const
01014 {
01015 return &d->relations;
01016 }
01017
01018 Field::List* QuerySchema::asterisks() const
01019 {
01020 return &d->asterisks;
01021 }
01022
01023 QString QuerySchema::statement() const
01024 {
01025 return d->statement;
01026 }
01027
01028 void QuerySchema::setStatement(const QString &s)
01029 {
01030 d->statement = s;
01031 }
01032
01033 Field* QuerySchema::field(const QString& identifier, bool expanded)
01034 {
01035 QueryColumnInfo *ci = columnInfo(identifier, expanded);
01036 return ci ? ci->field : 0;
01037 }
01038
01039 QueryColumnInfo* QuerySchema::columnInfo(const QString& identifier, bool expanded)
01040 {
01041 computeFieldsExpanded();
01042 return expanded ? d->columnInfosByNameExpanded[identifier] : d->columnInfosByName[identifier];
01043 }
01044
01045 QueryColumnInfo::Vector QuerySchema::fieldsExpanded(FieldsExpandedOptions options)
01046 {
01047 computeFieldsExpanded();
01048 if (options == WithInternalFields || options == WithInternalFieldsAndRowID) {
01049
01050 QueryColumnInfo::Vector*& tmpFieldsExpandedWithInternal =
01051 (options == WithInternalFields) ? d->fieldsExpandedWithInternal : d->fieldsExpandedWithInternalAndRowID;
01052
01053 if (!tmpFieldsExpandedWithInternal) {
01054
01055 const uint size = d->fieldsExpanded->count()
01056 + (d->internalFields ? d->internalFields->count() : 0)
01057 + ((options == WithInternalFieldsAndRowID) ? 1 : 0) ;
01058 tmpFieldsExpandedWithInternal = new QueryColumnInfo::Vector( size );
01059 const uint fieldsExpandedVectorSize = d->fieldsExpanded->size();
01060 for (uint i=0; i<fieldsExpandedVectorSize; i++)
01061 tmpFieldsExpandedWithInternal->insert(i, d->fieldsExpanded->at(i));
01062 const uint internalFieldsCount = d->internalFields ? d->internalFields->size() : 0;
01063 if (internalFieldsCount > 0) {
01064 for (uint i=0; i < internalFieldsCount; i++)
01065 tmpFieldsExpandedWithInternal->insert(
01066 fieldsExpandedVectorSize + i, d->internalFields->at(i));
01067 }
01068 if (options == WithInternalFieldsAndRowID) {
01069 if (!d->fakeRowIDField) {
01070 d->fakeRowIDField = new Field("rowID", Field::BigInteger);
01071 d->fakeRowIDCol = new QueryColumnInfo(d->fakeRowIDField, QCString(), true);
01072 }
01073 tmpFieldsExpandedWithInternal->insert(
01074 fieldsExpandedVectorSize + internalFieldsCount, d->fakeRowIDCol );
01075 }
01076 }
01077 return *tmpFieldsExpandedWithInternal;
01078 }
01079
01080 if (options == Default)
01081 return *d->fieldsExpanded;
01082
01083
01084 QDict<char> columnsAlreadyFound;
01085 QueryColumnInfo::Vector result( d->fieldsExpanded->count() );
01086
01087
01088 uint uniqueListCount = 0;
01089 for (uint i=0; i<d->fieldsExpanded->count(); i++) {
01090 QueryColumnInfo *ci = (*d->fieldsExpanded)[i];
01091
01092
01093 if (!columnsAlreadyFound[ci->aliasOrName()]) {
01094 columnsAlreadyFound.insert(ci->aliasOrName(), (char*)1);
01095 result.insert(uniqueListCount++, ci);
01096 }
01097 }
01098 result.resize(uniqueListCount);
01099 return result;
01100 }
01101
01102 QueryColumnInfo::Vector QuerySchema::internalFields()
01103 {
01104 computeFieldsExpanded();
01105 return d->internalFields ? *d->internalFields : QueryColumnInfo::Vector();
01106 }
01107
01108 QueryColumnInfo* QuerySchema::expandedOrInternalField(uint index)
01109 {
01110 QueryColumnInfo::Vector vector = fieldsExpanded(WithInternalFields);
01111 return (index < vector.size()) ? vector[index] : 0;
01112 }
01113
01114 void QuerySchema::computeFieldsExpanded()
01115 {
01116 if (d->fieldsExpanded)
01117 return;
01118
01119 if (!d->columnsOrder) {
01120 d->columnsOrder = new QMap<QueryColumnInfo*,int>();
01121 d->columnsOrderWithoutAsterisks = new QMap<QueryColumnInfo*,int>();
01122 }
01123 else {
01124 d->columnsOrder->clear();
01125 d->columnsOrderWithoutAsterisks->clear();
01126 }
01127
01128
01129 QueryColumnInfo::List list;
01130 QueryColumnInfo::List lookup_list;
01131 QMap<QueryColumnInfo*, bool> columnInfosOutsideAsterisks;
01132 uint i = 0;
01133 uint fieldPosition = 0;
01134 Field *f;
01135 for (Field::ListIterator it = fieldsIterator(); (f = it.current()); ++it, fieldPosition++) {
01136 if (f->isQueryAsterisk()) {
01137 if (static_cast<QueryAsterisk*>(f)->isSingleTableAsterisk()) {
01138 Field::List *ast_fields = static_cast<QueryAsterisk*>(f)->table()->fields();
01139 for (Field *ast_f = ast_fields->first(); ast_f; ast_f=ast_fields->next()) {
01140
01141 QueryColumnInfo *ci = new QueryColumnInfo(ast_f, QCString(),
01142 isColumnVisible(fieldPosition));
01143 list.append( ci );
01144 KexiDBDbg << "QuerySchema::computeFieldsExpanded(): caching (unexpanded) columns order: "
01145 << ci->debugString() << " at position " << fieldPosition << endl;
01146 d->columnsOrder->insert(ci, fieldPosition);
01147
01148 }
01149 }
01150 else {
01151 for (TableSchema *table = d->tables.first(); table; table = d->tables.next()) {
01152
01153 Field::List *tab_fields = table->fields();
01154 for (Field *tab_f = tab_fields->first(); tab_f; tab_f = tab_fields->next()) {
01156
01157
01158 QueryColumnInfo *ci = new QueryColumnInfo(tab_f, QCString(),
01159 isColumnVisible(fieldPosition));
01160 list.append( ci );
01161 KexiDBDbg << "QuerySchema::computeFieldsExpanded(): caching (unexpanded) columns order: "
01162 << ci->debugString() << " at position " << fieldPosition << endl;
01163 d->columnsOrder->insert(ci, fieldPosition);
01164 }
01165 }
01166 }
01167 }
01168 else {
01169
01170
01171 QueryColumnInfo *ci = new QueryColumnInfo(f, columnAlias(fieldPosition), isColumnVisible(fieldPosition));
01172 list.append( ci );
01173 columnInfosOutsideAsterisks.insert( ci, true );
01174 KexiDBDbg << "QuerySchema::computeFieldsExpanded(): caching (unexpanded) column's order: "
01175 << ci->debugString() << " at position " << fieldPosition << endl;
01176 d->columnsOrder->insert(ci, fieldPosition);
01177 d->columnsOrderWithoutAsterisks->insert(ci, fieldPosition);
01178
01179
01180 LookupFieldSchema *lookupFieldSchema = f->table() ? f->table()->lookupFieldSchema( *f ) : 0;
01181 if (lookupFieldSchema) {
01182
01183
01184
01185
01186 LookupFieldSchema::RowSource& rowSource = lookupFieldSchema->rowSource();
01187 if (rowSource.type()==LookupFieldSchema::RowSource::Table) {
01188 TableSchema *lookupTable = connection()->tableSchema( rowSource.name() );
01189 Field *visibleField = 0;
01190 Field *boundField = 0;
01191 if (lookupTable && lookupFieldSchema->boundColumn()>=0
01192 && (uint)lookupFieldSchema->boundColumn() < lookupTable->fieldCount()
01193 && (visibleField = lookupTable->field( lookupFieldSchema->visibleColumn()))
01194 && (boundField = lookupTable->field( lookupFieldSchema->boundColumn() )))
01195 {
01196 lookup_list.append( new QueryColumnInfo(visibleField, QCString(), true) );
01197
01198
01199
01200
01201
01202
01203
01204
01205
01206
01207 }
01208 }
01209 }
01210 }
01211 }
01212
01213 if (!d->fieldsExpanded) {
01214 d->fieldsExpanded = new QueryColumnInfo::Vector( list.count() );
01215 d->fieldsExpanded->setAutoDelete(true);
01216 d->columnsOrderExpanded = new QMap<QueryColumnInfo*,int>();
01217 }
01218 else {
01219 d->fieldsExpanded->clear();
01220 d->fieldsExpanded->resize( list.count() );
01221 d->columnsOrderExpanded->clear();
01222 }
01223
01224
01225
01226
01227
01228
01229 d->columnInfosByName.clear();
01230 d->columnInfosByNameExpanded.clear();
01231 i=0;
01232 for (QueryColumnInfo::ListIterator it(list); it.current(); ++it, i++)
01233 {
01234 d->fieldsExpanded->insert(i, it.current());
01235 d->columnsOrderExpanded->insert(it.current(), i);
01236
01237 if (!it.current()->alias.isEmpty()) {
01238
01239 if (!d->columnInfosByNameExpanded[ it.current()->alias ])
01240 d->columnInfosByNameExpanded.insert( it.current()->alias, it.current() );
01241 QString tableAndAlias( it.current()->alias );
01242 if (it.current()->field->table())
01243 tableAndAlias.prepend(it.current()->field->table()->name() + ".");
01244 if (!d->columnInfosByNameExpanded[ tableAndAlias ])
01245 d->columnInfosByNameExpanded.insert( tableAndAlias, it.current() );
01246
01247 if (columnInfosOutsideAsterisks.contains(it.current())) {
01248 if (!d->columnInfosByName[ it.current()->alias ])
01249 d->columnInfosByName.insert( it.current()->alias, it.current() );
01250 if (!d->columnInfosByName[ tableAndAlias ])
01251 d->columnInfosByName.insert( tableAndAlias, it.current() );
01252 }
01253 }
01254 else {
01255
01256 if (!d->columnInfosByNameExpanded[ it.current()->field->name() ])
01257 d->columnInfosByNameExpanded.insert( it.current()->field->name(), it.current() );
01258 QString tableAndName( it.current()->field->name() );
01259 if (it.current()->field->table())
01260 tableAndName.prepend(it.current()->field->table()->name() + ".");
01261 if (!d->columnInfosByNameExpanded[ tableAndName ])
01262 d->columnInfosByNameExpanded.insert( tableAndName, it.current() );
01263
01264 if (columnInfosOutsideAsterisks.contains(it.current())) {
01265 if (!d->columnInfosByName[ it.current()->field->name() ])
01266 d->columnInfosByName.insert( it.current()->field->name(), it.current() );
01267 if (!d->columnInfosByName[ tableAndName ])
01268 d->columnInfosByName.insert( tableAndName, it.current() );
01269 }
01270 }
01271 }
01272
01273
01274 QDict<uint> lookup_dict;
01275
01276 lookup_dict.setAutoDelete(true);
01277 i=0;
01278 for (QueryColumnInfo::ListIterator it(lookup_list); it.current();)
01279 {
01280 QString tableAndFieldName( it.current()->field->table()->name()+"."+it.current()->field->name() );
01281 if ( columnInfo( tableAndFieldName )
01282 || lookup_dict[tableAndFieldName] ) {
01283
01284 lookup_list.removeRef( it.current() );
01285 }
01286 else {
01287 lookup_dict.replace( tableAndFieldName, new uint( i ) );
01288 ++it;
01289 i++;
01290 }
01291 }
01292
01293
01294 if (d->internalFields) {
01295 d->internalFields->clear();
01296 d->internalFields->resize( lookup_list.count() );
01297 }
01298 delete d->fieldsExpandedWithInternal;
01299 delete d->fieldsExpandedWithInternalAndRowID;
01300 d->fieldsExpandedWithInternal = 0;
01301 d->fieldsExpandedWithInternalAndRowID = 0;
01302 i=0;
01303 if (!lookup_list.isEmpty() && !d->internalFields) {
01304 d->internalFields = new QueryColumnInfo::Vector( lookup_list.count() );
01305 d->internalFields->setAutoDelete(true);
01306 }
01307 for (QueryColumnInfo::ListIterator it(lookup_list); it.current();i++, ++it)
01308 {
01309
01310 d->internalFields->insert(i, it.current());
01311 d->columnsOrderExpanded->insert(it.current(), list.count()+i);
01312 }
01313
01314
01315 for (i=0; i < d->fieldsExpanded->size(); i++) {
01316 QueryColumnInfo* ci = d->fieldsExpanded->at(i);
01318 LookupFieldSchema *lookupFieldSchema
01319 = ci->field->table() ? ci->field->table()->lookupFieldSchema( *ci->field ) : 0;
01320 if (lookupFieldSchema) {
01321 LookupFieldSchema::RowSource& rowSource = lookupFieldSchema->rowSource();
01322 TableSchema *lookupTable = connection()->tableSchema( rowSource.name() );
01323 Field *visibleField = 0;
01324 if (lookupTable && lookupFieldSchema->boundColumn()>=0
01325 && (uint)lookupFieldSchema->boundColumn() < lookupTable->fieldCount()
01326 && (visibleField = lookupTable->field( lookupFieldSchema->visibleColumn())))
01327 {
01328 QString visibleTableAndFieldName( visibleField->table()->name()+"."+visibleField->name() );
01329 uint *index = lookup_dict[ visibleTableAndFieldName ];
01330 if (index)
01331 ci->setIndexForVisibleLookupValue( d->fieldsExpanded->size() + *index );
01332 }
01333 }
01334 }
01335 }
01336
01337 QMap<QueryColumnInfo*,int> QuerySchema::columnsOrder(ColumnsOrderOptions options)
01338 {
01339 if (!d->columnsOrder)
01340 computeFieldsExpanded();
01341 if (options == UnexpandedList)
01342 return *d->columnsOrder;
01343 else if (options == UnexpandedListWithoutAsterisks)
01344 return *d->columnsOrderWithoutAsterisks;
01345 return *d->columnsOrderExpanded;
01346 }
01347
01348 QValueVector<int> QuerySchema::pkeyFieldsOrder()
01349 {
01350 if (d->pkeyFieldsOrder)
01351 return *d->pkeyFieldsOrder;
01352
01353 TableSchema *tbl = masterTable();
01354 if (!tbl || !tbl->primaryKey())
01355 return QValueVector<int>();
01356
01357
01358 IndexSchema *pkey = tbl->primaryKey();
01359 d->pkeyFieldsOrder = new QValueVector<int>( pkey->fieldCount(), -1 );
01360
01361 const uint fCount = fieldsExpanded().count();
01362 d->pkeyFieldsCount = 0;
01363 for (uint i = 0; i<fCount; i++) {
01364 QueryColumnInfo *fi = d->fieldsExpanded->at(i);
01365 const int fieldIndex = fi->field->table()==tbl ? pkey->indexOf(fi->field) : -1;
01366 if (fieldIndex!=-1
01367 && d->pkeyFieldsOrder->at(fieldIndex)==-1 )
01368 {
01369 KexiDBDbg << "QuerySchema::pkeyFieldsOrder(): FIELD " << fi->field->name()
01370 << " IS IN PKEY AT POSITION #" << fieldIndex << endl;
01371
01372 (*d->pkeyFieldsOrder)[fieldIndex]=i;
01373 d->pkeyFieldsCount++;
01374
01375 }
01376 }
01377 KexiDBDbg << "QuerySchema::pkeyFieldsOrder(): " << d->pkeyFieldsCount
01378 << " OUT OF " << pkey->fieldCount() << " PKEY'S FIELDS FOUND IN QUERY " << name() << endl;
01379 return *d->pkeyFieldsOrder;
01380 }
01381
01382 uint QuerySchema::pkeyFieldsCount()
01383 {
01384 (void)pkeyFieldsOrder();
01385 return d->pkeyFieldsCount;
01386 }
01387
01388 Relationship* QuerySchema::addRelationship( Field *field1, Field *field2 )
01389 {
01390
01391 Relationship *r = new Relationship(this, field1, field2);
01392 if (r->isEmpty()) {
01393 delete r;
01394 return 0;
01395 }
01396
01397 d->relations.append( r );
01398 return r;
01399 }
01400
01401 QueryColumnInfo::List* QuerySchema::autoIncrementFields()
01402 {
01403 if (!d->autoincFields) {
01404 d->autoincFields = new QueryColumnInfo::List();
01405 }
01406 TableSchema *mt = masterTable();
01407 if (!mt) {
01408 KexiDBWarn << "QuerySchema::autoIncrementFields(): no master table!" << endl;
01409 return d->autoincFields;
01410 }
01411 if (d->autoincFields->isEmpty()) {
01412 QueryColumnInfo::Vector fexp = fieldsExpanded();
01413 for (int i=0; i<(int)fexp.count(); i++) {
01414 QueryColumnInfo *fi = fexp[i];
01415 if (fi->field->table() == mt && fi->field->isAutoIncrement()) {
01416 d->autoincFields->append( fi );
01417 }
01418 }
01419 }
01420 return d->autoincFields;
01421 }
01422
01423 QString QuerySchema::sqlColumnsList(QueryColumnInfo::List* infolist, Driver *driver)
01424 {
01425 if (!infolist)
01426 return QString::null;
01427 QString result;
01428 result.reserve(256);
01429 QueryColumnInfo::ListIterator it( *infolist );
01430 bool start = true;
01431 for (; it.current(); ++it) {
01432 if (!start)
01433 result += ",";
01434 else
01435 start = false;
01436 result += driver->escapeIdentifier( it.current()->field->name() );
01437 }
01438 return result;
01439 }
01440
01441 QString QuerySchema::autoIncrementSQLFieldsList(Driver *driver)
01442 {
01443 if ((Driver *)d->lastUsedDriverForAutoIncrementSQLFieldsList != driver
01444 || d->autoIncrementSQLFieldsList.isEmpty())
01445 {
01446 d->autoIncrementSQLFieldsList = QuerySchema::sqlColumnsList( autoIncrementFields(), driver );
01447 d->lastUsedDriverForAutoIncrementSQLFieldsList = driver;
01448 }
01449 return d->autoIncrementSQLFieldsList;
01450 }
01451
01452 void QuerySchema::setWhereExpression(BaseExpr *expr)
01453 {
01454 delete d->whereExpr;
01455 d->whereExpr = expr;
01456 }
01457
01458 void QuerySchema::addToWhereExpression(KexiDB::Field *field, const QVariant& value, int relation)
01459 {
01460 int token;
01461 if (value.isNull())
01462 token = SQL_NULL;
01463 else if (field->isIntegerType()) {
01464 token = INTEGER_CONST;
01465 }
01466 else if (field->isFPNumericType()) {
01467 token = REAL_CONST;
01468 }
01469 else {
01470 token = CHARACTER_STRING_LITERAL;
01472 }
01473
01474 BinaryExpr * newExpr = new BinaryExpr(
01475 KexiDBExpr_Relational,
01476 new ConstExpr( token, value ),
01477 relation,
01478 new VariableExpr((field->table() ? (field->table()->name()+".") : QString::null)+field->name())
01479 );
01480 if (d->whereExpr) {
01481 d->whereExpr = new BinaryExpr(
01482 KexiDBExpr_Logical,
01483 d->whereExpr,
01484 AND,
01485 newExpr
01486 );
01487 }
01488 else {
01489 d->whereExpr = newExpr;
01490 }
01491 }
01492
01493
01494
01495
01496
01497
01498
01499
01500
01501
01502
01503
01504
01506
01507
01508
01509 BaseExpr *QuerySchema::whereExpression() const
01510 {
01511 return d->whereExpr;
01512 }
01513
01514 void QuerySchema::setOrderByColumnList(const OrderByColumnList& list)
01515 {
01516 d->orderByColumnList = list;
01517
01518 }
01519
01520 OrderByColumnList& QuerySchema::orderByColumnList() const
01521 {
01522 return d->orderByColumnList;
01523 }
01524
01525 QuerySchemaParameterList QuerySchema::parameters()
01526 {
01527 if (!whereExpression())
01528 return QuerySchemaParameterList();
01529 QuerySchemaParameterList params;
01530 whereExpression()->getQueryParameters(params);
01531 return params;
01532 }
01533
01534
01535
01536
01537
01538
01539
01540
01541
01542
01543
01544
01545
01546
01547
01548
01549
01550
01551
01552
01553
01554
01555
01556
01557
01558
01559
01560
01561
01562
01563
01564
01565
01566
01567
01568
01569
01570
01571
01572
01573
01574
01575
01576
01577
01578
01579
01580
01581
01582
01583
01584
01585
01586
01587
01588
01589
01590
01591 QueryAsterisk::QueryAsterisk( QuerySchema *query, TableSchema *table )
01592 :Field()
01593 ,m_table(table)
01594 {
01595 assert(query);
01596 m_parent = query;
01597 setType(Field::Asterisk);
01598 }
01599
01600 QueryAsterisk::~QueryAsterisk()
01601 {
01602 }
01603
01604 void QueryAsterisk::setTable(TableSchema *table)
01605 {
01606 KexiDBDbg << "QueryAsterisk::setTable()" << endl;
01607 m_table=table;
01608 }
01609
01610 QString QueryAsterisk::debugString()
01611 {
01612 QString dbg;
01613 if (isAllTableAsterisk()) {
01614 dbg += "ALL-TABLES ASTERISK (*) ON TABLES(";
01615 TableSchema *table;
01616 QString table_names;
01617 for (TableSchema::ListIterator it( *query()->tables() ); (table = it.current()); ++it) {
01618 if (!table_names.isEmpty())
01619 table_names += ", ";
01620 table_names += table->name();
01621 }
01622 dbg += (table_names + ")");
01623 }
01624 else {
01625 dbg += ("SINGLE-TABLE ASTERISK (" + table()->name() + ".*)");
01626 }
01627 return dbg;
01628 }
01629