aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard M. Stallman1999-01-11 15:26:36 +0000
committerRichard M. Stallman1999-01-11 15:26:36 +0000
commit95e4b2efaf743e2fd2c6a59b38f6687068e3fc8f (patch)
tree8160a252967d4a6afcf2c0c72fa6238cbbdf1fb5
parentd9c21094c7a47b8037393e9427c8e7180a8c6ea2 (diff)
downloademacs-95e4b2efaf743e2fd2c6a59b38f6687068e3fc8f.tar.gz
emacs-95e4b2efaf743e2fd2c6a59b38f6687068e3fc8f.zip
Initial revision
-rw-r--r--lisp/progmodes/sql.el1060
1 files changed, 1060 insertions, 0 deletions
diff --git a/lisp/progmodes/sql.el b/lisp/progmodes/sql.el
new file mode 100644
index 00000000000..bf80379bffa
--- /dev/null
+++ b/lisp/progmodes/sql.el
@@ -0,0 +1,1060 @@
1;;; sql.el --- specialized comint.el for SQL interpreters
2
3;; Copyright (C) 1998 Free Software Foundation, Inc.
4
5;; Author: Alex Schroeder <a.schroeder@bsiag.ch>
6;; Maintainer: Alex Schroeder <a.schroeder@bsiag.ch>
7;; Version: 1.1.5
8;; Keywords: processes SQL
9
10;; This file is part of GNU Emacs.
11
12;; GNU Emacs is free software; you can redistribute it and/or modify
13;; it under the terms of the GNU General Public License as published by
14;; the Free Software Foundation; either version 2, or (at your option)
15;; any later version.
16
17;; GNU Emacs is distributed in the hope that it will be useful,
18;; but WITHOUT ANY WARRANTY; without even the implied warranty of
19;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20;; GNU General Public License for more details.
21
22;; You should have received a copy of the GNU General Public License
23;; along with GNU Emacs; see the file COPYING. If not, write to the
24;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
25;; Boston, MA 02111-1307, USA.
26
27;;; Commentary:
28
29;; Please send me bug reports and bug fixes so that I can merge them
30;; into the master source.
31
32;; You can get the latest version of this file from my homepage
33;; <URL:http://www.geocities.com/TimesSquare/6120/emacs.html>.
34
35;; This file provides a sql-mode and a sql-interactive-mode. My goals
36;; were two simple modes providing syntactic hilighting. The
37;; interactive mode had to provide a command-line history; the other
38;; mode had to provide "send region/buffer to SQL interpreter"
39;; functions. "simple" in this context means easy to use, easy to
40;; maintain and little or no bells and whistles.
41
42;; If anybody feels like extending this sql mode, take a look at the
43;; above mentioned modes and write a sqlx-mode on top of this one. If
44;; this proves to be difficult, please suggest changes that will
45;; facilitate your plans.
46
47;; sql-interactive-mode is used to interact with a SQL interpreter
48;; process in the *SQL* buffer. The *SQL* buffer is created by
49;; calling a SQL interpreter-specific entry function. Do *not* call
50;; sql-interactive-mode by itself.
51
52;; The list of currently supported interpreters and the corresponding
53;; entry function used to create the *SQL* buffers is shown with
54;; `sql-help' (M-x sql-help).
55
56;; Since sql-interactive-mode is built on top of the general
57;; command-interpreter-in-a-buffer mode (comint mode), it shares a
58;; common base functionality, and a common set of bindings, with all
59;; modes derived from comint mode. This makes these modes easier to
60;; use.
61
62;; sql-mode can be used to enable syntactic hilighting for SQL
63;; statements in another buffer. SQL statements can then be sent to
64;; the SQL process in the *SQL* buffer. sql-mode has already been
65;; used as a template to a simple PL/SQL mode.
66
67;; For documentation on the functionality provided by comint mode, and
68;; the hooks available for customising it, see the file `comint.el'.
69
70;; Hint for newbies: take a look at `dabbrev-expand' and `abbrev-mode'.
71
72;;; Requirements for Emacs 19.34:
73
74;; If you are using Emacs 19.34, you will have to get and install
75;; the file regexp-opt.el
76;; <URL:ftp://ftp.ifi.uio.no/pub/emacs/emacs-20.3/lisp/emacs-lisp/regexp-opt.el>
77;; and the custom package
78;; <URL:http://www.dina.kvl.dk/~abraham/custom/>.
79
80;;; Bugs:
81
82;; Using sql-ms (isql by Microsoft): When commands with syntax errors
83;; or execution errors are executed, there is no server feedback.
84;; This happens in stored procedures for example. The server messages
85;; only appear after the process is exited. This makes things
86;; somewhat unreliable.
87
88;;; To Do:
89
90;; Add better hilight support for other brands; there is a bias towards
91;; Oracle because that's what I use at work. Anybody else just send in
92;; your lists of reserved words, keywords and builtin functions!
93
94;; Add different hilighting levels.
95
96;;; Thanks to all the people who helped me out:
97
98;; Kai Blauberg <kai.blauberg@metla.fi>
99;; <ibalaban@dalet.com>
100;; Yair Friedman <yfriedma@JohnBryce.Co.Il>
101;; Gregor Zych <zych@pool.informatik.rwth-aachen.de>
102
103
104;;; Code:
105
106(require 'comint)
107;; Need the following to allow GNU Emacs 19 to compile the file.
108(require 'regexp-opt)
109(require 'custom)
110
111;;; Allow customization
112
113(defgroup SQL nil
114 "Running a SQL interpreter from within Emacs buffers"
115 :group 'processes)
116
117;; These three variables will be used as defaults, if set.
118
119(defcustom sql-user ""
120 "*Default username."
121 :type 'string
122 :group 'SQL)
123
124(defcustom sql-password ""
125 "*Default password.
126
127Storing your password in a textfile such as ~/.emacs could be dangerous.
128Customizing your password will store it in your ~/.emacs file."
129 :type 'string
130 :group 'SQL)
131
132(defcustom sql-database ""
133 "*Default database."
134 :type 'string
135 :group 'SQL)
136
137(defcustom sql-server ""
138 "*Default server.
139
140Currently, this is only used by MS isql."
141 :type 'string
142 :group 'SQL)
143
144(defcustom sql-pop-to-buffer-after-send-region nil
145 "*If t, pop to the buffer SQL statements are sent to.
146
147After a call to `sql-send-region' or `sql-send-buffer',
148the window is split and the SQLi buffer is shown. If this
149variable is not nil, that buffer's window will be selected."
150 :type 'string
151 :group 'SQL)
152
153;; The usual hooks
154
155(defcustom sql-interactive-mode-hook '()
156 "*Hook for customising `sql-interactive-mode'."
157 :type 'hook
158 :group 'SQL)
159
160(defcustom sql-mode-hook '()
161 "*Hook for customising `sql-mode'."
162 :type 'hook
163 :group 'SQL)
164
165;; Customisation for Oracle
166
167(defcustom sql-oracle-program "sqlplus"
168 "*Command to start sqlplus by Oracle.
169
170Starts `sql-interactive-mode' after doing some setup.
171
172Under NT, \"sqlplus\" usually starts the sqlplus \"GUI\". In order to
173start the sqlplus console, use \"plus33\" or something similar. You
174will find the file in your Orant\\bin directory.
175
176The program can also specify a TCP connection. See `make-comint'."
177 :type 'file
178 :group 'SQL)
179
180;; Customisation for SyBase
181
182(defcustom sql-sybase-program "isql"
183 "*Command to start isql by SyBase.
184
185Starts `sql-interactive-mode' after doing some setup.
186
187The program can also specify a TCP connection. See `make-comint'."
188 :type 'file
189 :group 'SQL)
190
191;; Customisation for Informix
192
193(defcustom sql-informix-program "dbaccess"
194 "*Command to start dbaccess by Informix.
195
196Starts `sql-interactive-mode' after doing some setup.
197
198The program can also specify a TCP connection. See `make-comint'."
199 :type 'file
200 :group 'SQL)
201
202;; Customisation for Ingres
203
204(defcustom sql-ingres-program "sql"
205 "*Command to start sql by Ingres.
206
207Starts `sql-interactive-mode' after doing some setup.
208
209The program can also specify a TCP connection. See `make-comint'."
210 :type 'file
211 :group 'SQL)
212
213;; Customisation for Microsoft
214
215(defcustom sql-ms-program "isql"
216 "*Command to start isql by Microsoft.
217
218Starts `sql-interactive-mode' after doing some setup.
219
220The program can also specify a TCP connection. See `make-comint'."
221 :type 'file
222 :group 'SQL)
223
224;; Customisation for Postgres
225
226(defcustom sql-postgres-program "psql"
227 "Command to start psql by Postgres.
228
229Starts `sql-interactive-mode' after doing some setup.
230
231The program can also specify a TCP connection. See `make-comint'."
232 :type 'file
233 :group 'SQL)
234
235
236
237;;; Variables which do not need customization
238
239(defvar sql-user-history nil
240 "History of usernames used.")
241
242(defvar sql-database-history nil
243 "History of databases used.")
244
245(defvar sql-server-history nil
246 "History of servers used.")
247
248;; Passwords are not kept in a history.
249
250(defvar sql-buffer nil
251 "Current *SQL* buffer.")
252
253(defvar sql-prompt-regexp nil
254 "Prompt used to initialize `comint-prompt-regexp'.
255
256You can change `comint-prompt-regexp' on `sql-interactive-mode-hook'.")
257
258;; Keymap for sql-interactive-mode, based on comint-mode-map.
259
260(if (not (string-match "XEmacs\\|Lucid" emacs-version))
261 (defvar sql-interactive-mode-map
262 (let ((map (nconc (make-sparse-keymap) comint-mode-map)))
263 (define-key map "\C-j" 'sql-accumulate-and-indent)
264 (define-key map "\C-c\C-w" 'sql-copy-column)
265 map)
266 "Mode map used for `sql-interactive-mode'.")
267 ;; XEmacs
268 (defvar sql-interactive-mode-map nil)
269 (if (not sql-interactive-mode-map)
270 (let ((map (make-keymap)))
271 (set-keymap-parents map (list comint-mode-map))
272 (set-keymap-name map 'sql-interactive-mode-map)
273 (define-key map "\C-j" 'sql-accumulate-and-indent)
274 (define-key map "\C-c\C-w" 'sql-copy-column)
275 (setq sql-interactive-mode-map map))))
276
277;; Keymap for sql-mode.
278
279(defvar sql-mode-map
280 (let ((map (make-sparse-keymap)))
281 (define-key map "\C-c\C-r" 'sql-send-region)
282 (define-key map "\C-c\C-b" 'sql-send-buffer)
283 (define-key map "\t" 'indent-relative)
284 map)
285 "Mode map used for `sql-mode'.")
286
287;; easy menu for sql-mode.
288
289(easy-menu-define
290 sql-mode-menu sql-mode-map
291 "Menu for `sql-mode'."
292 '("SQL"
293 ["Send Region" sql-send-region mark-active]
294 ["Send Buffer" sql-send-buffer t]
295 ["Pop to SQLi buffer after send"
296 sql-toggle-pop-to-buffer-after-send-region
297 :style toggle
298 :selected sql-pop-to-buffer-after-send-region]))
299
300;; Abbreviations -- if you want more of them, define them in your
301;; ~/.emacs file. Abbrevs have to be enabled in your ~/.emacs, too.
302
303(defvar sql-mode-abbrev-table nil
304 "Abbrev table used in `sql-mode' and `sql-interactive-mode'.")
305(if sql-mode-abbrev-table
306 ()
307 (let ((wrapper))
308 (define-abbrev-table 'sql-mode-abbrev-table ())
309 (define-abbrev sql-mode-abbrev-table "ins" "insert" nil)
310 (define-abbrev sql-mode-abbrev-table "upd" "update" nil)
311 (define-abbrev sql-mode-abbrev-table "del" "delete" nil)
312 (define-abbrev sql-mode-abbrev-table "sel" "select" nil)))
313
314;; Syntax Table
315
316(defvar sql-mode-syntax-table
317 (let ((table (make-syntax-table)))
318 ;; C-style comments /**/ (see elisp manual "Syntax Flags"))
319 (modify-syntax-entry ?/ ". 14" table)
320 (modify-syntax-entry ?* ". 23" table)
321 ;; double-dash starts comment
322 (modify-syntax-entry ?- ". 12b" table)
323 ;; newline and formfeed end coments
324 (modify-syntax-entry ?\n "> b" table)
325 (modify-syntax-entry ?\f "> b" table)
326 table)
327 "Syntax table used in `sql-mode' and `sql-interactive-mode'.")
328
329;; Font lock support
330
331(defvar sql-mode-ansi-font-lock-keywords nil
332 "ANSI SQL keywords used by font-lock.
333
334This variable is used by `sql-mode' and `sql-interactive-mode'. The
335regular expressions are created during compilation by calling the
336function `regexp-opt'. Therefore, take a look at the source before
337you define your own sql-mode-ansi-font-lock-keywords. You may want to
338add functions and PL/SQL keywords.")
339(if sql-mode-ansi-font-lock-keywords
340 ()
341 (let ((ansi-keywords (eval-when-compile
342 (concat "\\b"
343 (regexp-opt '(
344"authorization" "avg" "begin" "close" "cobol" "commit"
345"continue" "count" "declare" "double" "end" "escape"
346"exec" "fetch" "foreign" "fortran" "found" "go" "goto" "indicator"
347"key" "language" "max" "min" "module" "numeric" "open" "pascal" "pli"
348"precision" "primary" "procedure" "references" "rollback"
349"schema" "section" "some" "sqlcode" "sqlerror" "sum" "work") t) "\\b")))
350 (ansi-reserved-words (eval-when-compile
351 (concat "\\b"
352 (regexp-opt '(
353"all" "and" "any" "as" "asc" "between" "by" "check" "create"
354"current" "default" "delete" "desc" "distinct" "exists" "float" "for"
355"from" "grant" "group" "having" "in" "insert" "into" "is"
356"like" "not" "null" "of" "on" "option" "or" "order" "privileges"
357"public" "select" "set" "table" "to" "union" "unique"
358"update" "user" "values" "view" "where" "with") t) "\\b")))
359 (ansi-types (eval-when-compile
360 (concat "\\b"
361 (regexp-opt '(
362;; ANSI Keywords that look like types
363"character" "cursor" "dec" "int" "real"
364;; ANSI Reserved Word that look like types
365"char" "integer" "smallint" ) t) "\\b"))))
366 (setq sql-mode-ansi-font-lock-keywords
367 (list (cons ansi-keywords font-lock-function-name-face)
368 (cons ansi-reserved-words font-lock-keyword-face)
369 (cons ansi-types font-lock-type-face)))))
370
371(defvar sql-mode-oracle-font-lock-keywords nil
372 "Oracle SQL keywords used by font-lock.
373
374This variable is used by `sql-mode' and `sql-interactive-mode'. The
375regular expressions are created during compilation by calling the
376function `regexp-opt'. Therefore, take a look at the source before
377you define your own sql-mode-oracle-font-lock-keywords. You may want
378to add functions and PL/SQL keywords.")
379(if sql-mode-oracle-font-lock-keywords
380 ()
381 (let ((oracle-keywords (eval-when-compile
382 (concat "\\b"
383 (regexp-opt '(
384"admin" "after" "allocate" "analyze" "archive" "archivelog" "backup"
385"become" "before" "block" "body" "cache" "cancel" "cascade" "change"
386"checkpoint" "compile" "constraint" "constraints" "contents"
387"controlfile" "cycle" "database" "datafile" "dba" "disable" "dismount"
388"dump" "each" "enable" "events" "except" "exceptions" "execute"
389"explain" "extent" "externally" "flush" "force" "freelist" "freelists"
390"function" "groups" "including" "initrans" "instance" "layer" "link"
391"lists" "logfile" "manage" "manual" "maxdatafiles" "maxinistances"
392"maxlogfiles" "maxloghistory" "maxlogmembers" "maxtrans" "maxvalue"
393"minextents" "minvalue" "mount" "new" "next" "noarchivelog" "nocache"
394"nocycle" "nomaxvalue" "nominvalue" "none" "noorder" "noresetlogs"
395"normal" "nosort" "off" "old" "only" "optimal" "own" "package"
396"parallel" "pctincrease" "pctused" "plan" "private" "profile" "quota"
397"read" "recover" "referencing" "resetlogs" "restricted" "reuse" "role"
398"roles" "savepoint" "scn" "segment" "sequence" "shared" "snapshot"
399"sort" "statement_id" "statistics" "stop" "storage" "switch" "system"
400"tables" "tablespace" "temporary" "thread" "time" "tracing"
401"transaction" "triggers" "truncate" "under" "unlimited" "until" "use"
402"using" "when" "write") t) "\\b")))
403 (oracle-reserved-words (eval-when-compile
404 (concat "\\b"
405 (regexp-opt '(
406"access" "add" "alter" "audit" "cluster" "column" "comment" "compress"
407"connect" "drop" "else" "exclusive" "file" "grant"
408"identified" "immediate" "increment" "index" "initial" "intersect"
409"level" "lock" "long" "maxextents" "minus" "mode" "modify" "noaudit"
410"nocompress" "nowait" "number" "offline" "online" "pctfree" "prior"
411"raw" "rename" "resource" "revoke" "row" "rowlabel" "rownum"
412"rows" "session" "share" "size" "start" "successful" "synonym" "sysdate"
413"then" "trigger" "uid" "validate" "whenever") t) "\\b")))
414 (oracle-types (eval-when-compile
415 (concat "\\b"
416 (regexp-opt '(
417;; Oracle Keywords that look like types
418;; Oracle Reserved Words that look like types
419"date" "decimal" "rowid" "varchar" "varchar2") t) "\\b")))
420 (oracle-builtin-functions (eval-when-compile
421 (concat "\\b"
422 (regexp-opt '(
423;; Misc Oracle builtin functions
424"abs" "add_months" "ascii" "avg" "ceil" "chartorowid" "chr" "concat"
425"convert" "cos" "cosh" "count" "currval" "decode" "dump" "exp" "floor"
426"glb" "greatest" "greatest_lb" "hextoraw" "initcap" "instr" "instrb"
427"last_day" "least" "least_ub" "length" "lengthb" "ln" "log" "lower"
428"lpad" "ltrim" "lub" "max" "min" "mod" "months_between" "new_time"
429"next_day" "nextval" "nls_initcap" "nls_lower" "nls_upper" "nlssort"
430"nvl" "power" "rawtohex" "replace" "round" "rowidtochar" "rpad"
431"rtrim" "sign" "sin" "sinh" "soundex" "sqlcode" "sqlerrm" "sqrt"
432"stddev" "sum" "substr" "substrb" "tan" "tanh" "to_char"
433"to_date" "to_label" "to_multi_byte" "to_number" "to_single_byte"
434"translate" "trunc" "uid" "upper" "userenv" "variance" "vsize") t) "\\b"))))
435 (setq sql-mode-oracle-font-lock-keywords
436 (append sql-mode-ansi-font-lock-keywords
437 (list (cons oracle-keywords font-lock-function-name-face)
438 (cons oracle-reserved-words font-lock-keyword-face)
439 ;; XEmacs doesn't have font-lock-builtin-face
440 (if (string-match "XEmacs\\|Lucid" emacs-version)
441 (cons oracle-builtin-functions font-lock-preprocessor-face)
442 ;; GNU Emacs 19 doesn't have it either
443 (if (string-match "GNU Emacs 19" emacs-version)
444 (cons oracle-builtin-functions font-lock-function-name-face)
445 ;; Emacs
446 (cons oracle-builtin-functions font-lock-builtin-face)))
447 (cons oracle-types font-lock-type-face))))))
448
449(defvar sql-mode-postgres-font-lock-keywords nil
450 "Postgres SQL keywords used by font-lock.
451
452This variable is used by `sql-mode' and `sql-interactive-mode'. The
453regular expressions are created during compilation by calling the
454function `regexp-opt'. Therefore, take a look at the source before
455you define your own sql-mode-postgres-font-lock-keywords.")
456
457(if sql-mode-postgres-font-lock-keywords
458 ()
459 (let ((postgres-reserved-words (eval-when-compile
460 (concat "\\b"
461 (regexp-opt '(
462"language"
463) t) "\\b")))
464 (postgres-types (eval-when-compile
465 (concat "\\b"
466 (regexp-opt '(
467"bool" "box" "circle" "char" "char2" "char4" "char8" "char16" "date"
468"float4" "float8" "int2" "int4" "int8" "line" "lseg" "money" "path"
469"point" "polygon" "serial" "text" "time" "timespan" "timestamp" "varchar"
470) t)"\\b")))
471 (postgres-builtin-functions (eval-when-compile
472 (concat "\\b"
473 (regexp-opt '(
474;; Misc Postgres builtin functions
475"abstime" "age" "area" "box" "center" "date_part" "date_trunc"
476"datetime" "dexp" "diameter" "dpow" "float" "float4" "height"
477"initcap" "integer" "isclosed" "isfinite" "isoldpath" "isopen"
478"length" "lower" "lpad" "ltrim" "pclose" "point" "points" "popen"
479"position" "radius" "reltime" "revertpoly" "rpad" "rtrim" "substr"
480"substring" "text" "timespan" "translate" "trim" "upgradepath"
481"upgradepoly" "upper" "varchar" "width"
482) t) "\\b"))))
483 (setq sql-mode-postgres-font-lock-keywords
484 (append sql-mode-ansi-font-lock-keywords
485 (list (cons postgres-reserved-words font-lock-keyword-face)
486 ;; XEmacs doesn't have font-lock-builtin-face
487 (if (string-match "XEmacs\\|Lucid" emacs-version)
488 (cons postgres-builtin-functions font-lock-preprocessor-face)
489 ;; Emacs
490 (cons postgres-builtin-functions font-lock-builtin-face))
491 (cons postgres-types font-lock-type-face))))))
492
493
494(defvar sql-mode-font-lock-keywords sql-mode-ansi-font-lock-keywords
495 "SQL keywords used by font-lock.
496
497This variable defaults to `sql-mode-ansi-font-lock-keywords'. This is
498used for the default `font-lock-defaults' value in `sql-mode'. This
499can be changed by some entry functions to provide more hilighting.")
500
501
502
503;;; Small functions
504
505(defun sql-accumulate-and-indent ()
506 "Continue SQL statement on the next line."
507 (interactive)
508 ;; comint-accumulate is a Emacs 20.X thingie
509 (if (not (string-match "XEmacs\\|Lucid\\|GNU Emacs 19" emacs-version))
510 (comint-accumulate))
511 (indent-according-to-mode))
512
513;;;###autoload
514(defun sql-help ()
515 "Shows short help for the SQL modes.
516
517Use an entry function to open an interactive SQL buffer. This buffer is
518usually named *SQL*. The name of the major mode is SQLi.
519
520Use the following commands to start a specific SQL interpreter:
521
522psql by PostGres: \\[sql-postgres]
523SQL*Plus: \\[sql-oracle]
524dbaccess: \\[sql-informix]
525isql (Sybase): \\[sql-sybase]
526sql (Ingres): \\[sql-ingres]
527isql (Microsoft): \\[sql-ms]
528
529Once you have the SQLi buffer, you can enter SQL statements in the
530buffer. The output generated is appended to the buffer and a new prompt
531is generated. See the In/Out menu in the SQLi buffer for some functions
532that help you navigate through the buffer, the input history, etc.
533
534Put a line with a call to autoload into your `~/.emacs' file for each
535entry function you want to use regularly:
536
537\(autoload 'sql-postgres \"sql\" \"Interactive SQL mode.\" t)
538
539If you have a really complex SQL statement or if you are writing a
540procedure, you can do this in a separate buffer. Put the new buffer in
541`sql-mode' by calling \\[sql-mode]. The name of this buffer can be
542anything. The name of the major mode is SQL.
543
544In this SQL buffer (SQL mode), you can send the region or the entire
545buffer to the interactive SQL buffer (SQLi mode). The results are
546appended to the SQLi buffer without disturbing your SQL buffer."
547 (interactive)
548 (describe-function 'sql-help))
549
550(defun sql-read-passwd (prompt &optional default)
551 "Read a password using PROMPT.
552Optional DEFAULT is password to start with. This function calls
553`read-passwd' if it is available. If not, function
554`ange-ftp-read-passwd' is called. This should always be available,
555even in old versions of Emacs."
556 (if (fboundp 'read-passwd)
557 (read-passwd prompt nil default)
558 (unless (fboundp 'ange-ftp-read-passwd)
559 (autoload 'ange-ftp-read-passwd "ange-ftp"))
560 (ange-ftp-read-passwd prompt default)))
561
562(defun sql-get-login (&rest what)
563 "Get username, password and database from the user.
564
565The variables `sql-user', `sql-password', `sql-server' and
566`sql-database' can be customised. They are used as the default
567values. Usernames, servers and databases are stored in
568`sql-user-history', `sql-server-history' and `database-history'.
569Passwords are not stored in a history.
570
571Parameter WHAT is a list of the arguments passed to this function.
572The function asks for the username if WHAT contains symbol `user', for
573the password if it contains symbol `password', for the server if it
574contains symbol `server', and for the database if it contains symbol
575`database'.
576
577In order to ask the user for username, password and database, call the
578function like this: (sql-get-login 'user 'password 'database)."
579 (interactive)
580 (if (memq 'user what)
581 (setq sql-user
582 (read-from-minibuffer "User: " sql-user nil nil
583 sql-user-history)))
584 (if (memq 'password what)
585 (setq sql-password
586 (sql-read-passwd "Password: " sql-password)))
587 (if (memq 'server what)
588 (setq sql-server
589 (read-from-minibuffer "Server: " sql-server nil nil
590 sql-server-history)))
591 (if (memq 'database what)
592 (setq sql-database
593 (read-from-minibuffer "Database: " sql-database nil nil
594 sql-database-history))))
595
596(defun sql-copy-column ()
597 "Copy current column to the end of buffer.
598Inserts SELECT or commas if appropriate."
599 (interactive)
600 (let ((column))
601 (save-excursion
602 (setq column (buffer-substring
603 (progn (forward-char 1) (backward-sexp 1) (point))
604 (progn (forward-sexp 1) (point))))
605 (goto-char (point-max))
606 (cond
607 ;; if empty command line, insert SELECT
608 ((save-excursion (beginning-of-line)
609 (looking-at (concat comint-prompt-regexp "$")))
610 (insert "SELECT "))
611 ;; else if appending to SELECT or ORDER BY, insert a comma
612 ((save-excursion
613 (re-search-backward "\\b\\(select\\|order by\\) .+"
614 (save-excursion (beginning-of-line) (point)) t))
615 (insert ", "))
616 ;; else insert a space
617 (t
618 (if (eq (preceding-char) ? )
619 nil
620 (insert " "))))
621 ;; in any case, insert the column
622 (insert column)
623 (message "%s" column))))
624
625
626
627;;; Sending the region to the SQLi buffer.
628
629(defun sql-send-region (start end)
630 "Send a region to the SQL process."
631 (interactive "r")
632 (if (buffer-live-p sql-buffer)
633 (save-excursion
634 (comint-send-region sql-buffer start end)
635 (if (string-match "\n$" (buffer-substring start end))
636 ()
637 (comint-send-string sql-buffer "\n"))
638 (if sql-pop-to-buffer-after-send-region
639 (pop-to-buffer sql-buffer)
640 (display-buffer sql-buffer)))
641 (message "No SQL process started.")))
642
643(defun sql-send-buffer ()
644 "Send the buffer contents to the SQL process."
645 (interactive)
646 (sql-send-region (point-min) (point-max)))
647
648(defun sql-toggle-pop-to-buffer-after-send-region (&optional value)
649 "Toggle `sql-pop-to-buffer-after-send-region'.
650
651If given the optional parameter VALUE, sets
652sql-toggle-pop-to-buffer-after-send-region to VALUE."
653 (interactive "P")
654 (if value
655 (setq sql-pop-to-buffer-after-send-region value)
656 (setq sql-pop-to-buffer-after-send-region
657 (null sql-pop-to-buffer-after-send-region ))))
658
659
660
661;;; SQL mode -- uses SQL interactive mode
662
663;;;###autoload
664(defun sql-mode ()
665 "Major mode to edit SQL.
666
667You can send SQL statements to the *SQL* buffer using
668\\[sql-send-region]. Such a buffer must exist before you can do this.
669See `sql-help'.
670
671\\{sql-mode-map}
672Customization: Entry to this mode runs the `sql-mode-hook'.
673
674Here is an example for your .emacs file. It opens every file ending in
675.sql with sql-mode.
676
677\(setq auto-mode-alist (append auto-mode-alist
678 \(list '(\"\\\\.sql$\" . sql-mode))))"
679 (interactive)
680 (kill-all-local-variables)
681 (setq major-mode 'sql-mode)
682 (setq mode-name "SQL")
683 (use-local-map sql-mode-map)
684 (set-syntax-table sql-mode-syntax-table)
685 (make-local-variable 'font-lock-defaults)
686 (setq font-lock-defaults '(sql-mode-font-lock-keywords
687 nil t ((95 . "w") (46 . "w"))))
688 (setq local-abbrev-table sql-mode-abbrev-table)
689 (setq abbrev-all-caps 1)
690 (run-hooks 'sql-mode-hook))
691
692
693
694;;; SQL interactive mode
695
696(put 'sql-interactive-mode 'mode-class 'special)
697
698(defun sql-interactive-mode ()
699 "Major mode to use a SQL interpreter interactively.
700
701Do not call this function by yourself. The environment must be
702initialized by an entry function specific for the SQL interpreter. See
703`sql-help' for a list of available entry functions.
704
705\\[comint-send-input] after the end of the process' output sends the
706text from the end of process to the end of the current line.
707\\[comint-send-input] before end of process output copies the current
708line minus the prompt to the end of the buffer and sends it.
709\\[comint-copy-old-input] just copies the current line.
710Use \\[sql-accumulate-and-indent] to enter multi-line statements.
711
712If you want to make multiple SQL buffers, rename the `*SQL*' buffer
713using \\[rename-buffer] or \\[rename-uniquely] and start a new process.
714
715If you accidentally suspend your process, use \\[comint-continue-subjob]
716to continue it.
717
718\\{sql-interactive-mode-map}
719Customization: Entry to this mode runs the hooks on `comint-mode-hook'
720and `sql-interactive-mode-hook' (in that order). Before each input, the
721hooks on `comint-input-filter-functions' are run. After each SQL
722interpreter output, the hooks on `comint-output-filter-functions' are
723run.
724
725Variable `comint-input-ring-file-name' controls the initialisation of
726the input ring history.
727
728Variables `comint-output-filter-functions', a hook, and
729`comint-scroll-to-bottom-on-input' and
730`comint-scroll-to-bottom-on-output' control whether input and output
731cause the window to scroll to the end of the buffer.
732
733If you want to make SQL buffers limited in length, add the function
734`comint-truncate-buffer' to `comint-output-filter-functions'.
735
736Here is an example for your .emacs file. It keeps the *SQL* Buffer a
737certain length and stores all inputs in an input-ring file.
738
739\(add-hook 'sql-interactive-mode-hook
740 \(function (lambda ()
741 \(setq comint-input-ring-file-name \"~/.sql_history\")
742 \(setq comint-output-filter-functions 'comint-truncate-buffer))))
743
744Here is another example. It will always put point back to the statement
745you entered, right above the output it created.
746
747\(setq comint-output-filter-functions
748 \(function (lambda (STR) (comint-show-output))))"
749 (comint-mode)
750 (setq comint-prompt-regexp sql-prompt-regexp)
751 (setq major-mode 'sql-interactive-mode)
752 (setq mode-name "SQLi")
753 (use-local-map sql-interactive-mode-map)
754 (set-syntax-table sql-mode-syntax-table)
755 (make-local-variable 'font-lock-defaults)
756 (setq font-lock-defaults '(sql-mode-font-lock-keywords t t ((95 . "w") (46 . "w"))))
757 (setq left-margin 5)
758 (setq local-abbrev-table sql-mode-abbrev-table)
759 (setq abbrev-all-caps 1)
760 (set-process-sentinel (get-buffer-process sql-buffer) 'sql-stop)
761 (run-hooks 'sql-interactive-mode-hook)
762 ;; calling the hook before calling comint-read-input-ring allows users
763 ;; to set comint-input-ring-file-name in sql-interactive-mode-hook.
764 (comint-read-input-ring t))
765
766(defun sql-stop (process event)
767 "Called when the SQL process is stopped.
768
769Writes the input history to a history file using `comint-write-input-ring'
770and inserts a short message in the SQL buffer.
771
772This function is a sentinel watching the SQL interpreter process.
773Sentinels will always get the two parameters PROCESS and EVENT."
774 (comint-write-input-ring)
775 (if (buffer-live-p sql-buffer)
776 (insert (format "\nProcess %s %s\n" process event))))
777
778
779
780;;; Entry functions for different SQL interpreters.
781
782(defun sql-oracle ()
783 "Run sqlplus by Oracle as an inferior process.
784
785If buffer *SQL* exists but no process is running, make a new process.
786If buffer exists and a process is running, just switch to buffer
787`*SQL*'.
788
789Interpreter used comes from variable `sql-oracle-program'. Login
790uses the variables `sql-user', `sql-password' and `sql-database' as
791defaults, if set.
792
793The buffer is put in sql-interactive-mode, giving commands for sending
794input. See `sql-interactive-mode'.
795
796To specify a coding system for converting non-ASCII characters
797in the input and output to the process, use \\[universal-coding-system-argument]
798before \\[sql-oracle]. You can also specify this with \\[set-buffer-process-coding-system]
799in the SQL buffer, after you start the process.
800The default comes from `process-coding-system-alist' and
801`default-process-coding-system'.
802
803\(Type \\[describe-mode] in the SQL buffer for a list of commands.)"
804 (interactive)
805 (if (comint-check-proc "*SQL*")
806 (pop-to-buffer "*SQL*")
807 (sql-get-login 'user 'password 'database)
808 (message "Login...")
809 ;; Produce user/password@database construct. Password without user
810 ;; is meaningless; database without user/password is meaningless,
811 ;; because "@param" will ask sqlplus to interpret the script
812 ;; "param".
813 (let ((parameter nil))
814 (if (not (string= "" sql-user))
815 (if (not (string= "" sql-password))
816 (setq parameter (concat sql-user "/" sql-password))
817 (setq parameter sql-user)))
818 (if (and parameter (not (string= "" sql-database)))
819 (setq parameter (concat parameter "@" sql-database)))
820 (if parameter
821 (set-buffer (make-comint "SQL" sql-oracle-program nil parameter))
822 (set-buffer (make-comint "SQL" sql-oracle-program nil))))
823 (setq sql-prompt-regexp "^SQL> ")
824 (setq sql-buffer (current-buffer))
825 ;; set sql-mode-font-lock-keywords to something different before
826 ;; calling sql-interactive-mode.
827 (setq sql-mode-font-lock-keywords sql-mode-oracle-font-lock-keywords)
828 (sql-interactive-mode)
829 (message "Login...done")
830 (pop-to-buffer sql-buffer)))
831
832
833
834(defun sql-sybase ()
835 "Run isql by SyBase as an inferior process.
836
837If buffer *SQL* exists but no process is running, make a new process.
838If buffer exists and a process is running, just switch to buffer
839`*SQL*'.
840
841Interpreter used comes from variable `sql-sybase-program'. Login uses
842the variables `sql-user', `sql-password' and `sql-database' as defaults,
843if set.
844
845The buffer is put in sql-interactive-mode, giving commands for sending
846input. See `sql-interactive-mode'.
847
848To specify a coding system for converting non-ASCII characters
849in the input and output to the process, use \\[universal-coding-system-argument]
850before \\[sql-sybase]. You can also specify this with \\[set-buffer-process-coding-system]
851in the SQL buffer, after you start the process.
852The default comes from `process-coding-system-alist' and
853`default-process-coding-system'.
854
855\(Type \\[describe-mode] in the SQL buffer for a list of commands.)"
856 (interactive)
857 (if (comint-check-proc "*SQL*")
858 (pop-to-buffer "*SQL*")
859 (sql-get-login 'user 'password 'database)
860 (message "Login...")
861 ;; Put all parameters to the program (if defined) in a list and call
862 ;; make-comint.
863 (let ((params '("-w" "2048" "-n")))
864 ;; I had a zillion versions of this using nconc and mapcar,
865 ;; mixtures of eval, list and quotes -- you have been warned.
866 (if (not (string= "" sql-database))
867 (setq params (append (list "-S" sql-database) params)))
868 (if (not (string= "" sql-password))
869 (setq params (append (list "-P" sql-password) params)))
870 (if (not (string= "" sql-user))
871 (setq params (append (list "-U" sql-user) params)))
872 (set-buffer (apply 'make-comint "SQL" sql-sybase-program
873 nil params)))
874 (setq sql-prompt-regexp "^SQL> ")
875 (setq sql-buffer (current-buffer))
876 (sql-interactive-mode)
877 (message "Login...done")
878 (pop-to-buffer sql-buffer)))
879
880
881
882(defun sql-informix ()
883 "Run dbaccess by Informix as an inferior process.
884
885If buffer *SQL* exists but no process is running, make a new process.
886If buffer exists and a process is running, just switch to buffer
887`*SQL*'.
888
889Interpreter used comes from variable `sql-informix-program'. Login uses
890the variable `sql-database' as default, if set.
891
892The buffer is put in sql-interactive-mode, giving commands for sending
893input. See `sql-interactive-mode'.
894
895To specify a coding system for converting non-ASCII characters
896in the input and output to the process, use \\[universal-coding-system-argument]
897before \\[sql-informix]. You can also specify this with \\[set-buffer-process-coding-system]
898in the SQL buffer, after you start the process.
899The default comes from `process-coding-system-alist' and
900`default-process-coding-system'.
901
902\(Type \\[describe-mode] in the SQL buffer for a list of commands.)"
903 (interactive)
904 (if (comint-check-proc "*SQL*")
905 (pop-to-buffer "*SQL*")
906 (sql-get-login 'database)
907 (message "Login...")
908 ;; username and password are ignored.
909 (if (string= "" sql-database)
910 (set-buffer (make-comint "SQL" sql-informix-program nil))
911 (set-buffer (make-comint "SQL" sql-informix-program nil sql-database)))
912 (setq sql-prompt-regexp "^SQL> ")
913 (setq sql-buffer (current-buffer))
914 (sql-interactive-mode)
915 (message "Login...done")
916 (pop-to-buffer sql-buffer)))
917
918
919
920(defun sql-ingres ()
921 "Run sql by Ingres as an inferior process.
922
923If buffer *SQL* exists but no process is running, make a new process.
924If buffer exists and a process is running, just switch to buffer
925`*SQL*'.
926
927Interpreter used comes from variable `sql-ingres-program'. Login uses
928the variable `sql-database' as default, if set.
929
930The buffer is put in sql-interactive-mode, giving commands for sending
931input. See `sql-interactive-mode'.
932
933To specify a coding system for converting non-ASCII characters
934in the input and output to the process, use \\[universal-coding-system-argument]
935before \\[sql-ingres]. You can also specify this with \\[set-buffer-process-coding-system]
936in the SQL buffer, after you start the process.
937The default comes from `process-coding-system-alist' and
938`default-process-coding-system'.
939
940\(Type \\[describe-mode] in the SQL buffer for a list of commands.)"
941 (interactive)
942 (if (comint-check-proc "*SQL*")
943 (pop-to-buffer "*SQL*")
944 (sql-get-login 'database)
945 (message "Login...")
946 ;; username and password are ignored.
947 (if (string= "" sql-database)
948 (set-buffer (make-comint "SQL" sql-ingres-program nil))
949 (set-buffer (make-comint "SQL" sql-ingres-program nil sql-database)))
950 (setq sql-prompt-regexp "^\* ")
951 (setq sql-buffer (current-buffer))
952 (sql-interactive-mode)
953 (message "Login...done")
954 (pop-to-buffer sql-buffer)))
955
956
957
958(defun sql-ms ()
959 "Run isql by Microsoft as an inferior process.
960
961If buffer *SQL* exists but no process is running, make a new process.
962If buffer exists and a process is running, just switch to buffer
963`*SQL*'.
964
965Interpreter used comes from variable `sql-ms-program'. Login uses the
966variables `sql-user', `sql-password', `sql-server' and `sql-database'
967as defaults, if set.
968
969The buffer is put in sql-interactive-mode, giving commands for sending
970input. See `sql-interactive-mode'.
971
972To specify a coding system for converting non-ASCII characters
973in the input and output to the process, use \\[universal-coding-system-argument]
974before \\[sql-sybase]. You can also specify this with \\[set-buffer-process-coding-system]
975in the SQL buffer, after you start the process.
976The default comes from `process-coding-system-alist' and
977`default-process-coding-system'.
978
979\(Type \\[describe-mode] in the SQL buffer for a list of commands.)"
980 (interactive)
981 (if (comint-check-proc "*SQL*")
982 (pop-to-buffer "*SQL*")
983 (sql-get-login 'user 'password 'database 'server)
984 (message "Login...")
985 ;; Put all parameters to the program (if defined) in a list and call
986 ;; make-comint.
987 (let ((params '("-w 300")))
988 (if (not (string= "" sql-server))
989 (setq params (append (list "-S" sql-server) params)))
990 (if (not (string= "" sql-database))
991 (setq params (append (list "-d" sql-database) params)))
992 (if (not (string= "" sql-user))
993 (setq params (append (list "-U" sql-user) params)))
994 (if (not (string= "" sql-password))
995 (setq params (append (list "-P" sql-password) params))
996 ;; If -P is passed to ISQL as the last argument without a password,
997 ;; it's considered null.
998 (setq params (append params (list "-P"))))
999 (set-buffer (apply 'make-comint "SQL" sql-ms-program
1000 nil params)))
1001 (setq sql-prompt-regexp "^[0-9]*>")
1002 (setq sql-buffer (current-buffer))
1003 (sql-interactive-mode)
1004 (message "Login...done")
1005 (pop-to-buffer sql-buffer)))
1006
1007
1008
1009
1010;;;###autoload
1011(defun sql-postgres ()
1012 "Run psql by Postgres as an inferior process.
1013
1014If buffer *SQL* exists but no process is running, make a new process.
1015If buffer exists and a process is running, just switch to buffer
1016`*SQL*'.
1017
1018Interpreter used comes from variable `sql-postgres-program'. Login uses
1019the variable `sql-database' as default, if set.
1020
1021The buffer is put in sql-interactive-mode, giving commands for sending
1022input. See `sql-interactive-mode'.
1023
1024To specify a coding system for converting non-ASCII characters
1025in the input and output to the process, use \\[universal-coding-system-argument]
1026before \\[sql-postgres]. You can also specify this with \\[set-buffer-process-coding-system]
1027in the SQL buffer, after you start the process.
1028The default comes from `process-coding-system-alist' and
1029`default-process-coding-system'. If your output lines end with ^M,
1030your might try undecided-dos as a coding system. If this doesn't help,
1031Try to set `comint-output-filter-functions' like this:
1032
1033\(setq comint-output-filter-functions (append comint-output-filter-functions
1034 '(comint-strip-ctrl-m)))
1035
1036\(Type \\[describe-mode] in the SQL buffer for a list of commands.)"
1037 (interactive)
1038 (if (comint-check-proc "*SQL*")
1039 (pop-to-buffer "*SQL*")
1040 (sql-get-login 'database)
1041 (message "Login...")
1042 ;; username and password are ignored.
1043 (if (string= "" sql-database)
1044 (set-buffer (make-comint "SQL" sql-postgres-program nil))
1045 (set-buffer (make-comint "SQL" sql-postgres-program nil sql-database)))
1046 (setq sql-prompt-regexp "^.*> *")
1047 ;; This is a lousy hack to prevent psql from truncating it's output
1048 ;; and giving stupid warnings. If s.o. knows a way to prevent psql
1049 ;; from acting this way, then I would be very thankful to
1050 ;; incorporate this (Gregor Zych <zych@pool.informatik.rwth-aachen.de>)
1051 (comint-send-string "*SQL*" "\\o \| cat\n")
1052 (setq sql-mode-font-lock-keywords sql-mode-postgres-font-lock-keywords)
1053 (setq sql-buffer (current-buffer))
1054 (sql-interactive-mode)
1055 (message "Login...done")
1056 (pop-to-buffer sql-buffer)))
1057
1058(provide 'sql)
1059
1060;;; sql.el ends here