20#include "kexidb/queryschema.h"
21#include "kexidb/driver.h"
22#include "kexidb/connection.h"
23#include "kexidb/expression.h"
24#include "kexidb/parser/sqlparser.h"
26#include "lookupfieldschema.h"
30#include <tqvaluelist.h>
31#include <tqasciidict.h>
34#include <tqbitarray.h>
41QueryColumnInfo::QueryColumnInfo(
Field *f,
const TQCString& _alias,
bool _visible,
43 : field(f), alias(_alias), visible(_visible), m_indexForVisibleLookupValue(-1)
44 , m_foreignColumn(foreignColumn)
48QueryColumnInfo::~QueryColumnInfo()
54 return field->name() +
55 ( alias.isEmpty() ? TQString()
56 : (TQString::fromLatin1(
" AS ") + TQString(alias)) );
62class QuerySchemaPrivate
65 QuerySchemaPrivate(
QuerySchema* q, QuerySchemaPrivate* copy = 0)
70 , maxIndexWithAlias(-1)
74 , fieldsExpandedWithInternalAndRowID(0)
75 , fieldsExpandedWithInternal(0)
78 , columnsOrderWithoutAsterisks(0)
79 , columnsOrderExpanded(0)
82 , tablesBoundToColumns(64, -1)
83 , tablePositionsForAliases(67, false)
84 , columnPositionsForAliases(67, false)
86 , ownedVisibleColumns(0)
87 , regenerateExprAliases(false)
89 columnAliases.setAutoDelete(
true);
90 tableAliases.setAutoDelete(
true);
91 asterisks.setAutoDelete(
true);
92 relations.setAutoDelete(
true);
93 tablePositionsForAliases.setAutoDelete(
true);
94 columnPositionsForAliases.setAutoDelete(
true);
95 visibility.fill(
false);
99 if (copy->fieldsExpanded)
100 fieldsExpanded =
new QueryColumnInfo::Vector(*copy->fieldsExpanded);
101 if (copy->internalFields)
102 internalFields =
new QueryColumnInfo::Vector(*copy->internalFields);
103 if (copy->fieldsExpandedWithInternalAndRowID)
104 fieldsExpandedWithInternalAndRowID =
new QueryColumnInfo::Vector(
105 *copy->fieldsExpandedWithInternalAndRowID);
106 if (copy->fieldsExpandedWithInternal)
107 fieldsExpandedWithInternal =
new QueryColumnInfo::Vector(
108 *copy->fieldsExpandedWithInternal);
109 if (copy->autoincFields)
110 autoincFields =
new QueryColumnInfo::List(*copy->autoincFields);
111 if (copy->columnsOrder)
112 columnsOrder =
new TQMap<QueryColumnInfo*,int>(*copy->columnsOrder);
113 if (copy->columnsOrderWithoutAsterisks)
114 columnsOrderWithoutAsterisks =
new TQMap<QueryColumnInfo*,int>(
115 *copy->columnsOrderWithoutAsterisks);
116 if (copy->columnsOrderExpanded)
117 columnsOrderExpanded =
new TQMap<QueryColumnInfo*,int>(*copy->columnsOrderExpanded);
118 if (copy->pkeyFieldsOrder)
119 pkeyFieldsOrder =
new TQValueVector<int>(*copy->pkeyFieldsOrder);
121 whereExpr = copy->whereExpr->copy();
122 if (copy->fakeRowIDCol)
124 if (copy->fakeRowIDField)
125 fakeRowIDField =
new Field(*copy->fakeRowIDField);
126 if (copy->ownedVisibleColumns)
127 ownedVisibleColumns =
new Field::List(*copy->ownedVisibleColumns);
130 ~QuerySchemaPrivate()
132 delete fieldsExpanded;
133 delete internalFields;
134 delete fieldsExpandedWithInternalAndRowID;
135 delete fieldsExpandedWithInternal;
136 delete autoincFields;
138 delete columnsOrderWithoutAsterisks;
139 delete columnsOrderExpanded;
140 delete pkeyFieldsOrder;
143 delete fakeRowIDField;
144 delete ownedVisibleColumns;
149 columnAliases.clear();
150 tableAliases.clear();
156 delete pkeyFieldsOrder;
158 visibility.fill(
false);
159 tablesBoundToColumns = TQValueVector<int>(64,-1);
160 tablePositionsForAliases.clear();
161 columnPositionsForAliases.clear();
164 void clearCachedData()
166 orderByColumnList.clear();
167 if (fieldsExpanded) {
168 delete fieldsExpanded;
170 delete internalFields;
174 delete columnsOrderWithoutAsterisks;
175 columnsOrderWithoutAsterisks = 0;
176 delete columnsOrderExpanded;
177 columnsOrderExpanded = 0;
178 delete autoincFields;
180 autoIncrementSQLFieldsList = TQString();
181 columnInfosByNameExpanded.clear();
182 columnInfosByName.clear();
183 delete ownedVisibleColumns;
184 ownedVisibleColumns = 0;
188 void setColumnAliasInternal(uint position,
const TQCString& alias)
190 columnAliases.replace(position,
new TQCString(alias));
191 columnPositionsForAliases.replace(alias,
new int(position));
192 maxIndexWithAlias = TQMAX( maxIndexWithAlias, (
int)position );
195 void setColumnAlias(uint position,
const TQCString& alias)
197 TQCString *oldAlias = columnAliases.take(position);
199 tablePositionsForAliases.remove(*oldAlias);
202 if (alias.isEmpty()) {
203 maxIndexWithAlias = -1;
206 setColumnAliasInternal(position, alias);
210 bool hasColumnAliases()
212 tryRegenerateExprAliases();
213 return !columnAliases.isEmpty();
216 TQCString* columnAlias(uint position)
218 tryRegenerateExprAliases();
219 return columnAliases[position];
232 Field *fakeRowIDField;
236 void tryRegenerateExprAliases()
238 if (!regenerateExprAliases)
244 TQCString columnAlias;
250 columnAlias = (i18n(
"short for 'expression' word (only latin letters, please)",
"expr")
251 + TQString::number(colNum)).latin1();
252 if (!tablePositionsForAliases[columnAlias])
255 setColumnAliasInternal(p, columnAlias);
258 regenerateExprAliases =
false;
262 TQIntDict<TQCString> columnAliases;
266 TQIntDict<TQCString> tableAliases;
269 int maxIndexWithAlias;
272 int maxIndexWithTableAlias;
275 TQBitArray visibility;
282 QueryColumnInfo::Vector *fieldsExpanded;
285 QueryColumnInfo::Vector *internalFields;
289 QueryColumnInfo::Vector *fieldsExpandedWithInternalAndRowID;
293 QueryColumnInfo::Vector *fieldsExpandedWithInternal;
299 QueryColumnInfo::List *autoincFields;
302 TQString autoIncrementSQLFieldsList;
303 TQGuardedPtr<Driver> lastUsedDriverForAutoIncrementSQLFieldsList;
306 TQMap<QueryColumnInfo*,int> *columnsOrder;
309 TQMap<QueryColumnInfo*,int> *columnsOrderWithoutAsterisks;
314 TQMap<QueryColumnInfo*,int> *columnsOrderExpanded;
319 TQValueVector<int> *pkeyFieldsOrder;
322 uint pkeyFieldsCount;
328 Relationship::List relations;
345 TQValueVector<int> tablesBoundToColumns;
348 TQAsciiDict<int> tablePositionsForAliases;
351 TQAsciiDict<int> columnPositionsForAliases;
356 TQDict<QueryColumnInfo> columnInfosByNameExpanded;
358 TQDict<QueryColumnInfo> columnInfosByName;
365 bool regenerateExprAliases : 1;
371OrderByColumn::OrderByColumn()
379OrderByColumn::OrderByColumn(
QueryColumnInfo& column,
bool ascending,
int pos)
383 , m_ascending(ascending)
387OrderByColumn::OrderByColumn(
Field& field,
bool ascending)
391 , m_ascending(ascending)
395OrderByColumn::~OrderByColumn()
401 TQString orderString(
m_ascending ?
"ascending" :
"descending" );
404 return TQString(
"COLUMN_AT_POSITION_%1(%2, %3)")
415 const TQString orderString(
m_ascending ?
"" :
" DESC" );
416 TQString fieldName, tableName;
419 return TQString::number(
m_pos+1) + orderString;
421 if (includeTableName &&
m_column->alias.isEmpty()) {
433 if (includeTableName) {
443 return tableName + fieldName + orderString;
454 const TQString& field1,
bool ascending1,
455 const TQString& field2,
bool ascending2,
456 const TQString& field3,
bool ascending3,
457 const TQString& field4,
bool ascending4,
458 const TQString& field5,
bool ascending5)
461#define ADD_COL(fieldName, ascending) \
462 if (ok && !fieldName.isEmpty()) { \
463 if (!appendField( querySchema, fieldName, ascending )) \
469 ADD_COL(field1, ascending1);
470 ADD_COL(field2, ascending2);
471 ADD_COL(field3, ascending3);
472 ADD_COL(field4, ascending4);
473 ADD_COL(field5, ascending5);
477 for (uint i=0; i<numAdded; i++)
482OrderByColumnList::~OrderByColumnList()
493 QueryColumnInfo::Vector fieldsExpanded( querySchema.
fieldsExpanded() );
494 QueryColumnInfo* ci = (pos >= (int)fieldsExpanded.size()) ? 0 : fieldsExpanded[pos];
507 const TQString& fieldName,
bool ascending)
519 KexiDBWarn <<
"OrderByColumnList::addColumn(QuerySchema& querySchema, "
520 "const TQString& column, bool ascending): no such field \"" << fieldName <<
"\"" << endl;
534 for (OrderByColumn::ListConstIterator it=constBegin(); it!=constEnd(); ++it) {
537 dbg += (*it).debugString();
545 for (OrderByColumn::ListConstIterator it=constBegin(); it!=constEnd(); ++it) {
548 string += (*it).toSQLString(includeTableNames, drv, identifierEscaping);
558 , d( new QuerySchemaPrivate(this) )
566 , d( new QuerySchemaPrivate(this) )
568 d->masterTable = &tableSchema;
578 m_name = d->masterTable->name();
580 m_caption = d->masterTable->caption();
594 , d( new QuerySchemaPrivate(this, querySchema.d) )
600 f = f_it.current()->
copy();
601 if (
static_cast<const KexiDB::FieldList *
>(f_it.current()->m_parent) == &querySchema)
610QuerySchema::~QuerySchema()
615void QuerySchema::init()
617 m_type = KexiDB::QueryObjectType;
640 int bindToTable,
bool visible)
643 KexiDBWarn <<
"QuerySchema::insertField(): !field" << endl;
647 if (position>m_fields.count()) {
648 KexiDBWarn <<
"QuerySchema::insertField(): position (" << position <<
") out of range" << endl;
652 KexiDBWarn <<
"QuerySchema::insertField(): WARNING: field '"<<field->name()
653 <<
"' must contain table information!" <<endl;
657 d->visibility.resize(d->visibility.size()*2);
658 d->tablesBoundToColumns.resize(d->tablesBoundToColumns.size()*2);
660 d->clearCachedData();
663 d->asterisks.append(field);
666 if (field->
table() && (d->tables.findRef(field->
table())==-1))
667 d->tables.append(field->
table());
669 else if (field->
table()) {
671 if (d->tables.findRef(field->
table())==-1)
672 d->tables.append(field->
table());
680 d->visibility.setBit(i, d->visibility.testBit(i-1));
681 d->visibility.setBit(position, visible);
684 if (bindToTable < -1 && bindToTable>(
int)d->tables.count()) {
685 KexiDBWarn <<
"QuerySchema::insertField(): bindToTable (" << bindToTable
686 <<
") out of range" << endl;
691 d->tablesBoundToColumns[i] = d->tablesBoundToColumns[i-1];
692 d->tablesBoundToColumns[ position ] = bindToTable;
694 KexiDBDbg <<
"QuerySchema::insertField(): bound to table (" << bindToTable <<
"): " <<endl;
696 KexiDBDbg <<
" <NOT SPECIFIED>" << endl;
698 KexiDBDbg <<
" name=" << d->tables.at(bindToTable)->name()
699 <<
" alias=" <<
tableAlias(bindToTable) << endl;
702 s+= (TQString::number(d->tablesBoundToColumns[i]) +
" ");
703 KexiDBDbg <<
"tablesBoundToColumns == [" << s <<
"]" <<endl;
706 d->regenerateExprAliases =
true;
713 if (columnPosition > d->tablesBoundToColumns.count()) {
714 KexiDBWarn <<
"QuerySchema::tableBoundToColumn(): columnPosition (" << columnPosition
715 <<
") out of range" << endl;
718 return d->tablesBoundToColumns[columnPosition];
723 return insertField(m_fields.count(), field, visible);
729 return insertField(m_fields.count(), field, bindToTable, visible);
736 d->clearCachedData();
738 d->asterisks.remove(field);
751 return (position <
fieldCount()) ? d->visibility.testBit(position) :
false;
757 d->visibility.setBit(position, v);
765 asterisk->m_name = (asterisk->
table() ? asterisk->
table()->name() +
".*" :
"*")
766 + TQString::number(
asterisks()->count());
783 +
"-masterTable=" + (mt ? mt->name() :
"<NULL>")
786 +
"-FIELDS EXPANDED ";
789 uint fieldsExpandedCount = 0;
792 fieldsExpandedCount = fe.size();
793 for ( uint i=0; i < fieldsExpandedCount; i++ ) {
804 dbg1.prepend( TQString(
"(%1):\n").arg(fieldsExpandedCount) );
818 if (!tAlias.isEmpty()) {
820 +
"\" uses alias \"" + TQString(tAlias) +
"\" of table \""
821 + d->tables.at(tablePos)->name() +
"\"\n");
825 if (!dbg2.isEmpty()) {
826 dbg +=
"\n-BINDINGS:\n";
832 TQString table_names;
833 table_names.reserve(512);
835 if (!table_names.isEmpty())
837 table_names += (TQString(
"'") +
table->name() +
"'");
839 if (d->tables.isEmpty())
840 table_names =
"<NONE>";
841 dbg += (TQString(
"-TABLES:\n") + table_names);
843 if (!d->hasColumnAliases())
844 aliases =
"<NONE>\n";
847 for (
int i=0; it.current(); ++it, i++) {
848 TQCString *alias = d->columnAlias(i);
850 aliases += (TQString(
"field #%1: ").arg(i)
851 + (it.current()->name().isEmpty() ?
"<noname>" : it.current()->name())
852 +
" -> " + (
const char*)*alias +
"\n");
856 dbg += TQString(
"\n-COLUMN ALIASES:\n" + aliases);
857 if (d->tableAliases.isEmpty())
862 for (
int i=0; t_it.current(); ++t_it, i++) {
863 TQCString *alias = d->tableAliases[i];
865 aliases += (TQString(
"table #%1: ").arg(i)
866 + (t_it.current()->name().isEmpty() ?
"<noname>" : t_it.current()->name())
867 +
" -> " + (
const char*)*alias +
"\n");
870 dbg += TQString(
"-TABLE ALIASES:\n" + aliases);
871 TQString where = d->whereExpr ? d->whereExpr->debugString() : TQString();
872 if (!where.isEmpty())
873 dbg += (TQString(
"\n-WHERE EXPRESSION:\n") + where);
883 return d->masterTable;
884 if (d->tables.isEmpty())
889 TQString tableNameLower;
891 if (!tableNameLower.isEmpty() && it.current()->name().lower()!=tableNameLower) {
897 return d->tables.first();
903 d->masterTable=
table;
913 KexiDBDbg <<
"QuerySchema::addTable() " << (
void *)
table
914 <<
" alias=" << alias << endl;
921 if (alias.isEmpty() && d->tables.findRef(
table)!=-1) {
922 const TQString& tableNameLower =
table->name().lower();
923 const TQString& aliasLower = TQString(alias.lower());
926 if (it.current()->name().lower()==tableNameLower) {
928 if (tAlias == aliasLower) {
929 KexiDBWarn <<
"QuerySchema::addTable(): table with \""
930 << tAlias <<
"\" alias already added!" << endl;
937 d->tables.append(
table);
939 if (!alias.isEmpty())
947 if (d->masterTable ==
table)
949 d->tables.remove(
table);
957 if (it.current()->name().lower()==tableName.lower())
965 return d->tables.findRef(
table)!=-1;
970 TQString tableName, fieldName;
975 if (tableName.isEmpty()) {
977 if (it.current()->field(fieldName))
978 return it.current()->field(fieldName);
985 return tableSchema->
field(fieldName);
990 TQCString *a = d->columnAlias(position);
991 return a ? *a : TQCString();
996 return d->columnAlias(position)!=0;
1001 if (position >= m_fields.count()) {
1002 KexiDBWarn <<
"QuerySchema::setColumnAlias(): position (" << position
1003 <<
") out of range!" << endl;
1006 TQCString fixedAlias = alias.stripWhiteSpace();
1009 KexiDBWarn <<
"QuerySchema::setColumnAlias(): position (" << position
1010 <<
") could not remove alias when no name is specified for expression column!" << endl;
1013 d->setColumnAlias(position, fixedAlias);
1018 TQCString *a = d->tableAliases[position];
1019 return a ? *a : TQCString();
1024 int *num = d->tablePositionsForAliases[name];
1034 if (it.current()->name().lower()==tableName.lower())
1043 TQValueList<int> result;
1044 const TQString& tableNameLower = tableName.lower();
1046 if (it.current()->name().lower()==tableNameLower) {
1055 return d->tableAliases[position]!=0;
1060 int *num = d->columnPositionsForAliases[name];
1068 if (position >= d->tables.count()) {
1069 KexiDBWarn <<
"QuerySchema::setTableAlias(): position (" << position
1070 <<
") out of range!" << endl;
1073 TQCString fixedAlias = alias.stripWhiteSpace();
1074 if (fixedAlias.isEmpty()) {
1075 TQCString *oldAlias = d->tableAliases.take(position);
1077 d->tablePositionsForAliases.remove(*oldAlias);
1083 d->tableAliases.replace(position,
new TQCString(fixedAlias));
1084 d->tablePositionsForAliases.replace(fixedAlias,
new int(position));
1091 return &d->relations;
1096 return &d->asterisks;
1101 return d->statement;
1112 return ci ? ci->field : 0;
1118 return expanded ? d->columnInfosByNameExpanded[identifier] : d->columnInfosByName[identifier];
1126 QueryColumnInfo::Vector*& tmpFieldsExpandedWithInternal =
1127 (options ==
WithInternalFields) ? d->fieldsExpandedWithInternal : d->fieldsExpandedWithInternalAndRowID;
1129 if (!tmpFieldsExpandedWithInternal) {
1131 const uint size = d->fieldsExpanded->count()
1132 + (d->internalFields ? d->internalFields->count() : 0)
1134 tmpFieldsExpandedWithInternal =
new QueryColumnInfo::Vector( size );
1135 const uint fieldsExpandedVectorSize = d->fieldsExpanded->size();
1136 for (uint i=0; i<fieldsExpandedVectorSize; i++)
1137 tmpFieldsExpandedWithInternal->insert(i, d->fieldsExpanded->at(i));
1138 const uint internalFieldsCount = d->internalFields ? d->internalFields->size() : 0;
1139 if (internalFieldsCount > 0) {
1140 for (uint i=0; i < internalFieldsCount; i++)
1141 tmpFieldsExpandedWithInternal->insert(
1142 fieldsExpandedVectorSize + i, d->internalFields->at(i));
1145 if (!d->fakeRowIDField) {
1147 d->fakeRowIDCol =
new QueryColumnInfo(d->fakeRowIDField, TQCString(),
true);
1149 tmpFieldsExpandedWithInternal->insert(
1150 fieldsExpandedVectorSize + internalFieldsCount, d->fakeRowIDCol );
1153 return *tmpFieldsExpandedWithInternal;
1157 return *d->fieldsExpanded;
1160 TQDict<char> columnsAlreadyFound;
1161 QueryColumnInfo::Vector result( d->fieldsExpanded->count() );
1164 uint uniqueListCount = 0;
1165 for (uint i=0; i<d->fieldsExpanded->count(); i++) {
1170 columnsAlreadyFound.insert(ci->
aliasOrName(), (
char*)1);
1171 result.insert(uniqueListCount++, ci);
1174 result.resize(uniqueListCount);
1181 return d->internalFields ? *d->internalFields : QueryColumnInfo::Vector();
1187 return (index < vector.size()) ? vector[index] : 0;
1190inline TQString lookupColumnKey(
Field *foreignField,
Field* field)
1194 res = field->
table()->name() +
".";
1195 return res + field->name() +
"_" + foreignField->
table()->name() +
"." + foreignField->name();
1200 if (d->fieldsExpanded)
1203 if (!d->columnsOrder) {
1204 d->columnsOrder =
new TQMap<QueryColumnInfo*,int>();
1205 d->columnsOrderWithoutAsterisks =
new TQMap<QueryColumnInfo*,int>();
1208 d->columnsOrder->clear();
1209 d->columnsOrderWithoutAsterisks->clear();
1211 if (d->ownedVisibleColumns)
1212 d->ownedVisibleColumns->clear();
1215 QueryColumnInfo::List list;
1216 QueryColumnInfo::List lookup_list;
1217 TQMap<QueryColumnInfo*, bool> columnInfosOutsideAsterisks;
1219 uint fieldPosition = 0;
1220 uint numberOfColumnsWithMultipleVisibleFields = 0;
1222 for (
Field::ListIterator it = fieldsIterator(); (f = it.current()); ++it, fieldPosition++) {
1226 for (
Field *ast_f = ast_fields->first(); ast_f; ast_f=ast_fields->next()) {
1231 KexiDBDbg <<
"QuerySchema::computeFieldsExpanded(): caching (unexpanded) columns order: "
1232 << ci->
debugString() <<
" at position " << fieldPosition << endl;
1233 d->columnsOrder->insert(ci, fieldPosition);
1241 for (
Field *tab_f = tab_fields->first(); tab_f; tab_f = tab_fields->next()) {
1248 KexiDBDbg <<
"QuerySchema::computeFieldsExpanded(): caching (unexpanded) columns order: "
1249 << ci->
debugString() <<
" at position " << fieldPosition << endl;
1250 d->columnsOrder->insert(ci, fieldPosition);
1260 columnInfosOutsideAsterisks.insert( ci,
true );
1261 KexiDBDbg <<
"QuerySchema::computeFieldsExpanded(): caching (unexpanded) column's order: "
1262 << ci->
debugString() <<
" at position " << fieldPosition << endl;
1263 d->columnsOrder->insert(ci, fieldPosition);
1264 d->columnsOrderWithoutAsterisks->insert(ci, fieldPosition);
1268 if (!lookupFieldSchema || lookupFieldSchema->
boundColumn()<0)
1278 Field *boundField = 0;
1284 Field *visibleColumn = 0;
1287 visibleColumn = visibleColumns->fields()->first();
1292 visibleColumn =
new Field();
1294 TQString::fromLatin1(
"[multiple_visible_fields_%1]")
1295 .arg( ++numberOfColumnsWithMultipleVisibleFields ));
1297 new ConstExpr(CHARACTER_STRING_LITERAL, TQVariant()));
1298 if (!d->ownedVisibleColumns) {
1300 d->ownedVisibleColumns->setAutoDelete(
true);
1302 d->ownedVisibleColumns->append( visibleColumn );
1318 delete visibleColumns;
1324 const QueryColumnInfo::Vector lookupQueryFieldsExpanded( lookupQuery->
fieldsExpanded() );
1325 if ((uint)lookupFieldSchema->
boundColumn() >= lookupQueryFieldsExpanded.count())
1328 if (!(boundColumnInfo = lookupQueryFieldsExpanded[ lookupFieldSchema->
boundColumn() ]))
1330 Field *boundField = boundColumnInfo->field;
1333 const TQValueList<uint> visibleColumns( lookupFieldSchema->
visibleColumns() );
1336 foreach (TQValueList<uint>::ConstIterator, visibleColumnsIt, visibleColumns) {
1337 if ((*visibleColumnsIt) >= lookupQueryFieldsExpanded.count()) {
1344 Field *visibleColumn = 0;
1346 if (visibleColumns.count() == 1) {
1347 visibleColumn = lookupQueryFieldsExpanded[ visibleColumns.first() ]->field;
1352 visibleColumn =
new Field();
1354 TQString::fromLatin1(
"[multiple_visible_fields_%1]")
1355 .arg( ++numberOfColumnsWithMultipleVisibleFields ));
1357 new ConstExpr(CHARACTER_STRING_LITERAL, TQVariant()));
1358 if (!d->ownedVisibleColumns) {
1360 d->ownedVisibleColumns->setAutoDelete(
true);
1362 d->ownedVisibleColumns->append( visibleColumn );
1381 if (!d->fieldsExpanded) {
1382 d->fieldsExpanded =
new QueryColumnInfo::Vector( list.count() );
1383 d->fieldsExpanded->setAutoDelete(
true);
1384 d->columnsOrderExpanded =
new TQMap<QueryColumnInfo*,int>();
1387 d->fieldsExpanded->clear();
1388 d->fieldsExpanded->resize( list.count() );
1389 d->columnsOrderExpanded->clear();
1397 d->columnInfosByName.clear();
1398 d->columnInfosByNameExpanded.clear();
1401 for (QueryColumnInfo::ListIterator it(list); (ci = it.current()); ++it, i++) {
1402 d->fieldsExpanded->insert(i, ci);
1403 d->columnsOrderExpanded->insert(ci, i);
1405 if (!ci->alias.isEmpty()) {
1407 if (!d->columnInfosByNameExpanded[ ci->alias ])
1408 d->columnInfosByNameExpanded.insert( ci->alias, ci );
1409 TQString tableAndAlias( ci->alias );
1410 if (ci->field->
table())
1411 tableAndAlias.prepend(ci->field->
table()->name() +
".");
1412 if (!d->columnInfosByNameExpanded[ tableAndAlias ])
1413 d->columnInfosByNameExpanded.insert( tableAndAlias, ci );
1415 if (columnInfosOutsideAsterisks.contains(ci)) {
1416 if (!d->columnInfosByName[ ci->alias ])
1417 d->columnInfosByName.insert( ci->alias, ci );
1418 if (!d->columnInfosByName[ tableAndAlias ])
1419 d->columnInfosByName.insert( tableAndAlias, ci );
1424 if (!d->columnInfosByNameExpanded[ ci->field->name() ])
1425 d->columnInfosByNameExpanded.insert( ci->field->name(), ci );
1426 TQString tableAndName( ci->field->name() );
1427 if (ci->field->
table())
1428 tableAndName.prepend(ci->field->
table()->name() +
".");
1429 if (!d->columnInfosByNameExpanded[ tableAndName ])
1430 d->columnInfosByNameExpanded.insert( tableAndName, ci );
1432 if (columnInfosOutsideAsterisks.contains(ci)) {
1433 if (!d->columnInfosByName[ ci->field->name() ])
1434 d->columnInfosByName.insert( ci->field->name(), ci );
1435 if (!d->columnInfosByName[ tableAndName ])
1436 d->columnInfosByName.insert( tableAndName, ci );
1442 TQDict<uint> lookup_dict(1009);
1444 lookup_dict.setAutoDelete(
true);
1446 for (QueryColumnInfo::ListIterator it(lookup_list); (ci = it.current());)
1448 const TQString key( lookupColumnKey(ci->
foreignColumn()->field, ci->field) );
1450 lookup_dict[ key ]) {
1453 lookup_list.removeRef( ci );
1456 lookup_dict.replace( key,
new uint( i ) );
1463 if (d->internalFields) {
1464 d->internalFields->clear();
1465 d->internalFields->resize( lookup_list.count() );
1467 delete d->fieldsExpandedWithInternal;
1468 delete d->fieldsExpandedWithInternalAndRowID;
1469 d->fieldsExpandedWithInternal = 0;
1470 d->fieldsExpandedWithInternalAndRowID = 0;
1471 if (!lookup_list.isEmpty() && !d->internalFields) {
1472 d->internalFields =
new QueryColumnInfo::Vector( lookup_list.count() );
1473 d->internalFields->setAutoDelete(
true);
1476 for (QueryColumnInfo::ListIterator it(lookup_list); it.current();i++, ++it)
1479 d->internalFields->insert(i, it.current());
1480 d->columnsOrderExpanded->insert(it.current(), list.count()+i);
1484 numberOfColumnsWithMultipleVisibleFields = 0;
1485 for (i=0; i < d->fieldsExpanded->size(); i++) {
1490 if (!lookupFieldSchema || lookupFieldSchema->
boundColumn()<0)
1500 Field *visibleColumn = 0;
1504 visibleColumn = visibleColumns->fields()->first();
1505 const TQString key( lookupColumnKey(ci->field, visibleColumn) );
1506 uint *index = lookup_dict[ key ];
1511 const TQString key( TQString::fromLatin1(
"[multiple_visible_fields_%1]_%2.%3")
1512 .arg( ++numberOfColumnsWithMultipleVisibleFields )
1513 .arg(ci->field->
table()->name()).arg(ci->field->name()) );
1514 uint *index = lookup_dict[ key ];
1519 delete visibleColumns;
1525 const QueryColumnInfo::Vector lookupQueryFieldsExpanded( lookupQuery->
fieldsExpanded() );
1526 if ((uint)lookupFieldSchema->
boundColumn() >= lookupQueryFieldsExpanded.count())
1529 if (!(boundColumnInfo = lookupQueryFieldsExpanded[ lookupFieldSchema->
boundColumn() ]))
1531 Field *boundField = boundColumnInfo->field;
1534 const TQValueList<uint> visibleColumns( lookupFieldSchema->
visibleColumns() );
1535 Field *visibleColumn = 0;
1537 if (visibleColumns.count() == 1) {
1538 visibleColumn = lookupQueryFieldsExpanded[ visibleColumns.first() ]->field;
1539 const TQString key( lookupColumnKey(ci->field, visibleColumn) );
1540 uint *index = lookup_dict[ key ];
1545 const TQString key( TQString::fromLatin1(
"[multiple_visible_fields_%1]_%2.%3")
1546 .arg( ++numberOfColumnsWithMultipleVisibleFields )
1547 .arg(ci->field->
table()->name()).arg(ci->field->name()) );
1548 uint *index = lookup_dict[ key ];
1554 KexiDBWarn <<
"QuerySchema::computeFieldsExpanded(): unsupported row source type "
1562 if (!d->columnsOrder)
1565 return *d->columnsOrder;
1567 return *d->columnsOrderWithoutAsterisks;
1568 return *d->columnsOrderExpanded;
1573 if (d->pkeyFieldsOrder)
1574 return *d->pkeyFieldsOrder;
1578 return TQValueVector<int>();
1584 d->pkeyFieldsOrder =
new TQValueVector<int>( pkey->
fieldCount(), -1 );
1587 d->pkeyFieldsCount = 0;
1588 for (uint i = 0; i<fCount; i++) {
1590 const int fieldIndex = fi->field->
table()==tbl ? pkey->
indexOf(fi->field) : -1;
1592 && d->pkeyFieldsOrder->at(fieldIndex)==-1 )
1594 KexiDBDbg <<
"QuerySchema::pkeyFieldsOrder(): FIELD " << fi->field->name()
1595 <<
" IS IN PKEY AT POSITION #" << fieldIndex << endl;
1597 (*d->pkeyFieldsOrder)[fieldIndex]=i;
1598 d->pkeyFieldsCount++;
1602 KexiDBDbg <<
"QuerySchema::pkeyFieldsOrder(): " << d->pkeyFieldsCount
1603 <<
" OUT OF " << pkey->
fieldCount() <<
" PKEY'S FIELDS FOUND IN QUERY " << name() << endl;
1604 return *d->pkeyFieldsOrder;
1610 return d->pkeyFieldsCount;
1616 Relationship *r =
new Relationship(
this, field1, field2);
1622 d->relations.append( r );
1628 if (!d->autoincFields) {
1629 d->autoincFields =
new QueryColumnInfo::List();
1633 KexiDBWarn <<
"QuerySchema::autoIncrementFields(): no master table!" << endl;
1634 return d->autoincFields;
1636 if (d->autoincFields->isEmpty()) {
1638 for (
int i=0; i<(int)fexp.count(); i++) {
1641 d->autoincFields->append( fi );
1645 return d->autoincFields;
1653 result.reserve(256);
1654 QueryColumnInfo::ListIterator it( *infolist );
1656 for (; it.current(); ++it) {
1668 if ((
Driver *)d->lastUsedDriverForAutoIncrementSQLFieldsList != driver
1669 || d->autoIncrementSQLFieldsList.isEmpty())
1672 d->lastUsedDriverForAutoIncrementSQLFieldsList = driver;
1674 return d->autoIncrementSQLFieldsList;
1679 delete d->whereExpr;
1680 d->whereExpr = expr;
1689 token = INTEGER_CONST;
1695 token = CHARACTER_STRING_LITERAL;
1700 KexiDBExpr_Relational,
1714 d->whereExpr = newExpr;
1736 return d->whereExpr;
1741 d->orderByColumnList = list;
1747 return d->orderByColumnList;
1753 return QuerySchemaParameterList();
1754 QuerySchemaParameterList params;
1825QueryAsterisk::~QueryAsterisk()
1836 KexiDBDbg <<
"QueryAsterisk::setTable()" << endl;
1844 dbg +=
"ALL-TABLES ASTERISK (*) ON TABLES(";
1846 TQString table_names;
1848 if (!table_names.isEmpty())
1849 table_names +=
", ";
1850 table_names +=
table->name();
1852 dbg += (table_names +
")");
1855 dbg += (
"SINGLE-TABLE ASTERISK (" +
table()->name() +
".*)");
A base class for all expressions.
virtual void getQueryParameters(QuerySchemaParameterList ¶ms)=0
Provides database connection, allowing queries and data modification.
TableSchema * tableSchema(int tableId)
QuerySchema * querySchema(int queryId)
Generic database abstraction.
TQString escapeIdentifier(const TQString &str, int options=EscapeDriver|EscapeAsNecessary) const
Driver-specific identifier escaping (e.g. for a table name, db name, etc.)
virtual void removeField(KexiDB::Field *field)
FieldList * subList(const TQString &n1, const TQString &n2=TQString(), const TQString &n3=TQString(), const TQString &n4=TQString(), const TQString &n5=TQString(), const TQString &n6=TQString(), const TQString &n7=TQString(), const TQString &n8=TQString(), const TQString &n9=TQString(), const TQString &n10=TQString(), const TQString &n11=TQString(), const TQString &n12=TQString(), const TQString &n13=TQString(), const TQString &n14=TQString(), const TQString &n15=TQString(), const TQString &n16=TQString(), const TQString &n17=TQString(), const TQString &n18=TQString())
virtual TQString debugString()
virtual FieldList & insertField(uint index, Field *field)
int indexOf(const Field *field)
virtual Field * copy() const
virtual TQString debugString() const
void setName(const TQString &name)
@ Asterisk
Special, internal types:
TQString captionOrName() const
TQPtrList< Field > List
list of fields
FieldList * m_parent
In most cases this points to a TableSchema object that field is assigned.
bool isFPNumericType() const
bool isIntegerType() const
bool isAutoIncrement() const
TQPtrListIterator< Field > ListIterator
iterator for list of fields
virtual bool isQueryAsterisk() const
bool isExpression() const
void setExpression(KexiDB::BaseExpr *expr)
virtual TableSchema * table() const
Provides information about database index that can be created for a database table.
Row source information that can be specified for the lookup field schema.
TQString typeName() const
@ Table
table as lookup row source
@ Query
named query as lookup row source
Provides information about lookup field's setup.
TQValueList< uint > visibleColumns() const
KexiDB::OrderByColumnList provides list of sorted columns for a query schema.
void appendColumn(QueryColumnInfo &columnInfo, bool ascending=true)
TQString toSQLString(bool includeTableNames=true, Driver *drv=0, int identifierEscaping=Driver::EscapeDriver|Driver::EscapeAsNecessary) const
bool appendFields(QuerySchema &querySchema, const TQString &field1, bool ascending1=true, const TQString &field2=TQString(), bool ascending2=true, const TQString &field3=TQString(), bool ascending3=true, const TQString &field4=TQString(), bool ascending4=true, const TQString &field5=TQString(), bool ascending5=true)
TQString debugString() const
void appendField(Field &field, bool ascending=true)
KexiDB::OrderByColumn provides information about a single query column used for sorting.
QueryColumnInfo * m_column
Column to sort.
TQString debugString() const
TQString toSQLString(bool includeTableName=true, Driver *drv=0, int identifierEscaping=Driver::EscapeDriver|Driver::EscapeAsNecessary) const
Field * m_field
Used only in case when the second contructor is used.
int m_pos
A helper for m_column that allows to know that sorting column was defined by providing its position.
bool m_ascending
true if ascending sorting should be performed (the default).
KexiDB::QueryAsterisk class encapsulates information about single asterisk in query definition.
virtual void setTable(TableSchema *table)
bool isAllTableAsterisk() const
virtual Field * copy() const
QuerySchema * query() const
bool isSingleTableAsterisk() const
virtual TableSchema * table() const
virtual TQString debugString() const
QueryAsterisk(QuerySchema *query, TableSchema *table=0)
Helper class that assigns additional information for the column in a query.
TQCString aliasOrName() const
QueryColumnInfo * foreignColumn() const
void setIndexForVisibleLookupValue(int index)
TQString debugString() const
KexiDB::QuerySchema provides information about database query.
TableSchema * masterTable() const
TQCString columnAlias(uint position) const
FieldList & addExpression(BaseExpr *expr, bool visible=true)
int tablePosition(const TQString &tableName) const
Relationship::List * relationships() const
virtual TQString debugString()
virtual FieldList & insertField(uint position, Field *field)
void addTable(TableSchema *table, const TQCString &alias=TQCString())
Connection * connection() const
TQString autoIncrementSQLFieldsList(Driver *driver)
void setColumnVisible(uint position, bool v)
Sets visibility flag for column at position to v.
void setTableAlias(uint position, const TQCString &alias)
virtual Field * field(const TQString &name, bool expanded=true)
FieldList & addAsterisk(QueryAsterisk *asterisk, bool visible=true)
void setWhereExpression(BaseExpr *expr)
Relationship * addRelationship(Field *field1, Field *field2)
void setStatement(const TQString &s)
OrderByColumnList & orderByColumnList() const
TQValueList< int > tablePositions(const TQString &tableName) const
TableSchema * table(const TQString &tableName) const
@ WithInternalFieldsAndRowID
Like WithInternalFields but RowID (big int type) field is appended after internal fields.
@ Default
All fields are returned even if duplicated.
@ WithInternalFields
Like Default but internal fields (for lookup) are appended.
int tablePositionForAlias(const TQCString &name) const
TQMap< QueryColumnInfo *, int > columnsOrder(ColumnsOrderOptions options=ExpandedList)
bool hasColumnAlias(uint position) const
void removeTable(TableSchema *table)
QueryColumnInfo::Vector fieldsExpanded(FieldsExpandedOptions options=Default)
TQValueVector< int > pkeyFieldsOrder()
bool hasTableAlias(uint position) const
bool isColumnVisible(uint position) const
QueryColumnInfo::Vector internalFields()
@ UnexpandedList
A map for unexpanded list is created.
@ UnexpandedListWithoutAsterisks
A map for unexpanded list is created, with asterisks skipped.
QueryColumnInfo::List * autoIncrementFields()
int tableBoundToColumn(uint columnPosition) const
void setMasterTable(TableSchema *table)
void computeFieldsExpanded()
int columnPositionForAlias(const TQCString &name) const
Field * findTableField(const TQString &tableOrTableAndFieldName) const
bool contains(TableSchema *table) const
Field::List * asterisks() const
TableSchema::List * tables() const
TQCString tableAlias(uint position) const
QueryColumnInfo * columnInfo(const TQString &identifier, bool expanded=true)
static TQString sqlColumnsList(QueryColumnInfo::List *infolist, Driver *driver)
TQString statement() const
void setOrderByColumnList(const OrderByColumnList &list)
BaseExpr * whereExpression() const
FieldList & addField(Field *field, bool visible=true)
virtual void removeField(Field *field)
QueryColumnInfo * expandedOrInternalField(uint index)
void addToWhereExpression(KexiDB::Field *field, const TQVariant &value, int relation='=')
void setColumnAlias(uint position, const TQCString &alias)
QuerySchemaParameterList parameters()
virtual TQString schemaDataDebugString() const
void clear()
Clears all properties except 'type'.
Connection * connection() const
IndexSchema * primaryKey() const
TQPtrListIterator< TableSchema > ListIterator
Iterator for tables list.
TQPtrList< TableSchema > List
Type of tables list.
LookupFieldSchema * lookupFieldSchema(const Field &field) const
Variables like fieldname or tablename.fieldname
High-level database connectivity library with database backend drivers.
TQValueList< OrderByColumn > OrderByColumnListBase
A base for KexiDB::OrderByColumnList.
KEXI_DB_EXPORT bool splitToTableAndFieldParts(const TQString &string, TQString &tableName, TQString &fieldName, SplitToTableAndFieldPartsOptions option=FailIfNoTableOrFieldName)
@ SetFieldNameIfNoTableName
see splitToTableAndFieldParts()