;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL.
;;;; *************************************************************************
-(in-package #:clsql-sys)
+(in-package #:clsql)
(defclass standard-db-object ()
((view-database :initform nil :initarg :view-database :reader view-database
(when (member (view-class-slot-db-kind slotdef) '(:base :key))
(let ((cdef
(list (sql-expression :attribute (view-class-slot-column slotdef))
- (slot-type slotdef))))
+ (specified-type slotdef))))
(setf cdef (append cdef (list (view-class-slot-db-type slotdef))))
(let ((const (view-class-slot-db-constraints slotdef)))
(when const
(defclass ,class ,supers ,slots
,@(if (find :metaclass `,cl-options :key #'car)
`,cl-options
- (cons '(:metaclass clsql-sys::standard-db-class) `,cl-options)))
- (finalize-inheritance (find-class ',class))))
+ (cons '(:metaclass clsql::standard-db-class) `,cl-options)))
+ (finalize-inheritance (find-class ',class))
+ (find-class ',class)))
(defun keyslots-for-class (class)
(slot-value class 'key-slots))
(car list)
list))
-(defun slot-type (slotdef)
- (specified-type slotdef))
-
(defvar *update-context* nil)
(defmethod update-slot-from-db ((instance standard-db-object) slotdef value)
(declare (optimize (speed 3) #+cmu (extensions:inhibit-warnings 3)))
(let* ((slot-reader (view-class-slot-db-reader slotdef))
(slot-name (slot-definition-name slotdef))
- (slot-type (slot-type slotdef))
+ (slot-type (specified-type slotdef))
(*update-context* (cons (type-of instance) slot-name)))
(cond ((and value (null slot-reader))
(setf (slot-value instance slot-name)
(defmethod key-value-from-db (slotdef value database)
(declare (optimize (speed 3) #+cmu (extensions:inhibit-warnings 3)))
(let ((slot-reader (view-class-slot-db-reader slotdef))
- (slot-type (slot-type slotdef)))
+ (slot-type (specified-type slotdef)))
(cond ((and value (null slot-reader))
(read-sql-value value (delistify slot-type) database))
((null value)
(defun db-value-from-slot (slotdef val database)
(let ((dbwriter (view-class-slot-db-writer slotdef))
- (dbtype (slot-type slotdef)))
+ (dbtype (specified-type slotdef)))
(typecase dbwriter
(string (format nil dbwriter val))
(function (apply dbwriter (list val)))
(database-output-sql-as-type dbtype val database)))))))
(defun check-slot-type (slotdef val)
- (let* ((slot-type (slot-type slotdef))
+ (let* ((slot-type (specified-type slotdef))
(basetype (if (listp slot-type) (car slot-type) slot-type)))
(when (and slot-type val)
(unless (typep val basetype)
(let ((qualifier (key-qualifier-for-instance instance :database vd)))
(delete-records :from vt :where qualifier :database vd)
(setf (slot-value instance 'view-database) nil))
- (error 'clsql-no-database-error nil))))
+ (error 'clsql-base::clsql-no-database-error :database nil))))
(defmethod update-instance-from-records ((instance standard-db-object)
&key (database *default-database*))
(sels (generate-selection-list view-class))
(res (apply #'select (append (mapcar #'cdr sels)
(list :from view-table
- :where view-qual)))))
+ :where view-qual)
+ (list :result-types nil)))))
(when res
(get-slot-values-from-view instance (mapcar #'car sels) (car res)))))
(view-qual (key-qualifier-for-instance instance :database vd))
(slot-def (slotdef-for-slot-with-class slot view-class))
(att-ref (generate-attribute-reference view-class slot-def))
- (res (select att-ref :from view-table :where view-qual)))
+ (res (select att-ref :from view-table :where view-qual
+ :result-types nil)))
(when res
(get-slot-values-from-view instance (list slot-def) (car res)))))
(defmethod update-slot-with-null ((object standard-db-object)
slotname
slotdef)
- (let ((st (slot-type slotdef))
- (void-value (slot-value slotdef 'void-value)))
- (setf (slot-value object slotname) void-value)))
+ (setf (slot-value object slotname) (slot-value slotdef 'void-value)))
(defvar +no-slot-value+ '+no-slot-value+)
(defmethod database-get-type-specifier (type args database)
(declare (ignore type args))
- (if (clsql-base-sys::in (database-underlying-type database)
+ (if (clsql-base::in (database-underlying-type database)
:postgresql :postgresql-socket)
"VARCHAR"
"VARCHAR(255)"))
(format nil "INT(~A)" (car args))
"INT"))
+(deftype bigint ()
+ "An integer larger than a 32-bit integer, this width may vary by SQL implementation."
+ 'integer)
+
(defmethod database-get-type-specifier ((type (eql 'bigint)) args database)
(declare (ignore args database))
"BIGINT")
database)
(if args
(format nil "VARCHAR(~A)" (car args))
- (if (clsql-base-sys::in (database-underlying-type database)
+ (if (clsql-base::in (database-underlying-type database)
:postgresql :postgresql-socket)
"VARCHAR"
"VARCHAR(255)")))
database)
(if args
(format nil "VARCHAR(~A)" (car args))
- (if (clsql-base-sys::in (database-underlying-type database)
+ (if (clsql-base::in (database-underlying-type database)
:postgresql :postgresql-socket)
"VARCHAR"
"VARCHAR(255)")))
(defmethod database-get-type-specifier ((type (eql 'string)) args database)
(if args
(format nil "VARCHAR(~A)" (car args))
- (if (clsql-base-sys::in (database-underlying-type database)
+ (if (clsql-base::in (database-underlying-type database)
:postgresql :postgresql-socket)
"VARCHAR"
"VARCHAR(255)")))
+(deftype universal-time ()
+ "A positive integer as returned by GET-UNIVERSAL-TIME."
+ '(integer 1 *))
+
(defmethod database-get-type-specifier ((type (eql 'universal-time)) args database)
(declare (ignore args database))
"BIGINT")
(declare (ignore database))
(progv '(*print-circle* *print-array*) '(t t)
(let ((escaped (prin1-to-string val)))
- (clsql-base-sys::substitute-char-string
+ (clsql-base::substitute-char-string
escaped #\Null " "))))
(defmethod database-output-sql-as-type ((type (eql 'symbol)) val database)
(prin1-to-string val)))
(defmethod database-output-sql-as-type ((type (eql 'boolean)) val database)
- (declare (ignore database))
- (if val "t" "f"))
+ (case (database-underlying-type database)
+ (:mysql
+ (if val 1 0))
+ (t
+ (if val "t" "f"))))
(defmethod database-output-sql-as-type ((type (eql 'string)) val database)
(declare (ignore database))
(defmethod read-sql-value (val (type (eql 'symbol)) database)
(declare (ignore database))
(when (< 0 (length val))
- (unless (string= val (clsql-base-sys:symbol-name-default-case "NIL"))
- (intern (clsql-base-sys:symbol-name-default-case val)
+ (unless (string= val (clsql-base:symbol-name-default-case "NIL"))
+ (intern (clsql-base:symbol-name-default-case val)
(symbol-package *update-context*)))))
(defmethod read-sql-value (val (type (eql 'integer)) database)
(declare (ignore database))
(etypecase val
(string
- (parse-integer val))
+ (unless (string-equal "NIL" val)
+ (parse-integer val)))
(number val)))
(defmethod read-sql-value (val (type (eql 'bigint)) database)
(declare (ignore database))
(etypecase val
(string
- (parse-integer val))
+ (unless (string-equal "NIL" val)
+ (parse-integer val)))
(number val)))
(defmethod read-sql-value (val (type (eql 'float)) database)
(float (read-from-string val)))
(defmethod read-sql-value (val (type (eql 'boolean)) database)
- (declare (ignore database))
- (equal "t" val))
+ (case (database-underlying-type database)
+ (:mysql
+ (etypecase val
+ (string (if (string= "0" val) nil t))
+ (integer (if (zerop val) nil t))))
+ (:postgresql
+ (if (eq :odbc (database-type database))
+ (if (string= "0" val) nil t)
+ (equal "t" val)))
+ (t
+ (equal "t" val))))
(defmethod read-sql-value (val (type (eql 'univeral-time)) database)
(declare (ignore database))
(unless (eq 'NULL val)
- (etypecase val
- (string
- (parse-intger val))
- (number val)))
+ (etypecase val
+ (string
+ (parse-integer val))
+ (number val))))
(defmethod read-sql-value (val (type (eql 'wall-time)) database)
(declare (ignore database))
(jc (gethash :join-class dbi)))
(let ((jq (join-qualifier class object slot-def)))
(when jq
- (select jc :where jq)))))
+ (select jc :where jq :flatp t :result-types nil)))))
(defun fault-join-slot (class object slot-def)
(let* ((dbi (view-class-slot-db-info slot-def))
(defun find-all (view-classes &rest args &key all set-operation distinct from
where group-by having order-by order-by-descending offset limit
- refresh (database *default-database*))
- "tweeze me apart someone pleeze"
+ refresh flatp (database *default-database*))
+ "Called by SELECT to generate object query results when the
+ View Classes VIEW-CLASSES are passed as arguments to SELECT."
(declare (ignore all set-operation group-by having offset limit)
(optimize (debug 3) (speed 1)))
(remf args :from)
+ (remf args :flatp)
+ (remf args :result-types)
(labels ((table-sql-expr (table)
(sql-expression :table (view-table table)))
(ref-equal (ref1 ref2)
obj))
(build-objects (vals sclasses sels)
(let ((objects (mapcar #'(lambda (sclass sel)
- (build-object vals sclass sel))
+ (prog1 (build-object vals sclass sel)
+ (setf vals (nthcdr (list-length sel)
+ vals))))
sclasses sels)))
- (if (= (length sclasses) 1)
+ (if (and flatp (= (length sclasses) 1))
(car objects)
objects))))
(let* ((*db-deserializing* t)
(*default-database* (or database
- (error 'clsql-no-database-error nil)))
+ (error 'clsql-base::clsql-no-database-error :database nil)))
(sclasses (mapcar #'find-class view-classes))
(sels (mapcar #'generate-selection-list sclasses))
(fullsels (apply #'append sels))
(append (mapcar #'cdr fullsels)
(cons :from
(list (append (when from (listify from))
- (listify tables)))) args)))
+ (listify tables))))
+ (list :result-types nil)
+ args)))
(mapcar #'(lambda (r) (build-objects r sclasses sels)) res))))
(defmethod instance-refreshed ((instance standard-db-object)))
-(defun select (&rest select-all-args)
+(defmethod select (&rest select-all-args)
"Selects data from database given the constraints specified. Returns
a list of lists of record values as specified by select-all-args. By
default, the records are each represented as lists of attribute
(apply #'find-all target-args qualifier-args)
(let ((expr (apply #'make-query select-all-args)))
(destructuring-bind (&key (flatp nil)
+ (result-types :auto)
+ (field-names t)
(database *default-database*)
&allow-other-keys)
qualifier-args
- (let ((res (query expr :database database)))
- (if (and flatp
- (= (length (slot-value expr 'selections)) 1))
- (mapcar #'car res)
- res))))))))
+ (query expr :flatp flatp :result-types result-types
+ :field-names field-names :database database)))))))
+