r9388: * db-oracle/oracle-api: Add OCIServerVersion
[clsql.git] / db-oracle / oracle-sql.lisp
index a1e81d08b44f525f5422d0fed51aa94f8152b8e4..ebd7e8cb1f54887ac9900ae0cc1fcbee1e45a0b6 100644 (file)
@@ -15,6 +15,9 @@
 
 (in-package #:clsql-oracle)
 
+(defvar *oracle-server-version* nil
+  "Version string of Oracle server.")
+
 (defmethod database-initialize-database-type
     ((database-type (eql :oracle)))
   t)
@@ -210,7 +213,7 @@ the length of that format.")))
   (declare (type (mod #.+n-buf-rows+) string-index))
   (declare (type (and unsigned-byte fixnum) size))
   (let* ((raw (uffi:convert-from-foreign-string 
-              (uffi:pointer-address (uffi:deref-array arrayptr '(:array :unsigned-char) (* string-index size)))))
+              (+ (uffi:pointer-address arrayptr) (* string-index size))))
         (trimmed (string-trim " " raw)))
     (if (equal trimmed "NULL") nil trimmed)))
 
@@ -255,19 +258,17 @@ the length of that format.")))
 ;  (sql:query "select '',OWNER,TABLE_NAME,TABLE_TYPE,'' from all_catalog"))
   
 
-(defmethod list-all-user-database-tables ((db oracle-database))
-  (unless db
-    (setf db clsql:*default-database*))
+(defmethod database-list-tables ((db oracle-database) &key owner)
   (values (database-query "select TABLE_NAME from all_catalog
-               where owner <> 'PUBLIC' and owner <> 'SYSTEM' and owner <> 'SYS'"
+               where owner not in ('PUBLIC','SYSTEM','SYS','WMSYS','EXFSYS','CTXSYS','WKSYS','WK_TEST','MDSYS','DMSYS','OLAPSYS','ORDSYS','XDB')"
                          db nil nil)))
 
 
-(defmethod database-list-tables ((database oracle-database)
+(defmethod database-list-views ((database oracle-database)
                                  &key (system-tables nil) owner)
   (if system-tables
       (database-query "select table_name from all_catalog" database nil nil)
-    (database-query "select table_name from all_catalog where owner <> 'PUBLIC' and owner <> 'SYSTEM' and owner <> 'SYS'"
+    (database-query "select table_name from all_catalog where owner != 'PUBLIC' and owner != 'SYSTEM' and owner != 'SYS'"
                    database nil nil)))
 
 ;; Return a list of all columns in TABLE.
@@ -310,7 +311,7 @@ the length of that format.")))
     (mapcar #'car
            (database-query
             (format nil
-                    "select user_tab_columns,column_name from user_tab_columns where user_tab_columns.table_name=~A"
+                    "select user_tab_columns,column_name from user_tab_columns where user_tab_columns.table_name='~A'"
                     relname)
             database nil nil))))
 
@@ -390,7 +391,7 @@ the length of that format.")))
                    (value
                     (let ((arb (foreign-resource-buffer (cd-indicators cd))))
                       (declare (type short-pointer arb))
-                      (unless (= (uffi:deref-array arb :int irow) -1)
+                      (unless (= (uffi:deref-array arb '(:array :int) irow) -1)
                         (ecase (cd-oci-data-type cd)
                           (#.SQLT-STR  (deref-oci-string b irow (cd-sizeof cd)))
                           (#.SQLT-FLT  (uffi:deref-array b '(:array :double) irow))
@@ -419,7 +420,9 @@ the length of that format.")))
                                                 :nulls-ok t))))
            (uffi:with-foreign-object (rowcount :long)
              (oci-attr-get (uffi:deref-pointer (qc-stmthp qc) void-pointer) +oci-htype-stmt+
-                           (c-& rowcount :long) nil +oci-attr-row-count+ 
+                           rowcount 
+                          (uffi:make-null-pointer :unsigned-long)
+                          +oci-attr-row-count+ 
                            (uffi:deref-pointer errhp void-pointer))
              (setf (qc-n-from-oci qc)
                    (- (uffi:deref-pointer rowcount :long) (qc-total-n-from-oci qc)))
@@ -555,14 +558,14 @@ the length of that format.")))
             
 
 (defun make-query-cursor-cds (database stmthp types)
-  (declare (optimize (speed 3))
+  (declare (optimize (safety 3) #+nil (speed 3))
           (type oracle-database database)
           (type pointer-pointer-void stmthp))
   (with-slots (errhp)
     database
     (unless (eq types :auto)
       (error "unsupported TYPES value"))
-    (uffi:with-foreign-objects ((dtype :unsigned-short)
+    (uffi:with-foreign-objects ((dtype-foreign :unsigned-short)
                           (parmdp (* :void))
                           (precision :byte)
                           (scale :byte)
@@ -575,7 +578,8 @@ the length of that format.")))
            (sizeof nil))
        (do ((icolumn 0 (1+ icolumn))
             (cds-as-reversed-list nil))
-           ((not (eql (oci-param-get (uffi:deref-pointer stmthp void-pointer) +oci-htype-stmt+
+           ((not (eql (oci-param-get (uffi:deref-pointer stmthp void-pointer) 
+                                     +oci-htype-stmt+
                                      (uffi:deref-pointer errhp void-pointer)
                                      parmdp
                                      (1+ icolumn) :database database)
@@ -585,65 +589,66 @@ the length of that format.")))
          ;; handle in Lisp.
          (oci-attr-get (uffi:deref-pointer parmdp void-pointer)
                        +oci-dtype-param+ 
-                       dtype
+                       dtype-foreign
                        (uffi:make-null-pointer :int) +oci-attr-data-type+
                        (uffi:deref-pointer errhp void-pointer))
-         (case dtype
-           (#.SQLT-DATE
-            (setf buffer (acquire-foreign-resource :char (* 32 +n-buf-rows+)))
-            (setf sizeof 32 dtype #.SQLT-STR))
-           (2 ;; number
-            ;;(oci-attr-get parmdp +oci-dtype-param+
-            ;;(addr precision) nil +oci-attr-precision+
-            ;;(uffi:deref-pointer errhp))
-            (oci-attr-get (uffi:deref-pointer parmdp void-pointer)
-                          +oci-dtype-param+
-                          scale
-                          (uffi:make-null-pointer :int) +oci-attr-scale+
-                          (uffi:deref-pointer errhp void-pointer))
-            (cond
-             ((zerop scale)
-              (setf buffer (acquire-foreign-resource :init +n-buf-rows+)
-                    sizeof 4                   ;; sizeof(int)
-                    dtype #.SQLT-INT))
-             (t
-              (setf buffer (acquire-foreign-resource :double +n-buf-rows+)
-                    sizeof 8                   ;; sizeof(double)
-                    dtype #.SQLT-FLT))))          
-           (t  ; Default to SQL-STR
-            (setf (uffi:deref-pointer colsize :unsigned-long) 0
-                  dtype #.SQLT-STR)
-            (oci-attr-get (uffi:deref-pointer parmdp void-pointer)
-                          +oci-dtype-param+ 
-                          colsize
-                          (uffi:make-null-pointer :int) ;;  (uffi:pointer-address colsizesize) 
-                          +oci-attr-data-size+
-                          (uffi:deref-pointer errhp void-pointer))
-            (let ((colsize-including-null (1+ (uffi:deref-pointer colsize :unsigned-long))))
-              (setf buffer (acquire-foreign-resource
-                            :char (* +n-buf-rows+ colsize-including-null)))
-              (setf sizeof colsize-including-null))))
-         (let ((retcodes (acquire-foreign-resource :short +n-buf-rows+))
-               (indicators (acquire-foreign-resource :short +n-buf-rows+)))
-           (push (make-cd :name "col" ;(subseq colname 0 colnamelen)
-                          :sizeof sizeof
-                          :buffer buffer
-                          :oci-data-type dtype
-                          :retcodes retcodes
-                          :indicators indicators)
-                 cds-as-reversed-list)
-           (oci-define-by-pos (uffi:deref-pointer stmthp void-pointer)
-                              (uffi:pointer-address defnp)
-                              (uffi:deref-pointer errhp void-pointer)
-                              (1+ icolumn) ; OCI 1-based indexing again
-                              (foreign-resource-buffer buffer)
-                              sizeof
-                              dtype
-                              (foreign-resource-buffer indicators)
-                              nil
-                              (foreign-resource-buffer retcodes)
-                              +oci-default+)))))))
-
+         (let ((dtype (uffi:deref-pointer dtype-foreign :unsigned-short)))
+           (case dtype
+             (#.SQLT-DATE
+              (setf buffer (acquire-foreign-resource :char (* 32 +n-buf-rows+)))
+              (setf sizeof 32 dtype #.SQLT-STR))
+             (2 ;; number
+              ;;(oci-attr-get parmdp +oci-dtype-param+
+              ;;(addr precision) nil +oci-attr-precision+
+              ;;(uffi:deref-pointer errhp))
+              (oci-attr-get (uffi:deref-pointer parmdp void-pointer)
+                            +oci-dtype-param+
+                            scale
+                            (uffi:make-null-pointer :int) +oci-attr-scale+
+                            (uffi:deref-pointer errhp void-pointer))
+              (cond
+               ((zerop scale)
+                (setf buffer (acquire-foreign-resource :init +n-buf-rows+)
+                      sizeof 4                 ;; sizeof(int)
+                      dtype #.SQLT-INT))
+               (t
+                (setf buffer (acquire-foreign-resource :double +n-buf-rows+)
+                      sizeof 8                   ;; sizeof(double)
+                      dtype #.SQLT-FLT))))          
+             (t                        ; Default to SQL-STR
+              (setf (uffi:deref-pointer colsize :unsigned-long) 0
+                    dtype #.SQLT-STR)
+              (oci-attr-get (uffi:deref-pointer parmdp void-pointer)
+                            +oci-dtype-param+ 
+                            colsize
+                            (uffi:make-null-pointer :int) ;;  (uffi:pointer-address colsizesize) 
+                            +oci-attr-data-size+
+                            (uffi:deref-pointer errhp void-pointer))
+              (let ((colsize-including-null (1+ (uffi:deref-pointer colsize :unsigned-long))))
+                (setf buffer (acquire-foreign-resource
+                              :char (* +n-buf-rows+ colsize-including-null)))
+                (setf sizeof colsize-including-null))))
+           (let ((retcodes (acquire-foreign-resource :short +n-buf-rows+))
+                 (indicators (acquire-foreign-resource :short +n-buf-rows+)))
+             (push (make-cd :name "col" ;(subseq colname 0 colnamelen)
+                            :sizeof sizeof
+                            :buffer buffer
+                            :oci-data-type dtype
+                            :retcodes retcodes
+                            :indicators indicators)
+                   cds-as-reversed-list)
+             (oci-define-by-pos (uffi:deref-pointer stmthp void-pointer)
+                                defnp
+                                (uffi:deref-pointer errhp void-pointer)
+                                (1+ icolumn) ; OCI 1-based indexing again
+                                (foreign-resource-buffer buffer)
+                                sizeof
+                                dtype
+                                (foreign-resource-buffer indicators)
+                                (uffi:make-null-pointer :unsigned-short)
+                                (foreign-resource-buffer retcodes)
+                                +oci-default+))))))))
+  
 ;; Release the resources associated with a QUERY-CURSOR.
 
 (defun close-query (qc)
@@ -732,6 +737,14 @@ the length of that format.")))
                   (uffi:convert-to-cstring data-source-name) (length data-source-name)
                   :database db)
        ;; :date-format-length (1+ (length date-format)))))
+       (uffi:with-foreign-object (buf (:array :unsigned-char 512))
+         (oci-server-version (uffi:deref-pointer svchp void-pointer)
+                             (uffi:deref-pointer errhp void-pointer)
+                             buf
+                             512
+                             +oci-htype-svcctx+)
+         (setf *oracle-server-version* (uffi:convert-from-foreign-string buf)))
+       
        (setf (slot-value db 'clsql-sys::state) :open)
         (database-execute-command
         (format nil "alter session set NLS_DATE_FORMAT='~A'" (date-format db)) db)
@@ -764,7 +777,7 @@ the length of that format.")))
 
 (defmethod database-query (query-expression (database oracle-database) result-types field-names)
   (let ((cursor (sql-stmt-exec query-expression database :types :auto)))
-    (declare (type (or query-cursor null) cursor))
+    ;; (declare (type (or query-cursor null) cursor))
     (if (null cursor) ; No table was returned.
        (values)
       (do ((reversed-result nil))
@@ -907,3 +920,7 @@ the length of that format.")))
       buf)))
 
 
+;; Specifications
+
+(defmethod db-type-has-bigint? ((type (eql :oracle)))
+  nil)