Copyright up-date.
[bpt/emacs.git] / lisp / progmodes / sql.el
CommitLineData
95e4b2ef
RS
1;;; sql.el --- specialized comint.el for SQL interpreters
2
9ef3882f 3;; Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
95e4b2ef 4
1533eb58
AS
5;; Author: Alex Schroeder <alex@gnu.org>
6;; Maintainer: Alex Schroeder <alex@gnu.org>
77d352a6 7;; Version: 1.4.16
dab100d7 8;; Keywords: comm languages processes
95e4b2ef
RS
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
c04bb32e 29;; Please send bug reports and bug fixes to the mailing list at
801d1cb0
AS
30;; sql.el@gnu.org. If you want to subscribe to the mailing list, send
31;; mail to sql.el-request@gnu.org with `subscribe sql.el FIRSTNAME
1533eb58 32;; LASTNAME' in the mail body.
95e4b2ef 33
95e4b2ef
RS
34;; This file provides a sql-mode and a sql-interactive-mode. My goals
35;; were two simple modes providing syntactic hilighting. The
36;; interactive mode had to provide a command-line history; the other
37;; mode had to provide "send region/buffer to SQL interpreter"
38;; functions. "simple" in this context means easy to use, easy to
801d1cb0 39;; maintain and little or no bells and whistles.
95e4b2ef
RS
40
41;; If anybody feels like extending this sql mode, take a look at the
42;; above mentioned modes and write a sqlx-mode on top of this one. If
43;; this proves to be difficult, please suggest changes that will
44;; facilitate your plans.
45
46;; sql-interactive-mode is used to interact with a SQL interpreter
dab100d7
RS
47;; process in a SQLi buffer (usually called `*SQL*'). The SQLi buffer
48;; is created by calling a SQL interpreter-specific entry function. Do
49;; *not* call sql-interactive-mode by itself.
95e4b2ef
RS
50
51;; The list of currently supported interpreters and the corresponding
dab100d7 52;; entry function used to create the SQLi buffers is shown with
95e4b2ef
RS
53;; `sql-help' (M-x sql-help).
54
55;; Since sql-interactive-mode is built on top of the general
56;; command-interpreter-in-a-buffer mode (comint mode), it shares a
57;; common base functionality, and a common set of bindings, with all
58;; modes derived from comint mode. This makes these modes easier to
59;; use.
60
61;; sql-mode can be used to enable syntactic hilighting for SQL
62;; statements in another buffer. SQL statements can then be sent to
dab100d7 63;; the SQL process in the SQLi buffer. sql-mode has already been
95e4b2ef
RS
64;; used as a template to a simple PL/SQL mode.
65
66;; For documentation on the functionality provided by comint mode, and
67;; the hooks available for customising it, see the file `comint.el'.
68
801d1cb0
AS
69;; Hint for newbies: take a look at `dabbrev-expand', `abbrev-mode', and
70;; `imenu-add-menubar-index'.
95e4b2ef
RS
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
9ef3882f
GM
88;; ChangeLog available on request.
89
95e4b2ef
RS
90;;; To Do:
91
92;; Add better hilight support for other brands; there is a bias towards
93;; Oracle because that's what I use at work. Anybody else just send in
dab100d7
RS
94;; your lists of reserved words, keywords and builtin functions! As
95;; long as I don't receive any feedback, everything is hilighted with
96;; ANSI keywords only. I received the list of ANSI keywords from a
97;; user; if you know of any changes, let me know.
95e4b2ef
RS
98
99;; Add different hilighting levels.
100
101;;; Thanks to all the people who helped me out:
102
103;; Kai Blauberg <kai.blauberg@metla.fi>
104;; <ibalaban@dalet.com>
105;; Yair Friedman <yfriedma@JohnBryce.Co.Il>
106;; Gregor Zych <zych@pool.informatik.rwth-aachen.de>
a081a529 107;; nino <nino@inform.dk>
801d1cb0 108;; Berend de Boer <berend@pobox.com>
dab100d7 109
95e4b2ef
RS
110\f
111
112;;; Code:
113
114(require 'comint)
115;; Need the following to allow GNU Emacs 19 to compile the file.
116(require 'regexp-opt)
117(require 'custom)
118
119;;; Allow customization
120
121(defgroup SQL nil
122 "Running a SQL interpreter from within Emacs buffers"
6629e5ba 123 :version "20.4"
95e4b2ef
RS
124 :group 'processes)
125
126;; These three variables will be used as defaults, if set.
127
128(defcustom sql-user ""
129 "*Default username."
130 :type 'string
131 :group 'SQL)
132
133(defcustom sql-password ""
134 "*Default password.
135
136Storing your password in a textfile such as ~/.emacs could be dangerous.
137Customizing your password will store it in your ~/.emacs file."
138 :type 'string
139 :group 'SQL)
140
141(defcustom sql-database ""
142 "*Default database."
143 :type 'string
144 :group 'SQL)
145
146(defcustom sql-server ""
dab100d7 147 "*Default server or host."
95e4b2ef
RS
148 :type 'string
149 :group 'SQL)
150
801d1cb0
AS
151;; misc customization of sql.el behaviour
152
9ef3882f
GM
153(defcustom sql-electric-stuff nil
154 "Treat some input as electric.
155If set to the symbol `semicolon', then hitting `;' will send current
156input in the SQLi buffer to the process.
157If set to the symbol `go', then hitting `go' on a line by itself will
158send current input in the SQLi buffer to the process.
159If set to nil, then you must use \\[comint-send-input] in order to send
160current input in the SQLi buffer to the process."
161 :type '(choice (const :tag "Nothing" nil)
162 (const :tag "The semikolon `;'" semicolon)
163 (const :tag "The string `go' by itself" go))
164 :version "20.8"
165 :group 'SQL)
166
95e4b2ef
RS
167(defcustom sql-pop-to-buffer-after-send-region nil
168 "*If t, pop to the buffer SQL statements are sent to.
169
170After a call to `sql-send-region' or `sql-send-buffer',
171the window is split and the SQLi buffer is shown. If this
a081a529
RS
172variable is not nil, that buffer's window will be selected
173by calling `pop-to-buffer'. If this variable is nil, that
174buffer is shown using `display-buffer'."
c7055d66
RS
175 :type 'boolean
176 :group 'SQL)
177
801d1cb0
AS
178;; imenu support for sql-mode.
179
180(defvar sql-imenu-generic-expression
181 '(("Tables" "^\\s-*create\\s-+table\\s-+\\(\\w+\\)" 1)
182 ("Indexes" "^\\s-*create\\s-+index\\s-+\\(\\w+\\)" 1))
183 "Define interesting points in the SQL buffer for `imenu'.
184
9ef3882f
GM
185This is used to set `imenu-generic-expression' when SQL mode is
186entered. Subsequent changes to sql-imenu-generic-expression will not
187affect existing SQL buffers because imenu-generic-expression is a
188local variable.")
801d1cb0
AS
189
190;; history file
191
c7055d66
RS
192(defcustom sql-input-ring-file-name nil
193 "*If non-nil, name of the file to read/write input history.
194
9ef73b91
KH
195You have to set this variable if you want the history of your commands
196saved from one Emacs session to the next. If this variable is set,
197exiting the SQL interpreter in an SQLi buffer will write the input
198history to the specified file. Starting a new process in a SQLi buffer
199will read the input history from the specified file.
200
77d352a6
GM
201This is used to initialize `comint-input-ring-file-name'.
202
203Note that the size of the input history is determined by the variable
204`comint-input-ring-size'."
c7055d66
RS
205 :type '(choice (const :tag "none" nil)
206 (file))
207 :group 'SQL)
208
209(defcustom sql-input-ring-separator "\n--\n"
210 "*Separator between commands in the history file.
211
212If set to \"\\n\", each line in the history file will be interpreted as
213one command. Multi-line commands are split into several commands when
214the input ring is initialized from a history file.
215
77d352a6
GM
216This variable used to initialize `comint-input-ring-separator'.
217`comint-input-ring-separator' is part of Emacs 21; if your Emacs
218does not have it, setting `sql-input-ring-separator' will have no
219effect. In that case multiline commands will be split into several
220commands when the input history is read, as if you had set
221`sql-input-ring-separator' to \"\\n\"."
95e4b2ef
RS
222 :type 'string
223 :group 'SQL)
224
225;; The usual hooks
226
227(defcustom sql-interactive-mode-hook '()
228 "*Hook for customising `sql-interactive-mode'."
229 :type 'hook
230 :group 'SQL)
231
232(defcustom sql-mode-hook '()
233 "*Hook for customising `sql-mode'."
234 :type 'hook
235 :group 'SQL)
236
c7055d66
RS
237(defcustom sql-set-sqli-hook '()
238 "*Hook for reacting to changes of `sql-buffer'.
239
240This is called by `sql-set-sqli-buffer' when the value of `sql-buffer'
241is changed."
242 :type 'hook
243 :group 'SQL)
244
95e4b2ef
RS
245;; Customisation for Oracle
246
247(defcustom sql-oracle-program "sqlplus"
248 "*Command to start sqlplus by Oracle.
249
250Starts `sql-interactive-mode' after doing some setup.
251
252Under NT, \"sqlplus\" usually starts the sqlplus \"GUI\". In order to
253start the sqlplus console, use \"plus33\" or something similar. You
254will find the file in your Orant\\bin directory.
255
a081a529
RS
256The program can also specify a TCP connection. See `make-comint'."
257 :type 'file
258 :group 'SQL)
259
9ef3882f
GM
260(defcustom sql-oracle-options nil
261 "*List of additional options for `sql-oracle-program'."
262 :type '(repeat string)
263 :version "20.8"
264 :group 'SQL)
265
a081a529
RS
266;; Customisation for MySql
267
268(defcustom sql-mysql-program "mysql"
269 "*Command to start mysql by TcX.
270
271Starts `sql-interactive-mode' after doing some setup.
272
dab100d7
RS
273The program can also specify a TCP connection. See `make-comint'."
274 :type 'file
275 :group 'SQL)
276
277;; Customisation for Solid
278
279(defcustom sql-solid-program "solsql"
280 "*Command to start SOLID SQL Editor.
281
282Starts `sql-interactive-mode' after doing some setup.
283
95e4b2ef
RS
284The program can also specify a TCP connection. See `make-comint'."
285 :type 'file
286 :group 'SQL)
287
288;; Customisation for SyBase
289
290(defcustom sql-sybase-program "isql"
801d1cb0 291 "*Command to start isql by SyBase.
95e4b2ef
RS
292
293Starts `sql-interactive-mode' after doing some setup.
294
295The program can also specify a TCP connection. See `make-comint'."
296 :type 'file
297 :group 'SQL)
298
299;; Customisation for Informix
300
301(defcustom sql-informix-program "dbaccess"
801d1cb0 302 "*Command to start dbaccess by Informix.
95e4b2ef
RS
303
304Starts `sql-interactive-mode' after doing some setup.
305
306The program can also specify a TCP connection. See `make-comint'."
307 :type 'file
308 :group 'SQL)
309
310;; Customisation for Ingres
311
312(defcustom sql-ingres-program "sql"
801d1cb0 313 "*Command to start sql by Ingres.
95e4b2ef
RS
314
315Starts `sql-interactive-mode' after doing some setup.
316
317The program can also specify a TCP connection. See `make-comint'."
318 :type 'file
319 :group 'SQL)
320
321;; Customisation for Microsoft
322
323(defcustom sql-ms-program "isql"
801d1cb0 324 "*Command to start isql by Microsoft.
95e4b2ef
RS
325
326Starts `sql-interactive-mode' after doing some setup.
327
328The program can also specify a TCP connection. See `make-comint'."
329 :type 'file
330 :group 'SQL)
331
332;; Customisation for Postgres
333
334(defcustom sql-postgres-program "psql"
801d1cb0 335 "Command to start psql by Postgres.
95e4b2ef
RS
336
337Starts `sql-interactive-mode' after doing some setup.
338
339The program can also specify a TCP connection. See `make-comint'."
340 :type 'file
341 :group 'SQL)
342
343\f
344
345;;; Variables which do not need customization
346
347(defvar sql-user-history nil
348 "History of usernames used.")
349
350(defvar sql-database-history nil
351 "History of databases used.")
352
353(defvar sql-server-history nil
354 "History of servers used.")
355
356;; Passwords are not kept in a history.
357
358(defvar sql-buffer nil
dab100d7
RS
359 "Current SQLi buffer.
360
361The global value of sql-buffer is the name of the latest SQLi buffer
362created. Any SQL buffer created will make a local copy of this value.
363See `sql-interactive-mode' for more on multiple sessions. If you want
364to change the SQLi buffer a SQL mode sends its SQL strings to, change
c7055d66 365the local value of `sql-buffer' using \\[sql-set-sqli-buffer].")
95e4b2ef
RS
366
367(defvar sql-prompt-regexp nil
368 "Prompt used to initialize `comint-prompt-regexp'.
369
370You can change `comint-prompt-regexp' on `sql-interactive-mode-hook'.")
371
a081a529
RS
372(defvar sql-prompt-length 0
373 "Prompt used to set `left-margin' in `sql-interactive-mode'.
374
375You can change it on `sql-interactive-mode-hook'.")
376
c7055d66
RS
377(defvar sql-alternate-buffer-name nil
378 "Buffer-local string used to possibly rename the SQLi buffer.
379
380Used by `sql-rename-buffer'.")
381
9ef3882f
GM
382;; Keymap for sql-interactive-mode.
383
384(defvar sql-interactive-mode-map
385 (let ((map (make-sparse-keymap)))
386 (if (functionp 'set-keymap-parent)
387 (set-keymap-parent map comint-mode-map); Emacs
388 (set-keymap-parents map (list comint-mode-map))); XEmacs
389 (if (functionp 'set-keymap-name)
390 (set-keymap-name map 'sql-interactive-mode-map)); XEmacs
391 (define-key map (kbd "C-j") 'sql-accumulate-and-indent)
392 (define-key map (kbd "C-c C-w") 'sql-copy-column)
393 (define-key map (kbd "O") 'sql-magic-go)
394 (define-key map (kbd "o") 'sql-magic-go)
395 (define-key map (kbd ";") 'sql-magic-semicolon)
396 map)
397 "Mode map used for `sql-interactive-mode'.
398Based on `comint-mode-map'.")
95e4b2ef
RS
399
400;; Keymap for sql-mode.
401
402(defvar sql-mode-map
403 (let ((map (make-sparse-keymap)))
9ef3882f
GM
404 (define-key map (kbd "C-c C-c") 'sql-send-paragraph)
405 (define-key map (kbd "C-c C-r") 'sql-send-region)
406 (define-key map (kbd "C-c C-b") 'sql-send-buffer)
77d352a6 407 (define-key map (kbd "<TAB>") 'indent-relative)
95e4b2ef
RS
408 map)
409 "Mode map used for `sql-mode'.")
410
411;; easy menu for sql-mode.
412
801d1cb0
AS
413(easy-menu-define
414 sql-mode-menu sql-mode-map
95e4b2ef
RS
415 "Menu for `sql-mode'."
416 '("SQL"
dab100d7
RS
417 ["Send Paragraph" sql-send-paragraph (and (buffer-live-p sql-buffer)
418 (get-buffer-process sql-buffer))]
801d1cb0 419 ["Send Region" sql-send-region (and mark-active
dab100d7
RS
420 (buffer-live-p sql-buffer)
421 (get-buffer-process sql-buffer))]
422 ["Send Buffer" sql-send-buffer (and (buffer-live-p sql-buffer)
423 (get-buffer-process sql-buffer))]
424 ["Show SQLi buffer" sql-show-sqli-buffer t]
c7055d66 425 ["Set SQLi buffer" sql-set-sqli-buffer t]
801d1cb0 426 ["Pop to SQLi buffer after send"
95e4b2ef
RS
427 sql-toggle-pop-to-buffer-after-send-region
428 :style toggle
429 :selected sql-pop-to-buffer-after-send-region]))
430
c7055d66
RS
431;; easy menu for sql-interactive-mode.
432
801d1cb0 433(easy-menu-define
c7055d66
RS
434 sql-interactive-mode-menu sql-interactive-mode-map
435 "Menu for `sql-interactive-mode'."
436 '("SQL"
437 ["Rename Buffer" sql-rename-buffer t]))
438
95e4b2ef
RS
439;; Abbreviations -- if you want more of them, define them in your
440;; ~/.emacs file. Abbrevs have to be enabled in your ~/.emacs, too.
441
442(defvar sql-mode-abbrev-table nil
443 "Abbrev table used in `sql-mode' and `sql-interactive-mode'.")
444(if sql-mode-abbrev-table
445 ()
446 (let ((wrapper))
447 (define-abbrev-table 'sql-mode-abbrev-table ())
448 (define-abbrev sql-mode-abbrev-table "ins" "insert" nil)
449 (define-abbrev sql-mode-abbrev-table "upd" "update" nil)
450 (define-abbrev sql-mode-abbrev-table "del" "delete" nil)
451 (define-abbrev sql-mode-abbrev-table "sel" "select" nil)))
452
453;; Syntax Table
454
801d1cb0 455(defvar sql-mode-syntax-table
95e4b2ef
RS
456 (let ((table (make-syntax-table)))
457 ;; C-style comments /**/ (see elisp manual "Syntax Flags"))
458 (modify-syntax-entry ?/ ". 14" table)
459 (modify-syntax-entry ?* ". 23" table)
460 ;; double-dash starts comment
c04bb32e
RS
461 (if (string-match "XEmacs\\|Lucid" emacs-version)
462 (modify-syntax-entry ?- ". 56" table)
463 (modify-syntax-entry ?- ". 12b" table))
95e4b2ef
RS
464 ;; newline and formfeed end coments
465 (modify-syntax-entry ?\n "> b" table)
466 (modify-syntax-entry ?\f "> b" table)
a081a529
RS
467 ;; single quotes (') quotes delimit strings
468 (modify-syntax-entry ?' "\"" table)
95e4b2ef
RS
469 table)
470 "Syntax table used in `sql-mode' and `sql-interactive-mode'.")
471
472;; Font lock support
473
474(defvar sql-mode-ansi-font-lock-keywords nil
475 "ANSI SQL keywords used by font-lock.
476
477This variable is used by `sql-mode' and `sql-interactive-mode'. The
478regular expressions are created during compilation by calling the
479function `regexp-opt'. Therefore, take a look at the source before
480you define your own sql-mode-ansi-font-lock-keywords. You may want to
481add functions and PL/SQL keywords.")
482(if sql-mode-ansi-font-lock-keywords
483 ()
484 (let ((ansi-keywords (eval-when-compile
485 (concat "\\b"
486 (regexp-opt '(
487"authorization" "avg" "begin" "close" "cobol" "commit"
488"continue" "count" "declare" "double" "end" "escape"
801d1cb0 489"exec" "fetch" "foreign" "fortran" "found" "go" "goto" "indicator"
95e4b2ef
RS
490"key" "language" "max" "min" "module" "numeric" "open" "pascal" "pli"
491"precision" "primary" "procedure" "references" "rollback"
492"schema" "section" "some" "sqlcode" "sqlerror" "sum" "work") t) "\\b")))
493 (ansi-reserved-words (eval-when-compile
494 (concat "\\b"
495 (regexp-opt '(
496"all" "and" "any" "as" "asc" "between" "by" "check" "create"
497"current" "default" "delete" "desc" "distinct" "exists" "float" "for"
498"from" "grant" "group" "having" "in" "insert" "into" "is"
499"like" "not" "null" "of" "on" "option" "or" "order" "privileges"
500"public" "select" "set" "table" "to" "union" "unique"
501"update" "user" "values" "view" "where" "with") t) "\\b")))
502 (ansi-types (eval-when-compile
503 (concat "\\b"
504 (regexp-opt '(
801d1cb0
AS
505;; ANSI Keywords that look like types
506"character" "cursor" "dec" "int" "real"
95e4b2ef
RS
507;; ANSI Reserved Word that look like types
508"char" "integer" "smallint" ) t) "\\b"))))
509 (setq sql-mode-ansi-font-lock-keywords
8de85318
KH
510 (list (cons ansi-keywords 'font-lock-function-name-face)
511 (cons ansi-reserved-words 'font-lock-keyword-face)
512 (cons ansi-types 'font-lock-type-face)))))
95e4b2ef
RS
513
514(defvar sql-mode-oracle-font-lock-keywords nil
515 "Oracle SQL keywords used by font-lock.
516
517This variable is used by `sql-mode' and `sql-interactive-mode'. The
518regular expressions are created during compilation by calling the
519function `regexp-opt'. Therefore, take a look at the source before
520you define your own sql-mode-oracle-font-lock-keywords. You may want
521to add functions and PL/SQL keywords.")
522(if sql-mode-oracle-font-lock-keywords
523 ()
524 (let ((oracle-keywords (eval-when-compile
525 (concat "\\b"
526 (regexp-opt '(
527"admin" "after" "allocate" "analyze" "archive" "archivelog" "backup"
528"become" "before" "block" "body" "cache" "cancel" "cascade" "change"
529"checkpoint" "compile" "constraint" "constraints" "contents"
530"controlfile" "cycle" "database" "datafile" "dba" "disable" "dismount"
77d352a6
GM
531"dump" "each" "else" "elsif" "enable" "events" "except" "exceptions"
532"execute" "exit" "explain" "extent" "externally" "false" "flush" "force"
533"freelist" "freelists" "function" "groups" "if" "including" "initrans"
534"instance" "layer" "link" "lists" "logfile" "loop" "manage" "manual"
535"maxdatafiles" "maxinistances" "maxlogfiles" "maxloghistory"
536"maxlogmembers" "maxtrans" "maxvalue" "minextents" "minvalue" "mount"
537"new" "next" "noarchivelog" "nocache" "nocycle" "nomaxvalue"
538"nominvalue" "none" "noorder" "noresetlogs" "normal" "nosort" "off"
539"old" "only" "optimal" "others" "out" "own" "package" "parallel"
540"pctincrease" "pctused" "plan" "pragma" "private" "profile" "quota"
541"raise" "read" "recover" "referencing" "resetlogs" "restrict_references"
542"restricted" "return" "returning" "reuse" "rnds" "rnps" "role" "roles"
543"savepoint" "scn" "segment" "sequence" "shared" "snapshot" "sort"
544"statement_id" "statistics" "stop" "storage" "subtype" "switch" "system"
95e4b2ef 545"tables" "tablespace" "temporary" "thread" "time" "tracing"
77d352a6
GM
546"transaction" "triggers" "true" "truncate" "type" "under" "unlimited"
547"until" "use" "using" "when" "while" "wnds" "wnps" "write") t) "\\b")))
548 (oracle-warning-words (eval-when-compile
549 (concat "\\b"
550 (regexp-opt '(
551"cursor_already_open" "dup_val_on_index" "exception" "invalid_cursor"
552"invalid_number" "login_denied" "no_data_found" "not_logged_on"
553"notfound" "others" "pragma" "program_error" "storage_error"
554"timeout_on_resource" "too_many_rows" "transaction_backed_out"
555"value_error" "zero_divide") t) "\\b")))
95e4b2ef
RS
556 (oracle-reserved-words (eval-when-compile
557 (concat "\\b"
558 (regexp-opt '(
559"access" "add" "alter" "audit" "cluster" "column" "comment" "compress"
560"connect" "drop" "else" "exclusive" "file" "grant"
561"identified" "immediate" "increment" "index" "initial" "intersect"
562"level" "lock" "long" "maxextents" "minus" "mode" "modify" "noaudit"
563"nocompress" "nowait" "number" "offline" "online" "pctfree" "prior"
564"raw" "rename" "resource" "revoke" "row" "rowlabel" "rownum"
565"rows" "session" "share" "size" "start" "successful" "synonym" "sysdate"
566"then" "trigger" "uid" "validate" "whenever") t) "\\b")))
567 (oracle-types (eval-when-compile
568 (concat "\\b"
569 (regexp-opt '(
570;; Oracle Keywords that look like types
571;; Oracle Reserved Words that look like types
77d352a6
GM
572"binary_integer" "blob" "boolean" "constant" "date" "decimal" "rowid"
573"varchar" "varchar2") t) "\\b")))
95e4b2ef
RS
574 (oracle-builtin-functions (eval-when-compile
575 (concat "\\b"
576 (regexp-opt '(
577;; Misc Oracle builtin functions
578"abs" "add_months" "ascii" "avg" "ceil" "chartorowid" "chr" "concat"
579"convert" "cos" "cosh" "count" "currval" "decode" "dump" "exp" "floor"
580"glb" "greatest" "greatest_lb" "hextoraw" "initcap" "instr" "instrb"
581"last_day" "least" "least_ub" "length" "lengthb" "ln" "log" "lower"
582"lpad" "ltrim" "lub" "max" "min" "mod" "months_between" "new_time"
583"next_day" "nextval" "nls_initcap" "nls_lower" "nls_upper" "nlssort"
584"nvl" "power" "rawtohex" "replace" "round" "rowidtochar" "rpad"
585"rtrim" "sign" "sin" "sinh" "soundex" "sqlcode" "sqlerrm" "sqrt"
586"stddev" "sum" "substr" "substrb" "tan" "tanh" "to_char"
587"to_date" "to_label" "to_multi_byte" "to_number" "to_single_byte"
77d352a6 588"translate" "trim" "trunc" "uid" "upper" "userenv" "variance" "vsize") t) "\\b"))))
95e4b2ef
RS
589 (setq sql-mode-oracle-font-lock-keywords
590 (append sql-mode-ansi-font-lock-keywords
8de85318 591 (list (cons oracle-keywords 'font-lock-function-name-face)
77d352a6 592 (cons oracle-warning-words 'font-lock-warning-face)
8de85318 593 (cons oracle-reserved-words 'font-lock-keyword-face)
95e4b2ef
RS
594 ;; XEmacs doesn't have font-lock-builtin-face
595 (if (string-match "XEmacs\\|Lucid" emacs-version)
8de85318 596 (cons oracle-builtin-functions 'font-lock-preprocessor-face)
95e4b2ef
RS
597 ;; GNU Emacs 19 doesn't have it either
598 (if (string-match "GNU Emacs 19" emacs-version)
8de85318 599 (cons oracle-builtin-functions 'font-lock-function-name-face)
95e4b2ef 600 ;; Emacs
8de85318
KH
601 (cons oracle-builtin-functions 'font-lock-builtin-face)))
602 (cons oracle-types 'font-lock-type-face))))))
95e4b2ef
RS
603
604(defvar sql-mode-postgres-font-lock-keywords nil
605 "Postgres SQL keywords used by font-lock.
606
607This variable is used by `sql-mode' and `sql-interactive-mode'. The
608regular expressions are created during compilation by calling the
609function `regexp-opt'. Therefore, take a look at the source before
610you define your own sql-mode-postgres-font-lock-keywords.")
611
612(if sql-mode-postgres-font-lock-keywords
613 ()
614 (let ((postgres-reserved-words (eval-when-compile
615 (concat "\\b"
616 (regexp-opt '(
617"language"
618) t) "\\b")))
801d1cb0
AS
619 (postgres-types (eval-when-compile
620 (concat "\\b"
621 (regexp-opt '(
622"bool" "box" "circle" "char" "char2" "char4" "char8" "char16" "date"
623"float4" "float8" "int2" "int4" "int8" "line" "lseg" "money" "path"
95e4b2ef
RS
624"point" "polygon" "serial" "text" "time" "timespan" "timestamp" "varchar"
625) t)"\\b")))
626 (postgres-builtin-functions (eval-when-compile
627 (concat "\\b"
628 (regexp-opt '(
629;; Misc Postgres builtin functions
630"abstime" "age" "area" "box" "center" "date_part" "date_trunc"
631"datetime" "dexp" "diameter" "dpow" "float" "float4" "height"
632"initcap" "integer" "isclosed" "isfinite" "isoldpath" "isopen"
633"length" "lower" "lpad" "ltrim" "pclose" "point" "points" "popen"
634"position" "radius" "reltime" "revertpoly" "rpad" "rtrim" "substr"
635"substring" "text" "timespan" "translate" "trim" "upgradepath"
636"upgradepoly" "upper" "varchar" "width"
637) t) "\\b"))))
638 (setq sql-mode-postgres-font-lock-keywords
639 (append sql-mode-ansi-font-lock-keywords
8de85318
KH
640 (list (cons postgres-reserved-words 'font-lock-keyword-face)
641 ;; XEmacs doesn't have 'font-lock-builtin-face
95e4b2ef 642 (if (string-match "XEmacs\\|Lucid" emacs-version)
8de85318 643 (cons postgres-builtin-functions 'font-lock-preprocessor-face)
95e4b2ef 644 ;; Emacs
8de85318
KH
645 (cons postgres-builtin-functions 'font-lock-builtin-face))
646 (cons postgres-types 'font-lock-type-face))))))
95e4b2ef
RS
647
648
649(defvar sql-mode-font-lock-keywords sql-mode-ansi-font-lock-keywords
650 "SQL keywords used by font-lock.
651
652This variable defaults to `sql-mode-ansi-font-lock-keywords'. This is
653used for the default `font-lock-defaults' value in `sql-mode'. This
654can be changed by some entry functions to provide more hilighting.")
655
656\f
657
658;;; Small functions
659
9ef3882f
GM
660(defun sql-magic-go (arg)
661 "Insert \"o\" and call `comint-send-input'.
662`sql-electric-stuff' must be the symbol `go'."
663 (interactive "P")
664 (self-insert-command (prefix-numeric-value arg))
665 (if (and (equal sql-electric-stuff 'go)
666 (save-excursion
3035b156
MB
667 (comint-bol nil)
668 (looking-at "go\\b")))
9ef3882f
GM
669 (comint-send-input)))
670
671(defun sql-magic-semicolon (arg)
672 "Insert semicolon and call `comint-send-input'.
673`sql-electric-stuff' must be the symbol `semicolon'."
674 (interactive "P")
675 (self-insert-command (prefix-numeric-value arg))
676 (if (equal sql-electric-stuff 'semicolon)
677 (comint-send-input)))
678
95e4b2ef
RS
679(defun sql-accumulate-and-indent ()
680 "Continue SQL statement on the next line."
681 (interactive)
9ef3882f
GM
682 (if (fboundp 'comint-accumulate)
683 (comint-accumulate)
684 (newline))
95e4b2ef
RS
685 (indent-according-to-mode))
686
687;;;###autoload
688(defun sql-help ()
801d1cb0 689 "Show short help for the SQL modes.
95e4b2ef
RS
690
691Use an entry function to open an interactive SQL buffer. This buffer is
dab100d7 692usually named `*SQL*'. The name of the major mode is SQLi.
95e4b2ef
RS
693
694Use the following commands to start a specific SQL interpreter:
695
dab100d7 696 PostGres: \\[sql-postgres]
50842164
RS
697
698Other non-free SQL implementations are also supported:
699
dab100d7
RS
700 MySQL: \\[sql-mysql]
701 Solid: \\[sql-solid]
702 Oracle: \\[sql-oracle]
703 Informix: \\[sql-informix]
50842164
RS
704 Sybase: \\[sql-sybase]
705 Ingres: \\[sql-ingres]
706 Microsoft: \\[sql-ms]
707
708But we urge you to choose a free implementation instead of these.
95e4b2ef
RS
709
710Once you have the SQLi buffer, you can enter SQL statements in the
711buffer. The output generated is appended to the buffer and a new prompt
712is generated. See the In/Out menu in the SQLi buffer for some functions
713that help you navigate through the buffer, the input history, etc.
714
95e4b2ef
RS
715If you have a really complex SQL statement or if you are writing a
716procedure, you can do this in a separate buffer. Put the new buffer in
717`sql-mode' by calling \\[sql-mode]. The name of this buffer can be
718anything. The name of the major mode is SQL.
719
720In this SQL buffer (SQL mode), you can send the region or the entire
721buffer to the interactive SQL buffer (SQLi mode). The results are
722appended to the SQLi buffer without disturbing your SQL buffer."
723 (interactive)
724 (describe-function 'sql-help))
725
726(defun sql-read-passwd (prompt &optional default)
727 "Read a password using PROMPT.
728Optional DEFAULT is password to start with. This function calls
729`read-passwd' if it is available. If not, function
730`ange-ftp-read-passwd' is called. This should always be available,
731even in old versions of Emacs."
732 (if (fboundp 'read-passwd)
733 (read-passwd prompt nil default)
734 (unless (fboundp 'ange-ftp-read-passwd)
735 (autoload 'ange-ftp-read-passwd "ange-ftp"))
736 (ange-ftp-read-passwd prompt default)))
737
738(defun sql-get-login (&rest what)
739 "Get username, password and database from the user.
740
dab100d7
RS
741The variables `sql-user', `sql-password', `sql-server', and
742`sql-database' can be customised. They are used as the default values.
743Usernames, servers and databases are stored in `sql-user-history',
744`sql-server-history' and `database-history'. Passwords are not stored
745in a history.
95e4b2ef
RS
746
747Parameter WHAT is a list of the arguments passed to this function.
748The function asks for the username if WHAT contains symbol `user', for
749the password if it contains symbol `password', for the server if it
750contains symbol `server', and for the database if it contains symbol
751`database'.
752
753In order to ask the user for username, password and database, call the
754function like this: (sql-get-login 'user 'password 'database)."
755 (interactive)
756 (if (memq 'user what)
801d1cb0 757 (setq sql-user
95e4b2ef
RS
758 (read-from-minibuffer "User: " sql-user nil nil
759 sql-user-history)))
760 (if (memq 'password what)
801d1cb0 761 (setq sql-password
95e4b2ef
RS
762 (sql-read-passwd "Password: " sql-password)))
763 (if (memq 'server what)
801d1cb0 764 (setq sql-server
95e4b2ef
RS
765 (read-from-minibuffer "Server: " sql-server nil nil
766 sql-server-history)))
767 (if (memq 'database what)
801d1cb0 768 (setq sql-database
95e4b2ef
RS
769 (read-from-minibuffer "Database: " sql-database nil nil
770 sql-database-history))))
1533eb58 771
46d94d0d
GM
772(defun sql-find-sqli-buffer ()
773 "Return the current default SQLi buffer or nil.
774In order to qualify, the SQLi buffer must be alive,
775be in `sql-interactive-mode' and have a process."
9ef3882f
GM
776 (let ((default-buffer (default-value 'sql-buffer)))
777 (if (and (buffer-live-p default-buffer)
778 (get-buffer-process default-buffer))
779 default-buffer
780 (save-excursion
781 (let ((buflist (buffer-list))
782 (found))
783 (while (not (or (null buflist)
784 found))
785 (let ((candidate (car buflist)))
786 (set-buffer candidate)
787 (if (and (equal major-mode 'sql-interactive-mode)
788 (get-buffer-process candidate))
789 (setq found candidate))
790 (setq buflist (cdr buflist))))
791 found)))))
46d94d0d
GM
792
793(defun sql-set-sqli-buffer-generally ()
794 "Set SQLi buffer for all SQL buffers that have none.
795This function checks all SQL buffers for their SQLi buffer. If their
796SQLi buffer is nonexistent or has no process, it is set to the current
797default SQLi buffer. The current default SQLi buffer is determined
798using `sql-find-sqli-buffer'. If `sql-buffer' is set,
799`sql-set-sqli-hook' is run."
800 (interactive)
801 (save-excursion
802 (let ((buflist (buffer-list))
803 (default-sqli-buffer (sql-find-sqli-buffer)))
804 (setq-default sql-buffer default-sqli-buffer)
805 (while (not (null buflist))
806 (let ((candidate (car buflist)))
807 (set-buffer candidate)
808 (if (and (equal major-mode 'sql-mode)
809 (not (buffer-live-p sql-buffer)))
810 (progn
811 (setq sql-buffer default-sqli-buffer)
812 (run-hooks 'sql-set-sqli-hook))))
813 (setq buflist (cdr buflist))))))
814
c7055d66
RS
815(defun sql-set-sqli-buffer ()
816 "Set the SQLi buffer SQL strings are sent to.
95e4b2ef 817
c7055d66
RS
818Call this function in a SQL buffer in order to set the SQLi buffer SQL
819strings are sent to. Calling this function sets `sql-buffer' and runs
820`sql-set-sqli-hook'.
dab100d7 821
c7055d66 822If you call it from a SQL buffer, this sets the local copy of
801d1cb0 823`sql-buffer'.
dab100d7 824
c7055d66 825If you call it from anywhere else, it sets the global copy of
dab100d7
RS
826`sql-buffer'."
827 (interactive)
46d94d0d
GM
828 (let ((default-buffer (sql-find-sqli-buffer)))
829 (if (null default-buffer)
830 (error "There is no suitable SQLi buffer"))
831 (let ((new-buffer
832 (get-buffer
833 (read-buffer "New SQLi buffer: " default-buffer t))))
834 (if (null (get-buffer-process new-buffer))
835 (error "Buffer %s has no process" (buffer-name new-buffer)))
836 (if (null (save-excursion
837 (set-buffer new-buffer)
838 (equal major-mode 'sql-interactive-mode)))
839 (error "Buffer %s is no SQLi buffer" (buffer-name new-buffer)))
840 (if new-buffer
841 (progn
842 (setq sql-buffer new-buffer)
843 (run-hooks 'sql-set-sqli-hook))))))
dab100d7
RS
844
845(defun sql-show-sqli-buffer ()
846 "Show the name of current SQLi buffer.
847
848This is the buffer SQL strings are sent to. It is stored in the
849variable `sql-buffer'. See `sql-help' on how to create such a buffer."
850 (interactive)
851 (if (null (buffer-live-p sql-buffer))
c7055d66 852 (message "%s has no SQLi buffer set." (buffer-name (current-buffer)))
dab100d7
RS
853 (if (null (get-buffer-process sql-buffer))
854 (message "Buffer %s has no process." (buffer-name sql-buffer))
855 (message "Current SQLi buffer is %s." (buffer-name sql-buffer)))))
856
c7055d66
RS
857(defun sql-make-alternate-buffer-name ()
858 "Return a string that can be used to rename a SQLi buffer.
859
860This is used to set `sql-alternate-buffer-name' within
861`sql-interactive-mode'."
862 (concat (if (string= "" sql-user)
9ef3882f 863 (if (string= "" (user-login-name))
c7055d66 864 ()
9ef3882f 865 (concat (user-login-name) "/"))
c7055d66
RS
866 (concat sql-user "/"))
867 (if (string= "" sql-database)
868 (if (string= "" sql-server)
9ef3882f 869 (system-name)
c7055d66
RS
870 sql-server)
871 sql-database)))
872
873(defun sql-rename-buffer ()
874 "Renames a SQLi buffer."
875 (interactive)
876 (rename-buffer (format "*SQL: %s*" sql-alternate-buffer-name) t))
877
95e4b2ef
RS
878(defun sql-copy-column ()
879 "Copy current column to the end of buffer.
880Inserts SELECT or commas if appropriate."
881 (interactive)
882 (let ((column))
883 (save-excursion
884 (setq column (buffer-substring
885 (progn (forward-char 1) (backward-sexp 1) (point))
886 (progn (forward-sexp 1) (point))))
887 (goto-char (point-max))
3035b156
MB
888 (let ((bol (comint-line-beginning-position)))
889 (cond
890 ;; if empty command line, insert SELECT
891 ((= bol (point))
892 (insert "SELECT "))
893 ;; else if appending to INTO .* (, SELECT or ORDER BY, insert a comma
894 ((save-excursion
895 (re-search-backward "\\b\\(\\(into\\s-+\\S-+\\s-+(\\)\\|select\\|order by\\) .+"
896 bol t))
897 (insert ", "))
898 ;; else insert a space
899 (t
900 (if (eq (preceding-char) ? )
901 nil
902 (insert " ")))))
95e4b2ef
RS
903 ;; in any case, insert the column
904 (insert column)
905 (message "%s" column))))
906
77d352a6
GM
907;; On NT, SQL*Plus for Oracle turns on full buffering for stdout if it
908;; is not attached to a character device; therefore placeholder
909;; replacement by SQL*Plus is fully buffered. The workaround lets
910;; Emacs query for the placeholders.
911
912(defvar sql-placeholder-history nil
913 "History of placeholder values used.")
914
915(defun sql-query-placeholders-and-send (proc string)
916 "Send to PROC input STRING, maybe replacing placeholders.
917Placeholders are words starting with and ampersand like &this.
918This function is used for `comint-input-sender' if using `sql-oracle' on NT."
919 (while (string-match "&\\(\\sw+\\)" string)
920 (setq string (replace-match
921 (read-from-minibuffer
922 (format "Enter value for %s: " (match-string 1 string))
923 nil nil nil sql-placeholder-history)
924 t t string)))
925 (comint-send-string proc string)
926 (comint-send-string proc "\n"))
927
95e4b2ef
RS
928\f
929
930;;; Sending the region to the SQLi buffer.
931
932(defun sql-send-region (start end)
933 "Send a region to the SQL process."
934 (interactive "r")
935 (if (buffer-live-p sql-buffer)
936 (save-excursion
937 (comint-send-region sql-buffer start end)
938 (if (string-match "\n$" (buffer-substring start end))
939 ()
940 (comint-send-string sql-buffer "\n"))
a081a529 941 (message "Sent string to buffer %s." (buffer-name sql-buffer))
801d1cb0 942 (if sql-pop-to-buffer-after-send-region
95e4b2ef
RS
943 (pop-to-buffer sql-buffer)
944 (display-buffer sql-buffer)))
945 (message "No SQL process started.")))
946
dab100d7
RS
947(defun sql-send-paragraph ()
948 "Send the current paragraph to the SQL process."
949 (interactive)
950 (let ((start (save-excursion
951 (backward-paragraph)
952 (point)))
953 (end (save-excursion
954 (forward-paragraph)
955 (point))))
956 (sql-send-region start end)))
957
95e4b2ef
RS
958(defun sql-send-buffer ()
959 "Send the buffer contents to the SQL process."
960 (interactive)
961 (sql-send-region (point-min) (point-max)))
962
963(defun sql-toggle-pop-to-buffer-after-send-region (&optional value)
964 "Toggle `sql-pop-to-buffer-after-send-region'.
965
966If given the optional parameter VALUE, sets
967sql-toggle-pop-to-buffer-after-send-region to VALUE."
968 (interactive "P")
969 (if value
970 (setq sql-pop-to-buffer-after-send-region value)
801d1cb0 971 (setq sql-pop-to-buffer-after-send-region
95e4b2ef
RS
972 (null sql-pop-to-buffer-after-send-region ))))
973
974\f
975
976;;; SQL mode -- uses SQL interactive mode
977
978;;;###autoload
979(defun sql-mode ()
980 "Major mode to edit SQL.
981
dab100d7 982You can send SQL statements to the SQLi buffer using
95e4b2ef 983\\[sql-send-region]. Such a buffer must exist before you can do this.
dab100d7 984See `sql-help' on how to create SQLi buffers.
95e4b2ef 985
801d1cb0 986\\{sql-mode-map}
95e4b2ef
RS
987Customization: Entry to this mode runs the `sql-mode-hook'.
988
dab100d7
RS
989When you put a buffer in SQL mode, the buffer stores the last SQLi
990buffer created as its destination in the variable `sql-buffer'. This
991will be the buffer \\[sql-send-region] sends the region to. If this
992SQLi buffer is killed, \\[sql-send-region] is no longer able to
c7055d66
RS
993determine where the strings should be sent to. You can set the
994value of `sql-buffer' using \\[sql-set-sqli-buffer].
95e4b2ef 995
dab100d7
RS
996For information on how to create multiple SQLi buffers, see
997`sql-interactive-mode'."
95e4b2ef
RS
998 (interactive)
999 (kill-all-local-variables)
1000 (setq major-mode 'sql-mode)
1001 (setq mode-name "SQL")
1002 (use-local-map sql-mode-map)
1003 (set-syntax-table sql-mode-syntax-table)
1004 (make-local-variable 'font-lock-defaults)
801d1cb0
AS
1005 ;; Note that making KEYWORDS-ONLY nil will cause havoc if you try
1006 ;; SELECT 'x' FROM DUAL with SQL*Plus, because the title of the column
1007 ;; will have just one quote. Therefore syntactic hilighting is
1008 ;; disabled for interactive buffers. `_' and `.' are considered part
1009 ;; of words.
1010 (setq font-lock-defaults '(sql-mode-font-lock-keywords
1011 nil t ((?_ . "w") (?. . "w"))))
a081a529
RS
1012 (make-local-variable 'comment-start)
1013 (setq comment-start "--")
801d1cb0 1014 ;; Make each buffer in sql-mode remember the "current" SQLi buffer.
dab100d7 1015 (make-local-variable 'sql-buffer)
801d1cb0
AS
1016 ;; Add imenu support for sql-mode. Note that imenu-generic-expression
1017 ;; is buffer-local, so we don't need a local-variable for it. SQL is
1018 ;; case-insensitive, that's why we have to set imenu-case-fold-search.
1019 ;; imenu-syntax-alist makes sure that `_' is considered part of object
1020 ;; names.
1021 (setq imenu-generic-expression sql-imenu-generic-expression
1022 imenu-case-fold-search t
1023 imenu-syntax-alist '(("_" . "w")))
c7055d66
RS
1024 ;; Make `sql-send-paragraph' work on paragraphs that contain indented
1025 ;; lines.
1026 (make-local-variable 'paragraph-separate)
1027 (make-local-variable 'paragraph-start)
1028 (setq paragraph-separate "[\f]*$"
1029 paragraph-start "[\n\f]")
801d1cb0 1030 ;; Abbrevs
95e4b2ef
RS
1031 (setq local-abbrev-table sql-mode-abbrev-table)
1032 (setq abbrev-all-caps 1)
801d1cb0 1033 ;; Run hook
95e4b2ef
RS
1034 (run-hooks 'sql-mode-hook))
1035
1036\f
1037
1038;;; SQL interactive mode
1039
1040(put 'sql-interactive-mode 'mode-class 'special)
1041
1042(defun sql-interactive-mode ()
1043 "Major mode to use a SQL interpreter interactively.
1044
1045Do not call this function by yourself. The environment must be
1046initialized by an entry function specific for the SQL interpreter. See
1047`sql-help' for a list of available entry functions.
1048
1049\\[comint-send-input] after the end of the process' output sends the
1050text from the end of process to the end of the current line.
1051\\[comint-send-input] before end of process output copies the current
1052line minus the prompt to the end of the buffer and sends it.
1053\\[comint-copy-old-input] just copies the current line.
1054Use \\[sql-accumulate-and-indent] to enter multi-line statements.
1055
1056If you want to make multiple SQL buffers, rename the `*SQL*' buffer
1057using \\[rename-buffer] or \\[rename-uniquely] and start a new process.
dab100d7
RS
1058See `sql-help' for a list of available entry functions. The last buffer
1059created by such an entry function is the current SQLi buffer. SQL
1060buffers will send strings to the SQLi buffer current at the time of
1061their creation. See `sql-mode' for details.
1062
1063Sample session using two connections:
1064
10651. Create first SQLi buffer by calling an entry function.
10662. Rename buffer \"*SQL*\" to \"*Connection 1*\".
10673. Create a SQL buffer \"test1.sql\".
10684. Create second SQLi buffer by calling an entry function.
10695. Rename buffer \"*SQL*\" to \"*Connection 2*\".
10706. Create a SQL buffer \"test2.sql\".
1071
1072Now \\[sql-send-region] in buffer \"test1.sql\" will send the region to
1073buffer \"*Connection 1*\", \\[sql-send-region] in buffer \"test2.sql\"
1074will send the region to buffer \"*Connection 2*\".
95e4b2ef
RS
1075
1076If you accidentally suspend your process, use \\[comint-continue-subjob]
dab100d7
RS
1077to continue it. On some operating systems, this will not work because
1078the signals are not supported.
95e4b2ef
RS
1079
1080\\{sql-interactive-mode-map}
1081Customization: Entry to this mode runs the hooks on `comint-mode-hook'
1082and `sql-interactive-mode-hook' (in that order). Before each input, the
1083hooks on `comint-input-filter-functions' are run. After each SQL
1084interpreter output, the hooks on `comint-output-filter-functions' are
1085run.
1086
c7055d66 1087Variable `sql-input-ring-file-name' controls the initialisation of the
77d352a6 1088input ring history.
95e4b2ef
RS
1089
1090Variables `comint-output-filter-functions', a hook, and
1091`comint-scroll-to-bottom-on-input' and
1092`comint-scroll-to-bottom-on-output' control whether input and output
1093cause the window to scroll to the end of the buffer.
1094
1095If you want to make SQL buffers limited in length, add the function
1096`comint-truncate-buffer' to `comint-output-filter-functions'.
1097
dab100d7 1098Here is an example for your .emacs file. It keeps the SQLi buffer a
c7055d66 1099certain length.
95e4b2ef
RS
1100
1101\(add-hook 'sql-interactive-mode-hook
1102 \(function (lambda ()
95e4b2ef
RS
1103 \(setq comint-output-filter-functions 'comint-truncate-buffer))))
1104
1105Here is another example. It will always put point back to the statement
1106you entered, right above the output it created.
1107
801d1cb0 1108\(setq comint-output-filter-functions
95e4b2ef
RS
1109 \(function (lambda (STR) (comint-show-output))))"
1110 (comint-mode)
1111 (setq comint-prompt-regexp sql-prompt-regexp)
a081a529 1112 (setq left-margin sql-prompt-length)
95e4b2ef
RS
1113 (setq major-mode 'sql-interactive-mode)
1114 (setq mode-name "SQLi")
1115 (use-local-map sql-interactive-mode-map)
1116 (set-syntax-table sql-mode-syntax-table)
1117 (make-local-variable 'font-lock-defaults)
a081a529 1118 ;; Note that making KEYWORDS-ONLY nil will cause havoc if you try
801d1cb0
AS
1119 ;; SELECT 'x' FROM DUAL with SQL*Plus, because the title of the column
1120 ;; will have just one quote. Therefore syntactic hilighting is
1121 ;; disabled for interactive buffers. `_' and `.' are considered part
1122 ;; of words.
1123 (setq font-lock-defaults '(sql-mode-font-lock-keywords
1124 t t ((?_ . "w") (?. . "w"))))
c7055d66 1125 ;; Enable commenting and uncommenting of the region.
a081a529
RS
1126 (make-local-variable 'comment-start)
1127 (setq comment-start "--")
c7055d66
RS
1128 ;; Abbreviation table init and case-insensitive. It is not activatet
1129 ;; by default.
95e4b2ef
RS
1130 (setq local-abbrev-table sql-mode-abbrev-table)
1131 (setq abbrev-all-caps 1)
c7055d66 1132 ;; Exiting the process will call sql-stop.
95e4b2ef 1133 (set-process-sentinel (get-buffer-process sql-buffer) 'sql-stop)
77d352a6
GM
1134 ;; People wanting a different history file for each
1135 ;; buffer/process/client/whatever can change separator and file-name
1136 ;; on the sql-interactive-mode-hook.
1137 (setq comint-input-ring-separator sql-input-ring-separator
1138 comint-input-ring-file-name sql-input-ring-file-name)
c7055d66
RS
1139 ;; Create a usefull name for renaming this buffer later.
1140 (make-local-variable 'sql-alternate-buffer-name)
1141 (setq sql-alternate-buffer-name (sql-make-alternate-buffer-name))
1142 ;; User stuff.
95e4b2ef 1143 (run-hooks 'sql-interactive-mode-hook)
c7055d66 1144 ;; Calling the hook before calling comint-read-input-ring allows users
95e4b2ef 1145 ;; to set comint-input-ring-file-name in sql-interactive-mode-hook.
77d352a6 1146 (comint-read-input-ring t))
95e4b2ef
RS
1147
1148(defun sql-stop (process event)
1149 "Called when the SQL process is stopped.
1150
c7055d66
RS
1151Writes the input history to a history file using
1152`comint-write-input-ring' and inserts a short message in the SQL buffer.
1153`comint-comint-input-ring-file-name' is temporarily bound to
c04bb32e 1154`sql-input-ring-file-name'.
95e4b2ef
RS
1155
1156This function is a sentinel watching the SQL interpreter process.
1157Sentinels will always get the two parameters PROCESS and EVENT."
77d352a6
GM
1158 (comint-write-input-ring)
1159 (if (and (eq (current-buffer) sql-buffer)
1160 (not buffer-read-only))
1161 (insert (format "\nProcess %s %s\n" process event))
1162 (message "Process %s %s" process event)))
95e4b2ef
RS
1163
1164\f
1165
1166;;; Entry functions for different SQL interpreters.
1167
77d352a6 1168;;;###autoload
95e4b2ef
RS
1169(defun sql-oracle ()
1170 "Run sqlplus by Oracle as an inferior process.
1171
dab100d7 1172If buffer `*SQL*' exists but no process is running, make a new process.
95e4b2ef
RS
1173If buffer exists and a process is running, just switch to buffer
1174`*SQL*'.
1175
dab100d7
RS
1176Interpreter used comes from variable `sql-oracle-program'. Login uses
1177the variables `sql-user', `sql-password', and `sql-database' as
9ef3882f
GM
1178defaults, if set. Additional command line parameters can be stored in
1179the list `sql-oracle-options'.
95e4b2ef
RS
1180
1181The buffer is put in sql-interactive-mode, giving commands for sending
1182input. See `sql-interactive-mode'.
1183
1184To specify a coding system for converting non-ASCII characters
1185in the input and output to the process, use \\[universal-coding-system-argument]
1186before \\[sql-oracle]. You can also specify this with \\[set-buffer-process-coding-system]
1187in the SQL buffer, after you start the process.
1188The default comes from `process-coding-system-alist' and
1189`default-process-coding-system'.
1190
1191\(Type \\[describe-mode] in the SQL buffer for a list of commands.)"
1192 (interactive)
1193 (if (comint-check-proc "*SQL*")
1194 (pop-to-buffer "*SQL*")
1195 (sql-get-login 'user 'password 'database)
1196 (message "Login...")
1197 ;; Produce user/password@database construct. Password without user
1198 ;; is meaningless; database without user/password is meaningless,
1199 ;; because "@param" will ask sqlplus to interpret the script
1200 ;; "param".
1201 (let ((parameter nil))
1202 (if (not (string= "" sql-user))
1203 (if (not (string= "" sql-password))
1204 (setq parameter (concat sql-user "/" sql-password))
1205 (setq parameter sql-user)))
1206 (if (and parameter (not (string= "" sql-database)))
1207 (setq parameter (concat parameter "@" sql-database)))
1208 (if parameter
9ef3882f
GM
1209 (setq parameter (nconc (list parameter) sql-oracle-options))
1210 (setq parameter sql-oracle-options))
1211 (if parameter
1212 (set-buffer (apply 'make-comint "SQL" sql-oracle-program nil
1213 parameter))
95e4b2ef
RS
1214 (set-buffer (make-comint "SQL" sql-oracle-program nil))))
1215 (setq sql-prompt-regexp "^SQL> ")
a081a529 1216 (setq sql-prompt-length 5)
95e4b2ef
RS
1217 (setq sql-buffer (current-buffer))
1218 ;; set sql-mode-font-lock-keywords to something different before
1219 ;; calling sql-interactive-mode.
1220 (setq sql-mode-font-lock-keywords sql-mode-oracle-font-lock-keywords)
1221 (sql-interactive-mode)
77d352a6
GM
1222 ;; If running on NT, make sure we do placeholder replacement ourselves.
1223 (if (eq window-system 'w32)
1224 (setq comint-input-sender 'sql-query-placeholders-and-send))
95e4b2ef
RS
1225 (message "Login...done")
1226 (pop-to-buffer sql-buffer)))
1227
1228\f
1229
77d352a6 1230;;;###autoload
95e4b2ef
RS
1231(defun sql-sybase ()
1232 "Run isql by SyBase as an inferior process.
1233
dab100d7 1234If buffer `*SQL*' exists but no process is running, make a new process.
95e4b2ef
RS
1235If buffer exists and a process is running, just switch to buffer
1236`*SQL*'.
1237
1238Interpreter used comes from variable `sql-sybase-program'. Login uses
1533eb58 1239the variables `sql-user', `sql-password', and `sql-server' as
dab100d7 1240defaults, if set.
95e4b2ef
RS
1241
1242The buffer is put in sql-interactive-mode, giving commands for sending
1243input. See `sql-interactive-mode'.
1244
1245To specify a coding system for converting non-ASCII characters
1246in the input and output to the process, use \\[universal-coding-system-argument]
1247before \\[sql-sybase]. You can also specify this with \\[set-buffer-process-coding-system]
1248in the SQL buffer, after you start the process.
1249The default comes from `process-coding-system-alist' and
1250`default-process-coding-system'.
1251
1252\(Type \\[describe-mode] in the SQL buffer for a list of commands.)"
1253 (interactive)
1254 (if (comint-check-proc "*SQL*")
1255 (pop-to-buffer "*SQL*")
1533eb58 1256 (sql-get-login 'user 'password 'server)
95e4b2ef
RS
1257 (message "Login...")
1258 ;; Put all parameters to the program (if defined) in a list and call
1259 ;; make-comint.
1260 (let ((params '("-w" "2048" "-n")))
1533eb58
AS
1261 ;; There is no way to specify the database via command line
1262 ;; parameters. The -S option specifies the server.
1263 (if (not (string= "" sql-server))
1264 (setq params (append (list "-S" sql-server) params)))
95e4b2ef
RS
1265 (if (not (string= "" sql-password))
1266 (setq params (append (list "-P" sql-password) params)))
1267 (if (not (string= "" sql-user))
1268 (setq params (append (list "-U" sql-user) params)))
801d1cb0 1269 (set-buffer (apply 'make-comint "SQL" sql-sybase-program
95e4b2ef
RS
1270 nil params)))
1271 (setq sql-prompt-regexp "^SQL> ")
a081a529 1272 (setq sql-prompt-length 5)
95e4b2ef
RS
1273 (setq sql-buffer (current-buffer))
1274 (sql-interactive-mode)
1275 (message "Login...done")
1276 (pop-to-buffer sql-buffer)))
1277
1278\f
1279
77d352a6 1280;;;###autoload
95e4b2ef
RS
1281(defun sql-informix ()
1282 "Run dbaccess by Informix as an inferior process.
1283
dab100d7 1284If buffer `*SQL*' exists but no process is running, make a new process.
95e4b2ef
RS
1285If buffer exists and a process is running, just switch to buffer
1286`*SQL*'.
1287
1288Interpreter used comes from variable `sql-informix-program'. Login uses
1289the variable `sql-database' as default, if set.
1290
1291The buffer is put in sql-interactive-mode, giving commands for sending
1292input. See `sql-interactive-mode'.
1293
1294To specify a coding system for converting non-ASCII characters
1295in the input and output to the process, use \\[universal-coding-system-argument]
1296before \\[sql-informix]. You can also specify this with \\[set-buffer-process-coding-system]
1297in the SQL buffer, after you start the process.
1298The default comes from `process-coding-system-alist' and
1299`default-process-coding-system'.
1300
1301\(Type \\[describe-mode] in the SQL buffer for a list of commands.)"
1302 (interactive)
1303 (if (comint-check-proc "*SQL*")
1304 (pop-to-buffer "*SQL*")
1305 (sql-get-login 'database)
1306 (message "Login...")
1307 ;; username and password are ignored.
1308 (if (string= "" sql-database)
1309 (set-buffer (make-comint "SQL" sql-informix-program nil))
9ef3882f 1310 (set-buffer (make-comint "SQL" sql-informix-program nil sql-database "-")))
95e4b2ef 1311 (setq sql-prompt-regexp "^SQL> ")
a081a529
RS
1312 (setq sql-prompt-length 5)
1313 (setq sql-buffer (current-buffer))
1314 (sql-interactive-mode)
1315 (message "Login...done")
1316 (pop-to-buffer sql-buffer)))
1317
1318\f
1319
77d352a6 1320;;;###autoload
a081a529
RS
1321(defun sql-mysql ()
1322 "Run mysql by TcX as an inferior process.
dab100d7
RS
1323
1324Note that the widespread idea that mysql is free software is inaccurate;
1325its license is too restrictive. We urge you to use PostGres instead.
a081a529 1326
50842164 1327If buffer `*SQL*' exists but no process is running, make a new process.
a081a529
RS
1328If buffer exists and a process is running, just switch to buffer
1329`*SQL*'.
1330
1331Interpreter used comes from variable `sql-mysql-program'. Login uses
dab100d7
RS
1332the variables `sql-user', `sql-password', `sql-database', and
1333`sql-server' as defaults, if set.
a081a529
RS
1334
1335The buffer is put in sql-interactive-mode, giving commands for sending
1336input. See `sql-interactive-mode'.
1337
1338To specify a coding system for converting non-ASCII characters
1339in the input and output to the process, use \\[universal-coding-system-argument]
dab100d7 1340before \\[sql-mysql]. You can also specify this with \\[set-buffer-process-coding-system]
a081a529
RS
1341in the SQL buffer, after you start the process.
1342The default comes from `process-coding-system-alist' and
1343`default-process-coding-system'.
1344
1345\(Type \\[describe-mode] in the SQL buffer for a list of commands.)"
1346 (interactive)
1347 (if (comint-check-proc "*SQL*")
1348 (pop-to-buffer "*SQL*")
dab100d7 1349 (sql-get-login 'user 'password 'database 'server)
a081a529
RS
1350 (message "Login...")
1351 ;; Put all parameters to the program (if defined) in a list and call
1352 ;; make-comint.
1353 (let ((params))
1354 (if (not (string= "" sql-database))
dab100d7
RS
1355 (setq params (append (list sql-database) params)))
1356 (if (not (string= "" sql-server))
1357 (setq params (append (list (concat "--host=" sql-server)) params)))
a081a529
RS
1358 (if (not (string= "" sql-password))
1359 (setq params (append (list (concat "--password=" sql-password)) params)))
1360 (if (not (string= "" sql-user))
1361 (setq params (append (list (concat "--user=" sql-user)) params)))
801d1cb0 1362 (set-buffer (apply 'make-comint "SQL" sql-mysql-program
a081a529
RS
1363 nil params)))
1364 (setq sql-prompt-regexp "^mysql>")
1365 (setq sql-prompt-length 6)
95e4b2ef
RS
1366 (setq sql-buffer (current-buffer))
1367 (sql-interactive-mode)
1368 (message "Login...done")
1369 (pop-to-buffer sql-buffer)))
1370
1371\f
1372
77d352a6 1373;;;###autoload
dab100d7
RS
1374(defun sql-solid ()
1375 "Run solsql by Solid as an inferior process.
1376
1377If buffer `*SQL*' exists but no process is running, make a new process.
1378If buffer exists and a process is running, just switch to buffer
1379`*SQL*'.
1380
1381Interpreter used comes from variable `sql-solid-program'. Login uses
1382the variables `sql-user', `sql-password', and `sql-server' as
1383defaults, if set.
1384
1385The buffer is put in sql-interactive-mode, giving commands for sending
1386input. See `sql-interactive-mode'.
1387
1388To specify a coding system for converting non-ASCII characters
1389in the input and output to the process, use \\[universal-coding-system-argument]
1390before \\[sql-solid]. You can also specify this with \\[set-buffer-process-coding-system]
1391in the SQL buffer, after you start the process.
1392The default comes from `process-coding-system-alist' and
1393`default-process-coding-system'.
1394
1395\(Type \\[describe-mode] in the SQL buffer for a list of commands.)"
1396 (interactive)
1397 (if (comint-check-proc "*SQL*")
1398 (pop-to-buffer "*SQL*")
1399 (sql-get-login 'user 'password 'server)
1400 (message "Login...")
1401 ;; Put all parameters to the program (if defined) in a list and call
1402 ;; make-comint.
1403 (let ((params))
1404 ;; It only makes sense if both username and password are there.
1405 (if (not (or (string= "" sql-user)
1406 (string= "" sql-password)))
1407 (setq params (append (list sql-user sql-password) params)))
1408 (if (not (string= "" sql-server))
1409 (setq params (append (list sql-server) params)))
801d1cb0 1410 (set-buffer (apply 'make-comint "SQL" sql-solid-program
dab100d7
RS
1411 nil params)))
1412 (setq sql-prompt-regexp "^")
1413 (setq sql-prompt-length 0)
1414 (setq sql-buffer (current-buffer))
1415 (sql-interactive-mode)
1416 (message "Login...done")
1417 (pop-to-buffer sql-buffer)))
1418
1419\f
1420
77d352a6 1421;;;###autoload
95e4b2ef
RS
1422(defun sql-ingres ()
1423 "Run sql by Ingres as an inferior process.
1424
dab100d7 1425If buffer `*SQL*' exists but no process is running, make a new process.
95e4b2ef
RS
1426If buffer exists and a process is running, just switch to buffer
1427`*SQL*'.
1428
1429Interpreter used comes from variable `sql-ingres-program'. Login uses
1430the variable `sql-database' as default, if set.
1431
1432The buffer is put in sql-interactive-mode, giving commands for sending
1433input. See `sql-interactive-mode'.
1434
1435To specify a coding system for converting non-ASCII characters
1436in the input and output to the process, use \\[universal-coding-system-argument]
1437before \\[sql-ingres]. You can also specify this with \\[set-buffer-process-coding-system]
1438in the SQL buffer, after you start the process.
1439The default comes from `process-coding-system-alist' and
1440`default-process-coding-system'.
1441
1442\(Type \\[describe-mode] in the SQL buffer for a list of commands.)"
1443 (interactive)
1444 (if (comint-check-proc "*SQL*")
1445 (pop-to-buffer "*SQL*")
1446 (sql-get-login 'database)
1447 (message "Login...")
1448 ;; username and password are ignored.
1449 (if (string= "" sql-database)
1450 (set-buffer (make-comint "SQL" sql-ingres-program nil))
1451 (set-buffer (make-comint "SQL" sql-ingres-program nil sql-database)))
1452 (setq sql-prompt-regexp "^\* ")
a081a529 1453 (setq sql-prompt-length 2)
95e4b2ef
RS
1454 (setq sql-buffer (current-buffer))
1455 (sql-interactive-mode)
1456 (message "Login...done")
1457 (pop-to-buffer sql-buffer)))
1458
1459\f
1460
77d352a6 1461;;;###autoload
95e4b2ef
RS
1462(defun sql-ms ()
1463 "Run isql by Microsoft as an inferior process.
1464
dab100d7 1465If buffer `*SQL*' exists but no process is running, make a new process.
95e4b2ef
RS
1466If buffer exists and a process is running, just switch to buffer
1467`*SQL*'.
1468
1469Interpreter used comes from variable `sql-ms-program'. Login uses the
dab100d7 1470variables `sql-user', `sql-password', `sql-database', and `sql-server'
95e4b2ef
RS
1471as defaults, if set.
1472
1473The buffer is put in sql-interactive-mode, giving commands for sending
1474input. See `sql-interactive-mode'.
1475
1476To specify a coding system for converting non-ASCII characters
1477in the input and output to the process, use \\[universal-coding-system-argument]
dab100d7 1478before \\[sql-ms]. You can also specify this with \\[set-buffer-process-coding-system]
95e4b2ef
RS
1479in the SQL buffer, after you start the process.
1480The default comes from `process-coding-system-alist' and
1481`default-process-coding-system'.
1482
1483\(Type \\[describe-mode] in the SQL buffer for a list of commands.)"
1484 (interactive)
1485 (if (comint-check-proc "*SQL*")
1486 (pop-to-buffer "*SQL*")
1487 (sql-get-login 'user 'password 'database 'server)
1488 (message "Login...")
1489 ;; Put all parameters to the program (if defined) in a list and call
1490 ;; make-comint.
1491 (let ((params '("-w 300")))
1492 (if (not (string= "" sql-server))
1493 (setq params (append (list "-S" sql-server) params)))
1494 (if (not (string= "" sql-database))
1495 (setq params (append (list "-d" sql-database) params)))
1496 (if (not (string= "" sql-user))
1497 (setq params (append (list "-U" sql-user) params)))
1498 (if (not (string= "" sql-password))
1499 (setq params (append (list "-P" sql-password) params))
1500 ;; If -P is passed to ISQL as the last argument without a password,
1501 ;; it's considered null.
1502 (setq params (append params (list "-P"))))
1503 (set-buffer (apply 'make-comint "SQL" sql-ms-program
1504 nil params)))
1505 (setq sql-prompt-regexp "^[0-9]*>")
a081a529 1506 (setq sql-prompt-length 5)
95e4b2ef
RS
1507 (setq sql-buffer (current-buffer))
1508 (sql-interactive-mode)
1509 (message "Login...done")
1510 (pop-to-buffer sql-buffer)))
1511
1512
1513\f
1514
1515;;;###autoload
1516(defun sql-postgres ()
1517 "Run psql by Postgres as an inferior process.
1518
dab100d7 1519If buffer `*SQL*' exists but no process is running, make a new process.
95e4b2ef
RS
1520If buffer exists and a process is running, just switch to buffer
1521`*SQL*'.
1522
1523Interpreter used comes from variable `sql-postgres-program'. Login uses
c04bb32e 1524the variables `sql-database' and `sql-server' as default, if set.
95e4b2ef
RS
1525
1526The buffer is put in sql-interactive-mode, giving commands for sending
1527input. See `sql-interactive-mode'.
1528
1529To specify a coding system for converting non-ASCII characters
1530in the input and output to the process, use \\[universal-coding-system-argument]
1531before \\[sql-postgres]. You can also specify this with \\[set-buffer-process-coding-system]
1532in the SQL buffer, after you start the process.
1533The default comes from `process-coding-system-alist' and
801d1cb0 1534`default-process-coding-system'. If your output lines end with ^M,
95e4b2ef
RS
1535your might try undecided-dos as a coding system. If this doesn't help,
1536Try to set `comint-output-filter-functions' like this:
1537
1538\(setq comint-output-filter-functions (append comint-output-filter-functions
1539 '(comint-strip-ctrl-m)))
1540
1541\(Type \\[describe-mode] in the SQL buffer for a list of commands.)"
1542 (interactive)
1543 (if (comint-check-proc "*SQL*")
1544 (pop-to-buffer "*SQL*")
c04bb32e 1545 (sql-get-login 'database 'server)
95e4b2ef
RS
1546 (message "Login...")
1547 ;; username and password are ignored.
c04bb32e
RS
1548 (let ((params))
1549 (if (not (string= "" sql-database))
1550 (setq params (append (list sql-database) params)))
1551 (if (not (string= "" sql-server))
1552 (setq params (append (list "-h" sql-server) params)))
801d1cb0 1553 (set-buffer (apply 'make-comint "SQL" sql-postgres-program
c04bb32e 1554 nil params)))
95e4b2ef 1555 (setq sql-prompt-regexp "^.*> *")
a081a529 1556 (setq sql-prompt-length 5)
95e4b2ef 1557 ;; This is a lousy hack to prevent psql from truncating it's output
801d1cb0 1558 ;; and giving stupid warnings. If s.o. knows a way to prevent psql
95e4b2ef
RS
1559 ;; from acting this way, then I would be very thankful to
1560 ;; incorporate this (Gregor Zych <zych@pool.informatik.rwth-aachen.de>)
1561 (comint-send-string "*SQL*" "\\o \| cat\n")
1562 (setq sql-mode-font-lock-keywords sql-mode-postgres-font-lock-keywords)
1563 (setq sql-buffer (current-buffer))
1564 (sql-interactive-mode)
1565 (message "Login...done")
1566 (pop-to-buffer sql-buffer)))
1567
1568(provide 'sql)
1569
1570;;; sql.el ends here