OracleSqlUtil.qm.dox.h
// -*- mode: c++; indent-tabs-mode: nil -*-
// @file OracleSqlUtil.qm Qore user module for working with Oracle SQL data
/* OracleSqlUtil.qm Copyright 2013 - 2016 Qore Technologies, sro
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
// this module requires Qore 0.8.12 or better
// requires the SqlUtil module
// requires the Util module
// for bindOracleCollection
// don't use "$" signs for variables and class members, assume local variable scope
// require type definitions everywhere
// enable all warnings
/* Version History: see docs below
*/
a.*, rownum rnum from (select * from schema.table where type = %v order by type) a where rownum <= %v) where rnum > %v", ("user", 300, 200));
@endcode
note that the following simpler SQL is generated for Oracle 12c+ servers:
@code{.py}
$ds.vselectRows("select * from schema.table where type = %v order by type offset %v rows fetch next %v rows only", ("user", 200, 100));
@endcode
@subsection ora_in_operator IN Operator on Oracle
In order to avoid dynamic SQL and better manage the server's shared pool (in particular, the number of parsed statements), the %OracleSqlUtil
module uses bind by value with the SQL \c IN operator.
For example, the following query:
@code{.py}
my *hash $q = $table.select(("where": ("col1": op_in(1, 2, 3, 4))));
@endcode
Results in the equivalent of the following SQL:
@code{.py}
my *hash $q = $ds.select("select * from schema.table where col1 in (select column_value from table(%v))", bindOracleCollection("SYS.ODCIVARCHAR2LIST", (1,2,3,4)));
@endcode
@htmlonly <style><!-- td.qore { background-color: #5b9409; color: white; } --></style> @endhtmlonly
<table>
<tr>
<td class="qore"><b>Qore Type</b></td>
<td class="qore"><b>Oracle Collection</b></td>
</tr>
<tr>
<td>Date</td>
<td>\c SYS.ODCIDATELIST</td>
</tr>
<tr>
<td>Float</td>
<td>\c SYS.ODCINUMBERLIST</td>
</tr>
<tr>
<td>Integer</td>
<td>\c SYS.ODCINUMBERLIST</td>
</tr>
<tr>
<td>Number</td>
<td>\c SYS.ODCINUMBERLIST</td>
</tr>
<tr>
<td>String</td>
<td>\c SYS.ODCIVARCHAR2LIST</td>
</tr>
</table>
There universal collections are limited to 32767 elements. And \c SYS.ODCIVARCHAR2LIST element size is \c VARCHAR2(4000).
@subsection ora_partitioning_select Partition Support in Selects
It's possible to select from a particular partition of a table with %OracleSqlUtil;
@ref OracleSqlUtil::OracleTable::OracleSelectOptions "OracleSelectOptions" defines the \c "partition" key which can be added to a
@ref select_option_hash "select option hash " to specify the partition to select from as in the following example:
@code{.py}
my *list $rows = $table.selectRows(("created": op_gt(2012-05-01), "partition": "p1"));
@endcode
Which generates an SQL command like the following:
@code{.py}
my *list $rows = $ds.vselectRows("select * from schema.table partition(p1) where created > %v", (2012-05-01));
@endcode
@subsection ora_partitioning_join Partition Support in Joins
It's possible to perform a join on a particular partition of a table with %OracleSqlUtil; the join option \c "partition" is
supported to specify the partition to join on as in the following example:
@code{.py}
my *list $rows = $table.selectRows(("join": join_inner($table2, "t2", ("id": "altid"), NOTHING, ("partition": "p2"))));
@endcode
Which generates an SQL command like the following:
@code{.py}
my *list $rows = $ds.vselectRows("select * from schema.table inner join schema.table2 partition(p2) t2 on (schema.table.id = t2.altid)");
@endcode
@section ora_schema_management Schema Management on Oracle
Note that when getting an object description from an Oracle database, if the object cannot be found in the connection schema, then
if a synonym of the same type exists and the target object is accessible, then the target object is read automatically and the owning
schema name is also set to the actual owner of the object.
@subsection ora_type_mapping Type Mapping
Column types are mapped from %Qore types as follows:
<b>Oracle Column Type Mappings</b>
<table>
<tr>
<td class="qore"><b>Generic Type Name</b></td>
<td class="qore"><b>Oracle Type Used</b></td>
</tr>
<tr>
<td>\c float</td>
<td>\c number</td>
</tr>
<tr>
<td>\c integer</td>
<td>\c number</td>
</tr>
<tr>
<td>\c number</td>
<td>\c number</td>
</tr>
<tr>
<td>\c string</td>
<td>\c varchar2</td>
</tr>
<tr>
<td>\c date</td>
<td>\c timestamp(6)</td>
</tr>
<tr>
<td>\c binary</td>
<td>\c blob</td>
</tr>
<tr>
<td>@ref SqlUtil::BLOB</td>
<td>\c blob</td>
</tr>
<tr>
<td>@ref SqlUtil::CHAR</td>
<td>\c char</td>
</tr>
<tr>
<td>@ref SqlUtil::CLOB</td>
<td>\c clob</td>
</tr>
<tr>
<td>@ref SqlUtil::NUMERIC</td>
<td>\c number</td>
</tr>
<tr>
<td>@ref SqlUtil::VARCHAR</td>
<td>\c varchar2</td>
</tr>
</table>
To use other types, use the \c "native_type" @ref SqlUtil::AbstractTable::ColumnDescOptions "column description option" with the
native Oracle type name instead (under the \c "driver" and \c "oracle" keys for schemas supporting multiple databases).
@subsection ora_other_objects Additional Object Types Supported
The following additional schema objects can be managed with %OracleSqlUtil:
- @ref ora_materialized_views "materialized views"
- @ref ora_packages "packages"
- @ref ora_types "types"
@subsection ora_materialized_views Materialized Views
The @ref schema_desc_hash takes an optional key, \c "materialized_views" that allows materialized views in Oracle schemas to be managed along with other objects.
The \c "materialized_views" should be assigned to a hash, each key name is the name of the materialized view, and the values are hashes with the
following keys:
- \c "logging": (@ref bool_type "bool") if the materialized view should be logged
- \c "use_index": (@ref bool_type "bool") if the materialized view should be indexed
- \c "src": (@ref bool_type "bool") the source of the materialized view
The \c "materialized_views" key can go in the top level of the @ref schema_desc_hash for Oracle-only schemas, or, for schemas targeting multiple database types, under the \c "driver" and \c "oracle" keys as in the following example:
@code{.py}
my hash $schema = (
"driver": (
"oracle": (
"materialized_views": (
"example_mv": (
"logging": False,
"use_index": False,
"src": "select type, count(1) total_count from table group by type",
),
),
),
),
);
@endcode
@subsection ora_packages Packages
The @ref schema_desc_hash takes an optional key, \c "packages" that allows packages in Oracle schemas to be managed along with other objects.
The \c "packages" should be assigned to a hash, each key name is the name of the package, and the values are hashes with the
following key:
- \c "src": (@ref bool_type "bool") the source of the package
The \c "packages" key can go in the top level of the @ref schema_desc_hash for Oracle-only schemas, or, for schemas targeting multiple database types, under the \c "driver" and \c "oracle" keys as in the following example:
@code{.py}
my hash $schema = (
"driver": (
"oracle": (
"packages": (
"example_pkg": (
"src": "types as
type cursorType is ref cursor;
MYSTATCOMPLETE constant order_status.orderstatus%type := 'C';
MYSTATERROR constant order_status.orderstatus%type := 'E';
",
),
),
),
),
);
@endcode
@subsection ora_types Types
The @ref schema_desc_hash takes an optional key, \c "types" that allows types in Oracle schemas to be managed along with other objects.
The \c "types" should be assigned to a hash, each key name is the name of the type, and the values are strings giving the type definition.
The \c "types" key can go in the top level of the @ref schema_desc_hash for Oracle-only schemas, or, for schemas targeting multiple database types, under the \c "driver" and \c "oracle" keys as in the following example:
@code{.py}
my hash $schema = (
"driver": (
"oracle": (
"types": (
"num_array": "table of number",
"str_array": "table of varchar2(240)",
),
),
),
);
@endcode
@see OracleSqlUtil::OracleDatabase::OracleSchemaDescriptionOptions for a list of Oracle-specific schema description hash keys.
@section ora_relnotes Release Notes
@subsection v12 OracleSqlUtil v1.2
- implemented support for the \c "returning" clause as an insert option
- implemented support for views for DML in the @ref OracleSqlUtil::OracleTable class
- implemented @ref OracleSqlUtil::OracleTable::getBaseType()
- implemented support for Oracle pseudocolumns in queries
- implemented support for @ref SqlUtil::cop_cast() operator
- fixed bugs in @ref SqlUtil::cop_seq() and @ref SqlUtil::cop_seq_currval() (<a href="https://github.com/qorelanguage/qore/issues/624">issue 624</a>)
- return lists from Oracle's data dictionary ordered
- implemented @ref OracleSqlUtil::OracleTable::bindEmptyStringsAsNull()
- implemented high-performance "upsert" (merge) support also supporting bulk DML
- implemented @ref SqlUtil::cop_substr() and @ref SqlUtil::uop_substr() operators (<a href="https://github.com/qorelanguage/qore/issues/801">issue 801</a>)
- implemented @ref SqlUtil::op_substr() where operator (<a href="https://github.com/qorelanguage/qore/issues/883">issue 883</a>)
@subsection v11 OracleSqlUtil v1.1
- fixed selects with "limit" but no "offset"
- convert date/time values to timestamps with microseconds resolution instead of dates with second resolution when dynamically inserting values as strings in SQL (binding by value not affected)
- fixed schema information classes when the "string-numbers" driver option is enabled
@subsection v10 OracleSqlUtil v1.0
- initial release
*/
namespace OracleSqlUtil {
OracleTable get_table(AbstractDatasource nds, string nname, *hash opts);
OracleDatabase get_database(AbstractDatasource nds, *hash opts);
class OracleColumn : public SqlUtil::AbstractColumn {
public:
public :
bool char_used;
int byte_size;
public:
constructor(string n, string nt, *string qt, softint sz, bool nul, *string dv, *string cm, bool is_char = False, bool cu = False, softint bs) ;
string getNativeTypeString();
list getAddColumnSql(AbstractTable t);
list getModifySqlImpl(AbstractTable t, AbstractColumn col, *hash opt);
string getRenameSql(AbstractTable t, string new_name);
bool equalImpl(AbstractColumn c);
};
class OracleNumberColumn : public OracleColumn,public SqlUtil::NumericColumnInfo {
public:
constructor(string n, string nt, *string qt, softint sz, bool nul, *string dv, *string cm, softint bs, softint n_scale = 0) ;
string getNativeTypeString();
};
class OracleIndex : public SqlUtil::AbstractIndex {
public:
public :
string native_type;
*string tablespace;
public:
constructor(string n, bool u, hash c, string nt, *string t) ;
string getCreateSql(string table_name, *hash opt);
bool equalImpl(AbstractIndex ix);
string getRenameSql(string table_name, string new_name);
};
class OracleForeignConstraint : public SqlUtil::AbstractForeignConstraint {
public:
public :
bool enabled;
public:
constructor(string n, Columns c, ForeignConstraintTarget t, bool e) ;
string getCreateSql(string table_name, *hash opt);
softlist getRenameSql(string table_name, string new_name);
string getDisableSql(string table_name);
string getEnableSql(string table_name, *hash opt);
};
class OracleCheckConstraint : public SqlUtil::AbstractCheckConstraint {
public:
public :
bool enabled;
public:
constructor(string n, string n_src, bool e = True) ;
string getCreateSql(string table_name, *hash opt);
softlist getRenameSql(string table_name, string new_name);
string getDisableSql(string table_name);
string getEnableSql(string table_name, *hash opt);
};
class OracleUniqueConstraint : public SqlUtil::AbstractUniqueConstraint {
public:
private :
bool enabled;
*string tablespace;
public:
constructor(string n, hash n_cols, bool e = True, *string ts) ;
OracleColumn memberGate(string k);
bool setIndexBase(string ix);
clearIndex();
string getCreateSql(string table_name, *hash opts);
softlist getRenameSql(string table_name, string new_name);
string getDisableSql(string table_name);
string getEnableSql(string table_name, *hash opt);
bool isEnabled();
*string getTablespace();
};
class OraclePrimaryKey : public SqlUtil::AbstractPrimaryKey {
public:
private :
*string tablespace;
public:
constructor();
constructor(string n, *hash c, *string ts) ;
OracleColumn memberGate(string k);
bool setIndexBase(string ix);
clearIndex();
string getCreateSql(string table_name, *hash opts);
softlist getRenameSql(string table_name, string new_name);
string getDropSql(string table_name);
string getDisableSql(string table_name);
string getEnableSql(string table_name, *hash opt);
};
class OracleSequence : public SqlUtil::AbstractSequence {
public:
constructor(string n_name, number n_start = 1, number n_increment = 1, *softnumber n_end) ;
string getCreateSql(*hash opt);
string getRenameSql(string new_name);
};
class OracleView : public SqlUtil::AbstractView {
public:
public :
*string type_text;
*string oid_text;
*string view_type_owner;
*string view_type;
*string superview_name;
bool container_data;
public:
constructor(string n_name, string n_src, *string n_schema, *string n_type_text,
*string n_oid_text, *string n_view_type_owner,
*string n_view_type, *string n_superview_name,
bool n_updatable, bool n_container_data)
;
string getCreateSql(*hash opt);
softlist getRenameSql(string new_name);
};
class OracleTrigger : public SqlUtil::AbstractTrigger {
public:
public :
bool enabled;
public:
constructor(string n, string n_src, bool en = True) ;
softlist getCreateSql(string table_name, *hash opt);
bool equalImpl(AbstractFunctionBase t);
softlist getRenameSql(string table_name, string new_name);
softlist getDropSql(string table_name);
};
class OracleCodeBase : public SqlUtil::AbstractFunction {
public:
constructor(string n, string n_type, string n_src) ;
softlist getCreateSql(*hash opt);
bool equalImpl(AbstractFunctionBase t);
list getRenameSql(string new_name);
};
class OracleType : public OracleCodeBase {
public:
constructor(string n_name, string n_src) ;
string getDropSqlForce();
};
class OracleFunction : public OracleCodeBase {
public:
constructor(string n, string n_src) ;
};
class OracleProcedure : public OracleCodeBase {
public:
constructor(string n, string n_src) ;
};
class OraclePackage : public OracleCodeBase {
public:
private :
*string body_src;
public:
constructor(string n, string n_src, *string n_body_src) ;
list getCreateSql(*hash opt);
bool equalImpl(AbstractFunctionBase t);
};
class OracleMaterializedView : public OracleCodeBase {
public:
public :
bool logging;
bool use_index;
*string tablespace;
public:
constructor(string n, string n_src, bool n_logging = True, bool n_use_index = True, *string n_tablespace) ;
softlist getCreateSql(*hash opt);
bool equalImpl(AbstractFunctionBase t);
};
class OracleDatabase : public SqlUtil::AbstractDatabase {
public:
public :
const OracleCreationOptions = AbstractDatabase::CreationOptions + (
"compute_statistics": Type::Boolean,
);
const OracleAlignSchemaOptions = AbstractDatabase::CreationOptions
+ OracleCreationOptions
+ OracleTable::OracleAlignTableOptions
;
const OracleSchemaDescriptionOptions = AbstractDatabase::SchemaDescriptionOptions + (
"types": Type::Hash,
"type_map": Type::Hash,
"packages": Type::Hash,
"package_map": Type::Hash,
"materialized_views": Type::Hash,
"materialized_view_map": Type::Hash,
//"synonyms": Type::Hash,
//"synonym_map": Type::Hash,
);
const OraclePackageDescriptionOptions = (
"src": Type::String,
"body": Type::String,
);
const OracleMaterializedViewDescriptionOptions = (
"logging": Type::Boolean,
"use_index": Type::Boolean,
"tablespace": Type::String,
"src": Type::String,
);
const OracleReservedWords = (
"access": True,
"else": True,
"modify": True,
"start": True,
"add": True,
"exclusive": True,
"noaudit": True,
"select": True,
"all": True,
"exists": True,
"nocompress": True,
"session": True,
"alter": True,
"file": True,
"not": True,
"set": True,
"and": True,
"float": True,
"notfound": True,
"share": True,
"any": True,
"for": True,
"nowait": True,
"size": True,
"arraylen": True,
"from": True,
"null": True,
"smallint": True,
"as": True,
"grant": True,
"number": True,
"sqlbuf": True,
"asc": True,
"group": True,
"of": True,
"successful": True,
"audit": True,
"having": True,
"offline": True,
"synonym": True,
"between": True,
"identified": True,
"on": True,
"sysdate": True,
"by": True,
"immediate": True,
"online": True,
"table": True,
"char": True,
"in": True,
"option": True,
"then": True,
"check": True,
"increment": True,
"or": True,
"to": True,
"cluster": True,
"index": True,
"order": True,
"trigger": True,
"column": True,
"initial": True,
"pctfree": True,
"uid": True,
"comment": True,
"insert": True,
"prior": True,
"union": True,
"compress": True,
"integer": True,
"privileges": True,
"unique": True,
"connect": True,
"intersect": True,
"public": True,
"update": True,
"create": True,
"into": True,
"raw": True,
"user": True,
"current": True,
"is": True,
"rename": True,
"validate": True,
"date": True,
"level": True,
"resource": True,
"values": True,
"decimal": True,
"like": True,
"revoke": True,
"varchar": True,
"default": True,
"lock": True,
"row": True,
"varchar2": True,
"delete": True,
"long": True,
"view": True,
"desc": True,
"maxextents": True,
"rowlabel": True,
"whenever": True,
"distinct": True,
"minus": True,
"rownum": True,
"where": True,
"drop": True,
"mode": True,
"rows": True,
"with": True,
);
const OracleRebuildIndexOptions = (
"parallel" : Type::Boolean,
"logging" : Type::Boolean,
"statictics" : Type::Boolean,
"tablespace" : Type::String,
"cond_rebuild" : Type::Boolean,
"cond_maxheight" : Type::Int,
"cond_maxleafpct" : Type::Int,
);
const OracleComputeStatisticsOptions = ComputeStatisticsOptions + (
"estimate_percent" : Type::Int,
"block_sample" : Type::Boolean,
"method_opt" : Type::String,
"degree" : Type::Int,
"granularity" : Type::String,
"cascade" : Type::Boolean,
"stattab" : Type::String,
"statid" : Type::String,
"options" : Type::String,
"statown" : Type::String,
);
public:
constructor(AbstractDatasource nds, *hash opts) ;
private list featuresImpl();
private OracleSequence makeSequenceImpl(string name, number start = 1, number increment = 1, *softnumber end, *hash opts);
private getSchemaName(reference name, reference schema);
private *AbstractSequence getSequenceImpl(string name);
private *AbstractView getViewImpl(string name);
private OracleFunction makeFunctionImpl(string name, string src, *hash opts);
private OracleProcedure makeProcedureImpl(string name, string src, *hash opts);
private OraclePackage makePackage(string name, string src, string body, *hash opts);
private OraclePackage makePackageFromDescription(string name, hash ph, *hash opts);
private OracleType makeType(string name, string src, *hash opts);
private OracleMaterializedView makeMaterializedView(string name, string src, bool logging = True, bool use_index = True, *string tablespace, *hash opts);
private OracleMaterializedView makeMaterializedViewFromDescription(string name, hash mvh, *hash opts);
private list getDropSchemaSqlImpl(hash schema_hash, *hash opt);
private list getAlignSqlImpl(hash schema_hash, *hash opt);
private *OracleFunction getFunctionImpl(string name);
private *OracleProcedure getProcedureImpl(string name);
*OraclePackage getPackage(string name);
*OracleType getType(string name);
*OracleMaterializedView getMaterializedView(string name);
private *string getSource(string type, string name);
private checkSource(string type, string name, reference src);
list listSynonyms();
ListIterator synonymIterator();
list listTypes();
ListIterator typeIterator();
list listPackages();
ListIterator packageIterator();
list listMaterializedViews();
ListIterator materializedViewIterator();
private list listTablesImpl();
private list listFunctionsImpl();
private list listProceduresImpl();
private list listSequencesImpl();
private list listViewsImpl();
private list getListIntern(string type);
private list getListIntern(list l);
private string getCreateSqlImpl(list l);
static string getCreateSql(list l);
private hash getCreationOptions();
private hash getAlignSchemaOptions();
private hash getSchemaDescriptionOptions();
private hash getRebuildIndexOptions();
private hash getComputeStatisticsOptions();
private softint getNextSequenceValueImpl(string name);
private softint getCurrentSequenceValueImpl(string name);
private bool supportsSequencesImpl();
private bool supportsTypesImpl();
private bool supportsPackagesImpl();
bool rebuildIndexAnalyze(AbstractIndex index, int maxh, int maxleaf);
bool rebuildIndexAnalyze(string name, int maxh, int maxleaf);
private bool rebuildIndexImpl(string name, *hash options);
private computeStatisticsImpl(*hash options);
private computeStatisticsSchemaImpl(*hash options);
private computeStatisticsTablesImpl(*hash options);
private reclaimSpaceImpl(*hash options);
};
class OracleTable : public SqlUtil::AbstractTable {
public:
public :
const OraTypeMap = (
"number": ("qore": Type::Number, "size": SZ_NUM, "size_range": (1, 38), "scale_range": (-84, 127)),
"varchar2": ("qore": Type::String, "size": SZ_MAND, "size_range": (1, 4000), "is_char": True),
"char": ("qore": Type::String, "size": SZ_MAND, "size_range": (1, 4000), "is_char": True),
"date": ("qore": Type::Date,),
"timestamp": ("qore": Type::Date, "size": SZ_OPT, "size_range": (0, 9)),
"timestamp with time zone": ("qore": Type::Date, "size": SZ_OPT, "size_range": (0, 9)),
"timestamp with local time zone": ("qore": Type::Date, "size": SZ_OPT, "size_range": (0, 9)),
"interval year to month": ("qore": Type::Date,),
"interval day to second": ("qore": Type::Date,),
"timestamp(0)": ("qore": Type::Date,),
"timestamp(1)": ("qore": Type::Date,),
"timestamp(2)": ("qore": Type::Date,),
"timestamp(3)": ("qore": Type::Date,),
"timestamp(4)": ("qore": Type::Date,),
"timestamp(5)": ("qore": Type::Date,),
"timestamp(6)": ("qore": Type::Date,),
"timestamp(7)": ("qore": Type::Date,),
"timestamp(8)": ("qore": Type::Date,),
"timestamp(9)": ("qore": Type::Date,),
"timestamp(0) with time zone": ("qore": Type::Date,),
"timestamp(1) with time zone": ("qore": Type::Date,),
"timestamp(2) with time zone": ("qore": Type::Date,),
"timestamp(3) with time zone": ("qore": Type::Date,),
"timestamp(4) with time zone": ("qore": Type::Date,),
"timestamp(5) with time zone": ("qore": Type::Date,),
"timestamp(6) with time zone": ("qore": Type::Date,),
"timestamp(7) with time zone": ("qore": Type::Date,),
"timestamp(8) with time zone": ("qore": Type::Date,),
"timestamp(9) with time zone": ("qore": Type::Date,),
"timestamp(0) with local time zone": ("qore": Type::Date,),
"timestamp(1) with local time zone": ("qore": Type::Date,),
"timestamp(2) with local time zone": ("qore": Type::Date,),
"timestamp(3) with local time zone": ("qore": Type::Date,),
"timestamp(4) with local time zone": ("qore": Type::Date,),
"timestamp(5) with local time zone": ("qore": Type::Date,),
"timestamp(6) with local time zone": ("qore": Type::Date,),
"timestamp(7) with local time zone": ("qore": Type::Date,),
"timestamp(8) with local time zone": ("qore": Type::Date,),
"timestamp(9) with local time zone": ("qore": Type::Date,),
"interval year(0) to month": ("qore": Type::Date,),
"interval year(1) to month": ("qore": Type::Date,),
"interval year(2) to month": ("qore": Type::Date,),
"interval year(3) to month": ("qore": Type::Date,),
"interval year(4) to month": ("qore": Type::Date,),
"interval year(5) to month": ("qore": Type::Date,),
"interval year(6) to month": ("qore": Type::Date,),
"interval year(7) to month": ("qore": Type::Date,),
"interval year(8) to month": ("qore": Type::Date,),
"interval year(9) to month": ("qore": Type::Date,),
"interval day(0) to second(0)": ("qore": Type::Date,),
"interval day(0) to second(1)": ("qore": Type::Date,),
"interval day(0) to second(2)": ("qore": Type::Date,),
"interval day(0) to second(3)": ("qore": Type::Date,),
"interval day(0) to second(4)": ("qore": Type::Date,),
"interval day(0) to second(5)": ("qore": Type::Date,),
"interval day(0) to second(6)": ("qore": Type::Date,),
"interval day(0) to second(7)": ("qore": Type::Date,),
"interval day(0) to second(8)": ("qore": Type::Date,),
"interval day(0) to second(9)": ("qore": Type::Date,),
"interval day(1) to second(0)": ("qore": Type::Date,),
"interval day(1) to second(1)": ("qore": Type::Date,),
"interval day(1) to second(2)": ("qore": Type::Date,),
"interval day(1) to second(3)": ("qore": Type::Date,),
"interval day(1) to second(4)": ("qore": Type::Date,),
"interval day(1) to second(5)": ("qore": Type::Date,),
"interval day(1) to second(6)": ("qore": Type::Date,),
"interval day(1) to second(7)": ("qore": Type::Date,),
"interval day(1) to second(8)": ("qore": Type::Date,),
"interval day(1) to second(9)": ("qore": Type::Date,),
"interval day(2) to second(0)": ("qore": Type::Date,),
"interval day(2) to second(1)": ("qore": Type::Date,),
"interval day(2) to second(2)": ("qore": Type::Date,),
"interval day(2) to second(3)": ("qore": Type::Date,),
"interval day(2) to second(4)": ("qore": Type::Date,),
"interval day(2) to second(5)": ("qore": Type::Date,),
"interval day(2) to second(6)": ("qore": Type::Date,),
"interval day(2) to second(7)": ("qore": Type::Date,),
"interval day(2) to second(8)": ("qore": Type::Date,),
"interval day(2) to second(9)": ("qore": Type::Date,),
"clob": ("qore": Type::String,),
"blob": ("qore": Type::Binary,),
"long": ("qore": Type::Binary,),
"raw": ("qore": Type::Binary, "size": SZ_MAND, "size_range": (1, 2000)),
"bfile": ("qore": Type::Binary,),
"binary_float": ("qore": Type::Float,),
"binary_double": ("qore": Type::Float,),
"rowid": ("qore": Type::String,),
"urowid": ("qore": Type::String, "size": SZ_OPT, "size_range": (1, 4000)),
);
const QoreTypeMap = (
"integer": "number",
"float": "number",
"number": "number",
"string": "varchar2",
"date": "timestamp(6)",
"binary": "blob",
SqlUtil::CHAR: "char",
SqlUtil::CLOB: "clob",
SqlUtil::BLOB: "blob",
);
const OraColumnOpts = (
"character_semantics": Type::Boolean,
);
const OraColumnOptions = AbstractTable::ColumnOptions + OraColumnOpts;
const OraColumnDescOptions = AbstractTable::ColumnDescOptions + OraColumnOpts;
const OracleIndexOptions = AbstractTable::IndexOptions + (
"compute_statistics": Type::Boolean,
);
const OracleConstraintOptions = OracleIndexOptions + (
"index": Type::String,
);
const OracleTableCreationOptions = AbstractTable::TableCreationOptions
+ OracleConstraintOptions
+ OraColumnOptions
;
const OracleAlignTableOptions = AbstractTable::AlignTableOptions + OracleTableCreationOptions;
const OracleSelectOptions = AbstractTable::SelectOptions + (
"partition": Type::String,
);
const OracleOpMap = DefaultOpMap + (
OP_IN: (
"code": string (object t, string cn, softlist arg, reference args, *hash jch, bool join = False, *hash ch, *hash psch) {
// Qorus bug #989 SqlUtil: oracle op_in can fail in large amount of input elements
// There is no support for CLOBs in WHERE clause in Oracle at all.
// Binding large strings (over 4000 chars is performed by a CLOB in Qore driver.
// Result of op_in operator can be "ORA-00932: inconsistent datatypes" if is
// the list longer or if it contains large items with:
// return cn + " in (select regexp_substr(%v,'[^,]+', 1, level) from dual connect by regexp_substr(%v, '[^,]+', 1, level) is not null)";
// determine list members type. Let's assume the 1st non NULL/NOTHING
// element gives the type code for all elements.
ListIterator it(arg);
int ltype;
while (it.next());
// Bind to oracle by expected type
switch (ltype);
return cn + " in (select column_value from table(%v))";
throw "MISSING-ORACLE-DRIVER", "op_in requires oracle driver";
},
),
OP_SUBSTR: (
"code": string (object t, string cn, any arg, reference args, *hash jch, bool join = False, *hash ch, *hash psch) {
args += arg[0]; // start
if (!exists arg[1]);
args += arg[1]; // count
args += arg[2]; // text
return sprintf("substr(%s,%v,%v) = %v", cn);
},
),
);
const OracleCopMap = DefaultCopMap + (
COP_CAST: (
"code": string (string cve, list args) {
string name = QoreTypeMap{args[0]} ?? args[0];
hash desc = OraTypeMap{name};
string sql = sprintf ("cast (%s as %s", cve, name);
switch (name);
sql += ")";
return sql;
},
),
COP_SUBSTR: (
"code": string (string cve, list args) {
if (!exists args[1])
return sprintf("substr(%s,%d)", cve, args[0]);
return sprintf("substr(%s,%d,%d)", cve, args[0], args[1]);
},
),
COP_OVER: (
"argcolumn": True,
"argoptional": True,
"code": string (*string cve, *string arg) {
string sql = cve + " over (";
if (arg)
sql += sprintf("partition by %s", arg);
sql += ")";
return sql;
},
),
COP_YEAR: (
"code": string (string arg1, any arg) {
return sprintf("to_char(%s, 'YYYY')", arg1);
}
),
COP_YEAR_MONTH: (
"code": string (string arg1, any arg) {
return sprintf("to_char(%s, 'YYYY-MM')", arg1);
}
),
COP_YEAR_DAY: (
"code": string (string arg1, any arg) {
return sprintf("to_char(%s, 'YYYY-MM-DD')", arg1);
}
),
COP_YEAR_HOUR: (
"code": string (string arg1, any arg) {
return sprintf("to_char(%s, 'YYYY-MM-DD HH24')", arg1);
}
),
COP_SEQ: (
"nocolumn": True,
"withalias": True,
"code": string (*string cve, hash arg, reference psch) {
string sql = sprintf("%s.nextval", arg.seq);
if (arg.as);
return sql;
}
),
COP_SEQ_CURRVAL: (
"nocolumn": True,
"withalias": True,
"code": string (*string cve, hash arg, reference psch) {
string sql = sprintf("%s.currval", arg.seq);
if (arg.as);
return sql;
}
),
);
const OracleIopMap = DefaultIopMap + (
IOP_SEQ: (
"arg": Type::String,
"immediate": True,
"code": string (string cve, string arg) {
return sprintf("%s.nextval", arg);
},
),
IOP_SEQ_CURRVAL: (
"arg": Type::String,
"immediate": True,
"code": string (string cve, string arg) {
return sprintf("%s.currval", arg);
},
),
);
const OracleUopMap = DefaultUopMap + (
COP_SEQ: (
"nocolumn": True,
"code": string (*string cve, string arg) {
return sprintf("%s.nextval", arg);
}
),
COP_SEQ_CURRVAL: (
"nocolumn": True,
"code": string (*string cve, string arg) {
return sprintf("%s.currval", arg);
}
),
);
const OraclePseudoColumnHash = (
"rowid": True,
"rownum": True,
"object_id": True,
"object_value": True,
"ora_rowscn": True,
);
public:
private :
// schema name
string schema;
// tablespace name
*string tablespace;
// is the table read only?
bool readonly;
// table comment
*string comment;
// dblink
*string dblink;
// Oracle server major version
int ora_major;
// helper flag to indicate if is the OracleTable real table or a view
bool m_isView = False;
public:
constructor(AbstractDatasource nds, string nname, *hash opts) ;
private bool checkExistenceImpl();
private setTableInfoIntern();
string getSqlName();
bool isView();
private hash setSchemaTable();
private setDblinkSchema();
private hash setTable();
private string getUserSchema();
private string getDBString();
string getSchemaName();
*string getTablespaceName();
*string getComment();
bool readOnly();
private hash getColumnOptions();
private hash getColumnDescOptions();
private hash getSelectOptions();
private getSelectWhereSqlUnlocked(reference sql, reference args, *hash qh, *hash jch, bool join = False, *hash ch, *hash psch);
private doSelectOrderByWithOffsetSqlUnlockedImpl(reference sql, reference args, *hash qh, *hash jch, *hash ch, *hash psch, list coll);
private doSelectLimitOnlyUnlockedImpl(reference sql, reference args, *hash qh);
private Columns describeImpl();
private OraclePrimaryKey getPrimaryKeyImpl();
private Indexes getIndexesImpl();
private ForeignConstraints getForeignConstraintsImpl(*hash opts);
private Constraints getConstraintsImpl();
private string getSelectSqlName(*hash qh);
private Triggers getTriggersImpl();
string getCreateTableSqlImpl(*hash opt);
private *list getCreateMiscSqlImpl(*hash opt, bool cache);
private string getCreateSqlImpl(list l);
private string getRenameSqlImpl(string new_name);
private AbstractColumn addColumnImpl(string cname, hash opt, bool nullable = True);
private AbstractPrimaryKey addPrimaryKeyImpl(string cname, hash ch, *hash opt);
private AbstractIndex addIndexImpl(string iname, bool enabled, hash ch, *hash opt);
private AbstractForeignConstraint addForeignConstraintImpl(string cname, hash ch, string table, hash tch, *hash opt);
private AbstractCheckConstraint addCheckConstraintImpl(string cname, string src, *hash opt);
private AbstractUniqueConstraint addUniqueConstraintImpl(string cname, hash ch, *hash opt);
private AbstractTrigger addTriggerImpl(string tname, string src, *hash opt);
private bool tryInsertImpl(string sql, hash row);
private *list getAlignSqlImpl(AbstractTable t, *hash opt);
private hash getQoreTypeMapImpl();
private hash getTypeMapImpl();
private hash getIndexOptions();
private hash getConstraintOptions();
private hash getTableCreationOptions();
private hash getAlignTableOptions();
private hash getWhereOperatorMap();
private hash getColumnOperatorMap();
private hash getInsertOperatorMap();
private hash getRawUpdateOperatorMap();
private *hash getPseudoColumnHash();
private *string getSqlValueImpl(any v);
string getColumnSqlName(string col);
list getColumnSqlNames(softlist cols);
string getBaseType();
code getBulkUpsertClosure(hash example_row, int upsert_strategy = AbstractTable::UpsertAuto, *hash opt);
code getUpsertClosure(hash row, int upsert_strategy = UpsertAuto, *hash opt);
private code getUpsertInsertOnly(Columns cols, hash row, *hash opt);
private code getUpsertUpdateOnly(Columns cols, hash row, *hash opt);
bool hasArrayBind();
bool bindEmptyStringsAsNull();
private bool asteriskRequiresPrefix();
private *hash doReturningImpl(hash opt, reference sql, list args);
private bool emptyImpl();
private setupTableImpl(hash desc, *hash opt);
private bool constraintsLinkedToIndexesImpl();
private bool uniqueIndexCreatesConstraintImpl();
private bool supportsTablespacesImpl();
private copyImpl(AbstractTable old);
};
};
OracleSqlUtil::OracleUniqueConstraint
represents an Oracle unique constraint
Definition: OracleSqlUtil.qm.dox.h:494
Date
const Date
OracleSqlUtil::OracleMaterializedView
represents an Oracle materialized view
Definition: OracleSqlUtil.qm.dox.h:800
date
date date(date dt)
COP_SEQ
const COP_SEQ
Hash
const Hash
OracleSqlUtil
the OracleSqlUtil namespace contains all the objects in the OracleSqlUtil module
Definition: OracleSqlUtil.qm.dox.h:324
UpsertAuto
const UpsertAuto
String
const String
DefaultIopMap
const DefaultIopMap
sprintf
string sprintf(string fmt,...)
OP_IN
const OP_IN
SqlUtil::AbstractTable
DefaultCopMap
const DefaultCopMap
SqlUtil::VARCHAR
const VARCHAR
OracleSqlUtil::OracleIndex::tablespace
*string tablespace
the tablespace name of the index (if supported)
Definition: OracleSqlUtil.qm.dox.h:416
OracleSqlUtil::OracleMaterializedView::logging
bool logging
Flag if is loggign mode used.
Definition: OracleSqlUtil.qm.dox.h:805
OracleSqlUtil::OracleView::view_type_owner
*string view_type_owner
Owner of the type of the view if the view is a typed view.
Definition: OracleSqlUtil.qm.dox.h:648
OracleSqlUtil::OracleTable
represents an Oracle table
Definition: OracleSqlUtil.qm.dox.h:1251
SqlUtil::AbstractIndex
OracleSqlUtil::OracleMaterializedView::tablespace
*string tablespace
Name of the potential tablespace.
Definition: OracleSqlUtil.qm.dox.h:809
COP_OVER
const COP_OVER
OracleSqlUtil::OracleView::superview_name
*string superview_name
Name of the superview.
Definition: OracleSqlUtil.qm.dox.h:652
OracleSqlUtil::OracleTrigger::enabled
bool enabled
True if the trigger is enabled, False if not
Definition: OracleSqlUtil.qm.dox.h:681
COP_SEQ_CURRVAL
const COP_SEQ_CURRVAL
SqlUtil::NumericColumnInfo
True
const True
SZ_MAND
const SZ_MAND
SqlUtil::CHAR
const CHAR
SqlUtil::AbstractSequence
OracleSqlUtil::OracleForeignConstraint::enabled
bool enabled
True if the constraint is enabled, False if not
Definition: OracleSqlUtil.qm.dox.h:443
OracleSqlUtil::OracleCheckConstraint::enabled
bool enabled
True if the constraint is enabled, False if not
Definition: OracleSqlUtil.qm.dox.h:471
OracleSqlUtil::OracleProcedure
represents an Oracle procedure
Definition: OracleSqlUtil.qm.dox.h:761
number
number number(softnumber n)
uop_substr
hash uop_substr(int start, *int count, *hash nest)
COP_YEAR_HOUR
const COP_YEAR_HOUR
binary
binary binary()
IOP_SEQ_CURRVAL
const IOP_SEQ_CURRVAL
SqlUtil::AbstractForeignConstraint
False
const False
OracleSqlUtil::OracleUniqueConstraint::tablespace
*string tablespace
any tablespace for the unique key index
Definition: OracleSqlUtil.qm.dox.h:502
OracleSqlUtil::OracleUniqueConstraint::enabled
bool enabled
True if the constraint is enabled, False if not
Definition: OracleSqlUtil.qm.dox.h:499
OracleSqlUtil::OracleView
represents an Oracle view
Definition: OracleSqlUtil.qm.dox.h:639
SqlUtil::AbstractCheckConstraint
list
list list(...)
Float
const Float
SqlUtil
op_substr
hash op_substr(int start, *int count, string text)
index
int index(softstring str, softstring substr, softint pos=0)
SqlUtil::cop_cast
hash cop_cast(any column, string arg, *any arg1, *any arg2)
Boolean
const Boolean
cop_substr
hash cop_substr(any column, int start, *int count)
SZ_NUM
const SZ_NUM
microseconds
date microseconds(softint us)
Binary
const Binary
OracleSqlUtil::OracleView::oid_text
*string oid_text
WITH OID clause of the typed view.
Definition: OracleSqlUtil.qm.dox.h:646
exists
bool exists(...)
OracleSqlUtil::OracleMaterializedView::use_index
bool use_index
Flag if is index used.
Definition: OracleSqlUtil.qm.dox.h:807
COP_YEAR_MONTH
const COP_YEAR_MONTH
SqlUtil::BLOB
const BLOB
OracleSqlUtil::OracleDatabase
the Oracle specialization for SqlUtil::AbstractDatabase
Definition: OracleSqlUtil.qm.dox.h:832
type
string type(any arg)
OracleSqlUtil::OracleColumn::byte_size
int byte_size
byte size of the column
Definition: OracleSqlUtil.qm.dox.h:341
SqlUtil::CLOB
const CLOB
NOTHING
const NOTHING
Util::same
bool same(list l)
SqlUtil::AbstractFunction
SqlUtil::AbstractView
OracleSqlUtil::OracleCheckConstraint
represents an Oracle check constraint
Definition: OracleSqlUtil.qm.dox.h:466
OracleSqlUtil::OracleNumberColumn
represents an Oracle number column
Definition: OracleSqlUtil.qm.dox.h:397
OracleSqlUtil::OraclePackage
represents an Oracle package
Definition: OracleSqlUtil.qm.dox.h:773
Int
const Int
COP_YEAR
const COP_YEAR
string
string string(softstring str, *string enc)
OracleSqlUtil::OracleColumn
represents an Oracle column
Definition: OracleSqlUtil.qm.dox.h:334
OracleSqlUtil::OracleView::type_text
*string type_text
Type clause of the typed view.
Definition: OracleSqlUtil.qm.dox.h:644
OracleSqlUtil::get_database
OracleDatabase get_database(AbstractDatasource nds, *hash opts)
returns an OracleDatabase object corresponding to the arguments
SqlUtil::AbstractTrigger
SqlUtil::AbstractColumn
COP_CAST
const COP_CAST
join_inner
hash join_inner(AbstractTable table, *string alias, *hash jcols, *hash cond, *hash opt)
OracleSqlUtil::OraclePackage::body_src
*string body_src
package body source
Definition: OracleSqlUtil.qm.dox.h:778
DefaultUopMap
const DefaultUopMap
cop_seq
hash cop_seq(string seq, *string as)
COP_YEAR_DAY
const COP_YEAR_DAY
OracleSqlUtil::OracleTable::getBaseType
string getBaseType()
returns the base type of the underlying object (either "table" or "view")
OracleSqlUtil::OraclePrimaryKey::tablespace
*string tablespace
any tablespace for the primary key index
Definition: OracleSqlUtil.qm.dox.h:564
OracleSqlUtil::OracleView::view_type
*string view_type
Type of the view if the view is a typed view.
Definition: OracleSqlUtil.qm.dox.h:650
SqlUtil::AbstractTable::ColumnDescOptions
const ColumnDescOptions
Qore
Object
const Object
OracleSqlUtil::OracleSequence
represents an Oracle sequence
Definition: OracleSqlUtil.qm.dox.h:622
OracleSqlUtil::OracleTrigger
represents an Oracle trigger
Definition: OracleSqlUtil.qm.dox.h:676
OracleSqlUtil::get_table
OracleTable get_table(AbstractDatasource nds, string nname, *hash opts)
returns an OracleTable object corresponding to the arguments
hash
hash hash(object obj)
OracleSqlUtil::OracleView::container_data
bool container_data
Indicates whether the view contains container-specific data.
Definition: OracleSqlUtil.qm.dox.h:654
COP_SUBSTR
const COP_SUBSTR
OracleSqlUtil::OracleDatabase::OracleSchemaDescriptionOptions
const OracleSchemaDescriptionOptions
oracle-specific schema description keys
Definition: OracleSqlUtil.qm.dox.h:856
OP_SUBSTR
const OP_SUBSTR
SZ_OPT
const SZ_OPT
IOP_SEQ
const IOP_SEQ
OracleSqlUtil::OracleForeignConstraint
represents an Oracle foreign constraint
Definition: OracleSqlUtil.qm.dox.h:438
SqlUtil::AbstractDatabase
cop_seq_currval
hash cop_seq_currval(string seq, *string as)
OracleSqlUtil::OracleType
represents an Oracle type
Definition: OracleSqlUtil.qm.dox.h:730
OracleSqlUtil::OraclePrimaryKey
represents an Oracle primary key
Definition: OracleSqlUtil.qm.dox.h:559
SqlUtil::AbstractPrimaryKey
OracleSqlUtil::OracleIndex::native_type
string native_type
the native type of the index (if supported)
Definition: OracleSqlUtil.qm.dox.h:413
join
string join(string str,...)
SqlUtil::NUMERIC
const NUMERIC
Number
const Number
OracleSqlUtil::OracleIndex
represents an Oracle index
Definition: OracleSqlUtil.qm.dox.h:408
DefaultOpMap
const DefaultOpMap
SqlUtil::AbstractUniqueConstraint
OracleSqlUtil::OracleColumn::char_used
bool char_used
the column uses character semantics
Definition: OracleSqlUtil.qm.dox.h:339
OracleSqlUtil::OracleFunction
represents an Oracle function
Definition: OracleSqlUtil.qm.dox.h:749
OracleSqlUtil::OracleCodeBase
the base class for Oracle code objects
Definition: OracleSqlUtil.qm.dox.h:705