oracle-tns
Driver Oracle

Sin Instant Client.
Rust puro. Oracle 12c+.

oracle-tns es una implementacion en Rust puro del protocolo TNS de Oracle. Sin Oracle Instant Client, sin bindings a C, sin bibliotecas compartidas. Un binario estatico musl que habla TNS nativamente — O3LOGON, O5LOGON, queries, PL/SQL, procedimientos almacenados, REF CURSORs.

Este driver conecta a Oracle 12c R1 con verificadores de contrasena 10G/11G — algo que python-oracledb, node-oracledb, oracle-nio y kalliope no pueden hacer (DPY-3015).
~5.5 MB
binario estatico musl
13ms
latencia promedio VPN
5
targets de fuzzing
48M+
ejecuciones de fuzz

Inicio Rapido

Conectar a Oracle
en tres pasos.

1. Agregar dependencia
cargo add oracle-tns
2. Configurar conexion
use oracle_tns::{ConnectConfig, OracleSession};

let config = ConnectConfig {
    host: "db.example.com".to_string(),
    port: 1521,
    service_name: "MYDB".to_string(),
    username: "myuser".to_string(),
    password: "mypassword".to_string(),
};
3. Consultar
let mut session = OracleSession::connect(&config).await?;

let rows = session.query(
    "SELECT id, name, email FROM users WHERE department = :1",
    &[BindParam::varchar("Engineering")],
).await?;

for row in rows {
    let id: i64 = row.get("ID")?;
    let name: String = row.get("NAME")?;
    println!("{id}: {name}");
}

session.close().await?;

Funcionalidades

Protocolo Oracle completo
en Rust puro.

ConnectHandshake TNS, autenticacion O3LOGON (0x939) + O5LOGON, resolucion de service name
QuerySELECT con decodificacion completa — VARCHAR2, NUMBER, DATE, RAW, NULL
Bind parametersVariables de bind posicionales (:1, :2) — tipos VARCHAR, INTEGER
PaginacionSoporte OFFSET/FETCH NEXT para limitacion de filas en Oracle 12c+
Bloques PL/SQLEjecucion de bloques PL/SQL anonimos con variables de bind
ProcedimientosCALL con parametros IN y OUT
Parametros OUTLectura de valores de salida de llamadas a procedimientos
REF CURSORBind de cursor OUT, fetch de result set con metadata de columnas
DMLINSERT, UPDATE, DELETE, CREATE TABLE, DROP TABLE
Connection poolPool asincrono con conexiones min/max configurables y timeout de inactividad
PingVerificacion ligera de salud de conexion sobre TNS

Comparacion

oracle-tns vs el resto

oracle-tnspython-oracledbnode-oracledbInstant Client
Tamano binario~5.5 MB (static musl)~50 MB + Python~30 MB + Node.js~250 MB
Requiere Instant ClientNoThin: No, Thick: SiThin: No, Thick: SiSi (lo es)
Soporte Oracle 12c R1SiFalla (DPY-3015)FallaSi
Verificador 10G/11GSi (O3LOGON)NoNoSi
AsincronoSi (tokio)Si (asyncio)Si (promises)No
Connection poolingSiSiSiSi (OCI)
Fuzz testingSi (48M+ ejecuciones)NoNoNo

Seguridad

Fuzz-tested.
48 millones de ejecuciones.

Cada parser en oracle-tns esta fuzz-tested con cargo-fuzz. Cinco targets cubriendo decodificacion de paquetes TNS, parsing de numeros, decodificacion de fechas, operaciones de codec y manejo de paquetes de conexion. Cinco bugs encontrados y corregidos antes de llegar a produccion.

BugTargetImpactoEstado
decode_number overflowfuzz_numberPanic con bytes NUMBER malformadosCorregido
AcceptPacket boundsfuzz_tns_packetLectura fuera de limites en paquete truncadoCorregido
codec OOMfuzz_codecBomba de asignacion via prefijo de longitud (vector DoS)Corregido
decode_date overflowfuzz_datePanic con componentes de fecha invalidosCorregido
slice index panicfuzz_codecIndice fuera de limites en chunk CLR parcialCorregido
5
targets de fuzz
48M+
ejecuciones totales
5
bugs encontrados
0
issues abiertos

Protocolo Wire

TNS desde el cable.

TNS Packet Framing
Cada mensaje Oracle se envuelve en un paquete TNS: header de 8 bytes con longitud, checksum, tipo y flags. Los tipos incluyen Connect (1), Accept (2), Data (6), Marker (12). El driver maneja reensamblado de paquetes, negociacion SDU y lecturas chunked.
Enteros de Longitud Variable
Oracle usa enteros sin signo UB2 (2 bytes) y UB4 (4 bytes) en formato big-endian para longitudes y offsets. El driver lee estos del cable y los usa para parsear limites de campos en paquetes de datos.
CLR Chunked Encoding
Los datos de columna se codifican en formato CLR (Column Length Representation): un byte de longitud seguido de bytes de datos. Para valores mayores a 254 bytes, se usa codificacion chunked con prefijo 0xFE y multiples segmentos con prefijo de longitud.
Autenticacion O3LOGON / O5LOGON
O5LOGON usa intercambio de claves Diffie-Hellman con SHA-1. O3LOGON (verificador 0x939) es requerido para Oracle 12c R1 con verificadores legacy 10G/11G — esta es la autenticacion que todos los otros thin drivers fallan en implementar.

Referencia API

Tipos y funciones principales.

ConnectConfig
pub struct ConnectConfig {
    pub host: String,
    pub port: u16,
    pub service_name: String,
    pub username: String,
    pub password: String,
}
OracleSession
impl OracleSession {
    pub async fn connect(config: &ConnectConfig) -> Result<Self>;
    pub async fn query(&mut self, sql: &str, params: &[BindParam]) -> Result<Vec<Row>>;
    pub async fn execute(&mut self, sql: &str, params: &[BindParam]) -> Result<u64>;
    pub async fn call(&mut self, sql: &str, params: &mut [BindParam]) -> Result<()>;
    pub async fn ping(&mut self) -> Result<()>;
    pub async fn close(self) -> Result<()>;
}
BindParam
impl BindParam {
    pub fn varchar(value: &str) -> Self;
    pub fn integer(value: i64) -> Self;
    pub fn out_varchar() -> Self;
    pub fn out_cursor() -> Self;
}
Cursor + OracleValue
impl Cursor {
    pub fn fetch_all(&self) -> &[Row];
    pub fn columns(&self) -> &[ColumnInfo];
}

pub enum OracleValue {
    Varchar(String),
    Number(f64),
    Integer(i64),
    Date(NaiveDateTime),
    Raw(Vec<u8>),
    Null,
}

Limitaciones Conocidas

Pendiente de implementar.

Streaming CLOB/BLOB
Los tipos de objetos grandes aun no estan soportados. Valores que excedan el tamano SDU necesitaran lecturas por streaming — implementacion pendiente.
TIMESTAMP WITH TIME ZONE
DATE y TIMESTAMP basicos funcionan. El parsing de TIMESTAMP WITH TIME ZONE y TIMESTAMP WITH LOCAL TIME ZONE aun no esta implementado.
TCP keepalive
Conexiones de larga duracion sobre redes inestables pueden caer silenciosamente. Configuracion de TCP keepalive esta pendiente.