1 ;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*-
2 ;;;; *************************************************************************
3 ;;;; FILE IDENTIFICATION
5 ;;;; Name: conditions.lisp
6 ;;;; Purpose: Error conditions for high-level SQL interface
7 ;;;; Programmers: Kevin M. Rosenberg based on
8 ;;;; Original code by Pierre R. Mai
9 ;;;; Date Started: Feb 2002
13 ;;;; This file, part of CLSQL, is Copyright (c) 2002-2004 by Kevin M. Rosenberg
14 ;;;; and Copyright (c) 1999-2001 by Pierre R. Mai
16 ;;;; CLSQL users are granted the rights to distribute and use this software
17 ;;;; as governed by the terms of the Lisp Lesser GNU Public License
18 ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL.
19 ;;;; *************************************************************************
21 (in-package #:clsql-sys)
23 (defvar *backend-warning-behavior* :warn
24 "Action to perform on warning messages from backend. Default is to :warn. May also be
25 set to :error to signal an error or :ignore/nil to silently ignore the warning.")
28 (define-condition clsql-condition ()
31 (define-condition clsql-error (error clsql-condition)
34 (define-condition clsql-simple-error (simple-condition clsql-error)
37 (define-condition clsql-warning (warning clsql-condition)
40 (define-condition clsql-simple-warning (simple-condition clsql-warning)
43 (define-condition clsql-generic-error (clsql-error)
44 ((message :initarg :message
45 :reader clsql-generic-error-message))
46 (:report (lambda (c stream)
47 (format stream (clsql-generic-error-message c)))))
49 (define-condition clsql-invalid-spec-error (clsql-error)
50 ((connection-spec :initarg :connection-spec
51 :reader clsql-invalid-spec-error-connection-spec)
52 (database-type :initarg :database-type
53 :reader clsql-invalid-spec-error-database-type)
54 (template :initarg :template
55 :reader clsql-invalid-spec-error-template))
56 (:report (lambda (c stream)
57 (format stream "The connection specification ~A~%is invalid for database type ~A.~%The connection specification must conform to ~A"
58 (clsql-invalid-spec-error-connection-spec c)
59 (clsql-invalid-spec-error-database-type c)
60 (clsql-invalid-spec-error-template c)))))
62 (defmacro check-connection-spec (connection-spec database-type template)
63 "Check the connection specification against the provided template,
64 and signal an clsql-invalid-spec-error if they don't match."
66 (destructuring-bind ,template ,connection-spec
67 (declare (ignore ,@(remove '&optional template)))
69 (error () (error 'clsql-invalid-spec-error
70 :connection-spec ,connection-spec
71 :database-type ,database-type
72 :template (quote ,template)))))
74 (define-condition clsql-access-error (clsql-error)
75 ((database-type :initarg :database-type
76 :reader clsql-access-error-database-type)
77 (connection-spec :initarg :connection-spec
78 :reader clsql-access-error-connection-spec)
79 (error :initarg :error :reader clsql-access-error-error))
80 (:report (lambda (c stream)
81 (format stream "While trying to access database ~A~% using database-type ~A:~% Error ~A~% has occurred."
82 (database-name-from-spec
83 (clsql-access-error-connection-spec c)
84 (clsql-access-error-database-type c))
85 (clsql-access-error-database-type c)
86 (clsql-access-error-error c)))))
88 (define-condition clsql-connect-error (clsql-access-error)
89 ((errno :initarg :errno :reader clsql-connect-error-errno))
90 (:report (lambda (c stream)
91 (format stream "While trying to connect to database ~A~% using database-type ~A:~% Error ~D / ~A~% has occurred."
92 (database-name-from-spec
93 (clsql-access-error-connection-spec c)
94 (clsql-access-error-database-type c))
95 (clsql-access-error-database-type c)
96 (clsql-connect-error-errno c)
97 (clsql-access-error-error c)))))
99 (define-condition clsql-sql-error (clsql-error)
100 ((database :initarg :database :reader clsql-sql-error-database)
101 (message :initarg :message :initform nil :reader clsql-sql-error-message)
102 (expression :initarg :expression :initarg nil :reader clsql-sql-error-expression)
103 (errno :initarg :errno :initarg nil :reader clsql-sql-error-errno)
104 (error :initarg :error :initarg nil :reader clsql-sql-error-error))
105 (:report (lambda (c stream)
106 (if (clsql-sql-error-message c)
107 (format stream "While accessing database ~A,~% Error ~A~% has occurred."
108 (clsql-sql-error-database c)
109 (clsql-sql-error-message c))
110 (format stream "While accessing database ~A~% with expression ~S:~% Error ~D / ~A~% has occurred."
111 (clsql-sql-error-database c)
112 (clsql-sql-error-expression c)
113 (clsql-sql-error-errno c)
114 (clsql-sql-error-error c))))))
116 (define-condition clsql-database-warning (clsql-warning)
117 ((database :initarg :database :reader clsql-database-warning-database)
118 (message :initarg :message :reader clsql-database-warning-message))
119 (:report (lambda (c stream)
120 (format stream "While accessing database ~A~% Warning: ~A~% has occurred."
121 (clsql-database-warning-database c)
122 (clsql-database-warning-message c)))))
124 (define-condition clsql-exists-condition (clsql-condition)
125 ((old-db :initarg :old-db :reader clsql-exists-condition-old-db)
126 (new-db :initarg :new-db :reader clsql-exists-condition-new-db
128 (:report (lambda (c stream)
129 (format stream "In call to ~S:~%" 'connect)
131 ((null (clsql-exists-condition-new-db c))
133 " There is an existing connection ~A to database ~A."
134 (clsql-exists-condition-old-db c)
135 (database-name (clsql-exists-condition-old-db c))))
136 ((eq (clsql-exists-condition-new-db c)
137 (clsql-exists-condition-old-db c))
139 " Using existing connection ~A to database ~A."
140 (clsql-exists-condition-old-db c)
141 (database-name (clsql-exists-condition-old-db c))))
144 " Created new connection ~A to database ~A~%, although there is an existing connection (~A)."
145 (clsql-exists-condition-new-db c)
146 (database-name (clsql-exists-condition-new-db c))
147 (clsql-exists-condition-old-db c)))))))
149 (define-condition clsql-exists-warning (clsql-exists-condition
153 (define-condition clsql-exists-error (clsql-exists-condition
157 (define-condition clsql-closed-error (clsql-error)
158 ((database :initarg :database :reader clsql-closed-error-database))
159 (:report (lambda (c stream)
160 (format stream "The database ~A has already been closed."
161 (clsql-closed-error-database c)))))
163 (define-condition clsql-no-database-error (clsql-error)
164 ((database :initarg :database :reader clsql-no-database-error-database))
165 (:report (lambda (c stream)
166 (format stream "~S is not a CLSQL database."
167 (clsql-no-database-error-database c)))))
169 (define-condition clsql-odbc-error (clsql-error)
170 ((odbc-message :initarg :odbc-message
171 :reader clsql-odbc-error-message)
172 (sql-state :initarg :sql-state :initform nil
173 :reader clsql-odbc-error-sql-state))
174 (:report (lambda (c stream)
175 (format stream "[ODBC error] ~A; state: ~A"
176 (clsql-odbc-error-message c)
177 (clsql-odbc-error-sql-state c)))))
182 (defun signal-closed-database-error (database)
183 (cerror "Ignore this error and return nil."
187 (defun signal-no-database-error (database)
188 (error 'clsql-no-database-error :database database))
190 (define-condition clsql-type-error (clsql-error clsql-condition)
191 ((slotname :initarg :slotname
192 :reader clsql-type-error-slotname)
193 (typespec :initarg :typespec
194 :reader clsql-type-error-typespec)
195 (value :initarg :value
196 :reader clsql-type-error-value))
197 (:report (lambda (c stream)
199 "Invalid value ~A in slot ~A, not of type ~A."
200 (clsql-type-error-value c)
201 (clsql-type-error-slotname c)
202 (clsql-type-error-typespec c)))))
204 (define-condition clsql-sql-syntax-error (clsql-error)
205 ((reason :initarg :reason
206 :reader clsql-sql-syntax-error-reason))
207 (:report (lambda (c stream)
208 (format stream "Invalid SQL syntax: ~A"
209 (clsql-sql-syntax-error-reason c)))))