r9457: Reworked CLSQL file structure.
[clsql.git] / sql / conditions.lisp
index 571054d4d95e9d10128c58c356b578383379b93e..dc48d2fc1201a1da10ad512041b0515621aa2975 100644 (file)
@@ -2,16 +2,12 @@
 ;;;; *************************************************************************
 ;;;; FILE IDENTIFICATION
 ;;;;
-;;;; Name:          conditions.lisp
-;;;; Purpose:       Error conditions for high-level SQL interface
-;;;; Programmers:   Kevin M. Rosenberg based on
-;;;;                 Original code by Pierre R. Mai 
-;;;; Date Started:  Feb 2002
+;;;; Name:     conditions.lisp
+;;;; Purpose:  Error conditions for CLSQL
 ;;;;
 ;;;; $Id$
 ;;;;
 ;;;; This file, part of CLSQL, is Copyright (c) 2002-2004 by Kevin M. Rosenberg
-;;;; and Copyright (c) 1999-2001 by Pierre R. Mai
 ;;;;
 ;;;; CLSQL users are granted the rights to distribute and use this software
 ;;;; as governed by the terms of the Lisp Lesser GNU Public License
   "Action to perform on warning messages from backend. Default is to :warn. May also be
 set to :error to signal an error or :ignore/nil to silently ignore the warning.")
 
-;;; Conditions
-(define-condition clsql-condition ()
+;;; CommonSQL-compatible conditions
+(define-condition sql-condition ()
   ())
 
-(define-condition clsql-error (error clsql-condition)
+(define-condition sql-error (simple-error)
   ())
 
-(define-condition clsql-simple-error (simple-condition clsql-error)
-  ())
-
-(define-condition clsql-warning (warning clsql-condition)
-  ())
-
-(define-condition clsql-simple-warning (simple-condition clsql-warning)
-  ())
-
-(define-condition clsql-generic-error (clsql-error)
-  ((message :initarg :message
-           :reader clsql-generic-error-message))
-  (:report (lambda (c stream)
-            (format stream (clsql-generic-error-message c)))))
-
-(define-condition clsql-invalid-spec-error (clsql-error)
-  ((connection-spec :initarg :connection-spec
-                   :reader clsql-invalid-spec-error-connection-spec)
-   (database-type :initarg :database-type
-                 :reader clsql-invalid-spec-error-database-type)
-   (template :initarg :template
-            :reader clsql-invalid-spec-error-template))
-  (:report (lambda (c stream)
-            (format stream "The connection specification ~A~%is invalid for database type ~A.~%The connection specification must conform to ~A"
-                    (clsql-invalid-spec-error-connection-spec c)
-                    (clsql-invalid-spec-error-database-type c)
-                    (clsql-invalid-spec-error-template c)))))
-
-(defmacro check-connection-spec (connection-spec database-type template)
-  "Check the connection specification against the provided template,
-and signal an clsql-invalid-spec-error if they don't match."
-  `(handler-case
-    (destructuring-bind ,template ,connection-spec 
-      (declare (ignore ,@(remove '&optional template)))
-      t)
-    (error () (error 'clsql-invalid-spec-error
-                    :connection-spec ,connection-spec
-                    :database-type ,database-type
-                    :template (quote ,template)))))
-
-(define-condition clsql-access-error (clsql-error)
-  ((database-type :initarg :database-type
-                 :reader clsql-access-error-database-type)
-   (connection-spec :initarg :connection-spec
-                   :reader clsql-access-error-connection-spec)
-   (error :initarg :error :reader clsql-access-error-error))
+(define-condition sql-database-error (sql-error)
+  ((error-id :initarg :error-id 
+            :initform nil
+            :reader sql-error-error-id)
+   (secondary-error-id :initarg :secondary-error-id
+                      :initform nil
+                      :reader sql-error-secondary-error-id)
+   (database-message :initarg :message
+                    :initform nil
+                    :reader sql-error-database-message)
+   (database :initarg :database
+                    :initform nil
+                    :reader sql-error-database))
   (:report (lambda (c stream)
-            (format stream "While trying to access database ~A~%  using database-type ~A:~%  Error ~A~%  has occurred."
-                    (database-name-from-spec
-                     (clsql-access-error-connection-spec c)
-                     (clsql-access-error-database-type c))
-                    (clsql-access-error-database-type c)
-                    (clsql-access-error-error c)))))
-
-(define-condition clsql-connect-error (clsql-access-error)
-  ((errno :initarg :errno :reader clsql-connect-error-errno))
+            (format stream "A database error occurred~A: ~A / ~A~%  ~A"
+                    (if (sql-error-database c)
+                        (format nil " on database ~A" (sql-error-database c))
+                        "")
+                    (sql-error-error-id c)
+                    (sql-error-secondary-error-id 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
+                 :reader sql-error-database-type)
+   (connection-spec :initarg :connection-spec :initform nil
+                 :reader sql-error-connection-spec))
   (:report (lambda (c stream)
             (format stream "While trying to connect to database ~A~%  using database-type ~A:~%  Error ~D / ~A~%  has occurred."
                     (database-name-from-spec
-                     (clsql-access-error-connection-spec c)
-                     (clsql-access-error-database-type c))
-                    (clsql-access-error-database-type c)
-                    (clsql-connect-error-errno c)
-                    (clsql-access-error-error c)))))
-
-(define-condition clsql-sql-error (clsql-error)
-  ((database :initarg :database :reader clsql-sql-error-database)
-   (message :initarg :message :initform nil :reader clsql-sql-error-message)
-   (expression :initarg :expression :initarg nil :reader clsql-sql-error-expression)
-   (errno :initarg :errno :initarg nil :reader clsql-sql-error-errno)
-   (error :initarg :error :initarg nil :reader clsql-sql-error-error))
+                     (sql-error-connection-spec c)
+                     (sql-error-database-type c))
+                    (sql-error-database-type c)
+                    (sql-error-error-id 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 
+              :reader sql-error-expression))
   (:report (lambda (c stream)
-            (if (clsql-sql-error-message c)
-                (format stream "While accessing database ~A~%, Error~%  ~A~%  has occurred."
-                        (clsql-sql-error-database c)
-                        (clsql-sql-error-message c))
-              (format stream "While accessing database ~A~%  with expression ~S:~%  Error ~D / ~A~%  has occurred."
-                      (clsql-sql-error-database c)
-                      (clsql-sql-error-expression c)
-                      (clsql-sql-error-errno c)
-                      (clsql-sql-error-error c))))))
-
-(define-condition clsql-database-warning (clsql-warning)
-  ((database :initarg :database :reader clsql-database-warning-database)
-   (message :initarg :message :reader clsql-database-warning-message))
+            (format stream "While accessing database ~A~%  with expression ~S:~%  Error ~D / ~A~%  has occurred."
+                    (sql-error-database c)
+                    (sql-error-expression c)
+                    (sql-error-error-id 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
+           :initform "Unspecified error"
+           :reader sql-user-error-message))
   (:report (lambda (c stream)
-            (format stream "While accessing database ~A~%  Warning: ~A~%  has occurred."
-                    (clsql-database-warning-database c)
-                    (clsql-database-warning-message c)))))
-
-(define-condition clsql-exists-condition (clsql-condition)
-   ((old-db :initarg :old-db :reader clsql-exists-condition-old-db)
-    (new-db :initarg :new-db :reader clsql-exists-condition-new-db
-           :initform nil))
-   (:report (lambda (c stream)
-             (format stream "In call to ~S:~%" 'connect)
-             (cond
-               ((null (clsql-exists-condition-new-db c))
-                (format stream
-                        "  There is an existing connection ~A to database ~A."
-                        (clsql-exists-condition-old-db c)
-                        (database-name (clsql-exists-condition-old-db c))))
-               ((eq (clsql-exists-condition-new-db c)
-                    (clsql-exists-condition-old-db c))
-                (format stream
-                        "  Using existing connection ~A to database ~A."
-                        (clsql-exists-condition-old-db c)
-                        (database-name (clsql-exists-condition-old-db c))))
-               (t
-                (format stream
-                        "  Created new connection ~A to database ~A~%, although there is an existing connection (~A)."
-                        (clsql-exists-condition-new-db c)
-                        (database-name (clsql-exists-condition-new-db c))
-                        (clsql-exists-condition-old-db c)))))))
-
-(define-condition clsql-exists-warning (clsql-exists-condition
-                                        clsql-warning)
-  ())
-
-(define-condition clsql-exists-error (clsql-exists-condition
-                                      clsql-error)
-  ())
+            (format stream "A CLSQL lisp code error occurred: ~A "
+                    (sql-user-error-message c))))
+  (:documentation  "Used to signal lisp errors inside CLSQL."))
 
-(define-condition clsql-closed-error (clsql-error)
-  ((database :initarg :database :reader clsql-closed-error-database))
-  (:report (lambda (c stream)
-            (format stream "The database ~A has already been closed."
-                    (clsql-closed-error-database c)))))
 
-(define-condition clsql-no-database-error (clsql-error)
-  ((database :initarg :database :reader clsql-no-database-error-database))
-  (:report (lambda (c stream)
-            (format stream "~S is not a CLSQL database." 
-                    (clsql-no-database-error-database c)))))
-
-(define-condition clsql-odbc-error (clsql-error)
-  ((odbc-message :initarg :odbc-message
-                :reader clsql-odbc-error-message)
-   (sql-state :initarg :sql-state :initform nil
-             :reader clsql-odbc-error-sql-state))
-  (:report (lambda (c stream)
-            (format stream "[ODBC error] ~A; state: ~A"
-                    (clsql-odbc-error-message c)
-                    (clsql-odbc-error-sql-state c)))))
 
 ;; Signal conditions
 
-
 (defun signal-closed-database-error (database)
-  (cerror "Ignore this error and return nil."
-         'clsql-closed-error
-         :database database))
+  (error 'sql-fatal-error
+        :database database
+        :message "Database is closed."))
 
 (defun signal-no-database-error (database)
-  (error 'clsql-no-database-error :database database))
-
-(define-condition clsql-type-error (clsql-error clsql-condition)
-  ((slotname :initarg :slotname
-            :reader clsql-type-error-slotname)
-   (typespec :initarg :typespec
-            :reader clsql-type-error-typespec)
-   (value :initarg :value
-         :reader clsql-type-error-value))
-  (:report (lambda (c stream)
-            (format stream
-                    "Invalid value ~A in slot ~A, not of type ~A."
-                    (clsql-type-error-value c)
-                    (clsql-type-error-slotname c)
-                    (clsql-type-error-typespec c)))))
-
-(define-condition clsql-sql-syntax-error (clsql-error)
-  ((reason :initarg :reason
-          :reader clsql-sql-syntax-error-reason))
+  (error 'sql-database-error
+        :database database
+        :message (format nil "~A is not a database." database)))
+
+
+;;; CLSQL Extensions
+
+(define-condition sql-warning (warning sql-condition)
+  ((message :initarg :message :reader sql-warning-message))
   (:report (lambda (c stream)
-            (format stream "Invalid SQL syntax: ~A"
-                    (clsql-sql-syntax-error-reason c)))))
+            (format stream (sql-warning-message c)))))
 
+(define-condition sql-database-warning (sql-warning)
+  ((database :initarg :database :reader sql-warning-database))
+  (:report (lambda (c stream)
+            (format stream 
+                    "While accessing database ~A~%  Warning: ~A~%  has occurred."
+                    (sql-warning-database c)
+                    (sql-warning-message c)))))