annotate base/database/database-connect.lisp @ 279:c591a5034da6

New base module for general database functions Ignore-this: 403f22ca6285cba4a23eeddb1d0a806f Currently just provides a slightly more secure way of connecting to a database. darcs-hash:20090519135617-16a00-ce026a38abfb53e5728cd0cbb6c976e403691dde.gz
author j.forth <j.forth@gold.ac.uk>
date Tue, 19 May 2009 14:56:17 +0100
parents
children e1842efb1dd4
rev   line source
j@279 1 (cl:in-package #:amuse-database-admin)
j@279 2
j@279 3 (defparameter *amuse-database* nil)
j@279 4
j@279 5 (defun connect-to-database (&key (database-name "amuse") username
j@279 6 use-tunnel (make-default t))
j@279 7 "Well, slightly more secure I guess. Requires that an option file
j@279 8 exists containing connection-spec s-expressions. If no such file
j@279 9 exists a skeleton file can be created by calling
j@279 10 make-db-option-file (the password still needs to be added
j@279 11 manually). The path is ~/.amuse.lisp.
j@279 12
j@279 13 A better approach might be to use something like:
j@279 14 http://www.cliki.net/trivial-configuration-parser. Or for slime to
j@279 15 prompt the user for the password something
j@279 16 like (swank::eval-in-emacs `(read-passwd \"Password: \")). However,
j@279 17 this presents other security issues.
j@279 18
j@279 19 If use-tunnel is t, then regardless of the host specified in the
j@279 20 connection-spec, it will be set to localhost. It is assumed that the
j@279 21 tunnel is already set up.
j@279 22
j@279 23 When make-default is t, the newly created connection is assigned to
j@279 24 *amuse-database*. If make-default is nil, then the connection is
j@279 25 returned and is expected to be handled by the caller. This is useful
j@279 26 for connecting to different databases within individual
j@279 27 implementations (mainly for testing purposes)."
j@279 28 (if (and make-default
j@279 29 *amuse-database*
j@279 30 (clsql-mysql::is-database-open *amuse-database*))
j@279 31 (error "A default AMuSE database connection already exists:
j@279 32 ~S" (clsql:database-name *amuse-database*))
j@279 33 (let ((connection-spec (%get-connection-spec database-name
j@279 34 username)))
j@279 35 (when use-tunnel
j@279 36 (setf (car connection-spec) "127.0.0.1"))
j@279 37 (let ((connection (%get-database-connection connection-spec)))
j@279 38 (when make-default
j@279 39 (setf *amuse-database* connection))
j@279 40 connection))))
j@279 41
j@279 42 (defun disconnect-from-database (&optional (database-connection
j@279 43 *amuse-database*))
j@279 44 (clsql:disconnect :database database-connection))
j@279 45
j@279 46 (defun make-db-option-file (&key database-name host username (port "3306"))
j@279 47 (with-open-file (stream (%make-db-option-file-pathname) :direction :output)
j@279 48 (sb-ext:run-program "chmod"
j@279 49 (list "600" (namestring
j@279 50 (%make-db-option-file-pathname)))
j@279 51 :search t)
j@279 52 (princ "
j@279 53 ;;; Option file containing connection-spec s-expressions for connecting
j@279 54 ;;; to a database from within AMuSE. You can have multiple specifications,
j@279 55 ;;; but they must be uniquely identifiable by database name or a combination
j@279 56 ;;; of database and username.
j@279 57
j@279 58 ;;; You need to fill in the missing <details>." stream)
j@279 59 (format stream "~2%(~S ~S ~S \"<pwd>\" ~S)"
j@279 60 (if host host "<host>")
j@279 61 (if database-name database-name "<db-name>")
j@279 62 (if username username "<username>")
j@279 63 port))
j@279 64 (warn "You now need to manually edit ~A."
j@279 65 (namestring (%make-db-option-file-pathname))))
j@279 66
j@279 67 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
j@279 68 ;;; Helper functions
j@279 69
j@279 70 (defun %get-database-connection (connection-spec)
j@279 71 (clsql:connect connection-spec
j@279 72 :if-exists :old
j@279 73 :database-type :mysql))
j@279 74
j@279 75 (defun %get-connection-spec (db-name username)
j@279 76 (let ((option-file (probe-file (%make-db-option-file-pathname))))
j@279 77 (if option-file
j@279 78 (with-open-file (stream option-file)
j@279 79 (loop for connection-spec = (read stream nil)
j@279 80 while connection-spec
j@279 81 do (destructuring-bind (host db usr pwd prt)
j@279 82 connection-spec
j@279 83 (declare (ignore host pwd prt))
j@279 84 (when (equal db-name db)
j@279 85 (when (or (null username)
j@279 86 (equal username usr))
j@279 87 (return connection-spec))))
j@279 88 finally (error "No connection-spec exists matching
j@279 89 database: ~A and username: ~A" db-name username)))
j@279 90 ;; If file doesn't exist, create it.
j@279 91 (error "~A option file does not exist.
j@279 92 You need to run: amuse-database-admin:make-db-option-file."
j@279 93 (namestring (%make-db-option-file-pathname))))))
j@279 94
j@279 95 (defun %make-db-option-file-pathname ()
j@279 96 (merge-pathnames (user-homedir-pathname) ".amuse.lisp"))