Source: sqlguipart/sqlguidoc.h
|
|
|
|
/***************************************************************************
sqlguidoc.h - description
-------------------
begin : Sat Apr 14 18:28:06 CEST 2001
copyright : (C) 2001 by mb
email : marcus@beranek.de
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#ifndef SQLGUIDOC_H
#define SQLGUIDOC_H
#ifdef HAVE_CONFIG_H
#include
#endif
// include files for QT
#include
#include
#include
// include files for KDE
#include
#include
#include
class SqlGuiView;
class KLocale;
#include "db_components.h"
class SqlGuiDoc : public QObject{
Q_OBJECT
public:
/**
* API-Documentation for SqlGui
*
* Note: to use this class, you must include the following: #include <sqlgui/sqlguidoc.h> and not <sqlguipart/sqlguidoc.h> as the headline says...
*
* Note: This API is still under development and considered beta. The API might change in the future without notice.
* SqlGui comes with libraries for the MySQL- and the PostgreSQL-database-system. These libraries fully implement the SqlGui-API.
* These libraries may be used as a "reference"-implementation.
*
* SqlGuiDoc is the base class for communication with the database-server. All classes, which are used by sqlgui for communication with a database, should inherit from SqlGuiDoc.
* There is no need to overload the constructor, but you must reimplement the following member-functions:
*
*
* openDocument (very important, see below)
* slotDoQuery (very important, see below)
*
* slotDbCreate
* slotDbDelete
* slotTableDelete
* slotTableCheck
* slotTableOptimize
* slotTableRepair
* slotServerStatus
* slotCountRows
*
*
*
* The starting-point is the internal representation of a databse-server. The member "DB"
* is a pointer to this internal representation. DB points to the struct "base".
* This structure contains all databases SqlGuiDoc finds on the connected server.
* It has also pointers to the tables, which belong to the databases.
*
* The structure has the following definition:
*
* typedef
* struct base {
* const char * name; // basename
* table_t * table_list; // list of tables in this database
* struct base * next; // pointer to the next database
* } base_t;
*
*
* @see db_components.h
*
* The internal representation of the database-server is a linked list.
* The list-linkage is simple, i.e. you can go from one element to the next one, but you can't go back.
*
*
* db1 -> db2 -> db3 -> ... -> NULL
*
*
* There's no real need for a more complex structure, because sqlgui needs to get the elements once, everything else
* (like sorting) is done by the database itself or the view (in SqlGuiView, which makes use of QTable, which handles sorting).
*
* Every entry in this list contains the name of the database, a pointer to its tables and a pointer to the next database:
*
*
* db1
* -> name
* -> table_list
* -> next
*
*
* The fisrt element of this list is always "DB".
* To go through the whole structure you just need to do the following:
*
*
* #include "db_components.h"
*
* base_t * b = DB;
*
* while (b) {
* // do something with this base, for example read basename:
* cout << b->name << endl;
* // goto next base:
* b = b->next;
* }
*
*
*
* The last entry of the list must be a NULL-pointer.
*
* The same mechanism is used for tables and their columnes:
*
*
* db1 -> table_list
* |
* tb1 -> tb2 -> tb3 -> ... -> NULL
* |
* colum_list
* |
* col1 -> col2 -> col3 -> ... -> NULL
*
*
*
* The table_list and column_list have the following definition (defined in db_components.h):
*
*
* typedef
* struct column{
* const char * name; // column-name
* char * type; // string, describing the column-type (depends on database).
* char pri; // 'Y' if column is primary-key, ' ' otherwise.
* const char * extra_flags; // for attributes like INDEX, NOT NULL, AUTO_INC etc.
* struct column * next; // pointer to the next column in list. last pointer in list must be a NULL-pointer.
* } column_t;
*
* typedef
* struct table{
* const char * name; // table-name
* int type; // table-type (reserved. should be 0)
* const char * type_n; // name of the table type (reserved. should be '')
* column_t * column_list; // pointer to the columnes in this table
* struct table * next; // pointer to the next table in this database. last pointer in list must be a NULL-pointer.
* } table_t;
*
*
*
* To traverse the full server-structure, you need to do something like this:
*
*
* #include "db_components.h"
*
* base_t * b = DB;
*
* while (b) {
* // do something with the database:
* cout << "Database " << d->name << ":" << endl;
* table_t * t = b->table_list;
*
* while (t) {
* // do something with the table:
* cout << " Table " << t->name << ":" << endl;
* column_t * c = t->column_list;
*
* while(c) {
* // do something with the column:
* cout << " Column " << c->name << endl;
* c = c->next;
* }
* t = t->next;
* }
* b = b->next;
* }
*
*
*
* When building your own library for a specific database, you have to remember to include the following two factory-functions in your library (i.e. in the file "sqlguidoc_YOURDB.cpp"):
*
*
* extern "C" SqlGuiDoc* create(QWidget *parent, const char *name){
* return new SqlGuiDocMysql( parent, name ); // replace SqlGuiDocMysql with SqlGuiDocYOURDB
* }
*
* extern "C" void destroy( SqlGuiDoc* p){
* delete p;
* }
*
*
*
* These to functions are needed by SqlguiPart to load the library
*
* @see base_t
* @see table_t
* @see column_t
* @see row_t
* @see field_t
*/
SqlGuiDoc(QWidget *parent, const char *name=0);
/**
* Destructor.
*/
~SqlGuiDoc();
/**
*
* Opens a connection to the specified host "url" as user "uname" with password "pwd".
* If the database requires a database-name to open a connection to, then the
* database-name "base" must also be given.
*
* This method retrieves a list of all databases (if no database is given), their tables, columnes and column-types.
* With this information it then constructs the internal representation of the database-server.
*
* If the datanbase-name is given, this method should retrieve exactly one database (the given one), its tables, columnes and column-types only.
* When connecting to a MySQL-server no database-name must be given. This is because the MySQL-API offers a function to retrieve a list of all
* databases without connecting to a specific database. Many other APIs don't offer this kind of function.
*
* It also sets the member "DB", so that it points to the first element of the internal database-representation.
*
* A typical implementation could be (here: pseudo-code; replace with the specific database-functions of your favourite database-server):
*
*
* connect_to_database( host, user, password ); // replace with specific db-code for "connect_to_database"
*
* DB = NULL;
* base_t * old = NULL;
*
* if ( connected ) { // replace with specific db-code for "connected"
*
* while ( d = getDatabaseList() ) { // replace with specific db-code for "getDatabaseList"
*
* base_t * b = new base_t;
* b->name = d->name(); // replace with specific db-code "d->name"
* b->table_list = getTables( d ); // replace with specific db-code "getTables"
* b->next = NULL;
*
* if (old) {
* old->next = b;
* old = b;
* } else {
* DB = b;
* old = DB;
* }
* }
* }
*
*
*
* Of course you have to use the functions offered by your database-server. This example is just written here, to give you an idea of how to start
* building the internal database-representation. Also a database may not offer the ability to get a list of its databases. Instead you must
* already know the database-name, to which you would like to connect to.
*
* In some cases, it may be difficult to get previous example working. The easiest way to get the constuction of the DB-object working,
* is to split up the information-retrieval into separte parts:
*
*
* 1) get all database-names and store them in the DB-object
* 2) for every database in DB get the tables and store them in DB
* 3) for every database and for every table get the column-names and store them in DB
*
*
*
* connect_to_database( host, user, password ); // replace with specific db-code for "connect_to_database"
*
* DB = NULL;
* base_t * old = NULL;
*
* if ( connected ) { // replace with specific db-code for "connected"
*
* while ( d = getDatabaseList() ) { // replace with specific db-code for "getDatabaseList"
*
* base_t * b = new base_t;
* b->name = d->name(); // replace with specific db-code "d->name"
* b->next = NULL;
*
* if (old) {
* old->next = b;
* old = b;
* } else {
* DB = b;
* old = DB;
* }
* }
*
* base_t * db = DB;
* while( db ){
* db->table_list = getTables( db ); // replace with specific db-code for "getTables"
* db = db->next;
* }
*
* db = DB;
* while( db ){
* table_t * tb = db->table_list;
* while( tb ){
* tb->column_list = getColumnes( db, tb ); // replace with specific db-code for "getColumnes"
* tb = tb->next;
* }
* db = db->next;
* }
* }
*
*
*
* This may take a little bit longer to get all the information, but may also save you a lot of debugging-time and headaches.
*
* You might want to take a look at "sqlguidoc_mysql.cpp" or "sqlguidoc_pgsql.cpp".
*
* This member-function must be reimplemented.
*
* @param url host to connect to (maybe with :port)
* @param uname username for login
* @param pwd password for login
* @param base the base to connect to (must be given on some database-systems, may be ignored if not needed [e.g.: mysql])
* @see SqlGuiDocMysql
*
*/
virtual bool openDocument(const QString& url, const QString& uname, const QString& pwd, const QString& base);
/**
* returns the member DB, the pointer to the first element of the internal database-reprentation
* (no need for reimplementation).
*
* @see base_t
*/
base_t * getDBs();
/**
* returns a pointer to the first row of the internal representation of a result from a query
* (no need for reimplementation).
*
* @see base_t
*/
row_t * getFirstRes();
/**
* returns a pointer to the next row of the internal representation of a result from a query
* (no need for reimplementation).
*
* @see base_t
*/
row_t * getNextRes();
/**
* returns the name of the database, which was affected by the last query
* (no need for reimplementation).
*/
QString* resultDB();
/** Deprecated.
* returns the name of the tablee, which was affected by the last query
* (no need for reimplementation).
*/
QString* resultTable();
/**
* returns a pointer to the columns, which were affected by the last query
* (no need for reimplementation).
*
* @see base_t
*/
column_t* resultCols();
/**
* tells sqlgui, that a new connection will be opened. returns always true.
* there's no real need for this function, so it may be removed in the future.
*/
bool newDocument();
/**
* returns the url of the currently connected host
* (no need for reimplementation).
*/
const KURL& URL() const;
/**
* sets the url of the currently connected host
* (no need for reimplementation).
*
* @param url The url of the connected host
*/
void setURL(const KURL& url);
/**
* returns the name of the table, which was affected by the last query
* (no need for reimplementation).
*/
QString * getLastTable();
/**
* returns the column-name of the primary key, which was found in the last query.
* if there is more than one key, only the first key will be returned. (ToDo: handle multiple keys)
* (no need for reimplementation).
*/
QString * getPrimaryKey();
/**
* returns the hostname of the of the currently connected database-server
* (no need for reimplementation).
*/
QString getHost();
/**
* returns the username, which was given in the current connection
* (no need for reimplementation).
*/
QString getUser();
/**
* returns the password, which was given in the current connection
* (no need for reimplementation).
*/
QString getPass();
/**
* returns the name of the of the currently connected database
* (no need for reimplementation).
*/
QString getBase();
/**
* returns the portnumber, which was given in the current connection
* (no need for reimplementation).
*/
unsigned short int getPort();
/**
* moves the pointer in the internal database-representation to the next base
* (no need for reimplementation).
*/
bool gotoNextBase();
/**
* moves the pointer in the internal database-representation to the next table
* (no need for reimplementation).
*/
bool gotoNextTable();
/**
* moves the pointer in the internal database-representation to the next column
* (no need for reimplementation).
*/
bool gotoNextColumn();
/**
* moves the pointer in the internal representation of a database-result to the next row
* (no need for reimplementation).
*/
bool gotoNextRow();
/**
* moves the pointer in the internal representation of a database-result the next field
* (no need for reimplementation).
*/
bool gotoNextField();
/**
* returns the base, to which the pointer in the internal representation now points
* (no need for reimplementation).
*/
base_t* getActualBase();
/**
* returns the table, to which the pointer in the internal representation now points
* (no need for reimplementation).
*/
table_t* getActualTable();
/**
* returns the column, to which the pointer in the internal representation now points
* (no need for reimplementation).
*/
column_t* getActualColumn();
/**
* returns the row, to which the pointer in the internal representation now points
* (no need for reimplementation).
*/
row_t* getActualRow();
/**
* returns the field, to which the pointer in the internal representation now points
* (no need for reimplementation).
*/
field_t* getActualField();
/**
* returns the name of the base, to which the pointer in the internal representation now points
* (no need for reimplementation).
*/
QString getActualBaseName();
/**
* returns the name of the table, to which the pointer in the internal representation now points
* (no need for reimplementation).
*/
QString getActualTableName();
/**
* returns the type of the table, to which the pointer in the internal representation now points
* (no need for reimplementation).
*/
QString getActualTableType();
/**
* returns the name of the column, to which the pointer in the internal representation now points
* (no need for reimplementation).
*/
QString getActualColumnName();
/**
* sets the view-widget for this database-representation
* (no need for reimplementation).
*
* @param v The view of this database-representation
*/
void setView( SqlGuiView* v );
/**
* returns true, when connected, false otherwise.
*
* purely virtual, must be reimplemented.
*
*/
virtual bool isConnected();
/**
* returns the protocol-name (i.e. mysql, pgsql, ...)
*/
virtual QString getProtocol();
public slots:
/**
* calls openDocument with the given arguments.
*
* @param h hostname | hostname:port
* @param u user
* @param p passort
*/
void slotDoLogin( QString url, QString uname, QString pwd, QString base);
/**
* closes the current connection and calls openDocument with the results from getHost, getUser and getPass.
*/
void slotReConnect();
/**
* sends the query Anfrage to the base Base to the currently connected host.
* Then reads the result from that query and updates the internal representation of the databses-server.
*
* Emits QueryDone() on success, resultChanged() when the result changed, DbQueryError( QString* errormsg ) on failure,
* lastActionChanged( lastDB, lastTable, primKey ) to tell the part, to which table the last query was sent.
*
* If the query doesn't fail, then this method has to do the following:
*
*
* 1) Check if the query returned a result. If not, emit QueryDone().
*
* 2) If there is a result, this method has to:
* - set lastDB (QString*, name of the database, which was affected)
* - set lastTable (QString*, name of the table, which was affected)
* - set lastCols (column_t*, list of the columnes with the column-names and -types)
* - set primKey (QString*, name of the first column, which is a primary key)
* - set RESULT (row_t*, list of the rows in the resultset)
* - set RESULT_Start (row_t*, pointer to the first element of the resultset, i.e. to RESULT)
* - emit resultChanged() when the result changes
* - emit lastActionChanged( lastDB, lastTable, primKey )
* - emit QueryDone() when finished successfully
*
*
*
*
* The resultlist must be represented as a row-type row_t. It uses the same mechanism as the database_list, table_list and column_list:
*
*
* row1 -> row2 -> row3 -> ... -> NULL
* |
* field1 -> field2 -> field3 -> ... -> NULL
* |
* value (i.e. string-representation of the field-value)
*
*
*
* Thr row-list has the following definition:
*
*
* typedef
* struct field{
* int length; // (reserved).
* char * value; // String-representation of the field-value.
* struct field * next; // pointer to the next field in this row. last pointer in list must be a NULL-pointer.
* } field_t;
*
* typedef
* struct row{
* field_t * feld; // pointer to the first field in this row. Must not be NULL!
* struct row * next; // pointer to the next row in the resultset. last pointer in result-set must be a NULL-pointer.
* } row_t;
*
*
*
* This method is purely virtual, must be reimplemented.
*
* @see SqlGuiDocMysql
* @see SqlGuiDocMysql::slotDoQuery
*
* @param Base database
* @param Anfrage sql-query
*/
virtual void slotDoQuery(QString * Base, QString* Anfrage);
/**
* Creates a new database. Emits NewDbCreated() on success, DbQueryError() on failure. This may be done by calling slotDoQuery (see below).
*
* purely virtual, must be reimplemented.
*
*
* SqlGuiDocYOURDB::slotDbCreate( QString* db ){
* QString * sql = new QString( "CREATE DATABASE ");
* sql->append( db );
* slotDoQuery( db, sql );
* emit( NewDbCreated() ); // emitted everytime, not very clean, but should work
* }
*
*
* @param db databasename
*
*/
virtual void slotDbCreate( QString* db);
/**
* Deletes the database db. Emits DbErased() on success, DbQueryError() on failure. This may be done by calling slotDoQuery.
*
* purely virtual, must be reimplemented
*
* @param db databasename
*/
virtual void slotDbDelete( QString* db );
/**
* deletes the table tb in the database db. Emits TableErased() on success, DbQueryError() on failure. This may be done by calling slotDoQuery.
*
* purely virtual, must be reimplemented.
*
* @param db databasename
* @param tb tablename
*/
virtual void slotTableDelete(QString* db, QString* tb);
/**
* checks the table tb in the database db. May also do nothing, if the database doesn't support checking tables.
* Currently there is no signal emitted on success. This behaviour may change in the future.
*
* purely virtual, must be reimplemented.
*
* @param db databasename
* @param tb tablename
*/
virtual void slotTableCheck(QString* db, QString* tb);
/**
* Optimizes the table tb in the database db. May also do nothing, if the database doesn't support optimizing tables.
* Currently there is no signal emitted on success. This behaviour may change in the future.
*
* purely virtual, must be reimplemented.
*
* @param db databasename
* @param tb tablename
*/
virtual void slotTableOptimize(QString* db, QString* tb);
/**
* repairs the table tb in the database db. May also do nothing, if the database doesn't support repairing tables.
* Currently there is no signal emitted on success. This behaviour may change in the future.
*
* purely virtual, must be reimplemented.
*
* @param db databasename
* @param tb tablename
*/
virtual void slotTableRepair(QString* db, QString* tb);
/**
* Calls clearResult.
*
*/
void slotClearMemory();
/**
* Gets some information from the server and represents them in a QString msg. Emits serverStatus( QString msg ).
* The msg will be shown in a QMessagebox.
*
* purely virtual, must be reimplemented.
*
*/
virtual void slotServerStatus();
/**
* counts the rows in the table _tb in the databse _db. May be done by calling slotDoQuery().
* Currently there is no signal emitted on success. This behaviour may change in the future.
*
* purely virtual, must be reimplemented.
*
* @param db databasename
* @param tb tablename
*/
virtual void slotCountRows( QString* _db, QString* _tb);
signals:
virtual void connectionChanged();
virtual void loginComplete();
virtual void loginError();
virtual void resultChanged();
virtual void tableChecked();
virtual void tableOptimized();
virtual void tableRepaired();
virtual void NewDbCreated();
virtual void NewTableCreated();
virtual void DbErased();
virtual void TableErased();
virtual void DbQueryError( QString* errmsg );
virtual void QueryDone();
virtual void queryEmpty();
virtual void lastActionChanged( QString* db, QString* tab, QString* prim);
virtual void serverStatus( QString status );
public:
/**
* The hostname, to which we connect.
*/
QString doc_host;
/**
* The portnumber, on which the database-server is listening.
*/
unsigned short int doc_port;
/**
* The username, which we use for the login.
*/
QString doc_uname;
/**
* The password, which we use for the login.
*/
QString doc_pass;
/**
* The base, to which we are connected.
*/
QString doc_base;
base_t * DB;
QString *QUERY;
QString *STATUS;
QString *lastDB;
QString *lastTable;
QString *primKey;
int stat; // MySQL-Error-Code
int field_pos; // Aktuelle Position in der altuellen Zeile
int row_pos; // Aktuelle Zeilen-Position
row_t* RESULT_Start; // Pointer auf das erste Zeilen-Element der letzten SQL-Anfrage
row_t* RESULT; // Pointer auf das aktuelle Zeilen-Element der letzten SQL-Anfrage
protected slots:
void clearResult();
protected:
/**
* Extracts the database-name from the sql-statement sql. Still experimental, only tested for statements on MySQL.
*/
QString getDbFromSQL(QString * sql);
/**
* Extracts the table-name from the sql-statement sql. Still experimental, only tested for statements on MySQL.
* Currently works only, if exaclty one table is given in the statement.
*/
QString getTableFromSQL(QString * sql);
/**
* A pointer to a list of columns. This list contains the column-names and column-types of the last result.
*/
column_t * lastCols; // Pointer auf eine List mit den Spalten-Namen der letzten SQL-Query
QWidget *myParentWidget;
KLocale* kl;
/**
* An URL representing all data (i.e. database-type, host-, user- and basename) of the currently connected database-server.
*
* Valid URLs have the following structure: type://username\@hostname[/basename]
* Valid database-types (i.e. valid protocols) are: ibmdb2, mysql, oracle, pgsql, sapdb. These names might change in the near future (to be compatible with jdbc).
*
* Examples:
* mysql://nobody@localhost
* sapdb://DBA@mysqerver.org/TEST
*
*/
KURL doc_url;
/**
*/
base_t* cleardb( base_t ** db );
/**
*/
table_t* cleartb( table_t ** tb );
/**
*/
column_t* clearsp( column_t ** sp );
/**
*/
row_t* clearrw( row_t ** rw );
/**
*/
field_t* clearfd( field_t ** fd );
/**
*/
base_t* basePosition;
/**
*/
table_t* tablePosition;
/**
*/
column_t* columnPosition;
/**
*/
row_t* rowPosition;
/**
*/
field_t* fieldPosition;
/**
*/
SqlGuiView* view;
/**
*/
bool connectionEnabled;
};
typedef SqlGuiDoc* create_t(QWidget*);
typedef void destroy_t(SqlGuiDoc*);
#endif // SQLGUIDOC_H
Generated by: marcus on voyager on Mon Sep 16 15:31:33 2002, using kdoc 2.0a53. |