# Source: query.h |
Annotated List
Files
Globals
Hierarchy
Index

    /*
       This file is part of the KDB libraries
       Copyright (c) 2000 Praduroux Alessandro <pradu@thekompany.com>

       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., 59 Temple Place - Suite 330,
       Boston, MA 02111-1307, USA.
    */
    #ifndef KDB_QUERY_H
    #define KDB_QUERY_H "$Id: query.h,v 1.7 2001/02/01 03:15:49 garbanzo Exp $"

    #include <qstring.h>
    #include <qstringlist.h>
    #include <qlist.h>
    #include <qmap.h>

    #include <ksharedptr.h>

    #include <kdb/recordset.h>
    #include <kdb/dataobject.h>

    namespace KDB {

    class Connector;
    class Recordset;

    class Query;
    class QueryPrivate;

    typedef KSharedPtr<Query>            QueryPtr;
    typedef QValueList<QueryPtr>         QueryList;
    typedef QValueListIterator<QueryPtr> QueryIterator;
    typedef QMap<QString,QString>        ParameterList;

    struct qryField {
        QString table;
        QString name;
        QString aggregate;
        QString val;
    };

    typedef QList<qryField>         FldList;
    typedef QListIterator<qryField> FldIterator;

    struct qryCond {
        QString condition;
        int type;
        int level;
    };

    typedef QList<qryCond>         CondList;
    typedef QListIterator<qryCond> CondIterator;

    /**
     * Representation of a stored query.
     *
     * Through this object we access the fields and
     * parameters of the query, if any.
     *
     * Each query is stored in the database as an XML definition. This definition
     * will contain the list of fields, calculated fields (not implemented yet), tables, filters - join
     * expressions and parameters. One exception to that is done when the query is built
     * using an SQL expression in @ref Database::newQuery . In this case, the SQL is stored.
     *
     * Queries are of two types: select queries and command queries. Select queries can
     * be used to obtain a recordset using @ref openRecordset , while command queries are
     * executed using @ref execute . Command queries have different types: Update, Insert,
     * Delete. By default, a newly built query is a Select query. You can change the query
     * type using @ref setType
     *
     * Queries can be parametrized. While building the query,
     * the user can use the special construct %name, and provide a
     * corresponding value using the @ref setParameter call. Before the execution (through
     * @ref openRecordset or @ref execute ), a parameter substitution is done. When there is no
     * corresponding parameter value, the %xxx keyword is removed. This can lead to incorrect
     * SQL. Parameter substitution is done on the complete SQL statement, allowing creation
     * of queries that access data with similar definition in different tables with only one
     * query definition.
     *
     * @author Alessandro Praduroux <pradu@thekompany.com>
     * @version kdbcore 0.0.2
     */

    class Query :public DataObject{

        friend class Connector;
        Q_OBJECT

     public:

        /**
         * The type of query. Select queries can be executed using @ref openRecordset, while
         * command queries through @ref execute. the opposite will generate an error.
         */
        enum QueryType { Select, Insert, Update, Delete };

        /**
         * Type of conditional expression.
         */
        enum ConditionType { And, Or };
     public:

        ~Query();

        /**
         * Sets the query type.
         */
        void setType(QueryType type);

        /**
         * Returns the query type
         */
        QueryType type() const;

        /**
         * Return the list of known properties. This is a QDict<char> where the keys are
         * the parameter names and the items are the parameter values
         */
        ParameterList parameters() const;

        /**
         * Set the value of a parameter
         */
        void setParameter(const QString &prop, const QString &value);

        /**
         * Return the actual value of a parameter
         */
        QString parameter(const QString &prop) const;

        /**
         * Append a new field to the field list of the query.
         * WARNING! aggregate functions aren't yet supported. The sig is here but the SQL ignores
         * aggregates.
         * @param table The table to which this field belongs. Ignored for command queries.
         * @param name The name of the field
         * @param aggregate The aggregate function to apply to this field
         * @param value The value this field should get (useful only for update and insert queries,
         * ignored otherwhise).
         * @return true if the field has been appended, false oterwise
         */
        bool addField(const QString &table,
                      const QString &name,
                      const QString &value = QString::null,
                      const QString &aggregate = QString::null);

        /**
         * Remove a field from the list of fields
         */
        void removeField( const QString & table, const QString &name );

        /**
         * Returns the list of fields
         */
        FldList fields() const;

        /**
         * Add a table to the existing list of tables. For insert, update and delete queries
         * only the first table is taken into consideration. All others will be discarded
         * silently.
         * If this table is already present in the table list, and an alias isn't supplied,
         * it will be created based on the table name.
         * @returns the alias of the table added.
         */
        QString addTable(const QString &name, const QString & alias = QString::null) ;

        /**
         * Remove a table from the list of tables, by alias. This will also remove all fields for the
         * removed table
         */
        void removeTable(const QString &alias);

        /**
         * Return the list of table aliases.
         */
        QStringList tables();

        /**
         * given an alias, retrieve the corresponding table name
         */
        QString tableName(const QString & alias);

        /**
         * Add a condition to the query. Ignored for insert queries.
         *
         * Conditions can be nested to an arbitrary level. Proper use of the level parameter can
         * lead to complex conditional expressions.
         *
         * for example:
         * <pre>
         * qry->addCondition("A = B", And, 0);
         * qry->addCondition("B = C", And, 1);
         * qry->addCondition("C = D", Or, 2);
         * qry->addCondition("E = C", And, 2);
         * qry->addCondition("F = A", And, 0);
         * </pre>
         * will lead to the following SQL condition:
         * <pre>
         * WHERE A = B
         *   AND (B = C
         *        OR (C = D
         *            AND E = C
         *           )
         *       )
         *   AND F = A
         * </pre>
         * @param condition The condition without 'where', 'and', or parenthesis. Something
         * like "table1.field1 is null" or "table1.field1 = table2.field1"
         * @param type Wether the condition should be ANDed or ORed with other same level conditions
         * @param level The nesting level of the condition
         */
        void addCondition(const QString &condition, ConditionType type = And, int level = 0);

        /**
         * Remove a condition from the query. It will be removed the first condition that matches
         */
        void removeCondition(const QString &condition, int level = 0);

        /**
         * Return a list of conditions
         */
        CondList conditions();

        /**
         * Return the SQL code associated to the query. The statement is computed
         * on the fly using the stored definition, and parameter parsing is performed.
         */
        QString SQL();

        /**
         * Executes a command query, and return the number of rows affected by this
         * query. If called on a select query, it will fail and generate an error.
         */
        KDB_ULONG execute();

        /**
         * Creates a recordset based on this query.
         * If called on a command query, it will fail and generate an error.
         */
        virtual RecordsetPtr openRecordset();

        /**
         * Saves the query into the database as XML definition or SQL, depending on how it is
         * created
         */
        void save();

        /**
         * Clear the content of all list (parameters, fields, tables) and the SQL
         */
        void clear();

        /**
         * Return true if the query has been modified somewhat
         */
        bool isDirty();

     signals:

        /**
         * This signal is emitted whenever the definition of the query changes.
         * That means a field or table or condition is added or removed
         */
        void definitionChanged();

        /**
         * This signal is emitted once when the query is saved the first time into
         * the database. It is used by Database to add the query name to the list of
         * database queries
         */
        void created(Query *);

     protected:

        Query( Connector * conn, QObject *parent = 0L, const char *name = 0L, const QString &sql = QString::null );

        /**
         * This function will create the SQL string to pass to
         * the DBMS engine. It can be overridden by special types of
         * queries ?? dunno if it will help
         */
        virtual QString buildSQL();

     private:

        QueryPrivate *d;

        Connector * connector;

    };

    }

    #endif

Generated by: root@sparc.ports.openbsd.org on Wed May 2 09:48:14 2001, using kdoc 2.0a53.