r9241: add type-modified database identifier support to SELECT
authorKevin M. Rosenberg <kevin@rosenberg.net>
Wed, 5 May 2004 04:28:32 +0000 (04:28 +0000)
committerKevin M. Rosenberg <kevin@rosenberg.net>
Wed, 5 May 2004 04:28:32 +0000 (04:28 +0000)
ChangeLog
TODO
sql/generics.lisp
sql/metaclasses.lisp
sql/objects.lisp
tests/test-fdml.lisp

index 380400d8d605e71c0833bb09f07cc2aea14d0981..223de7d3fd0f47a8a4f20f59955f229427b4bfe1 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,12 @@
 4 May 2004 Kevin Rosenberg (kevin@rosenberg.net)
        * base/basic-sql.lisp: Avoid multiple evaluation
        of query-expression in DO-QUERY
+       * sql/objects.lisp: Make SELECT a normal function.
+       SELECT now accepts type-modified database identifiers, such as
+        [foo :string] which means that the values in column foo are returned 
+        as Lisp strings.
+       * test/test-fdml.lisp: Add tests for type-modified
+       database identifiers.
        
 4 May 2004 Kevin Rosenberg (kevin@rosenberg.net)
        * Version 2.10.10
diff --git a/TODO b/TODO
index e7885ada35855a768e667e452532f153a80cd364..eaadf078ffe3ef8ba9e3ccda8d70b5f9e4dc8de7 100644 (file)
--- a/TODO
+++ b/TODO
@@ -25,10 +25,7 @@ COMMONSQL SPEC
   
     SELECT 
       o keyword arg :refresh should function as advertised 
-      o should accept type-modified database identifiers (e.g., 
-        [foo :string] which means that the values in column foo are returned 
-        as Lisp strings) 
-
  >> The object-oriented sql interface
 
     DEF-VIEW-CLASS
index 0fa8abe68962a60287a2fd7c1d97669270b8f88a..cbf2d7eb292d5592a4400facf2e24462fa1ad52b 100644 (file)
 
 (in-package #:clsql)
 
-(defgeneric select (&rest args) 
-  (:documentation
-   "The function SELECT selects data from DATABASE, which has a
-default value of *DEFAULT-DATABASE*, given the constraints
-specified by the rest of the ARGS. It returns a list of objects
-as specified by SELECTIONS. By default, the objects will each be
-represented as lists of attribute values. The argument SELECTIONS
-consists either of database identifiers, type-modified database
-identifiers or literal strings. A type-modifed database
-identifier is an expression such as [foo :string] which means
-that the values in column foo are returned as Lisp strings.  The
-FLATP argument, which has a default value of nil, specifies if
-full bracketed results should be returned for each matched
-entry. If FLATP is nil, the results are returned as a list of
-lists. If FLATP is t, the results are returned as elements of a
-list, only if there is only one result per row. The arguments
-ALL, SET-OPERATION, DISTINCT, FROM, WHERE, GROUP-BY, HAVING and
-ORDER-by have the same function as the equivalent SQL expression.
-The SELECT function is common across both the functional and
-object-oriented SQL interfaces. If selections refers to View
-Classes then the select operation becomes object-oriented. This
-means that SELECT returns a list of View Class instances, and
-SLOT-VALUE becomes a valid SQL operator for use within the where
-clause. In the View Class case, a second equivalent select call
-will return the same View Class instance objects. If REFRESH is
-true, then existing instances are updated if necessary, and in
-this case you might need to extend the hook INSTANCE-REFRESHED.
-The default value of REFRESH is nil. SQL expressions used in the
-SELECT function are specified using the square bracket syntax,
-once this syntax has been enabled using
-ENABLE-SQL-READER-SYNTAX."))
-
 (defgeneric update-record-from-slot (object slot &key database)
   (:documentation
    "The generic function UPDATE-RECORD-FROM-SLOT updates an individual
index 082b1d3c111079a487953b643751d1ad5a8cd231..edb794298f3d374b088409c6e361185f592db15c 100644 (file)
                               :db-writer :db-info))
 (defvar +extra-class-options+ '(:base-table))
 
+#+lispworks
 (dolist (slot-option +extra-slot-options+)
   (process-slot-option standard-db-class slot-option))
 
+#+lispworks
 (dolist (class-option +extra-class-options+)
   (process-class-option standard-db-class class-option))
 
index 627989b104c1da1b34f47b68f9ff7a4eb511ca08..833abd79e0510f3a47682bbea747a793fdc27b1a 100644 (file)
@@ -841,14 +841,37 @@ superclass of the newly-defined View Class."
 
 (defmethod instance-refreshed ((instance standard-db-object)))
 
-(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
-values. The selections argument may be either db-identifiers, literal
-strings or view classes.  If the argument consists solely of view
-classes, the return value will be instances of objects rather than raw
-tuples."
+(defun select (&rest select-all-args) 
+   "The function SELECT selects data from DATABASE, which has a
+default value of *DEFAULT-DATABASE*, given the constraints
+specified by the rest of the ARGS. It returns a list of objects
+as specified by SELECTIONS. By default, the objects will each be
+represented as lists of attribute values. The argument SELECTIONS
+consists either of database identifiers, type-modified database
+identifiers or literal strings. A type-modifed database
+identifier is an expression such as [foo :string] which means
+that the values in column foo are returned as Lisp strings.  The
+FLATP argument, which has a default value of nil, specifies if
+full bracketed results should be returned for each matched
+entry. If FLATP is nil, the results are returned as a list of
+lists. If FLATP is t, the results are returned as elements of a
+list, only if there is only one result per row. The arguments
+ALL, SET-OPERATION, DISTINCT, FROM, WHERE, GROUP-BY, HAVING and
+ORDER-by have the same function as the equivalent SQL expression.
+The SELECT function is common across both the functional and
+object-oriented SQL interfaces. If selections refers to View
+Classes then the select operation becomes object-oriented. This
+means that SELECT returns a list of View Class instances, and
+SLOT-VALUE becomes a valid SQL operator for use within the where
+clause. In the View Class case, a second equivalent select call
+will return the same View Class instance objects. If REFRESH is
+true, then existing instances are updated if necessary, and in
+this case you might need to extend the hook INSTANCE-REFRESHED.
+The default value of REFRESH is nil. SQL expressions used in the
+SELECT function are specified using the square bracket syntax,
+once this syntax has been enabled using
+ENABLE-SQL-READER-SYNTAX."
+
   (flet ((select-objects (target-args)
            (and target-args
                 (every #'(lambda (arg)
@@ -859,13 +882,28 @@ tuples."
         (query-get-selections select-all-args)
       (if (select-objects target-args)
           (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
-             (query expr :flatp flatp :result-types result-types 
-                    :field-names field-names :database database)))))))
+       (let* ((expr (apply #'make-query select-all-args))
+              (specified-types
+               (mapcar #'(lambda (attrib)
+                           (if (typep attrib 'sql-ident-attribute)
+                               (let ((type (slot-value attrib 'type)))
+                                 (if type
+                                     type
+                                   t))
+                             t))
+                       (slot-value expr 'selections))))
+         (destructuring-bind (&key (flatp nil)
+                                   (result-types :auto)
+                                   (field-names t) 
+                                   (database *default-database*)
+                              &allow-other-keys)
+             qualifier-args
+           (query expr :flatp flatp 
+                  :result-types 
+                  ;; specifying a type for an attribute overrides result-types
+                  (if (some #'(lambda (x) (not (eq t x))) specified-types) 
+                      specified-types
+                    result-types)
+                  :field-names field-names
+                  :database database)))))))
 
index a91cf9c62d6da49995799a309710cedaea27b08c..1134c913193a35001b362ae711ad12d6c791186c 100644 (file)
      :field-names nil)
   ((1)))
 
+(deftest :fdml/select/17
+    (clsql:select [emplid] [last-name] :from [employee] :where [= 1 [emplid]]
+     :field-names nil)
+  ((1 "Lenin")))
+
+(deftest :fdml/select/18
+    (clsql:select [emplid :string] [last-name] :from [employee] :where [= 1 [emplid]]
+     :field-names nil)
+  (("1" "Lenin")))
+
 ;(deftest :fdml/select/11
 ;    (clsql:select [emplid] :from [employee]
 ;                :where [= [emplid] [any [select [companyid] :from [company]]]]