;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL.
;;;; *************************************************************************
-(in-package #:clsql-base-sys)
+(in-package #:clsql-base)
(setf (documentation 'database-name 'function)
"Returns the name of a database.")
(defvar *default-database* nil
"Specifies the default database to be used.")
+(defun is-database-open (database)
+ (eql (database-state database) :open))
+
(defun find-database (database &key (errorp t) (db-type nil))
"The function FIND-DATABASE, given a string DATABASE, searches
amongst the connected databases for one matching the name DATABASE. If
to the new connection, otherwise *default-database is not changed. If
pool is t the connection will be taken from the general pool, if pool
is a conn-pool object the connection will be taken from this pool."
+
+ (unless database-type
+ (error "Must specify a database-type."))
+
+ (when (stringp connection-spec)
+ (setq connection-spec (string-to-list-connection-spec connection-spec)))
+
+ (unless (member database-type *loaded-database-types*)
+ (asdf:operate 'asdf:load-op (ensure-keyword
+ (concatenate 'string
+ (symbol-name '#:clsql-)
+ (symbol-name database-type)))))
+
(if pool
(acquire-from-pool connection-spec database-type pool)
(let* ((db-name (database-name-from-spec connection-spec database-type))
(setq result
(database-connect connection-spec database-type)))
(when result
+ (setf (slot-value result 'state) :open)
(pushnew result *connected-databases*)
(when make-default (setq *default-database* result))
result))))
(setf *connected-databases* (delete database *connected-databases*))
(when (eq database *default-database*)
(setf *default-database* (car *connected-databases*)))
- (change-class database 'closed-database)
+ (setf (slot-value database 'state) :closed)
t)))))
closed. When non-nil (this is the default value) the connection is
closed without error checking. When FORCE is nil, an error is signaled
if the database connection has been lost."
- ;; TODO: just a placeholder
- (declare (ignore database error force)))
-
+ (let ((db (etypecase database
+ (database database)
+ ((or string list)
+ (let ((db (find-database database :errorp nil)))
+ (when (null db)
+ (if (and database error)
+ (error 'clsql-generic-error
+ :message
+ (format nil "Unable to find database with connection-spec ~A." database))
+ (return-from reconnect nil)))
+ db)))))
+
+ (when (is-database-open db)
+ (if force
+ (ignore-errors (disconnect :database db))
+ (disconnect :database db :error nil)))
+
+ (connect (connection-spec db))))
(defun status (&optional full)
output, for the connected databases and initialized database types. If
full is T, detailed status information is printed. The default value
of full is NIL."
- (declare (ignore full))
- ;; TODO: table details if full is true?
(flet ((get-data ()
(let ((data '()))
(dolist (db (connected-databases) data)
- (push (list (database-name db)
- (string (database-type db))
- (when (conn-pool db) "T" "NIL")
- (format nil "~A" (length (database-list-tables db)))
- (format nil "~A" (length (database-list-views db)))
- (if (equal db *default-database*) " *" ""))
- data))))
- (compute-sizes (data)
+ (push
+ (append
+ (list (if (equal db *default-database*) "*" "")
+ (database-name db)
+ (string-downcase (string (database-type db)))
+ (cond ((and (command-recording-stream db)
+ (result-recording-stream db))
+ "Both")
+ ((command-recording-stream db) "Commands")
+ ((result-recording-stream db) "Results")
+ (t "nil")))
+ (when full
+ (list
+ (if (conn-pool db) "t" "nil")
+ (format nil "~A" (length (database-list-tables db)))
+ (format nil "~A" (length (database-list-views db))))))
+ data))))
+ (compute-sizes (data)
(mapcar #'(lambda (x) (apply #'max (mapcar #'length x)))
(apply #'mapcar (cons #'list data))))
(print-separator (size)
(format t "~&~A" (make-string size :initial-element #\-))))
+ (format t "~&CLSQL STATUS: ~A~%" (iso-timestring (get-time)))
(let ((data (get-data)))
(when data
- (let* ((titles (list "NAME" "TYPE" "POOLED" "TABLES" "VIEWS" "DEFAULT"))
+ (let* ((titles (if full
+ (list "" "DATABASE" "TYPE" "RECORDING" "POOLED"
+ "TABLES" "VIEWS")
+ (list "" "DATABASE" "TYPE" "RECORDING")))
(sizes (compute-sizes (cons titles data)))
(total-size (+ (apply #'+ sizes) (* 2 (1- (length titles)))))
(control-string (format nil "~~&~~{~{~~~AA ~}~~}" sizes)))
(print-separator total-size))))
(values)))
+(defun create-database (connection-spec &key database-type)
+ (when (stringp connection-spec)
+ (setq connection-spec (string-to-list-connection-spec connection-spec)))
+ (database-create connection-spec database-type))
+
+(defun probe-database (connection-spec &key database-type)
+ (when (stringp connection-spec)
+ (setq connection-spec (string-to-list-connection-spec connection-spec)))
+ (database-probe connection-spec database-type))
+
+(defun destroy-database (connection-spec &key database-type)
+ (when (stringp connection-spec)
+ (setq connection-spec (string-to-list-connection-spec connection-spec)))
+ (database-destroy connection-spec database-type))
+
+(defun list-databases (connection-spec &key database-type)
+ (when (stringp connection-spec)
+ (setq connection-spec (string-to-list-connection-spec connection-spec)))
+ (database-list connection-spec database-type))
(defmacro with-database ((db-var connection-spec &rest connect-args) &body body)
"Evaluate the body in an environment, where `db-var' is bound to the
`(progv '(*default-database*)
(list ,database)
,@body))
+