258 lines
		
	
	
		
			7.5 KiB
		
	
	
	
		
			Factor
		
	
	
			
		
		
	
	
			258 lines
		
	
	
		
			7.5 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 alien.strings combinators kernel math
 | |
| namespaces oracle.liboci prettyprint sequences
 | |
| io.encodings.ascii accessors ;
 | |
| 
 | |
| 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
 | |
|     ascii alien>string throw ;
 | |
| 
 | |
| : check-result ( result -- )
 | |
|     {
 | |
|         { OCI_SUCCESS [ ] }
 | |
|         { OCI_ERROR [ err get get-oci-error ] }
 | |
|         { OCI_INVALID_HANDLE [ "invalid handle" throw ] }
 | |
|         [ "operation failed" throw ]
 | |
|     } case ;
 | |
| 
 | |
| : check-status ( status -- bool )
 | |
|     {
 | |
|         { OCI_SUCCESS [ t ] }
 | |
|         { OCI_ERROR [ err get get-oci-error ] }
 | |
|         { OCI_INVALID_HANDLE [ "invalid handle" throw ] }
 | |
|         { OCI_NO_DATA [ f ] }
 | |
|         [ "operation failed" throw ]
 | |
|     } case ;
 | |
| 
 | |
| ! =========================================================
 | |
| ! 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 username>> dup length swap ascii malloc-string swap 
 | |
|     con get password>> dup length swap ascii malloc-string swap
 | |
|     con get db>> dup length swap ascii malloc-string swap
 | |
|     OCILogon check-result ;
 | |
| 
 | |
| ! =========================================================
 | |
| ! Attach to server and attribute-setting routines
 | |
| ! =========================================================
 | |
| 
 | |
| : attach-to-server ( -- )
 | |
|     srv get err get con get 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 username>> dup length swap ascii malloc-string swap 
 | |
|     OCI_ATTR_USERNAME err get OCIAttrSet check-result ;
 | |
| 
 | |
| : set-password-attribute ( -- )
 | |
|     ses get OCI_HTYPE_SESSION con get password>> dup length swap ascii malloc-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 ascii malloc-string swap
 | |
|     OCI_NTV_SYNTAX OCI_DEFAULT OCIStmtPrepare check-result ;
 | |
| 
 | |
| : calculate-size ( type -- size )
 | |
|     {
 | |
|         { SQLT_INT [ "int" heap-size ] }
 | |
|         { SQLT_FLT [ "float" heap-size ] }
 | |
|         { SQLT_CHR [ "char" heap-size ] }
 | |
|         { SQLT_NUM [ "int" heap-size 10 * ] }
 | |
|         { SQLT_STR [ 64 ] }
 | |
|         { SQLT_ODT [ 256 ] }
 | |
|     } case ;
 | |
| 
 | |
| : define-by-position ( position type -- )
 | |
|     >r >r stm get f <void*> err get
 | |
|     r> r> dup calculate-size >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> ascii alien>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 ascii alien>string res get swap suffix res set
 | |
|         fetch-each
 | |
|     ] [ ] if ;
 | |
| 
 | |
| : run-query ( object -- object )
 | |
|     execute-statement [
 | |
|         buf get ascii alien>string res get swap suffix res set
 | |
|         fetch-each
 | |
|     ] [ ] if ;
 | |
| 
 | |
| : gather-results ( -- seq )
 | |
|     res get ;
 | |
| 
 | |
| : show-result ( -- )
 | |
|     res get [ . ] each ;
 | |
| 
 | |
| : clear-result ( -- )
 | |
|     V{ } clone res set ;
 |