:safe 'stringp)
(defcustom sql-port 0
- "Default port."
+ "Default port for connecting to a MySQL or Postgres server."
:version "24.1"
:type 'number
:group 'SQL
'(:font-lock :sqli-program :sqli-options :sqli-login :statement))
(defcustom sql-connection-alist nil
- "An alist of connection parameters for interacting with a SQL
- product.
-
+ "An alist of connection parameters for interacting with a SQL product.
Each element of the alist is as follows:
\(CONNECTION \(SQL-VARIABLE VALUE) ...)
Where CONNECTION is a symbol identifying the connection, SQL-VARIABLE
is the symbol name of a SQL mode variable, and VALUE is the value to
-be assigned to the variable.
-
-The most common SQL-VARIABLE settings associated with a connection
-are:
-
- `sql-product'
- `sql-user'
- `sql-password'
- `sql-port'
- `sql-server'
- `sql-database'
+be assigned to the variable. The most common SQL-VARIABLE settings
+associated with a connection are: `sql-product', `sql-user',
+`sql-password', `sql-port', `sql-server', and `sql-database'.
If a SQL-VARIABLE is part of the connection, it will not be
-prompted for during login."
-
+prompted for during login. The command `sql-connect' starts a
+predefined SQLi session using the parameters from this list.
+Connections defined here appear in the submenu SQL->Start... for
+making new SQLi sessions."
:type `(alist :key-type (string :tag "Connection")
:value-type
(set
This hook is invoked in a buffer once it is ready to accept input
for the first time."
+ :version "24.1"
:type 'hook
:group 'SQL)
All products share this list; products should define a regexp to
identify additional keywords in a variable defined by
-the :statement feature.")
+the :statement feature."
+ :version "24.1"
+ :type 'string
+ :group 'SQL)
;; Customization for Oracle
:version "24.1"
:group 'SQL)
-(defcustom sql-oracle-statement-starters (regexp-opt '("declare" "begin" "with"))
- "Additional statement starting keywords in Oracle.")
+(defcustom sql-oracle-statement-starters
+ (regexp-opt '("declare" "begin" "with"))
+ "Additional statement starting keywords in Oracle."
+ :version "24.1"
+ :type 'string
+ :group 'SQL)
(defcustom sql-oracle-scan-on t
"Non-nil if placeholders should be replaced in Oracle SQLi.
SET DEFINE OFF
In older versions of SQL*Plus, this was the SET SCAN OFF command."
+ :version "24.1"
:type 'boolean
:group 'SQL)
"Read a password using PROMPT. Optional DEFAULT is password to start with."
(read-passwd prompt nil default))
-(defun sql-get-login-ext (prompt last-value history-var plist)
+(defun sql-get-login-ext (symbol prompt history-var plist)
"Prompt user with extended login parameters.
+The global value of SYMBOL is the last value and the global value
+of the SYMBOL is set based on the user's input.
+
If PLIST is nil, then the user is simply prompted for a string
value.
The `:completion' property prompts for a string specified by its
value. (The property value is used as the PREDICATE argument to
`completing-read'.)"
- (let* ((default (plist-get plist :default))
- (prompt-def
- (if default
- (if (string-match "\\(\\):[ \t]*\\'" prompt)
- (replace-match (format " (default \"%s\")" default) t t prompt 1)
- (replace-regexp-in-string "[ \t]*\\'"
- (format " (default \"%s\") " default)
- prompt t t))
- prompt))
- (use-dialog-box nil))
- (cond
- ((plist-member plist :file)
- (expand-file-name
- (read-file-name prompt
- (file-name-directory last-value) default t
- (file-name-nondirectory last-value)
- (when (plist-get plist :file)
- `(lambda (f)
- (string-match
- (concat "\\<" ,(plist-get plist :file) "\\>")
- (file-name-nondirectory f)))))))
-
- ((plist-member plist :completion)
- (completing-read prompt-def (plist-get plist :completion) nil t
- last-value history-var default))
-
- ((plist-get plist :number)
- (read-number prompt (or default last-value 0)))
-
- (t
- (let ((r (read-from-minibuffer prompt-def last-value nil nil history-var nil)))
- (if (string= "" r) (or default "") r))))))
+ (set-default
+ symbol
+ (let* ((default (plist-get plist :default))
+ (last-value (default-value symbol))
+ (prompt-def
+ (if default
+ (if (string-match "\\(\\):[ \t]*\\'" prompt)
+ (replace-match (format " (default \"%s\")" default) t t prompt 1)
+ (replace-regexp-in-string "[ \t]*\\'"
+ (format " (default \"%s\") " default)
+ prompt t t))
+ prompt))
+ (use-dialog-box nil))
+ (cond
+ ((plist-member plist :file)
+ (expand-file-name
+ (read-file-name prompt
+ (file-name-directory last-value) default t
+ (file-name-nondirectory last-value)
+ (when (plist-get plist :file)
+ `(lambda (f)
+ (string-match
+ (concat "\\<" ,(plist-get plist :file) "\\>")
+ (file-name-nondirectory f)))))))
+
+ ((plist-member plist :completion)
+ (completing-read prompt-def (plist-get plist :completion) nil t
+ last-value history-var default))
+
+ ((plist-get plist :number)
+ (read-number prompt (or default last-value 0)))
+
+ (t
+ (let ((r (read-from-minibuffer prompt-def last-value nil nil history-var nil)))
+ (if (string= "" r) (or default "") r)))))))
(defun sql-get-login (&rest what)
"Get username, password and database from the user.
(cond
((eq token 'user) ; user
- (setq sql-user
- (sql-get-login-ext "User: " sql-user
- 'sql-user-history plist)))
+ (sql-get-login-ext 'sql-user "User: " 'sql-user-history plist))
- ((eq token 'password) ; password
- (setq sql-password
- (sql-read-passwd "Password: " sql-password)))
+ ((eq token 'password) ; password
+ (setq-default sql-password
+ (sql-read-passwd "Password: " sql-password)))
- ((eq token 'server) ; server
- (setq sql-server
- (sql-get-login-ext "Server: " sql-server
- 'sql-server-history plist)))
+ ((eq token 'server) ; server
+ (sql-get-login-ext 'sql-server "Server: " 'sql-server-history plist))
- ((eq token 'database) ; database
- (setq sql-database
- (sql-get-login-ext "Database: " sql-database
- 'sql-database-history plist)))
+ ((eq token 'database) ; database
+ (sql-get-login-ext 'sql-database "Database: " 'sql-database-history plist))
((eq token 'port) ; port
- (setq sql-port
- (sql-get-login-ext "Port: " sql-port
- nil (append '(:number t) plist)))))))
+ (sql-get-login-ext 'sql-port "Port: " nil (append '(:number t) plist))))))
what))
(defun sql-find-sqli-buffer (&optional product connection)
(read-from-minibuffer prompt tname))))
(defun sql-list-all (&optional enhanced)
- "List all database objects."
+ "List all database objects.
+With optional prefix argument ENHANCED, displays additional
+details or extends the listing to include other schemas objects."
(interactive "P")
(let ((sqlbuf (sql-find-sqli-buffer)))
(unless sqlbuf
(set (make-local-variable 'sql-buffer) sqlbuf))))
(defun sql-list-table (name &optional enhanced)
- "List the details of a database table. "
+ "List the details of a database table named NAME.
+Displays the columns in the relation. With optional prefix argument
+ENHANCED, displays additional details about each column."
(interactive
(list (sql-read-table-name "Table name: ")
current-prefix-arg))
(set (make-local-variable 'sql-server) sql-server)
(set (make-local-variable 'sql-port) sql-port)
(set (make-local-variable 'sql-connection) sql-connection)
+ (setq-default sql-connection nil)
;; Contains the name of database objects
(set (make-local-variable 'sql-contains-names) t)
;; Keep track of existing object names
;; Settings are defined
(if connect-set
;; Set the desired parameters
- (eval `(let*
- (,@(cdr connect-set)
- ;; :sqli-login params variable
- (param-var (sql-get-product-feature sql-product
- :sqli-login nil t))
- ;; :sqli-login params value
- (login-params (sql-get-product-feature sql-product
- :sqli-login))
- ;; which params are in the connection
- (set-params (mapcar
- (lambda (v)
- (cond
- ((eq (car v) 'sql-user) 'user)
- ((eq (car v) 'sql-password) 'password)
- ((eq (car v) 'sql-server) 'server)
- ((eq (car v) 'sql-database) 'database)
- ((eq (car v) 'sql-port) 'port)
- (t (car v))))
- (cdr connect-set)))
- ;; the remaining params (w/o the connection params)
- (rem-params (sql-for-each-login
- login-params
- (lambda (token plist)
- (unless (member token set-params)
- (if plist
- (cons token plist)
- token))))))
-
- ;; Set the remaining parameters and start the
- ;; interactive session
- (eval `(let ((sql-connection ,connection)
- (,param-var ',rem-params))
- (sql-product-interactive sql-product
- new-name)))))
+ (let (param-var login-params set-params rem-params)
+
+ ;; :sqli-login params variable
+ (setq param-var
+ (sql-get-product-feature sql-product :sqli-login nil t))
+
+ ;; :sqli-login params value
+ (setq login-params
+ (sql-get-product-feature sql-product :sqli-login))
+
+ ;; Params in the connection
+ (setq set-params
+ (mapcar
+ (lambda (v)
+ (cond
+ ((eq (car v) 'sql-user) 'user)
+ ((eq (car v) 'sql-password) 'password)
+ ((eq (car v) 'sql-server) 'server)
+ ((eq (car v) 'sql-database) 'database)
+ ((eq (car v) 'sql-port) 'port)
+ (t (car v))))
+ (cdr connect-set)))
+
+ ;; the remaining params (w/o the connection params)
+ (setq rem-params
+ (sql-for-each-login login-params
+ (lambda (token plist)
+ (unless (member token set-params)
+ (if plist (cons token plist) token)))))
+
+ ;; Set the parameters and start the interactive session
+ (mapc
+ (lambda (vv)
+ (set-default (car vv) (eval (cadr vv))))
+ (cdr connect-set))
+ (setq-default sql-connection connection)
+
+ ;; Start the SQLi session with revised list of login parameters
+ (eval `(let ((,param-var ',rem-params))
+ (sql-product-interactive sql-product new-name))))
(message "SQL Connection <%s> does not exist" connection)
nil)))
+
(message "No SQL Connections defined")
nil))
;; Connect to database.
(message "Login...")
- (funcall (sql-get-product-feature product :sqli-comint-func)
- product
- (sql-get-product-feature product :sqli-options))
+ (let ((sql-user (default-value 'sql-user))
+ (sql-password (default-value 'sql-password))
+ (sql-server (default-value 'sql-server))
+ (sql-database (default-value 'sql-database))
+ (sql-port (default-value 'sql-port)))
+ (funcall (sql-get-product-feature product :sqli-comint-func)
+ product
+ (sql-get-product-feature product :sqli-options)))
;; Set SQLi mode.
(let ((sql-interactive-product product))
(setq new-sqli-buffer (current-buffer))
(when new-name
(sql-rename-buffer new-name))
- (set (make-local-variable 'sql-buffer)
+ (set (make-local-variable 'sql-buffer)
(buffer-name new-sqli-buffer))
;; Set `sql-buffer' in the start buffer
passed as command line arguments."
(let ((program (sql-get-product-feature product :sqli-program))
(buf-name "SQL"))
- ;; make sure we can find the program
- (unless (executable-find program)
+ ;; Make sure we can find the program. `executable-find' does not
+ ;; work for remote hosts; we suppress the check there.
+ (unless (or (file-remote-p default-directory)
+ (executable-find program))
(error "Unable to locate SQL program \'%s\'" program))
- ;; Make sure buffer name is unique
+ ;; Make sure buffer name is unique.
(when (sql-buffer-live-p (format "*%s*" buf-name))
(setq buf-name (format "SQL-%s" product))
(when (sql-buffer-live-p (format "*%s*" buf-name))