Skip to content

iliasaz/SwiftOracle

 
 

Repository files navigation

SwiftOracle

OCILIB wrapper for Swift, linux compatible

New in this release

  • Added support for REF Cursors. See an example below.
  • Added a layer of "swifty" objects - SwiftyField, SwiftyRow. This is still work in progress.

New in previous release

  • Added array binding (BindVarArray)
  • Added executeBulkDML that uses arrays of bind variables in DMLs for greatly improved performance
  • Added connection and sesssion pooling
  • Added Bindvar stringValue representation
  • Added Date support;
  • Added prefetchSize in cursor.execute to support efficient data transfers
  • Added a dependency on C bridge to OCILIB (swift 5 compatible)

This is wrapper for ocilib (https://github.com/vrogier/ocilib).

Installation (1) Installing Oracle Instant Client
Download Basic package (zip) and SDK package (zip) for your platform from https://www.oracle.com/database/technologies/instant-client/downloads.html

Unzip both into one directory, ex. /Users/me/instantclient_19_8. This will be your ORACLE_HOME.
Set environment variables:
export ORACLE_HOME=/Users/me/instantclient_19_8
export TNS_ADMIN=$ORACLE_HOME/network/admin
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$ORACLE_HOME
export PATH=$PATH:$ORACLE_HOME

(2) Make sure you have C compiler installed

(3) Installing OCILIB
git clone https://github.com/vrogier/ocilib.git
cd ocilib
./configure --with-oracle-home=$ORACLE_HOME --with-oracle-lib-path=$ORACLE_HOME --with-oracle-headers-path=$ORACLE_HOME/sdk/include --disable-dependency-tracking
make
chmod 755 config/install-sh
sudo make install

Make sure there are no errors in either of these steps (warning are OK.)

(4) If using SwiftOracle with SPM, make sure to set LD_LIBRARY_PATH as above and also include linker flags, ex., -Xlinker -L/usr/local/lib

(5) If using Xcode, set the following project Build Settings:

Header Search Paths -> /Users/me/instantclient_19_8/sdk/include, /usr/local/include.
Library Search Paths -> /Users/me/instantclient_19_8, /usr/local/lib.
Runpath Search Paths -> /Users/me/instantclient_19_8.

PR are welcome.

Here is what you can do:

let service = OracleService(host: "dv", port:"1521", service: "xe")

let b = Connection(service: service, user:"broq", pwd:"anypassword")

try b.open()
b.autocommit = true


let cursor = try b.cursor()

try cursor.execute("select * from users where login=:login or 1=1", params: ["login": "user2"])
for r in cursor {
    print(r.dict)
    print(r.list)
    print(r["LOGIN"]!.string)
    print(r["ID"]!.int)
}

try cursor.execute("select * from sources where id=:id", params: ["id": 3])
for r in cursor {
    print(r)
}
try cursor.execute("select * from sources where reverse_enabled=:ids or 1=1", params: ["ids": 1.0 ])
for r in cursor {
    print(r["OWNER"]! as? String)
    print(r)
}

try cursor.execute("insert into users (id, login, alive) values (USERS_ID_SEQ.nextval, :2, :3) RETURNING id INTO :id ", params: ["2": "фіва", "3": 3,], register: ["id": .int])
cursor.register("id", type: .int)

for r in cursor {
    print(r)
}

print(cursor.affected)

REF Cursor example

import Foundation
import SwiftOracle

// Create a DB stored function that returns a REF cursor
/* 
 create or replace function get_refcursor(i_type in varchar2, i_maxrows in number) return sys_refcursor as
 cv sys_refcursor;
 begin
 open cv for select object_name, object_id from user_objects where object_type = i_type and rownum <= i_maxrows;
 return cv;
 end;
 /
*/
 
let service = OracleService(from_string: "test_database")
let conn = Connection(service: service, user: "user", pwd: "password")
let sql = "select level as rnum, get_refcursor('PACKAGE', level) as cv from dual connect by level < 6"

try conn.open()
let mainCursor = try conn.cursor()
try mainCursor.execute(sql)
print("executed main cursor")

for r in mainCursor {
    print("main cursor row number: \(r["RNUM"]!.int)")
    let cursorPtr = r["CV"]!.cursor
    let cur = try conn.cursor(statementPtr: cursorPtr)
    try cur.executePreparedStatement()
    print("printing child cursor output")
    for r1 in cur {
        print("object_name: \(r1["OBJECT_NAME"]!.string), object_id: \(r1["OBJECT_ID"]!.int)")
    }
}

About

OCILIB wrapper for Swift, linux compatible

Resources

Stars

Watchers

Forks

Packages

No packages published

Languages

  • Swift 100.0%