From 5990bfce392a05c10237d4f97b008c4f828028e5 Mon Sep 17 00:00:00 2001 From: "Kevin M. Rosenberg" Date: Wed, 5 May 2004 04:28:32 +0000 Subject: [PATCH] r9241: add type-modified database identifier support to SELECT --- ChangeLog | 6 ++++ TODO | 5 +-- sql/generics.lisp | 32 -------------------- sql/metaclasses.lisp | 2 ++ sql/objects.lisp | 72 +++++++++++++++++++++++++++++++++----------- tests/test-fdml.lisp | 10 ++++++ 6 files changed, 74 insertions(+), 53 deletions(-) diff --git a/ChangeLog b/ChangeLog index 380400d..223de7d 100644 --- 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 e7885ad..eaadf07 100644 --- 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 diff --git a/sql/generics.lisp b/sql/generics.lisp index 0fa8abe..cbf2d7e 100644 --- a/sql/generics.lisp +++ b/sql/generics.lisp @@ -18,38 +18,6 @@ (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 diff --git a/sql/metaclasses.lisp b/sql/metaclasses.lisp index 082b1d3..edb7942 100644 --- a/sql/metaclasses.lisp +++ b/sql/metaclasses.lisp @@ -60,9 +60,11 @@ :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)) diff --git a/sql/objects.lisp b/sql/objects.lisp index 627989b..833abd7 100644 --- a/sql/objects.lisp +++ b/sql/objects.lisp @@ -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))))))) diff --git a/tests/test-fdml.lisp b/tests/test-fdml.lisp index a91cf9c..1134c91 100644 --- a/tests/test-fdml.lisp +++ b/tests/test-fdml.lisp @@ -303,6 +303,16 @@ :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]]]] -- 2.34.1