Qore SqlUtil Module Reference 1.9
|
Most schema management is performed by using the Database class (which is a wrapper for the AbstractDatabase class).
The most complex object is the AbstarctTable, which has its own section.
One of the primary goals of schema management in SqlUtil is to facilitate automatic schema management from a database-independent schema description. The idea is that a schema can be described in a generic way and then SqlUtil can use the generic schema description to align the database with the description. Aligning in SqlUtil is performed as follows:
Unfortuntely, it's not currently possible to describe all database objects in a generic way (and it probably never will be); in particular, functions, triggers, and other objects based on procedural code or database-specific functionality have to be defined in their database-specific formats.
The following is a table describing the alignment support for various objects supported by SqlUtil; for database-specific objects, see the database-specific SqlUtil module:
Database Object | Alignment Type |
Columns | aligned in place |
Constraints | dropped and recreated |
Functions and Procedures | dropped and recreated |
Indexes | dropped and recreated |
Sequences | dropped and recreated |
Triggers | dropped and recreated |
AbstractTables | aligned in place |
New objects are generally creating using appropriate methods from the Database class, such as the following:
Tables can also be created by instantiating a Table object (see SqlUtil::AbstractTable::constructor()).
Each database driver may provide additional objects (such as types or materialized views, etc); see driver-specific documentation for more information.
Existing objects can be retrieved from the database using appropriate methods from the Database class, such as the following:
Each database driver may provide additional objects (such as types or materialized views, etc); see driver-specific documentation for more information.
Listing database objects can be performed using appropriate methods from the Database class, such as the following:
Alternatively, iterators for lists of objects can be acquired with the following methods:
The SqlUtil::Tables class manages a group of tables and the foreign key dependencies between the tables. This class is useful when managing an entire schema, particularly in the context of manual changes to a schema, such as a schema upgrade or downgrade for complex scenarios that are beyond the capabilities of the automatic schema and table alignment code.
Below you can find some examples of what the Tables class can do.
A schema template can be created any way required (ie by hand, or by retrieving the description from another database), but typically they will be created from a schema description hash.
The following code provides an example of creating a schema template and using it to align the schema in the database with the template using callbacks:
The schema description hash has the following structure:
tables:
a hash of table description hashes keyed by table name; each entry describes a tablesequences:
a hash of sequence description hashes keyed by sequence name; each entry describes a sequencefunctions:
a hash of function description hashes keyed by function name; each entry describes a functionprocedures:
a hash of procedure description hashes keyed by procedure name; each entry describes a proceduredriver:
this key can optionally contain a hash keyed by driver name which contains a hash of values that will be added to the schema description hash before processing; this way a schema description hash can contain all the information required for the schema including driver-specific options; any driver-specific options will overwrite values in the top level of the hash if there are duplicate hash keysEach database driver may provide additional objects (such as types or materialized views, packages, etc); see driver-specific documentation for more information.
The following is an example of a schema description hash:
The main class to be used for table management is Table (which is a wrapper for AbstractTable). This class can be used both for building a table from scratch or for retrieving the structure of a table from the database.
Real table related work is done in AbstractTable. AbstractTable is also instance returned from most of API calls used.
Tables can be created manually, by creating a Table object and then populating the table with columns, indexes, etc, and then calling SqlUtil::AbstractTable::create() for example. The following methods can be used for adding new attributes to a table:
Note that if the table is known to be in the database already (for example, if the original table info was read from the database), then calling one of the above methods will also effect the change in the database immediately.
Alternatively, the following methods can be used to retrieve the SQL that can be executed for the particular database driver that the SqlUtil::Table object is based on:
Otherwise a table can be built from a table description hash with one of the following methods:
Table description hashes are also used when aligning tables to a template, which can be used to automate schema upgrades; see SqlUtil::AbstractTable::getAlignSql(), SqlUtil::AbstractDatabase::getAlignSql(), and table description hash for more information.
The following methods retrieve table information from the database:
The SqlUtil::AbstractTable::cache() method can be used to retrieve all table information from the database immediately as in the following example:
Use the following code to test if a table exists:
Or the following:
Template tables can be created any way required (ie by hand, or by retrieving the description from another database), but typically they will be created from a table description hash.
The following code provides an example of creating a template table and using it to align a table in the database with the template using callbacks:
Table description hashes have the following structure:
columns:
(required) a hash of column information keyed by column name; the values are column description hashesprimary_key:
(optional) a primary key description hash describing the primary key for the tableindexes:
(optional) a hash of index information keyed by index name; the values are index description hashestriggers:
(optional) a hash of trigger information keyed by trigger name; the values are the trigger source code; since triggers are driver-dependent, a driver-independent table description would include trigger hashes under the drivers
key and the driver key name under that; see below for an exampleforeign_constraints:
(optional) a hash of foreign constraint information keyed by constraint name; the values are foreign constraint hashesunique_constraints:
(optional) a hash of unique constraint information keyed by constraint name; the values are unique constraint hashesdriver:
this key can optionally contain a hash keyed by driver name which contains a hash of values that will be added to the table description hash before processing; this way a table description hash can contain all the information required for the table including driver-specific options; any driver-specific options will overwrite values in the top level of the hash if there are duplicate hash keys, see below for an exampleHere is an example of a table description hash:
"pgsql"
driver: "functions"
which is used by the PgsqlSqlUtil module to create trigger functions used by the table's trigger.Column description hashes have the following structure:
qore_type:
a qore type string that will be converted to a native DB type with some default conversionnative_type:
the native database column type; if both native_type
and qore_type
are given then native_type
is usedsize:
for data types requiring a size component, the size; for numeric columns this represents the precision for examplescale:
for numeric data types, this value gives the scaledefault_value:
the default value for the columndefault_value_native:
a boolean flag to say if a default_value
should be validated against table column type (False) or used as it is (True) to allow to use DBMS native functions or features. Defaults to False. It is strongly recommended to use default_value_native
for default_value
in driver
specific sub-hash to avoid non-portable schema hashescomment:
an optional comment for the columnnotnull:
if the column should have a "not null" constraint on it; if missing the default value is Falsedriver:
this key can optionally contain a hash keyed by driver name which contains a hash of values that will be added to the column description hash before processing; this way a column description hash can contain all the information required for the column including driver-specific options; any driver-specific options will overwrite values in the top level of the hash if there are duplicate hash keys, see below for an exampleNote that the above structure is an extension of the fields in SqlUtil::AbstractTable::ColumnDescOptions, adding notnull
and driver
keys for additional information to create the column in the table.
Here is an example of a column description hash:
The above hash<auto> describes a column that will be have TIMESTAMP
type on most databases, but DATE
on Oracle.
The primary key description hash has the following keys:
name:
(required) the name of the primary keycolumns:
(required) a single column name or a list of column names making up the primary keyHere is an example of a primary key description hash:
The foreign constraint description hash has the following keys:
columns:
(required) a single column name or a list of column names in the current table making up the foreign constrainttable:
(required) a string giving the name of the table the foreign constraint is ontarget_columns:
(optional) this key is only necessary if the columns in the foreign table have different names than in the current table; if so, it must be assigned to a single column name or a list of column names in the foreign table; if this key is present then the same number of columns must appear in each keyThe following is an example of a foreign key description hash:
The unique constraint description hash has the following key:
columns:
(required) a single column name or a list of column names in the current table making up the unique constraintThe following is an example of a unique constraint description hash:
Index description hashes have the following structure:
columns:
(required) a single column or a list of column names making up the indexunique:
a boolean value indicating if the index is unique or not, if missing, then the index is assumed to e not uniqueThe following is an example of an index description hash:
Most of the SqlUtil methods that return SQL strings also accept an option hash where callbacks an be set. Callbacks can be used to display detailed information about long-running operations, such as schema or data alignment for complex schemas or large data sets, or as a generic framework for executing and logging SQL operations.
the "error_callback"
closure or call reference is called with information about the current SQL operation if an error occurs in the sql callback and can be specified as in the following example:
The "info_callback"
closure or call reference is called with information about the current SQL operation and can be specified as in the following example:
The "sql_callback"
closure or call reference is called with an SQL string suitable for raw execution for each SQL command that is returned or generated for a particular operation and can be specified as in the following example:
If the "sql_callback_executed"
flag is set to True then the called method knows that the changes are made in the database and the internal representation of the affected object(s) is also updated accordingly. Here is an example:
The "sqlarg_callback"
closure or call reference is called with an SQL string and arguments for each SQL command that is executed during SQL data operations and can be specified as in the following example:
The "info_callback"
upsert option key can be assigned to a closure or call reference that is called whenever an row result is available; this callback takes the following arguments:
Here is an example of an upsert callback:
This option is identical to Upsert Info Callback, except the result argument is always SqlUtil::AbstractTable::UR_Inserted.