adbc-driver-oracle
An Apache Arrow ADBC driver for Oracle Database — pure Go, no Oracle Client libraries required.
Speaks Oracle's native TNS/TTC wire protocol directly from Go and returns
Apache Arrow RecordBatches straight from the result set — the way
python-oracledb's "thin mode" does, but for the whole ADBC ecosystem.
No Instant Client, no ORACLE_HOME, no LD_LIBRARY_PATH. Just
pip install. Supports the standard ADBC bulk-ingest path
(Statement.BindStream → array-bind INSERT) for fast Arrow → Oracle loads.
Distributed as:
- a Go module —
github.com/gizmodata/adbc-driver-oracle - a
pip install adbc-driver-oraclewheel for Python (macOS / Linux / Windows × x64 / arm64) - a c-shared library (
libadbc_driver_oracle.{so,dylib,dll}) attached to each GitHub Release for C / C++ / Rust / R / driver-manifest consumers
Status: Alpha. Tested against Oracle Database 23ai Free; the wire protocol targets Oracle 12.1 and later (the same range as python-oracledb thin mode). See Limitations for what is not covered yet.
Quickstart
1. Have an Oracle Database handy
For local development the gvenzl/oracle-free container is the fastest route (x86_64 and arm64):
docker run --name oracle-adbc-test -d -p 1521:1521 \
-e ORACLE_PASSWORD=tiger -e APP_USER=scott -e APP_USER_PASSWORD=tiger \
gvenzl/oracle-free:23-slim-faststart
That gives you oracle://scott:tiger@localhost:1521/FREEPDB1.
2. Install the driver
Python:
pip install adbc-driver-oracle
Go:
go get github.com/gizmodata/adbc-driver-oracle@latest
3. Connect and query
import adbc_driver_oracle.dbapi as oracle
import pyarrow
with oracle.connect(
uri="oracle://scott:tiger@localhost:1521/FREEPDB1",
) as conn, conn.cursor() as cur:
cur.execute("SELECT 42 AS answer, 'hello oracle' AS greeting FROM DUAL")
table: pyarrow.Table = cur.fetch_arrow_table()
print(table)
The result is a real pyarrow.Table — pass it straight to Polars, Pandas,
DuckDB, ibis, or anything else that consumes Arrow:
import polars as pl
df = pl.from_arrow(table)
Prefer to keep credentials out of the URI? Pass them as options:
with oracle.connect(
uri="oracle://localhost:1521/FREEPDB1",
db_kwargs={"username": "scott", "password": "tiger"},
) as conn:
...
Alternative: drive adbc_driver_manager directly
If you prefer the generic ADBC driver manager
idiom — passing the driver to adbc_driver_manager.dbapi.connect rather
than going through our wrapper — point at the bundled shared library via
_driver_path():
from adbc_driver_manager import dbapi
import adbc_driver_oracle
with dbapi.connect(
driver=adbc_driver_oracle._driver_path(),
entrypoint="OracleDriverInit",
db_kwargs={"uri": "oracle://scott:tiger@localhost:1521/FREEPDB1"},
) as conn, conn.cursor() as cur:
cur.execute("SELECT 42 AS answer FROM DUAL")
table = cur.fetch_arrow_table()
Streaming large result sets
Cursor.fetch_record_batch() returns a pyarrow.RecordBatchReader that
pulls rows from the server one batch at a time. Memory stays bounded by
adbc.oracle.batch_size even when the result is millions of rows:
with conn.cursor() as cur:
cur.execute("SELECT * FROM sales.orders") # arbitrary size
reader = cur.fetch_record_batch()
for batch in reader:
process(batch)
Oracle → GizmoSQL (or any ADBC target), ADBC to ADBC
The reader above can be handed straight to another driver's bulk ingest, so a table moves from Oracle into GizmoSQL without ever being materialised on the client — no pandas, no ODBC, no Oracle Client:
import adbc_driver_oracle.dbapi as oracle
import adbc_driver_gizmosql.dbapi as gizmosql
with oracle.connect(uri=oracle_uri) as src, \
gizmosql.connect(gizmosql_uri, username="token", password=token) as dst:
with src.cursor() as s, dst.cursor() as d:
s.execute("SELECT * FROM sales.orders")
rows = d.adbc_ingest(table_name="orders", data=s.fetch_record_batch(), mode="replace")
dst.commit()
print(f"Loaded {rows:,} rows")
(python/tests/test_oracle_to_gizmosql.py runs exactly this against a
live Oracle + GizmoSQL pair in CI; GizmoSQL is a test-only dependency —
the driver itself has no GizmoSQL code.)
DuckDB / GizmoSQL ↔ Oracle via adbc_scanner
Because the driver is a plain ADBC c-shared library, DuckDB — and
therefore GizmoSQL, which embeds DuckDB — can talk to Oracle live
through the adbc_scanner
community extension, in both directions:
INSTALL adbc_scanner FROM community;
LOAD adbc_scanner;
-- credentials once, in a DuckDB secret
CREATE SECRET ora_secret (
TYPE adbc,
SCOPE 'oracle://db.example.com:1521/PROD',
driver 'oracle', -- by name after `python -m adbc_driver_oracle install-manifest`,
-- or a path: '/path/to/libadbc_driver_oracle.so'
uri 'oracle://db.example.com:1521/PROD',
username 'app',
password 's3cret'
);
-- pull: Oracle as an attached catalog (projection + filter pushdown)
ATTACH 'oracle://db.example.com:1521/PROD' AS ora (TYPE adbc);
SELECT * FROM ora.SALES.ORDERS WHERE AMT > 100;
SELECT o.ORDER_ID, c.name FROM ora.SALES.ORDERS o JOIN customers c ON c.id = o.CUST_ID;
-- arbitrary Oracle SQL, and push in the other direction, via the same secret
SET VARIABLE ora = adbc_connect({'secret': 'ora_secret'});
SELECT * FROM adbc_scan(getvariable('ora')::BIGINT, 'SELECT * FROM sales.orders WHERE ROWNUM <= 10');
SELECT * FROM adbc_insert(getvariable('ora')::BIGINT, 'ORDERS_COPY', (SELECT * FROM local_orders), mode := 'create');
python/tests/test_adbc_scanner.py covers both directions.
DuckDB via connection profiles (the adbc community extension)
DuckDB's adbc community extension (INSTALL adbc FROM community; see the
GizmoSQL guide)
resolves databases through ADBC connection profiles — no credentials in
your SQL — and additionally supports writes (INSERT, COPY,
CREATE TABLE AS) into the attached database through ADBC bulk ingest:
python -m adbc_driver_oracle install-manifest # registers driver "oracle"
cat > ~/.config/adbc/profiles/prod.toml <<EOF # macOS: ~/Library/Application Support/ADBC/Profiles/
profile_version = 1
driver = "oracle"
[Options]
uri = "oracle://db.example.com:1521/PROD"
username = "app"
password = "s3cret"
EOF
INSTALL adbc FROM community;
LOAD adbc;
SELECT * FROM read_adbc('profile://prod', 'SELECT * FROM sales.orders WHERE ROWNUM <= 10');
ATTACH 'profile://prod' AS ora (TYPE adbc);
USE ora.SALES;
SELECT COUNT(*) FROM ORDERS;
CREATE TABLE ORDERS_2024 AS SELECT * FROM memory.staged_orders; -- bulk ingest into Oracle
python/tests/test_duckdb_adbc_client.py covers read_adbc, ATTACH,
and CTAS/INSERT. (The adbc_scanner extension above is the one to use
when you want predicate/projection pushdown on attached tables.)
Bulk ingest (Arrow → Oracle)
import pyarrow as pa
import adbc_driver_oracle.dbapi as oracle
table = pa.table({"id": [1, 2, 3], "name": ["alice", "bob", "carol"]})
with oracle.connect(
uri="oracle://scott:tiger@localhost:1521/FREEPDB1",
autocommit=True, # ADBC connections are autocommit-OFF by default;
# opt in here so the ingest persists on close
) as conn, conn.cursor() as cur:
# create_append: create CUSTOMERS from the Arrow schema if it
# doesn't exist, then append via array-bind INSERT.
cur.adbc_ingest(table_name="customers", data=table, mode="create_append")
Heads-up — autocommit is off by default. Per the Python DB-API,
oracle.connect()opens connections inside a transaction. Without theautocommit=Trueabove (or an explicitconn.commit()), the append is rolled back when the connection closes. (Oracle DDL — theCREATE TABLEin the create-family modes — always commits implicitly.)
mode accepts the four standard ADBC ingest modes:
| mode | behavior |
|---|---|
create |
create the table (errors if it already exists), then append — this is the default when mode is omitted |
append |
append to an existing table (no DDL; errors if missing) |
replace |
drop the table if it exists, recreate it, then append |
create_append |
create the table if it doesn't exist, then append |
Table DDL for the create-family modes is generated from the Arrow schema
(see Type mapping); simple column names are upper-cased
like unquoted Oracle identifiers, anything else is quoted verbatim. Pass
db_schema_name=... to target another schema. Rows are sent as
array-bound INSERTs, 5000 per round trip. Statement options
(cur.adbc_statement.set_options(...) / stmt.SetOption in Go):
| Statement option | Default | Notes |
|---|---|---|
adbc.oracle.ingest.batch_rows |
5000 |
Rows per array-bind INSERT round trip. |
adbc.oracle.ingest.varchar_length |
4000 |
VARCHAR2(n) length for Arrow string columns in generated DDL. |
adbc.oracle.ingest.string_type |
VARCHAR2 |
VARCHAR2, NVARCHAR2, CLOB or NCLOB for string columns. |
adbc.oracle.ingest.raw_length |
2000 |
RAW(n) length for Arrow binary columns. |
adbc.oracle.ingest.binary_type |
RAW |
RAW or BLOB for binary columns. |
adbc.oracle.ingest.struct_type |
JSON |
JSON (21c+), CLOB, VARCHAR2 or BLOB for list / struct / map columns (stored as JSON text). |
adbc.oracle.ingest.tablespace |
(default) | TABLESPACE clause for tables created by ingest. |
Values larger than the server's maximum VARCHAR2/RAW size are bound
as LONG / LONG RAW, so strings and blobs of any size load into
CLOB / BLOB columns.
Transactions (autocommit off)
import adbc_driver_oracle.dbapi as oracle
with oracle.connect(
uri="oracle://scott:tiger@localhost:1521/FREEPDB1",
autocommit=False,
) as conn, conn.cursor() as cur:
cur.execute("INSERT INTO orders VALUES (1, 'pending')")
cur.execute("INSERT INTO order_items VALUES (1, 'widget', 2)")
conn.commit() # both inserts persist atomically
PL/SQL: OUT / IN OUT binds and implicit result sets
A PL/SQL block's OUT / IN OUT binds come back as a one-row result
set (the Arrow C Data Interface can't mutate bound input); each field carries
ORACLE:parameter_type = OUT / IN OUT metadata. Bind a typed
placeholder to choose the return type — an untyped None returns text:
cur.execute(
"BEGIN :doubled := :n * 2; :greeting := 'hello ' || :greeting; END;",
pa.record_batch([pa.array([None], pa.int64()), pa.array([21], pa.int64()), pa.array(["world"])],
names=["doubled", "n", "greeting"]),
)
cur.fetch_arrow_table().to_pylist() # [{'DOUBLED': 42, 'GREETING': 'hello world'}]
Cursors returned with DBMS_SQL.RETURN_RESULT stream back exactly like
a query (the first cursor; further ones are closed):
cur.execute("""DECLARE c SYS_REFCURSOR; BEGIN
OPEN c FOR SELECT * FROM emp; DBMS_SQL.RETURN_RESULT(c); END;""")
table = cur.fetch_arrow_table()
Object types, collections, XMLType and SDO_GEOMETRY
User-defined object types, VARRAYs and nested tables come back as JSON
text — attributes keyed by name, collections as arrays, LOB attributes
inlined, dates as ISO-8601 — so any Arrow consumer can read them without
Oracle-specific type knowledge. XMLType columns come back as XML text
and MDSYS.SDO_GEOMETRY as GeoArrow WKB (points, lines, polygons
incl. rectangles, multi-geometries and collections, 2D/3D/4D; circular
arcs are not supported). With adbc.oracle.use_extension_types=true the
fields are annotated with Arrow extension types (arrow.json,
arrow.opaque for XMLType, geoarrow.wkb) — pyarrow materialises them
automatically:
with oracle.connect(uri=uri, db_kwargs={"adbc.oracle.use_extension_types": "true"}) as conn, conn.cursor() as cur:
cur.execute("SELECT name, address, boundary FROM sites") # address is an object type, boundary SDO_GEOMETRY
table = cur.fetch_arrow_table()
table.schema.field("BOUNDARY").type # binary with geoarrow.wkb metadata -> shapely.from_wkb(...)
Nested Arrow columns (list, struct, map) are ingested as JSON text
into JSON columns (21c+; adbc.oracle.ingest.struct_type selects
CLOB, VARCHAR2 or BLOB instead).
Native Network Encryption (NNE)
The driver speaks Oracle's Advanced Networking Option, so it works with servers that require Native Network Encryption and/or data integrity checksumming — no Oracle Client and no TLS certificate wrangling. After the connect handshake it runs the encryption / checksum negotiation (Diffie-Hellman key exchange) and then AES-encrypts and checksums every packet.
It is on by default at accepted: nothing changes for a server that
doesn't ask for it, and a server that requires it is transparently
negotiated (AES-256 / SHA-512 in the common case). Force it with
adbc.oracle.nne=required to guarantee the session is encrypted, or turn
it off with rejected:
# Just works against a server with SQLNET.ENCRYPTION_SERVER=REQUIRED:
with oracle.connect(uri="oracle://user:pw@exadata-scan:1521/PROD") as conn, conn.cursor() as cur:
cur.execute("SELECT * FROM sales.orders") # every packet AES-encrypted + checksummed
# Refuse to connect unless the channel is encrypted:
oracle.connect(uri=uri, db_kwargs={"adbc.oracle.nne": "required"})
Supported: AES-128/192/256 encryption and MD5 / SHA-1 / SHA-256 / SHA-384
/ SHA-512 checksums (the driver offers only AES ciphers; legacy RC4/DES
are never used). Kerberos / RADIUS network authentication is not
supported — use password, TLS or token auth. Over a tcps (TLS)
connection NNE stays off by default since the channel is already
encrypted.
Cancellation
cursor.adbc_cancel() (or a cancelled/expired context.Context in Go)
interrupts the running server call; the statement fails with
ORA-01013 and the connection stays usable. Cancellation uses TCP
out-of-band data on Linux/macOS (in-band markers on Windows and over
TLS), the same mechanism as python-oracledb.
Parameter binding
Positional ? placeholders are rewritten to Oracle's :1, :2, …
bind variables; native :name / :1 styles pass through untouched:
cur.execute("SELECT ename, sal FROM emp WHERE deptno = ? AND sal > ?", (10, 1500))
Connection URL
oracle://[user[:password]@]host[:port]/SERVICE_NAME[?option=value...]
oracle://[user[:password]@]host[:port]?sid=ORCL
Oracle Easy Connect
strings (host:port/service) and full (DESCRIPTION=...) TNS connect
descriptors are accepted in place of the oracle:// form.
| Option | Default | Notes |
|---|---|---|
adbc.uri |
— | Pass as the uri= kwarg to oracle.connect. |
username / password |
(URI) | Standard ADBC credential options; override the URI's user:password. |
adbc.oracle.host |
(URI) | Database host. |
adbc.oracle.port |
1521 |
Listener port. |
adbc.oracle.service_name |
(URI) | Service name (e.g. FREEPDB1). |
adbc.oracle.sid |
(none) | SID, as an alternative to a service name. |
adbc.oracle.tls |
false |
true → TLS (tcps) transport. |
adbc.oracle.tls.ca_cert |
(none) | PEM CA bundle for verifying the server certificate. |
adbc.oracle.tls.skip_verify |
false |
true → skip server certificate verification. |
adbc.oracle.tls.server_name |
(host) | Host name for certificate verification / SNI. |
adbc.oracle.wallet_location |
(none) | Directory containing ewallet.pem (Autonomous Database wallet); implies TLS. mTLS works with an unencrypted key. |
adbc.oracle.token |
(none) | OAuth / IAM bearer token instead of a password (TLS only). |
adbc.oracle.mode |
(none) | sysdba, sysoper, sysasm, sysbackup, sysdg, syskm, sysrac. |
adbc.oracle.connect_timeout |
30 |
Dial timeout, as seconds or a Go duration like 1.5s. |
adbc.oracle.batch_size |
65536 |
Maximum rows per Arrow record batch. |
adbc.oracle.prefetch_rows |
(batch size, max 65536) | Rows the server returns per fetch round trip. |
adbc.oracle.number_mode |
auto |
NUMBER → Arrow policy: auto, decimal, double, string (see Type mapping). |
adbc.oracle.interval_mode |
monthdaynano |
INTERVAL → Arrow policy: monthdaynano, duration (DAY TO SECOND), string (ISO 8601). |
adbc.oracle.date_mode |
timestamp |
DATE → timestamp[s] (keeps the time of day) or date32. |
adbc.oracle.batch_bytes |
0 |
Approximate upper bound on bytes per Arrow record batch (0 = only batch_size applies). |
adbc.oracle.disable_oob |
false |
Disable out-of-band (TCP urgent) breaks used for cancellation; falls back to in-band markers. |
adbc.oracle.nne |
accepted |
Native Network Encryption / data integrity: accepted, requested, required, rejected. |
adbc.oracle.nne_checksum |
(=nne) |
Data-integrity level, if different from nne. |
adbc.oracle.nne_encryption_algorithms |
(all AES) | Comma-separated encryption preference, e.g. AES256,AES192. |
adbc.oracle.nne_checksum_algorithms |
(all) | Comma-separated checksum preference, e.g. SHA512,SHA256. |
adbc.oracle.use_extension_types |
false |
Annotate JSON / object (arrow.json), XMLType (arrow.opaque) and SDO_GEOMETRY (geoarrow.wkb) columns with Arrow extension-type metadata. |
adbc.oracle.session_time_zone |
+00:00 |
Session TIME_ZONE; TIMESTAMP WITH LOCAL TIME ZONE values are returned in it. |
adbc.oracle.sdu |
(server) | Requested session data unit (packet size) in bytes. |
adbc.oracle.application_name |
(executable name) | Program name reported to the server (V$SESSION.PROGRAM, CLIENT_PROGRAM_NAME). |
adbc.oracle.current_schema |
(none) | Sets the session's current schema after connecting. |
adbc.oracle.trace |
false |
true → hex-dump TNS packets to stderr. |
All of these are also accepted as ?key=value URI query parameters
(without the adbc.oracle. prefix, e.g. ?tls=true&number_mode=decimal).
After connecting, adbc.oracle.batch_size, adbc.oracle.batch_bytes,
adbc.oracle.prefetch_rows, adbc.oracle.number_mode,
adbc.oracle.interval_mode, adbc.oracle.date_mode and the end-to-end tracing attributes
adbc.oracle.module / .action / .client_info / .client_identifier
can be changed per connection.
The URI is its own kwarg; everything else goes through db_kwargs:
import adbc_driver_oracle.dbapi as oracle
oracle.connect(
uri="oracle://db.example.com:2484/PROD",
db_kwargs={
"username": "app",
"password": "s3cret",
"adbc.oracle.tls": "true",
"adbc.oracle.tls.ca_cert": "/etc/ssl/certs/corp-ca.pem",
},
)
Connection profiles & driver manifests
ADBC connection profiles (adbc-driver-manager ≥ 1.11) let you keep a connection's driver + options in a reusable TOML file instead of code. Profiles resolve the driver by name, which requires a driver manifest on the search path. Install ours once per environment:
$ python -m adbc_driver_oracle install-manifest
Wrote ADBC driver manifest: .../etc/adbc/drivers/oracle.toml
(Inside a virtualenv/conda env this targets the environment's
auto-searched etc/adbc/drivers/; otherwise the per-user ADBC config
directory. --user, --venv, and --dir PATH override; the same is
available programmatically as adbc_driver_oracle.install_manifest().)
With the manifest in place, the driver manager finds the driver by name
— no import of adbc_driver_oracle needed:
from adbc_driver_manager import dbapi
# Resolve by URI scheme alone:
conn = dbapi.connect(uri="oracle://scott:tiger@localhost:1521/FREEPDB1")
And a profile bundles the whole connection. Drop this in
~/.config/adbc/profiles/oracle_prod.toml (Linux;
~/Library/Application Support/ADBC/Profiles/ on macOS, or any
directory named in ADBC_PROFILE_PATH):
profile_version = 1
driver = "oracle"
[Options]
uri = "oracle://db.example.com:2484/PROD"
username = "app"
password = "{{ env_var(ORACLE_PASSWORD) }}"
"adbc.oracle.tls" = true
then connect from any ADBC driver-manager binding:
conn = dbapi.connect(profile="oracle_prod")
The {{ env_var(...) }} substitution keeps secrets out of the file;
options set explicitly in code still override profile values.
Using from Go
import (
"context"
"github.com/apache/arrow-go/v18/arrow/memory"
"github.com/gizmodata/adbc-driver-oracle/driver/oracle"
)
drv := oracle.NewDriver(memory.DefaultAllocator)
db, _ := drv.NewDatabase(map[string]string{
"uri": "oracle://scott:tiger@localhost:1521/FREEPDB1",
})
conn, _ := db.Open(context.Background())
stmt, _ := conn.NewStatement()
_ = stmt.SetSqlQuery("SELECT ename, sal FROM emp")
reader, _, _ := stmt.ExecuteQuery(context.Background())
defer reader.Release()
for reader.Next() {
rec := reader.Record()
// ...
}
Type mapping
Reads (adbc.oracle.number_mode=auto, the default):
| Oracle type | Arrow type |
|---|---|
NUMBER(p,0) with 1 ≤ p ≤ 18 |
int64 |
NUMBER(p,s) with 1 ≤ p ≤ 38 |
decimal128(p,s) |
NUMBER (no precision), FLOAT, computed expressions (COUNT(*), 1/3, literals) |
float64 |
BINARY_FLOAT / BINARY_DOUBLE |
float32 / float64 |
CHAR, VARCHAR2, NCHAR, NVARCHAR2, LONG, CLOB, NCLOB |
utf8 |
RAW, LONG RAW, BLOB |
binary |
DATE |
timestamp[s] (date32 with date_mode=date32) |
TIMESTAMP(n) |
timestamp[s / ms / us / ns] by fractional-second precision n |
TIMESTAMP WITH TIME ZONE / WITH LOCAL TIME ZONE |
timestamp[…, tz=UTC] (the instant; the original offset is not kept) |
INTERVAL DAY TO SECOND |
month_day_nano_interval; duration[unit by precision] with interval_mode=duration; ISO-8601 utf8 (P1DT2H3M4.5S) with interval_mode=string |
INTERVAL YEAR TO MONTH |
month_day_nano_interval; ISO-8601 utf8 (P2Y3M) with interval_mode=string |
ROWID / UROWID |
utf8 |
JSON (21c+) |
utf8 — native OSON decoded to JSON text client-side |
BOOLEAN (23ai) |
bool |
| Object types, VARRAY, nested table | utf8 JSON text (arrow.json extension with use_extension_types) |
XMLTYPE |
utf8 XML text (arrow.opaque extension) |
MDSYS.SDO_GEOMETRY |
binary WKB (geoarrow.wkb extension) |
number_mode=decimal maps every NUMBER to decimal128 ((38,10) when
the precision is unknown), double maps all of them to float64, and
string returns the exact decimal text — useful when precision matters
and a column's declared scale can't be trusted.
Writes (bind parameters and bulk-ingest DDL):
| Arrow type | Bind type | Generated DDL |
|---|---|---|
int8/16/32/64, uint* |
NUMBER |
NUMBER(3/5/10/19/20) |
float16 / float32 / float64 |
BINARY_FLOAT / BINARY_FLOAT / BINARY_DOUBLE |
same |
decimal128/256(p,s) |
NUMBER |
NUMBER(p,s) |
utf8, large_utf8, utf8_view |
VARCHAR2 (LONG above the server max) |
VARCHAR2(4000) (CLOB for large_utf8; see ingest options) |
binary, fixed_size_binary, large_binary |
RAW (LONG RAW above the max) |
RAW(2000) / RAW(n) / BLOB |
bool |
BOOLEAN on 23ai, else NUMBER 0/1 |
BOOLEAN / NUMBER(1) |
date32 / date64 |
DATE |
DATE |
timestamp[unit] (naive) |
TIMESTAMP |
TIMESTAMP(0/3/6/9) |
timestamp[unit, tz] |
TIMESTAMP WITH TIME ZONE (as UTC) |
TIMESTAMP(n) WITH TIME ZONE |
duration, month_day_nano_interval (no months) |
INTERVAL DAY TO SECOND |
INTERVAL DAY(9) TO SECOND(9) |
list, struct, map |
VARCHAR2 / LONG (JSON text) |
JSON (21c+) — see ingest.struct_type |
Empty strings are bound as NULL, matching Oracle's own '' semantics.
Limitations
- Kerberos / RADIUS network authentication is not supported (use password, TLS, wallet or token auth). Native Network Encryption is supported (see above).
REF CURSORbind/column values,BFILE, LOB-typedOUTbinds,VECTOR, Advanced Queuing, objects stored in LOBs (degenerate images) and SDO_GEOMETRY circular arcs / compound elements are not supported yet (selectVECTOR_SERIALIZE(...),SDO_UTIL.TO_WKBGEOMETRY(...)etc. to read those as text/binary). Object types are read-only: they cannot be bound as parameters or written by ingest.- Strings inside object images are decoded as UTF-8 (AL32UTF8 databases; national-character attributes as UTF-16).
- Named time-zone regions in
TIMESTAMP WITH TIME ZONEvalues are returned as UTC instants (offset-based zones are exact). - Kerberos / RADIUS / external OS authentication, DRCP pooling and Oracle wallet private keys with a password are not supported.
- Cancellation is only honoured by the server at SQL execution
checkpoints; a call blocked in e.g.
DBMS_SESSION.SLEEPfinishes beforeORA-01013is raised (python-oracledb behaves the same).
Repo layout
adbc-driver-oracle/
├── go.mod, go.sum
├── internal/
│ ├── tns/ — TNS packets (CONNECT/ACCEPT/REDIRECT/DATA/MARKER), TLS, SDU, Native Network Encryption (ANO)
│ ├── ttc/ — TTC message layer: protocol/data-type negotiation, O5LOGON auth, cursors, fetch
│ └── oratype/ — NUMBER / DATE / TIMESTAMP / INTERVAL / ROWID / OSON (JSON) codecs
├── driver/oracle/ — pure-Go ADBC Driver/Database/Connection/Statement impl
├── pkg/oracle/ — cgo c-shared wrapper (produces libadbc_driver_oracle.{so,dylib,dll})
├── python/ — Python wheel sources (adbc_driver_oracle)
└── .github/ — CI: go test, python tests (Oracle Free + GizmoSQL services), wheel matrix, PyPI publish
Credits
- Protocol reference:
oracle/python-oracledbthin mode (Apache-2.0 / UPL) andsijms/go-ora(MIT) - ADBC framework: Apache Arrow ADBC (Apache-2.0)
License
MIT. Protocol reference credits are listed above.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file adbc_driver_oracle-0.4.0-py3-none-win_amd64.whl.
File metadata
- Download URL: adbc_driver_oracle-0.4.0-py3-none-win_amd64.whl
- Upload date:
- Size: 8.2 MB
- Tags: Python 3, Windows x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f48c6bb63d51b6b429460e9edfa90ec0839374f23b83ec84b288999065c58419
|
|
| MD5 |
768d62a687c652960c5a16b93898afe2
|
|
| BLAKE2b-256 |
3186f6b7405541c86dcab11c1defc366fb322181994f7b27fb1be66e8a868388
|
Provenance
The following attestation bundles were made for adbc_driver_oracle-0.4.0-py3-none-win_amd64.whl:
Publisher:
ci.yml on gizmodata/adbc-driver-oracle
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
adbc_driver_oracle-0.4.0-py3-none-win_amd64.whl -
Subject digest:
f48c6bb63d51b6b429460e9edfa90ec0839374f23b83ec84b288999065c58419 - Sigstore transparency entry: 2617741486
- Sigstore integration time:
-
Permalink:
gizmodata/adbc-driver-oracle@8fcda119d273a7a65f28fcdd6c63516a47227507 -
Branch / Tag:
refs/tags/v0.4.0 - Owner: https://github.com/gizmodata
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
ci.yml@8fcda119d273a7a65f28fcdd6c63516a47227507 -
Trigger Event:
push
-
Statement type:
File details
Details for the file adbc_driver_oracle-0.4.0-py3-none-manylinux2014_x86_64.whl.
File metadata
- Download URL: adbc_driver_oracle-0.4.0-py3-none-manylinux2014_x86_64.whl
- Upload date:
- Size: 8.3 MB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4089f748490aa379a9a5285ac6e176af626b93bc35cf1c6b4cd173eb030b79ed
|
|
| MD5 |
5263c6025a9148730ffc4099f5d929ec
|
|
| BLAKE2b-256 |
529481955143b79d60b00c98903b8178825909cebb5d679ac482bf1ad2203350
|
Provenance
The following attestation bundles were made for adbc_driver_oracle-0.4.0-py3-none-manylinux2014_x86_64.whl:
Publisher:
ci.yml on gizmodata/adbc-driver-oracle
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
adbc_driver_oracle-0.4.0-py3-none-manylinux2014_x86_64.whl -
Subject digest:
4089f748490aa379a9a5285ac6e176af626b93bc35cf1c6b4cd173eb030b79ed - Sigstore transparency entry: 2617741481
- Sigstore integration time:
-
Permalink:
gizmodata/adbc-driver-oracle@8fcda119d273a7a65f28fcdd6c63516a47227507 -
Branch / Tag:
refs/tags/v0.4.0 - Owner: https://github.com/gizmodata
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
ci.yml@8fcda119d273a7a65f28fcdd6c63516a47227507 -
Trigger Event:
push
-
Statement type:
File details
Details for the file adbc_driver_oracle-0.4.0-py3-none-manylinux2014_aarch64.whl.
File metadata
- Download URL: adbc_driver_oracle-0.4.0-py3-none-manylinux2014_aarch64.whl
- Upload date:
- Size: 7.6 MB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7b4188e5285caa6257d279f30a9f3102abe446d24218acad078538c65921f510
|
|
| MD5 |
e293ead28fbb20bd5b89bb54939c9608
|
|
| BLAKE2b-256 |
da2aac1e076018aff3cacdafa459fd6ef15e52e94fe9c1c7db9a0ce83790fcf3
|
Provenance
The following attestation bundles were made for adbc_driver_oracle-0.4.0-py3-none-manylinux2014_aarch64.whl:
Publisher:
ci.yml on gizmodata/adbc-driver-oracle
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
adbc_driver_oracle-0.4.0-py3-none-manylinux2014_aarch64.whl -
Subject digest:
7b4188e5285caa6257d279f30a9f3102abe446d24218acad078538c65921f510 - Sigstore transparency entry: 2617741473
- Sigstore integration time:
-
Permalink:
gizmodata/adbc-driver-oracle@8fcda119d273a7a65f28fcdd6c63516a47227507 -
Branch / Tag:
refs/tags/v0.4.0 - Owner: https://github.com/gizmodata
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
ci.yml@8fcda119d273a7a65f28fcdd6c63516a47227507 -
Trigger Event:
push
-
Statement type:
File details
Details for the file adbc_driver_oracle-0.4.0-py3-none-macosx_12_0_universal2.whl.
File metadata
- Download URL: adbc_driver_oracle-0.4.0-py3-none-macosx_12_0_universal2.whl
- Upload date:
- Size: 4.0 MB
- Tags: Python 3, macOS 12.0+ universal2 (ARM64, x86-64)
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8b005ef27a1696586025ee15d3a067dc635db91b6b8a1abb2485f4a639082cc7
|
|
| MD5 |
ffa62803412674874e6d485165b9ac2c
|
|
| BLAKE2b-256 |
2eb7bce0f00e6e0a972ce5af1cda8a64b91c3057719eb9fea52cb01cc3802002
|
Provenance
The following attestation bundles were made for adbc_driver_oracle-0.4.0-py3-none-macosx_12_0_universal2.whl:
Publisher:
ci.yml on gizmodata/adbc-driver-oracle
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
adbc_driver_oracle-0.4.0-py3-none-macosx_12_0_universal2.whl -
Subject digest:
8b005ef27a1696586025ee15d3a067dc635db91b6b8a1abb2485f4a639082cc7 - Sigstore transparency entry: 2617741464
- Sigstore integration time:
-
Permalink:
gizmodata/adbc-driver-oracle@8fcda119d273a7a65f28fcdd6c63516a47227507 -
Branch / Tag:
refs/tags/v0.4.0 - Owner: https://github.com/gizmodata
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
ci.yml@8fcda119d273a7a65f28fcdd6c63516a47227507 -
Trigger Event:
push
-
Statement type: