Skip to main content

Oracle catalog

The Oracle catalog connects Gravitino to an Oracle database over JDBC, exposing Oracle users as schemas and Oracle tables as tables. It is a read-write catalog for tables and a read-only catalog for schemas, because Oracle schemas are database users and Gravitino does not create or drop them.

Oracle folds an unquoted identifier to uppercase and preserves the case of a quoted one. Gravitino reproduces that rule rather than hiding it, so the naming section below matters more here than it does for most catalogs.

Quick Start

1. Confirm the driver is present. The Oracle JDBC driver ships inside the connector at catalogs/jdbc-oracle/libs, so there is no separate download step. This differs from the MySQL and PostgreSQL catalogs, which require you to supply a driver yourself.

2. Create the catalog. Declare the connection to the Oracle instance and the account Gravitino uses to reach it.

GRAVITINO_URL=http://localhost:8090
METALAKE=metalake_demo

curl -X POST -H "Content-Type: application/json" \
-d '{
"name": "oracle_catalog",
"type": "RELATIONAL",
"provider": "jdbc-oracle",
"comment": "Oracle catalog",
"properties": {
"jdbc-url": "jdbc:oracle:thin:@{oracle_host}:1521:{oracle_sid}",
"jdbc-user": "{oracle_user}",
"jdbc-password": "{oracle_password}",
"jdbc-driver": "oracle.jdbc.OracleDriver"
}
}' \
"${GRAVITINO_URL}/api/metalakes/${METALAKE}/catalogs"

3. List the schemas. Gravitino returns the Oracle users visible to the connecting account, filtered as described in Schemas below.

Catalog Properties

The Oracle catalog defines no properties of its own beyond the JDBC properties every JDBC catalog shares. Four of those are required.

PropertyDescriptionExample
jdbc-urlThe Oracle JDBC connection stringjdbc:oracle:thin:@localhost:1521:ORCL
jdbc-userThe Oracle account Gravitino connects asgravitino
jdbc-passwordThe password for that accountgravitino
jdbc-driverThe driver class nameoracle.jdbc.OracleDriver

Gravitino issues ALTER SESSION SET CURRENT_SCHEMA on each connection before working with a table, so the connecting account needs privileges on every schema you intend to reach through the catalog, not only on its own.

Schemas

A schema in this catalog is an Oracle user. Gravitino lists and loads them but does not create, alter, or drop them, since managing Oracle accounts is a database administration task rather than a metadata one. Attempting to create or drop a schema raises an unsupported operation error. Schema comments are also unavailable, because Oracle has no COMMENT ON SCHEMA syntax.

Listing filters out Oracle's own accounts. On Oracle 12c and later Gravitino uses the ORACLE_MAINTAINED column of ALL_USERS, which covers accounts installed by optional components. On Oracle 11g that column does not exist, so a built-in list of known system users is used instead, and that list still applies on newer releases as a fallback for accounts that are not marked consistently.

Tables

Table create, load, list, rename, alter, drop, and purge are all supported. A drop is always issued as DROP TABLE ... PURGE, so the table does not land in Oracle's recycle bin and cannot be recovered with FLASHBACK TABLE.

Oracle does not support transactional DDL. An alter that carries several changes is executed as one statement per change in sequence, so a failure partway through leaves the earlier statements committed. The failing statement and the statements that already ran are both written to the server log.

Table Properties

Four properties come back from Oracle's ALL_TABLES view. Only tablespace can be supplied, and only at create time.

PropertySourceSettable
tablespaceALL_TABLES.TABLESPACE_NAMEAt table creation only
partitionedALL_TABLES.PARTITIONEDNo, derived by Oracle
row_movementALL_TABLES.ROW_MOVEMENTNo, derived by Oracle
compressionALL_TABLES.COMPRESSIONNo, derived by Oracle

Table property changes are not supported at all, so a tablespace chosen at creation cannot be changed afterward through Gravitino.

Table and column comments are supported. Oracle's JDBC driver does not populate REMARKS in DatabaseMetaData.getColumns(), so Gravitino reads column comments from ALL_COL_COMMENTS directly.

Indexes

Primary key and unique key are the only index types this catalog supports, both at create time and through an alter. They are read back from ALL_CONSTRAINTS and ALL_CONS_COLUMNS, which means only constraint-backed indexes appear, not standalone Oracle indexes.

Index names are case-sensitive and are never folded, so a name must be given exactly as it was created for a delete to match it.

Partitioning

Oracle tables can be created with single-level range, list, or hash partitioning. Range partitioning takes a single column, and composite partitioning is not supported in either direction: a table already partitioned on more than one range column cannot be loaded.

Gravitino transformOracle clauseRestriction
RangePARTITION BY RANGEOne column, at least one partition
ListPARTITION BY LISTSingle level
BucketPARTITION BY HASHSingle level

Range partition bounds are read back by evaluating Oracle's stored HIGH_VALUE expression, so a bound that Oracle cannot evaluate to a literal of a supported type causes the load to fail rather than returning a partial result.

Table distribution and sort orders are not supported.

Supported Table Changes

ChangeSupported
Rename tableYes
Update table commentYes
Add columnYes, at the default position only
Delete columnYes
Rename columnYes
Update column typeYes
Update column nullableYes
Update column defaultYes
Update column commentYes
Add or delete indexYes, for primary key and unique key
Update column positionNo, Oracle cannot reorder columns
Auto incrementNo, at create time or through an alter
Set or remove propertyNo

Nested column names are not supported by any of the column changes.

Identifier Case and Quoting

Gravitino follows Oracle's own rule rather than treating the catalog as uniformly case-sensitive or case-insensitive. An unquoted name is folded to uppercase. A name written with literal double quotes keeps its exact case, and the quotes are consumed as a signal rather than stored.

Name as givenPhysical Oracle objectValidation
app_userAPP_USERMust match ^[A-Za-z][A-Za-z0-9_$#]{0,29}$
"MyTable"MyTableContent is 1 to 30 bytes and excludes . and NUL

Two consequences are worth stating plainly. The quoting signal is not persisted, so a later reference to a case-sensitive object has to supply the quoted form again to resolve to the same physical name. And the 30-byte limit is measured in bytes of the database character set, not characters, so a multi-byte name reaches the limit sooner than its length suggests.

Oracle has no escape for a double quote inside a quoted identifier, so an embedded " is rejected rather than doubled.

Names returned by a list operation come back exactly as Oracle stores them, with no quoting added.

Type Mapping

Oracle to Gravitino

Oracle typeGravitino type
NUMBER with no precision or scaleExternal type NUMBER
NUMBER(1)Boolean
NUMBER(p) where p is 2 to 3Byte
NUMBER(p) where p is 4 to 5Short
NUMBER(p) where p is 6 to 10Integer
NUMBER(p) where p is 11 to 19Long
NUMBER(p) where p is 20 or moreDecimal(p, 0)
NUMBER(p,s) with positive sDecimal(p, s)
NUMBER(p,s) with negative sExternal type NUMBER(p,s)
VARCHAR2(n), VARCHAR(n)Varchar(n)
CHAR(n)Char(n)
NCHAR, NVARCHAR2External type
CLOB, NCLOBString
BLOB, RAW, LONG RAWBinary
FLOAT, BINARY_DOUBLEDouble
BINARY_FLOATFloat
DATETimestamp without time zone
TIMESTAMP(p)Timestamp without time zone, precision p
TIMESTAMP(p) WITH TIME ZONETimestamp with time zone, precision p
Any other typeExternal type carrying the Oracle name

TIMESTAMP WITH LOCAL TIME ZONE is rejected rather than mapped. Gravitino's timestamp type cannot distinguish it from TIMESTAMP WITH TIME ZONE, so accepting it would silently change the semantics of the column on a round trip.

A precision omitted by the driver is treated as Oracle's maximum of 38.

Gravitino to Oracle

Gravitino typeOracle type
BooleanNUMBER(1)
ByteNUMBER(3)
ShortNUMBER(5)
IntegerNUMBER(10)
LongNUMBER(19)
Decimal(p, s)NUMBER(p,s)
FloatBINARY_FLOAT
DoubleBINARY_DOUBLE
StringCLOB
Varchar(n)VARCHAR2(n)
Char(n)CHAR(n)
BinaryBLOB
Timestamp without time zoneTIMESTAMP(p), TIMESTAMP(6) when no precision is set
Timestamp with time zoneTIMESTAMP(p) WITH TIME ZONE, TIMESTAMP(6) WITH TIME ZONE when no precision is set
External typeThe Oracle type name it carries

Date has no mapping. Oracle's DATE carries a time component and reads back as a timestamp, so creating a column as Gravitino's date type is rejected. Use an external type of DATE when you need the Oracle type by name.

Two mappings are deliberately asymmetric and worth knowing before you round-trip a table. String becomes CLOB on the way out while VARCHAR2 with no precision becomes String on the way back, and FLOAT becomes Double while Double becomes BINARY_DOUBLE.

Column Default Values

Literal defaults are carried through in both directions. Five Oracle functions are recognized as function expressions rather than being treated as literal text: SYSDATE, SYSTIMESTAMP, CURRENT_TIMESTAMP, CURRENT_DATE, and SYS_GUID. Any other expression is preserved as an unparsed expression.

Oracle requires DEFAULT to precede NOT NULL in a column definition, and Gravitino generates the clauses in that order.

Error Mapping

Oracle error codes are translated into Gravitino exceptions so that a caller sees the same failure types it would from any other catalog.

Oracle errorGravitino exception
ORA-01918, ORA-01435 user does not existNo such schema
ORA-01920 user name conflicts with an existing nameSchema already exists
ORA-00942 table or view does not existNo such table
ORA-00955 name is already used by an existing objectTable already exists
ORA-01031 insufficient privilegesRuntime error naming the cause

Any other error code produces a generic runtime exception carrying the Oracle message, and the unrecognized code is written to the server log.