|
|
//*************************************************************************** /* * TOra - An Oracle Toolkit for DBA's and developers * Copyright (C) 2003 Quest Software, Inc * * 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; only version 2 of * the License is valid for this program. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, you have permission to link this program * with the Oracle Client libraries and distribute executables, as long * as you follow the requirements of the GNU GPL in regard to all of the * software in the executable aside from Oracle client libraries. * * Specifically you are not permitted to link this program with the * Qt/UNIX, Qt/Windows or Qt Non Commercial products of TrollTech. * And you are not permitted to distribute binaries compiled against * these libraries without written consent from Quest Software, Inc. * Observe that this does not disallow linking to the Qt Free Edition. * * All trademarks belong to their respective owners. * ****************************************************************************/ #ifndef TO_EXTRACT #define TO_EXTRACT #include <list> #include <map> #include <qfile.h> #include <qstring.h> #include <qtextstream.h> #include <qvariant.h> class QWidget; class toConnection; // Liberally ported from DDL::Oracle 1.06 // Copyright (c) 2000, 2001 Richard Sutherland - United States of America /** * This class can be used to reverse engineered database objects. */ class toExtract { public: /** This is an abstract class to implement part of an extractor for a database. Observe * that an extractor must be stateless and threadsafe except for constructors and * destructors. Use the toExtract::context function for saving context. */ class extractor { protected: /** Register an operation to be handled by this extractor. * @param db Database this extractor works on. * @param oper What kind of operation to implement. Can be one of CREATE, * DESCRIBE, MIGRATE or DROP. * @param type The type of object that this is implemented for. Database specific. */ void registerExtract(const QString &db, const QString &oper, const QString &type); /** Unregister an operation to be handled by this extractor. * @param db Database this extractor works on. * @param oper What kind of operation to implement. Can be one of CREATE, * DESCRIBE, MIGRATE or DROP. * @param type The type of object that this is implemented for. Database specific. */ void unregisterExtract(const QString &db, const QString &oper, const QString &type); public: /** Create an extractor. Normally called from a statical instantiator. Should register * objects it can handle @ref registerExtract. Apart from the objects it handles one * extractor per database can also register an empty operation and type parameter to * @ref registerExtract which will be called to initialize an extractor once per * constructed toExtract object. * operation. */ extractor(); /** Destructor. */ virtual ~extractor(); /** Initiate an extractor for a given connection. Can be used to set up states necessary * for further processing. Should probably set blocksize to be used for resizing (@ref * toExtract::setBlocksize). * @param ext Extractor to generate script. */ virtual void initialize(toExtract &ext) const; /** Called to generate a script to recreate a database object. * @param ext Extractor to generate script. * @param stream Stream to write script to. * @param type Type of object to recreate. * @param schema Specify the schema of the output script or description. If empty * don't specify any object. If the string "1" use same object as input. * Otherwise use the specified schema. * @param owner Owner of database object. * @param name Name of database object. * @return A string containing a script to recreate an object. */ virtual void create(toExtract &ext, QTextStream &stream, const QString &type, const QString &schema, const QString &owner, const QString &name) const; /** Called to describe a database object. * @param ext Extractor to generate script. * @param lst List of descriptions for the object. Should be appended. * @param type Type of object to recreate. * @param schema Specify the schema of the output script or description. If empty * don't specify any object. If the string "1" use same object as input. * Otherwise use the specified schema. * @param owner Owner of database object. * @param name Name of database object. */ virtual void describe(toExtract &ext, std::list<QString> &lst, const QString &type, const QString &schema, const QString &owner, const QString &name) const; /** Called to generate a script to migrate a database object from one description to * another description. * @param ext Extractor to generate script. * @param type Type of object to migrate. * @param src Source description list. * @param dst Destination description list. * @return A script to change the src database object to dst. */ virtual void migrate(toExtract &ext, QTextStream &stream, const QString &type, std::list<QString> &src, std::list<QString> &dst) const; /** Called to generate a script to drop an object. * @param ext Extractor to generate script. * @param type Type of object to recreate. * @param schema Specify the schema of the output script or description. If empty * don't specify any object. If the string "1" use same object as input. * Otherwise use the specified schema. * @param owner Owner of database object. * @param name Name of database object. * @return A string containing a script to recreate an object. */ virtual void drop(toExtract &ext, QTextStream &stream, const QString &type, const QString &schema, const QString &owner, const QString &name) const; }; private: toConnection &Connection; QWidget *Parent; // Attributes QString Schema; QString Resize; bool Code; bool Comments; bool Constraints; bool Contents; bool Grants; bool Heading; bool Indexes; bool Parallel; bool Partition; bool Prompt; bool Storage; bool Initialized; int CommitDistance; // Database info int BlockSize; std::list<QString> Initial; std::list<QString> Next; std::list<QString> Limit; // Context, can be used by the extractor to save context std::map<QCString,QVariant> Context; // Stuff to handle extractors static std::map<QString,extractor *> *Extractors; static void allocExtract(void); static QString extractorName(const QString &db, const QString &oper, const QString &type); static extractor *findExtractor(toConnection &conn, const QString &oper, const QString &type); extractor *findExtractor(const QString &oper, const QString &type) { return findExtractor(Connection,oper,type); } void initialize(void); // General internal functions /** Parse an object string to get owner and name of the object. * @param object Object string on the format {owner}.{name}. * @param owner Reference to string which will get the object owner. * @param name Reference to string which will get the object name. */ void parseObject(const QString &object,QString &owner,QString &name); void setSizes(void); void rethrow(const QString &what,const QString &object,const QString &exc); QString generateHeading(const QString &action,std::list<QString> &list); static std::map<QString,std::list<QString> > migrateGroup(std::list<QString> &grpLst); public: /** Create a new extractor. * @param conn Connection to extract from. * @param parent Parent widget of progress indicator. */ toExtract(toConnection &conn,QWidget *parent); /** Create script to recreate list of objects. * @param object List of object. This has the format {type}:{schema}.{object}. * The type is database dependent but can as an example be of * CONSTRAINT, DATABASE LINK, EXCHANGE INDEX, * EXCHANGE TABLE, FUNCTION, INDEX, MATERIALIZED VIEW, * MATERIALIZED VIEW LOG, PACKAGE, PACKAGE BODY, PROCEDURE, * PROFILE, ROLE, ROLE GRANTS, ROLLBACK SEGMENT, SEQUENCE, * SNAPSHOT, SNAPSHOT LOG, SYNONYM, TABLE, TABLE FAMILY, * TABLE CONTENTS, TABLE REFERENCES, TABLESPACE, TRIGGER, * TRIGGER, TYPE, USER, USER GRANTS for Oracle databases. * @return A string containing a script to recreate the specified objects. */ QString create(std::list<QString> &object) { QString ret; QTextStream s(&ret,IO_WriteOnly); create(s,object); return ret; } /** Create script to recreate list of objects. * @param stream Stream to write result to. * @param object List of object. This has the format {type}:{schema}.{object}. * The type is database dependent but can as an example be of * CONSTRAINT, DATABASE LINK, EXCHANGE INDEX, * EXCHANGE TABLE, FUNCTION, INDEX, MATERIALIZED VIEW, * MATERIALIZED VIEW LOG, PACKAGE, PACKAGE BODY, PROCEDURE, * PROFILE, ROLE, ROLE GRANTS, ROLLBACK SEGMENT, SEQUENCE, * SNAPSHOT, SNAPSHOT LOG, SYNONYM, TABLE, TABLE FAMILY, * TABLE CONTENTS, TABLE REFERENCES, TABLESPACE, TRIGGER, * TRIGGER, TYPE, USER, USER GRANTS for Oracle databases. */ void create(QTextStream &stream,std::list<QString> &object); /** Create a description of objects. * @param object List of object. This has the format {type}:{schema}.{object}. * The type is database dependent but can as an example be of * CONSTRAINT, DATABASE LINK, EXCHANGE INDEX, * EXCHANGE TABLE, FUNCTION, INDEX, MATERIALIZED VIEW, * MATERIALIZED VIEW LOG, PACKAGE, PACKAGE BODY, PROCEDURE, * PROFILE, ROLE, ROLE GRANTS, ROLLBACK SEGMENT, SEQUENCE, * SNAPSHOT, SNAPSHOT LOG, SYNONYM, TABLE, TABLE FAMILY, * TABLE CONTENTS, TABLE REFERENCES, TABLESPACE, TRIGGER, * TRIGGER, TYPE, USER, USER GRANTS for Oracle databases. * @return A list of strings describing the objects. Each string should be * considered like a list of strings separated by the character '\001'. * The later in each string the smaller item the change and it is hierachical. */ std::list<QString> describe(std::list<QString> &object); /** Create script to drop a list of objects. * @param object List of object. This has the format {type}:{schema}.{object}. * The type is database dependent but can as an example be of * CONSTRAINT, DATABASE LINK, EXCHANGE INDEX, * EXCHANGE TABLE, FUNCTION, INDEX, MATERIALIZED VIEW, * MATERIALIZED VIEW LOG, PACKAGE, PACKAGE BODY, PROCEDURE, * PROFILE, ROLE, ROLE GRANTS, ROLLBACK SEGMENT, SEQUENCE, * SNAPSHOT, SNAPSHOT LOG, SYNONYM, TABLE, TABLE FAMILY, * TABLE CONTENTS, TABLE REFERENCES, TABLESPACE, TRIGGER, * TRIGGER, TYPE, USER, USER GRANTS for Oracle databases. * @return A string containing a script to drop the specified objects. */ QString drop(std::list<QString> &object) { QString ret; QTextStream s(&ret,IO_WriteOnly); drop(s,object); return ret; } /** Create script to drop a list of objects. * @param stream Stream to write result to. * @param object List of object. This has the format {type}:{schema}.{object}. * The type is database dependent but can as an example be of * CONSTRAINT, DATABASE LINK, EXCHANGE INDEX, * EXCHANGE TABLE, FUNCTION, INDEX, MATERIALIZED VIEW, * MATERIALIZED VIEW LOG, PACKAGE, PACKAGE BODY, PROCEDURE, * PROFILE, ROLE, ROLE GRANTS, ROLLBACK SEGMENT, SEQUENCE, * SNAPSHOT, SNAPSHOT LOG, SYNONYM, TABLE, TABLE FAMILY, * TABLE CONTENTS, TABLE REFERENCES, TABLESPACE, TRIGGER, * TRIGGER, TYPE, USER, USER GRANTS for Oracle databases. * @return A string containing a script to drop the specified objects. */ void drop(QTextStream &stream,std::list<QString> &object); /** Called to generate a script to migrate a database object from one description to * another description. * @param stream Stream to write result to. * @param src Source description list, generated by describes for the same database. * @param dst Destination description list, generated by describes for the same database. * @return A script to change the src database object to dst. */ QString migrate(std::list<QString> &drpLst,std::list<QString> &crtLst) { QString ret; QTextStream s(&ret,IO_WriteOnly); migrate(s,drpLst,crtLst); return ret; } /** Called to generate a script to migrate a database object from one description to * another description. * @param stream Stream to write result to. * @param src Source description list, generated by describes for the same database. * @param dst Destination description list, generated by describes for the same database. * @return A script to change the src database object to dst. */ void migrate(QTextStream &stream,std::list<QString> &drpLst,std::list<QString> &crtLst); /** Set a context for this extractor. * @param name Name of this context * @param val Value of this context */ void setState(const QCString &name,const QVariant &val); /** Get the value of a context for the current extractor. * @param name Name of the context to extract. * @return The value of the context. */ QVariant state(const QCString &name); /** Set the schema of the extraction. * @param schema Specify the schema of the output script or description. If empty * don't specify any object. If the string "1" use same object as input. * Otherwise use the specified schema. */ void setSchema(const QString &schema) { Schema=schema; } /** Set sizes to use for resize of object on extraction. * @param A list of sizes separated by ':'. Should be an even multiple of three where * the first value is the largest current size to use these values. The next * value is the initial value to use, the last is the next increment value to * use. As a special case the string "1" can be used to set up auto resize. */ void setResize(const QString &resize) { Resize=resize; setSizes(); } /** Set inclusion of prompts. * @param prompt If prompt generation should be generated. */ void setPrompt(bool prompt) { Prompt=prompt; } /** Include heading in scripts. * @param heading Include heading in scripts. */ void setHeading(bool heading) { Heading=heading; } /** Include constraints in extraction. * @param constraints Include constraints. */ void setConstraints(bool constraints) { Constraints=constraints; } /** Include indexes in extraction. * @param indexes Include indexes. */ void setIndexes(bool indexes) { Indexes=indexes; } /** Include grants in extraction. * @param val Include grants. */ void setGrants(bool val) { Grants=val; } /** Include storage specification in extraction. * @param val Include storage specification. */ void setStorage(bool val) { Storage=val; } /** Include parallel specification in extraction. * @param val Include parallel specification. */ void setParallel(bool val) { Parallel=val; } /** Include partition specification in extraction. * @param val Include partition specification. */ void setPartition(bool val) { Partition=val; } /** Include contents of tables in scripts. * @param val Include contents of tables. * @param commitdistance The commit distance of the contents 0 means whole tables. */ void setContents(bool val,int commitdistance) { Contents=val; CommitDistance=commitdistance; } /** Include comments in extraction. * @param val Include indexes. */ void setComments(bool val) { Comments=val; } /** Include code in extraction. * @param val Include code. */ void setCode(bool val) { Code=val; } /** Set blocksize of database. * @param val New value of blocksize. */ void setBlockSize(int val) { BlockSize=val; setSizes(); } /** Get schema specification. * @return Schema specification. * @see setSchema */ const QString &getSchema(void) { return Schema; } /** Get resize specification. * @return Resize specification. * @see setResize */ bool getResize(void) { return !Resize.isEmpty(); } /** Check if prompt are generated. * @return If prompts are generated. */ bool getPrompt(void) { return Prompt; } /** Check if headings are generated. * @return If headings are generated. */ bool getHeading(void) { return Heading; } /** Check if constraints are generated. * @return If constraints are generated. */ bool getConstraints(void) { return Constraints; } /** Check if indexes are generated. * @return If indexes are generated. */ bool getIndexes(void) { return Indexes; } /** Check if grants are generated. * @return If grants are generated. */ bool getGrants(void) { return Grants; } /** Check if storage specification are generated. * @return If storage specification are generated. */ bool getStorage(void) { return Storage; } /** Check if parallell specification are generated. * @return If parallell specification are generated. */ bool getParallel(void) { return Parallel; } /** Check if partition specification are generated. * @return If partition specification are generated. */ bool getPartition(void) { return Partition; } /** Check if contents of tables are generated. * @return If content is generated. */ bool getContents(void) { return Contents; } /** Get the distance of the commits when content is generated. * @return Commit distance. */ int getCommitDistance(void) { return CommitDistance; } /** Check if comments are generated. * @return If comments are generated. */ bool getComments(void) { return Comments; } /** Check if code is generated. * @return If code is generated. */ bool getCode(void) { return Code; } /** Get blocksize. */ int getBlockSize(void) { return BlockSize; } /** Get the connection this extractor is working on. */ toConnection &connection() { return Connection; } /** Fill in the initial and next value for an object currently holding a @ref number of * allocated blocks. Uses the resize or default sizes. * @param blocks Blocks currently allocated. * @param initial New initial value. * @param next New next value. */ void initialNext(const QString &blocks,QString &initial,QString &next); /** Get the schema name specified by the extractor setup. Will include the following '.' * if needed. * @param owner Owner of object to get schema for. * @param desc Used from describe and not to generate script. * @return The translated schema. */ QString intSchema(const QString &owner,bool desc); /** Create a source and destination object list to two other lists * containing dropped and created objects or attributes. * @param source Source list input (Will not be modified). * @param destination Destination list input (Will not be modified). * @param drop Drop list output (Will be overwritten). * @param create Create list output (Will be overwritten). */ static void srcDst2DropCreate(std::list<QString> &source,std::list<QString> &destination, std::list<QString> &drop,std::list<QString> &creat); /** Check if a database is supported at all by the extractor. * @param conn Connection to check for support. * @return True if the database is supported. */ static bool canHandle(toConnection &conn); /** Add a list to description. * @param ret The return list to add a line to. * @param ctx The current description context. * @param arg1 First extra argument to add. */ static void addDescription(std::list<QString> &ret,std::list<QString> &ctx, const QString &arg1=QString::null,const QString &arg2=QString::null, const QString &arg3=QString::null,const QString &arg4=QString::null, const QString &arg5=QString::null,const QString &arg6=QString::null, const QString &arg7=QString::null,const QString &arg8=QString::null, const QString &arg9=QString::null); /** Split a description line into its components. * @param str The description line to split. * @return The list of components. */ static std::list<QString> splitDescribe(const QString &str); /** Get the part of a description indicated by the level * @param str Description string * @param level The level to get (0 is the first level) */ static QString partDescribe(const QString &str,int level); /** Get the context of a given level. * @param str Description string * @param level The level to get the context for (1 is the first to not return empty string. * @return The context, if not enough parts are available null is returned. */ static QString contextDescribe(const QString &str,int level); friend class extractor; }; #endif