diff options
author | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-01-20 01:29:50 +0000 |
---|---|---|
committer | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-01-20 01:29:50 +0000 |
commit | 8362bf63dea22bbf6736609b0f49c152f975eb63 (patch) | |
tree | 0eea3928e39e50fae91d4e68b21b1e6cbae25604 /kexi/kexidb/utils.h | |
download | koffice-8362bf63dea22bbf6736609b0f49c152f975eb63.tar.gz koffice-8362bf63dea22bbf6736609b0f49c152f975eb63.zip |
Added old abandoned KDE3 version of koffice
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/applications/koffice@1077364 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'kexi/kexidb/utils.h')
-rw-r--r-- | kexi/kexidb/utils.h | 476 |
1 files changed, 476 insertions, 0 deletions
diff --git a/kexi/kexidb/utils.h b/kexi/kexidb/utils.h new file mode 100644 index 00000000..a455f5b8 --- /dev/null +++ b/kexi/kexidb/utils.h @@ -0,0 +1,476 @@ +/* This file is part of the KDE project + Copyright (C) 2004-2007 Jaroslaw Staniek <js@iidea.pl> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + + +#ifndef KEXIDB_UTILS_H +#define KEXIDB_UTILS_H + +#include <qvaluelist.h> +#include <qvariant.h> + +#include <kexidb/connection.h> +#include <kexidb/driver.h> + +class QDomNode; +class QDomElement; +class QDomDocument; + +namespace KexiDB +{ + //! for convenience + inline KEXI_DB_EXPORT bool deleteRow(Connection &conn, TableSchema *table, + const QString &keyname, const QString &keyval) + { + return table!=0 && conn.executeSQL("DELETE FROM " + table->name() + " WHERE " + + keyname + "=" + conn.driver()->valueToSQL( Field::Text, QVariant(keyval) )); + } + + inline KEXI_DB_EXPORT bool deleteRow(Connection &conn, const QString &tableName, + const QString &keyname, const QString &keyval) + { + return conn.executeSQL("DELETE FROM " + tableName + " WHERE " + + keyname + "=" + conn.driver()->valueToSQL( Field::Text, QVariant(keyval) )); + } + + inline KEXI_DB_EXPORT bool deleteRow(Connection &conn, TableSchema *table, + const QString &keyname, int keyval) + { + return table!=0 && conn.executeSQL("DELETE FROM " + table->name() + " WHERE " + + keyname + "=" + conn.driver()->valueToSQL( Field::Integer, QVariant(keyval) )); + } + + inline KEXI_DB_EXPORT bool deleteRow(Connection &conn, const QString &tableName, + const QString &keyname, int keyval) + { + return conn.executeSQL("DELETE FROM " + tableName + " WHERE " + + keyname + "=" + conn.driver()->valueToSQL( Field::Integer, QVariant(keyval) )); + } + + /*! Delete row with two generic criterias. */ + inline KEXI_DB_EXPORT bool deleteRow(Connection &conn, const QString &tableName, + const QString &keyname1, Field::Type keytype1, const QVariant& keyval1, + const QString &keyname2, Field::Type keytype2, const QVariant& keyval2) + { + return conn.executeSQL("DELETE FROM " + tableName + " WHERE " + + keyname1 + "=" + conn.driver()->valueToSQL( keytype1, keyval1 ) + + " AND " + keyname2 + "=" + conn.driver()->valueToSQL( keytype2, keyval2 )); + } + + inline KEXI_DB_EXPORT bool replaceRow(Connection &conn, TableSchema *table, + const QString &keyname, const QString &keyval, const QString &valname, QVariant val, int ftype) + { + if (!table || !KexiDB::deleteRow(conn, table, keyname, keyval)) + return false; + return conn.executeSQL("INSERT INTO " + table->name() + + " (" + keyname + "," + valname + ") VALUES (" + + conn.driver()->valueToSQL( Field::Text, QVariant(keyval) ) + "," + + conn.driver()->valueToSQL( ftype, val) + ")"); + } + + typedef QValueList<uint> TypeGroupList; + + /*! \return list of types for type group \a typeGroup. */ + KEXI_DB_EXPORT const TypeGroupList typesForGroup(Field::TypeGroup typeGroup); + + /*! \return list of i18n'd type names for type group \a typeGroup. */ + KEXI_DB_EXPORT QStringList typeNamesForGroup(Field::TypeGroup typeGroup); + + /*! \return list of (not-i18n'd) type names for type group \a typeGroup. */ + KEXI_DB_EXPORT QStringList typeStringsForGroup(Field::TypeGroup typeGroup); + + /*! \return default field type for type group \a typeGroup, + for example, Field::Integer for Field::IntegerGroup. + It is used e.g. in KexiAlterTableDialog, to properly fill + 'type' property when user selects type group for a field. */ + KEXI_DB_EXPORT Field::Type defaultTypeForGroup(Field::TypeGroup typeGroup); + + /*! \return a slightly simplified type name for \a field. + For BLOB type it returns i18n'd "Image" string or other, depending on the mime type. + For numbers (either floating-point or integer) it returns i18n'd "Number: string. + For other types it the same string as Field::typeGroupName() is returned. */ +//! @todo support names of other BLOB subtypes + KEXI_DB_EXPORT QString simplifiedTypeName(const Field& field); + + /*! \return true if \a v represents an empty (but not null) value. + Values of some types (as for strings) can be both empty and not null. */ + inline bool isEmptyValue(Field *f, const QVariant &v) { + if (f->hasEmptyProperty() && v.toString().isEmpty() && !v.toString().isNull()) + return true; + return v.isNull(); + } + + /*! Sets \a msg to an error message retrieved from object \a obj, and \a details + to details of this error (server message and result number). + Does nothing if \a obj is null or no error occurred. + \a msg and \a details strings are not overwritten. + If \a msg is not empty, \a obj's error message is appended to \a details. + */ + KEXI_DB_EXPORT void getHTMLErrorMesage(Object* obj, QString& msg, QString &details); + + /*! This methods works like above, but appends both a message and a description + to \a msg. */ + KEXI_DB_EXPORT void getHTMLErrorMesage(Object* obj, QString& msg); + + /*! This methods works like above, but works on \a result's members instead. */ + KEXI_DB_EXPORT void getHTMLErrorMesage(Object* obj, ResultInfo *result); + + /*! Function useful for building WHERE parts of sql statements. + Constructs an sql string like "fielname = value" for specific \a drv driver, + field type \a t, \a fieldName and \a value. If \a value is null, "fieldname is NULL" + string is returned. */ + inline KEXI_DB_EXPORT QString sqlWhere(Driver *drv, Field::Type t, + const QString fieldName, const QVariant value) + { + if (value.isNull()) + return fieldName + " is NULL"; + return fieldName + "=" + drv->valueToSQL( t, value ); + } + + /*! \return identifier for object \a objName of type \a objType + or 0 if such object does not exist. */ + KEXI_DB_EXPORT int idForObjectName( Connection &conn, const QString& objName, int objType ); + + /*! Variant class providing a pointer to table or query. */ + class KEXI_DB_EXPORT TableOrQuerySchema { + public: + /*! Creates a new TableOrQuerySchema variant object, retrieving table or query schema + using \a conn connection and \a name. If both table and query exists for \a name, + table has priority over query. + You should check whether a query or table has been found by testing + (query() || table()) expression. */ + TableOrQuerySchema(Connection *conn, const QCString& name); + + /*! Creates a new TableOrQuerySchema variant object, retrieving table or query schema + using \a conn connection and \a name. If \a table is true, \a name is assumed + to be a table name, otherwise \a name is assumed to be a query name. + You should check whether a query or table has been found by testing + (query() || table()) expression. */ + TableOrQuerySchema(Connection *conn, const QCString& name, bool table); + + /*! Creates a new TableOrQuerySchema variant object. \a tableOrQuery must be of + class TableSchema or QuerySchema. + You should check whether a query or table has been found by testing + (query() || table()) expression. */ + TableOrQuerySchema(FieldList &tableOrQuery); + + /*! Creates a new TableOrQuerySchema variant object, retrieving table or query schema + using \a conn connection and \a id. + You should check whether a query or table has been found by testing + (query() || table()) expression. */ + TableOrQuerySchema(Connection *conn, int id); + + /*! Creates a new TableOrQuerySchema variant object, keeping a pointer so \a table + object. */ + TableOrQuerySchema(TableSchema* table); + + /*! Creates a new TableOrQuerySchema variant object, keeping a pointer so \a query + object. */ + TableOrQuerySchema(QuerySchema* query); + + //! \return a pointer to the query if it's provided + QuerySchema* query() const { return m_query; } + + //! \return a pointer to the table if it's provided + TableSchema* table() const { return m_table; } + + //! \return name of a query or table + QCString name() const; + + //! \return caption (if present) or name of the table/query + QString captionOrName() const; + + //! \return number of fields + uint fieldCount() const; + + //! \return all columns for the table or the query + const QueryColumnInfo::Vector columns(bool unique = false); + + /*! \return a field of the table or the query schema for name \a name + or 0 if there is no such field. */ + Field* field(const QString& name); + + /*! Like Field* field(const QString& name); + but returns all information associated with field/column \a name. */ + QueryColumnInfo* columnInfo(const QString& name); + + /*! \return connection object, for table or query or 0 if there's no table or query defined. */ + Connection* connection() const; + + /*! \return String for debugging purposes. */ + QString debugString(); + + /*! Shows debug information about table or query. */ + void debug(); + + protected: + QCString m_name; //!< the name is kept here because m_table and m_table can be 0 + //! and we still want name() and acptionOrName() work. + TableSchema* m_table; + QuerySchema* m_query; + }; + +//! @todo perhaps use Q_ULLONG here? + /*! \return number of rows that can be retrieved after executing \a sql statement + within a connection \a conn. The statement should be of type SELECT. + For SQL data sources it does not fetch any records, only "COUNT(*)" + SQL aggregation is used at the backed. + -1 is returned if error occured. */ + int rowCount(Connection &conn, const QString& sql); + +//! @todo perhaps use Q_ULLONG here? + /*! \return number of rows that can be retrieved from \a tableSchema. + The table must be created or retrieved using a Connection object, + i.e. tableSchema.connection() must not return 0. + For SQL data sources it does not fetch any records, only "COUNT(*)" + SQL aggregation is used at the backed. + -1 is returned if error occurred. */ + KEXI_DB_EXPORT int rowCount(const TableSchema& tableSchema); + +//! @todo perhaps use Q_ULLONG here? + /*! Like above but operates on a query schema. */ + KEXI_DB_EXPORT int rowCount(QuerySchema& querySchema); + +//! @todo perhaps use Q_ULLONG here? + /*! Like above but operates on a table or query schema variant. */ + KEXI_DB_EXPORT int rowCount(TableOrQuerySchema& tableOrQuery); + + /*! \return a number of columns that can be retrieved from table or query schema. + In case of query, expanded fields are counted. Can return -1 if \a tableOrQuery + has neither table or query assigned. */ + KEXI_DB_EXPORT int fieldCount(TableOrQuerySchema& tableOrQuery); + + /*! shows connection test dialog with a progress bar indicating connection testing + (within a second thread). + \a data is used to perform a (temporary) test connection. \a msgHandler is used to display errors. + On successful connecting, a message is displayed. After testing, temporary connection is closed. */ + KEXI_DB_EXPORT void connectionTestDialog(QWidget* parent, const ConnectionData& data, + MessageHandler& msgHandler); + + /*! Saves connection data \a data into \a map. */ + KEXI_DB_EXPORT QMap<QString,QString> toMap( const ConnectionData& data ); + + /*! Restores connection data \a data from \a map. */ + KEXI_DB_EXPORT void fromMap( const QMap<QString,QString>& map, ConnectionData& data ); + + //! Used in splitToTableAndFieldParts(). + enum SplitToTableAndFieldPartsOptions { + FailIfNoTableOrFieldName = 0, //!< default value for splitToTableAndFieldParts() + SetFieldNameIfNoTableName = 1 //!< see splitToTableAndFieldParts() + }; + + /*! Splits \a string like "table.field" into "table" and "field" parts. + On success, a table name is passed to \a tableName and a field name is passed to \a fieldName. + The function fails if either: + - \a string is empty, or + - \a string does not contain '.' character and \a option is FailIfNoTableOrFieldName + (the default), or + - '.' character is the first of last character of \a string (in this case table name + or field name could become empty what is not allowed). + + If \a option is SetFieldNameIfNoTableName and \a string does not contain '.', + \a string is passed to \a fieldName and \a tableName is set to QString::null + without failure. + + If function fails, \a tableName and \a fieldName remain unchanged. + \return true on success. */ + KEXI_DB_EXPORT bool splitToTableAndFieldParts(const QString& string, + QString& tableName, QString& fieldName, + SplitToTableAndFieldPartsOptions option = FailIfNoTableOrFieldName); + + /*! \return true if \a type supports "visibleDecimalPlaces" property. */ + KEXI_DB_EXPORT bool supportsVisibleDecimalPlacesProperty(Field::Type type); + + /*! \return string constructed by converting \a value. + * If \a decimalPlaces is < 0, all meaningful fractional digits are returned. + * If \a automatically is 0, just integer part is returned. + * If \a automatically is > 0, fractional part should take exactly + N digits: if the fractional part is shorter than N, additional zeros are appended. + For example, "12.345" becomes "12.345000" if N=6. + + No rounding is actually performed. + KLocale::formatNumber() and KLocale::decimalSymbol() are used to get locale settings. + + @see KexiDB::Field::visibleDecimalPlaces() */ + KEXI_DB_EXPORT QString formatNumberForVisibleDecimalPlaces(double value, int decimalPlaces); + + //! \return true if \a propertyName is a builtin field property. + KEXI_DB_EXPORT bool isBuiltinTableFieldProperty( const QCString& propertyName ); + + //! \return true if \a propertyName is an extended field property. + KEXI_DB_EXPORT bool isExtendedTableFieldProperty( const QCString& propertyName ); + + /*! \return type of field for integer value \a type. + If \a type cannot be casted to KexiDB::Field::Type, KexiDB::Field::InvalidType is returned. + This can be used when type information is deserialized from a string or QVariant. */ + KEXI_DB_EXPORT Field::Type intToFieldType( int type ); + + /*! Sets property values for \a field. \return true if all the values are valid and allowed. + On failure contents of \a field is undefined. + Properties coming from extended schema are also supported. + This function is used e.g. by AlterTableHandler when property information comes in form of text. + */ + KEXI_DB_EXPORT bool setFieldProperties( Field& field, const QMap<QCString, QVariant>& values ); + + /*! Sets property value for \a field. \return true if the property has been found and + the value is valid for this property. On failure contents of \a field is undefined. + Properties coming from extended schema are also supported as well as + QVariant customProperty(const QString& propertyName) const; + + This function is used e.g. by AlterTableHandler when property information comes in form of text. + */ + KEXI_DB_EXPORT bool setFieldProperty(Field& field, const QCString& propertyName, + const QVariant& value); + + /*! @return property value loaded from a DOM \a node, written in a QtDesigner-like + notation: <number>int</number> or <bool>bool</bool>, etc. Supported types are + "string", "cstring", "bool", "number". For invalid values null QVariant is returned. + You can check the validity of the returned value using QVariant::type(). */ + KEXI_DB_EXPORT QVariant loadPropertyValueFromDom( const QDomNode& node ); + + /*! Convenience version of loadPropertyValueFromDom(). \return int value. */ + KEXI_DB_EXPORT int loadIntPropertyValueFromDom( const QDomNode& node, bool* ok ); + + /*! Convenience version of loadPropertyValueFromDom(). \return QString value. */ + KEXI_DB_EXPORT QString loadStringPropertyValueFromDom( const QDomNode& node, bool* ok ); + + /*! Saves integer element for value \a value to \a doc document within parent element + \a parentEl. The value will be enclosed in "number" element and "elementName" element. + Example: saveNumberElementToDom(doc, parentEl, "height", 15) will create + \code + <height><number>15</number></height> + \endcode + \return the reference to element created with tag elementName. */ + KEXI_DB_EXPORT QDomElement saveNumberElementToDom(QDomDocument& doc, QDomElement& parentEl, + const QString& elementName, int value); + + /*! Saves boolean element for value \a value to \a doc document within parent element + \a parentEl. Like saveNumberElementToDom() but creates "bool" tags. True/false values will be + saved as "true"/"false" strings. + \return the reference to element created with tag elementName. */ + KEXI_DB_EXPORT QDomElement saveBooleanElementToDom(QDomDocument& doc, QDomElement& parentEl, + const QString& elementName, bool value); + + /*! \return an empty value that can be set for a database field of type \a type having + "null" property set. Empty string is returned for text type, 0 for integer + or floating-point types, false for boolean type, empty null byte array for BLOB type. + For date, time and date/time types current date, time, date+time is returned, respectively. + Returns null QVariant for unsupported values like KexiDB::Field::InvalidType. + This function is efficient (uses a cache) and is heavily used by the AlterTableHandler + for filling new columns. */ + KEXI_DB_EXPORT QVariant emptyValueForType( Field::Type type ); + + /*! \return a value that can be set for a database field of type \a type having + "notEmpty" property set. It works in a similar way as + @ref QVariant emptyValueForType( KexiDB::Field::Type type ) with the following differences: + - " " string (a single space) is returned for Text and LongText types + - a byte array with saved "filenew" PNG image (icon) for BLOB type + Returns null QVariant for unsupported values like KexiDB::Field::InvalidType. + This function is efficient (uses a cache) and is heavily used by the AlterTableHandler + for filling new columns. */ + KEXI_DB_EXPORT QVariant notEmptyValueForType( Field::Type type ); + + //! Escaping types used in escapeBLOB(). + enum BLOBEscapingType { + BLOBEscapeXHex = 1, //!< escaping like X'1FAD', used by sqlite (hex numbers) + BLOBEscape0xHex, //!< escaping like 0x1FAD, used by mysql (hex numbers) + BLOBEscapeHex, //!< escaping like 1FAD without quotes or prefixes + BLOBEscapeOctal //!< escaping like 'zk\\000$x', used by pgsql + //!< (only non-printable characters are escaped using octal numbers) + //!< See http://www.postgresql.org/docs/8.1/interactive/datatype-binary.html + }; + +//! @todo reverse function for BLOBEscapeOctal is available: processBinaryData() in pqxxcursor.cpp - move it here + /*! \return a string containing escaped, printable representation of \a array. + Escaping is controlled by \a type. For empty array QString::null is returned, + so if you want to use this function in an SQL statement, empty arrays should be + detected and "NULL" string should be put instead. + This is helper, used in Driver::escapeBLOB() and KexiDB::variantToString(). */ + KEXI_DB_EXPORT QString escapeBLOB(const QByteArray& array, BLOBEscapingType type); + + /*! \return byte array converted from \a data of length \a length. + \a data is escaped in format used by PostgreSQL's bytea datatype + described at http://www.postgresql.org/docs/8.1/interactive/datatype-binary.html + This function is used by PostgreSQL KexiDB and migration drivers. */ + KEXI_DB_EXPORT QByteArray pgsqlByteaToByteArray(const char* data, int length); + + /*! \return string value serialized from a variant value \a v. + This functions works like QVariant::toString() except the case when \a v is of type ByteArray. + In this case KexiDB::escapeBLOB(v.toByteArray(), KexiDB::BLOBEscapeHex) is used. + This function is needed for handling values of random type, for example "defaultValue" + property of table fields can contain value of any type. + Note: the returned string is an unescaped string. */ + KEXI_DB_EXPORT QString variantToString( const QVariant& v ); + + /*! \return variant value of type \a type for a string \a s that was previously serialized using + \ref variantToString( const QVariant& v ) function. + \a ok is set to the result of the operation. */ + KEXI_DB_EXPORT QVariant stringToVariant( const QString& s, QVariant::Type type, bool &ok ); + + /*! \return true if setting default value for \a field field is allowed. Fields with unique + (and thus primary key) flags set do not accept default values. + False is returned aslo if \a field is 0. */ + KEXI_DB_EXPORT bool isDefaultValueAllowed( Field* field ); + + /*! Gets limits for values of type \a type. The result is put into \a minValue and \a maxValue. + Supported types are Byte, ShortInteger, Integer and BigInteger + Results for BigInteger or non-integer types are the same as for Integer due + to limitation of int type. + Signed integers are assumed. */ +//! @todo add support for unsigned flag + KEXI_DB_EXPORT void getLimitsForType(Field::Type type, int &minValue, int &maxValue); + + /*! Shows debug information about \a rowData row data. */ + KEXI_DB_EXPORT void debugRowData(const RowData& rowData); + + /*! \return type that's maximum of two integer types \a t1 and \a t2, e.g. Integer for (Byte, Integer). + If one of the types is not of the integer group, Field::InvalidType is returned. */ + KEXI_DB_EXPORT Field::Type maximumForIntegerTypes(Field::Type t1, Field::Type t2); + + /*! \return QVariant value converted from null-terminated \a data string. + In case of BLOB type, \a data is not nul lterminated, so passing length is needed. */ + inline QVariant cstringToVariant(const char* data, KexiDB::Field* f, int length = -1) + { + if (!data) + return QVariant(); + // from mo st to least frequently used types: + + if (!f || f->isTextType()) + return QString::fromUtf8(data, length); + if (f->isIntegerType()) { + if (f->type()==KexiDB::Field::BigInteger) + return QVariant( QString::fromLatin1(data, length).toLongLong() ); + return QVariant( QString::fromLatin1(data, length).toInt() ); + } + if (f->isFPNumericType()) + return QString::fromLatin1(data, length).toDouble(); + if (f->type()==KexiDB::Field::BLOB) { + QByteArray ba; + ba.duplicate(data, length); + return ba; + } + // the default +//! @todo date/time? + QVariant result(QString::fromUtf8(data, length)); + if (!result.cast( KexiDB::Field::variantType(f->type()) )) + return QVariant(); + return result; + } +} + +#endif |