;;; sql.el --- specialized comint.el for SQL interpreters
-;; Copyright (C) 1998,99,2000,01,02,03,04 Free Software Foundation, Inc.
+;; Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
+;; Free Software Foundation, Inc.
;; Author: Alex Schroeder <alex@gnu.org>
;; Maintainer: Michael Mauger <mmaug@yahoo.com>
-;; Version: 2.0.0
+;; Version: 2.0.2
;; Keywords: comm languages processes
;; URL: http://savannah.gnu.org/cgi-bin/viewcvs/emacs/emacs/lisp/progmodes/sql.el
;; URL: http://www.emacswiki.org/cgi-bin/wiki.pl?SqlMode
;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
;;; Commentary:
;; Please send bug reports and bug fixes to the mailing list at
-;; sql.el@gnu.org. If you want to subscribe to the mailing list, send
-;; mail to sql.el-request@gnu.org with `subscribe sql.el FIRSTNAME
-;; LASTNAME' in the mail body.
-
-;; This file provides a sql-mode and a sql-interactive-mode. My goals
-;; were two simple modes providing syntactic hilighting. The
-;; interactive mode had to provide a command-line history; the other
-;; mode had to provide "send region/buffer to SQL interpreter"
-;; functions. "simple" in this context means easy to use, easy to
-;; maintain and little or no bells and whistles.
+;; help-gnu-emacs@gnu.org. If you want to subscribe to the mailing
+;; list, see the web page at
+;; http://lists.gnu.org/mailman/listinfo/help-gnu-emacs for
+;; instructions. I monitor this list actively. If you send an e-mail
+;; to Alex Schroeder it usually makes it to me when Alex has a chance
+;; to forward them along (Thanks, Alex).
+
+;; This file provides a sql-mode and a sql-interactive-mode. The
+;; original goals were two simple modes providing syntactic
+;; highlighting. The interactive mode had to provide a command-line
+;; history; the other mode had to provide "send region/buffer to SQL
+;; interpreter" functions. "simple" in this context means easy to
+;; use, easy to maintain and little or no bells and whistles. This
+;; has changed somewhat as experience with the mode has accumulated.
+
+;; Support for different flavors of SQL and command interpreters was
+;; available in early versions of sql.el. This support has been
+;; extended and formalized in later versions. Part of the impetus for
+;; the improved support of SQL flavors was borne out of the current
+;; maintainer's consulting experience. In the past fifteen years, I
+;; have used Oracle, Sybase, Informix, MySQL, Postgres, and SQLServer.
+;; On some assignments, I have used two or more of these concurrently.
;; If anybody feels like extending this sql mode, take a look at the
;; above mentioned modes and write a sqlx-mode on top of this one. If
;; this proves to be difficult, please suggest changes that will
-;; facilitate your plans.
+;; facilitate your plans. Facilities have been provided to add
+;; products and product-specific configuration.
;; sql-interactive-mode is used to interact with a SQL interpreter
;; process in a SQLi buffer (usually called `*SQL*'). The SQLi buffer
-;; is created by calling a SQL interpreter-specific entry function. Do
-;; *not* call sql-interactive-mode by itself.
+;; is created by calling a SQL interpreter-specific entry function or
+;; sql-product-interactive. Do *not* call sql-interactive-mode by
+;; itself.
;; The list of currently supported interpreters and the corresponding
;; entry function used to create the SQLi buffers is shown with
;; Gregor Zych <zych@pool.informatik.rwth-aachen.de>
;; nino <nino@inform.dk>
;; Berend de Boer <berend@pobox.com>
-;; Michael Mauger <mmaug@yahoo.com>
;; Adam Jenkins <adam@thejenkins.org>
+;; Michael Mauger <mmaug@yahoo.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
\f
(eval-when-compile ;; needed in Emacs 19, 20
(setq max-specpdl-size 2000))
+(defvar font-lock-keyword-face)
+(defvar font-lock-set-defaults)
+(defvar font-lock-string-face)
+
;;; Allow customization
(defgroup SQL nil
- "Running a SQL interpreter from within Emacs buffers"
+ "Running a SQL interpreter from within Emacs buffers."
:version "20.4"
:group 'processes)
;; -w is the linesize
"*List of additional options for `sql-ms-program'."
:type '(repeat string)
- :version "21.4"
+ :version "22.1"
:group 'SQL)
;; Customization for Postgres
;;; Variables which do not need customization
-(defvar sql-xemacs-p
- (string-match "XEmacs\\|Lucid" emacs-version)
- "Is this a non-GNU Emacs?")
-
-(defvar sql-emacs19-p
- (string-match "GNU Emacs 19" emacs-version)
- "Is this a GNU Emacs 19?")
-
-(defvar sql-emacs20-p
- (string-match "20" emacs-version)
- "Is this a GNU Emacs 20?")
-
(defvar sql-user-history nil
"History of usernames used.")
(defvar sql-interactive-mode-map
(let ((map (make-sparse-keymap)))
- (if (functionp 'set-keymap-parent)
+ (if (fboundp 'set-keymap-parent)
(set-keymap-parent map comint-mode-map); Emacs
- (set-keymap-parents map (list comint-mode-map))); XEmacs
- (if (functionp 'set-keymap-name)
+ (if (fboundp 'set-keymap-parents)
+ (set-keymap-parents map (list comint-mode-map)))); XEmacs
+ (if (fboundp 'set-keymap-name)
(set-keymap-name map 'sql-interactive-mode-map)); XEmacs
(define-key map (kbd "C-j") 'sql-accumulate-and-indent)
(define-key map (kbd "C-c C-w") 'sql-copy-column)
(defvar sql-mode-abbrev-table nil
"Abbrev table used in `sql-mode' and `sql-interactive-mode'.")
(unless sql-mode-abbrev-table
- (define-abbrev-table 'sql-mode-abbrev-table nil)
- (mapcar
- ;; In Emacs 21.3+, provide SYSTEM-FLAG to define-abbrev.
- '(lambda (abbrev)
- (let ((name (car abbrev))
- (expansion (cdr abbrev)))
- (condition-case nil
- (define-abbrev sql-mode-abbrev-table name expansion nil 0 t)
- (error
- (define-abbrev sql-mode-abbrev-table name expansion)))))
- '(("ins" "insert")
- ("upd" "update")
- ("del" "delete")
- ("sel" "select")
- ("proc" "procedure")
- ("func" "function")
- ("cr" "create"))))
+ (define-abbrev-table 'sql-mode-abbrev-table nil))
+
+(mapcar
+ ;; In Emacs 22+, provide SYSTEM-FLAG to define-abbrev.
+ '(lambda (abbrev)
+ (let ((name (car abbrev))
+ (expansion (cdr abbrev)))
+ (condition-case nil
+ (define-abbrev sql-mode-abbrev-table name expansion nil 0 t)
+ (error
+ (define-abbrev sql-mode-abbrev-table name expansion)))))
+ '(("ins" . "insert")
+ ("upd" . "update")
+ ("del" . "delete")
+ ("sel" . "select")
+ ("proc" . "procedure")
+ ("func" . "function")
+ ("cr" . "create")))
;; Syntax Table
;; C-style comments /**/ (see elisp manual "Syntax Flags"))
(modify-syntax-entry ?/ ". 14" table)
(modify-syntax-entry ?* ". 23" table)
- ;; double-dash starts comment
- (if sql-xemacs-p
- (modify-syntax-entry ?- ". 56" table)
- (modify-syntax-entry ?- ". 12b" table))
- ;; newline and formfeed end coments
+ ;; double-dash starts comments
+ (modify-syntax-entry ?- ". 12b" table)
+ ;; newline and formfeed end comments
(modify-syntax-entry ?\n "> b" table)
(modify-syntax-entry ?\f "> b" table)
- ;; single quotes (') quotes delimit strings
+ ;; single quotes (') delimit strings
(modify-syntax-entry ?' "\"" table)
+ ;; double quotes (") don't delimit strings
+ (modify-syntax-entry ?\" "." table)
;; backslash is no escape character
(modify-syntax-entry ?\\ "." table)
table)
;; Font lock support
(defvar sql-mode-font-lock-object-name
- (list (concat "^\\s-*\\(create\\|drop\\|alter\\)\\s-+" ;; lead off with CREATE, DROP or ALTER
- "\\(\\w+\\s-+\\)*" ;; optional intervening keywords
- "\\(table\\|view\\|package\\(\\s-+body\\)?\\|proc\\(edure\\)?"
- "\\|function\\|trigger\\|sequence\\|rule\\|default\\)\\s-+"
- "\\(\\w+\\)")
- 6 'font-lock-function-name-face)
+ (eval-when-compile
+ (list (concat "^\\s-*\\(?:create\\|drop\\|alter\\)\\s-+" ;; lead off with CREATE, DROP or ALTER
+ "\\(?:\\w+\\s-+\\)*" ;; optional intervening keywords
+ "\\(?:table\\|view\\|\\(?:package\\|type\\)\\(?:\\s-+body\\)?\\|proc\\(?:edure\\)?"
+ "\\|function\\|trigger\\|sequence\\|rule\\|default\\)\\s-+"
+ "\\(\\w+\\)")
+ 1 'font-lock-function-name-face))
"Pattern to match the names of top-level objects.
statement. The format of variable should be a valid
`font-lock-keywords' entry.")
-(defvar sql-builtin-face
- (if sql-xemacs-p
- ;; XEmacs doesn't have the builtin face
- 'font-lock-preprocessor-face
- ;; GNU Emacs 19 doesn't either
- (if sql-emacs19-p
- 'font-lock-keyword-face
- ;; Emacs 2x
- 'font-lock-builtin-face))
- "Builtin face for font-lock in SQL mode.")
-
-(defvar sql-doc-face
- (if (or sql-xemacs-p
- sql-emacs19-p
- sql-emacs20-p)
- 'font-lock-string-face
- 'font-lock-doc-face)
- "Documentation face for font-lock in SQL mode.")
-
(defmacro sql-keywords-re (&rest keywords)
"Compile-time generation of regexp matching any one of KEYWORDS."
`(eval-when-compile
`((,ansi-non-reserved . font-lock-keyword-face)
(,ansi-reserved . font-lock-keyword-face)
- (,ansi-funcs . ,sql-builtin-face)
+ (,ansi-funcs . font-lock-builtin-face)
(,ansi-types . font-lock-type-face)))
"ANSI SQL keywords used by font-lock.
"\\b.*$"
))))
- `((,sqlplus-commands . ,sql-doc-face)
- (,oracle-functions . ,sql-builtin-face)
+ `((,sqlplus-commands . font-lock-doc-face)
+ (,oracle-functions . font-lock-builtin-face)
(,oracle-keywords . font-lock-keyword-face)
(,oracle-types . font-lock-type-face)
- (,plsql-functions . ,sql-builtin-face)
+ (,plsql-functions . font-lock-builtin-face)
(,plsql-keywords . font-lock-keyword-face)
(,plsql-type . font-lock-type-face)
(,plsql-warning . font-lock-warning-face)))
"timestamp" "varchar" "varying" "void" "zone"
)))
- `((,pg-funcs . ,sql-builtin-face)
+ `((,pg-funcs . font-lock-builtin-face)
(,pg-reserved . font-lock-keyword-face)
(,pg-types . font-lock-type-face)))
`((,linter-keywords . font-lock-keyword-face)
(,linter-reserved . font-lock-keyword-face)
- (,linter-functions . ,sql-builtin-face)
+ (,linter-functions . font-lock-builtin-face)
(,linter-types . font-lock-type-face)))
"Linter SQL keywords used by font-lock.
) t)
"\\)\\)\\|go\\s-*\\|use\\s-+\\|setuser\\s-+\\|dbcc\\s-+\\).*$"))))
- `((,ms-commands . ,sql-doc-face)
+ `((,ms-commands . font-lock-doc-face)
(,ms-reserved . font-lock-keyword-face)
- (,ms-functions . ,sql-builtin-face)
+ (,ms-functions . font-lock-builtin-face)
(,ms-vars . font-lock-variable-name-face)
(,ms-types . font-lock-type-face)))
"zerofill"
)))
- `((,mysql-funcs . ,sql-builtin-face)
+ `((,mysql-funcs . font-lock-builtin-face)
(,mysql-keywords . font-lock-keyword-face)
(,mysql-types . font-lock-type-face)))
;; Get the product-specific keywords.
(setq sql-mode-font-lock-keywords
(append
- (eval (sql-product-feature :font-lock))
+ (unless (eq sql-product 'ansi)
+ (eval (sql-product-feature :font-lock)))
+ ;; Always highlight ANSI keywords
(eval (sql-product-feature :font-lock 'ansi))
+ ;; Fontify object names in CREATE, DROP and ALTER DDL
+ ;; statements
(list sql-mode-font-lock-object-name)))
- ;; Setup font-lock. (What is the minimum we should have to do
- ;; here?)
- (setq font-lock-set-defaults nil
- font-lock-keywords sql-mode-font-lock-keywords
- font-lock-defaults (list 'sql-mode-font-lock-keywords
+ ;; Setup font-lock. Force re-parsing of `font-lock-defaults'.
+ (set (make-local-variable 'font-lock-set-defaults) nil)
+ (setq font-lock-defaults (list 'sql-mode-font-lock-keywords
keywords-only t syntax-alist))
+ ;; Force font lock to reinitialize if it is already on
+ ;; Otherwise, we can wait until it can be started.
+ (when (and (fboundp 'font-lock-mode)
+ font-lock-mode)
+ (font-lock-mode-internal nil)
+ (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))
+ nil t)
+
;; Setup imenu; it needs the same syntax-alist.
(when imenu
(setq imenu-syntax-alist syntax-alist))))
;; Setup font-lock
(sql-product-font-lock nil t)
- ;; Force fontification, if its enabled.
- (if (and (boundp 'font-lock-mode)
- font-lock-mode)
- (font-lock-fontify-buffer))
-
;; Set the mode name to include the product.
(setq mode-name (concat "SQL[" (prin1-to-string sql-product) "]"))))
(describe-function 'sql-help))
(defun sql-read-passwd (prompt &optional default)
- "Read a password using PROMPT.
-Optional DEFAULT is password to start with. This function calls
-`read-passwd' if it is available. If not, function
-`ange-ftp-read-passwd' is called. This should always be available,
-even in old versions of Emacs."
- (if (fboundp 'read-passwd)
- (read-passwd prompt nil default)
- (unless (fboundp 'ange-ftp-read-passwd)
- (autoload 'ange-ftp-read-passwd "ange-ftp"))
- (ange-ftp-read-passwd prompt default)))
+ "Read a password using PROMPT. Optional DEFAULT is password to start with."
+ (read-passwd prompt nil default))
(defun sql-get-login (&rest what)
"Get username, password and database from the user.
(insert ", "))
;; else insert a space
(t
- (if (eq (preceding-char) ? )
+ (if (eq (preceding-char) ?\s)
nil
(insert " ")))))
;; in any case, insert the column
(setq local-abbrev-table sql-mode-abbrev-table)
(setq abbrev-all-caps 1)
;; Run hook
- (run-hooks 'sql-mode-hook)
+ (run-mode-hooks 'sql-mode-hook)
;; Catch changes to sql-product and highlight accordingly
(sql-highlight-product)
(add-hook 'hack-local-variables-hook 'sql-highlight-product t t))
interpreter output, the hooks on `comint-output-filter-functions' are
run.
-Variable `sql-input-ring-file-name' controls the initialisation of the
+Variable `sql-input-ring-file-name' controls the initialization of the
input ring history.
Variables `comint-output-filter-functions', a hook, and
\(setq comint-output-filter-functions
\(function (lambda (STR) (comint-show-output))))"
- (comint-mode)
+ (delay-mode-hooks (comint-mode))
;; Get the `sql-product' for this interactive session.
(set (make-local-variable 'sql-product)
(or sql-interactive-product
(make-local-variable 'sql-input-ring-separator)
(make-local-variable 'sql-input-ring-file-name)
;; Run hook.
- (run-hooks 'sql-interactive-mode-hook)
+ (run-mode-hooks 'sql-interactive-mode-hook)
;; Set comint based on user overrides.
(setq comint-prompt-regexp sql-prompt-regexp)
(setq left-margin sql-prompt-length)