diff --git a/kexi/kexidb/drivers/mysql/mysqlcursor.cpp b/kexi/kexidb/drivers/mysql/mysqlcursor.cpp --- a/kexi/kexidb/drivers/mysql/mysqlcursor.cpp +++ b/kexi/kexidb/drivers/mysql/mysqlcursor.cpp @@ -1,6 +1,6 @@ /* This file is part of the KDE project Copyright (C) 2003 Joseph Wenninger - Copyright (C) 2005 Jarosław Staniek + Copyright (C) 2005-2016 Jarosław Staniek This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -112,8 +112,8 @@ if (!d->mysqlrow || pos >= m_fieldCount || d->mysqlrow[pos] == 0) return QVariant(); - KexiDB::Field *f = (m_fieldsExpanded && pos < (uint)m_fieldsExpanded->count()) - ? m_fieldsExpanded->at(pos)->field : 0; + const KexiDB::Field *f = (m_visibleFieldsExpanded && pos < uint(m_visibleFieldsExpanded->count())) + ? m_visibleFieldsExpanded->at(pos)->field : 0; //! @todo js: use MYSQL_FIELD::type here! @@ -130,15 +130,15 @@ if (d->numRows == 0) return false; -//! @todo js: use MYSQL_FIELD::type here! -//! see SQLiteCursor::storeCurrentRow() - - const uint fieldsExpandedCount = m_fieldsExpanded ? m_fieldsExpanded->count() : UINT_MAX; - const uint realCount = qMin(fieldsExpandedCount, m_fieldsToStoreInRow); - for (uint i = 0; i < realCount; i++) { - Field *f = m_fieldsExpanded ? m_fieldsExpanded->at(i)->field : 0; - if (m_fieldsExpanded && !f) - continue; + if (!m_visibleFieldsExpanded) {//simple version: without types + for (uint i = 0; i < m_fieldCount; i++) { + data[i] = QString::fromUtf8(d->mysqlrow[i], d->lengths[i]); + } + return true; + } + + for (int i = 0; i < int(m_fieldCount); ++i) { + Field *f = m_visibleFieldsExpanded->at(i)->field; data[i] = KexiDB::cstringToVariant(d->mysqlrow[i], f, d->lengths[i]); } return true; diff --git a/kexi/kexidb/drivers/pqxx/pqxxcursor.cpp b/kexi/kexidb/drivers/pqxx/pqxxcursor.cpp --- a/kexi/kexidb/drivers/pqxx/pqxxcursor.cpp +++ b/kexi/kexidb/drivers/pqxx/pqxxcursor.cpp @@ -174,11 +174,10 @@ return QVariant(); } - KexiDB::Field *f = (m_fieldsExpanded && pos < qMin((uint)m_fieldsExpanded->count(), m_fieldCount)) - ? m_fieldsExpanded->at(pos)->field : 0; - // KexiDBDrvDbg << pos; //from most to least frequently used types: + const Field *f = (m_visibleFieldsExpanded && pos < uint(m_visibleFieldsExpanded->count())) + ? m_visibleFieldsExpanded->at(pos)->field : 0; if (f) { //We probably have a schema type query so can use kexi to determin the row type const Field::Type type = f->type(); // cache: evaluating type of expressions can be expensive if (type == Field::Null || type == Field::InvalidType) { diff --git a/kexi/kexidb/drivers/sybase/sybasecursor.cpp b/kexi/kexidb/drivers/sybase/sybasecursor.cpp --- a/kexi/kexidb/drivers/sybase/sybasecursor.cpp +++ b/kexi/kexidb/drivers/sybase/sybasecursor.cpp @@ -147,8 +147,8 @@ if (!d->dbProcess || pos >= m_fieldCount) return QVariant(); - KexiDB::Field *f = (m_fieldsExpanded && pos < uint(m_fieldsExpanded->count())) - ? m_fieldsExpanded->at(pos)->field : 0; + KexiDB::Field *f = (m_visibleFieldsExpanded && pos < uint(m_visibleFieldsExpanded->count())) + ? m_visibleFieldsExpanded->at(pos)->field : 0; // db-library indexes its columns from 1 pos = pos + 1; @@ -182,11 +182,11 @@ // if (d->numRows<=0) // return false; - const uint fieldsExpandedCount = m_fieldsExpanded ? m_fieldsExpanded->count() : UINT_MAX; + const uint fieldsExpandedCount = m_visibleFieldsExpanded ? m_visibleFieldsExpanded->count() : UINT_MAX; const uint realCount = qMin(fieldsExpandedCount, m_fieldsToStoreInRow); for (uint i = 0; i < realCount; i++) { - Field *f = m_fieldsExpanded ? m_fieldsExpanded->at(i)->field : 0; - if (m_fieldsExpanded && !f) + Field *f = m_visibleFieldsExpanded ? m_visibleFieldsExpanded->at(i)->field : 0; + if (m_visibleFieldsExpanded && !f) continue; long int columnDataLength = dbdatlen(d->dbProcess, i + 1); diff --git a/libs/db/cursor.h b/libs/db/cursor.h --- a/libs/db/cursor.h +++ b/libs/db/cursor.h @@ -1,5 +1,5 @@ /* This file is part of the KDE project - Copyright (C) 2003-2006 Jarosław Staniek + Copyright (C) 2003-2016 Jarosław Staniek This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -393,7 +393,7 @@ // //! Useful e.g. for value(int) method when we need access to schema def. - QueryColumnInfo::Vector* m_fieldsExpanded; + QueryColumnInfo::Vector* m_visibleFieldsExpanded; //! Used by setOrderByColumnList() QueryColumnInfo::Vector* m_orderByColumnList; diff --git a/libs/db/cursor.cpp b/libs/db/cursor.cpp --- a/libs/db/cursor.cpp +++ b/libs/db/cursor.cpp @@ -1,5 +1,5 @@ /* This file is part of the KDE project - Copyright (C) 2003-2006 Jarosław Staniek + Copyright (C) 2003-2016 Jarosław Staniek This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -87,15 +87,15 @@ if (m_query) { //get list of all fields - m_fieldsExpanded = new QueryColumnInfo::Vector(); - *m_fieldsExpanded = m_query->fieldsExpanded( + m_visibleFieldsExpanded = new QueryColumnInfo::Vector(); + *m_visibleFieldsExpanded = m_query->visibleFieldsExpanded( m_containsROWIDInfo ? QuerySchema::WithInternalFieldsAndRowID : QuerySchema::WithInternalFields); - m_logicalFieldCount = m_fieldsExpanded->count() + m_logicalFieldCount = m_visibleFieldsExpanded->count() - m_query->internalFields().count() - (m_containsROWIDInfo ? 1 : 0); - m_fieldCount = m_fieldsExpanded->count(); + m_fieldCount = m_visibleFieldsExpanded->count(); m_fieldsToStoreInRow = m_fieldCount; } else { - m_fieldsExpanded = 0; + m_visibleFieldsExpanded = 0; m_logicalFieldCount = 0; m_fieldCount = 0; m_fieldsToStoreInRow = 0; @@ -128,7 +128,7 @@ exit(1); } } - delete m_fieldsExpanded; + delete m_visibleFieldsExpanded; delete m_queryParameters; } diff --git a/libs/db/drivers/sqlite/sqlitecursor.cpp b/libs/db/drivers/sqlite/sqlitecursor.cpp --- a/libs/db/drivers/sqlite/sqlitecursor.cpp +++ b/libs/db/drivers/sqlite/sqlitecursor.cpp @@ -1,5 +1,5 @@ /* This file is part of the KDE project - Copyright (C) 2003-2006 Jarosław Staniek + Copyright (C) 2003-2016 Jarosław Staniek This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -383,27 +383,15 @@ { //const uint realCount = m_fieldCount + (m_containsROWIDInfo ? 1 : 0); //not needed data.resize(m_fieldCount); - if (!m_fieldsExpanded) {//simple version: without types + if (!m_visibleFieldsExpanded) {//simple version: without types for (uint i = 0; i < m_fieldCount; i++) { data[i] = QString::fromUtf8((const char*)sqlite3_column_text(d->prepared_st_handle, i)); } return true; } - //const uint fieldsExpandedCount = m_fieldsExpanded->count(); - const uint maxCount = qMin(m_fieldCount, (uint)m_fieldsExpanded->count()); - // i - visible field's index, j - physical index - for (uint i = 0, j = 0; i < m_fieldCount; ++i, ++j) { -// while (j < m_detailedVisibility.count() && !m_detailedVisibility[j]) //!m_query->isColumnVisible(j)) -// j++; - while (j < maxCount && !m_fieldsExpanded->at(j)->visible) - j++; - if (j >= (maxCount /*+(m_containsROWIDInfo ? 1 : 0)*/)) { - //ERR! - break; - } - //(m_logicalFieldCount introduced) Field *f = (m_containsROWIDInfo && i>=m_fieldCount) ? 0 : m_fieldsExpanded->at(j)->field; - Field *f = (i >= m_fieldCount) ? 0 : m_fieldsExpanded->at(j)->field; + for (uint i = 0; i < m_fieldCount; ++i) { + Field *f = m_visibleFieldsExpanded->at(i)->field; // KexiDBDrvDbg << "SQLiteCursor::storeCurrentRow(): col=" << (col ? *col : 0); data[i] = d->getValue(f, i); //, !f /*!f means ROWID*/); } @@ -417,8 +405,8 @@ return QVariant(); //TODO: allow disable range checking! - performance reasons // const KexiDB::Field *f = m_query ? m_query->field(i) : 0; - KexiDB::Field *f = (m_fieldsExpanded && i < (uint)m_fieldsExpanded->count()) - ? m_fieldsExpanded->at(i)->field : 0; + KexiDB::Field *f = (m_visibleFieldsExpanded && i < (uint)m_visibleFieldsExpanded->count()) + ? m_visibleFieldsExpanded->at(i)->field : 0; return d->getValue(f, i); //, i==m_logicalFieldCount/*ROWID*/); } diff --git a/libs/db/queryschema.h b/libs/db/queryschema.h --- a/libs/db/queryschema.h +++ b/libs/db/queryschema.h @@ -1,5 +1,5 @@ /* This file is part of the KDE project - Copyright (C) 2003-2012 Jarosław Staniek + Copyright (C) 2003-2016 Jarosław Staniek This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -611,7 +611,7 @@ explicitly specify "t2.name" as the identifier to get the second column. */ QueryColumnInfo* columnInfo(const QString& identifier, bool expanded = true); - /*! Options used in fieldsExpanded(). */ + /*! Options used in fieldsExpanded() and visibleFieldsExpanded(). */ enum FieldsExpandedOptions { Default, //!< All fields are returned even if duplicated Unique, //!< Unique list of fields is returned @@ -661,7 +661,14 @@ This method's result is cached by QuerySchema object. @todo js: UPDATE CACHE! */ - QueryColumnInfo::Vector fieldsExpanded(FieldsExpandedOptions options = Default); + inline QueryColumnInfo::Vector fieldsExpanded(FieldsExpandedOptions options = Default) { + return fieldsExpandedInternal(options, false); + } + + /*! Like fieldsExpanded() but returns only visible fields. */ + inline QueryColumnInfo::Vector visibleFieldsExpanded(FieldsExpandedOptions options = Default) { + return fieldsExpandedInternal(options, true); + } /*! \return list of internal fields used for lookup columns. */ QueryColumnInfo::Vector internalFields(); @@ -825,6 +832,9 @@ void computeFieldsExpanded(); + //! Used by fieldsExpanded(FieldsExpandedOptions) and visibleFieldsExpanded(FieldsExpandedOptions options). + QueryColumnInfo::Vector fieldsExpandedInternal(FieldsExpandedOptions options, bool onlyVisible); + QuerySchemaPrivate * const d; friend class Connection; diff --git a/libs/db/queryschema.cpp b/libs/db/queryschema.cpp --- a/libs/db/queryschema.cpp +++ b/libs/db/queryschema.cpp @@ -1,5 +1,5 @@ /* This file is part of the KDE project - Copyright (C) 2003-2012 Jarosław Staniek + Copyright (C) 2003-2016 Jarosław Staniek This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -881,27 +881,32 @@ return expanded ? d->columnInfosByNameExpanded[identifier] : d->columnInfosByName[identifier]; } -QueryColumnInfo::Vector QuerySchema::fieldsExpanded(FieldsExpandedOptions options) +QueryColumnInfo::Vector QuerySchema::fieldsExpandedInternal(FieldsExpandedOptions options, bool onlyVisible) { computeFieldsExpanded(); + QueryColumnInfo::Vector *realFieldsExpanded = onlyVisible ? d->visibleFieldsExpanded : d->fieldsExpanded; if (options == WithInternalFields || options == WithInternalFieldsAndRowID) { //a ref to a proper pointer (as we cache the vector for two cases) QueryColumnInfo::Vector*& tmpFieldsExpandedWithInternal = - (options == WithInternalFields) ? d->fieldsExpandedWithInternal : d->fieldsExpandedWithInternalAndRowID; + (options == WithInternalFields) ? + (onlyVisible ? d->visibleFieldsExpandedWithInternal : d->fieldsExpandedWithInternal) + : (onlyVisible ? d->visibleFieldsExpandedWithInternalAndRowID : d->fieldsExpandedWithInternalAndRowID); //special case if (!tmpFieldsExpandedWithInternal) { //glue expanded and internal fields and cache it - const uint size = d->fieldsExpanded->count() - + (d->internalFields ? d->internalFields->count() : 0) + const uint internalFieldsCount = d->internalFields ? d->internalFields->size() : 0; + const uint fieldsExpandedVectorSize = realFieldsExpanded->size(); + const uint size = fieldsExpandedVectorSize + internalFieldsCount + ((options == WithInternalFieldsAndRowID) ? 1 : 0) /*ROWID*/; tmpFieldsExpandedWithInternal = new QueryColumnInfo::Vector(size); - const uint fieldsExpandedVectorSize = d->fieldsExpanded->size(); - for (uint i = 0; i < fieldsExpandedVectorSize; i++) - (*tmpFieldsExpandedWithInternal)[i] = d->fieldsExpanded->at(i); - const uint internalFieldsCount = d->internalFields ? d->internalFields->size() : 0; + for (uint i = 0; i < fieldsExpandedVectorSize; i++) { + (*tmpFieldsExpandedWithInternal)[i] = realFieldsExpanded->at(i); + } if (internalFieldsCount > 0) { - for (uint i = 0; i < internalFieldsCount; i++) - (*tmpFieldsExpandedWithInternal)[fieldsExpandedVectorSize + i] = d->internalFields->at(i); + for (uint i = 0; i < internalFieldsCount; i++) { + QueryColumnInfo *info = d->internalFields->at(i); + (*tmpFieldsExpandedWithInternal)[fieldsExpandedVectorSize + i] = info; + } } if (options == WithInternalFieldsAndRowID) { if (!d->fakeRowIDField) { @@ -914,18 +919,19 @@ return *tmpFieldsExpandedWithInternal; } - if (options == Default) - return *d->fieldsExpanded; + if (options == Default) { + return *realFieldsExpanded; + } //options == Unique: QSet columnsAlreadyFound; - const uint fieldsExpandedCount(d->fieldsExpanded->count()); + const uint fieldsExpandedCount(realFieldsExpanded->count()); QueryColumnInfo::Vector result(fieldsExpandedCount); //initial size is set // QMapConstIterator columnsAlreadyFoundIt; //compute unique list uint uniqueListCount = 0; for (uint i = 0; i < fieldsExpandedCount; i++) { - QueryColumnInfo *ci = d->fieldsExpanded->at(i); + QueryColumnInfo *ci = realFieldsExpanded->at(i); // columnsAlreadyFoundIt = columnsAlreadyFound.find(ci); // uint foundColumnIndex = -1; if (!columnsAlreadyFound.contains(ci->aliasOrName())) {// columnsAlreadyFoundIt==columnsAlreadyFound.constEnd()) @@ -1134,13 +1140,15 @@ } //prepare clean vector for expanded list, and a map for order information if (!d->fieldsExpanded) { - d->fieldsExpanded = new QueryColumnInfo::Vector(list.count()); // Field::Vector( list.count() ); -//Qt 4 d->fieldsExpanded->setAutoDelete(true); + d->fieldsExpanded = new QueryColumnInfo::Vector(list.count()); + d->visibleFieldsExpanded = new QueryColumnInfo::Vector(list.count()); d->columnsOrderExpanded = new QHash(); } else {//for future: qDeleteAll(*d->fieldsExpanded); d->fieldsExpanded->clear(); d->fieldsExpanded->resize(list.count()); + d->visibleFieldsExpanded->clear(); + d->visibleFieldsExpanded->resize(list.count()); d->columnsOrderExpanded->clear(); } @@ -1152,9 +1160,14 @@ d->columnInfosByName.clear(); d->columnInfosByNameExpanded.clear(); i = -1; + int visibleIndex = -1; foreach(QueryColumnInfo* ci, list) { i++; (*d->fieldsExpanded)[i] = ci; + if (ci->visible) { + ++visibleIndex; + (*d->visibleFieldsExpanded)[visibleIndex] = ci; + } d->columnsOrderExpanded->insert(ci, i); //remember field by name/alias/table.name if there's no such string yet in d->columnInfosByNameExpanded if (!ci->alias.isEmpty()) { @@ -1191,6 +1204,7 @@ } } } + d->visibleFieldsExpanded->resize(visibleIndex + 1); //remove duplicates for lookup fields QHash lookup_dict; //used to fight duplicates and to update QueryColumnInfo::indexForVisibleLookupValue() diff --git a/libs/db/queryschema_p.h b/libs/db/queryschema_p.h --- a/libs/db/queryschema_p.h +++ b/libs/db/queryschema_p.h @@ -1,5 +1,5 @@ /* This file is part of the KDE project - Copyright (C) 2003-2012 Jarosław Staniek + Copyright (C) 2003-2016 Jarosław Staniek This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -104,6 +104,9 @@ /*! Temporary field vector for using in fieldsExpanded() */ QueryColumnInfo::Vector *fieldsExpanded; + /*! Like fieldsExpanded but only visible column infos; infos are not owned. */ + QueryColumnInfo::Vector *visibleFieldsExpanded; + /*! Temporary field vector containing internal fields used for lookup columns. */ QueryColumnInfo::Vector *internalFields; @@ -111,10 +114,16 @@ Contains not auto-deleted items.*/ QueryColumnInfo::Vector *fieldsExpandedWithInternalAndRowID; + /*! Like fieldsExpandedWithInternalAndRowID but only contains visible column infos; infos are not owned.*/ + QueryColumnInfo::Vector *visibleFieldsExpandedWithInternalAndRowID; + /*! Temporary, used to cache sum of expanded fields and internal fields used for lookup columns. Contains not auto-deleted items.*/ QueryColumnInfo::Vector *fieldsExpandedWithInternal; + /*! Like fieldsExpandedWithInternal but only contains visible column infos; infos are not owned.*/ + QueryColumnInfo::Vector *visibleFieldsExpandedWithInternal; + /*! A list of fields for ORDER BY section. @see QuerySchema::orderByColumnList(). */ OrderByColumnList* orderByColumnList; diff --git a/libs/db/queryschema_p.cpp b/libs/db/queryschema_p.cpp --- a/libs/db/queryschema_p.cpp +++ b/libs/db/queryschema_p.cpp @@ -1,5 +1,5 @@ /* This file is part of the KDE project - Copyright (C) 2003-2012 Jarosław Staniek + Copyright (C) 2003-2016 Jarosław Staniek This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -42,9 +42,12 @@ , maxIndexWithAlias(-1) , visibility(64) , fieldsExpanded(0) + , visibleFieldsExpanded(0) , internalFields(0) , fieldsExpandedWithInternalAndRowID(0) + , visibleFieldsExpandedWithInternalAndRowID(0) , fieldsExpandedWithInternal(0) + , visibleFieldsExpandedWithInternal(0) , orderByColumnList(0) , autoincFields(0) , columnsOrder(0) @@ -63,6 +66,7 @@ *this = *copy; // fieldsExpanded = 0; + visibleFieldsExpanded = 0; internalFields = 0; columnsOrder = 0; columnsOrderWithoutAsterisks = 0; @@ -74,7 +78,9 @@ columnInfosByName.clear(); ownedVisibleColumns = 0; fieldsExpandedWithInternalAndRowID = 0; + visibleFieldsExpandedWithInternalAndRowID = 0; fieldsExpandedWithInternal = 0; + visibleFieldsExpandedWithInternal = 0; pkeyFieldsOrder = 0; fakeRowIDCol = 0; fakeRowIDField = 0; @@ -114,7 +120,9 @@ delete internalFields; } delete fieldsExpandedWithInternalAndRowID; + delete visibleFieldsExpandedWithInternalAndRowID; delete fieldsExpandedWithInternal; + delete visibleFieldsExpandedWithInternal; } //static @@ -162,6 +170,8 @@ qDeleteAll(*fieldsExpanded); delete fieldsExpanded; fieldsExpanded = 0; + delete visibleFieldsExpanded; // NO qDeleteAll, items not owned + visibleFieldsExpanded = 0; if (internalFields) { qDeleteAll(*internalFields); delete internalFields; @@ -169,8 +179,12 @@ } delete fieldsExpandedWithInternalAndRowID; fieldsExpandedWithInternalAndRowID = 0; + delete visibleFieldsExpandedWithInternalAndRowID; + visibleFieldsExpandedWithInternalAndRowID = 0; delete fieldsExpandedWithInternal; fieldsExpandedWithInternal = 0; + delete visibleFieldsExpandedWithInternal; + visibleFieldsExpandedWithInternal = 0; } }