From bb245c9d1616927d1302f3f36d3ebbf6a0dd662d Mon Sep 17 00:00:00 2001 From: Marcus Pearce Date: Sat, 22 May 2004 13:28:01 +0000 Subject: [PATCH] r9426: Docstrings, docstrings, docstrings. --- ChangeLog | 14 ++++ doc/TODO | 4 +- sql/conditions.lisp | 32 +++++++-- sql/generics.lisp | 103 +++++++++++++-------------- sql/objects.lisp | 162 +++++++++++++++++++++++++++--------------- sql/package.lisp | 14 ++-- tests/test-oodml.lisp | 2 +- 7 files changed, 203 insertions(+), 128 deletions(-) diff --git a/ChangeLog b/ChangeLog index 27cf62d..7d40812 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,17 @@ +22 May 2004 Marcus Pearce (m.t.pearce@city.ac.uk) + * sql/generics.lisp: reworked docstrings. Remove generics for + ADD-TO-RELATION and REMOVE-FROM-RELATION. + * sql/objects.lisp: reworked docstrings. Changed UPDATE-OBJECT-JOINS + to UPDATE-OBJECTS-JOINS for CommonSQL compatibility. + * sql/package.lisp: Changed UPDATE-OBJECT-JOINS to UPDATE-OBJECTS-JOINS + for CommonSQL compatibility. Remove ADD-TO-RELATION and + REMOVE-FROM-RELATION. + * tests/test-oodml.lisp: Changed UPDATE-OBJECT-JOINS to + UPDATE-OBJECTS-JOINS for CommonSQL compatibility. + * doc/TODO: added notes about extra slot options to DEF-VIEW-CLASS. + * sql/conditions.lisp: add documentation for conditions. Add + SQL-TIMEOUT-ERROR and SQL-FATAL-ERROR for CommonSQL compatibility. + 21 May 2004 Marcus Pearce (m.t.pearce@city.ac.uk) * sql/basic-sql.lisp: reworked docstrings. * sql/transactions.lisp: reworked docstrings. diff --git a/doc/TODO b/doc/TODO index 3220070..4132cf6 100644 --- a/doc/TODO +++ b/doc/TODO @@ -41,9 +41,9 @@ DOCUMENTATION TO DO LIST - DROP-INDEX: keyword arg :on (for MySQL). - - DEF-VIEW-CLASS: DB-CONSTRAINTS and DB-TYPE slot options. + - DEF-VIEW-CLASS: DB-CONSTRAINTS, DB-TYPE and VOID-VALUE slot options. - - CREATE-TABLE: keyword args :TRANSACTIONS (for MySQL) and :CONSTRAINTS + - CREATE-TABLE: keyword args :TRANSACTIONS (for MySQL) and :CONSTRAINTS; description arg accepts optional DB-TYPE string. - transactions: START-TRANSACTION and IN-TRANSACTION-P. diff --git a/sql/conditions.lisp b/sql/conditions.lisp index aee96d8..dc48d2f 100644 --- a/sql/conditions.lisp +++ b/sql/conditions.lisp @@ -48,7 +48,8 @@ set to :error to signal an error or :ignore/nil to silently ignore the warning." "") (sql-error-error-id c) (sql-error-secondary-error-id c) - (sql-error-database-message c))))) + (sql-error-database-message c)))) + (:documentation "Used to signal an error in a CLSQL database interface.")) (define-condition sql-connection-error (sql-database-error) ((database-type :initarg :database-type :initform nil @@ -62,7 +63,8 @@ set to :error to signal an error or :ignore/nil to silently ignore the warning." (sql-error-database-type c)) (sql-error-database-type c) (sql-error-error-id c) - (sql-error-database-message c))))) + (sql-error-database-message c)))) + (:documentation "Used to signal an error in connecting to a database.")) (define-condition sql-database-data-error (sql-database-error) ((expression :initarg :expression :initarg nil @@ -72,10 +74,26 @@ set to :error to signal an error or :ignore/nil to silently ignore the warning." (sql-error-database c) (sql-error-expression c) (sql-error-error-id c) - (sql-error-database-message c))))) + (sql-error-database-message c)))) + (:documentation "Used to signal an error with the SQL data + passed to a database.")) (define-condition sql-temporary-error (sql-database-error) - ()) + () + (:documentation "Used to signal an error when the database +cannot currently process a valid interaction because, for +example, it is still executing another command possibly issued by +another user.")) + +(define-condition sql-timeout-error (sql-connection-error) + () + (:documentation "Used to signal an error when the database +times out while processing some operation.")) + +(define-condition sql-fatal-error (sql-connection-error) + () + (:documentation "Used to signal an error when the database +connection is no longer usable.")) (define-condition sql-user-error (sql-error) ((message :initarg :message @@ -83,13 +101,15 @@ set to :error to signal an error or :ignore/nil to silently ignore the warning." :reader sql-user-error-message)) (:report (lambda (c stream) (format stream "A CLSQL lisp code error occurred: ~A " - (sql-user-error-message c))))) + (sql-user-error-message c)))) + (:documentation "Used to signal lisp errors inside CLSQL.")) + ;; Signal conditions (defun signal-closed-database-error (database) - (error 'sql-connection-error + (error 'sql-fatal-error :database database :message "Database is closed.")) diff --git a/sql/generics.lisp b/sql/generics.lisp index a7c8be1..ac9f0bd 100644 --- a/sql/generics.lisp +++ b/sql/generics.lisp @@ -20,69 +20,72 @@ (defgeneric update-record-from-slot (object slot &key database) (:documentation - "The generic function UPDATE-RECORD-FROM-SLOT updates an individual -data item in the column represented by SLOT. The DATABASE is only used -if OBJECT is not yet associated with any database, in which case a -record is created in DATABASE. Only SLOT is initialized in this case; -other columns in the underlying database receive default values. The -argument SLOT is the CLOS slot name; the corresponding column names -are derived from the View Class definition.")) + "Updates the value stored in the column represented by the +slot, specified by the CLOS slot name SLOT, of View Class +instance OBJECT. DATABASE defaults to *DEFAULT-DATABASE* and +specifies the database in which the update is made only if OBJECT +is not associated with a database. In this case, a record is +created in DATABASE and the attribute represented by SLOT is +initialised from the value of the supplied slots with other +attributes having default values. Furthermore, OBJECT becomes +associated with DATABASE.")) (defgeneric update-record-from-slots (object slots &key database) (:documentation - "The generic function UPDATE-RECORD-FROM-SLOTS updates data in the -columns represented by SLOTS. The DATABASE is only used if OBJECT is -not yet associated with any database, in which case a record is -created in DATABASE. Only slots are initialized in this case; other -columns in the underlying database receive default values. The -argument SLOTS contains the CLOS slot names; the corresponding column -names are derived from the view class definition.")) + "Updates the values stored in the columns represented by the +slots, specified by the CLOS slot names SLOTS, of View Class +instance OBJECT. DATABASE defaults to *DEFAULT-DATABASE* and +specifies the database in which the update is made only if OBJECT +is not associated with a database. In this case, a record is +created in the appropriate table of DATABASE and the attributes +represented by SLOTS are initialised from the values of the +supplied slots with other attributes having default +values. Furthermore, OBJECT becomes associated with DATABASE.")) (defgeneric update-records-from-instance (object &key database) (:documentation - "Using an instance of a view class, OBJECT, update the database -table that stores its instance data. If OBJECT is already associated -with a database, that database is used, and DATABASE is ignored. If -OBJECT is not yet associated with a database, a record is created for -instance in the appropriate table of DATABASE and the instance becomes -associated with that database.")) + "Using an instance of a View Class, OBJECT, update the table +that stores its instance data. DATABASE defaults to +*DEFAULT-DATABASE* and specifies the database in which the update +is made only if OBJECT is not associated with a database. In this +case, a record is created in the appropriate table of DATABASE +using values from the slot values of OBJECT, and OBJECT becomes +associated with DATABASE.")) -(defgeneric delete-instance-records (instance) +(defgeneric delete-instance-records (object) (:documentation - "Deletes the records represented by INSTANCE from the database -associated with it. If INSTANCE has no associated database, an error -is signalled.")) + "Deletes the records represented by OBJECT in the appropriate +table of the database associated with OBJECT. If OBJECT is not +yet associated with a database, an error is signalled.")) -(defgeneric update-instance-from-records (instance &key database) +(defgeneric update-instance-from-records (object &key database) (:documentation - "The generic function UPDATE-INSTANCE-FROM-RECORDS updates the -values in the slots of the View Class instance INSTANCE using the data -in the database DATABASE which defaults to the DATABASE that instance -is associated with, or the value of *DEFAULT-DATABASE*. If INSTANCE is -associated with a database, then DATABASE must be that same -database. The update is not recursive on joins. Join slots (that is, -slots with :db-kind :join ) are updated, but the joined objects are -not updated.")) + "Updates the slot values of the View Class instance OBJECT +using the attribute values of the appropriate table of DATABASE +which defaults to the database associated with OBJECT or, if +OBJECT is not associated with a database, *DEFAULT-DATABASE*. +Join slots are updated but instances of the class on which the +join is made are not updated.")) -(defgeneric update-slot-from-record (instance slot &key database) +(defgeneric update-slot-from-record (object slot &key database) (:documentation - "Updates the value in the slot SLOT of the View Class instance -INSTANCE using the data in the database DATABASE which defaults to the -database that INSTANCE is associated with, or the value of -*DEFAULT-DATABASE*. The argument SLOT is the CLOS slot name, the -corresponding column names are derived from the View Class -definition. The update is not recursive on joins. Join slots (that is, -slots with :db-kind :join) are updated, but the joined objects are not + "Updates the slot value, specified by the CLOS slot name SLOT, +of the View Class instance OBJECT using the attribute values of +the appropriate table of DATABASE which defaults to the database +associated with OBJECT or, if OBJECT is not associated with a +database, *DEFAULT-DATABASE*. Join slots are updated but +instances of the class on which the join is made are not updated.")) -(defgeneric instance-refreshed (instance) +(defgeneric instance-refreshed (object) (:documentation - "The function INSTANCE-REFRESHED is called inside SELECT when its -REFRESH argument is true and the instance INSTANCE has just been -updated. The supplied method on STANDARD-DB-OBJECT does nothing. If -your application needs to take action when a View Class instance has -been updated by (select ... :refresh t) then add an INSTANCE-REFRESH -method specializing on your subclass of STANDARD-DB-OBJECT.")) + "Provides a hook which is called within an object oriented +call to SELECT with a non-nil value of REFRESH when the View +Class instance OBJECT has been updated from the database. A +method specialised on STANDARD-DB-OBJECT is provided which has no +effects. Methods specialised on particular View Classes can be +used to specify any operations that need to be made on View +Classes instances which have been updated in calls to SELECT.")) (defgeneric update-slot-with-null (instance slotname slotdef) (:documentation "Called to update a slot when its column has a NULL @@ -120,8 +123,4 @@ DATABASE-NULL-VALUE on the type of the slot.")) ) (defgeneric read-sql-value (val type database) ) -(defgeneric add-to-relation (target slot-name value) - ) -(defgeneric remove-from-relation (target slot-name value) - ) diff --git a/sql/objects.lisp b/sql/objects.lisp index e6a9457..fd246c9 100644 --- a/sql/objects.lisp +++ b/sql/objects.lisp @@ -72,9 +72,8 @@ (defun create-view-from-class (view-class-name &key (database *default-database*)) - "Creates a view in DATABASE based on VIEW-CLASS-NAME which defines -the view. The argument DATABASE has a default value of -*DEFAULT-DATABASE*." + "Creates a table as defined by the View Class VIEW-CLASS-NAME +in DATABASE which defaults to *DEFAULT-DATABASE*." (let ((tclass (find-class view-class-name))) (if tclass (let ((*default-database* database)) @@ -123,9 +122,8 @@ the view. The argument DATABASE has a default value of ;; (defun drop-view-from-class (view-class-name &key (database *default-database*)) - "Deletes a view or base table from DATABASE based on VIEW-CLASS-NAME -which defines that view. The argument DATABASE has a default value of -*DEFAULT-DATABASE*." + "Removes a table defined by the View Class VIEW-CLASS-NAME from +DATABASE which defaults to *DEFAULT-DATABASE*." (let ((tclass (find-class view-class-name))) (if tclass (let ((*default-database* database)) @@ -148,12 +146,10 @@ which defines that view. The argument DATABASE has a default value of (defun list-classes (&key (test #'identity) (root-class (find-class 'standard-db-object)) (database *default-database*)) - "The LIST-CLASSES function collects all the classes below -ROOT-CLASS, which defaults to standard-db-object, that are connected -to the supplied DATABASE and which satisfy the TEST function. The -default for the TEST argument is identity. By default, LIST-CLASSES -returns a list of all the classes connected to the default database, -*DEFAULT-DATABASE*." + "Returns a list of all the View Classes which are connected to +DATABASE, which defaults to *DEFAULT-DATABASE*, and which descend +from the class ROOT-CLASS and which satisfy the function TEST. By +default ROOT-CLASS is STANDARD-DB-OBJECT and TEST is IDENTITY." (flet ((find-superclass (class) (member root-class (class-precedence-list class)))) (let ((view-classes (and database (database-view-classes database)))) @@ -167,17 +163,40 @@ returns a list of all the classes connected to the default database, ;; (defmacro def-view-class (class supers slots &rest cl-options) - "Extends the syntax of defclass to allow special slots to be mapped -onto the attributes of database views. The macro DEF-VIEW-CLASS -creates a class called CLASS which maps onto a database view. Such a -class is called a View Class. The macro DEF-VIEW-CLASS extends the -syntax of DEFCLASS to allow special base slots to be mapped onto the -attributes of database views (presently single tables). When a select -query that names a View Class is submitted, then the corresponding -database view is queried, and the slots in the resulting View Class -instances are filled with attribute values from the database. If -SUPERS is nil then STANDARD-DB-OBJECT automatically becomes the -superclass of the newly-defined View Class." + "Creates a View Class called CLASS whose slots SLOTS can map +onto the attributes of a table in a database. If SUPERS is nil +then the superclass of CLASS will be STANDARD-DB-OBJECT, +otherwise SUPERS is a list of superclasses for CLASS which must +include STANDARD-DB-OBJECT or a descendent of this class. The +syntax of DEFCLASS is extended through the addition of a class +option :base-table which defines the database table onto which +the View Class maps and which defaults to CLASS. The DEFCLASS +syntax is also extended through additional slot +options. The :db-kind slot option specifies the kind of DB +mapping which is performed for this slot and defaults to :base +which indicates that the slot maps to an ordinary column of the +database table. A :db-kind value of :key indicates that this slot +is a special kind of :base slot which maps onto a column which is +one of the unique keys for the database table, the value :join +indicates this slot represents a join onto another View Class +which contains View Class objects, and the value :virtual +indicates a standard CLOS slot which does not map onto columns of +the database table. If a slot is specified with :db-kind :join, +the slot option :db-info contains a list which specifies the +nature of the join. For slots of :db-kind :base or :key, +the :type slot option has a special interpretation such that Lisp +types, such as string, integer and float are automatically +converted into appropriate SQL types for the column onto which +the slot maps. This behaviour may be over-ridden using +the :db-type slot option which is a string specifying the +vendor-specific database type for this slot's column definition +in the database. The :column slot option specifies the name of +the SQL column which the slot maps onto, if :db-kind is +not :virtual, and defaults to the slot name. The :void-value slot +option specifies the value to store if the SQL value is NULL and +defaults to NIL. The :db-constraints slot option is a string +representing an SQL table constraint expression or a list of such +strings." `(progn (defclass ,class ,supers ,slots ,@(if (find :metaclass `,cl-options :key #'car) @@ -812,13 +831,24 @@ superclass of the newly-defined View Class." ;;; Remote Joins (defvar *default-update-objects-max-len* nil - "The default maximum number of objects supplying data for a - query when updating remote joins.") - -(defun update-object-joins (objects &key (slots t) (force-p t) - class-name (max-len *default-update-objects-max-len*)) - "Updates the remote join slots, that is those slots defined without -:retrieval :immediate." + "The default value to use for the MAX-LEN keyword argument to + UPDATE-OBJECT-JOINS.") + +(defun update-objects-joins (objects &key (slots t) (force-p t) + class-name (max-len + *default-update-objects-max-len*)) + "Updates from the records of the appropriate database tables +the join slots specified by SLOTS in the supplied list of View +Class instances OBJECTS. SLOTS is t by default which means that +all join slots with :retrieval :immediate are updated. CLASS-NAME +is used to specify the View Class of all instance in OBJECTS and +default to nil which means that the class of the first instance +in OBJECTS is used. FORCE-P is t by default which means that all +join slots are updated whereas a value of nil means that only +unbound join slots are updated. MAX-LEN defaults to +*DEFAULT-UPDATE-OBJECTS-MAX-LEN* and when non-nil specifies that +UPDATE-OBJECT-JOINS may issue multiple database queries with a +maximum of MAX-LEN instances updated in each query." (assert (or (null max-len) (plusp max-len))) (when objects (unless class-name @@ -1088,35 +1118,49 @@ superclass of the newly-defined View Class." (defmethod instance-refreshed ((instance standard-db-object))) (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." + "Executes a query on DATABASE, which has a default value of +*DEFAULT-DATABASE*, specified by the SQL expressions supplied +using the remaining arguments in SELECT-ALL-ARGS. The SELECT +argument can be used to generate queries in both functional and +object oriented contexts. + +In the functional case, the required arguments specify the +columns selected by the query and may be symbolic SQL expressions +or strings representing attribute identifiers. Type modified +identifiers indicate that the values selected from the specified +column are converted to the specified lisp type. The keyword +arguments ALL, DISTINCT, FROM, GROUP-by, HAVING, ORDER-BY, +SET-OPERATION and WHERE are used to specify, using the symbolic +SQL syntax, the corresponding components of the SQL query +generated by the call to SELECT. RESULT-TYPES is a list of +symbols which specifies the lisp type for each field returned by +the query. If RESULT-TYPES is nil all results are returned as +strings whereas the default value of :auto means that the lisp +types are automatically computed for each field. FIELD-NAMES is t +by default which means that the second value returned is a list +of strings representing the columns selected by the query. If +FIELD-NAMES is nil, the list of column names is not returned as a +second value. + +In the object oriented case, the required arguments to SELECT are +symbols denoting View Classes which specify the database tables +to query. In this case, SELECT returns a list of View Class +instances whose slots are set from the attribute values of the +records in the specified table. Slot-value is a legal operator +which can be employed as part of the symbolic SQL syntax used in +the WHERE keyword argument to SELECT. REFRESH is nil by default +which means that the View Class instances returned are retrieved +from a cache if an equivalent call to SELECT has previously been +issued. If REFRESH is true, the View Class instances returned are +updated as necessary from the database and the generic function +INSTANCE-REFRESHED is called to perform any necessary operations +on the updated instances. + +In both object oriented and functional contexts, FLATP has a +default value of nil which means that the results are returned as +a list of lists. If FLATP is t and only one result is returned +for each record selected in the query, the results are returned +as elements of a list." (flet ((select-objects (target-args) (and target-args diff --git a/sql/package.lisp b/sql/package.lisp index e9362c3..77100e5 100644 --- a/sql/package.lisp +++ b/sql/package.lisp @@ -241,8 +241,8 @@ #:table-exists-p ; table xx #:list-attributes ; table xx #:attribute-type ; table xx - #:list-attribute-types ; table xx - #:*cache-table-queries-default* + #:list-attribute-types ; table xx + #:*cache-table-queries-default* ; table xx #:create-view ; table xx #:drop-view ; table xx #:create-index ; table xx @@ -255,9 +255,9 @@ #:drop-view-from-class ; objects xx ;;OODML #:instance-refreshed ; objects xx - #:update-object-joins ; - #:*default-update-objects-max-len* ; - #:update-slot-from-record ; objects xx + #:update-objects-joins ; objects xx + #:*default-update-objects-max-len* ; objects xx + #:update-slot-from-record ; objects xx #:update-instance-from-records ; objects xx #:update-records-from-instance ; objects xx #:update-record-from-slot ; objects xx @@ -290,12 +290,10 @@ #:set-sequence-position ; table xx ;;OODDL #:view-table ; metaclass x - #:universal-time ; objects xx + #:universal-time ; objects xx #:bigint ;;OODML #:*db-auto-sync* ; objects xx - #:add-to-relation ; objects x - #:remove-from-relation ; objects x #:read-sql-value ; objects x #:database-output-sql-as-type ; objects x #:database-get-type-specifier ; objects x diff --git a/tests/test-oodml.lisp b/tests/test-oodml.lisp index 549ddbc..abbaddd 100644 --- a/tests/test-oodml.lisp +++ b/tests/test-oodml.lisp @@ -446,7 +446,7 @@ :flatp t)) (dea-list-copy (copy-seq dea-list)) (initially-unbound (every #'(lambda (dea) (not (slot-boundp dea 'address))) dea-list))) - (update-object-joins dea-list) + (update-objects-joins dea-list) (values initially-unbound (equal dea-list dea-list-copy) -- 2.34.1