ArpeOracle — Examples & recipes
Copy-paste snippets for the common tasks. All assume the driver is installed and
loadable by name (driver="arpeoracle") — see Install. For the full
option reference behind each db_kwargs, see Connection.
- Connect and query to Arrow
- Connect with discrete options
- Straight to pandas / Polars
- Connect and query from DuckDB
- Prepared statements & parameter binding
- Bulk ingest an Arrow table
- Export a query to Parquet
- Native Network Encryption
- TLS / Oracle Cloud ADB with a wallet
- OCI IAM & OAuth2 / Entra ID token auth
Connect and query to Arrow
The same recipe in every ADBC client — the driver is loaded by name (arpeoracle)
from the installed ADBC manifest, so only the language changes:
- Python
- C / C++
- C#
- Go
- Java
- R
- Rust
import adbc_driver_manager.dbapi as dbapi
with dbapi.connect(
driver="arpeoracle",
db_kwargs={"uri": "oracle://scott:tiger@localhost:1521/orclpdb1"},
) as conn, conn.cursor() as cur:
cur.execute("SELECT * FROM lineitem WHERE ROWNUM <= 10")
table = cur.fetch_arrow_table() # pyarrow.Table
print(table.schema)
#include <cstdio>
#include <cstdlib>
#include <arrow-adbc/adbc.h>
#include <arrow-adbc/adbc_driver_manager.h>
#define CHECK(EXPR) \
if (AdbcStatusCode s = (EXPR); s != ADBC_STATUS_OK) { \
std::fprintf(stderr, "%s failed: %s\n", #EXPR, \
error.message ? error.message : "(unknown)"); \
std::exit(1); \
}
int main() {
AdbcError error = {};
AdbcDatabase database = {};
CHECK(AdbcDatabaseNew(&database, &error));
// Load the driver by name from the installed ADBC manifest.
CHECK(AdbcDatabaseSetOption(&database, "driver", "arpeoracle", &error));
CHECK(AdbcDatabaseSetOption(
&database, "uri",
"oracle://scott:tiger@localhost:1521/orclpdb1", &error));
CHECK(AdbcDatabaseInit(&database, &error));
AdbcConnection connection = {};
CHECK(AdbcConnectionNew(&connection, &error));
CHECK(AdbcConnectionInit(&connection, &database, &error));
AdbcStatement statement = {};
CHECK(AdbcStatementNew(&connection, &statement, &error));
CHECK(AdbcStatementSetSqlQuery(&statement, "SELECT * FROM lineitem WHERE ROWNUM <= 10", &error));
ArrowArrayStream stream = {}; // Arrow C Data interface
int64_t rows_affected = -1;
CHECK(AdbcStatementExecuteQuery(&statement, &stream, &rows_affected, &error));
// consume `stream` with nanoarrow / Arrow C++, then release:
stream.release(&stream);
AdbcStatementRelease(&statement, &error);
AdbcConnectionRelease(&connection, &error);
AdbcDatabaseRelease(&database, &error);
return 0;
}
using Apache.Arrow.Adbc;
using Apache.Arrow.Adbc.DriverManager;
var parameters = new Dictionary<string, string>
{
["uri"] = "oracle://scott:tiger@localhost:1521/orclpdb1",
};
// Load the driver by name from the installed ADBC manifest.
using AdbcDriver driver = AdbcDriverManager.FindLoadDriver(
"arpeoracle", loadOptions: AdbcLoadFlags.Default);
using AdbcDatabase database = driver.Open(parameters);
using AdbcConnection connection = database.Connect(null);
using AdbcStatement statement = connection.CreateStatement();
statement.SqlQuery = "SELECT * FROM lineitem WHERE ROWNUM <= 10";
QueryResult result = statement.ExecuteQuery();
using var stream = result.Stream!; // IArrowArrayStream of RecordBatches
Console.WriteLine(stream.Schema);
package main
import (
"context"
"fmt"
"github.com/apache/arrow-adbc/go/adbc"
"github.com/apache/arrow-adbc/go/adbc/drivermgr"
)
func main() {
ctx := context.Background()
var drv drivermgr.Driver
// Load the driver by name from the installed ADBC manifest.
db, err := drv.NewDatabase(map[string]string{
"driver": "arpeoracle",
adbc.OptionKeyURI: "oracle://scott:tiger@localhost:1521/orclpdb1",
})
if err != nil {
panic(err)
}
defer db.Close()
conn, err := db.Open(ctx)
if err != nil {
panic(err)
}
defer conn.Close()
stmt, err := conn.NewStatement()
if err != nil {
panic(err)
}
defer stmt.Close()
if err := stmt.SetSqlQuery("SELECT * FROM lineitem WHERE ROWNUM <= 10"); err != nil {
panic(err)
}
reader, _, err := stmt.ExecuteQuery(ctx) // (array.RecordReader, int64, error)
if err != nil {
panic(err)
}
defer reader.Release()
fmt.Println(reader.Schema())
}
import java.util.HashMap;
import java.util.Map;
import org.apache.arrow.adbc.core.AdbcConnection;
import org.apache.arrow.adbc.core.AdbcDatabase;
import org.apache.arrow.adbc.core.AdbcDriver;
import org.apache.arrow.adbc.core.AdbcStatement;
import org.apache.arrow.adbc.driver.jni.JniDriver;
import org.apache.arrow.memory.BufferAllocator;
import org.apache.arrow.memory.RootAllocator;
import org.apache.arrow.vector.ipc.ArrowReader;
public class ConnectAndQuery {
public static void main(String[] args) throws Exception {
Map<String, Object> parameters = new HashMap<>();
// Load the driver by name from the installed ADBC manifest.
JniDriver.PARAM_DRIVER.set(parameters, "arpeoracle");
AdbcDriver.PARAM_URI.set(parameters,
"oracle://scott:tiger@localhost:1521/orclpdb1");
try (BufferAllocator allocator = new RootAllocator();
AdbcDatabase db = new JniDriver(allocator).open(parameters);
AdbcConnection connection = db.connect();
AdbcStatement statement = connection.createStatement()) {
statement.setSqlQuery("SELECT * FROM lineitem WHERE ROWNUM <= 10");
try (AdbcStatement.QueryResult result = statement.executeQuery()) {
ArrowReader reader = result.getReader();
System.out.println(reader.getVectorSchemaRoot().getSchema());
}
}
}
}
library(adbcdrivermanager)
library(arrow)
# Load the driver by name from the installed ADBC manifest.
db <- adbc_database_init(
adbc_driver("arpeoracle"),
uri = "oracle://scott:tiger@localhost:1521/orclpdb1"
)
con <- adbc_connection_init(db)
table <- read_adbc(con, "SELECT * FROM lineitem WHERE ROWNUM <= 10") |>
as_arrow_table()
print(table$schema)
use adbc_core::options::{AdbcVersion, OptionDatabase, OptionValue};
use adbc_core::{Connection, Database, Driver, Statement, LOAD_FLAG_DEFAULT};
use adbc_driver_manager::ManagedDriver;
use arrow_array::RecordBatchReader;
fn main() -> Result<(), Box<dyn std::error::Error>> {
// Load the driver by name from the installed ADBC manifest.
let mut driver = ManagedDriver::load_from_name(
"arpeoracle", None, AdbcVersion::default(), LOAD_FLAG_DEFAULT, None,
)?;
let mut database = driver.new_database_with_opts([(
OptionDatabase::Uri,
OptionValue::String(
"oracle://scott:tiger@localhost:1521/orclpdb1".into(),
),
)])?;
let mut connection = database.new_connection()?;
let mut statement = connection.new_statement()?;
statement.set_sql_query("SELECT * FROM lineitem WHERE ROWNUM <= 10")?;
let reader = statement.execute()?; // impl RecordBatchReader
println!("{}", reader.schema());
Ok(())
}
Connect with discrete options
Discrete options keep secrets out of a single string and override any uri. Set them
where the uri went — the rest of each program is identical to the recipe above:
- Python
- C / C++
- C#
- Go
- Java
- R
- Rust
conn = dbapi.connect(driver="arpeoracle", db_kwargs={
"adbc.arpeoracle.server": "localhost",
"adbc.arpeoracle.port": "1521",
"adbc.arpeoracle.service_name": "orclpdb1",
"adbc.arpeoracle.username": "scott",
"adbc.arpeoracle.password": "tiger",
})
CHECK(AdbcDatabaseNew(&database, &error));
CHECK(AdbcDatabaseSetOption(&database, "driver", "arpeoracle", &error));
CHECK(AdbcDatabaseSetOption(&database, "adbc.arpeoracle.server", "localhost", &error));
CHECK(AdbcDatabaseSetOption(&database, "adbc.arpeoracle.port", "1521", &error));
CHECK(AdbcDatabaseSetOption(&database, "adbc.arpeoracle.service_name", "orclpdb1", &error));
CHECK(AdbcDatabaseSetOption(&database, "adbc.arpeoracle.username", "scott", &error));
CHECK(AdbcDatabaseSetOption(&database, "adbc.arpeoracle.password", "tiger", &error));
CHECK(AdbcDatabaseInit(&database, &error));
var parameters = new Dictionary<string, string>
{
["adbc.arpeoracle.server"] = "localhost",
["adbc.arpeoracle.port"] = "1521",
["adbc.arpeoracle.service_name"] = "orclpdb1",
["adbc.arpeoracle.username"] = "scott",
["adbc.arpeoracle.password"] = "tiger",
};
using AdbcDriver driver = AdbcDriverManager.FindLoadDriver("arpeoracle", loadOptions: AdbcLoadFlags.Default);
using AdbcDatabase database = driver.Open(parameters);
db, err := drv.NewDatabase(map[string]string{
"driver": "arpeoracle",
"adbc.arpeoracle.server": "localhost",
"adbc.arpeoracle.port": "1521",
"adbc.arpeoracle.service_name": "orclpdb1",
"adbc.arpeoracle.username": "scott",
"adbc.arpeoracle.password": "tiger",
})
Map<String, Object> parameters = new HashMap<>();
JniDriver.PARAM_DRIVER.set(parameters, "arpeoracle");
parameters.put("adbc.arpeoracle.server", "localhost");
parameters.put("adbc.arpeoracle.port", "1521");
parameters.put("adbc.arpeoracle.service_name", "orclpdb1");
parameters.put("adbc.arpeoracle.username", "scott");
parameters.put("adbc.arpeoracle.password", "tiger");
AdbcDatabase db = new JniDriver(allocator).open(parameters);
db <- adbc_database_init(
adbc_driver("arpeoracle"),
adbc.arpeoracle.server = "localhost",
adbc.arpeoracle.port = "1521",
adbc.arpeoracle.service_name = "orclpdb1",
adbc.arpeoracle.username = "scott",
adbc.arpeoracle.password = "tiger"
)
let mut database = driver.new_database_with_opts([
(OptionDatabase::Other("adbc.arpeoracle.server".into()), OptionValue::String("localhost".into())),
(OptionDatabase::Other("adbc.arpeoracle.port".into()), OptionValue::String("1521".into())),
(OptionDatabase::Other("adbc.arpeoracle.service_name".into()), OptionValue::String("orclpdb1".into())),
(OptionDatabase::Other("adbc.arpeoracle.username".into()), OptionValue::String("scott".into())),
(OptionDatabase::Other("adbc.arpeoracle.password".into()), OptionValue::String("tiger".into())),
])?;
Straight to pandas / Polars
The result is already Arrow, so these handoffs stay zero-copy — no row-by-row marshalling. pandas and Polars read straight from the ADBC connection:
import adbc_driver_manager.dbapi as dbapi
import pandas as pd
import polars as pl
uri = "oracle://scott:tiger@localhost:1521/orclpdb1"
with dbapi.connect(driver="arpeoracle", db_kwargs={"uri": uri}) as conn:
# pandas — Arrow-backed dtypes, no Python-object columns
df = pd.read_sql(
"SELECT * FROM orders WHERE o_orderdate >= DATE '1996-01-01'",
conn, dtype_backend="pyarrow",
)
# Polars — reads the same ADBC result directly
pf = pl.read_database(
"SELECT * FROM orders WHERE o_orderdate >= DATE '1996-01-01'", conn
)
Connect and query from DuckDB
DuckDB itself can be the ADBC client, via the third-party
adbc_scanner community extension — it
loads the arpeoracle driver and scans the result straight into DuckDB, in pure SQL:
-- DuckDB itself as the ADBC client, via the adbc_scanner community extension:
-- https://query.farm/products/extensions/adbc_scanner/
INSTALL adbc_scanner FROM community;
LOAD adbc_scanner;
-- Load the driver by name from the installed ADBC manifest.
SET VARIABLE conn = adbc_connect({
'driver': 'arpeoracle',
'uri': 'oracle://scott:tiger@localhost:1521/orclpdb1'
});
SELECT * FROM adbc_scan(getvariable('conn'), 'SELECT * FROM lineitem WHERE ROWNUM <= 10');
Prepared statements & parameter binding
Oracle uses positional :1, :2 bind placeholders. In the compiled clients you bind an
Arrow batch of parameters to the statement before executing:
- Python
- C / C++
- C#
- Go
- Java
- R
- Rust
with conn.cursor() as cur:
cur.execute("SELECT * FROM orders WHERE o_orderkey = :1", parameters=[42])
row = cur.fetch_arrow_table()
// One-row, one-column (int64) parameter batch, built with nanoarrow.
ArrowSchema param_schema = {};
ArrowSchemaInitFromType(¶m_schema, NANOARROW_TYPE_STRUCT);
ArrowSchemaAllocateChildren(¶m_schema, 1);
ArrowSchemaInitFromType(param_schema.children[0], NANOARROW_TYPE_INT64);
ArrowSchemaSetName(param_schema.children[0], "0");
ArrowArray param_array = {};
ArrowArrayInitFromSchema(¶m_array, ¶m_schema, nullptr);
ArrowArrayStartAppending(¶m_array);
ArrowArrayAppendInt(param_array.children[0], 42);
ArrowArrayFinishElement(¶m_array);
ArrowArrayFinishBuildingDefault(¶m_array, nullptr);
CHECK(AdbcStatementSetSqlQuery(&statement, "SELECT * FROM orders WHERE o_orderkey = :1", &error));
CHECK(AdbcStatementBind(&statement, ¶m_array, ¶m_schema, &error));
CHECK(AdbcStatementExecuteQuery(&statement, &stream, &rows_affected, &error));
using Apache.Arrow;
var schema = new Schema(new[] { new Field("0", Int64Type.Default, nullable: false) }, null);
var paramCol = new Int64Array.Builder().Append(42).Build();
var parameters = new RecordBatch(schema, new IArrowArray[] { paramCol }, 1);
using AdbcStatement statement = connection.CreateStatement();
statement.SqlQuery = "SELECT * FROM orders WHERE o_orderkey = :1";
statement.Bind(parameters, schema);
QueryResult result = statement.ExecuteQuery();
using var stream = result.Stream!;
import (
"github.com/apache/arrow-go/v18/arrow"
"github.com/apache/arrow-go/v18/arrow/array"
"github.com/apache/arrow-go/v18/arrow/memory"
)
schema := arrow.NewSchema([]arrow.Field{
{Name: "0", Type: arrow.PrimitiveTypes.Int64},
}, nil)
bldr := array.NewRecordBuilder(memory.DefaultAllocator, schema)
defer bldr.Release()
bldr.Field(0).(*array.Int64Builder).Append(42)
rec := bldr.NewRecord()
defer rec.Release()
_ = stmt.SetSqlQuery("SELECT * FROM orders WHERE o_orderkey = :1")
if err := stmt.Bind(ctx, rec); err != nil {
panic(err)
}
reader, _, err := stmt.ExecuteQuery(ctx)
if err != nil {
panic(err)
}
defer reader.Release()
import org.apache.arrow.vector.BigIntVector;
import org.apache.arrow.vector.VectorSchemaRoot;
import org.apache.arrow.vector.types.pojo.ArrowType;
import org.apache.arrow.vector.types.pojo.Field;
import org.apache.arrow.vector.types.pojo.FieldType;
import org.apache.arrow.vector.types.pojo.Schema;
import java.util.List;
Field field = new Field("0", FieldType.notNullable(new ArrowType.Int(64, true)), null);
try (VectorSchemaRoot root = VectorSchemaRoot.create(new Schema(List.of(field)), allocator)) {
BigIntVector col = (BigIntVector) root.getVector("0");
col.allocateNew(1);
col.set(0, 42);
root.setRowCount(1);
try (AdbcStatement statement = connection.createStatement()) {
statement.setSqlQuery("SELECT * FROM orders WHERE o_orderkey = :1");
statement.bind(root);
try (AdbcStatement.QueryResult result = statement.executeQuery()) {
ArrowReader reader = result.getReader();
while (reader.loadNextBatch()) {
System.out.println(reader.getVectorSchemaRoot().contentToTSVString());
}
}
}
}
result <- read_adbc(
con,
"SELECT * FROM orders WHERE o_orderkey = :1",
bind = data.frame(o_orderkey = 42L)
) |>
as_arrow_table()
print(result)
use std::sync::Arc;
use arrow_array::{Int64Array, RecordBatch, RecordBatchReader};
use arrow_schema::{DataType, Field, Schema};
let schema = Arc::new(Schema::new(vec![Field::new("0", DataType::Int64, false)]));
let batch = RecordBatch::try_new(schema, vec![Arc::new(Int64Array::from(vec![42_i64]))])?;
statement.set_sql_query("SELECT * FROM orders WHERE o_orderkey = :1")?;
statement.bind(batch)?;
let reader = statement.execute()?;
println!("{}", reader.schema());
Array binding — bind a whole Arrow batch of parameters in one call (Python's
executemany):
with conn.cursor() as cur:
cur.executemany(
"INSERT INTO t(a, b) VALUES (:1, :2)",
seq_of_parameters=[(1, "x"), (2, "y"), (3, "z")],
)
conn.commit()
Bulk ingest an Arrow table
adbc_ingest pipes an Arrow table straight in via an array-bound INSERT:
- Python
- C#
- Go
- Java
- R
import pyarrow as pa
table = pa.table({
"id": pa.array([1, 2, 3], pa.int32()),
"name": pa.array(["a", "b", "c"], pa.string()),
})
with conn.cursor() as cur:
cur.adbc_ingest("my_table", table, mode="create") # create | append | replace | create_append
conn.commit()
using Apache.Arrow;
var schema = new Schema(new[]
{
new Field("id", Int32Type.Default, nullable: false),
new Field("name", StringType.Default, nullable: false),
}, null);
var idCol = new Int32Array.Builder().AppendRange(new[] { 1, 2, 3 }).Build();
var nameCol = new StringArray.Builder().Append("a").Append("b").Append("c").Build();
var batch = new RecordBatch(schema, new IArrowArray[] { idCol, nameCol }, 3);
using AdbcStatement statement = connection.CreateStatement();
statement.SetOption("adbc.ingest.target_table", "my_table");
statement.SetOption("adbc.ingest.mode", "adbc.ingest.mode.create");
statement.Bind(batch, schema);
statement.ExecuteUpdate(); // autocommit is on by default: no Commit needed
import (
"github.com/apache/arrow-adbc/go/adbc"
"github.com/apache/arrow-go/v18/arrow"
"github.com/apache/arrow-go/v18/arrow/array"
"github.com/apache/arrow-go/v18/arrow/memory"
)
schema := arrow.NewSchema([]arrow.Field{
{Name: "id", Type: arrow.PrimitiveTypes.Int32},
{Name: "name", Type: arrow.BinaryTypes.String},
}, nil)
bldr := array.NewRecordBuilder(memory.DefaultAllocator, schema)
defer bldr.Release()
bldr.Field(0).(*array.Int32Builder).AppendValues([]int32{1, 2, 3}, nil)
bldr.Field(1).(*array.StringBuilder).AppendValues([]string{"a", "b", "c"}, nil)
rec := bldr.NewRecord()
defer rec.Release()
_ = stmt.SetOption(adbc.OptionKeyIngestTargetTable, "my_table")
_ = stmt.SetOption(adbc.OptionKeyIngestMode, adbc.OptionValueIngestModeCreate)
if err := stmt.Bind(ctx, rec); err != nil {
panic(err)
}
if _, err := stmt.ExecuteUpdate(ctx); err != nil {
panic(err)
}
// autocommit is on by default: no Commit needed
import org.apache.arrow.adbc.core.BulkIngestMode;
import org.apache.arrow.vector.IntVector;
import org.apache.arrow.vector.VarCharVector;
import org.apache.arrow.vector.VectorSchemaRoot;
import org.apache.arrow.vector.types.pojo.ArrowType;
import org.apache.arrow.vector.types.pojo.Field;
import org.apache.arrow.vector.types.pojo.FieldType;
import org.apache.arrow.vector.types.pojo.Schema;
import java.nio.charset.StandardCharsets;
import java.util.List;
Schema schema = new Schema(List.of(
new Field("id", FieldType.notNullable(new ArrowType.Int(32, true)), null),
new Field("name", FieldType.notNullable(new ArrowType.Utf8()), null)));
try (VectorSchemaRoot root = VectorSchemaRoot.create(schema, allocator)) {
IntVector id = (IntVector) root.getVector("id");
VarCharVector name = (VarCharVector) root.getVector("name");
id.allocateNew(3);
name.allocateNew(3);
id.set(0, 1); id.set(1, 2); id.set(2, 3);
name.setSafe(0, "a".getBytes(StandardCharsets.UTF_8));
name.setSafe(1, "b".getBytes(StandardCharsets.UTF_8));
name.setSafe(2, "c".getBytes(StandardCharsets.UTF_8));
root.setRowCount(3);
try (AdbcStatement statement =
connection.bulkIngest("my_table", BulkIngestMode.CREATE)) {
statement.bind(root);
statement.executeUpdate();
}
}
tbl <- arrow::arrow_table(
id = arrow::Array$create(1:3, type = arrow::int32()),
name = c("a", "b", "c")
)
tbl |> write_adbc(con, "my_table", mode = "create")
Rust & C++ have no one-call adbc_ingest helper: set the standard statement
options adbc.ingest.target_table / adbc.ingest.mode, Bind the Arrow batch, then
execute_update (Rust) / AdbcStatementExecuteQuery (C++).
Ingest into a specific schema or a GLOBAL TEMPORARY table via the statement
options adbc.ingest.target_db_schema / adbc.ingest.temporary (see
Connection). Table
and column names are used exactly as given (quoted), so my_table above is the
case-sensitive "my_table" — see
Data types.
Export a query to Parquet
import pyarrow.parquet as pq
with conn.cursor() as cur:
cur.execute("SELECT * FROM lineitem")
reader = cur.fetch_record_batch() # streaming RecordBatchReader
with pq.ParquetWriter("lineitem.parquet", reader.schema) as w:
for batch in reader:
w.write_batch(batch)
Streaming keeps memory flat regardless of result size. batch_size (rows per
batch) is a memory knob, not a throughput knob — see
Timeouts & performance.
Native Network Encryption
Encrypt the whole session without TCPS — the way to connect a server configured
SQLNET.ENCRYPTION_SERVER=REQUIRED:
conn = dbapi.connect(driver="arpeoracle", db_kwargs={
"adbc.arpeoracle.server": "dbhost",
"adbc.arpeoracle.service_name": "orclpdb1",
"adbc.arpeoracle.username": "scott",
"adbc.arpeoracle.password": "tiger",
"adbc.arpeoracle.encryption": "required", # AES-256 payloads
"adbc.arpeoracle.data_integrity": "required", # SHA-256 checksum
})
TLS / Oracle Cloud ADB with a wallet
Point wallet_location at an unzipped ADB wallet (mutual TLS):
conn = dbapi.connect(driver="arpeoracle", db_kwargs={
"adbc.arpeoracle.server": "adb.<region>.oraclecloud.com",
"adbc.arpeoracle.port": "1522",
"adbc.arpeoracle.service_name": "<svc>_low.adb.oraclecloud.com",
"adbc.arpeoracle.username": "scott",
"adbc.arpeoracle.password": "tiger",
"adbc.arpeoracle.ssl_mode": "verify-full",
"adbc.arpeoracle.wallet_location": "/home/you/wallet",
"adbc.arpeoracle.wallet_password": "<wallet-pw>",
})
OCI IAM & OAuth2 / Entra ID token auth
OCI IAM database token (oci iam db-token get writes the token directory); pair
with the ADB wallet for mutual TLS:
db_kwargs = {
"adbc.arpeoracle.server": "adb.<region>.oraclecloud.com",
"adbc.arpeoracle.port": "1522",
"adbc.arpeoracle.service_name": "<svc>_low.adb.oraclecloud.com",
"adbc.arpeoracle.auth_method": "token",
"adbc.arpeoracle.token_location": "/home/you/.oci/db-token",
"adbc.arpeoracle.ssl_mode": "verify-full",
"adbc.arpeoracle.wallet_location": "/home/you/wallet",
"adbc.arpeoracle.wallet_password": "<wallet-pw>",
}
OAuth2 / Microsoft Entra ID bearer token — setting the token auto-selects the
method (no username; Oracle maps the token's upn claim to a global user):
db_kwargs = {
"adbc.arpeoracle.server": "adb.<region>.oraclecloud.com",
"adbc.arpeoracle.port": "1522",
"adbc.arpeoracle.service_name": "<svc>_low.adb.oraclecloud.com",
"adbc.arpeoracle.access_token": "<entra-jwt>", # or token_file=<path>
# wallet options as above for ADB mutual TLS
}
See Authentication.
Loading by explicit path
Load-by-name (above) uses the ADBC manifest the installer registers. When the driver is
not installed system-wide, point the driver manager at the shared library instead — e.g.
in C# via CAdbcDriverImporter.Load("libarpeoracle_adbc_driver-linux-x64.so", "AdbcDriverInit")
(arpeoracle_adbc_driver-win-x64.dll on Windows). Alternatively, keep loading by name and point
ADBC_DRIVER_PATH at the directory holding the arpeoracle.toml manifest. Everything after
loading is identical.
See also
- Connection — every connection option
- Data types — the Arrow types you get back
- Troubleshooting — when a snippet does not connect