257 lines
		
	
	
		
			7.7 KiB
		
	
	
	
		
			Factor
		
	
	
			
		
		
	
	
			257 lines
		
	
	
		
			7.7 KiB
		
	
	
	
		
			Factor
		
	
	
! Copyright (C) 2007 Elie CHAFTARI
 | 
						|
! See http://factorcode.org/license.txt for BSD license.
 | 
						|
!
 | 
						|
! Adapted from oci.h and ociap.h
 | 
						|
! Tested with Oracle version - 10.1.0.3 Instant Client
 | 
						|
 | 
						|
USING: alien alien.c-types combinators kernel math namespaces oracle.liboci
 | 
						|
prettyprint sequences ;
 | 
						|
 | 
						|
IN: oracle
 | 
						|
 | 
						|
SYMBOL: env
 | 
						|
SYMBOL: err
 | 
						|
SYMBOL: srv
 | 
						|
SYMBOL: svc
 | 
						|
SYMBOL: ses
 | 
						|
SYMBOL: stm
 | 
						|
SYMBOL: buf
 | 
						|
SYMBOL: res
 | 
						|
 | 
						|
SYMBOL: con
 | 
						|
 | 
						|
TUPLE: connection username password db ;
 | 
						|
 | 
						|
C: <connection> connection
 | 
						|
 | 
						|
! =========================================================
 | 
						|
! Error-handling routines
 | 
						|
! =========================================================
 | 
						|
 | 
						|
: get-oci-error ( object -- * )
 | 
						|
    1 f "uint*" <c-object> dup >r 512 "uchar" <c-array> dup >r
 | 
						|
    512 OCI_HTYPE_ERROR OCIErrorGet r> r> *uint drop
 | 
						|
    alien>char-string throw ;
 | 
						|
 | 
						|
: check-result ( result -- )
 | 
						|
    {
 | 
						|
        { [ dup OCI_SUCCESS = ] [ drop ] }
 | 
						|
        { [ dup OCI_ERROR = ] [ err get get-oci-error ] }
 | 
						|
        { [ dup OCI_INVALID_HANDLE = ] [ "invalid handle" throw ] }
 | 
						|
        { [ t ] [ "operation failed" throw ] }
 | 
						|
    } cond ;
 | 
						|
 | 
						|
: check-status ( status -- bool )
 | 
						|
    {
 | 
						|
        { [ dup OCI_SUCCESS = ] [ drop t ] }
 | 
						|
        { [ dup OCI_ERROR = ] [ err get get-oci-error ] }
 | 
						|
        { [ dup OCI_INVALID_HANDLE = ] [ "invalid handle" throw ] }
 | 
						|
        { [ dup OCI_NO_DATA = ] [ drop f ] }
 | 
						|
        { [ t ] [ "operation failed" throw ] }
 | 
						|
    } cond ;
 | 
						|
 | 
						|
! =========================================================
 | 
						|
! Initialization and handle-allocation routines
 | 
						|
! =========================================================
 | 
						|
 | 
						|
! Legacy initialization routine
 | 
						|
: oci-initialize ( -- )
 | 
						|
    OCI_DEFAULT f f f f OCIInitialize check-result ;
 | 
						|
 | 
						|
! Legacy initialization routine
 | 
						|
: oci-env-init ( -- )
 | 
						|
    "void*" <c-object> dup OCI_DEFAULT 0 f OCIEnvInit
 | 
						|
    check-result *void* env set ;
 | 
						|
 | 
						|
: create-environment ( -- )
 | 
						|
    "void*" <c-object> dup OCI_DEFAULT f f f f 0 f OCIEnvCreate 
 | 
						|
    check-result *void* env set ;
 | 
						|
 | 
						|
: allocate-error-handle ( -- )
 | 
						|
    env get
 | 
						|
    "void*" <c-object> tuck OCI_HTYPE_ERROR 0 f OCIHandleAlloc 
 | 
						|
    check-result *void* err set ;
 | 
						|
 | 
						|
: allocate-service-handle ( -- )
 | 
						|
    env get
 | 
						|
    "void*" <c-object> tuck OCI_HTYPE_SVCCTX 0 f OCIHandleAlloc 
 | 
						|
    check-result *void* svc set ;
 | 
						|
 | 
						|
: allocate-session-handle ( -- )
 | 
						|
    env get
 | 
						|
    "void*" <c-object> tuck OCI_HTYPE_SESSION 0 f OCIHandleAlloc 
 | 
						|
    check-result *void* ses set ;
 | 
						|
 | 
						|
: allocate-server-handle ( -- )
 | 
						|
    env get
 | 
						|
    "void*" <c-object> tuck OCI_HTYPE_SERVER 0 f OCIHandleAlloc 
 | 
						|
    check-result *void* srv set ;
 | 
						|
 | 
						|
: init ( -- )
 | 
						|
    oci-initialize
 | 
						|
    oci-env-init
 | 
						|
    allocate-error-handle
 | 
						|
    allocate-service-handle
 | 
						|
    allocate-session-handle
 | 
						|
    allocate-server-handle ;
 | 
						|
 | 
						|
! =========================================================
 | 
						|
! Single user session logon routine
 | 
						|
! =========================================================
 | 
						|
 | 
						|
: oci-log-on ( -- )
 | 
						|
    env get err get svc get 
 | 
						|
    con get connection-username dup length swap malloc-char-string swap 
 | 
						|
    con get connection-password dup length swap malloc-char-string swap
 | 
						|
    con get connection-db dup length swap malloc-char-string swap
 | 
						|
    OCILogon check-result ;
 | 
						|
 | 
						|
! =========================================================
 | 
						|
! Attach to server and attribute-setting routines
 | 
						|
! =========================================================
 | 
						|
 | 
						|
: attach-to-server ( -- )
 | 
						|
    srv get err get con get connection-db dup length OCI_DEFAULT
 | 
						|
    OCIServerAttach check-result ;
 | 
						|
 | 
						|
: set-service-attribute ( -- )
 | 
						|
    svc get OCI_HTYPE_SVCCTX srv get 0 OCI_ATTR_SERVER err get OCIAttrSet check-result ;
 | 
						|
 | 
						|
: set-username-attribute ( -- )
 | 
						|
    ses get OCI_HTYPE_SESSION con get connection-username dup length swap malloc-char-string swap 
 | 
						|
    OCI_ATTR_USERNAME err get OCIAttrSet check-result ;
 | 
						|
 | 
						|
: set-password-attribute ( -- )
 | 
						|
    ses get OCI_HTYPE_SESSION con get connection-password dup length swap malloc-char-string swap 
 | 
						|
    OCI_ATTR_PASSWORD err get OCIAttrSet check-result ;
 | 
						|
 | 
						|
: set-attributes ( -- )
 | 
						|
    set-service-attribute
 | 
						|
    set-username-attribute
 | 
						|
    set-password-attribute ;
 | 
						|
 | 
						|
! =========================================================
 | 
						|
! Session startup routines
 | 
						|
! =========================================================
 | 
						|
 | 
						|
: begin-session ( -- )
 | 
						|
    svc get err get ses get OCI_CRED_RDBMS OCI_DEFAULT OCISessionBegin check-result ;
 | 
						|
 | 
						|
: set-authentication-handle ( -- )
 | 
						|
    svc get OCI_HTYPE_SVCCTX ses get 0 OCI_ATTR_SESSION err get OCIAttrSet check-result ;
 | 
						|
 | 
						|
! =========================================================
 | 
						|
! Statement preparation and execution routines
 | 
						|
! =========================================================
 | 
						|
 | 
						|
: allocate-statement-handle ( -- )
 | 
						|
    env get
 | 
						|
    "void*" <c-object> tuck OCI_HTYPE_STMT 0 f OCIHandleAlloc 
 | 
						|
    check-result *void* stm set ;
 | 
						|
 | 
						|
: prepare-statement ( statement -- )
 | 
						|
    >r stm get err get r> dup length swap malloc-char-string swap
 | 
						|
    OCI_NTV_SYNTAX OCI_DEFAULT OCIStmtPrepare check-result ;
 | 
						|
 | 
						|
: calculate-size ( type -- size object )
 | 
						|
    {
 | 
						|
        { [ dup SQLT_INT = ] [ "int" heap-size ] }
 | 
						|
        { [ dup SQLT_FLT = ] [ "float" heap-size ] }
 | 
						|
        { [ dup SQLT_CHR = ] [ "char" heap-size ] }
 | 
						|
        { [ dup SQLT_NUM = ] [ "int" heap-size 10 * ] }
 | 
						|
        { [ dup SQLT_STR = ] [ 64 ] }
 | 
						|
        { [ dup SQLT_ODT = ] [ 256 ] }
 | 
						|
    } cond ;
 | 
						|
 | 
						|
: define-by-position ( position type -- )
 | 
						|
    >r >r stm get f <void*> err get
 | 
						|
    r> r> calculate-size swap >r [ "char" malloc-array dup buf set ] keep 1+
 | 
						|
    r> f f f OCI_DEFAULT OCIDefineByPos check-result ;
 | 
						|
 | 
						|
: execute-statement ( -- bool )
 | 
						|
    svc get stm get err get 1 0 f f OCI_DEFAULT OCIStmtExecute check-status ;
 | 
						|
 | 
						|
: fetch-statement ( -- bool )
 | 
						|
    stm get err get 1 OCI_FETCH_NEXT OCI_DEFAULT OCIStmtFetch check-status ;
 | 
						|
 | 
						|
: free-statement-handle ( -- )
 | 
						|
    stm get OCI_HTYPE_STMT OCIHandleFree check-result ;
 | 
						|
 | 
						|
! =========================================================
 | 
						|
! Log off and detach from server routines
 | 
						|
! =========================================================
 | 
						|
 | 
						|
: end-session ( -- )
 | 
						|
    svc get err get ses get OCI_DEFAULT OCISessionEnd check-result ;
 | 
						|
 | 
						|
: detach-from-server ( -- )
 | 
						|
    srv get err get OCI_DEFAULT OCIServerDetach check-result ;
 | 
						|
 | 
						|
: log-off ( -- )
 | 
						|
    end-session
 | 
						|
    detach-from-server ;
 | 
						|
 | 
						|
! =========================================================
 | 
						|
! Clean-up and termination routines
 | 
						|
! =========================================================
 | 
						|
 | 
						|
: free-service-handle ( -- )
 | 
						|
    svc get OCI_HTYPE_SVCCTX OCIHandleFree check-result ;
 | 
						|
 | 
						|
: free-server-handle ( -- )
 | 
						|
    srv get OCI_HTYPE_SERVER OCIHandleFree check-result ;
 | 
						|
 | 
						|
: free-error-handle ( -- )
 | 
						|
    err get OCI_HTYPE_ERROR OCIHandleFree check-result ;
 | 
						|
 | 
						|
: free-environment-handle ( -- )
 | 
						|
    env get OCI_HTYPE_ENV OCIHandleFree check-result ;
 | 
						|
 | 
						|
: clean-up ( -- )
 | 
						|
    free-service-handle
 | 
						|
    free-server-handle
 | 
						|
    free-error-handle
 | 
						|
    free-environment-handle ;
 | 
						|
 | 
						|
: terminate ( -- )
 | 
						|
    OCI_DEFAULT OCITerminate check-result ;
 | 
						|
 | 
						|
! =========================================================
 | 
						|
! Utility routines
 | 
						|
! =========================================================
 | 
						|
 | 
						|
: server-version ( -- )
 | 
						|
    srv get err get 512 "uchar" malloc-array dup >r 512 OCI_HTYPE_SERVER
 | 
						|
    OCIServerVersion check-result r> alien>char-string . ;
 | 
						|
 | 
						|
! =========================================================
 | 
						|
! Public routines
 | 
						|
! =========================================================
 | 
						|
 | 
						|
: log-on ( username password db -- )
 | 
						|
    <connection> con set 
 | 
						|
    init attach-to-server set-attributes
 | 
						|
    begin-session set-authentication-handle 
 | 
						|
    V{ } clone res set ;
 | 
						|
 | 
						|
: fetch-each ( object -- object )
 | 
						|
    fetch-statement [
 | 
						|
        buf get alien>char-string res get swap add res set
 | 
						|
        fetch-each
 | 
						|
    ] [ ] if ;
 | 
						|
 | 
						|
: run-query ( object -- object )
 | 
						|
    execute-statement [
 | 
						|
        buf get alien>char-string res get swap add res set
 | 
						|
        fetch-each
 | 
						|
    ] [ ] if ;
 | 
						|
 | 
						|
: gather-results ( -- seq )
 | 
						|
    res get ;
 | 
						|
 | 
						|
: show-result ( -- )
 | 
						|
    res get [ . ] each ;
 | 
						|
 | 
						|
: clear-result ( -- )
 | 
						|
    V{ } clone res set ;
 |