;; Copyright (C) 1998-2013 Free Software Foundation, Inc.
;; Author: Alex Schroeder <alex@gnu.org>
-;; Maintainer: Michael Mauger <mmaug@yahoo.com>
-;; Version: 3.1
+;; Maintainer: Michael Mauger <michael@mauger.com>
+;; Version: 3.2
;; Keywords: comm languages processes
;; URL: http://savannah.gnu.org/projects/emacs/
;; nino <nino@inform.dk>
;; Berend de Boer <berend@pobox.com>
;; Adam Jenkins <adam@thejenkins.org>
-;; Michael Mauger <mmaug@yahoo.com> -- improved product support
+;; Michael Mauger <michael@mauger.com> -- improved product support
;; Drew Adams <drew.adams@oracle.com> -- Emacs 20 support
;; Harald Maier <maierh@myself.com> -- sql-send-string
;; Stefan Monnier <monnier@iro.umontreal.ca> -- font-lock corrections;
;; Andrew Schein <andrew@andrewschein.com> -- sql-port bug
;; Ian Bjorhovde <idbjorh@dataproxy.com> -- db2 escape newlines
;; incorrectly enabled by default
+;; Roman Scherer <roman.scherer@nugg.ad> -- Connection documentation
+;; Mark Wilkinson <wilkinsonmr@gmail.com> -- file-local variables ignored
+;;
\f
\(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', and `sql-database'.
+Where CONNECTION is a case-insensitive string 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', and `sql-database'.
If a SQL-VARIABLE is part of the connection, it will not be
prompted for during login. The command `sql-connect' starts a
;; double quotes (") don't delimit strings
(modify-syntax-entry ?\" "." table)
;; Make these all punctuation
- (mapc (lambda (c) (modify-syntax-entry c "." table))
+ (mapc #'(lambda (c) (modify-syntax-entry c "." table))
(string-to-list "!#$%&+,.:;<=>?@\\|"))
table)
"Syntax table used in `sql-mode' and `sql-interactive-mode'.")
(not (derived-mode-p 'sql-interactive-mode)))
(not sql-buffer)
(not (eq sql-product 'oracle)))
- (error "Not an Oracle buffer")
+ (user-error "Not an Oracle buffer")
(let ((b "*RESERVED WORDS*"))
(sql-execute sql-buffer b
"noswitch" "not" "nothing" "notimeout" "novalidate" "nowait" "null"
"nulls" "object" "of" "off" "offline" "oidindex" "old" "on" "online"
"only" "open" "operator" "optimal" "option" "or" "order"
-"organization" "out" "outer" "outline" "overflow" "overriding"
+"organization" "out" "outer" "outline" "over" "overflow" "overriding"
"package" "packages" "parallel" "parallel_enable" "parameters"
"parent" "partition" "partitions" "password" "password_grace_time"
"password_life_time" "password_lock_time" "password_reuse_max"
;; Oracle PL/SQL Functions
(sql-font-lock-keywords-builder 'font-lock-builtin-face nil
"delete" "trim" "extend" "exists" "first" "last" "count" "limit"
-"prior" "next"
+"prior" "next" "sqlcode" "sqlerrm"
)
;; Oracle PL/SQL Reserved words
(let ((init (or (and initial (symbol-name initial)) "ansi")))
(intern (completing-read
prompt
- (mapcar (lambda (info) (symbol-name (car info)))
+ (mapcar #'(lambda (info) (symbol-name (car info)))
sql-product-alist)
nil 'require-match
init 'sql-product-history init))))
;; Don't do anything if the product is already supported
(if (assoc product sql-product-alist)
- (message "Product `%s' is already defined" product)
+ (user-error "Product `%s' is already defined" product)
;; Add product to the alist
(add-to-list 'sql-product-alist `((,product :name ,display . ,plist)))
;; after this product's name.
(let ((next-item)
(down-display (downcase display)))
- (map-keymap (lambda (k b)
- (when (and (not next-item)
- (string-lessp down-display
- (downcase (cadr b))))
- (setq next-item k)))
+ (map-keymap #'(lambda (k b)
+ (when (and (not next-item)
+ (string-lessp down-display
+ (downcase (cadr b))))
+ (setq next-item k)))
(easy-menu-get-map sql-mode-menu '("Product")))
next-item))
product))
(symbolp v))
(set v newvalue)
(setcdr p (plist-put (cdr p) feature newvalue)))
- (message "`%s' is not a known product; use `sql-add-product' to add it first." product))))
+ (error "`%s' is not a known product; use `sql-add-product' to add it first." product))))
(defun sql-get-product-feature (product feature &optional fallback not-indirect)
"Lookup FEATURE associated with a SQL PRODUCT.
(symbolp v))
(symbol-value v)
v))
- (message "`%s' is not a known product; use `sql-add-product' to add it first." product)
+ (error "`%s' is not a known product; use `sql-add-product' to add it first." product)
nil)))
(defun sql-product-font-lock (keywords-only imenu)
(font-lock-mode-internal t))
(add-hook 'font-lock-mode-hook
- (lambda ()
- ;; Provide defaults for new font-lock faces.
- (defvar font-lock-builtin-face
- (if (boundp 'font-lock-preprocessor-face)
- font-lock-preprocessor-face
- font-lock-keyword-face))
- (defvar font-lock-doc-face font-lock-string-face))
+ #'(lambda ()
+ ;; Provide defaults for new font-lock faces.
+ (defvar font-lock-builtin-face
+ (if (boundp 'font-lock-preprocessor-face)
+ font-lock-preprocessor-face
+ font-lock-keyword-face))
+ (defvar font-lock-doc-face font-lock-string-face))
nil t)
;; Setup imenu; it needs the same syntax-alist.
"Iterate through login parameters and return a list of results."
(delq nil
(mapcar
- (lambda (param)
- (let ((token (or (car-safe param) param))
- (plist (cdr-safe param)))
- (funcall body token plist)))
+ #'(lambda (param)
+ (let ((token (or (car-safe param) param))
+ (plist (cdr-safe param)))
+ (funcall body token plist)))
login-params)))
\f
(defun sql-product-syntax-table ()
(let ((table (copy-syntax-table sql-mode-syntax-table)))
- (mapc (lambda (entry)
- (modify-syntax-entry (car entry) (cdr entry) table))
+ (mapc #'(lambda (entry)
+ (modify-syntax-entry (car entry) (cdr entry) table))
(sql-get-product-feature sql-product :syntax-alist))
table))
(append
;; Change all symbol character to word characters
(mapcar
- (lambda (entry) (if (string= (substring (cdr entry) 0 1) "_")
- (cons (car entry)
- (concat "w" (substring (cdr entry) 1)))
- entry))
+ #'(lambda (entry) (if (string= (substring (cdr entry) 0 1) "_")
+ (cons (car entry)
+ (concat "w" (substring (cdr entry) 1)))
+ entry))
(sql-get-product-feature sql-product :syntax-alist))
'((?_ . "w"))))
(list (sql-read-product "SQL product: ")))
(if (stringp product) (setq product (intern product)))
(when (not (assoc product sql-product-alist))
- (error "SQL product %s is not supported; treated as ANSI" product)
+ (user-error "SQL product %s is not supported; treated as ANSI" product)
(setq product 'ansi))
;; Save product setting and fontify.
(comint-bol nil)
(looking-at "go\\b")))
(comint-send-input)))
+(put 'sql-magic-go 'delete-selection t)
(defun sql-magic-semicolon (arg)
"Insert semicolon and call `comint-send-input'.
(self-insert-command (prefix-numeric-value arg))
(if (equal sql-electric-stuff 'semicolon)
(comint-send-input)))
+(put 'sql-magic-semicolon 'delete-selection t)
(defun sql-accumulate-and-indent ()
"Continue SQL statement on the next line."
t t doc 0)))
doc)
+(defun sql-default-value (var)
+ "Fetch the value of a variable.
+
+If the current buffer is in `sql-interactive-mode', then fetch
+the global value, otherwise use the buffer local value."
+ (if (derived-mode-p 'sql-interactive-mode)
+ (default-value var)
+ (buffer-local-value var (current-buffer))))
+
(defun sql-get-login-ext (symbol prompt history-var plist)
"Prompt user with extended login parameters.
(set-default
symbol
(let* ((default (plist-get plist :default))
- (last-value (default-value symbol))
+ (last-value (sql-default-value symbol))
(prompt-def
(if default
(if (string-match "\\(\\):[ \t]*\\'" prompt)
(`password
(setq-default sql-password
- (read-passwd "Password: " nil sql-password)))
+ (read-passwd "Password: " nil (sql-default-value 'sql-password))))
(`server
(sql-get-login-ext 'sql-server "Server: " 'sql-server-history plist))
(sql-buffer-live-p buf prod connection)
buf)
;; Look thru each buffer
- (car (apply 'append
- (mapcar (lambda (b)
- (and (sql-buffer-live-p b prod connection)
- (list (buffer-name b))))
+ (car (apply #'append
+ (mapcar #'(lambda (b)
+ (and (sql-buffer-live-p b prod connection)
+ (list (buffer-name b))))
(buffer-list)))))))
(defun sql-set-sqli-buffer-generally ()
(interactive)
(let ((default-buffer (sql-find-sqli-buffer)))
(if (null default-buffer)
- (error "There is no suitable SQLi buffer")
+ (user-error "There is no suitable SQLi buffer")
(let ((new-buffer (read-buffer "New SQLi buffer: " default-buffer t)))
(if (null (sql-buffer-live-p new-buffer))
- (error "Buffer %s is not a working SQLi buffer" new-buffer)
+ (user-error "Buffer %s is not a working SQLi buffer" new-buffer)
(when new-buffer
(setq sql-buffer new-buffer)
(run-hooks 'sql-set-sqli-hook)))))))
(interactive)
(if (or (null sql-buffer)
(null (buffer-live-p (get-buffer sql-buffer))))
- (message "%s has no SQLi buffer set." (buffer-name (current-buffer)))
+ (user-error "%s has no SQLi buffer set" (buffer-name (current-buffer)))
(if (null (get-buffer-process sql-buffer))
- (message "Buffer %s has no process." sql-buffer)
- (message "Current SQLi buffer is %s." sql-buffer))))
+ (user-error "Buffer %s has no process" sql-buffer)
+ (user-error "Current SQLi buffer is %s" sql-buffer))))
(defun sql-make-alternate-buffer-name ()
"Return a string that can be used to rename a SQLi buffer.
;; Build a name using the :sqli-login setting
(setq name
- (apply 'concat
+ (apply #'concat
(cdr
- (apply 'append nil
+ (apply #'append nil
(sql-for-each-login
(sql-get-product-feature sql-product :sqli-login)
- (lambda (token plist)
- (pcase token
- (`user
- (unless (string= "" sql-user)
- (list "/" sql-user)))
- (`port
- (unless (or (not (numberp sql-port))
- (= 0 sql-port))
- (list ":" (number-to-string sql-port))))
- (`server
- (unless (string= "" sql-server)
- (list "."
- (if (plist-member plist :file)
- (file-name-nondirectory sql-server)
- sql-server))))
- (`database
- (unless (string= "" sql-database)
- (list "@"
- (if (plist-member plist :file)
- (file-name-nondirectory sql-database)
- sql-database))))
-
- ;; (`password nil)
- (_ nil))))))))
+ #'(lambda (token plist)
+ (pcase token
+ (`user
+ (unless (string= "" sql-user)
+ (list "/" sql-user)))
+ (`port
+ (unless (or (not (numberp sql-port))
+ (= 0 sql-port))
+ (list ":" (number-to-string sql-port))))
+ (`server
+ (unless (string= "" sql-server)
+ (list "."
+ (if (plist-member plist :file)
+ (file-name-nondirectory sql-server)
+ sql-server))))
+ (`database
+ (unless (string= "" sql-database)
+ (list "@"
+ (if (plist-member plist :file)
+ (file-name-nondirectory sql-database)
+ sql-database))))
+
+ ;; (`password nil)
+ (_ nil))))))))
;; If there's a connection, use it and the name thus far
(if sql-connection
(interactive "P")
(if (not (derived-mode-p 'sql-interactive-mode))
- (message "Current buffer is not a SQL interactive buffer")
+ (user-error "Current buffer is not a SQL interactive buffer")
(setq sql-alternate-buffer-name
(cond
sql-alternate-buffer-name))
(t sql-alternate-buffer-name)))
+ (setq sql-alternate-buffer-name (substring-no-properties sql-alternate-buffer-name))
(rename-buffer (if (string= "" sql-alternate-buffer-name)
"*SQL*"
(format "*SQL: %s*" sql-alternate-buffer-name))
(defun sql-input-sender (proc string)
"Send STRING to PROC after applying filters."
- (let* ((product (with-current-buffer (process-buffer proc) sql-product))
+ (let* ((product (buffer-local-value 'sql-product (process-buffer proc)))
(filter (sql-get-product-feature product :input-filter)))
;; Apply filter(s)
((functionp filter)
(setq string (funcall filter string)))
((listp filter)
- (mapc (lambda (f) (setq string (funcall f string))) filter))
+ (mapc #'(lambda (f) (setq string (funcall f string))) filter))
(t nil))
;; Count how many newlines in the string
- (setq sql-output-newline-count 0)
- (mapc (lambda (ch)
- (when (eq ch ?\n)
- (setq sql-output-newline-count (1+ sql-output-newline-count))))
- string)
+ (setq sql-output-newline-count
+ (apply #'+ (mapcar #'(lambda (ch)
+ (if (eq ch ?\n) 1 0)) string)))
;; Send the string
(comint-simple-send proc string)))
(if sql-send-terminator
(sql-send-magic-terminator sql-buffer s sql-send-terminator))
- (message "Sent string to buffer %s." sql-buffer)))
+ (message "Sent string to buffer %s" sql-buffer)))
;; Display the sql buffer
(if sql-pop-to-buffer-after-send-region
(display-buffer sql-buffer)))
;; We don't have no stinkin' sql
- (message "No SQL process started."))))
+ (user-error "No SQL process started"))))
(defun sql-send-region (start end)
"Send a region to the SQL process."
(when visible
(message "Executing SQL command..."))
(if (consp command)
- (mapc (lambda (c) (sql-redirect-one sqlbuf c outbuf save-prior))
+ (mapc #'(lambda (c) (sql-redirect-one sqlbuf c outbuf save-prior))
command)
(sql-redirect-one sqlbuf command outbuf save-prior))
(when visible
(match-string regexp-groups))
;; list of numbers; return the specified matches only
((consp regexp-groups)
- (mapcar (lambda (c)
- (cond
- ((numberp c) (match-string c))
- ((stringp c) (match-substitute-replacement c))
- (t (error "sql-redirect-value: unknown REGEXP-GROUPS value - %s" c))))
+ (mapcar #'(lambda (c)
+ (cond
+ ((numberp c) (match-string c))
+ ((stringp c) (match-substitute-replacement c))
+ (t (error "sql-redirect-value: unknown REGEXP-GROUPS value - %s" c))))
regexp-groups))
;; String is specified; return replacement string
((stringp regexp-groups)
If the results are empty the OUTBUF is deleted, otherwise the
buffer is popped into a view window."
(mapc
- (lambda (c)
- (cond
- ((stringp c)
- (sql-redirect sqlbuf (if arg (format c arg) c) outbuf) t)
- ((functionp c)
- (apply c sqlbuf outbuf enhanced arg nil))
- (t (error "Unknown sql-execute item %s" c))))
+ #'(lambda (c)
+ (cond
+ ((stringp c)
+ (sql-redirect sqlbuf (if arg (format c arg) c) outbuf) t)
+ ((functionp c)
+ (apply c sqlbuf outbuf enhanced arg nil))
+ (t (error "Unknown sql-execute item %s" c))))
(if (consp command) command (cons command nil)))
-
+
(setq outbuf (get-buffer outbuf))
(if (zerop (buffer-size outbuf))
(kill-buffer outbuf)
(defun sql-execute-feature (sqlbuf outbuf feature enhanced arg)
"List objects or details in a separate display buffer."
- (let (command)
- (with-current-buffer sqlbuf
- (setq command (sql-get-product-feature sql-product feature)))
+ (let (command
+ (product (buffer-local-value 'sql-product (get-buffer sqlbuf))))
+ (setq command (sql-get-product-feature product feature))
(unless command
- (error "%s does not support %s" sql-product feature))
+ (error "%s does not support %s" product feature))
(when (consp command)
(setq command (if enhanced
(cdr command)
(apply f (current-buffer) (cons schema nil)))
cl)
(unless (member e cl) (setq cl (cons e cl))))
- (sort cl (function string<)))))))
+ (sort cl #'string<))))))
(defun sql-build-completions (schema)
"Generate a list of names in the database for use as completions."
(interactive "P")
(let ((sqlbuf (sql-find-sqli-buffer)))
(unless sqlbuf
- (error "No SQL interactive buffer found"))
+ (user-error "No SQL interactive buffer found"))
(sql-execute-feature sqlbuf "*List All*" :list-all enhanced nil)
(with-current-buffer sqlbuf
;; Contains the name of database objects
current-prefix-arg))
(let ((sqlbuf (sql-find-sqli-buffer)))
(unless sqlbuf
- (error "No SQL interactive buffer found"))
+ (user-error "No SQL interactive buffer found"))
(unless name
- (error "No table name specified"))
+ (user-error "No table name specified"))
(sql-execute-feature sqlbuf (format "*List %s*" name)
:list-table enhanced name)))
\f
"Read a connection name."
(let ((completion-ignore-case t))
(completing-read prompt
- (mapcar (lambda (c) (car c))
+ (mapcar #'(lambda (c) (car c))
sql-connection-alist)
nil t initial 'sql-connection-history default)))
(if sql-connection-alist
(list (sql-read-connection "Connection: " nil '(nil))
current-prefix-arg)
- nil))
+ (user-error "No SQL Connections defined")))
;; Are there connections defined
(if sql-connection-alist
;; Params in the connection
(setq set-params
(mapcar
- (lambda (v)
- (pcase (car v)
- (`sql-user 'user)
- (`sql-password 'password)
- (`sql-server 'server)
- (`sql-database 'database)
- (`sql-port 'port)
- (s s)))
+ #'(lambda (v)
+ (pcase (car v)
+ (`sql-user 'user)
+ (`sql-password 'password)
+ (`sql-server 'server)
+ (`sql-database 'database)
+ (`sql-port 'port)
+ (s s)))
(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)))))
+ #'(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))))
+ #'(lambda (vv)
+ (set-default (car vv) (eval (cadr vv))))
(cdr connect-set))
(setq-default sql-connection connection)
(eval `(let ((,param-var ',rem-params))
(sql-product-interactive ',sql-product ',new-name))))
- (message "SQL Connection <%s> does not exist" connection)
+ (user-error "SQL Connection <%s> does not exist" connection)
nil)))
- (message "No SQL Connections defined")
+ (user-error "No SQL Connections defined")
nil))
(defun sql-save-connection (name)
(interactive "sNew connection name: ")
(unless (derived-mode-p 'sql-interactive-mode)
- (error "Not in a SQL interactive mode!"))
+ (user-error "Not in a SQL interactive mode!"))
;; Capture the buffer local settings
(let* ((buf (current-buffer))
;; Add the new connection if it doesn't exist
(if (assoc name alist)
- (message "Connection <%s> already exists" name)
+ (user-error "Connection <%s> already exists" name)
(setq connect
(cons name
(sql-for-each-login
`(product ,@login)
- (lambda (token _plist)
- (pcase token
- (`product `(sql-product ',product))
- (`user `(sql-user ,user))
- (`database `(sql-database ,database))
- (`server `(sql-server ,server))
- (`port `(sql-port ,port)))))))
+ #'(lambda (token _plist)
+ (pcase token
+ (`product `(sql-product ',product))
+ (`user `(sql-user ,user))
+ (`database `(sql-database ,database))
+ (`server `(sql-server ,server))
+ (`port `(sql-port ,port)))))))
(setq alist (append alist (list connect)))
"Generate menu entries for using each connection."
(append
(mapcar
- (lambda (conn)
- (vector
- (format "Connection <%s>\t%s" (car conn)
- (let ((sql-user "") (sql-database "")
- (sql-server "") (sql-port 0))
- (eval `(let ,(cdr conn) (sql-make-alternate-buffer-name)))))
- (list 'sql-connect (car conn))
- t))
+ #'(lambda (conn)
+ (vector
+ (format "Connection <%s>\t%s" (car conn)
+ (let ((sql-user "") (sql-database "")
+ (sql-server "") (sql-port 0))
+ (eval `(let ,(cdr conn) (sql-make-alternate-buffer-name)))))
+ (list 'sql-connect (car conn))
+ t))
sql-connection-alist)
tail))
\f
;;; Entry functions for different SQL interpreters.
-
;;;###autoload
(defun sql-product-interactive (&optional product new-name)
"Run PRODUCT interpreter as an inferior process.
;; All done.
(message "Login...done")
(pop-to-buffer new-sqli-buffer)))))
- (message "No default SQL product defined. Set `sql-product'.")))
+ (user-error "No default SQL product defined. Set `sql-product'.")))
(defun sql-comint (product params)
"Set up a comint buffer to run the SQL processor.
(setq buf-name (format "SQL-%s%d" product i))))
(setq i (1+ i))))))
(set-buffer
- (apply 'make-comint buf-name program nil params))))
+ (apply #'make-comint buf-name program nil params))))
;;;###autoload
(defun sql-oracle (&optional buffer)
;;
(append
- ;; (apply 'concat (append
+ ;; (apply #'concat (append
;; '("SET")
;; option value...
;; Remove any settings that haven't changed
(mapc
- (lambda (one-cur-setting)
- (setq saved-settings (delete one-cur-setting saved-settings)))
+ #'(lambda (one-cur-setting)
+ (setq saved-settings (delete one-cur-setting saved-settings)))
(sql-oracle-save-settings sqlbuf))
;; Restore the changed settings
(sql-redirect sqlbuf "\\a"))
;; Return the list of table names (public schema name can be omitted)
- (mapcar (lambda (tbl)
- (if (string= (car tbl) "public")
- (cadr tbl)
- (format "%s.%s" (car tbl) (cadr tbl))))
+ (mapcar #'(lambda (tbl)
+ (if (string= (car tbl) "public")
+ (cadr tbl)
+ (format "%s.%s" (car tbl) (cadr tbl))))
cl))))
\f