r9424: * db-oracle/oracle-sql: Use clsql-specific error conditions. Use owner...
[clsql.git] / db-oracle / oracle-sql.lisp
index 0a704d25ba77d689892fe44838c33da40604f2f4..a041f87fa89329955538d67a23a5a2546011d353 100644 (file)
@@ -33,7 +33,7 @@ likely that we'll have to worry about the CMUCL limit."))
 
 
 (defmacro deref-vp (foreign-object)
-  `(uffi:deref-pointer ,foreign-object void-pointer))
+  `(uffi:deref-pointer ,foreign-object :pointer-void))
 
 ;; constants - from OCI?
 
@@ -128,7 +128,7 @@ the length of that format.")
                   (uffi:ensure-char-storable (code-char 0)))
 
              (setf (uffi:deref-pointer errcode :long) 0)
-             (oci-error-get (uffi:deref-pointer errhp void-pointer) 1
+             (oci-error-get (deref-vp errhp) 1
                            (uffi:make-null-pointer :unsigned-char)
                            errcode errbuf +errbuf-len+ +oci-htype-error+)
              (let ((subcode (uffi:deref-pointer errcode :long)))
@@ -159,9 +159,8 @@ the length of that format.")
 (defun osucc (code)
   (declare (type fixnum code))
   (unless (= code +oci-success+)
-    (error 'dbi-error
-          :format-control "unexpected OCI failure, code=~S"
-          :format-arguments (list code))))
+    (error 'sql-database-error
+          :message (format nil "unexpected OCI failure, code=~S" code))))
 
 
 ;;; Enabling this can be handy for low-level debugging.
@@ -191,10 +190,10 @@ the length of that format.")
 ;; In order to map the "same string" property above onto Lisp equality,
 ;; we drop trailing spaces in all cases:
 
-(uffi:def-type string-pointer (* :unsigned-char))
+(uffi:def-type string-array (:array :unsigned-char))
 
 (defun deref-oci-string (arrayptr string-index size)
-  (declare (type string-pointer arrayptr))
+  (declare (type string-array arrayptr))
   (declare (type (mod #.+n-buf-rows+) string-index))
   (declare (type (and unsigned-byte fixnum) size))
   (let* ((raw (uffi:convert-from-foreign-string 
@@ -226,7 +225,7 @@ the length of that format.")
   (flet (;; a character from OCI-DATE, interpreted as an unsigned byte
         (ub (i)
           (declare (type (mod #.+oci-date-bytes+) i))
-          (mod (uffi:deref-array oci-date string-pointer i) 256)))
+          (mod (uffi:deref-array oci-date string-array i) 256)))
     (let* ((century (* (- (ub 0) 100) 100))
           (year    (+ century (- (ub 1) 100)))
           (month   (ub 2))
@@ -236,10 +235,17 @@ the length of that format.")
           (second  (1- (ub 6))))
       (encode-universal-time second minute hour day month year))))
 
+(defun owner-phrase (owner)
+  (if owner
+      (format nil " WHERE OWNER='~A'" owner)
+    ""))
+
 (defmethod database-list-tables ((database oracle-database) &key owner)
   (mapcar #'car 
-         (database-query "select table_name from user_tables"
-                         database nil nil))
+         (database-query 
+          (concatenate 'string "select table_name from user_tables"
+                       (owner-phrase owner))
+          database nil nil))
   #+nil
   (values (database-query "select TABLE_NAME from all_catalog
                where owner not in ('PUBLIC','SYSTEM','SYS','WMSYS','EXFSYS','CTXSYS','WKSYS','WK_TEST','MDSYS','DMSYS','OLAPSYS','ORDSYS','XDB')"
@@ -248,15 +254,20 @@ the length of that format.")
 
 (defmethod database-list-views ((database oracle-database)
                                  &key owner)
-  ;; (database-query "select table_name from all_catalog" database nil nil)
   (mapcar #'car
-         (database-query "select view_name from user_views" database nil nil)))
+         (database-query
+          (concatenate 'string "select view_name from user_views"
+                       (owner-phrase owner))
+          database nil nil)))
 
 
 (defmethod database-list-indexes ((database oracle-database)
                                   &key (owner nil))
   (mapcar #'car
-         (database-query "select index_name from user_indexes" database nil nil)))
+         (database-query 
+          (concatenate 'string "select index_name from user_indexes"
+                       (owner-phrase owner))
+          database nil nil)))
 
 (defmethod list-all-table-columns (table (db oracle-database))
   (declare (string table))
@@ -288,8 +299,11 @@ the length of that format.")
   (mapcar #'car
          (database-query
           (format nil
-                  "select column_name from user_tab_columns where table_name='~A'"
-                  table)
+                  "select column_name from user_tab_columns where table_name='~A'~A"
+                  table
+                  (if owner
+                      (format nil " AND OWNER='~A'" owner)
+                    ""))
           database nil nil)))
 
 (defmethod database-attribute-type (attribute (table string)
@@ -298,8 +312,11 @@ the length of that format.")
   (let ((rows
         (database-query
          (format nil
-                 "select data_type,data_length,data_precision,data_scale,nullable from user_tab_columns where table_name='~A' and column_name='~A'"
-                 table attribute)
+                 "select data_type,data_length,data_precision,data_scale,nullable from user_tab_columns where table_name='~A' and column_name='~A'~A"
+                 table attribute
+                 (if owner
+                     (format nil " AND OWNER='~A'" owner)
+                   ""))                  
          database :auto nil)))
     (destructuring-bind (type length precision scale nullable) (car rows)
       (values (ensure-keyword type) length precision scale 
@@ -323,7 +340,7 @@ the length of that format.")
 ;; STREAM which has no more data, and QC is not a STREAM, we signal
 ;; DBI-ERROR instead.
 
-(uffi:def-type short-pointer '(* :short))
+(uffi:def-type short-array '(:array :short))
 (uffi:def-type int-pointer '(* :int))
 (uffi:def-type double-pointer '(* :double))
 
@@ -331,7 +348,7 @@ the length of that format.")
 (defstruct (oracle-result-set (:print-function print-query-cursor)
                               (:conc-name qc-)
                               (:constructor %make-query-cursor))
-  (db (error "missing DB")              ; db conn. this table is associated with
+  (db (error "missing DB")   ; db conn. this table is associated with
     :type oracle-database
     :read-only t)
   (stmthp (error "missing STMTHP")      ; the statement handle used to create
@@ -363,7 +380,7 @@ the length of that format.")
   ;;(declare (optimize (speed 3)))
   (cond ((zerop (qc-n-from-oci qc))
         (if eof-errorp
-            (error 'clsql-error :message
+            (error 'sql-database-error :message
                    (format nil "no more rows available in ~S" qc))
           eof-value))
        ((>= (qc-n-to-dbi qc)
@@ -380,17 +397,15 @@ the length of that format.")
                    (value
                     (let* ((arb (foreign-resource-buffer (cd-indicators cd)))
                            (indicator (uffi:deref-array arb '(:array :short) irow)))
-                      (declare (type short-pointer arb))
+                      (declare (type short-array arb))
                       (unless (= indicator -1)
                         (ecase (cd-oci-data-type cd)
                           (#.SQLT-STR  
                            (deref-oci-string b irow (cd-sizeof cd)))
                           (#.SQLT-FLT  
-                           (uffi:with-cast-pointer (bd b :double)
-                             (uffi:deref-array bd '(:array :double) irow)))
+                           (uffi:deref-array b '(:array :double) irow))
                           (#.SQLT-INT  
-                           (uffi:with-cast-pointer (bi b :int)
-                             (uffi:deref-array bi '(:array :int) irow)))
+                           (uffi:deref-array b '(:array :int) irow))
                           (#.SQLT-DATE 
                            (deref-oci-string b irow (cd-sizeof cd))))))))
               (when (and (eq :string (cd-result-type cd))
@@ -452,7 +467,7 @@ the length of that format.")
 (defun sql-stmt-exec (sql-stmt-string db result-types field-names)
   (with-slots (envhp svchp errhp)
     db
-    (let ((stmthp (uffi:allocate-foreign-object void-pointer)))
+    (let ((stmthp (uffi:allocate-foreign-object :pointer-void)))
       (uffi:with-foreign-object (stmttype :unsigned-short)
         
         (oci-handle-alloc (deref-vp envhp)
@@ -591,7 +606,7 @@ the length of that format.")
          (oci-attr-get (deref-vp parmdp)
                        +oci-dtype-param+ 
                        dtype-foreign
-                       (uffi:make-null-pointer :int)
+                       (uffi:make-null-pointer :unsigned-int)
                        +oci-attr-data-type+
                        (deref-vp errhp))
          (let ((dtype (uffi:deref-pointer dtype-foreign :unsigned-short)))
@@ -604,13 +619,13 @@ the length of that format.")
               (oci-attr-get (deref-vp parmdp)
                             +oci-dtype-param+
                             precision
-                            (uffi:make-null-pointer :int)
+                            (uffi:make-null-pointer :unsigned-int)
                             +oci-attr-precision+
                             (deref-vp errhp))
               (oci-attr-get (deref-vp parmdp)
                             +oci-dtype-param+
                             scale
-                            (uffi:make-null-pointer :int)
+                            (uffi:make-null-pointer :unsigned-int)
                             +oci-attr-scale+
                             (deref-vp errhp))
               (let ((*scale (uffi:deref-pointer scale :byte))
@@ -633,14 +648,14 @@ the length of that format.")
               (oci-attr-get (deref-vp parmdp)
                             +oci-dtype-param+ 
                             colsize
-                            (uffi:make-null-pointer :int) ;;  (uffi:pointer-address colsizesize) 
+                            (uffi:make-null-pointer :unsigned-int) ;;  (uffi:pointer-address colsizesize) 
                             +oci-attr-data-size+
                             (deref-vp errhp))
               (let ((colsize-including-null (1+ (uffi:deref-pointer colsize :unsigned-long))))
                 (setf buffer (acquire-foreign-resource
-                              :char (* +n-buf-rows+ colsize-including-null)))
+                              :unsigned-char (* +n-buf-rows+ colsize-including-null)))
                 (setf sizeof colsize-including-null))))
-           (let ((retcodes (acquire-foreign-resource :short +n-buf-rows+))
+           (let ((retcodes (acquire-foreign-resource :unsigned-short +n-buf-rows+))
                  (indicators (acquire-foreign-resource :short +n-buf-rows+))
                  (colname-string ""))
              (when field-names
@@ -671,12 +686,15 @@ the length of that format.")
                                 defnp
                                 (deref-vp errhp)
                                 (1+ icolumn) ; OCI 1-based indexing again
-                                (foreign-resource-buffer buffer)
+                                (uffi:with-cast-pointer (vp (foreign-resource-buffer buffer) :void)
+                                  vp)
                                 sizeof
                                 dtype
-                                (foreign-resource-buffer indicators)
+                                (uffi:with-cast-pointer (vp (foreign-resource-buffer indicators) :void)
+                                  vp)
                                 (uffi:make-null-pointer :unsigned-short)
-                                (foreign-resource-buffer retcodes)
+                                (uffi:with-cast-pointer (vp (foreign-resource-buffer retcodes) :unsigned-short)
+                                  vp)
                                 +oci-default+))))))))
   
 ;; Release the resources associated with a QUERY-CURSOR.
@@ -740,10 +758,11 @@ the length of that format.")
                          +oci-htype-error+ 0 +null-void-pointer-pointer+)
         (oci-handle-alloc (deref-vp envhp) srvhp
                          +oci-htype-server+ 0 +null-void-pointer-pointer+)
-       (oci-server-attach (deref-vp srvhp)
-                          (deref-vp errhp)
-                          (uffi:make-null-pointer :unsigned-char)
-                          0 +oci-default+)
+       (uffi:with-cstring (dblink nil)
+         (oci-server-attach (deref-vp srvhp)
+                            (deref-vp errhp)
+                            dblink
+                            0 +oci-default+))
         (oci-handle-alloc (deref-vp envhp) svchp
                          +oci-htype-svcctx+ 0 +null-void-pointer-pointer+)
         (oci-attr-set (deref-vp svchp)
@@ -757,7 +776,8 @@ the length of that format.")
        (uffi:with-foreign-object (buf '(:array :unsigned-char #.+errbuf-len+))
          (oci-server-version (deref-vp svchp)
                              (deref-vp errhp)
-                             buf +errbuf-len+ +oci-htype-svcctx+)
+                             (uffi:char-array-to-pointer buf)
+                             +errbuf-len+ +oci-htype-svcctx+)
          (setf server-version (uffi:convert-from-foreign-string buf)))
        (setq db (make-instance 'oracle-database
                                :name (database-name-from-spec connection-spec
@@ -790,7 +810,7 @@ the length of that format.")
   (cond 
     ((search " 10g " str)
      10)
-    ((search " 9g " str)
+    ((search "Oracle9i  " str)
      10)))
 
 
@@ -859,8 +879,10 @@ the length of that format.")
                 ) :database database)))
 
 (defmethod database-list-sequences ((database oracle-database) &key owner)
-  (mapcar #'car (database-query "select sequence_name from user_sequences" 
-                               database nil nil)))
+  (mapcar #'car (database-query 
+                (concatenate 'string "select sequence_name from user_sequences" 
+                             (owner-phrase owner))
+                database nil nil)))
 
 (defmethod database-execute-command (sql-expression (database oracle-database))
   (database-query sql-expression database nil nil)