oracle_rs/
constants.rs

1//! TNS protocol constants
2//!
3//! This module contains all the constants used in the Oracle TNS protocol,
4//! derived from the official python-oracledb thin driver and oracle-nio.
5
6// =============================================================================
7// Packet Types
8// =============================================================================
9
10/// TNS packet types (found in packet header byte 5)
11#[derive(Debug, Clone, Copy, PartialEq, Eq)]
12#[repr(u8)]
13pub enum PacketType {
14    /// Initial connection request from client
15    Connect = 1,
16    /// Server accepts connection
17    Accept = 2,
18    /// Server acknowledges (rarely used)
19    Ack = 3,
20    /// Server refuses connection
21    Refuse = 4,
22    /// Server redirects to different address
23    Redirect = 5,
24    /// Data packet (contains protocol messages)
25    Data = 6,
26    /// Null packet
27    Null = 7,
28    /// Abort connection
29    Abort = 9,
30    /// Request packet resend
31    Resend = 11,
32    /// Marker packet (break/reset/interrupt)
33    Marker = 12,
34    /// Attention packet
35    Attention = 13,
36    /// Control packet (inband notifications)
37    Control = 14,
38}
39
40impl TryFrom<u8> for PacketType {
41    type Error = crate::error::Error;
42
43    fn try_from(value: u8) -> Result<Self, Self::Error> {
44        match value {
45            1 => Ok(PacketType::Connect),
46            2 => Ok(PacketType::Accept),
47            3 => Ok(PacketType::Ack),
48            4 => Ok(PacketType::Refuse),
49            5 => Ok(PacketType::Redirect),
50            6 => Ok(PacketType::Data),
51            7 => Ok(PacketType::Null),
52            9 => Ok(PacketType::Abort),
53            11 => Ok(PacketType::Resend),
54            12 => Ok(PacketType::Marker),
55            13 => Ok(PacketType::Attention),
56            14 => Ok(PacketType::Control),
57            _ => Err(crate::error::Error::InvalidPacketType(value)),
58        }
59    }
60}
61
62// =============================================================================
63// Packet Flags
64// =============================================================================
65
66/// Packet flags (found in packet header byte 6)
67#[allow(missing_docs)]
68pub mod packet_flags {
69    pub const REDIRECT: u8 = 0x04;
70    pub const TLS_RENEG: u8 = 0x08;
71}
72
73// =============================================================================
74// Data Flags (for DATA packets)
75// =============================================================================
76
77/// Data flags (first 2 bytes of DATA packet payload)
78#[allow(missing_docs)]
79pub mod data_flags {
80    pub const BEGIN_PIPELINE: u16 = 0x1000;
81    pub const END_OF_REQUEST: u16 = 0x0800;
82    pub const END_OF_RESPONSE: u16 = 0x2000;
83    pub const EOF: u16 = 0x0040;
84}
85
86// =============================================================================
87// Marker Types
88// =============================================================================
89
90/// Marker types for MARKER packets
91#[derive(Debug, Clone, Copy, PartialEq, Eq)]
92#[repr(u8)]
93pub enum MarkerType {
94    /// Break marker - interrupts current operation
95    Break = 1,
96    /// Reset marker - resets connection state
97    Reset = 2,
98    /// Interrupt marker - signals interrupt request
99    Interrupt = 3,
100}
101
102// =============================================================================
103// Message Types (within DATA packets)
104// =============================================================================
105
106/// Message types found in DATA packet payloads
107#[derive(Debug, Clone, Copy, PartialEq, Eq)]
108#[repr(u8)]
109pub enum MessageType {
110    /// Protocol negotiation
111    Protocol = 1,
112    /// Data type negotiation
113    DataTypes = 2,
114    /// Execute function (TTC function call)
115    Function = 3,
116    /// Error response
117    Error = 4,
118    /// Row header
119    RowHeader = 6,
120    /// Row data
121    RowData = 7,
122    /// OPI parameter response
123    Parameter = 8,
124    /// Call status
125    Status = 9,
126    /// I/O vector
127    IoVector = 11,
128    /// LOB data
129    LobData = 14,
130    /// Warning message
131    Warning = 15,
132    /// Column describe information
133    DescribeInfo = 16,
134    /// Piggyback function
135    Piggyback = 17,
136    /// Flush out binds
137    FlushOutBinds = 19,
138    /// Bit vector
139    BitVector = 21,
140    /// Server-side piggyback
141    ServerSidePiggyback = 23,
142    /// One-way function
143    OnewayFn = 26,
144    /// Implicit resultset
145    ImplicitResultset = 27,
146    /// Renegotiate
147    Renegotiate = 28,
148    /// End of response marker
149    EndOfResponse = 29,
150    /// Token message
151    Token = 33,
152    /// Fast authentication
153    FastAuth = 34,
154}
155
156impl TryFrom<u8> for MessageType {
157    type Error = crate::error::Error;
158
159    fn try_from(value: u8) -> Result<Self, <Self as TryFrom<u8>>::Error> {
160        match value {
161            1 => Ok(MessageType::Protocol),
162            2 => Ok(MessageType::DataTypes),
163            3 => Ok(MessageType::Function),
164            4 => Ok(MessageType::Error),
165            6 => Ok(MessageType::RowHeader),
166            7 => Ok(MessageType::RowData),
167            8 => Ok(MessageType::Parameter),
168            9 => Ok(MessageType::Status),
169            11 => Ok(MessageType::IoVector),
170            14 => Ok(MessageType::LobData),
171            15 => Ok(MessageType::Warning),
172            16 => Ok(MessageType::DescribeInfo),
173            17 => Ok(MessageType::Piggyback),
174            19 => Ok(MessageType::FlushOutBinds),
175            21 => Ok(MessageType::BitVector),
176            23 => Ok(MessageType::ServerSidePiggyback),
177            26 => Ok(MessageType::OnewayFn),
178            27 => Ok(MessageType::ImplicitResultset),
179            28 => Ok(MessageType::Renegotiate),
180            29 => Ok(MessageType::EndOfResponse),
181            33 => Ok(MessageType::Token),
182            34 => Ok(MessageType::FastAuth),
183            _ => Err(crate::error::Error::InvalidMessageType(value)),
184        }
185    }
186}
187
188// =============================================================================
189// TTC Function Codes
190// =============================================================================
191
192/// TTC (Two-Task Common) function codes
193#[derive(Debug, Clone, Copy, PartialEq, Eq)]
194#[repr(u8)]
195pub enum FunctionCode {
196    /// Reexecute previous statement
197    Reexecute = 4,
198    /// Fetch rows
199    Fetch = 5,
200    /// Logoff from database
201    Logoff = 9,
202    /// Commit transaction
203    Commit = 14,
204    /// Rollback transaction
205    Rollback = 15,
206    /// Reexecute and fetch
207    ReexecuteAndFetch = 78,
208    /// Execute statement
209    Execute = 94,
210    /// LOB operation
211    LobOp = 96,
212    /// TPC transaction switch
213    TpcTxnSwitch = 103,
214    /// TPC transaction change state
215    TpcTxnChangeState = 104,
216    /// Close cursors
217    CloseCursors = 105,
218    /// Authentication phase one
219    AuthPhaseOne = 118,
220    /// Authentication phase two
221    AuthPhaseTwo = 115,
222    /// AQ enqueue
223    AqEnq = 121,
224    /// AQ dequeue
225    AqDeq = 122,
226    /// Direct path prepare
227    DirectPathPrepare = 128,
228    /// Direct path load stream
229    DirectPathLoadStream = 129,
230    /// Direct path operation
231    DirectPathOp = 130,
232    /// Set end-to-end attribute
233    SetEndToEndAttr = 135,
234    /// Array AQ
235    ArrayAq = 145,
236    /// Ping
237    Ping = 147,
238    /// Set schema
239    SetSchema = 152,
240    /// Session get
241    SessionGet = 162,
242    /// Session release
243    SessionRelease = 163,
244    /// Session state
245    SessionState = 176,
246    /// Pipeline begin
247    PipelineBegin = 199,
248    /// Pipeline end
249    PipelineEnd = 200,
250}
251
252// =============================================================================
253// Control Packet Types
254// =============================================================================
255
256/// Control packet type constants
257#[allow(missing_docs)]
258pub mod control_type {
259    pub const INBAND_NOTIFICATION: u16 = 8;
260    pub const RESET_OOB: u16 = 9;
261}
262
263// =============================================================================
264// Protocol Versions
265// =============================================================================
266
267/// Protocol version constants
268pub mod version {
269    /// Desired protocol version to request
270    pub const DESIRED: u16 = 319;
271    /// Minimum protocol version we support
272    pub const MINIMUM: u16 = 300;
273    /// Minimum accepted version (Oracle 12.1)
274    pub const MIN_ACCEPTED: u16 = 315;
275    /// Minimum version supporting large SDU
276    pub const MIN_LARGE_SDU: u16 = 315;
277    /// Minimum version supporting OOB check
278    pub const MIN_OOB_CHECK: u16 = 318;
279    /// Minimum version supporting end of response
280    pub const MIN_END_OF_RESPONSE: u16 = 319;
281}
282
283// =============================================================================
284// Connection Constants
285// =============================================================================
286
287/// Connection-related constants
288pub mod connection {
289    /// Default SDU (Session Data Unit) size
290    pub const DEFAULT_SDU: u16 = 8192;
291    /// Default TDU (Transport Data Unit) size
292    pub const DEFAULT_TDU: u16 = 65535;
293    /// Protocol characteristics flags
294    pub const PROTOCOL_CHARACTERISTICS: u16 = 0x4f98;
295    /// Check OOB flag
296    pub const CHECK_OOB: u32 = 0x01;
297    /// Maximum connect data that fits in first packet
298    pub const MAX_CONNECT_DATA: u16 = 230;
299}
300
301// =============================================================================
302// Service Options (GSO = Global Service Options)
303// =============================================================================
304
305/// Service options flags (GSO = Global Service Options)
306#[allow(missing_docs)]
307pub mod service_options {
308    pub const DONT_CARE: u16 = 0x0001;
309    pub const CAN_RECV_ATTENTION: u16 = 0x0400;
310}
311
312// =============================================================================
313// NSI (Network Session Interface) Flags
314// =============================================================================
315
316/// NSI (Network Session Interface) flags
317#[allow(missing_docs)]
318pub mod nsi_flags {
319    pub const DISABLE_NA: u8 = 0x04;
320    pub const NA_REQUIRED: u8 = 0x10;
321    pub const SUPPORT_SECURITY_RENEG: u8 = 0x80;
322}
323
324// =============================================================================
325// Accept Flags
326// =============================================================================
327
328/// Connection accept flags
329#[allow(missing_docs)]
330pub mod accept_flags {
331    pub const CHECK_OOB: u32 = 0x00000001;
332    pub const FAST_AUTH: u32 = 0x10000000;
333    pub const HAS_END_OF_RESPONSE: u32 = 0x02000000;
334}
335
336// =============================================================================
337// Authentication Modes
338// =============================================================================
339
340/// Authentication mode flags
341#[allow(missing_docs)]
342pub mod auth_mode {
343    pub const LOGON: u32 = 0x00000001;
344    pub const CHANGE_PASSWORD: u32 = 0x00000002;
345    pub const SYSDBA: u32 = 0x00000020;
346    pub const SYSOPER: u32 = 0x00000040;
347    pub const PRELIM: u32 = 0x00000080;
348    pub const WITH_PASSWORD: u32 = 0x00000100;
349    pub const SYSASM: u32 = 0x00400000;
350    pub const SYSBKP: u32 = 0x01000000;
351    pub const SYSDGD: u32 = 0x02000000;
352    pub const SYSKMT: u32 = 0x04000000;
353    pub const SYSRAC: u32 = 0x08000000;
354    pub const IAM_TOKEN: u32 = 0x20000000;
355}
356
357// =============================================================================
358// Verifier Types (for authentication)
359// =============================================================================
360
361/// Authentication verifier type constants
362#[allow(missing_docs)]
363pub mod verifier_type {
364    pub const V11G_1: u32 = 0xb152;
365    pub const V11G_2: u32 = 0x1b25;
366    pub const V12C: u32 = 0x4815;
367}
368
369// =============================================================================
370// Character Sets
371// =============================================================================
372
373/// Character set ID constants
374#[allow(missing_docs)]
375pub mod charset {
376    pub const AL16UTF8: u16 = 208;
377    pub const UTF8: u16 = 873;
378    pub const UTF16: u16 = 2000;
379}
380
381// =============================================================================
382// Compile-Time Capability Indices (CCAP)
383// =============================================================================
384
385/// Compile-time capability index constants
386#[allow(missing_docs)]
387pub mod ccap_index {
388    pub const SQL_VERSION: usize = 0;
389    pub const LOGON_TYPES: usize = 4;
390    pub const FEATURE_BACKPORT: usize = 5;
391    pub const FIELD_VERSION: usize = 7;
392    pub const SERVER_DEFINE_CONV: usize = 8;
393    pub const DEQUEUE_WITH_SELECTOR: usize = 9;
394    pub const TTC1: usize = 15;
395    pub const OCI1: usize = 16;
396    pub const TDS_VERSION: usize = 17;
397    pub const RPC_VERSION: usize = 18;
398    pub const RPC_SIG: usize = 19;
399    pub const DBF_VERSION: usize = 21;
400    pub const LOB: usize = 23;
401    pub const TTC2: usize = 26;
402    pub const UB2_DTY: usize = 27;
403    pub const OCI2: usize = 31;
404    pub const CLIENT_FN: usize = 34;
405    pub const OCI3: usize = 35;
406    pub const TTC3: usize = 37;
407    pub const SESS_SIGNATURE_VERSION: usize = 39;
408    pub const TTC4: usize = 40;
409    pub const LOB2: usize = 42;
410    pub const TTC5: usize = 44;
411    pub const VECTOR_FEATURES: usize = 52;
412    pub const MAX: usize = 53;
413}
414
415// =============================================================================
416// Compile-Time Capability Values (CCAP)
417// =============================================================================
418
419/// Compile-time capability value constants
420#[allow(missing_docs)]
421pub mod ccap_value {
422    pub const SQL_VERSION_MAX: u8 = 6;
423    pub const FIELD_VERSION_11_2: u8 = 6;
424    pub const FIELD_VERSION_12_1: u8 = 7;
425    pub const FIELD_VERSION_12_2: u8 = 8;
426    pub const FIELD_VERSION_18_1: u8 = 10;
427    pub const FIELD_VERSION_19_1: u8 = 12;
428    pub const FIELD_VERSION_21_1: u8 = 16;
429    pub const FIELD_VERSION_23_1: u8 = 17;
430    pub const FIELD_VERSION_23_4: u8 = 24;
431    pub const FIELD_VERSION_MAX: u8 = 24;
432
433    pub const O5LOGON: u8 = 8;
434    pub const O5LOGON_NP: u8 = 2;
435    pub const O7LOGON: u8 = 32;
436    pub const O8LOGON_LONG_IDENTIFIER: u8 = 64;
437    pub const O9LOGON_LONG_PASSWORD: u8 = 0x80;
438
439    pub const CTB_IMPLICIT_POOL: u8 = 0x08;
440    pub const CTB_OAUTH_MSG_ON_ERR: u8 = 0x10;
441
442    pub const END_OF_CALL_STATUS: u8 = 0x01;
443    pub const IND_RCD: u8 = 0x08;
444    pub const FAST_BVEC: u8 = 0x20;
445    pub const FAST_SESSION_PROPAGATE: u8 = 0x10;
446    pub const APP_CTX_PIGGYBACK: u8 = 0x80;
447
448    pub const TDS_VERSION_MAX: u8 = 3;
449    pub const RPC_VERSION_MAX: u8 = 7;
450    pub const RPC_SIG_VALUE: u8 = 3;
451    pub const DBF_VERSION_MAX: u8 = 1;
452    pub const CLIENT_FN_MAX: u8 = 12;
453
454    pub const LOB_UB8_SIZE: u8 = 0x01;
455    pub const LOB_ENCS: u8 = 0x02;
456    pub const LOB_PREFETCH_DATA: u8 = 0x04;
457    pub const LOB_TEMP_SIZE: u8 = 0x08;
458    pub const LOB_PREFETCH_LENGTH: u8 = 0x40;
459    pub const LOB_12C: u8 = 0x80;
460
461    pub const LOB2_QUASI: u8 = 0x01;
462    pub const LOB2_2GB_PREFETCH: u8 = 0x04;
463
464    pub const DRCP: u8 = 0x10;
465    pub const ZLNP: u8 = 0x04;
466    pub const INBAND_NOTIFICATION: u8 = 0x04;
467    pub const EXPLICIT_BOUNDARY: u8 = 0x40;
468    pub const END_OF_REQUEST: u8 = 0x20;
469
470    pub const LTXID: u8 = 0x08;
471    pub const IMPLICIT_RESULTS: u8 = 0x10;
472    pub const BIG_CHUNK_CLR: u8 = 0x20;
473    pub const KEEP_OUT_ORDER: u8 = 0x80;
474
475    // TTC5 flags
476    pub const VECTOR_SUPPORT: u8 = 0x08;
477    pub const TOKEN_SUPPORTED: u8 = 0x02;
478    pub const PIPELINING_SUPPORT: u8 = 0x04;
479    pub const PIPELINING_BREAK: u8 = 0x10;
480    pub const SESSIONLESS_TXNS: u8 = 0x20;
481
482    // Vector features
483    pub const VECTOR_FEATURE_BINARY: u8 = 0x01;
484    pub const VECTOR_FEATURE_SPARSE: u8 = 0x02;
485
486    // OCI3 flags
487    pub const OCI3_OCSSYNC: u8 = 0x20;
488}
489
490// =============================================================================
491// Runtime Capability Indices (RCAP)
492// =============================================================================
493
494/// Runtime capability index constants
495#[allow(missing_docs)]
496pub mod rcap_index {
497    pub const COMPAT: usize = 0;
498    pub const TTC: usize = 6;
499    pub const MAX: usize = 11;
500}
501
502// =============================================================================
503// Runtime Capability Values (RCAP)
504// =============================================================================
505
506/// Runtime capability value constants
507#[allow(missing_docs)]
508pub mod rcap_value {
509    pub const COMPAT_81: u8 = 2;
510    pub const TTC_ZERO_COPY: u8 = 0x01;
511    pub const TTC_32K: u8 = 0x04;
512    pub const TTC_SESSION_STATE_OPS: u8 = 0x10;
513}
514
515// =============================================================================
516// Encoding Flags
517// =============================================================================
518
519/// Character encoding flags
520#[allow(missing_docs)]
521pub mod encoding {
522    pub const MULTI_BYTE: u8 = 0x01;
523    pub const CONV_LENGTH: u8 = 0x02;
524}
525
526// =============================================================================
527// TNS Length Indicators
528// =============================================================================
529
530/// TNS length indicator constants
531pub mod length {
532    /// Maximum length that fits in a single byte
533    pub const MAX_SHORT: u8 = 252;
534    /// Escape character for special values
535    pub const ESCAPE_CHAR: u8 = 253;
536    /// Indicates a long (multi-byte) length follows
537    pub const LONG_INDICATOR: u8 = 254;
538    /// Indicates NULL value
539    pub const NULL_INDICATOR: u8 = 255;
540}
541
542// =============================================================================
543// Execute Options
544// =============================================================================
545
546/// Execute option flags
547#[allow(missing_docs)]
548pub mod exec_option {
549    pub const PARSE: u32 = 0x01;
550    pub const BIND: u32 = 0x08;
551    pub const DEFINE: u32 = 0x10;
552    pub const EXECUTE: u32 = 0x20;
553    pub const FETCH: u32 = 0x40;
554    pub const COMMIT: u32 = 0x100;
555    pub const COMMIT_REEXECUTE: u32 = 0x01;
556    pub const PLSQL_BIND: u32 = 0x400;
557    pub const NOT_PLSQL: u32 = 0x8000;
558    pub const DESCRIBE: u32 = 0x20000;
559    pub const NO_COMPRESSED_FETCH: u32 = 0x40000;
560    pub const BATCH_ERRORS: u32 = 0x80000;
561}
562
563// =============================================================================
564// Execute Flags
565// =============================================================================
566
567/// Execute flags for statement execution
568#[allow(missing_docs)]
569pub mod exec_flags {
570    pub const DML_ROWCOUNTS: u32 = 0x4000;
571    pub const IMPLICIT_RESULTSET: u32 = 0x8000;
572    pub const NO_CANCEL_ON_EOF: u32 = 0x80;
573    pub const SCROLLABLE: u32 = 0x02;
574}
575
576// =============================================================================
577// Fetch Orientation (for scrollable cursors)
578// =============================================================================
579
580/// Fetch orientation for scrollable cursor operations
581#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
582#[repr(u32)]
583pub enum FetchOrientation {
584    /// Fetch current row
585    Current = 0x01,
586    /// Fetch next row (default)
587    #[default]
588    Next = 0x02,
589    /// Fetch first row
590    First = 0x04,
591    /// Fetch last row
592    Last = 0x08,
593    /// Fetch previous row
594    Prior = 0x10,
595    /// Fetch absolute position
596    Absolute = 0x20,
597    /// Fetch relative to current position
598    Relative = 0x40,
599}
600
601// =============================================================================
602// Bind Directions
603// =============================================================================
604
605/// Bind parameter direction constants (wire format values)
606pub mod bind_dir {
607    /// Output only parameter (server writes, client reads)
608    pub const OUTPUT: u8 = 16;
609    /// Input only parameter (client writes, server reads)
610    pub const INPUT: u8 = 32;
611    /// Input/Output parameter (bidirectional)
612    pub const INPUT_OUTPUT: u8 = 48;
613}
614
615// =============================================================================
616// Oracle Data Types (ORA_TYPE_NUM)
617// =============================================================================
618
619/// Oracle internal data type numbers
620#[derive(Debug, Clone, Copy, PartialEq, Eq)]
621#[repr(u8)]
622pub enum OracleType {
623    /// VARCHAR2 string type
624    Varchar = 1,
625    /// NUMBER type
626    Number = 2,
627    /// BINARY_INTEGER (PL/SQL)
628    BinaryInteger = 3,
629    /// LONG string type
630    Long = 8,
631    /// ROWID
632    Rowid = 11,
633    /// DATE type
634    Date = 12,
635    /// RAW binary type
636    Raw = 23,
637    /// LONG RAW binary type
638    LongRaw = 24,
639    /// CHAR fixed-length string
640    Char = 96,
641    /// BINARY_FLOAT
642    BinaryFloat = 100,
643    /// BINARY_DOUBLE
644    BinaryDouble = 101,
645    /// REF CURSOR
646    Cursor = 102,
647    /// User-defined object type
648    Object = 109,
649    /// CLOB
650    Clob = 112,
651    /// BLOB
652    Blob = 113,
653    /// BFILE
654    Bfile = 114,
655    /// JSON (21c+)
656    Json = 119,
657    /// VECTOR (23ai)
658    Vector = 127,
659    /// TIMESTAMP
660    Timestamp = 180,
661    /// TIMESTAMP WITH TIME ZONE
662    TimestampTz = 181,
663    /// INTERVAL YEAR TO MONTH
664    IntervalYm = 182,
665    /// INTERVAL DAY TO SECOND
666    IntervalDs = 183,
667    /// UROWID
668    Urowid = 208,
669    /// TIMESTAMP WITH LOCAL TIME ZONE
670    TimestampLtz = 231,
671    /// BOOLEAN (23c+)
672    Boolean = 252,
673}
674
675impl OracleType {
676    /// Check if this type is a LOB type that requires special define handling
677    pub fn is_lob(&self) -> bool {
678        matches!(
679            self,
680            OracleType::Clob | OracleType::Blob | OracleType::Bfile | OracleType::Json | OracleType::Vector
681        )
682    }
683
684    /// Check if this type requires no prefetch (data must be fetched separately)
685    pub fn requires_no_prefetch(&self) -> bool {
686        matches!(
687            self,
688            OracleType::Clob | OracleType::Blob | OracleType::Json | OracleType::Vector
689        )
690    }
691}
692
693impl TryFrom<u8> for OracleType {
694    type Error = crate::error::Error;
695
696    fn try_from(value: u8) -> Result<Self, Self::Error> {
697        match value {
698            1 => Ok(OracleType::Varchar),
699            2 => Ok(OracleType::Number),
700            3 => Ok(OracleType::BinaryInteger),
701            8 => Ok(OracleType::Long),
702            11 => Ok(OracleType::Rowid),
703            12 => Ok(OracleType::Date),
704            23 => Ok(OracleType::Raw),
705            24 => Ok(OracleType::LongRaw),
706            96 => Ok(OracleType::Char),
707            100 => Ok(OracleType::BinaryFloat),
708            101 => Ok(OracleType::BinaryDouble),
709            102 => Ok(OracleType::Cursor),
710            109 => Ok(OracleType::Object),
711            112 => Ok(OracleType::Clob),
712            113 => Ok(OracleType::Blob),
713            114 => Ok(OracleType::Bfile),
714            119 => Ok(OracleType::Json),
715            127 => Ok(OracleType::Vector),
716            180 => Ok(OracleType::Timestamp),
717            181 => Ok(OracleType::TimestampTz),
718            182 => Ok(OracleType::IntervalYm),
719            183 => Ok(OracleType::IntervalDs),
720            208 => Ok(OracleType::Urowid),
721            231 => Ok(OracleType::TimestampLtz),
722            252 => Ok(OracleType::Boolean),
723            _ => Err(crate::error::Error::InvalidOracleType(value)),
724        }
725    }
726}
727
728// =============================================================================
729// Character Set Form (CSFRM)
730// =============================================================================
731
732/// Character set form (CSFRM) constants
733pub mod csfrm {
734    /// Implicit charset (database charset)
735    pub const IMPLICIT: u8 = 1;
736    /// NCHAR charset
737    pub const NCHAR: u8 = 2;
738}
739
740// =============================================================================
741// Miscellaneous Constants
742// =============================================================================
743
744/// Maximum length for LONG/LONG RAW columns
745pub const MAX_LONG_LENGTH: u32 = 0x7FFFFFFF;
746
747/// Maximum length for UROWID
748pub const MAX_UROWID_LENGTH: u32 = 5267;
749
750/// Bind indicator flags
751#[allow(missing_docs)]
752pub mod bind_flags {
753    pub const USE_INDICATORS: u8 = 0x01;
754    pub const ARRAY: u8 = 0x40;
755}
756
757/// Bind parameter direction (IN, OUT, IN OUT)
758#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
759#[repr(u8)]
760pub enum BindDirection {
761    /// Output only parameter (server writes, client reads)
762    Output = 16,
763    /// Input only parameter (client writes, server reads) - default
764    #[default]
765    Input = 32,
766    /// Input/Output parameter (bidirectional)
767    InputOutput = 48,
768}
769
770impl BindDirection {
771    /// Check if this direction includes input (IN or IN OUT)
772    pub fn is_input(&self) -> bool {
773        matches!(self, BindDirection::Input | BindDirection::InputOutput)
774    }
775
776    /// Check if this direction includes output (OUT or IN OUT)
777    pub fn is_output(&self) -> bool {
778        matches!(self, BindDirection::Output | BindDirection::InputOutput)
779    }
780
781    /// Create from wire value
782    pub fn from_wire(value: u8) -> Option<Self> {
783        match value {
784            16 => Some(BindDirection::Output),
785            32 => Some(BindDirection::Input),
786            48 => Some(BindDirection::InputOutput),
787            _ => None,
788        }
789    }
790}
791
792impl TryFrom<u8> for BindDirection {
793    type Error = crate::error::Error;
794
795    fn try_from(value: u8) -> Result<Self, Self::Error> {
796        BindDirection::from_wire(value)
797            .ok_or_else(|| crate::error::Error::Protocol(format!("Invalid bind direction: {}", value)))
798    }
799}
800
801/// LOB-related flags and constants
802#[allow(missing_docs)]
803pub mod lob_flags {
804    /// LOB prefetch flag for cont_flag field
805    pub const PREFETCH: u64 = 0x2000000;
806
807    // LOB locator offsets
808    pub const LOC_OFFSET_FLAG_1: usize = 4;
809    pub const LOC_OFFSET_FLAG_3: usize = 6;
810    pub const LOC_OFFSET_FLAG_4: usize = 7;
811    pub const LOC_FIXED_OFFSET: usize = 16;
812    pub const QLOCATOR_VERSION: u8 = 4;
813
814    // LOB locator flags (byte 1 at offset 4)
815    pub const LOC_FLAGS_BLOB: u8 = 0x01;
816    pub const LOC_FLAGS_VALUE_BASED: u8 = 0x20;
817    pub const LOC_FLAGS_ABSTRACT: u8 = 0x40;
818
819    // LOB locator flags (byte 2 at offset 5)
820    pub const LOC_FLAGS_INIT: u8 = 0x08;
821
822    // LOB locator flags (byte 4 at offset 7)
823    pub const LOC_FLAGS_TEMP: u8 = 0x01;
824    pub const LOC_FLAGS_VAR_LENGTH_CHARSET: u8 = 0x80;
825
826    // LOB open modes
827    pub const OPEN_READ_WRITE: u8 = 2;
828    pub const OPEN_READ_ONLY: u8 = 11;
829
830    // LOB buffer size (for locator metadata)
831    pub const BUFFER_SIZE: u32 = 112;
832}
833
834/// LOB operation codes (for function code 96)
835#[allow(missing_docs)]
836pub mod lob_op {
837    pub const GET_LENGTH: u32 = 0x0001;
838    pub const READ: u32 = 0x0002;
839    pub const TRIM: u32 = 0x0020;
840    pub const WRITE: u32 = 0x0040;
841    pub const GET_CHUNK_SIZE: u32 = 0x4000;
842    pub const CREATE_TEMP: u32 = 0x0110;
843    pub const FREE_TEMP: u32 = 0x0111;
844    pub const OPEN: u32 = 0x8000;
845    pub const CLOSE: u32 = 0x10000;
846    pub const IS_OPEN: u32 = 0x11000;
847    pub const ARRAY: u32 = 0x80000;
848    pub const FILE_EXISTS: u32 = 0x0800;
849    pub const FILE_OPEN: u32 = 0x0100;
850    pub const FILE_CLOSE: u32 = 0x0200;
851    pub const FILE_ISOPEN: u32 = 0x0400;
852}
853
854/// LOB duration constants
855pub mod lob_duration {
856    /// Session duration for temporary LOBs
857    pub const SESSION: u64 = 10;
858}
859
860// =============================================================================
861// Database Object / Collection Constants
862// =============================================================================
863
864/// Object/Collection flags and constants
865pub mod obj_flags {
866    /// Object is version 8.1 format
867    pub const IS_VERSION_81: u8 = 0x80;
868    /// Object is degenerate (no data)
869    pub const IS_DEGENERATE: u8 = 0x10;
870    /// Object is a collection
871    pub const IS_COLLECTION: u8 = 0x08;
872    /// No prefix segment
873    pub const NO_PREFIX_SEG: u8 = 0x04;
874    /// Current image version
875    pub const IMAGE_VERSION: u8 = 1;
876    /// Maximum short length for pickle encoding
877    pub const MAX_SHORT_LENGTH: u8 = 245;
878    /// Atomic NULL indicator
879    pub const ATOMIC_NULL: u8 = 253;
880    /// Non-null OID flag
881    pub const NON_NULL_OID: u8 = 0x02;
882    /// Has extent OID
883    pub const HAS_EXTENT_OID: u8 = 0x08;
884    /// Top level object
885    pub const TOP_LEVEL: u8 = 0x01;
886    /// Has indexes (for associative arrays)
887    pub const HAS_INDEXES: u8 = 0x10;
888    /// TOID prefix bytes (version/marker)
889    pub const TOID_PREFIX: [u8; 2] = [0x00, 0x22];
890    /// Extent OID (16 bytes) - appended to TOID after type OID
891    pub const EXTENT_OID: [u8; 16] = [
892        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
893        0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01,
894    ];
895}
896
897/// Collection type codes
898pub mod collection_type {
899    /// PL/SQL INDEX BY table (associative array)
900    pub const PLSQL_INDEX_TABLE: u8 = 1;
901    /// Nested table
902    pub const NESTED_TABLE: u8 = 2;
903    /// VARRAY
904    pub const VARRAY: u8 = 3;
905}
906
907/// TDS (Type Descriptor Set) type codes for object elements
908#[allow(missing_docs)]
909pub mod tds_type {
910    pub const CHAR: u8 = 1;
911    pub const DATE: u8 = 2;
912    pub const FLOAT: u8 = 5;
913    pub const NUMBER: u8 = 6;
914    pub const VARCHAR: u8 = 7;
915    pub const BOOLEAN: u8 = 8;
916    pub const RAW: u8 = 19;
917    pub const TIMESTAMP: u8 = 21;
918    pub const TIMESTAMP_TZ: u8 = 23;
919    pub const OBJ: u8 = 27;
920    pub const COLL: u8 = 28;
921    pub const CLOB: u8 = 29;
922    pub const BLOB: u8 = 30;
923    pub const TIMESTAMP_LTZ: u8 = 33;
924    pub const BINARY_FLOAT: u8 = 37;
925    pub const BINARY_DOUBLE: u8 = 38;
926    pub const START_EMBED_ADT: u8 = 39;
927    pub const BINARY_INTEGER: u8 = 47;
928    pub const UROWID: u8 = 104;
929    pub const INTERVAL_DS: u8 = 119;
930    pub const INTERVAL_YM: u8 = 120;
931}
932
933// =============================================================================
934// Error Codes
935// =============================================================================
936
937/// Oracle error code constants
938#[allow(missing_docs)]
939pub mod error_code {
940    pub const INCONSISTENT_DATA_TYPES: u32 = 932;
941    pub const VAR_NOT_IN_SELECT_LIST: u32 = 1007;
942    pub const NO_DATA_FOUND: u32 = 1403;
943    pub const EXCEEDED_IDLE_TIME: u32 = 2396;
944    pub const INVALID_SID: u32 = 12505;
945    pub const INVALID_SERVICE_NAME: u32 = 12514;
946    pub const SESSION_SHUTDOWN: u32 = 12572;
947    pub const INBAND_MESSAGE: u32 = 12573;
948    pub const ARRAY_DML_ERRORS: u32 = 24381;
949    pub const NO_MESSAGES_FOUND: u32 = 25228;
950}
951
952// =============================================================================
953// Packet Header
954// =============================================================================
955
956/// TNS packet header size in bytes
957pub const PACKET_HEADER_SIZE: usize = 8;
958
959#[cfg(test)]
960mod tests {
961    use super::*;
962
963    #[test]
964    fn test_packet_type_conversion() {
965        assert_eq!(PacketType::try_from(1).unwrap(), PacketType::Connect);
966        assert_eq!(PacketType::try_from(2).unwrap(), PacketType::Accept);
967        assert_eq!(PacketType::try_from(6).unwrap(), PacketType::Data);
968        assert!(PacketType::try_from(255).is_err());
969    }
970
971    #[test]
972    fn test_message_type_conversion() {
973        assert_eq!(MessageType::try_from(1).unwrap(), MessageType::Protocol);
974        assert_eq!(MessageType::try_from(3).unwrap(), MessageType::Function);
975        assert_eq!(MessageType::try_from(34).unwrap(), MessageType::FastAuth);
976        assert!(MessageType::try_from(255).is_err());
977    }
978
979    #[test]
980    fn test_packet_type_repr() {
981        assert_eq!(PacketType::Connect as u8, 1);
982        assert_eq!(PacketType::Accept as u8, 2);
983        assert_eq!(PacketType::Data as u8, 6);
984    }
985}