Merge from emacs-24; up to 2012-12-22T19:09:52Z!rgm@gnu.org
[bpt/emacs.git] / lisp / progmodes / sql.el
CommitLineData
93852cb0 1;;; sql.el --- specialized comint.el for SQL interpreters -*- lexical-binding: t -*-
95e4b2ef 2
ab422c4d 3;; Copyright (C) 1998-2013 Free Software Foundation, Inc.
95e4b2ef 4
1533eb58 5;; Author: Alex Schroeder <alex@gnu.org>
dc45d1a6 6;; Maintainer: Michael Mauger <mmaug@yahoo.com>
04e082b0 7;; Version: 3.1
dab100d7 8;; Keywords: comm languages processes
e084bc3d 9;; URL: http://savannah.gnu.org/projects/emacs/
95e4b2ef
RS
10
11;; This file is part of GNU Emacs.
12
b1fc2b50 13;; GNU Emacs is free software: you can redistribute it and/or modify
95e4b2ef 14;; it under the terms of the GNU General Public License as published by
b1fc2b50
GM
15;; the Free Software Foundation, either version 3 of the License, or
16;; (at your option) any later version.
95e4b2ef
RS
17
18;; GNU Emacs is distributed in the hope that it will be useful,
19;; but WITHOUT ANY WARRANTY; without even the implied warranty of
20;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21;; GNU General Public License for more details.
22
23;; You should have received a copy of the GNU General Public License
b1fc2b50 24;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
95e4b2ef
RS
25
26;;; Commentary:
27
c04bb32e 28;; Please send bug reports and bug fixes to the mailing list at
01295a22
RS
29;; help-gnu-emacs@gnu.org. If you want to subscribe to the mailing
30;; list, see the web page at
31;; http://lists.gnu.org/mailman/listinfo/help-gnu-emacs for
32;; instructions. I monitor this list actively. If you send an e-mail
33;; to Alex Schroeder it usually makes it to me when Alex has a chance
34;; to forward them along (Thanks, Alex).
35
36;; This file provides a sql-mode and a sql-interactive-mode. The
37;; original goals were two simple modes providing syntactic
38;; highlighting. The interactive mode had to provide a command-line
39;; history; the other mode had to provide "send region/buffer to SQL
40;; interpreter" functions. "simple" in this context means easy to
41;; use, easy to maintain and little or no bells and whistles. This
42;; has changed somewhat as experience with the mode has accumulated.
43
44;; Support for different flavors of SQL and command interpreters was
45;; available in early versions of sql.el. This support has been
46;; extended and formalized in later versions. Part of the impetus for
47;; the improved support of SQL flavors was borne out of the current
fbcc67e2 48;; maintainers consulting experience. In the past twenty years, I
01295a22
RS
49;; have used Oracle, Sybase, Informix, MySQL, Postgres, and SQLServer.
50;; On some assignments, I have used two or more of these concurrently.
95e4b2ef
RS
51
52;; If anybody feels like extending this sql mode, take a look at the
53;; above mentioned modes and write a sqlx-mode on top of this one. If
54;; this proves to be difficult, please suggest changes that will
01295a22
RS
55;; facilitate your plans. Facilities have been provided to add
56;; products and product-specific configuration.
95e4b2ef
RS
57
58;; sql-interactive-mode is used to interact with a SQL interpreter
dab100d7 59;; process in a SQLi buffer (usually called `*SQL*'). The SQLi buffer
01295a22
RS
60;; is created by calling a SQL interpreter-specific entry function or
61;; sql-product-interactive. Do *not* call sql-interactive-mode by
62;; itself.
95e4b2ef
RS
63
64;; The list of currently supported interpreters and the corresponding
dab100d7 65;; entry function used to create the SQLi buffers is shown with
95e4b2ef
RS
66;; `sql-help' (M-x sql-help).
67
68;; Since sql-interactive-mode is built on top of the general
69;; command-interpreter-in-a-buffer mode (comint mode), it shares a
70;; common base functionality, and a common set of bindings, with all
71;; modes derived from comint mode. This makes these modes easier to
72;; use.
73
311e7a89
GM
74;; sql-mode can be used to keep editing SQL statements. The SQL
75;; statements can be sent to the SQL process in the SQLi buffer.
95e4b2ef
RS
76
77;; For documentation on the functionality provided by comint mode, and
eb3f61dd 78;; the hooks available for customizing it, see the file `comint.el'.
95e4b2ef 79
801d1cb0
AS
80;; Hint for newbies: take a look at `dabbrev-expand', `abbrev-mode', and
81;; `imenu-add-menubar-index'.
95e4b2ef 82
95e4b2ef
RS
83;;; Bugs:
84
78024f88
AS
85;; sql-ms now uses osql instead of isql. Osql flushes its error
86;; stream more frequently than isql so that error messages are
87;; available. There is no prompt and some output still is buffered.
88;; This improves the interaction under Emacs but it still is somewhat
89;; awkward.
90
e4769531 91;; Quoted identifiers are not supported for highlighting. Most
78024f88
AS
92;; databases support the use of double quoted strings in place of
93;; identifiers; ms (Microsoft SQLServer) also supports identifiers
94;; enclosed within brackets [].
95e4b2ef 95
78024f88
AS
96;;; Product Support:
97
98;; To add support for additional SQL products the following steps
99;; must be followed ("xyz" is the name of the product in the examples
100;; below):
101
7492acc9 102;; 1) Add the product to the list of known products.
78024f88 103
7492acc9
MM
104;; (sql-add-product 'xyz "XyzDB"
105;; '(:free-software t))
78024f88 106
7492acc9
MM
107;; 2) Define font lock settings. All ANSI keywords will be
108;; highlighted automatically, so only product specific keywords
109;; need to be defined here.
78024f88 110
7492acc9
MM
111;; (defvar my-sql-mode-xyz-font-lock-keywords
112;; '(("\\b\\(red\\|orange\\|yellow\\)\\b"
113;; . font-lock-keyword-face))
114;; "XyzDB SQL keywords used by font-lock.")
78024f88 115
7492acc9
MM
116;; (sql-set-product-feature 'xyz
117;; :font-lock
118;; 'my-sql-mode-xyz-font-lock-keywords)
78024f88 119
7492acc9
MM
120;; 3) Define any special syntax characters including comments and
121;; identifier characters.
122
123;; (sql-set-product-feature 'xyz
fbcc67e2 124;; :syntax-alist ((?# . "_")))
7492acc9
MM
125
126;; 4) Define the interactive command interpreter for the database
127;; product.
128
129;; (defcustom my-sql-xyz-program "ixyz"
130;; "Command to start ixyz by XyzDB."
78024f88
AS
131;; :type 'file
132;; :group 'SQL)
133;;
7492acc9
MM
134;; (sql-set-product-feature 'xyz
135;; :sqli-program 'my-sql-xyz-program)
136;; (sql-set-product-feature 'xyz
137;; :prompt-regexp "^xyzdb> ")
138;; (sql-set-product-feature 'xyz
139;; :prompt-length 7)
140
141;; 5) Define login parameters and command line formatting.
142
143;; (defcustom my-sql-xyz-login-params '(user password server database)
144;; "Login parameters to needed to connect to XyzDB."
5474c40f 145;; :type 'sql-login-params
78024f88 146;; :group 'SQL)
7492acc9
MM
147;;
148;; (sql-set-product-feature 'xyz
149;; :sqli-login 'my-sql-xyz-login-params)
78024f88 150
7492acc9
MM
151;; (defcustom my-sql-xyz-options '("-X" "-Y" "-Z")
152;; "List of additional options for `sql-xyz-program'."
153;; :type '(repeat string)
154;; :group 'SQL)
155;;
156;; (sql-set-product-feature 'xyz
157;; :sqli-options 'my-sql-xyz-options))
78024f88 158
30c4d8dc 159;; (defun my-sql-comint-xyz (product options)
7492acc9 160;; "Connect ti XyzDB in a comint buffer."
78024f88
AS
161;;
162;; ;; Do something with `sql-user', `sql-password',
163;; ;; `sql-database', and `sql-server'.
93852cb0
SM
164;; (let ((params
165;; (append
78024f88 166;; (if (not (string= "" sql-user))
93852cb0
SM
167;; (list "-U" sql-user))
168;; (if (not (string= "" sql-password))
169;; (list "-P" sql-password))
170;; (if (not (string= "" sql-database))
171;; (list "-D" sql-database))
172;; (if (not (string= "" sql-server))
173;; (list "-S" sql-server))
174;; options)))
30c4d8dc 175;; (sql-comint product params)))
7492acc9
MM
176;;
177;; (sql-set-product-feature 'xyz
d26b0ea9 178;; :sqli-comint-func 'my-sql-comint-xyz)
78024f88 179
fbcc67e2 180;; 6) Define a convenience function to invoke the SQL interpreter.
7492acc9 181
9250002f 182;; (defun my-sql-xyz (&optional buffer)
7492acc9 183;; "Run ixyz by XyzDB as an inferior process."
9250002f
MM
184;; (interactive "P")
185;; (sql-product-interactive 'xyz buffer))
78024f88 186
b4dd5c9c
JB
187;;; To Do:
188
7492acc9
MM
189;; Improve keyword highlighting for individual products. I have tried
190;; to update those database that I use. Feel free to send me updates,
191;; or direct me to the reference manuals for your favorite database.
b4dd5c9c 192
7492acc9
MM
193;; When there are no keywords defined, the ANSI keywords are
194;; highlighted. ANSI keywords are highlighted even if the keyword is
195;; not used for your current product. This should help identify
196;; portability concerns.
197
198;; Add different highlighting levels.
199
200;; Add support for listing available tables or the columns in a table.
95e4b2ef
RS
201
202;;; Thanks to all the people who helped me out:
203
7492acc9 204;; Alex Schroeder <alex@gnu.org> -- the original author
95e4b2ef
RS
205;; Kai Blauberg <kai.blauberg@metla.fi>
206;; <ibalaban@dalet.com>
207;; Yair Friedman <yfriedma@JohnBryce.Co.Il>
208;; Gregor Zych <zych@pool.informatik.rwth-aachen.de>
a081a529 209;; nino <nino@inform.dk>
801d1cb0 210;; Berend de Boer <berend@pobox.com>
9fd8cb36 211;; Adam Jenkins <adam@thejenkins.org>
9a9069c9
SM
212;; Michael Mauger <mmaug@yahoo.com> -- improved product support
213;; Drew Adams <drew.adams@oracle.com> -- Emacs 20 support
214;; Harald Maier <maierh@myself.com> -- sql-send-string
04e082b0
MM
215;; Stefan Monnier <monnier@iro.umontreal.ca> -- font-lock corrections;
216;; code polish
bb5aa5d6
MM
217;; Paul Sleigh <bat@flurf.net> -- MySQL keyword enhancement
218;; Andrew Schein <andrew@andrewschein.com> -- sql-port bug
04e082b0
MM
219;; Ian Bjorhovde <idbjorh@dataproxy.com> -- db2 escape newlines
220;; incorrectly enabled by default
dab100d7 221
95e4b2ef
RS
222\f
223
224;;; Code:
225
93852cb0 226(require 'cl-lib)
95e4b2ef
RS
227(require 'comint)
228;; Need the following to allow GNU Emacs 19 to compile the file.
78024f88
AS
229(eval-when-compile
230 (require 'regexp-opt))
95e4b2ef 231(require 'custom)
fbcc67e2 232(require 'thingatpt)
fbcc67e2 233
ec38bb46
JB
234(defvar font-lock-keyword-face)
235(defvar font-lock-set-defaults)
236(defvar font-lock-string-face)
237
95e4b2ef
RS
238;;; Allow customization
239
240(defgroup SQL nil
b9584f65 241 "Running a SQL interpreter from within Emacs buffers."
6629e5ba 242 :version "20.4"
7492acc9 243 :group 'languages
95e4b2ef
RS
244 :group 'processes)
245
78024f88 246;; These four variables will be used as defaults, if set.
95e4b2ef
RS
247
248(defcustom sql-user ""
7492acc9 249 "Default username."
95e4b2ef 250 :type 'string
30c4d8dc
MM
251 :group 'SQL
252 :safe 'stringp)
95e4b2ef
RS
253
254(defcustom sql-password ""
7492acc9 255 "Default password.
865fe16f
CY
256If you customize this, the value will be stored in your init
257file. Since that is a plaintext file, this could be dangerous."
95e4b2ef 258 :type 'string
30c4d8dc
MM
259 :group 'SQL
260 :risky t)
95e4b2ef
RS
261
262(defcustom sql-database ""
7492acc9 263 "Default database."
95e4b2ef 264 :type 'string
30c4d8dc
MM
265 :group 'SQL
266 :safe 'stringp)
95e4b2ef
RS
267
268(defcustom sql-server ""
7492acc9 269 "Default server or host."
95e4b2ef 270 :type 'string
30c4d8dc
MM
271 :group 'SQL
272 :safe 'stringp)
7492acc9 273
9250002f 274(defcustom sql-port 0
34e8a2da 275 "Default port for connecting to a MySQL or Postgres server."
30c4d8dc 276 :version "24.1"
7492acc9 277 :type 'number
30c4d8dc
MM
278 :group 'SQL
279 :safe 'numberp)
95e4b2ef 280
5474c40f
MM
281;; Login parameter type
282
283(define-widget 'sql-login-params 'lazy
284 "Widget definition of the login parameters list"
74790210
MM
285 ;; FIXME: does not implement :default property for the user,
286 ;; database and server options. Anybody have some guidance on how to
287 ;; do this.
5474c40f
MM
288 :tag "Login Parameters"
289 :type '(repeat (choice
290 (const user)
291 (const password)
292 (choice :tag "server"
293 (const server)
294 (list :tag "file"
295 (const :format "" server)
296 (const :format "" :file)
297 regexp)
298 (list :tag "completion"
299 (const :format "" server)
300 (const :format "" :completion)
301 (restricted-sexp
74790210 302 :match-alternatives (listp stringp))))
5474c40f
MM
303 (choice :tag "database"
304 (const database)
305 (list :tag "file"
306 (const :format "" database)
307 (const :format "" :file)
308 regexp)
309 (list :tag "completion"
310 (const :format "" database)
311 (const :format "" :completion)
312 (restricted-sexp
74790210 313 :match-alternatives (listp stringp))))
5474c40f
MM
314 (const port))))
315
78024f88 316;; SQL Product support
78024f88
AS
317
318(defvar sql-interactive-product nil
319 "Product under `sql-interactive-mode'.")
320
30c4d8dc
MM
321(defvar sql-connection nil
322 "Connection name if interactive session started by `sql-connect'.")
323
9fd8cb36 324(defvar sql-product-alist
78024f88 325 '((ansi
55659495 326 :name "ANSI"
fbcc67e2
MM
327 :font-lock sql-mode-ansi-font-lock-keywords
328 :statement sql-ansi-statement-starters)
7492acc9 329
78024f88 330 (db2
55659495 331 :name "DB2"
78024f88 332 :font-lock sql-mode-db2-font-lock-keywords
7492acc9
MM
333 :sqli-program sql-db2-program
334 :sqli-options sql-db2-options
335 :sqli-login sql-db2-login-params
30c4d8dc 336 :sqli-comint-func sql-comint-db2
7492acc9
MM
337 :prompt-regexp "^db2 => "
338 :prompt-length 7
3bd2cfef 339 :prompt-cont-regexp "^db2 (cont\.) => "
7492acc9
MM
340 :input-filter sql-escape-newlines-filter)
341
78024f88 342 (informix
7492acc9 343 :name "Informix"
78024f88 344 :font-lock sql-mode-informix-font-lock-keywords
7492acc9
MM
345 :sqli-program sql-informix-program
346 :sqli-options sql-informix-options
347 :sqli-login sql-informix-login-params
30c4d8dc 348 :sqli-comint-func sql-comint-informix
7492acc9
MM
349 :prompt-regexp "^> "
350 :prompt-length 2
351 :syntax-alist ((?{ . "<") (?} . ">")))
352
78024f88 353 (ingres
7492acc9 354 :name "Ingres"
78024f88 355 :font-lock sql-mode-ingres-font-lock-keywords
7492acc9
MM
356 :sqli-program sql-ingres-program
357 :sqli-options sql-ingres-options
358 :sqli-login sql-ingres-login-params
30c4d8dc 359 :sqli-comint-func sql-comint-ingres
7492acc9 360 :prompt-regexp "^\* "
3bd2cfef
MM
361 :prompt-length 2
362 :prompt-cont-regexp "^\* ")
7492acc9 363
78024f88 364 (interbase
7492acc9 365 :name "Interbase"
78024f88 366 :font-lock sql-mode-interbase-font-lock-keywords
7492acc9
MM
367 :sqli-program sql-interbase-program
368 :sqli-options sql-interbase-options
369 :sqli-login sql-interbase-login-params
30c4d8dc 370 :sqli-comint-func sql-comint-interbase
7492acc9
MM
371 :prompt-regexp "^SQL> "
372 :prompt-length 5)
373
78024f88 374 (linter
7492acc9 375 :name "Linter"
78024f88 376 :font-lock sql-mode-linter-font-lock-keywords
7492acc9
MM
377 :sqli-program sql-linter-program
378 :sqli-options sql-linter-options
379 :sqli-login sql-linter-login-params
30c4d8dc 380 :sqli-comint-func sql-comint-linter
7492acc9
MM
381 :prompt-regexp "^SQL>"
382 :prompt-length 4)
383
78024f88 384 (ms
7492acc9 385 :name "Microsoft"
78024f88 386 :font-lock sql-mode-ms-font-lock-keywords
7492acc9
MM
387 :sqli-program sql-ms-program
388 :sqli-options sql-ms-options
389 :sqli-login sql-ms-login-params
30c4d8dc 390 :sqli-comint-func sql-comint-ms
7492acc9
MM
391 :prompt-regexp "^[0-9]*>"
392 :prompt-length 5
fbcc67e2 393 :syntax-alist ((?@ . "_"))
7492acc9
MM
394 :terminator ("^go" . "go"))
395
78024f88 396 (mysql
55659495 397 :name "MySQL"
7492acc9 398 :free-software t
78024f88 399 :font-lock sql-mode-mysql-font-lock-keywords
7492acc9
MM
400 :sqli-program sql-mysql-program
401 :sqli-options sql-mysql-options
402 :sqli-login sql-mysql-login-params
30c4d8dc 403 :sqli-comint-func sql-comint-mysql
74790210
MM
404 :list-all "SHOW TABLES;"
405 :list-table "DESCRIBE %s;"
7492acc9
MM
406 :prompt-regexp "^mysql> "
407 :prompt-length 6
3bd2cfef 408 :prompt-cont-regexp "^ -> "
fbcc67e2 409 :syntax-alist ((?# . "< b"))
7492acc9
MM
410 :input-filter sql-remove-tabs-filter)
411
78024f88 412 (oracle
7492acc9 413 :name "Oracle"
78024f88 414 :font-lock sql-mode-oracle-font-lock-keywords
7492acc9
MM
415 :sqli-program sql-oracle-program
416 :sqli-options sql-oracle-options
417 :sqli-login sql-oracle-login-params
30c4d8dc 418 :sqli-comint-func sql-comint-oracle
fbcc67e2
MM
419 :list-all sql-oracle-list-all
420 :list-table sql-oracle-list-table
421 :completion-object sql-oracle-completion-object
7492acc9
MM
422 :prompt-regexp "^SQL> "
423 :prompt-length 5
fbcc67e2
MM
424 :prompt-cont-regexp "^\\s-*[[:digit:]]+ "
425 :statement sql-oracle-statement-starters
426 :syntax-alist ((?$ . "_") (?# . "_"))
427 :terminator ("\\(^/\\|;\\)$" . "/")
7492acc9
MM
428 :input-filter sql-placeholders-filter)
429
78024f88 430 (postgres
7492acc9
MM
431 :name "Postgres"
432 :free-software t
78024f88 433 :font-lock sql-mode-postgres-font-lock-keywords
7492acc9
MM
434 :sqli-program sql-postgres-program
435 :sqli-options sql-postgres-options
436 :sqli-login sql-postgres-login-params
30c4d8dc 437 :sqli-comint-func sql-comint-postgres
74790210
MM
438 :list-all ("\\d+" . "\\dS+")
439 :list-table ("\\d+ %s" . "\\dS+ %s")
fbcc67e2
MM
440 :completion-object sql-postgres-completion-object
441 :prompt-regexp "^\\w*=[#>] "
7492acc9 442 :prompt-length 5
fbcc67e2 443 :prompt-cont-regexp "^\\w*[-(][#>] "
7492acc9 444 :input-filter sql-remove-tabs-filter
fbcc67e2 445 :terminator ("\\(^\\s-*\\\\g$\\|;\\)" . "\\g"))
7492acc9 446
78024f88 447 (solid
7492acc9 448 :name "Solid"
78024f88 449 :font-lock sql-mode-solid-font-lock-keywords
7492acc9
MM
450 :sqli-program sql-solid-program
451 :sqli-options sql-solid-options
452 :sqli-login sql-solid-login-params
30c4d8dc 453 :sqli-comint-func sql-comint-solid
7492acc9
MM
454 :prompt-regexp "^"
455 :prompt-length 0)
456
78024f88 457 (sqlite
55659495 458 :name "SQLite"
7492acc9 459 :free-software t
78024f88 460 :font-lock sql-mode-sqlite-font-lock-keywords
7492acc9
MM
461 :sqli-program sql-sqlite-program
462 :sqli-options sql-sqlite-options
463 :sqli-login sql-sqlite-login-params
30c4d8dc 464 :sqli-comint-func sql-comint-sqlite
74790210
MM
465 :list-all ".tables"
466 :list-table ".schema %s"
fbcc67e2 467 :completion-object sql-sqlite-completion-object
7492acc9 468 :prompt-regexp "^sqlite> "
3bd2cfef 469 :prompt-length 8
fbcc67e2 470 :prompt-cont-regexp "^ \.\.\.> "
3bd2cfef 471 :terminator ";")
7492acc9 472
78024f88 473 (sybase
7492acc9 474 :name "Sybase"
78024f88 475 :font-lock sql-mode-sybase-font-lock-keywords
7492acc9
MM
476 :sqli-program sql-sybase-program
477 :sqli-options sql-sybase-options
478 :sqli-login sql-sybase-login-params
30c4d8dc 479 :sqli-comint-func sql-comint-sybase
7492acc9
MM
480 :prompt-regexp "^SQL> "
481 :prompt-length 5
fbcc67e2 482 :syntax-alist ((?@ . "_"))
7492acc9 483 :terminator ("^go" . "go"))
78024f88 484 )
7492acc9
MM
485 "An alist of product specific configuration settings.
486
487Without an entry in this list a product will not be properly
488highlighted and will not support `sql-interactive-mode'.
78024f88
AS
489
490Each element in the list is in the following format:
491
492 \(PRODUCT FEATURE VALUE ...)
493
7492acc9
MM
494where PRODUCT is the appropriate value of `sql-product'. The
495product name is then followed by FEATURE-VALUE pairs. If a
496FEATURE is not specified, its VALUE is treated as nil. FEATURE
497may be any one of the following:
498
499 :name string containing the displayable name of
500 the product.
501
502 :free-software is the product Free (as in Freedom) software?
78024f88
AS
503
504 :font-lock name of the variable containing the product
505 specific font lock highlighting patterns.
506
7492acc9
MM
507 :sqli-program name of the variable containing the product
508 specific interactive program name.
509
510 :sqli-options name of the variable containing the list
511 of product specific options.
78024f88 512
7492acc9
MM
513 :sqli-login name of the variable containing the list of
514 login parameters (i.e., user, password,
515 database and server) needed to connect to
516 the database.
517
30c4d8dc 518 :sqli-comint-func name of a function which accepts no
78024f88
AS
519 parameters that will use the values of
520 `sql-user', `sql-password',
fbcc67e2
MM
521 `sql-database', `sql-server' and
522 `sql-port' to open a comint buffer and
523 connect to the database. Do product
524 specific configuration of comint in this
525 function.
78024f88 526
74790210
MM
527 :list-all Command string or function which produces
528 a listing of all objects in the database.
529 If it's a cons cell, then the car
530 produces the standard list of objects and
531 the cdr produces an enhanced list of
532 objects. What \"enhanced\" means is
533 dependent on the SQL product and may not
534 exist. In general though, the
535 \"enhanced\" list should include visible
536 objects from other schemas.
537
538 :list-table Command string or function which produces
539 a detailed listing of a specific database
540 table. If its a cons cell, then the car
541 produces the standard list and the cdr
542 produces an enhanced list.
543
fbcc67e2
MM
544 :completion-object A function that returns a list of
545 objects. Called with a single
546 parameter--if nil then list objects
547 accessible in the current schema, if
548 not-nil it is the name of a schema whose
549 objects should be listed.
550
551 :completion-column A function that returns a list of
552 columns. Called with a single
553 parameter--if nil then list objects
554 accessible in the current schema, if
555 not-nil it is the name of a schema whose
556 objects should be listed.
557
7492acc9 558 :prompt-regexp regular expression string that matches
9fd8cb36 559 the prompt issued by the product
7492acc9
MM
560 interpreter.
561
562 :prompt-length length of the prompt on the line.
563
3bd2cfef
MM
564 :prompt-cont-regexp regular expression string that matches
565 the continuation prompt issued by the
566 product interpreter.
567
7492acc9
MM
568 :input-filter function which can filter strings sent to
569 the command interpreter. It is also used
570 by the `sql-send-string',
571 `sql-send-region', `sql-send-paragraph'
572 and `sql-send-buffer' functions. The
573 function is passed the string sent to the
574 command interpreter and must return the
3bd2cfef
MM
575 filtered string. May also be a list of
576 such functions.
7492acc9 577
fbcc67e2
MM
578 :statement name of a variable containing a regexp that
579 matches the beginning of SQL statements.
580
7492acc9
MM
581 :terminator the terminator to be sent after a
582 `sql-send-string', `sql-send-region',
583 `sql-send-paragraph' and
584 `sql-send-buffer' command. May be the
585 literal string or a cons of a regexp to
586 match an existing terminator in the
587 string and the terminator to be used if
588 its absent. By default \";\".
589
590 :syntax-alist alist of syntax table entries to enable
591 special character treatment by font-lock
592 and imenu.
593
594Other features can be stored but they will be ignored. However,
595you can develop new functionality which is product independent by
596using `sql-get-product-feature' to lookup the product specific
597settings.")
598
599(defvar sql-indirect-features
fbcc67e2 600 '(:font-lock :sqli-program :sqli-options :sqli-login :statement))
78024f88 601
30c4d8dc 602(defcustom sql-connection-alist nil
34e8a2da 603 "An alist of connection parameters for interacting with a SQL product.
30c4d8dc
MM
604Each element of the alist is as follows:
605
606 \(CONNECTION \(SQL-VARIABLE VALUE) ...)
607
608Where CONNECTION is a symbol identifying the connection, SQL-VARIABLE
609is the symbol name of a SQL mode variable, and VALUE is the value to
34e8a2da
GM
610be assigned to the variable. The most common SQL-VARIABLE settings
611associated with a connection are: `sql-product', `sql-user',
612`sql-password', `sql-port', `sql-server', and `sql-database'.
30c4d8dc
MM
613
614If a SQL-VARIABLE is part of the connection, it will not be
34e8a2da
GM
615prompted for during login. The command `sql-connect' starts a
616predefined SQLi session using the parameters from this list.
617Connections defined here appear in the submenu SQL->Start... for
618making new SQLi sessions."
d26b0ea9 619 :type `(alist :key-type (string :tag "Connection")
30c4d8dc
MM
620 :value-type
621 (set
622 (group (const :tag "Product" sql-product)
623 (choice
93852cb0
SM
624 ,@(mapcar
625 (lambda (prod-info)
626 `(const :tag
627 ,(or (plist-get (cdr prod-info) :name)
628 (capitalize
629 (symbol-name (car prod-info))))
630 (quote ,(car prod-info))))
631 sql-product-alist)))
30c4d8dc
MM
632 (group (const :tag "Username" sql-user) string)
633 (group (const :tag "Password" sql-password) string)
634 (group (const :tag "Server" sql-server) string)
635 (group (const :tag "Database" sql-database) string)
d26b0ea9
MM
636 (group (const :tag "Port" sql-port) integer)
637 (repeat :inline t
638 (list :tab "Other"
639 (symbol :tag " Variable Symbol")
640 (sexp :tag "Value Expression")))))
30c4d8dc
MM
641 :version "24.1"
642 :group 'SQL)
643
55659495 644(defcustom sql-product 'ansi
93852cb0
SM
645 "Select the SQL database product used.
646This allows highlighting buffers properly when you open them."
55659495
SM
647 :type `(choice
648 ,@(mapcar (lambda (prod-info)
649 `(const :tag
650 ,(or (plist-get (cdr prod-info) :name)
651 (capitalize (symbol-name (car prod-info))))
652 ,(car prod-info)))
653 sql-product-alist))
30c4d8dc
MM
654 :group 'SQL
655 :safe 'symbolp)
9250002f 656(defvaralias 'sql-dialect 'sql-product)
7492acc9 657
91af3942 658;; misc customization of sql.el behavior
801d1cb0 659
9ef3882f
GM
660(defcustom sql-electric-stuff nil
661 "Treat some input as electric.
662If set to the symbol `semicolon', then hitting `;' will send current
663input in the SQLi buffer to the process.
664If set to the symbol `go', then hitting `go' on a line by itself will
665send current input in the SQLi buffer to the process.
666If set to nil, then you must use \\[comint-send-input] in order to send
667current input in the SQLi buffer to the process."
668 :type '(choice (const :tag "Nothing" nil)
063c6324 669 (const :tag "The semicolon `;'" semicolon)
9ef3882f
GM
670 (const :tag "The string `go' by itself" go))
671 :version "20.8"
672 :group 'SQL)
673
7492acc9
MM
674(defcustom sql-send-terminator nil
675 "When non-nil, add a terminator to text sent to the SQL interpreter.
676
677When text is sent to the SQL interpreter (via `sql-send-string',
678`sql-send-region', `sql-send-paragraph' or `sql-send-buffer'), a
679command terminator can be automatically sent as well. The
680terminator is not sent, if the string sent already ends with the
681terminator.
682
683If this value is t, then the default command terminator for the
684SQL interpreter is sent. If this value is a string, then the
685string is sent.
686
687If the value is a cons cell of the form (PAT . TERM), then PAT is
688a regexp used to match the terminator in the string and TERM is
689the terminator to be sent. This form is useful if the SQL
690interpreter has more than one way of submitting a SQL command.
691The PAT regexp can match any of them, and TERM is the way we do
692it automatically."
693
694 :type '(choice (const :tag "No Terminator" nil)
695 (const :tag "Default Terminator" t)
696 (string :tag "Terminator String")
697 (cons :tag "Terminator Pattern and String"
698 (string :tag "Terminator Pattern")
699 (string :tag "Terminator String")))
700 :version "22.2"
701 :group 'SQL)
95e4b2ef 702
fbcc67e2
MM
703(defvar sql-contains-names nil
704 "When non-nil, the current buffer contains database names.
705
706Globally should be set to nil; it will be non-nil in `sql-mode',
707`sql-interactive-mode' and list all buffers.")
708
709
7492acc9
MM
710(defcustom sql-pop-to-buffer-after-send-region nil
711 "When non-nil, pop to the buffer SQL statements are sent to.
712
713After a call to `sql-sent-string', `sql-send-region',
714`sql-send-paragraph' or `sql-send-buffer', the window is split
715and the SQLi buffer is shown. If this variable is not nil, that
716buffer's window will be selected by calling `pop-to-buffer'. If
717this variable is nil, that buffer is shown using
718`display-buffer'."
c7055d66
RS
719 :type 'boolean
720 :group 'SQL)
721
801d1cb0
AS
722;; imenu support for sql-mode.
723
724(defvar sql-imenu-generic-expression
78024f88 725 ;; Items are in reverse order because they are rendered in reverse.
4586ce8a
MM
726 '(("Rules/Defaults" "^\\s-*create\\s-+\\(?:\\w+\\s-+\\)*\\(?:rule\\|default\\)\\(?:if\\s-+not\\s-+exists\\s-+\\)?\\s-+\\(\\(?:\\w+\\s-*[.]\\s-*\\)*\\w+\\)" 1)
727 ("Sequences" "^\\s-*create\\s-+\\(?:\\w+\\s-+\\)*sequence\\s-+\\(?:if\\s-+not\\s-+exists\\s-+\\)?\\(\\(?:\\w+\\s-*[.]\\s-*\\)*\\w+\\)" 1)
728 ("Triggers" "^\\s-*create\\s-+\\(?:\\w+\\s-+\\)*trigger\\s-+\\(?:if\\s-+not\\s-+exists\\s-+\\)?\\(\\(?:\\w+\\s-*[.]\\s-*\\)*\\w+\\)" 1)
729 ("Functions" "^\\s-*\\(?:create\\s-+\\(?:\\w+\\s-+\\)*\\)?function\\s-+\\(?:if\\s-+not\\s-+exists\\s-+\\)?\\(\\(?:\\w+\\s-*[.]\\s-*\\)*\\w+\\)" 1)
730 ("Procedures" "^\\s-*\\(?:create\\s-+\\(?:\\w+\\s-+\\)*\\)?proc\\(?:edure\\)?\\s-+\\(?:if\\s-+not\\s-+exists\\s-+\\)?\\(\\(?:\\w+\\s-*[.]\\s-*\\)*\\w+\\)" 1)
731 ("Packages" "^\\s-*create\\s-+\\(?:\\w+\\s-+\\)*package\\s-+\\(?:body\\s-+\\)?\\(?:if\\s-+not\\s-+exists\\s-+\\)?\\(\\(?:\\w+\\s-*[.]\\s-*\\)*\\w+\\)" 1)
732 ("Types" "^\\s-*create\\s-+\\(?:\\w+\\s-+\\)*type\\s-+\\(?:body\\s-+\\)?\\(?:if\\s-+not\\s-+exists\\s-+\\)?\\(\\(?:\\w+\\s-*[.]\\s-*\\)*\\w+\\)" 1)
733 ("Indexes" "^\\s-*create\\s-+\\(?:\\w+\\s-+\\)*index\\s-+\\(?:if\\s-+not\\s-+exists\\s-+\\)?\\(\\(?:\\w+\\s-*[.]\\s-*\\)*\\w+\\)" 1)
734 ("Tables/Views" "^\\s-*create\\s-+\\(?:\\w+\\s-+\\)*\\(?:table\\|view\\)\\s-+\\(?:if\\s-+not\\s-+exists\\s-+\\)?\\(\\(?:\\w+\\s-*[.]\\s-*\\)*\\w+\\)" 1))
801d1cb0
AS
735 "Define interesting points in the SQL buffer for `imenu'.
736
9ef3882f 737This is used to set `imenu-generic-expression' when SQL mode is
063c6324
JB
738entered. Subsequent changes to `sql-imenu-generic-expression' will
739not affect existing SQL buffers because imenu-generic-expression is
740a local variable.")
801d1cb0
AS
741
742;; history file
743
c7055d66 744(defcustom sql-input-ring-file-name nil
7492acc9 745 "If non-nil, name of the file to read/write input history.
c7055d66 746
9ef73b91
KH
747You have to set this variable if you want the history of your commands
748saved from one Emacs session to the next. If this variable is set,
749exiting the SQL interpreter in an SQLi buffer will write the input
750history to the specified file. Starting a new process in a SQLi buffer
751will read the input history from the specified file.
752
77d352a6
GM
753This is used to initialize `comint-input-ring-file-name'.
754
755Note that the size of the input history is determined by the variable
756`comint-input-ring-size'."
c7055d66
RS
757 :type '(choice (const :tag "none" nil)
758 (file))
759 :group 'SQL)
760
761(defcustom sql-input-ring-separator "\n--\n"
7492acc9 762 "Separator between commands in the history file.
c7055d66
RS
763
764If set to \"\\n\", each line in the history file will be interpreted as
765one command. Multi-line commands are split into several commands when
766the input ring is initialized from a history file.
767
77d352a6
GM
768This variable used to initialize `comint-input-ring-separator'.
769`comint-input-ring-separator' is part of Emacs 21; if your Emacs
770does not have it, setting `sql-input-ring-separator' will have no
771effect. In that case multiline commands will be split into several
772commands when the input history is read, as if you had set
773`sql-input-ring-separator' to \"\\n\"."
95e4b2ef
RS
774 :type 'string
775 :group 'SQL)
776
777;; The usual hooks
778
779(defcustom sql-interactive-mode-hook '()
7492acc9 780 "Hook for customizing `sql-interactive-mode'."
95e4b2ef
RS
781 :type 'hook
782 :group 'SQL)
783
784(defcustom sql-mode-hook '()
7492acc9 785 "Hook for customizing `sql-mode'."
95e4b2ef
RS
786 :type 'hook
787 :group 'SQL)
788
c7055d66 789(defcustom sql-set-sqli-hook '()
7492acc9 790 "Hook for reacting to changes of `sql-buffer'.
c7055d66
RS
791
792This is called by `sql-set-sqli-buffer' when the value of `sql-buffer'
793is changed."
794 :type 'hook
795 :group 'SQL)
796
bb5aa5d6
MM
797(defcustom sql-login-hook '()
798 "Hook for interacting with a buffer in `sql-interactive-mode'.
799
800This hook is invoked in a buffer once it is ready to accept input
801for the first time."
2bed3f04 802 :version "24.1"
bb5aa5d6
MM
803 :type 'hook
804 :group 'SQL)
805
fbcc67e2
MM
806;; Customization for ANSI
807
93852cb0
SM
808(defcustom sql-ansi-statement-starters
809 (regexp-opt '("create" "alter" "drop"
810 "select" "insert" "update" "delete" "merge"
811 "grant" "revoke"))
812 "Regexp of keywords that start SQL commands.
fbcc67e2
MM
813
814All products share this list; products should define a regexp to
815identify additional keywords in a variable defined by
5fec1b8e 816the :statement feature."
2bed3f04 817 :version "24.1"
5fec1b8e
GM
818 :type 'string
819 :group 'SQL)
fbcc67e2 820
eb3f61dd 821;; Customization for Oracle
95e4b2ef
RS
822
823(defcustom sql-oracle-program "sqlplus"
7492acc9 824 "Command to start sqlplus by Oracle.
95e4b2ef
RS
825
826Starts `sql-interactive-mode' after doing some setup.
827
c38762fd
JB
828On Windows, \"sqlplus\" usually starts the sqlplus \"GUI\". In order
829to start the sqlplus console, use \"plus33\" or something similar.
830You will find the file in your Orant\\bin directory."
a081a529
RS
831 :type 'file
832 :group 'SQL)
833
9ef3882f 834(defcustom sql-oracle-options nil
7492acc9 835 "List of additional options for `sql-oracle-program'."
9ef3882f
GM
836 :type '(repeat string)
837 :version "20.8"
838 :group 'SQL)
839
7492acc9
MM
840(defcustom sql-oracle-login-params '(user password database)
841 "List of login parameters needed to connect to Oracle."
5474c40f 842 :type 'sql-login-params
7492acc9
MM
843 :version "24.1"
844 :group 'SQL)
845
5fec1b8e
GM
846(defcustom sql-oracle-statement-starters
847 (regexp-opt '("declare" "begin" "with"))
848 "Additional statement starting keywords in Oracle."
2bed3f04 849 :version "24.1"
5fec1b8e
GM
850 :type 'string
851 :group 'SQL)
fbcc67e2 852
7492acc9
MM
853(defcustom sql-oracle-scan-on t
854 "Non-nil if placeholders should be replaced in Oracle SQLi.
855
856When non-nil, Emacs will scan text sent to sqlplus and prompt
857for replacement text for & placeholders as sqlplus does. This
fbcc67e2 858is needed on Windows where SQL*Plus output is buffered and the
7492acc9
MM
859prompts are not shown until after the text is entered.
860
fbcc67e2
MM
861You need to issue the following command in SQL*Plus to be safe:
862
863 SET DEFINE OFF
7492acc9 864
fbcc67e2 865In older versions of SQL*Plus, this was the SET SCAN OFF command."
2bed3f04 866 :version "24.1"
7492acc9
MM
867 :type 'boolean
868 :group 'SQL)
869
04e082b0
MM
870(defcustom sql-db2-escape-newlines nil
871 "Non-nil if newlines should be escaped by a backslash in DB2 SQLi.
872
873When non-nil, Emacs will automatically insert a space and
874backslash prior to every newline in multi-line SQL statements as
875they are submitted to an interactive DB2 session."
876 :version "24.3"
877 :type 'boolean
878 :group 'SQL)
879
5d538ce3
JB
880;; Customization for SQLite
881
9250002f
MM
882(defcustom sql-sqlite-program (or (executable-find "sqlite3")
883 (executable-find "sqlite")
884 "sqlite")
7492acc9 885 "Command to start SQLite.
5d538ce3 886
7492acc9 887Starts `sql-interactive-mode' after doing some setup."
5d538ce3
JB
888 :type 'file
889 :group 'SQL)
890
891(defcustom sql-sqlite-options nil
7492acc9 892 "List of additional options for `sql-sqlite-program'."
5d538ce3
JB
893 :type '(repeat string)
894 :version "20.8"
895 :group 'SQL)
896
9250002f 897(defcustom sql-sqlite-login-params '((database :file ".*\\.\\(db\\|sqlite[23]?\\)"))
7492acc9 898 "List of login parameters needed to connect to SQLite."
5474c40f 899 :type 'sql-login-params
7492acc9
MM
900 :version "24.1"
901 :group 'SQL)
902
fbcc67e2 903;; Customization for MySQL
a081a529
RS
904
905(defcustom sql-mysql-program "mysql"
7492acc9 906 "Command to start mysql by TcX.
a081a529 907
7492acc9 908Starts `sql-interactive-mode' after doing some setup."
dab100d7
RS
909 :type 'file
910 :group 'SQL)
911
542c6552 912(defcustom sql-mysql-options nil
7492acc9 913 "List of additional options for `sql-mysql-program'.
524c8caf
GM
914The following list of options is reported to make things work
915on Windows: \"-C\" \"-t\" \"-f\" \"-n\"."
542c6552
GM
916 :type '(repeat string)
917 :version "20.8"
918 :group 'SQL)
919
7492acc9 920(defcustom sql-mysql-login-params '(user password database server)
fbcc67e2 921 "List of login parameters needed to connect to MySQL."
5474c40f 922 :type 'sql-login-params
7492acc9
MM
923 :version "24.1"
924 :group 'SQL)
925
eb3f61dd 926;; Customization for Solid
dab100d7
RS
927
928(defcustom sql-solid-program "solsql"
7492acc9 929 "Command to start SOLID SQL Editor.
dab100d7 930
7492acc9 931Starts `sql-interactive-mode' after doing some setup."
95e4b2ef
RS
932 :type 'file
933 :group 'SQL)
934
7492acc9
MM
935(defcustom sql-solid-login-params '(user password server)
936 "List of login parameters needed to connect to Solid."
5474c40f 937 :type 'sql-login-params
7492acc9
MM
938 :version "24.1"
939 :group 'SQL)
940
c38762fd 941;; Customization for Sybase
95e4b2ef
RS
942
943(defcustom sql-sybase-program "isql"
c38762fd 944 "Command to start isql by Sybase.
95e4b2ef 945
7492acc9 946Starts `sql-interactive-mode' after doing some setup."
95e4b2ef
RS
947 :type 'file
948 :group 'SQL)
949
9b5360aa 950(defcustom sql-sybase-options nil
7492acc9 951 "List of additional options for `sql-sybase-program'.
9b5360aa
GM
952Some versions of isql might require the -n option in order to work."
953 :type '(repeat string)
954 :version "20.8"
955 :group 'SQL)
956
7492acc9
MM
957(defcustom sql-sybase-login-params '(server user password database)
958 "List of login parameters needed to connect to Sybase."
5474c40f 959 :type 'sql-login-params
7492acc9
MM
960 :version "24.1"
961 :group 'SQL)
962
eb3f61dd 963;; Customization for Informix
95e4b2ef
RS
964
965(defcustom sql-informix-program "dbaccess"
7492acc9 966 "Command to start dbaccess by Informix.
95e4b2ef 967
7492acc9 968Starts `sql-interactive-mode' after doing some setup."
95e4b2ef
RS
969 :type 'file
970 :group 'SQL)
971
7492acc9
MM
972(defcustom sql-informix-login-params '(database)
973 "List of login parameters needed to connect to Informix."
5474c40f 974 :type 'sql-login-params
7492acc9
MM
975 :version "24.1"
976 :group 'SQL)
977
eb3f61dd 978;; Customization for Ingres
95e4b2ef
RS
979
980(defcustom sql-ingres-program "sql"
7492acc9 981 "Command to start sql by Ingres.
95e4b2ef 982
7492acc9 983Starts `sql-interactive-mode' after doing some setup."
95e4b2ef
RS
984 :type 'file
985 :group 'SQL)
986
7492acc9
MM
987(defcustom sql-ingres-login-params '(database)
988 "List of login parameters needed to connect to Ingres."
5474c40f 989 :type 'sql-login-params
7492acc9
MM
990 :version "24.1"
991 :group 'SQL)
992
eb3f61dd 993;; Customization for Microsoft
95e4b2ef 994
78024f88 995(defcustom sql-ms-program "osql"
7492acc9 996 "Command to start osql by Microsoft.
95e4b2ef 997
7492acc9 998Starts `sql-interactive-mode' after doing some setup."
95e4b2ef
RS
999 :type 'file
1000 :group 'SQL)
1001
f4df536d
JB
1002(defcustom sql-ms-options '("-w" "300" "-n")
1003 ;; -w is the linesize
7492acc9 1004 "List of additional options for `sql-ms-program'."
f4df536d 1005 :type '(repeat string)
bf247b6e 1006 :version "22.1"
f4df536d
JB
1007 :group 'SQL)
1008
7492acc9
MM
1009(defcustom sql-ms-login-params '(user password server database)
1010 "List of login parameters needed to connect to Microsoft."
5474c40f 1011 :type 'sql-login-params
7492acc9
MM
1012 :version "24.1"
1013 :group 'SQL)
1014
eb3f61dd 1015;; Customization for Postgres
95e4b2ef
RS
1016
1017(defcustom sql-postgres-program "psql"
801d1cb0 1018 "Command to start psql by Postgres.
95e4b2ef 1019
7492acc9 1020Starts `sql-interactive-mode' after doing some setup."
95e4b2ef
RS
1021 :type 'file
1022 :group 'SQL)
1023
524c8caf 1024(defcustom sql-postgres-options '("-P" "pager=off")
7492acc9 1025 "List of additional options for `sql-postgres-program'.
aa88e662
GM
1026The default setting includes the -P option which breaks older versions
1027of the psql client (such as version 6.5.3). The -P option is equivalent
1028to the --pset option. If you want the psql to prompt you for a user
1029name, add the string \"-u\" to the list of options. If you want to
1030provide a user name on the command line (newer versions such as 7.1),
1031add your name with a \"-U\" prefix (such as \"-Umark\") to the list."
311e7a89
GM
1032 :type '(repeat string)
1033 :version "20.8"
1034 :group 'SQL)
1035
74790210
MM
1036(defcustom sql-postgres-login-params `((user :default ,(user-login-name))
1037 (database :default ,(user-login-name))
1038 server)
7492acc9 1039 "List of login parameters needed to connect to Postgres."
5474c40f 1040 :type 'sql-login-params
7492acc9
MM
1041 :version "24.1"
1042 :group 'SQL)
1043
eb3f61dd
GM
1044;; Customization for Interbase
1045
1046(defcustom sql-interbase-program "isql"
7492acc9 1047 "Command to start isql by Interbase.
eb3f61dd 1048
7492acc9 1049Starts `sql-interactive-mode' after doing some setup."
eb3f61dd
GM
1050 :type 'file
1051 :group 'SQL)
1052
1053(defcustom sql-interbase-options nil
7492acc9 1054 "List of additional options for `sql-interbase-program'."
eb3f61dd
GM
1055 :type '(repeat string)
1056 :version "20.8"
1057 :group 'SQL)
1058
7492acc9
MM
1059(defcustom sql-interbase-login-params '(user password database)
1060 "List of login parameters needed to connect to Interbase."
5474c40f 1061 :type 'sql-login-params
7492acc9
MM
1062 :version "24.1"
1063 :group 'SQL)
1064
624ef9b3
GM
1065;; Customization for DB2
1066
1067(defcustom sql-db2-program "db2"
7492acc9 1068 "Command to start db2 by IBM.
624ef9b3 1069
7492acc9 1070Starts `sql-interactive-mode' after doing some setup."
624ef9b3
GM
1071 :type 'file
1072 :group 'SQL)
1073
1074(defcustom sql-db2-options nil
7492acc9 1075 "List of additional options for `sql-db2-program'."
624ef9b3
GM
1076 :type '(repeat string)
1077 :version "20.8"
1078 :group 'SQL)
1079
7492acc9
MM
1080(defcustom sql-db2-login-params nil
1081 "List of login parameters needed to connect to DB2."
5474c40f 1082 :type 'sql-login-params
7492acc9
MM
1083 :version "24.1"
1084 :group 'SQL)
1085
f4df536d
JB
1086;; Customization for Linter
1087
1088(defcustom sql-linter-program "inl"
7492acc9 1089 "Command to start inl by RELEX.
f4df536d
JB
1090
1091Starts `sql-interactive-mode' after doing some setup."
1092 :type 'file
1093 :group 'SQL)
1094
1095(defcustom sql-linter-options nil
7492acc9 1096 "List of additional options for `sql-linter-program'."
f4df536d
JB
1097 :type '(repeat string)
1098 :version "21.3"
1099 :group 'SQL)
1100
7492acc9
MM
1101(defcustom sql-linter-login-params '(user password database server)
1102 "Login parameters to needed to connect to Linter."
5474c40f 1103 :type 'sql-login-params
7492acc9
MM
1104 :version "24.1"
1105 :group 'SQL)
1106
95e4b2ef
RS
1107\f
1108
1109;;; Variables which do not need customization
1110
1111(defvar sql-user-history nil
1112 "History of usernames used.")
1113
1114(defvar sql-database-history nil
1115 "History of databases used.")
1116
1117(defvar sql-server-history nil
1118 "History of servers used.")
1119
1120;; Passwords are not kept in a history.
1121
74790210
MM
1122(defvar sql-product-history nil
1123 "History of products used.")
1124
1125(defvar sql-connection-history nil
1126 "History of connections used.")
1127
95e4b2ef 1128(defvar sql-buffer nil
dab100d7
RS
1129 "Current SQLi buffer.
1130
063c6324 1131The global value of `sql-buffer' is the name of the latest SQLi buffer
dab100d7
RS
1132created. Any SQL buffer created will make a local copy of this value.
1133See `sql-interactive-mode' for more on multiple sessions. If you want
1134to change the SQLi buffer a SQL mode sends its SQL strings to, change
c7055d66 1135the local value of `sql-buffer' using \\[sql-set-sqli-buffer].")
95e4b2ef
RS
1136
1137(defvar sql-prompt-regexp nil
1138 "Prompt used to initialize `comint-prompt-regexp'.
1139
78024f88 1140You can change `sql-prompt-regexp' on `sql-interactive-mode-hook'.")
95e4b2ef 1141
a081a529
RS
1142(defvar sql-prompt-length 0
1143 "Prompt used to set `left-margin' in `sql-interactive-mode'.
1144
78024f88 1145You can change `sql-prompt-length' on `sql-interactive-mode-hook'.")
a081a529 1146
3bd2cfef
MM
1147(defvar sql-prompt-cont-regexp nil
1148 "Prompt pattern of statement continuation prompts.")
1149
c7055d66
RS
1150(defvar sql-alternate-buffer-name nil
1151 "Buffer-local string used to possibly rename the SQLi buffer.
1152
1153Used by `sql-rename-buffer'.")
1154
fbcc67e2 1155(defun sql-buffer-live-p (buffer &optional product connection)
93852cb0 1156 "Return non-nil if the process associated with buffer is live.
a386ac70
MM
1157
1158BUFFER can be a buffer object or a buffer name. The buffer must
93852cb0 1159be a live buffer, have a running process attached to it, be in
fbcc67e2
MM
1160`sql-interactive-mode', and, if PRODUCT or CONNECTION are
1161specified, it's `sql-product' or `sql-connection' must match."
a386ac70
MM
1162
1163 (when buffer
1164 (setq buffer (get-buffer buffer))
1165 (and buffer
1166 (buffer-live-p buffer)
a386ac70
MM
1167 (comint-check-proc buffer)
1168 (with-current-buffer buffer
74790210 1169 (and (derived-mode-p 'sql-interactive-mode)
a386ac70 1170 (or (not product)
fbcc67e2
MM
1171 (eq product sql-product))
1172 (or (not connection)
1173 (eq connection sql-connection)))))))
9250002f 1174
9ef3882f
GM
1175;; Keymap for sql-interactive-mode.
1176
f4df536d 1177(defvar sql-interactive-mode-map
9ef3882f 1178 (let ((map (make-sparse-keymap)))
8d68e9b5 1179 (if (fboundp 'set-keymap-parent)
9ef3882f 1180 (set-keymap-parent map comint-mode-map); Emacs
8d68e9b5
RS
1181 (if (fboundp 'set-keymap-parents)
1182 (set-keymap-parents map (list comint-mode-map)))); XEmacs
1183 (if (fboundp 'set-keymap-name)
9ef3882f
GM
1184 (set-keymap-name map 'sql-interactive-mode-map)); XEmacs
1185 (define-key map (kbd "C-j") 'sql-accumulate-and-indent)
1186 (define-key map (kbd "C-c C-w") 'sql-copy-column)
1187 (define-key map (kbd "O") 'sql-magic-go)
1188 (define-key map (kbd "o") 'sql-magic-go)
1189 (define-key map (kbd ";") 'sql-magic-semicolon)
74790210
MM
1190 (define-key map (kbd "C-c C-l a") 'sql-list-all)
1191 (define-key map (kbd "C-c C-l t") 'sql-list-table)
9ef3882f
GM
1192 map)
1193 "Mode map used for `sql-interactive-mode'.
1194Based on `comint-mode-map'.")
95e4b2ef
RS
1195
1196;; Keymap for sql-mode.
1197
1198(defvar sql-mode-map
1199 (let ((map (make-sparse-keymap)))
9ef3882f
GM
1200 (define-key map (kbd "C-c C-c") 'sql-send-paragraph)
1201 (define-key map (kbd "C-c C-r") 'sql-send-region)
9fd8cb36 1202 (define-key map (kbd "C-c C-s") 'sql-send-string)
9ef3882f 1203 (define-key map (kbd "C-c C-b") 'sql-send-buffer)
7492acc9 1204 (define-key map (kbd "C-c C-i") 'sql-product-interactive)
74790210
MM
1205 (define-key map (kbd "C-c C-l a") 'sql-list-all)
1206 (define-key map (kbd "C-c C-l t") 'sql-list-table)
fbcc67e2
MM
1207 (define-key map [remap beginning-of-defun] 'sql-beginning-of-statement)
1208 (define-key map [remap end-of-defun] 'sql-end-of-statement)
95e4b2ef
RS
1209 map)
1210 "Mode map used for `sql-mode'.")
1211
1212;; easy menu for sql-mode.
1213
801d1cb0
AS
1214(easy-menu-define
1215 sql-mode-menu sql-mode-map
95e4b2ef 1216 "Menu for `sql-mode'."
55659495 1217 `("SQL"
9250002f 1218 ["Send Paragraph" sql-send-paragraph (sql-buffer-live-p sql-buffer)]
7492acc9 1219 ["Send Region" sql-send-region (and mark-active
9250002f
MM
1220 (sql-buffer-live-p sql-buffer))]
1221 ["Send Buffer" sql-send-buffer (sql-buffer-live-p sql-buffer)]
1222 ["Send String" sql-send-string (sql-buffer-live-p sql-buffer)]
d26b0ea9 1223 "--"
fbcc67e2
MM
1224 ["List all objects" sql-list-all (and (sql-buffer-live-p sql-buffer)
1225 (sql-get-product-feature sql-product :list-all))]
1226 ["List table details" sql-list-table (and (sql-buffer-live-p sql-buffer)
1227 (sql-get-product-feature sql-product :list-table))]
74790210 1228 "--"
d26b0ea9
MM
1229 ["Start SQLi session" sql-product-interactive
1230 :visible (not sql-connection-alist)
1231 :enable (sql-get-product-feature sql-product :sqli-comint-func)]
1232 ("Start..."
1233 :visible sql-connection-alist
1234 :filter sql-connection-menu-filter
1235 "--"
1236 ["New SQLi Session" sql-product-interactive (sql-get-product-feature sql-product :sqli-comint-func)])
1237 ["--"
1238 :visible sql-connection-alist]
dab100d7 1239 ["Show SQLi buffer" sql-show-sqli-buffer t]
c7055d66 1240 ["Set SQLi buffer" sql-set-sqli-buffer t]
801d1cb0 1241 ["Pop to SQLi buffer after send"
95e4b2ef
RS
1242 sql-toggle-pop-to-buffer-after-send-region
1243 :style toggle
624ef9b3 1244 :selected sql-pop-to-buffer-after-send-region]
78024f88
AS
1245 ["--" nil nil]
1246 ("Product"
55659495
SM
1247 ,@(mapcar (lambda (prod-info)
1248 (let* ((prod (pop prod-info))
1249 (name (or (plist-get prod-info :name)
1250 (capitalize (symbol-name prod))))
1251 (cmd (intern (format "sql-highlight-%s-keywords" prod))))
1252 (fset cmd `(lambda () ,(format "Highlight %s SQL keywords." name)
1253 (interactive)
1254 (sql-set-product ',prod)))
1255 (vector name cmd
1256 :style 'radio
1257 :selected `(eq sql-product ',prod))))
1258 sql-product-alist))))
95e4b2ef 1259
c7055d66
RS
1260;; easy menu for sql-interactive-mode.
1261
801d1cb0 1262(easy-menu-define
c7055d66
RS
1263 sql-interactive-mode-menu sql-interactive-mode-map
1264 "Menu for `sql-interactive-mode'."
1265 '("SQL"
d26b0ea9 1266 ["Rename Buffer" sql-rename-buffer t]
74790210
MM
1267 ["Save Connection" sql-save-connection (not sql-connection)]
1268 "--"
fbcc67e2
MM
1269 ["List all objects" sql-list-all (sql-get-product-feature sql-product :list-all)]
1270 ["List table details" sql-list-table (sql-get-product-feature sql-product :list-table)]))
c7055d66 1271
865fe16f
CY
1272;; Abbreviations -- if you want more of them, define them in your init
1273;; file. Abbrevs have to be enabled in your init file, too.
95e4b2ef 1274
93852cb0
SM
1275(define-abbrev-table 'sql-mode-abbrev-table
1276 '(("ins" "insert" nil nil t)
1277 ("upd" "update" nil nil t)
1278 ("del" "delete" nil nil t)
1279 ("sel" "select" nil nil t)
1280 ("proc" "procedure" nil nil t)
1281 ("func" "function" nil nil t)
1282 ("cr" "create" nil nil t))
95e4b2ef 1283 "Abbrev table used in `sql-mode' and `sql-interactive-mode'.")
95e4b2ef
RS
1284
1285;; Syntax Table
1286
801d1cb0 1287(defvar sql-mode-syntax-table
95e4b2ef
RS
1288 (let ((table (make-syntax-table)))
1289 ;; C-style comments /**/ (see elisp manual "Syntax Flags"))
1290 (modify-syntax-entry ?/ ". 14" table)
1291 (modify-syntax-entry ?* ". 23" table)
01295a22 1292 ;; double-dash starts comments
9a9069c9 1293 (modify-syntax-entry ?- ". 12b" table)
01295a22 1294 ;; newline and formfeed end comments
95e4b2ef
RS
1295 (modify-syntax-entry ?\n "> b" table)
1296 (modify-syntax-entry ?\f "> b" table)
01295a22 1297 ;; single quotes (') delimit strings
a081a529 1298 (modify-syntax-entry ?' "\"" table)
01295a22
RS
1299 ;; double quotes (") don't delimit strings
1300 (modify-syntax-entry ?\" "." table)
fbcc67e2
MM
1301 ;; Make these all punctuation
1302 (mapc (lambda (c) (modify-syntax-entry c "." table))
1303 (string-to-list "!#$%&+,.:;<=>?@\\|"))
95e4b2ef
RS
1304 table)
1305 "Syntax table used in `sql-mode' and `sql-interactive-mode'.")
1306
1307;; Font lock support
1308
78024f88 1309(defvar sql-mode-font-lock-object-name
01295a22
RS
1310 (eval-when-compile
1311 (list (concat "^\\s-*\\(?:create\\|drop\\|alter\\)\\s-+" ;; lead off with CREATE, DROP or ALTER
1312 "\\(?:\\w+\\s-+\\)*" ;; optional intervening keywords
1313 "\\(?:table\\|view\\|\\(?:package\\|type\\)\\(?:\\s-+body\\)?\\|proc\\(?:edure\\)?"
1314 "\\|function\\|trigger\\|sequence\\|rule\\|default\\)\\s-+"
21fa2482 1315 "\\(?:if\\s-+not\\s-+exists\\s-+\\)?" ;; IF NOT EXISTS
4586ce8a 1316 "\\(\\w+\\(?:\\s-*[.]\\s-*\\w+\\)*\\)")
01295a22 1317 1 'font-lock-function-name-face))
9fd8cb36
SM
1318
1319 "Pattern to match the names of top-level objects.
1320
1321The pattern matches the name in a CREATE, DROP or ALTER
1322statement. The format of variable should be a valid
1323`font-lock-keywords' entry.")
1324
7492acc9
MM
1325;; While there are international and American standards for SQL, they
1326;; are not followed closely, and most vendors offer significant
1327;; capabilities beyond those defined in the standard specifications.
1328
e4769531
PE
1329;; SQL mode provides support for highlighting based on the product. In
1330;; addition to highlighting the product keywords, any ANSI keywords not
1331;; used by the product are also highlighted. This will help identify
7492acc9
MM
1332;; keywords that could be restricted in future versions of the product
1333;; or might be a problem if ported to another product.
1334
1335;; To reduce the complexity and size of the regular expressions
1336;; generated to match keywords, ANSI keywords are filtered out of
1337;; product keywords if they are equivalent. To do this, we define a
1338;; function `sql-font-lock-keywords-builder' that removes any keywords
1339;; that are matched by the ANSI patterns and results in the same face
1340;; being applied. For this to work properly, we must play some games
1341;; with the execution and compile time behavior. This code is a
1342;; little tricky but works properly.
1343
1344;; When defining the keywords for individual products you should
1345;; include all of the keywords that you want matched. The filtering
1346;; against the ANSI keywords will be automatic if you use the
1347;; `sql-font-lock-keywords-builder' function and follow the
1348;; implementation pattern used for the other products in this file.
78024f88 1349
7492acc9
MM
1350(eval-when-compile
1351 (defvar sql-mode-ansi-font-lock-keywords)
1352 (setq sql-mode-ansi-font-lock-keywords nil))
1353
1354(eval-and-compile
1355 (defun sql-font-lock-keywords-builder (face boundaries &rest keywords)
1356 "Generation of regexp matching any one of KEYWORDS."
1357
1358 (let ((bdy (or boundaries '("\\b" . "\\b")))
1359 kwd)
1360
1361 ;; Remove keywords that are defined in ANSI
1362 (setq kwd keywords)
fbcc67e2
MM
1363 ;; (dolist (k keywords)
1364 ;; (catch 'next
1365 ;; (dolist (a sql-mode-ansi-font-lock-keywords)
1366 ;; (when (and (eq face (cdr a))
1367 ;; (eq (string-match (car a) k 0) 0)
1368 ;; (eq (match-end 0) (length k)))
1369 ;; (setq kwd (delq k kwd))
1370 ;; (throw 'next nil)))))
7492acc9
MM
1371
1372 ;; Create a properly formed font-lock-keywords item
1373 (cons (concat (car bdy)
1374 (regexp-opt kwd t)
1375 (cdr bdy))
fbcc67e2
MM
1376 face)))
1377
1378 (defun sql-regexp-abbrev (keyword)
1379 (let ((brk (string-match "[~]" keyword))
1380 (len (length keyword))
1381 (sep "\\(?:")
1382 re i)
1383 (if (not brk)
1384 keyword
1385 (setq re (substring keyword 0 brk)
1386 i (+ 2 brk)
1387 brk (1+ brk))
1388 (while (<= i len)
1389 (setq re (concat re sep (substring keyword brk i))
1390 sep "\\|"
1391 i (1+ i)))
1392 (concat re "\\)?"))))
1393
1394 (defun sql-regexp-abbrev-list (&rest keyw-list)
1395 (let ((re nil)
1396 (sep "\\<\\(?:"))
1397 (while keyw-list
1398 (setq re (concat re sep (sql-regexp-abbrev (car keyw-list)))
1399 sep "\\|"
1400 keyw-list (cdr keyw-list)))
1401 (concat re "\\)\\>"))))
9fd8cb36 1402
7492acc9
MM
1403(eval-when-compile
1404 (setq sql-mode-ansi-font-lock-keywords
1405 (list
1406 ;; ANSI Non Reserved keywords
1407 (sql-font-lock-keywords-builder 'font-lock-keyword-face nil
9fd8cb36
SM
1408"ada" "asensitive" "assignment" "asymmetric" "atomic" "between"
1409"bitvar" "called" "catalog_name" "chain" "character_set_catalog"
1410"character_set_name" "character_set_schema" "checked" "class_origin"
1411"cobol" "collation_catalog" "collation_name" "collation_schema"
1412"column_name" "command_function" "command_function_code" "committed"
1413"condition_number" "connection_name" "constraint_catalog"
1414"constraint_name" "constraint_schema" "contains" "cursor_name"
1415"datetime_interval_code" "datetime_interval_precision" "defined"
1416"definer" "dispatch" "dynamic_function" "dynamic_function_code"
1417"existing" "exists" "final" "fortran" "generated" "granted"
1418"hierarchy" "hold" "implementation" "infix" "insensitive" "instance"
1419"instantiable" "invoker" "key_member" "key_type" "length" "m"
1420"message_length" "message_octet_length" "message_text" "method" "more"
1421"mumps" "name" "nullable" "number" "options" "overlaps" "overriding"
1422"parameter_mode" "parameter_name" "parameter_ordinal_position"
1423"parameter_specific_catalog" "parameter_specific_name"
1424"parameter_specific_schema" "pascal" "pli" "position" "repeatable"
1425"returned_length" "returned_octet_length" "returned_sqlstate"
1426"routine_catalog" "routine_name" "routine_schema" "row_count" "scale"
1427"schema_name" "security" "self" "sensitive" "serializable"
1428"server_name" "similar" "simple" "source" "specific_name" "style"
1429"subclass_origin" "sublist" "symmetric" "system" "table_name"
1430"transaction_active" "transactions_committed"
1431"transactions_rolled_back" "transform" "transforms" "trigger_catalog"
1432"trigger_name" "trigger_schema" "type" "uncommitted" "unnamed"
1433"user_defined_type_catalog" "user_defined_type_name"
1434"user_defined_type_schema"
7492acc9 1435)
fbcc67e2 1436
7492acc9
MM
1437 ;; ANSI Reserved keywords
1438 (sql-font-lock-keywords-builder 'font-lock-keyword-face nil
9fd8cb36
SM
1439"absolute" "action" "add" "admin" "after" "aggregate" "alias" "all"
1440"allocate" "alter" "and" "any" "are" "as" "asc" "assertion" "at"
1441"authorization" "before" "begin" "both" "breadth" "by" "call"
1442"cascade" "cascaded" "case" "catalog" "check" "class" "close"
1443"collate" "collation" "column" "commit" "completion" "connect"
1444"connection" "constraint" "constraints" "constructor" "continue"
1445"corresponding" "create" "cross" "cube" "current" "cursor" "cycle"
1446"data" "day" "deallocate" "declare" "default" "deferrable" "deferred"
1447"delete" "depth" "deref" "desc" "describe" "descriptor" "destroy"
1448"destructor" "deterministic" "diagnostics" "dictionary" "disconnect"
1449"distinct" "domain" "drop" "dynamic" "each" "else" "end" "equals"
1450"escape" "every" "except" "exception" "exec" "execute" "external"
1451"false" "fetch" "first" "for" "foreign" "found" "free" "from" "full"
1452"function" "general" "get" "global" "go" "goto" "grant" "group"
1453"grouping" "having" "host" "hour" "identity" "ignore" "immediate" "in"
1454"indicator" "initialize" "initially" "inner" "inout" "input" "insert"
1455"intersect" "into" "is" "isolation" "iterate" "join" "key" "language"
1456"last" "lateral" "leading" "left" "less" "level" "like" "limit"
1457"local" "locator" "map" "match" "minute" "modifies" "modify" "module"
1458"month" "names" "natural" "new" "next" "no" "none" "not" "null" "of"
1459"off" "old" "on" "only" "open" "operation" "option" "or" "order"
1460"ordinality" "out" "outer" "output" "pad" "parameter" "parameters"
1461"partial" "path" "postfix" "prefix" "preorder" "prepare" "preserve"
1462"primary" "prior" "privileges" "procedure" "public" "read" "reads"
1463"recursive" "references" "referencing" "relative" "restrict" "result"
1464"return" "returns" "revoke" "right" "role" "rollback" "rollup"
1465"routine" "rows" "savepoint" "schema" "scroll" "search" "second"
1466"section" "select" "sequence" "session" "set" "sets" "size" "some"
1467"space" "specific" "specifictype" "sql" "sqlexception" "sqlstate"
1468"sqlwarning" "start" "state" "statement" "static" "structure" "table"
1469"temporary" "terminate" "than" "then" "timezone_hour"
1470"timezone_minute" "to" "trailing" "transaction" "translation"
1471"trigger" "true" "under" "union" "unique" "unknown" "unnest" "update"
1472"usage" "using" "value" "values" "variable" "view" "when" "whenever"
1473"where" "with" "without" "work" "write" "year"
7492acc9 1474)
9fd8cb36 1475
7492acc9
MM
1476 ;; ANSI Functions
1477 (sql-font-lock-keywords-builder 'font-lock-builtin-face nil
1478"abs" "avg" "bit_length" "cardinality" "cast" "char_length"
1479"character_length" "coalesce" "convert" "count" "current_date"
1480"current_path" "current_role" "current_time" "current_timestamp"
1481"current_user" "extract" "localtime" "localtimestamp" "lower" "max"
1482"min" "mod" "nullif" "octet_length" "overlay" "placing" "session_user"
1483"substring" "sum" "system_user" "translate" "treat" "trim" "upper"
1484"user"
1485)
fbcc67e2 1486
7492acc9
MM
1487 ;; ANSI Data Types
1488 (sql-font-lock-keywords-builder 'font-lock-type-face nil
9fd8cb36
SM
1489"array" "binary" "bit" "blob" "boolean" "char" "character" "clob"
1490"date" "dec" "decimal" "double" "float" "int" "integer" "interval"
1491"large" "national" "nchar" "nclob" "numeric" "object" "precision"
1492"real" "ref" "row" "scope" "smallint" "time" "timestamp" "varchar"
1493"varying" "zone"
7492acc9 1494))))
95e4b2ef 1495
7492acc9
MM
1496(defvar sql-mode-ansi-font-lock-keywords
1497 (eval-when-compile sql-mode-ansi-font-lock-keywords)
78024f88 1498 "ANSI SQL keywords used by font-lock.
95e4b2ef
RS
1499
1500This variable is used by `sql-mode' and `sql-interactive-mode'. The
1501regular expressions are created during compilation by calling the
1502function `regexp-opt'. Therefore, take a look at the source before
063c6324
JB
1503you define your own `sql-mode-ansi-font-lock-keywords'. You may want
1504to add functions and PL/SQL keywords.")
78024f88 1505
93852cb0 1506(defun sql--oracle-show-reserved-words ()
fbcc67e2 1507 ;; This function is for use by the maintainer of SQL.EL only.
fbcc67e2
MM
1508 (if (or (and (not (derived-mode-p 'sql-mode))
1509 (not (derived-mode-p 'sql-interactive-mode)))
1510 (not sql-buffer)
1511 (not (eq sql-product 'oracle)))
1512 (error "Not an Oracle buffer")
1513
1514 (let ((b "*RESERVED WORDS*"))
1515 (sql-execute sql-buffer b
1516 (concat "SELECT "
1517 " keyword "
1518 ", reserved AS \"Res\" "
1519 ", res_type AS \"Type\" "
1520 ", res_attr AS \"Attr\" "
1521 ", res_semi AS \"Semi\" "
1522 ", duplicate AS \"Dup\" "
1523 "FROM V$RESERVED_WORDS "
1524 "WHERE length > 1 "
1525 "AND SUBSTR(keyword, 1, 1) BETWEEN 'A' AND 'Z' "
1526 "ORDER BY 2 DESC, 3 DESC, 4 DESC, 5 DESC, 6 DESC, 1;")
1527 nil nil)
1528 (with-current-buffer b
1529 (set (make-local-variable 'sql-product) 'oracle)
1530 (sql-product-font-lock t nil)
1531 (font-lock-mode +1)))))
1532
78024f88 1533(defvar sql-mode-oracle-font-lock-keywords
7492acc9
MM
1534 (eval-when-compile
1535 (list
1536 ;; Oracle SQL*Plus Commands
fbcc67e2
MM
1537 ;; Only recognized in they start in column 1 and the
1538 ;; abbreviation is followed by a space or the end of line.
7492acc9 1539
fbcc67e2
MM
1540 "\\|"
1541 (list (concat "^" (sql-regexp-abbrev "rem~ark") "\\(?:\\s-.*\\)?$")
1542 0 'font-lock-comment-face t)
1543
1544 (list
1545 (concat
1546 "^\\(?:"
1547 (sql-regexp-abbrev-list
1548 "[@]\\{1,2\\}" "acc~ept" "a~ppend" "archive" "attribute"
1549 "bre~ak" "bti~tle" "c~hange" "cl~ear" "col~umn" "conn~ect"
1550 "copy" "def~ine" "del" "desc~ribe" "disc~onnect" "ed~it"
1551 "exec~ute" "exit" "get" "help" "ho~st" "[$]" "i~nput" "l~ist"
1552 "passw~ord" "pau~se" "pri~nt" "pro~mpt" "quit" "recover"
1553 "repf~ooter" "reph~eader" "r~un" "sav~e" "sho~w" "shutdown"
1554 "spo~ol" "sta~rt" "startup" "store" "tim~ing" "tti~tle"
1555 "undef~ine" "var~iable" "whenever")
1556 "\\|"
1557 (concat "\\(?:"
1558 (sql-regexp-abbrev "comp~ute")
1559 "\\s-+"
1560 (sql-regexp-abbrev-list
1561 "avg" "cou~nt" "min~imum" "max~imum" "num~ber" "sum"
1562 "std" "var~iance")
1563 "\\)")
1564 "\\|"
1565 (concat "\\(?:set\\s-+"
1566 (sql-regexp-abbrev-list
1567 "appi~nfo" "array~size" "auto~commit" "autop~rint"
1568 "autorecovery" "autot~race" "blo~ckterminator"
1569 "cmds~ep" "colsep" "com~patibility" "con~cat"
1570 "copyc~ommit" "copytypecheck" "def~ine" "describe"
1571 "echo" "editf~ile" "emb~edded" "esc~ape" "feed~back"
1572 "flagger" "flu~sh" "hea~ding" "heads~ep" "instance"
1573 "lin~esize" "lobof~fset" "long" "longc~hunksize"
1574 "mark~up" "newp~age" "null" "numf~ormat" "num~width"
1575 "pages~ize" "pau~se" "recsep" "recsepchar"
1576 "scan" "serverout~put" "shift~inout" "show~mode"
1577 "sqlbl~anklines" "sqlc~ase" "sqlco~ntinue"
1578 "sqln~umber" "sqlpluscompat~ibility" "sqlpre~fix"
1579 "sqlp~rompt" "sqlt~erminator" "suf~fix" "tab"
1580 "term~out" "ti~me" "timi~ng" "trim~out" "trims~pool"
1581 "und~erline" "ver~ify" "wra~p")
1582 "\\)")
1583
1584 "\\)\\(?:\\s-.*\\)?\\(?:[-]\n.*\\)*$")
1585 0 'font-lock-doc-face t)
7492acc9
MM
1586
1587 ;; Oracle Functions
1588 (sql-font-lock-keywords-builder 'font-lock-builtin-face nil
fbcc67e2
MM
1589"abs" "acos" "add_months" "appendchildxml" "ascii" "asciistr" "asin"
1590"atan" "atan2" "avg" "bfilename" "bin_to_num" "bitand" "cardinality"
1591"cast" "ceil" "chartorowid" "chr" "cluster_id" "cluster_probability"
1592"cluster_set" "coalesce" "collect" "compose" "concat" "convert" "corr"
bb5aa5d6 1593"connect_by_root" "connect_by_iscycle" "connect_by_isleaf"
fbcc67e2 1594"corr_k" "corr_s" "cos" "cosh" "count" "covar_pop" "covar_samp"
c7015153 1595"cube_table" "cume_dist" "current_date" "current_timestamp" "cv"
fbcc67e2
MM
1596"dataobj_to_partition" "dbtimezone" "decode" "decompose" "deletexml"
1597"dense_rank" "depth" "deref" "dump" "empty_blob" "empty_clob"
1598"existsnode" "exp" "extract" "extractvalue" "feature_id" "feature_set"
1599"feature_value" "first" "first_value" "floor" "from_tz" "greatest"
1600"grouping" "grouping_id" "group_id" "hextoraw" "initcap"
1601"insertchildxml" "insertchildxmlafter" "insertchildxmlbefore"
1602"insertxmlafter" "insertxmlbefore" "instr" "instr2" "instr4" "instrb"
1603"instrc" "iteration_number" "lag" "last" "last_day" "last_value"
1604"lead" "least" "length" "length2" "length4" "lengthb" "lengthc"
1605"listagg" "ln" "lnnvl" "localtimestamp" "log" "lower" "lpad" "ltrim"
1606"make_ref" "max" "median" "min" "mod" "months_between" "nanvl" "nchr"
1607"new_time" "next_day" "nlssort" "nls_charset_decl_len"
9fd8cb36 1608"nls_charset_id" "nls_charset_name" "nls_initcap" "nls_lower"
fbcc67e2
MM
1609"nls_upper" "nth_value" "ntile" "nullif" "numtodsinterval"
1610"numtoyminterval" "nvl" "nvl2" "ora_dst_affected" "ora_dst_convert"
1611"ora_dst_error" "ora_hash" "path" "percentile_cont" "percentile_disc"
1612"percent_rank" "power" "powermultiset" "powermultiset_by_cardinality"
1613"prediction" "prediction_bounds" "prediction_cost"
1614"prediction_details" "prediction_probability" "prediction_set"
1615"presentnnv" "presentv" "previous" "rank" "ratio_to_report" "rawtohex"
1616"rawtonhex" "ref" "reftohex" "regexp_count" "regexp_instr"
1617"regexp_replace" "regexp_substr" "regr_avgx" "regr_avgy" "regr_count"
1618"regr_intercept" "regr_r2" "regr_slope" "regr_sxx" "regr_sxy"
1619"regr_syy" "remainder" "replace" "round" "rowidtochar" "rowidtonchar"
1620"row_number" "rpad" "rtrim" "scn_to_timestamp" "sessiontimezone" "set"
1621"sign" "sin" "sinh" "soundex" "sqrt" "stats_binomial_test"
1622"stats_crosstab" "stats_f_test" "stats_ks_test" "stats_mode"
1623"stats_mw_test" "stats_one_way_anova" "stats_t_test_indep"
1624"stats_t_test_indepu" "stats_t_test_one" "stats_t_test_paired"
1625"stats_wsr_test" "stddev" "stddev_pop" "stddev_samp" "substr"
1626"substr2" "substr4" "substrb" "substrc" "sum" "sysdate" "systimestamp"
1627"sys_connect_by_path" "sys_context" "sys_dburigen" "sys_extract_utc"
1628"sys_guid" "sys_typeid" "sys_xmlagg" "sys_xmlgen" "tan" "tanh"
1629"timestamp_to_scn" "to_binary_double" "to_binary_float" "to_blob"
9fd8cb36
SM
1630"to_char" "to_clob" "to_date" "to_dsinterval" "to_lob" "to_multi_byte"
1631"to_nchar" "to_nclob" "to_number" "to_single_byte" "to_timestamp"
1632"to_timestamp_tz" "to_yminterval" "translate" "treat" "trim" "trunc"
fbcc67e2
MM
1633"tz_offset" "uid" "unistr" "updatexml" "upper" "user" "userenv"
1634"value" "variance" "var_pop" "var_samp" "vsize" "width_bucket"
1635"xmlagg" "xmlcast" "xmlcdata" "xmlcolattval" "xmlcomment" "xmlconcat"
1636"xmldiff" "xmlelement" "xmlexists" "xmlforest" "xmlisvalid" "xmlparse"
1637"xmlpatch" "xmlpi" "xmlquery" "xmlroot" "xmlsequence" "xmlserialize"
1638"xmltable" "xmltransform"
7492acc9 1639)
fbcc67e2
MM
1640
1641 ;; See the table V$RESERVED_WORDS
7492acc9
MM
1642 ;; Oracle Keywords
1643 (sql-font-lock-keywords-builder 'font-lock-keyword-face nil
9fd8cb36
SM
1644"abort" "access" "accessed" "account" "activate" "add" "admin"
1645"advise" "after" "agent" "aggregate" "all" "allocate" "allow" "alter"
1646"always" "analyze" "ancillary" "and" "any" "apply" "archive"
1647"archivelog" "array" "as" "asc" "associate" "at" "attribute"
1648"attributes" "audit" "authenticated" "authid" "authorization" "auto"
1649"autoallocate" "automatic" "availability" "backup" "before" "begin"
1650"behalf" "between" "binding" "bitmap" "block" "blocksize" "body"
1651"both" "buffer_pool" "build" "by" "cache" "call" "cancel"
1652"cascade" "case" "category" "certificate" "chained" "change" "check"
1653"checkpoint" "child" "chunk" "class" "clear" "clone" "close" "cluster"
1654"column" "column_value" "columns" "comment" "commit" "committed"
1655"compatibility" "compile" "complete" "composite_limit" "compress"
1656"compute" "connect" "connect_time" "consider" "consistent"
1657"constraint" "constraints" "constructor" "contents" "context"
1658"continue" "controlfile" "corruption" "cost" "cpu_per_call"
1659"cpu_per_session" "create" "cross" "cube" "current" "currval" "cycle"
1660"dangling" "data" "database" "datafile" "datafiles" "day" "ddl"
1661"deallocate" "debug" "default" "deferrable" "deferred" "definer"
1662"delay" "delete" "demand" "desc" "determines" "deterministic"
1663"dictionary" "dimension" "directory" "disable" "disassociate"
1664"disconnect" "distinct" "distinguished" "distributed" "dml" "drop"
1665"each" "element" "else" "enable" "end" "equals_path" "escape"
1666"estimate" "except" "exceptions" "exchange" "excluding" "exists"
1667"expire" "explain" "extent" "external" "externally"
1668"failed_login_attempts" "fast" "file" "final" "finish" "flush" "for"
1669"force" "foreign" "freelist" "freelists" "freepools" "fresh" "from"
1670"full" "function" "functions" "generated" "global" "global_name"
1671"globally" "grant" "group" "grouping" "groups" "guard" "hash"
1672"hashkeys" "having" "heap" "hierarchy" "id" "identified" "identifier"
1673"idle_time" "immediate" "in" "including" "increment" "index" "indexed"
1674"indexes" "indextype" "indextypes" "indicator" "initial" "initialized"
1675"initially" "initrans" "inner" "insert" "instance" "instantiable"
1676"instead" "intersect" "into" "invalidate" "is" "isolation" "java"
1677"join" "keep" "key" "kill" "language" "left" "less" "level"
1678"levels" "library" "like" "like2" "like4" "likec" "limit" "link"
1679"list" "lob" "local" "location" "locator" "lock" "log" "logfile"
1680"logging" "logical" "logical_reads_per_call"
1681"logical_reads_per_session" "managed" "management" "manual" "map"
1682"mapping" "master" "matched" "materialized" "maxdatafiles"
1683"maxextents" "maximize" "maxinstances" "maxlogfiles" "maxloghistory"
1684"maxlogmembers" "maxsize" "maxtrans" "maxvalue" "member" "memory"
1685"merge" "migrate" "minextents" "minimize" "minimum" "minus" "minvalue"
1686"mode" "modify" "monitoring" "month" "mount" "move" "movement" "name"
1687"named" "natural" "nested" "never" "new" "next" "nextval" "no"
1688"noarchivelog" "noaudit" "nocache" "nocompress" "nocopy" "nocycle"
1689"nodelay" "noforce" "nologging" "nomapping" "nomaxvalue" "nominimize"
1690"nominvalue" "nomonitoring" "none" "noorder" "noparallel" "norely"
1691"noresetlogs" "noreverse" "normal" "norowdependencies" "nosort"
1692"noswitch" "not" "nothing" "notimeout" "novalidate" "nowait" "null"
1693"nulls" "object" "of" "off" "offline" "oidindex" "old" "on" "online"
1694"only" "open" "operator" "optimal" "option" "or" "order"
1695"organization" "out" "outer" "outline" "overflow" "overriding"
1696"package" "packages" "parallel" "parallel_enable" "parameters"
1697"parent" "partition" "partitions" "password" "password_grace_time"
1698"password_life_time" "password_lock_time" "password_reuse_max"
1699"password_reuse_time" "password_verify_function" "pctfree"
1700"pctincrease" "pctthreshold" "pctused" "pctversion" "percent"
1701"performance" "permanent" "pfile" "physical" "pipelined" "plan"
1702"post_transaction" "pragma" "prebuilt" "preserve" "primary" "private"
1703"private_sga" "privileges" "procedure" "profile" "protection" "public"
1704"purge" "query" "quiesce" "quota" "range" "read" "reads" "rebuild"
1705"records_per_block" "recover" "recovery" "recycle" "reduced" "ref"
1706"references" "referencing" "refresh" "register" "reject" "relational"
1707"rely" "rename" "reset" "resetlogs" "resize" "resolve" "resolver"
1708"resource" "restrict" "restrict_references" "restricted" "result"
1709"resumable" "resume" "retention" "return" "returning" "reuse"
1710"reverse" "revoke" "rewrite" "right" "rnds" "rnps" "role" "roles"
1711"rollback" "rollup" "row" "rowdependencies" "rownum" "rows" "sample"
1712"savepoint" "scan" "schema" "scn" "scope" "segment" "select"
1713"selectivity" "self" "sequence" "serializable" "session"
1714"sessions_per_user" "set" "sets" "settings" "shared" "shared_pool"
1715"shrink" "shutdown" "siblings" "sid" "single" "size" "skip" "some"
1716"sort" "source" "space" "specification" "spfile" "split" "standby"
1717"start" "statement_id" "static" "statistics" "stop" "storage" "store"
1718"structure" "subpartition" "subpartitions" "substitutable"
1719"successful" "supplemental" "suspend" "switch" "switchover" "synonym"
1720"sys" "system" "table" "tables" "tablespace" "tempfile" "template"
1721"temporary" "test" "than" "then" "thread" "through" "time_zone"
1722"timeout" "to" "trace" "transaction" "trigger" "triggers" "truncate"
1723"trust" "type" "types" "unarchived" "under" "under_path" "undo"
1724"uniform" "union" "unique" "unlimited" "unlock" "unquiesce"
1725"unrecoverable" "until" "unusable" "unused" "update" "upgrade" "usage"
1726"use" "using" "validate" "validation" "value" "values" "variable"
1727"varray" "version" "view" "wait" "when" "whenever" "where" "with"
1728"without" "wnds" "wnps" "work" "write" "xmldata" "xmlschema" "xmltype"
7492acc9 1729)
fbcc67e2 1730
7492acc9
MM
1731 ;; Oracle Data Types
1732 (sql-font-lock-keywords-builder 'font-lock-type-face nil
fbcc67e2
MM
1733"bfile" "binary_double" "binary_float" "blob" "byte" "char" "charbyte"
1734"clob" "date" "day" "float" "interval" "local" "long" "longraw"
1735"minute" "month" "nchar" "nclob" "number" "nvarchar2" "raw" "rowid" "second"
1736"time" "timestamp" "urowid" "varchar2" "with" "year" "zone"
7492acc9 1737)
9fd8cb36 1738
7492acc9 1739 ;; Oracle PL/SQL Attributes
fbcc67e2
MM
1740 (sql-font-lock-keywords-builder 'font-lock-builtin-face '("%" . "\\b")
1741"bulk_exceptions" "bulk_rowcount" "found" "isopen" "notfound"
1742"rowcount" "rowtype" "type"
7492acc9
MM
1743)
1744
1745 ;; Oracle PL/SQL Functions
1746 (sql-font-lock-keywords-builder 'font-lock-builtin-face nil
fbcc67e2
MM
1747"delete" "trim" "extend" "exists" "first" "last" "count" "limit"
1748"prior" "next"
1749)
1750
1751 ;; Oracle PL/SQL Reserved words
1752 (sql-font-lock-keywords-builder 'font-lock-keyword-face nil
1753"all" "alter" "and" "any" "as" "asc" "at" "begin" "between" "by"
1754"case" "check" "clusters" "cluster" "colauth" "columns" "compress"
1755"connect" "crash" "create" "cursor" "declare" "default" "desc"
1756"distinct" "drop" "else" "end" "exception" "exclusive" "fetch" "for"
1757"from" "function" "goto" "grant" "group" "having" "identified" "if"
1758"in" "index" "indexes" "insert" "intersect" "into" "is" "like" "lock"
1759"minus" "mode" "nocompress" "not" "nowait" "null" "of" "on" "option"
1760"or" "order" "overlaps" "procedure" "public" "resource" "revoke"
1761"select" "share" "size" "sql" "start" "subtype" "tabauth" "table"
1762"then" "to" "type" "union" "unique" "update" "values" "view" "views"
1763"when" "where" "with"
1764
1765"true" "false"
1766"raise_application_error"
7492acc9 1767)
9fd8cb36 1768
7492acc9
MM
1769 ;; Oracle PL/SQL Keywords
1770 (sql-font-lock-keywords-builder 'font-lock-keyword-face nil
fbcc67e2
MM
1771"a" "add" "agent" "aggregate" "array" "attribute" "authid" "avg"
1772"bfile_base" "binary" "blob_base" "block" "body" "both" "bound" "bulk"
1773"byte" "c" "call" "calling" "cascade" "char" "char_base" "character"
1774"charset" "charsetform" "charsetid" "clob_base" "close" "collect"
1775"comment" "commit" "committed" "compiled" "constant" "constructor"
1776"context" "continue" "convert" "count" "current" "customdatum"
1777"dangling" "data" "date" "date_base" "day" "define" "delete"
1778"deterministic" "double" "duration" "element" "elsif" "empty" "escape"
1779"except" "exceptions" "execute" "exists" "exit" "external" "final"
1780"fixed" "float" "forall" "force" "general" "hash" "heap" "hidden"
1781"hour" "immediate" "including" "indicator" "indices" "infinite"
1782"instantiable" "int" "interface" "interval" "invalidate" "isolation"
1783"java" "language" "large" "leading" "length" "level" "library" "like2"
1784"like4" "likec" "limit" "limited" "local" "long" "loop" "map" "max"
1785"maxlen" "member" "merge" "min" "minute" "mod" "modify" "month"
1786"multiset" "name" "nan" "national" "native" "nchar" "new" "nocopy"
1787"number_base" "object" "ocicoll" "ocidate" "ocidatetime" "ociduration"
1788"ociinterval" "ociloblocator" "ocinumber" "ociraw" "ociref"
1789"ocirefcursor" "ocirowid" "ocistring" "ocitype" "old" "only" "opaque"
1790"open" "operator" "oracle" "oradata" "organization" "orlany" "orlvary"
1791"others" "out" "overriding" "package" "parallel_enable" "parameter"
1792"parameters" "parent" "partition" "pascal" "pipe" "pipelined" "pragma"
1793"precision" "prior" "private" "raise" "range" "raw" "read" "record"
1794"ref" "reference" "relies_on" "rem" "remainder" "rename" "result"
1795"result_cache" "return" "returning" "reverse" "rollback" "row"
1796"sample" "save" "savepoint" "sb1" "sb2" "sb4" "second" "segment"
1797"self" "separate" "sequence" "serializable" "set" "short" "size_t"
1798"some" "sparse" "sqlcode" "sqldata" "sqlname" "sqlstate" "standard"
1799"static" "stddev" "stored" "string" "struct" "style" "submultiset"
1800"subpartition" "substitutable" "sum" "synonym" "tdo" "the" "time"
1801"timestamp" "timezone_abbr" "timezone_hour" "timezone_minute"
1802"timezone_region" "trailing" "transaction" "transactional" "trusted"
1803"ub1" "ub2" "ub4" "under" "unsigned" "untrusted" "use" "using"
1804"valist" "value" "variable" "variance" "varray" "varying" "void"
1805"while" "work" "wrapped" "write" "year" "zone"
1806;; Pragma
1807"autonomous_transaction" "exception_init" "inline"
1808"restrict_references" "serially_reusable"
7492acc9 1809)
9fd8cb36 1810
7492acc9
MM
1811 ;; Oracle PL/SQL Data Types
1812 (sql-font-lock-keywords-builder 'font-lock-type-face nil
fbcc67e2
MM
1813"\"BINARY LARGE OBJECT\"" "\"CHAR LARGE OBJECT\"" "\"CHAR VARYING\""
1814"\"CHARACTER LARGE OBJECT\"" "\"CHARACTER VARYING\""
1815"\"DOUBLE PRECISION\"" "\"INTERVAL DAY TO SECOND\""
1816"\"INTERVAL YEAR TO MONTH\"" "\"LONG RAW\"" "\"NATIONAL CHAR\""
1817"\"NATIONAL CHARACTER LARGE OBJECT\"" "\"NATIONAL CHARACTER\""
1818"\"NCHAR LARGE OBJECT\"" "\"NCHAR\"" "\"NCLOB\"" "\"NVARCHAR2\""
1819"\"TIME WITH TIME ZONE\"" "\"TIMESTAMP WITH LOCAL TIME ZONE\""
1820"\"TIMESTAMP WITH TIME ZONE\""
1821"bfile" "bfile_base" "binary_double" "binary_float" "binary_integer"
1822"blob" "blob_base" "boolean" "char" "character" "char_base" "clob"
1823"clob_base" "cursor" "date" "day" "dec" "decimal"
1824"dsinterval_unconstrained" "float" "int" "integer" "interval" "local"
1825"long" "mlslabel" "month" "natural" "naturaln" "nchar_cs" "number"
1826"number_base" "numeric" "pls_integer" "positive" "positiven" "raw"
1827"real" "ref" "rowid" "second" "signtype" "simple_double"
1828"simple_float" "simple_integer" "smallint" "string" "time" "timestamp"
1829"timestamp_ltz_unconstrained" "timestamp_tz_unconstrained"
1830"timestamp_unconstrained" "time_tz_unconstrained" "time_unconstrained"
1831"to" "urowid" "varchar" "varchar2" "with" "year"
1832"yminterval_unconstrained" "zone"
7492acc9 1833)
9fd8cb36 1834
7492acc9
MM
1835 ;; Oracle PL/SQL Exceptions
1836 (sql-font-lock-keywords-builder 'font-lock-warning-face nil
78024f88
AS
1837"access_into_null" "case_not_found" "collection_is_null"
1838"cursor_already_open" "dup_val_on_index" "invalid_cursor"
fbcc67e2
MM
1839"invalid_number" "login_denied" "no_data_found" "no_data_needed"
1840"not_logged_on" "program_error" "rowtype_mismatch" "self_is_null"
1841"storage_error" "subscript_beyond_count" "subscript_outside_limit"
1842"sys_invalid_rowid" "timeout_on_resource" "too_many_rows"
1843"value_error" "zero_divide"
7492acc9 1844)))
95e4b2ef 1845
78024f88 1846 "Oracle SQL keywords used by font-lock.
95e4b2ef
RS
1847
1848This variable is used by `sql-mode' and `sql-interactive-mode'. The
1849regular expressions are created during compilation by calling the
1850function `regexp-opt'. Therefore, take a look at the source before
063c6324 1851you define your own `sql-mode-oracle-font-lock-keywords'. You may want
78024f88 1852to add functions and PL/SQL keywords.")
95e4b2ef 1853
78024f88 1854(defvar sql-mode-postgres-font-lock-keywords
7492acc9
MM
1855 (eval-when-compile
1856 (list
9250002f
MM
1857 ;; Postgres psql commands
1858 '("^\\s-*\\\\.*$" . font-lock-doc-face)
1859
1860 ;; Postgres unreserved words but may have meaning
1861 (sql-font-lock-keywords-builder 'font-lock-builtin-face nil "a"
1862"abs" "absent" "according" "ada" "alias" "allocate" "are" "array_agg"
1863"asensitive" "atomic" "attribute" "attributes" "avg" "base64"
1864"bernoulli" "bit_length" "bitvar" "blob" "blocked" "bom" "breadth" "c"
1865"call" "cardinality" "catalog_name" "ceil" "ceiling" "char_length"
1866"character_length" "character_set_catalog" "character_set_name"
1867"character_set_schema" "characters" "checked" "class_origin" "clob"
1868"cobol" "collation" "collation_catalog" "collation_name"
1869"collation_schema" "collect" "column_name" "columns"
1870"command_function" "command_function_code" "completion" "condition"
1871"condition_number" "connect" "connection_name" "constraint_catalog"
1872"constraint_name" "constraint_schema" "constructor" "contains"
1873"control" "convert" "corr" "corresponding" "count" "covar_pop"
1874"covar_samp" "cube" "cume_dist" "current_default_transform_group"
1875"current_path" "current_transform_group_for_type" "cursor_name"
1876"datalink" "datetime_interval_code" "datetime_interval_precision" "db"
1877"defined" "degree" "dense_rank" "depth" "deref" "derived" "describe"
1878"descriptor" "destroy" "destructor" "deterministic" "diagnostics"
1879"disconnect" "dispatch" "dlnewcopy" "dlpreviouscopy" "dlurlcomplete"
1880"dlurlcompleteonly" "dlurlcompletewrite" "dlurlpath" "dlurlpathonly"
1881"dlurlpathwrite" "dlurlscheme" "dlurlserver" "dlvalue" "dynamic"
1882"dynamic_function" "dynamic_function_code" "element" "empty"
1883"end-exec" "equals" "every" "exception" "exec" "existing" "exp" "file"
1884"filter" "final" "first_value" "flag" "floor" "fortran" "found" "free"
1885"fs" "fusion" "g" "general" "generated" "get" "go" "goto" "grouping"
1886"hex" "hierarchy" "host" "id" "ignore" "implementation" "import"
1887"indent" "indicator" "infix" "initialize" "instance" "instantiable"
1888"integrity" "intersection" "iterate" "k" "key_member" "key_type" "lag"
1889"last_value" "lateral" "lead" "length" "less" "library" "like_regex"
1890"link" "ln" "locator" "lower" "m" "map" "matched" "max"
1891"max_cardinality" "member" "merge" "message_length"
1892"message_octet_length" "message_text" "method" "min" "mod" "modifies"
1893"modify" "module" "more" "multiset" "mumps" "namespace" "nclob"
1894"nesting" "new" "nfc" "nfd" "nfkc" "nfkd" "nil" "normalize"
1895"normalized" "nth_value" "ntile" "nullable" "number"
1896"occurrences_regex" "octet_length" "octets" "old" "open" "operation"
1897"ordering" "ordinality" "others" "output" "overriding" "p" "pad"
1898"parameter" "parameter_mode" "parameter_name"
1899"parameter_ordinal_position" "parameter_specific_catalog"
1900"parameter_specific_name" "parameter_specific_schema" "parameters"
1901"pascal" "passing" "passthrough" "percent_rank" "percentile_cont"
1902"percentile_disc" "permission" "pli" "position_regex" "postfix"
1903"power" "prefix" "preorder" "public" "rank" "reads" "recovery" "ref"
1904"referencing" "regr_avgx" "regr_avgy" "regr_count" "regr_intercept"
1905"regr_r2" "regr_slope" "regr_sxx" "regr_sxy" "regr_syy" "requiring"
1906"respect" "restore" "result" "return" "returned_cardinality"
1907"returned_length" "returned_octet_length" "returned_sqlstate" "rollup"
1908"routine" "routine_catalog" "routine_name" "routine_schema"
1909"row_count" "row_number" "scale" "schema_name" "scope" "scope_catalog"
1910"scope_name" "scope_schema" "section" "selective" "self" "sensitive"
1911"server_name" "sets" "size" "source" "space" "specific"
1912"specific_name" "specifictype" "sql" "sqlcode" "sqlerror"
1913"sqlexception" "sqlstate" "sqlwarning" "sqrt" "state" "static"
1914"stddev_pop" "stddev_samp" "structure" "style" "subclass_origin"
1915"sublist" "submultiset" "substring_regex" "sum" "system_user" "t"
1916"table_name" "tablesample" "terminate" "than" "ties" "timezone_hour"
1917"timezone_minute" "token" "top_level_count" "transaction_active"
1918"transactions_committed" "transactions_rolled_back" "transform"
1919"transforms" "translate" "translate_regex" "translation"
1920"trigger_catalog" "trigger_name" "trigger_schema" "trim_array"
1921"uescape" "under" "unlink" "unnamed" "unnest" "untyped" "upper" "uri"
1922"usage" "user_defined_type_catalog" "user_defined_type_code"
1923"user_defined_type_name" "user_defined_type_schema" "var_pop"
1924"var_samp" "varbinary" "variable" "whenever" "width_bucket" "within"
1925"xmlagg" "xmlbinary" "xmlcast" "xmlcomment" "xmldeclaration"
1926"xmldocument" "xmlexists" "xmliterate" "xmlnamespaces" "xmlquery"
1927"xmlschema" "xmltable" "xmltext" "xmlvalidate"
1928)
1929
1930 ;; Postgres non-reserved words
7492acc9 1931 (sql-font-lock-keywords-builder 'font-lock-builtin-face nil
9250002f 1932"abort" "absolute" "access" "action" "add" "admin" "after" "aggregate"
016b2a42 1933"also" "alter" "always" "assertion" "assignment" "at" "attribute" "backward"
9250002f
MM
1934"before" "begin" "between" "by" "cache" "called" "cascade" "cascaded"
1935"catalog" "chain" "characteristics" "checkpoint" "class" "close"
1936"cluster" "coalesce" "comment" "comments" "commit" "committed"
1937"configuration" "connection" "constraints" "content" "continue"
1938"conversion" "copy" "cost" "createdb" "createrole" "createuser" "csv"
1939"current" "cursor" "cycle" "data" "database" "day" "deallocate" "dec"
1940"declare" "defaults" "deferred" "definer" "delete" "delimiter"
1941"delimiters" "dictionary" "disable" "discard" "document" "domain"
1942"drop" "each" "enable" "encoding" "encrypted" "enum" "escape"
1943"exclude" "excluding" "exclusive" "execute" "exists" "explain"
016b2a42 1944"extension" "external" "extract" "family" "first" "float" "following" "force"
9250002f
MM
1945"forward" "function" "functions" "global" "granted" "greatest"
1946"handler" "header" "hold" "hour" "identity" "if" "immediate"
1947"immutable" "implicit" "including" "increment" "index" "indexes"
1948"inherit" "inherits" "inline" "inout" "input" "insensitive" "insert"
016b2a42
JD
1949"instead" "invoker" "isolation" "key" "label" "language" "large" "last"
1950"lc_collate" "lc_ctype" "leakproof" "least" "level" "listen" "load" "local"
9250002f 1951"location" "lock" "login" "mapping" "match" "maxvalue" "minute"
016b2a42 1952"minvalue" "mode" "month" "move" "names" "national" "nchar"
9250002f 1953"next" "no" "nocreatedb" "nocreaterole" "nocreateuser" "noinherit"
016b2a42
JD
1954"nologin" "none" "noreplication" "nosuperuser" "nothing" "notify" "nowait" "nullif"
1955"nulls" "object" "of" "off" "oids" "operator" "option" "options" "out"
1956"overlay" "owned" "owner" "parser" "partial" "partition" "passing" "password"
1957"plans" "position" "preceding" "precision" "prepare" "prepared" "preserve" "prior"
9250002f 1958"privileges" "procedural" "procedure" "quote" "range" "read"
016b2a42
JD
1959"reassign" "recheck" "recursive" "ref" "reindex" "relative" "release"
1960"rename" "repeatable" "replace" "replica" "replication" "reset" "restart" "restrict"
9250002f 1961"returns" "revoke" "role" "rollback" "row" "rows" "rule" "savepoint"
016b2a42 1962"schema" "scroll" "search" "second" "security" "sequence"
9250002f 1963"serializable" "server" "session" "set" "setof" "share" "show"
016b2a42 1964"simple" "snapshot" "stable" "standalone" "start" "statement" "statistics"
9250002f
MM
1965"stdin" "stdout" "storage" "strict" "strip" "substring" "superuser"
1966"sysid" "system" "tables" "tablespace" "temp" "template" "temporary"
016b2a42
JD
1967"transaction" "treat" "trim" "truncate" "trusted" "type" "types"
1968"unbounded" "uncommitted" "unencrypted" "unlisten" "unlogged" "until"
1969"update" "vacuum" "valid" "validate" "validator" "value" "values" "varying" "version"
1970"view" "volatile" "whitespace" "without" "work" "wrapper" "write"
1971"xmlattributes" "xmlconcat" "xmlelement" "xmlexists" "xmlforest" "xmlparse"
1972"xmlpi" "xmlroot" "xmlserialize" "year" "yes" "zone"
7492acc9 1973)
9250002f 1974
7492acc9
MM
1975 ;; Postgres Reserved
1976 (sql-font-lock-keywords-builder 'font-lock-keyword-face nil
016b2a42 1977"all" "analyse" "analyze" "and" "array" "asc" "as" "asymmetric"
9250002f
MM
1978"authorization" "binary" "both" "case" "cast" "check" "collate"
1979"column" "concurrently" "constraint" "create" "cross"
1980"current_catalog" "current_date" "current_role" "current_schema"
1981"current_time" "current_timestamp" "current_user" "default"
1982"deferrable" "desc" "distinct" "do" "else" "end" "except" "false"
1983"fetch" "foreign" "for" "freeze" "from" "full" "grant" "group"
1984"having" "ilike" "initially" "inner" "in" "intersect" "into" "isnull"
1985"is" "join" "leading" "left" "like" "limit" "localtime"
016b2a42 1986"localtimestamp" "natural" "notnull" "not" "null" "offset"
9250002f
MM
1987"only" "on" "order" "or" "outer" "overlaps" "over" "placing" "primary"
1988"references" "returning" "right" "select" "session_user" "similar"
1989"some" "symmetric" "table" "then" "to" "trailing" "true" "union"
1990"unique" "user" "using" "variadic" "verbose" "when" "where" "window"
1991"with"
016b2a42
JD
1992)
1993
1994 ;; Postgres PL/pgSQL
1995 (sql-font-lock-keywords-builder 'font-lock-keyword-face nil
1996"assign" "if" "case" "loop" "while" "for" "foreach" "exit" "elsif" "return"
1997"raise" "execsql" "dynexecute" "perform" "getdiag" "open" "fetch" "move" "close"
7492acc9 1998)
9fd8cb36 1999
7492acc9
MM
2000 ;; Postgres Data Types
2001 (sql-font-lock-keywords-builder 'font-lock-type-face nil
9250002f
MM
2002"bigint" "bigserial" "bit" "bool" "boolean" "box" "bytea" "char"
2003"character" "cidr" "circle" "date" "decimal" "double" "float4"
2004"float8" "inet" "int" "int2" "int4" "int8" "integer" "interval" "line"
016b2a42
JD
2005"lseg" "macaddr" "money" "name" "numeric" "path" "point" "polygon"
2006"precision" "real" "serial" "serial4" "serial8" "sequences" "smallint" "text"
9250002f 2007"time" "timestamp" "timestamptz" "timetz" "tsquery" "tsvector"
016b2a42 2008"txid_snapshot" "unknown" "uuid" "varbit" "varchar" "varying" "without"
9250002f 2009"xml" "zone"
9fd8cb36
SM
2010)))
2011
78024f88 2012 "Postgres SQL keywords used by font-lock.
f4df536d
JB
2013
2014This variable is used by `sql-mode' and `sql-interactive-mode'. The
2015regular expressions are created during compilation by calling the
78024f88 2016function `regexp-opt'. Therefore, take a look at the source before
063c6324 2017you define your own `sql-mode-postgres-font-lock-keywords'.")
f4df536d 2018
78024f88 2019(defvar sql-mode-linter-font-lock-keywords
7492acc9
MM
2020 (eval-when-compile
2021 (list
2022 ;; Linter Keywords
2023 (sql-font-lock-keywords-builder 'font-lock-keyword-face nil
f4df536d
JB
2024"autocommit" "autoinc" "autorowid" "cancel" "cascade" "channel"
2025"committed" "count" "countblob" "cross" "current" "data" "database"
2026"datafile" "datafiles" "datesplit" "dba" "dbname" "default" "deferred"
2027"denied" "description" "device" "difference" "directory" "error"
2028"escape" "euc" "exclusive" "external" "extfile" "false" "file"
2029"filename" "filesize" "filetime" "filter" "findblob" "first" "foreign"
2030"full" "fuzzy" "global" "granted" "ignore" "immediate" "increment"
2031"indexes" "indexfile" "indexfiles" "indextime" "initial" "integrity"
2032"internal" "key" "last_autoinc" "last_rowid" "limit" "linter"
2033"linter_file_device" "linter_file_size" "linter_name_length" "ln"
2034"local" "login" "maxisn" "maxrow" "maxrowid" "maxvalue" "message"
2035"minvalue" "module" "names" "national" "natural" "new" "new_table"
2036"no" "node" "noneuc" "nulliferror" "numbers" "off" "old" "old_table"
2037"only" "operation" "optimistic" "option" "page" "partially" "password"
2038"phrase" "plan" "precision" "primary" "priority" "privileges"
2039"proc_info_size" "proc_par_name_len" "protocol" "quant" "range" "raw"
2040"read" "record" "records" "references" "remote" "rename" "replication"
2041"restart" "rewrite" "root" "row" "rule" "savepoint" "security"
2042"sensitive" "sequence" "serializable" "server" "since" "size" "some"
2043"startup" "statement" "station" "success" "sys_guid" "tables" "test"
2044"timeout" "trace" "transaction" "translation" "trigger"
2045"trigger_info_size" "true" "trunc" "uncommitted" "unicode" "unknown"
2046"unlimited" "unlisted" "user" "utf8" "value" "varying" "volumes"
2047"wait" "windows_code" "workspace" "write" "xml"
7492acc9 2048)
78024f88 2049
7492acc9
MM
2050 ;; Linter Reserved
2051 (sql-font-lock-keywords-builder 'font-lock-keyword-face nil
f4df536d
JB
2052"access" "action" "add" "address" "after" "all" "alter" "always" "and"
2053"any" "append" "as" "asc" "ascic" "async" "at_begin" "at_end" "audit"
2054"aud_obj_name_len" "backup" "base" "before" "between" "blobfile"
2055"blobfiles" "blobpct" "brief" "browse" "by" "case" "cast" "check"
2056"clear" "close" "column" "comment" "commit" "connect" "contains"
2057"correct" "create" "delete" "desc" "disable" "disconnect" "distinct"
2058"drop" "each" "ef" "else" "enable" "end" "event" "except" "exclude"
2059"execute" "exists" "extract" "fetch" "finish" "for" "from" "get"
2060"grant" "group" "having" "identified" "in" "index" "inner" "insert"
2061"instead" "intersect" "into" "is" "isolation" "join" "left" "level"
2062"like" "lock" "mode" "modify" "not" "nowait" "null" "of" "on" "open"
2063"or" "order" "outer" "owner" "press" "prior" "procedure" "public"
2064"purge" "rebuild" "resource" "restrict" "revoke" "right" "role"
2065"rollback" "rownum" "select" "session" "set" "share" "shutdown"
2066"start" "stop" "sync" "synchronize" "synonym" "sysdate" "table" "then"
2067"to" "union" "unique" "unlock" "until" "update" "using" "values"
2068"view" "when" "where" "with" "without"
7492acc9 2069)
78024f88 2070
7492acc9
MM
2071 ;; Linter Functions
2072 (sql-font-lock-keywords-builder 'font-lock-builtin-face nil
f4df536d
JB
2073"abs" "acos" "asin" "atan" "atan2" "avg" "ceil" "cos" "cosh" "divtime"
2074"exp" "floor" "getbits" "getblob" "getbyte" "getlong" "getraw"
2075"getstr" "gettext" "getword" "hextoraw" "lenblob" "length" "log"
2076"lower" "lpad" "ltrim" "max" "min" "mod" "monthname" "nvl"
2077"octet_length" "power" "rand" "rawtohex" "repeat_string"
2078"right_substr" "round" "rpad" "rtrim" "sign" "sin" "sinh" "soundex"
2079"sqrt" "sum" "tan" "tanh" "timeint_to_days" "to_char" "to_date"
2080"to_gmtime" "to_localtime" "to_number" "trim" "upper" "decode"
2081"substr" "substring" "chr" "dayname" "days" "greatest" "hex" "initcap"
2082"instr" "least" "multime" "replace" "width"
7492acc9 2083)
78024f88 2084
7492acc9
MM
2085 ;; Linter Data Types
2086 (sql-font-lock-keywords-builder 'font-lock-type-face nil
2087"bigint" "bitmap" "blob" "boolean" "char" "character" "date"
2088"datetime" "dec" "decimal" "double" "float" "int" "integer" "nchar"
2089"number" "numeric" "real" "smallint" "varbyte" "varchar" "byte"
2090"cursor" "long"
2091)))
78024f88
AS
2092
2093 "Linter SQL keywords used by font-lock.
f4df536d 2094
78024f88
AS
2095This variable is used by `sql-mode' and `sql-interactive-mode'. The
2096regular expressions are created during compilation by calling the
2097function `regexp-opt'.")
2098
2099(defvar sql-mode-ms-font-lock-keywords
7492acc9
MM
2100 (eval-when-compile
2101 (list
2102 ;; MS isql/osql Commands
2103 (cons
2104 (concat
2105 "^\\(?:\\(?:set\\s-+\\(?:"
2106 (regexp-opt '(
2107"datefirst" "dateformat" "deadlock_priority" "lock_timeout"
2108"concat_null_yields_null" "cursor_close_on_commit"
2109"disable_def_cnst_chk" "fips_flagger" "identity_insert" "language"
2110"offsets" "quoted_identifier" "arithabort" "arithignore" "fmtonly"
2111"nocount" "noexec" "numeric_roundabort" "parseonly"
2112"query_governor_cost_limit" "rowcount" "textsize" "ansi_defaults"
2113"ansi_null_dflt_off" "ansi_null_dflt_on" "ansi_nulls" "ansi_padding"
2114"ansi_warnings" "forceplan" "showplan_all" "showplan_text"
2115"statistics" "implicit_transactions" "remote_proc_transactions"
2116"transaction" "xact_abort"
2117) t)
2118 "\\)\\)\\|go\\s-*\\|use\\s-+\\|setuser\\s-+\\|dbcc\\s-+\\).*$")
2119 'font-lock-doc-face)
2120
2121 ;; MS Reserved
2122 (sql-font-lock-keywords-builder 'font-lock-keyword-face nil
78024f88
AS
2123"absolute" "add" "all" "alter" "and" "any" "as" "asc" "authorization"
2124"avg" "backup" "begin" "between" "break" "browse" "bulk" "by"
2125"cascade" "case" "check" "checkpoint" "close" "clustered" "coalesce"
2126"column" "commit" "committed" "compute" "confirm" "constraint"
2127"contains" "containstable" "continue" "controlrow" "convert" "count"
2128"create" "cross" "current" "current_date" "current_time"
9fd8cb36
SM
2129"current_timestamp" "current_user" "database" "deallocate" "declare"
2130"default" "delete" "deny" "desc" "disk" "distinct" "distributed"
2131"double" "drop" "dummy" "dump" "else" "end" "errlvl" "errorexit"
2132"escape" "except" "exec" "execute" "exists" "exit" "fetch" "file"
2133"fillfactor" "first" "floppy" "for" "foreign" "freetext"
78024f88
AS
2134"freetexttable" "from" "full" "goto" "grant" "group" "having"
2135"holdlock" "identity" "identity_insert" "identitycol" "if" "in"
2136"index" "inner" "insert" "intersect" "into" "is" "isolation" "join"
2137"key" "kill" "last" "left" "level" "like" "lineno" "load" "max" "min"
2138"mirrorexit" "national" "next" "nocheck" "nolock" "nonclustered" "not"
2139"null" "nullif" "of" "off" "offsets" "on" "once" "only" "open"
2140"opendatasource" "openquery" "openrowset" "option" "or" "order"
2141"outer" "output" "over" "paglock" "percent" "perm" "permanent" "pipe"
2142"plan" "precision" "prepare" "primary" "print" "prior" "privileges"
2143"proc" "procedure" "processexit" "public" "raiserror" "read"
2144"readcommitted" "readpast" "readtext" "readuncommitted" "reconfigure"
2145"references" "relative" "repeatable" "repeatableread" "replication"
2146"restore" "restrict" "return" "revoke" "right" "rollback" "rowcount"
2147"rowguidcol" "rowlock" "rule" "save" "schema" "select" "serializable"
2148"session_user" "set" "shutdown" "some" "statistics" "sum"
2149"system_user" "table" "tablock" "tablockx" "tape" "temp" "temporary"
2150"textsize" "then" "to" "top" "tran" "transaction" "trigger" "truncate"
2151"tsequal" "uncommitted" "union" "unique" "update" "updatetext"
2152"updlock" "use" "user" "values" "view" "waitfor" "when" "where"
9fd8cb36
SM
2153"while" "with" "work" "writetext" "collate" "function" "openxml"
2154"returns"
7492acc9 2155)
78024f88 2156
7492acc9
MM
2157 ;; MS Functions
2158 (sql-font-lock-keywords-builder 'font-lock-builtin-face nil
78024f88
AS
2159"@@connections" "@@cpu_busy" "@@cursor_rows" "@@datefirst" "@@dbts"
2160"@@error" "@@fetch_status" "@@identity" "@@idle" "@@io_busy"
2161"@@langid" "@@language" "@@lock_timeout" "@@max_connections"
2162"@@max_precision" "@@nestlevel" "@@options" "@@pack_received"
2163"@@pack_sent" "@@packet_errors" "@@procid" "@@remserver" "@@rowcount"
2164"@@servername" "@@servicename" "@@spid" "@@textsize" "@@timeticks"
2165"@@total_errors" "@@total_read" "@@total_write" "@@trancount"
2166"@@version" "abs" "acos" "and" "app_name" "ascii" "asin" "atan" "atn2"
2167"avg" "case" "cast" "ceiling" "char" "charindex" "coalesce"
2168"col_length" "col_name" "columnproperty" "containstable" "convert"
2169"cos" "cot" "count" "current_timestamp" "current_user" "cursor_status"
2170"databaseproperty" "datalength" "dateadd" "datediff" "datename"
2171"datepart" "day" "db_id" "db_name" "degrees" "difference" "exp"
2172"file_id" "file_name" "filegroup_id" "filegroup_name"
2173"filegroupproperty" "fileproperty" "floor" "formatmessage"
2174"freetexttable" "fulltextcatalogproperty" "fulltextserviceproperty"
2175"getansinull" "getdate" "grouping" "host_id" "host_name" "ident_incr"
2176"ident_seed" "identity" "index_col" "indexproperty" "is_member"
2177"is_srvrolemember" "isdate" "isnull" "isnumeric" "left" "len" "log"
2178"log10" "lower" "ltrim" "max" "min" "month" "nchar" "newid" "nullif"
2179"object_id" "object_name" "objectproperty" "openquery" "openrowset"
2180"parsename" "patindex" "patindex" "permissions" "pi" "power"
2181"quotename" "radians" "rand" "replace" "replicate" "reverse" "right"
2182"round" "rtrim" "session_user" "sign" "sin" "soundex" "space" "sqrt"
2183"square" "stats_date" "stdev" "stdevp" "str" "stuff" "substring" "sum"
2184"suser_id" "suser_name" "suser_sid" "suser_sname" "system_user" "tan"
2185"textptr" "textvalid" "typeproperty" "unicode" "upper" "user"
2186"user_id" "user_name" "var" "varp" "year"
7492acc9 2187)
78024f88 2188
7492acc9
MM
2189 ;; MS Variables
2190 '("\\b@[a-zA-Z0-9_]*\\b" . font-lock-variable-name-face)
78024f88 2191
7492acc9
MM
2192 ;; MS Types
2193 (sql-font-lock-keywords-builder 'font-lock-type-face nil
2194"binary" "bit" "char" "character" "cursor" "datetime" "dec" "decimal"
2195"double" "float" "image" "int" "integer" "money" "national" "nchar"
2196"ntext" "numeric" "numeric" "nvarchar" "precision" "real"
2197"smalldatetime" "smallint" "smallmoney" "text" "timestamp" "tinyint"
2198"uniqueidentifier" "varbinary" "varchar" "varying"
2199)))
78024f88
AS
2200
2201 "Microsoft SQLServer SQL keywords used by font-lock.
2202
2203This variable is used by `sql-mode' and `sql-interactive-mode'. The
2204regular expressions are created during compilation by calling the
2205function `regexp-opt'. Therefore, take a look at the source before
063c6324 2206you define your own `sql-mode-ms-font-lock-keywords'.")
78024f88 2207
9fd8cb36 2208(defvar sql-mode-sybase-font-lock-keywords nil
78024f88
AS
2209 "Sybase SQL keywords used by font-lock.
2210
2211This variable is used by `sql-mode' and `sql-interactive-mode'. The
2212regular expressions are created during compilation by calling the
2213function `regexp-opt'. Therefore, take a look at the source before
063c6324 2214you define your own `sql-mode-sybase-font-lock-keywords'.")
78024f88 2215
9fd8cb36 2216(defvar sql-mode-informix-font-lock-keywords nil
78024f88
AS
2217 "Informix SQL keywords used by font-lock.
2218
2219This variable is used by `sql-mode' and `sql-interactive-mode'. The
2220regular expressions are created during compilation by calling the
2221function `regexp-opt'. Therefore, take a look at the source before
063c6324 2222you define your own `sql-mode-informix-font-lock-keywords'.")
78024f88 2223
9fd8cb36 2224(defvar sql-mode-interbase-font-lock-keywords nil
78024f88
AS
2225 "Interbase SQL keywords used by font-lock.
2226
2227This variable is used by `sql-mode' and `sql-interactive-mode'. The
2228regular expressions are created during compilation by calling the
2229function `regexp-opt'. Therefore, take a look at the source before
063c6324 2230you define your own `sql-mode-interbase-font-lock-keywords'.")
78024f88 2231
9fd8cb36 2232(defvar sql-mode-ingres-font-lock-keywords nil
78024f88
AS
2233 "Ingres SQL keywords used by font-lock.
2234
2235This variable is used by `sql-mode' and `sql-interactive-mode'. The
2236regular expressions are created during compilation by calling the
2237function `regexp-opt'. Therefore, take a look at the source before
063c6324 2238you define your own `sql-mode-interbase-font-lock-keywords'.")
78024f88 2239
9fd8cb36 2240(defvar sql-mode-solid-font-lock-keywords nil
78024f88
AS
2241 "Solid SQL keywords used by font-lock.
2242
2243This variable is used by `sql-mode' and `sql-interactive-mode'. The
2244regular expressions are created during compilation by calling the
2245function `regexp-opt'. Therefore, take a look at the source before
063c6324 2246you define your own `sql-mode-solid-font-lock-keywords'.")
78024f88 2247
9fd8cb36 2248(defvar sql-mode-mysql-font-lock-keywords
7492acc9
MM
2249 (eval-when-compile
2250 (list
2251 ;; MySQL Functions
2252 (sql-font-lock-keywords-builder 'font-lock-builtin-face nil
9fd8cb36
SM
2253"ascii" "avg" "bdmpolyfromtext" "bdmpolyfromwkb" "bdpolyfromtext"
2254"bdpolyfromwkb" "benchmark" "bin" "bit_and" "bit_length" "bit_or"
2255"bit_xor" "both" "cast" "char_length" "character_length" "coalesce"
2256"concat" "concat_ws" "connection_id" "conv" "convert" "count"
2257"curdate" "current_date" "current_time" "current_timestamp" "curtime"
2258"elt" "encrypt" "export_set" "field" "find_in_set" "found_rows" "from"
2259"geomcollfromtext" "geomcollfromwkb" "geometrycollectionfromtext"
2260"geometrycollectionfromwkb" "geometryfromtext" "geometryfromwkb"
2261"geomfromtext" "geomfromwkb" "get_lock" "group_concat" "hex" "ifnull"
2262"instr" "interval" "isnull" "last_insert_id" "lcase" "leading"
2263"length" "linefromtext" "linefromwkb" "linestringfromtext"
2264"linestringfromwkb" "load_file" "locate" "lower" "lpad" "ltrim"
2265"make_set" "master_pos_wait" "max" "mid" "min" "mlinefromtext"
2266"mlinefromwkb" "mpointfromtext" "mpointfromwkb" "mpolyfromtext"
2267"mpolyfromwkb" "multilinestringfromtext" "multilinestringfromwkb"
2268"multipointfromtext" "multipointfromwkb" "multipolygonfromtext"
2269"multipolygonfromwkb" "now" "nullif" "oct" "octet_length" "ord"
2270"pointfromtext" "pointfromwkb" "polyfromtext" "polyfromwkb"
2271"polygonfromtext" "polygonfromwkb" "position" "quote" "rand"
2272"release_lock" "repeat" "replace" "reverse" "rpad" "rtrim" "soundex"
2273"space" "std" "stddev" "substring" "substring_index" "sum" "sysdate"
2274"trailing" "trim" "ucase" "unix_timestamp" "upper" "user" "variance"
7492acc9 2275)
9fd8cb36 2276
7492acc9
MM
2277 ;; MySQL Keywords
2278 (sql-font-lock-keywords-builder 'font-lock-keyword-face nil
9fd8cb36
SM
2279"action" "add" "after" "against" "all" "alter" "and" "as" "asc"
2280"auto_increment" "avg_row_length" "bdb" "between" "by" "cascade"
2281"case" "change" "character" "check" "checksum" "close" "collate"
2282"collation" "column" "columns" "comment" "committed" "concurrent"
2283"constraint" "create" "cross" "data" "database" "default"
2284"delay_key_write" "delayed" "delete" "desc" "directory" "disable"
bb5aa5d6 2285"distinct" "distinctrow" "do" "drop" "dumpfile" "duplicate" "else" "elseif"
9fd8cb36
SM
2286"enable" "enclosed" "end" "escaped" "exists" "fields" "first" "for"
2287"force" "foreign" "from" "full" "fulltext" "global" "group" "handler"
2288"having" "heap" "high_priority" "if" "ignore" "in" "index" "infile"
2289"inner" "insert" "insert_method" "into" "is" "isam" "isolation" "join"
2290"key" "keys" "last" "left" "level" "like" "limit" "lines" "load"
2291"local" "lock" "low_priority" "match" "max_rows" "merge" "min_rows"
2292"mode" "modify" "mrg_myisam" "myisam" "natural" "next" "no" "not"
2293"null" "offset" "oj" "on" "open" "optionally" "or" "order" "outer"
2294"outfile" "pack_keys" "partial" "password" "prev" "primary"
2295"procedure" "quick" "raid0" "raid_type" "read" "references" "rename"
2296"repeatable" "restrict" "right" "rollback" "rollup" "row_format"
2297"savepoint" "select" "separator" "serializable" "session" "set"
2298"share" "show" "sql_big_result" "sql_buffer_result" "sql_cache"
2299"sql_calc_found_rows" "sql_no_cache" "sql_small_result" "starting"
2300"straight_join" "striped" "table" "tables" "temporary" "terminated"
2301"then" "to" "transaction" "truncate" "type" "uncommitted" "union"
2302"unique" "unlock" "update" "use" "using" "values" "when" "where"
2303"with" "write" "xor"
7492acc9 2304)
9fd8cb36 2305
7492acc9
MM
2306 ;; MySQL Data Types
2307 (sql-font-lock-keywords-builder 'font-lock-type-face nil
9fd8cb36
SM
2308"bigint" "binary" "bit" "blob" "bool" "boolean" "char" "curve" "date"
2309"datetime" "dec" "decimal" "double" "enum" "fixed" "float" "geometry"
2310"geometrycollection" "int" "integer" "line" "linearring" "linestring"
2311"longblob" "longtext" "mediumblob" "mediumint" "mediumtext"
2312"multicurve" "multilinestring" "multipoint" "multipolygon"
2313"multisurface" "national" "numeric" "point" "polygon" "precision"
2314"real" "smallint" "surface" "text" "time" "timestamp" "tinyblob"
2315"tinyint" "tinytext" "unsigned" "varchar" "year" "year2" "year4"
2316"zerofill"
2317)))
2318
78024f88
AS
2319 "MySQL SQL keywords used by font-lock.
2320
2321This variable is used by `sql-mode' and `sql-interactive-mode'. The
2322regular expressions are created during compilation by calling the
2323function `regexp-opt'. Therefore, take a look at the source before
063c6324 2324you define your own `sql-mode-mysql-font-lock-keywords'.")
78024f88 2325
b93d4f22
MM
2326(defvar sql-mode-sqlite-font-lock-keywords
2327 (eval-when-compile
2328 (list
9250002f
MM
2329 ;; SQLite commands
2330 '("^[.].*$" . font-lock-doc-face)
2331
b93d4f22
MM
2332 ;; SQLite Keyword
2333 (sql-font-lock-keywords-builder 'font-lock-keyword-face nil
2334"abort" "action" "add" "after" "all" "alter" "analyze" "and" "as"
2335"asc" "attach" "autoincrement" "before" "begin" "between" "by"
2336"cascade" "case" "cast" "check" "collate" "column" "commit" "conflict"
3bd2cfef
MM
2337"constraint" "create" "cross" "database" "default" "deferrable"
2338"deferred" "delete" "desc" "detach" "distinct" "drop" "each" "else"
2339"end" "escape" "except" "exclusive" "exists" "explain" "fail" "for"
b93d4f22
MM
2340"foreign" "from" "full" "glob" "group" "having" "if" "ignore"
2341"immediate" "in" "index" "indexed" "initially" "inner" "insert"
2342"instead" "intersect" "into" "is" "isnull" "join" "key" "left" "like"
2343"limit" "match" "natural" "no" "not" "notnull" "null" "of" "offset"
2344"on" "or" "order" "outer" "plan" "pragma" "primary" "query" "raise"
2345"references" "regexp" "reindex" "release" "rename" "replace"
2346"restrict" "right" "rollback" "row" "savepoint" "select" "set" "table"
2347"temp" "temporary" "then" "to" "transaction" "trigger" "union"
2348"unique" "update" "using" "vacuum" "values" "view" "virtual" "when"
2349"where"
2350)
2351 ;; SQLite Data types
2352 (sql-font-lock-keywords-builder 'font-lock-type-face nil
2353"int" "integer" "tinyint" "smallint" "mediumint" "bigint" "unsigned"
3bd2cfef 2354"big" "int2" "int8" "character" "varchar" "varying" "nchar" "native"
b93d4f22 2355"nvarchar" "text" "clob" "blob" "real" "double" "precision" "float"
3bd2cfef 2356"numeric" "number" "decimal" "boolean" "date" "datetime"
b93d4f22
MM
2357)
2358 ;; SQLite Functions
2359 (sql-font-lock-keywords-builder 'font-lock-builtin-face nil
2360;; Core functions
2361"abs" "changes" "coalesce" "glob" "ifnull" "hex" "last_insert_rowid"
2362"length" "like" "load_extension" "lower" "ltrim" "max" "min" "nullif"
2363"quote" "random" "randomblob" "replace" "round" "rtrim" "soundex"
2364"sqlite_compileoption_get" "sqlite_compileoption_used"
2365"sqlite_source_id" "sqlite_version" "substr" "total_changes" "trim"
2366"typeof" "upper" "zeroblob"
2367;; Date/time functions
2368"time" "julianday" "strftime"
3bd2cfef 2369"current_date" "current_time" "current_timestamp"
b93d4f22
MM
2370;; Aggregate functions
2371"avg" "count" "group_concat" "max" "min" "sum" "total"
2372)))
2373
78024f88
AS
2374 "SQLite SQL keywords used by font-lock.
2375
2376This variable is used by `sql-mode' and `sql-interactive-mode'. The
2377regular expressions are created during compilation by calling the
2378function `regexp-opt'. Therefore, take a look at the source before
063c6324 2379you define your own `sql-mode-sqlite-font-lock-keywords'.")
78024f88 2380
9fd8cb36 2381(defvar sql-mode-db2-font-lock-keywords nil
78024f88
AS
2382 "DB2 SQL keywords used by font-lock.
2383
2384This variable is used by `sql-mode' and `sql-interactive-mode'. The
2385regular expressions are created during compilation by calling the
2386function `regexp-opt'. Therefore, take a look at the source before
063c6324 2387you define your own `sql-mode-db2-font-lock-keywords'.")
78024f88
AS
2388
2389(defvar sql-mode-font-lock-keywords nil
95e4b2ef
RS
2390 "SQL keywords used by font-lock.
2391
78024f88
AS
2392Setting this variable directly no longer has any affect. Use
2393`sql-product' and `sql-add-product-keywords' to control the
063c6324 2394highlighting rules in SQL mode.")
78024f88
AS
2395
2396\f
2397
2398;;; SQL Product support functions
2399
74790210
MM
2400(defun sql-read-product (prompt &optional initial)
2401 "Read a valid SQL product."
2402 (let ((init (or (and initial (symbol-name initial)) "ansi")))
2403 (intern (completing-read
2404 prompt
2405 (mapcar (lambda (info) (symbol-name (car info)))
2406 sql-product-alist)
2407 nil 'require-match
2408 init 'sql-product-history init))))
2409
7492acc9
MM
2410(defun sql-add-product (product display &rest plist)
2411 "Add support for a database product in `sql-mode'.
2412
2413Add PRODUCT to `sql-product-alist' which enables `sql-mode' to
2414properly support syntax highlighting and interactive interaction.
2415DISPLAY is the name of the SQL product that will appear in the
2416menu bar and in messages. PLIST initializes the product
2417configuration."
2418
2419 ;; Don't do anything if the product is already supported
2420 (if (assoc product sql-product-alist)
2421 (message "Product `%s' is already defined" product)
2422
2423 ;; Add product to the alist
2424 (add-to-list 'sql-product-alist `((,product :name ,display . ,plist)))
2425 ;; Add a menu item to the SQL->Product menu
2426 (easy-menu-add-item sql-mode-menu '("Product")
2427 ;; Each product is represented by a radio
2428 ;; button with it's display name.
2429 `[,display
d26b0ea9 2430 (sql-set-product ',product)
7492acc9
MM
2431 :style radio
2432 :selected (eq sql-product ',product)]
2433 ;; Maintain the product list in
2434 ;; (case-insensitive) alphabetic order of the
2435 ;; display names. Loop thru each keymap item
2436 ;; looking for an item whose display name is
2437 ;; after this product's name.
2438 (let ((next-item)
2439 (down-display (downcase display)))
2440 (map-keymap (lambda (k b)
2441 (when (and (not next-item)
2442 (string-lessp down-display
2443 (downcase (cadr b))))
2444 (setq next-item k)))
2445 (easy-menu-get-map sql-mode-menu '("Product")))
2446 next-item))
2447 product))
2448
2449(defun sql-del-product (product)
2450 "Remove support for PRODUCT in `sql-mode'."
2451
2452 ;; Remove the menu item based on the display name
2453 (easy-menu-remove-item sql-mode-menu '("Product") (sql-get-product-feature product :name))
2454 ;; Remove the product alist item
2455 (setq sql-product-alist (assq-delete-all product sql-product-alist))
2456 nil)
2457
2458(defun sql-set-product-feature (product feature newvalue)
2459 "Set FEATURE of database PRODUCT to NEWVALUE.
2460
2461The PRODUCT must be a symbol which identifies the database
2462product. The product must have already exist on the product
2463list. See `sql-add-product' to add new products. The FEATURE
2464argument must be a plist keyword accepted by
2465`sql-product-alist'."
2466
2467 (let* ((p (assoc product sql-product-alist))
2468 (v (plist-get (cdr p) feature)))
2469 (if p
2470 (if (and
2471 (member feature sql-indirect-features)
2472 (symbolp v))
2473 (set v newvalue)
2474 (setcdr p (plist-put (cdr p) feature newvalue)))
2475 (message "`%s' is not a known product; use `sql-add-product' to add it first." product))))
2476
30c4d8dc 2477(defun sql-get-product-feature (product feature &optional fallback not-indirect)
7492acc9
MM
2478 "Lookup FEATURE associated with a SQL PRODUCT.
2479
2480If the FEATURE is nil for PRODUCT, and FALLBACK is specified,
2481then the FEATURE associated with the FALLBACK product is
2482returned.
78024f88 2483
30c4d8dc
MM
2484If the FEATURE is in the list `sql-indirect-features', and the
2485NOT-INDIRECT parameter is not set, then the value of the symbol
2486stored in the connect alist is returned.
2487
063c6324 2488See `sql-product-alist' for a list of products and supported features."
7492acc9
MM
2489 (let* ((p (assoc product sql-product-alist))
2490 (v (plist-get (cdr p) feature)))
2491
2492 (if p
2493 ;; If no value and fallback, lookup feature for fallback
2494 (if (and (not v)
2495 fallback
2496 (not (eq product fallback)))
2497 (sql-get-product-feature fallback feature)
2498
2499 (if (and
2500 (member feature sql-indirect-features)
30c4d8dc 2501 (not not-indirect)
7492acc9
MM
2502 (symbolp v))
2503 (symbol-value v)
2504 v))
d26b0ea9
MM
2505 (message "`%s' is not a known product; use `sql-add-product' to add it first." product)
2506 nil)))
78024f88
AS
2507
2508(defun sql-product-font-lock (keywords-only imenu)
c38762fd 2509 "Configure font-lock and imenu with product-specific settings.
7492acc9
MM
2510
2511The KEYWORDS-ONLY flag is passed to font-lock to specify whether
e4769531 2512only keywords should be highlighted and syntactic highlighting
7492acc9
MM
2513skipped. The IMENU flag indicates whether `imenu-mode' should
2514also be configured."
2515
78024f88
AS
2516 (let
2517 ;; Get the product-specific syntax-alist.
fbcc67e2 2518 ((syntax-alist (sql-product-font-lock-syntax-alist)))
78024f88
AS
2519
2520 ;; Get the product-specific keywords.
175069ef
SM
2521 (set (make-local-variable 'sql-mode-font-lock-keywords)
2522 (append
2523 (unless (eq sql-product 'ansi)
2524 (sql-get-product-feature sql-product :font-lock))
2525 ;; Always highlight ANSI keywords
2526 (sql-get-product-feature 'ansi :font-lock)
2527 ;; Fontify object names in CREATE, DROP and ALTER DDL
2528 ;; statements
2529 (list sql-mode-font-lock-object-name)))
78024f88 2530
9a9069c9 2531 ;; Setup font-lock. Force re-parsing of `font-lock-defaults'.
7492acc9 2532 (kill-local-variable 'font-lock-set-defaults)
175069ef
SM
2533 (set (make-local-variable 'font-lock-defaults)
2534 (list 'sql-mode-font-lock-keywords
2535 keywords-only t syntax-alist))
78024f88 2536
9a9069c9
SM
2537 ;; Force font lock to reinitialize if it is already on
2538 ;; Otherwise, we can wait until it can be started.
2539 (when (and (fboundp 'font-lock-mode)
7492acc9 2540 (boundp 'font-lock-mode)
9a9069c9
SM
2541 font-lock-mode)
2542 (font-lock-mode-internal nil)
2543 (font-lock-mode-internal t))
2544
2545 (add-hook 'font-lock-mode-hook
2546 (lambda ()
2547 ;; Provide defaults for new font-lock faces.
2548 (defvar font-lock-builtin-face
2549 (if (boundp 'font-lock-preprocessor-face)
2550 font-lock-preprocessor-face
2551 font-lock-keyword-face))
2552 (defvar font-lock-doc-face font-lock-string-face))
2553 nil t)
2554
78024f88
AS
2555 ;; Setup imenu; it needs the same syntax-alist.
2556 (when imenu
7492acc9 2557 (setq imenu-syntax-alist syntax-alist))))
78024f88
AS
2558
2559;;;###autoload
9fd8cb36
SM
2560(defun sql-add-product-keywords (product keywords &optional append)
2561 "Add highlighting KEYWORDS for SQL PRODUCT.
2562
c38762fd 2563PRODUCT should be a symbol, the name of a SQL product, such as
9fd8cb36
SM
2564`oracle'. KEYWORDS should be a list; see the variable
2565`font-lock-keywords'. By default they are added at the beginning
2566of the current highlighting list. If optional argument APPEND is
2567`set', they are used to replace the current highlighting list.
2568If APPEND is any other non-nil value, they are added at the end
2569of the current highlighting list.
2570
2571For example:
2572
2573 (sql-add-product-keywords 'ms
2574 '((\"\\\\b\\\\w+_t\\\\b\" . font-lock-type-face)))
2575
2576adds a fontification pattern to fontify identifiers ending in
2577`_t' as data types."
2578
7492acc9
MM
2579 (let* ((sql-indirect-features nil)
2580 (font-lock-var (sql-get-product-feature product :font-lock))
2581 (old-val))
2582
2583 (setq old-val (symbol-value font-lock-var))
2584 (set font-lock-var
9fd8cb36
SM
2585 (if (eq append 'set)
2586 keywords
2587 (if append
7492acc9
MM
2588 (append old-val keywords)
2589 (append keywords old-val))))))
95e4b2ef 2590
5474c40f 2591(defun sql-for-each-login (login-params body)
93852cb0 2592 "Iterate through login parameters and return a list of results."
5474c40f
MM
2593 (delq nil
2594 (mapcar
2595 (lambda (param)
93852cb0
SM
2596 (let ((token (or (car-safe param) param))
2597 (plist (cdr-safe param)))
74790210 2598 (funcall body token plist)))
5474c40f
MM
2599 login-params)))
2600
95e4b2ef 2601\f
c0bbaf57 2602
624ef9b3
GM
2603;;; Functions to switch highlighting
2604
fbcc67e2
MM
2605(defun sql-product-syntax-table ()
2606 (let ((table (copy-syntax-table sql-mode-syntax-table)))
2607 (mapc (lambda (entry)
2608 (modify-syntax-entry (car entry) (cdr entry) table))
2609 (sql-get-product-feature sql-product :syntax-alist))
2610 table))
2611
2612(defun sql-product-font-lock-syntax-alist ()
2613 (append
2614 ;; Change all symbol character to word characters
2615 (mapcar
2616 (lambda (entry) (if (string= (substring (cdr entry) 0 1) "_")
2617 (cons (car entry)
2618 (concat "w" (substring (cdr entry) 1)))
2619 entry))
2620 (sql-get-product-feature sql-product :syntax-alist))
2621 '((?_ . "w"))))
2622
78024f88 2623(defun sql-highlight-product ()
c38762fd 2624 "Turn on the font highlighting for the SQL product selected."
55659495 2625 (when (derived-mode-p 'sql-mode)
fbcc67e2
MM
2626 ;; Enhance the syntax table for the product
2627 (set-syntax-table (sql-product-syntax-table))
2628
78024f88
AS
2629 ;; Setup font-lock
2630 (sql-product-font-lock nil t)
2631
78024f88 2632 ;; Set the mode name to include the product.
7492acc9
MM
2633 (setq mode-name (concat "SQL[" (or (sql-get-product-feature sql-product :name)
2634 (symbol-name sql-product)) "]"))))
78024f88
AS
2635
2636(defun sql-set-product (product)
c38762fd 2637 "Set `sql-product' to PRODUCT and enable appropriate highlighting."
55659495 2638 (interactive
74790210 2639 (list (sql-read-product "SQL product: ")))
55659495 2640 (if (stringp product) (setq product (intern product)))
9fd8cb36 2641 (when (not (assoc product sql-product-alist))
78024f88
AS
2642 (error "SQL product %s is not supported; treated as ANSI" product)
2643 (setq product 'ansi))
2644
2645 ;; Save product setting and fontify.
2646 (setq sql-product product)
2647 (sql-highlight-product))
624ef9b3
GM
2648\f
2649
04231ab8
MB
2650;;; Compatibility functions
2651
2652(if (not (fboundp 'comint-line-beginning-position))
2653 ;; comint-line-beginning-position is defined in Emacs 21
2654 (defun comint-line-beginning-position ()
063c6324 2655 "Return the buffer position of the beginning of the line, after any prompt.
fbcc67e2
MM
2656The prompt is assumed to be any text at the beginning of the line
2657matching the regular expression `comint-prompt-regexp', a buffer
2658local variable."
04231ab8
MB
2659 (save-excursion (comint-bol nil) (point))))
2660
93852cb0
SM
2661;;; SMIE support
2662
2663;; Needs a lot more love than I can provide. --Stef
2664
2665;; (require 'smie)
2666
2667;; (defconst sql-smie-grammar
2668;; (smie-prec2->grammar
2669;; (smie-bnf->prec2
2670;; ;; Partly based on http://www.h2database.com/html/grammar.html
2671;; '((cmd ("SELECT" select-exp "FROM" select-table-exp)
2672;; )
2673;; (select-exp ("*") (exp) (exp "AS" column-alias))
2674;; (column-alias)
2675;; (select-table-exp (table-exp "WHERE" exp) (table-exp))
2676;; (table-exp)
2677;; (exp ("CASE" exp "WHEN" exp "THEN" exp "ELSE" exp "END")
2678;; ("CASE" exp "WHEN" exp "THEN" exp "END"))
2679;; ;; Random ad-hoc additions.
2680;; (foo (foo "," foo))
2681;; )
2682;; '((assoc ",")))))
2683
2684;; (defun sql-smie-rules (kind token)
2685;; (pcase (cons kind token)
2686;; (`(:list-intro . ,_) t)
2687;; (`(:before . "(") (smie-rule-parent))))
2688
fbcc67e2
MM
2689;;; Motion Functions
2690
2691(defun sql-statement-regexp (prod)
2692 (let* ((ansi-stmt (sql-get-product-feature 'ansi :statement))
2693 (prod-stmt (sql-get-product-feature prod :statement)))
2694 (concat "^\\<"
2695 (if prod-stmt
2696 ansi-stmt
2697 (concat "\\(" ansi-stmt "\\|" prod-stmt "\\)"))
2698 "\\>")))
2699
2700(defun sql-beginning-of-statement (arg)
93852cb0 2701 "Move to the beginning of the current SQL statement."
fbcc67e2
MM
2702 (interactive "p")
2703
2704 (let ((here (point))
2705 (regexp (sql-statement-regexp sql-product))
2706 last next)
2707
2708 ;; Go to the end of the statement before the start we desire
2709 (setq last (or (sql-end-of-statement (- arg))
2710 (point-min)))
2711 ;; And find the end after that
2712 (setq next (or (sql-end-of-statement 1)
2713 (point-max)))
2714
2715 ;; Our start must be between them
2716 (goto-char last)
2717 ;; Find an beginning-of-stmt that's not in a comment
2718 (while (and (re-search-forward regexp next t 1)
2719 (nth 7 (syntax-ppss)))
2720 (goto-char (match-end 0)))
2721 (goto-char
2722 (if (match-data)
2723 (match-beginning 0)
2724 last))
2725 (beginning-of-line)
2726 ;; If we didn't move, try again
2727 (when (= here (point))
93852cb0 2728 (sql-beginning-of-statement (* 2 (cl-signum arg))))))
fbcc67e2
MM
2729
2730(defun sql-end-of-statement (arg)
93852cb0 2731 "Move to the end of the current SQL statement."
fbcc67e2
MM
2732 (interactive "p")
2733 (let ((term (sql-get-product-feature sql-product :terminator))
2734 (re-search (if (> 0 arg) 're-search-backward 're-search-forward))
2735 (here (point))
2736 (n 0))
2737 (when (consp term)
2738 (setq term (car term)))
2739 ;; Iterate until we've moved the desired number of stmt ends
93852cb0 2740 (while (not (= (cl-signum arg) 0))
fbcc67e2
MM
2741 ;; if we're looking at the terminator, jump by 2
2742 (if (or (and (> 0 arg) (looking-back term))
2743 (and (< 0 arg) (looking-at term)))
2744 (setq n 2)
2745 (setq n 1))
2746 ;; If we found another end-of-stmt
2747 (if (not (apply re-search term nil t n nil))
2748 (setq arg 0)
2749 ;; count it if we're not in a comment
2750 (unless (nth 7 (syntax-ppss))
93852cb0 2751 (setq arg (- arg (cl-signum arg))))))
fbcc67e2
MM
2752 (goto-char (if (match-data)
2753 (match-end 0)
2754 here))))
95e4b2ef
RS
2755
2756;;; Small functions
2757
9ef3882f
GM
2758(defun sql-magic-go (arg)
2759 "Insert \"o\" and call `comint-send-input'.
2760`sql-electric-stuff' must be the symbol `go'."
2761 (interactive "P")
2762 (self-insert-command (prefix-numeric-value arg))
2763 (if (and (equal sql-electric-stuff 'go)
2764 (save-excursion
3035b156
MB
2765 (comint-bol nil)
2766 (looking-at "go\\b")))
9ef3882f
GM
2767 (comint-send-input)))
2768
2769(defun sql-magic-semicolon (arg)
2770 "Insert semicolon and call `comint-send-input'.
2771`sql-electric-stuff' must be the symbol `semicolon'."
2772 (interactive "P")
2773 (self-insert-command (prefix-numeric-value arg))
2774 (if (equal sql-electric-stuff 'semicolon)
2775 (comint-send-input)))
2776
95e4b2ef
RS
2777(defun sql-accumulate-and-indent ()
2778 "Continue SQL statement on the next line."
2779 (interactive)
f4df536d 2780 (if (fboundp 'comint-accumulate)
9ef3882f
GM
2781 (comint-accumulate)
2782 (newline))
95e4b2ef
RS
2783 (indent-according-to-mode))
2784
7492acc9
MM
2785(defun sql-help-list-products (indent freep)
2786 "Generate listing of products available for use under SQLi.
2787
fbcc67e2 2788List products with :free-software attribute set to FREEP. Indent
7492acc9
MM
2789each line with INDENT."
2790
2791 (let (sqli-func doc)
2792 (setq doc "")
2793 (dolist (p sql-product-alist)
2794 (setq sqli-func (intern (concat "sql-" (symbol-name (car p)))))
2795
2796 (if (and (fboundp sqli-func)
2797 (eq (sql-get-product-feature (car p) :free-software) freep))
2798 (setq doc
2799 (concat doc
2800 indent
2801 (or (sql-get-product-feature (car p) :name)
2802 (symbol-name (car p)))
2803 ":\t"
2804 "\\["
2805 (symbol-name sqli-func)
2806 "]\n"))))
2807 doc))
2808
95e4b2ef 2809;;;###autoload
57618ecf
SM
2810(eval
2811 ;; FIXME: This dynamic-docstring-function trick doesn't work for byte-compiled
2812 ;; functions, because of the lazy-loading of docstrings, which strips away
2813 ;; text properties.
2814 '(defun sql-help ()
2815 #("Show short help for the SQL modes.
95e4b2ef
RS
2816
2817Use an entry function to open an interactive SQL buffer. This buffer is
dab100d7 2818usually named `*SQL*'. The name of the major mode is SQLi.
95e4b2ef
RS
2819
2820Use the following commands to start a specific SQL interpreter:
2821
7492acc9 2822 \\\\FREE
50842164
RS
2823
2824Other non-free SQL implementations are also supported:
2825
7492acc9 2826 \\\\NONFREE
50842164
RS
2827
2828But we urge you to choose a free implementation instead of these.
95e4b2ef 2829
7492acc9
MM
2830You can also use \\[sql-product-interactive] to invoke the
2831interpreter for the current `sql-product'.
2832
95e4b2ef
RS
2833Once you have the SQLi buffer, you can enter SQL statements in the
2834buffer. The output generated is appended to the buffer and a new prompt
2835is generated. See the In/Out menu in the SQLi buffer for some functions
2836that help you navigate through the buffer, the input history, etc.
2837
95e4b2ef
RS
2838If you have a really complex SQL statement or if you are writing a
2839procedure, you can do this in a separate buffer. Put the new buffer in
2840`sql-mode' by calling \\[sql-mode]. The name of this buffer can be
2841anything. The name of the major mode is SQL.
2842
2843In this SQL buffer (SQL mode), you can send the region or the entire
2844buffer to the interactive SQL buffer (SQLi mode). The results are
2845appended to the SQLi buffer without disturbing your SQL buffer."
57618ecf 2846 0 1 (dynamic-docstring-function sql--make-help-docstring))
95e4b2ef 2847 (interactive)
57618ecf 2848 (describe-function 'sql-help)))
7492acc9 2849
57618ecf
SM
2850(defun sql--make-help-docstring (doc _fun)
2851 "Insert references to loaded products into the help buffer string."
2852
2853 ;; Insert FREE software list
2854 (when (string-match "^\\(\\s-*\\)[\\\\][\\\\]FREE\\s-*\n" doc 0)
2855 (setq doc (replace-match (sql-help-list-products (match-string 1 doc) t)
2856 t t doc 0)))
2857
2858 ;; Insert non-FREE software list
2859 (when (string-match "^\\(\\s-*\\)[\\\\][\\\\]NONFREE\\s-*\n" doc 0)
2860 (setq doc (replace-match (sql-help-list-products (match-string 1 doc) nil)
2861 t t doc 0)))
2862 doc)
95e4b2ef 2863
f6561e1f 2864(defun sql-get-login-ext (symbol prompt history-var plist)
5474c40f
MM
2865 "Prompt user with extended login parameters.
2866
2bb1ae55 2867The global value of SYMBOL is the last value and the global value
f6561e1f
MM
2868of the SYMBOL is set based on the user's input.
2869
74790210 2870If PLIST is nil, then the user is simply prompted for a string
5474c40f
MM
2871value.
2872
74790210
MM
2873The property `:default' specifies the default value. If the
2874`:number' property is non-nil then ask for a number.
5474c40f 2875
74790210
MM
2876The `:file' property prompts for a file name that must match the
2877regexp pattern specified in its value.
5474c40f 2878
74790210
MM
2879The `:completion' property prompts for a string specified by its
2880value. (The property value is used as the PREDICATE argument to
2881`completing-read'.)"
2bb1ae55 2882 (set-default
f6561e1f
MM
2883 symbol
2884 (let* ((default (plist-get plist :default))
2885 (last-value (default-value symbol))
2886 (prompt-def
2887 (if default
2888 (if (string-match "\\(\\):[ \t]*\\'" prompt)
2889 (replace-match (format " (default \"%s\")" default) t t prompt 1)
2890 (replace-regexp-in-string "[ \t]*\\'"
2891 (format " (default \"%s\") " default)
2892 prompt t t))
2893 prompt))
2894 (use-dialog-box nil))
2895 (cond
2896 ((plist-member plist :file)
2897 (expand-file-name
2898 (read-file-name prompt
2899 (file-name-directory last-value) default t
2900 (file-name-nondirectory last-value)
2901 (when (plist-get plist :file)
2902 `(lambda (f)
2903 (string-match
2904 (concat "\\<" ,(plist-get plist :file) "\\>")
2905 (file-name-nondirectory f)))))))
2906
2907 ((plist-member plist :completion)
2908 (completing-read prompt-def (plist-get plist :completion) nil t
2909 last-value history-var default))
2910
2911 ((plist-get plist :number)
2912 (read-number prompt (or default last-value 0)))
2913
2914 (t
93852cb0 2915 (read-string prompt-def last-value history-var default))))))
5474c40f 2916
95e4b2ef
RS
2917(defun sql-get-login (&rest what)
2918 "Get username, password and database from the user.
2919
dab100d7 2920The variables `sql-user', `sql-password', `sql-server', and
eb3f61dd 2921`sql-database' can be customized. They are used as the default values.
dab100d7
RS
2922Usernames, servers and databases are stored in `sql-user-history',
2923`sql-server-history' and `database-history'. Passwords are not stored
2924in a history.
95e4b2ef 2925
7492acc9
MM
2926Parameter WHAT is a list of tokens passed as arguments in the
2927function call. The function asks for the username if WHAT
2928contains the symbol `user', for the password if it contains the
2929symbol `password', for the server if it contains the symbol
2930`server', and for the database if it contains the symbol
2931`database'. The members of WHAT are processed in the order in
2932which they are provided.
95e4b2ef 2933
74790210
MM
2934Each token may also be a list with the token in the car and a
2935plist of options as the cdr. The following properties are
2936supported:
5474c40f 2937
74790210
MM
2938 :file <filename-regexp>
2939 :completion <list-of-strings-or-function>
2940 :default <default-value>
2941 :number t
5474c40f 2942
95e4b2ef
RS
2943In order to ask the user for username, password and database, call the
2944function like this: (sql-get-login 'user 'password 'database)."
93852cb0
SM
2945 (dolist (w what)
2946 (let ((plist (cdr-safe w)))
2947 (pcase (or (car-safe w) w)
2948 (`user
2949 (sql-get-login-ext 'sql-user "User: " 'sql-user-history plist))
74790210 2950
93852cb0
SM
2951 (`password
2952 (setq-default sql-password
2953 (read-passwd "Password: " nil sql-password)))
74790210 2954
93852cb0
SM
2955 (`server
2956 (sql-get-login-ext 'sql-server "Server: " 'sql-server-history plist))
74790210 2957
93852cb0
SM
2958 (`database
2959 (sql-get-login-ext 'sql-database "Database: "
2960 'sql-database-history plist))
74790210 2961
93852cb0
SM
2962 (`port
2963 (sql-get-login-ext 'sql-port "Port: "
2964 nil (append '(:number t) plist)))))))
74790210 2965
fbcc67e2 2966(defun sql-find-sqli-buffer (&optional product connection)
93852cb0 2967 "Return the name of the current default SQLi buffer or nil.
9250002f
MM
2968In order to qualify, the SQLi buffer must be alive, be in
2969`sql-interactive-mode' and have a process."
a386ac70 2970 (let ((buf sql-buffer)
74790210 2971 (prod (or product sql-product)))
a386ac70
MM
2972 (or
2973 ;; Current sql-buffer, if there is one.
fbcc67e2 2974 (and (sql-buffer-live-p buf prod connection)
a386ac70
MM
2975 buf)
2976 ;; Global sql-buffer
2977 (and (setq buf (default-value 'sql-buffer))
fbcc67e2 2978 (sql-buffer-live-p buf prod connection)
a386ac70
MM
2979 buf)
2980 ;; Look thru each buffer
2981 (car (apply 'append
2982 (mapcar (lambda (b)
fbcc67e2 2983 (and (sql-buffer-live-p b prod connection)
a386ac70
MM
2984 (list (buffer-name b))))
2985 (buffer-list)))))))
46d94d0d
GM
2986
2987(defun sql-set-sqli-buffer-generally ()
f4df536d 2988 "Set SQLi buffer for all SQL buffers that have none.
46d94d0d
GM
2989This function checks all SQL buffers for their SQLi buffer. If their
2990SQLi buffer is nonexistent or has no process, it is set to the current
2991default SQLi buffer. The current default SQLi buffer is determined
2992using `sql-find-sqli-buffer'. If `sql-buffer' is set,
2993`sql-set-sqli-hook' is run."
2994 (interactive)
2995 (save-excursion
2996 (let ((buflist (buffer-list))
9250002f
MM
2997 (default-buffer (sql-find-sqli-buffer)))
2998 (setq-default sql-buffer default-buffer)
46d94d0d
GM
2999 (while (not (null buflist))
3000 (let ((candidate (car buflist)))
3001 (set-buffer candidate)
55659495 3002 (if (and (derived-mode-p 'sql-mode)
a386ac70 3003 (not (sql-buffer-live-p sql-buffer)))
46d94d0d 3004 (progn
9250002f 3005 (setq sql-buffer default-buffer)
a386ac70
MM
3006 (when default-buffer
3007 (run-hooks 'sql-set-sqli-hook)))))
46d94d0d
GM
3008 (setq buflist (cdr buflist))))))
3009
c7055d66
RS
3010(defun sql-set-sqli-buffer ()
3011 "Set the SQLi buffer SQL strings are sent to.
95e4b2ef 3012
c7055d66
RS
3013Call this function in a SQL buffer in order to set the SQLi buffer SQL
3014strings are sent to. Calling this function sets `sql-buffer' and runs
3015`sql-set-sqli-hook'.
dab100d7 3016
c7055d66 3017If you call it from a SQL buffer, this sets the local copy of
801d1cb0 3018`sql-buffer'.
dab100d7 3019
c7055d66 3020If you call it from anywhere else, it sets the global copy of
dab100d7
RS
3021`sql-buffer'."
3022 (interactive)
46d94d0d
GM
3023 (let ((default-buffer (sql-find-sqli-buffer)))
3024 (if (null default-buffer)
a386ac70
MM
3025 (error "There is no suitable SQLi buffer")
3026 (let ((new-buffer (read-buffer "New SQLi buffer: " default-buffer t)))
3027 (if (null (sql-buffer-live-p new-buffer))
3028 (error "Buffer %s is not a working SQLi buffer" new-buffer)
3029 (when new-buffer
3030 (setq sql-buffer new-buffer)
3031 (run-hooks 'sql-set-sqli-hook)))))))
dab100d7
RS
3032
3033(defun sql-show-sqli-buffer ()
3034 "Show the name of current SQLi buffer.
3035
3036This is the buffer SQL strings are sent to. It is stored in the
3037variable `sql-buffer'. See `sql-help' on how to create such a buffer."
3038 (interactive)
fbcc67e2
MM
3039 (if (or (null sql-buffer)
3040 (null (buffer-live-p (get-buffer sql-buffer))))
c7055d66 3041 (message "%s has no SQLi buffer set." (buffer-name (current-buffer)))
dab100d7 3042 (if (null (get-buffer-process sql-buffer))
9250002f
MM
3043 (message "Buffer %s has no process." sql-buffer)
3044 (message "Current SQLi buffer is %s." sql-buffer))))
dab100d7 3045
c7055d66 3046(defun sql-make-alternate-buffer-name ()
c38762fd 3047 "Return a string that can be used to rename a SQLi buffer.
c7055d66
RS
3048
3049This is used to set `sql-alternate-buffer-name' within
30c4d8dc
MM
3050`sql-interactive-mode'.
3051
3052If the session was started with `sql-connect' then the alternate
3053name would be the name of the connection.
3054
3055Otherwise, it uses the parameters identified by the :sqlilogin
3056parameter.
3057
3058If all else fails, the alternate name would be the user and
3059server/database name."
3060
d26b0ea9
MM
3061 (let ((name ""))
3062
5474c40f
MM
3063 ;; Build a name using the :sqli-login setting
3064 (setq name
3065 (apply 'concat
3bd2cfef
MM
3066 (cdr
3067 (apply 'append nil
3068 (sql-for-each-login
3069 (sql-get-product-feature sql-product :sqli-login)
74790210 3070 (lambda (token plist)
93852cb0
SM
3071 (pcase token
3072 (`user
3bd2cfef
MM
3073 (unless (string= "" sql-user)
3074 (list "/" sql-user)))
93852cb0 3075 (`port
9250002f
MM
3076 (unless (or (not (numberp sql-port))
3077 (= 0 sql-port))
3078 (list ":" (number-to-string sql-port))))
93852cb0 3079 (`server
3bd2cfef
MM
3080 (unless (string= "" sql-server)
3081 (list "."
74790210 3082 (if (plist-member plist :file)
3bd2cfef
MM
3083 (file-name-nondirectory sql-server)
3084 sql-server))))
93852cb0 3085 (`database
9250002f 3086 (unless (string= "" sql-database)
3bd2cfef 3087 (list "@"
74790210 3088 (if (plist-member plist :file)
3bd2cfef
MM
3089 (file-name-nondirectory sql-database)
3090 sql-database))))
3091
93852cb0
SM
3092 ;; (`password nil)
3093 (_ nil))))))))
5474c40f
MM
3094
3095 ;; If there's a connection, use it and the name thus far
d26b0ea9
MM
3096 (if sql-connection
3097 (format "<%s>%s" sql-connection (or name ""))
5474c40f
MM
3098
3099 ;; If there is no name, try to create something meaningful
3100 (if (string= "" (or name ""))
3101 (concat
3102 (if (string= "" sql-user)
3103 (if (string= "" (user-login-name))
3104 ()
3105 (concat (user-login-name) "/"))
3106 (concat sql-user "/"))
3107 (if (string= "" sql-database)
3108 (if (string= "" sql-server)
3109 (system-name)
3110 sql-server)
3111 sql-database))
3112
3bd2cfef
MM
3113 ;; Use the name we've got
3114 name))))
c7055d66 3115
9250002f
MM
3116(defun sql-rename-buffer (&optional new-name)
3117 "Rename a SQL interactive buffer.
3118
0d327994 3119Prompts for the new name if command is preceded by
9250002f
MM
3120\\[universal-argument]. If no buffer name is provided, then the
3121`sql-alternate-buffer-name' is used.
3122
3123The actual buffer name set will be \"*SQL: NEW-NAME*\". If
3124NEW-NAME is empty, then the buffer name will be \"*SQL*\"."
3125 (interactive "P")
3126
3127 (if (not (derived-mode-p 'sql-interactive-mode))
3128 (message "Current buffer is not a SQL interactive buffer")
3129
a386ac70
MM
3130 (setq sql-alternate-buffer-name
3131 (cond
3132 ((stringp new-name) new-name)
3133 ((consp new-name)
9250002f 3134 (read-string "Buffer name (\"*SQL: XXX*\"; enter `XXX'): "
a386ac70
MM
3135 sql-alternate-buffer-name))
3136 (t sql-alternate-buffer-name)))
9250002f
MM
3137
3138 (rename-buffer (if (string= "" sql-alternate-buffer-name)
3139 "*SQL*"
3140 (format "*SQL: %s*" sql-alternate-buffer-name))
3141 t)))
c7055d66 3142
95e4b2ef
RS
3143(defun sql-copy-column ()
3144 "Copy current column to the end of buffer.
3145Inserts SELECT or commas if appropriate."
3146 (interactive)
3147 (let ((column))
3148 (save-excursion
7492acc9 3149 (setq column (buffer-substring-no-properties
95e4b2ef
RS
3150 (progn (forward-char 1) (backward-sexp 1) (point))
3151 (progn (forward-sexp 1) (point))))
3152 (goto-char (point-max))
3035b156
MB
3153 (let ((bol (comint-line-beginning-position)))
3154 (cond
3155 ;; if empty command line, insert SELECT
3156 ((= bol (point))
3157 (insert "SELECT "))
3158 ;; else if appending to INTO .* (, SELECT or ORDER BY, insert a comma
3159 ((save-excursion
3160 (re-search-backward "\\b\\(\\(into\\s-+\\S-+\\s-+(\\)\\|select\\|order by\\) .+"
3161 bol t))
3162 (insert ", "))
3163 ;; else insert a space
3164 (t
b9584f65 3165 (if (eq (preceding-char) ?\s)
3035b156
MB
3166 nil
3167 (insert " ")))))
95e4b2ef
RS
3168 ;; in any case, insert the column
3169 (insert column)
3170 (message "%s" column))))
3171
063c6324
JB
3172;; On Windows, SQL*Plus for Oracle turns on full buffering for stdout
3173;; if it is not attached to a character device; therefore placeholder
77d352a6
GM
3174;; replacement by SQL*Plus is fully buffered. The workaround lets
3175;; Emacs query for the placeholders.
3176
3177(defvar sql-placeholder-history nil
3178 "History of placeholder values used.")
3179
7492acc9
MM
3180(defun sql-placeholders-filter (string)
3181 "Replace placeholders in STRING.
c38762fd 3182Placeholders are words starting with an ampersand like &this."
7492acc9
MM
3183
3184 (when sql-oracle-scan-on
3185 (while (string-match "&\\(\\sw+\\)" string)
3186 (setq string (replace-match
3187 (read-from-minibuffer
3188 (format "Enter value for %s: " (match-string 1 string))
3189 nil nil nil 'sql-placeholder-history)
3190 t t string))))
3191 string)
77d352a6 3192
624ef9b3
GM
3193;; Using DB2 interactively, newlines must be escaped with " \".
3194;; The space before the backslash is relevant.
04e082b0 3195
7492acc9 3196(defun sql-escape-newlines-filter (string)
c38762fd 3197 "Escape newlines in STRING.
624ef9b3 3198Every newline in STRING will be preceded with a space and a backslash."
04e082b0
MM
3199 (if (not sql-db2-escape-newlines)
3200 string
3201 (let ((result "") (start 0) mb me)
3202 (while (string-match "\n" string start)
3203 (setq mb (match-beginning 0)
3204 me (match-end 0)
3205 result (concat result
3206 (substring string start mb)
3207 (if (and (> mb 1)
3208 (string-equal " \\" (substring string (- mb 2) mb)))
3209 "" " \\\n"))
3210 start me))
3211 (concat result (substring string start)))))
624ef9b3 3212
95e4b2ef
RS
3213\f
3214
7492acc9
MM
3215;;; Input sender for SQLi buffers
3216
3bd2cfef
MM
3217(defvar sql-output-newline-count 0
3218 "Number of newlines in the input string.
3219
3220Allows the suppression of continuation prompts.")
3221
7492acc9 3222(defun sql-input-sender (proc string)
c38762fd 3223 "Send STRING to PROC after applying filters."
7492acc9
MM
3224
3225 (let* ((product (with-current-buffer (process-buffer proc) sql-product))
3226 (filter (sql-get-product-feature product :input-filter)))
3227
3bd2cfef
MM
3228 ;; Apply filter(s)
3229 (cond
3230 ((not filter)
3231 nil)
3232 ((functionp filter)
3233 (setq string (funcall filter string)))
3234 ((listp filter)
3235 (mapc (lambda (f) (setq string (funcall f string))) filter))
3236 (t nil))
3237
3238 ;; Count how many newlines in the string
3239 (setq sql-output-newline-count 0)
3240 (mapc (lambda (ch)
3241 (when (eq ch ?\n)
3242 (setq sql-output-newline-count (1+ sql-output-newline-count))))
3243 string)
3244
7492acc9 3245 ;; Send the string
3bd2cfef
MM
3246 (comint-simple-send proc string)))
3247
3248;;; Strip out continuation prompts
3249
fbcc67e2
MM
3250(defvar sql-preoutput-hold nil)
3251
3bd2cfef
MM
3252(defun sql-interactive-remove-continuation-prompt (oline)
3253 "Strip out continuation prompts out of the OLINE.
3254
3255Added to the `comint-preoutput-filter-functions' hook in a SQL
fbcc67e2 3256interactive buffer. If `sql-output-newline-count' is greater than
3bd2cfef 3257zero, then an output line matching the continuation prompt is filtered
fbcc67e2
MM
3258out. If the count is zero, then a newline is inserted into the output
3259to force the output from the query to appear on a new line.
3260
3261The complication to this filter is that the continuation prompts
3262may arrive in multiple chunks. If they do, then the function
3263saves any unfiltered output in a buffer and prepends that buffer
3264to the next chunk to properly match the broken-up prompt.
3265
3266If the filter gets confused, it should reset and stop filtering
3267to avoid deleting non-prompt output."
3268
3269 (let (did-filter)
3270 (setq oline (concat (or sql-preoutput-hold "") oline)
3271 sql-preoutput-hold nil)
3272
3273 (if (and comint-prompt-regexp
3274 (integerp sql-output-newline-count)
3275 (>= sql-output-newline-count 1))
3276 (progn
3277 (while (and (not (string= oline ""))
3278 (> sql-output-newline-count 0)
3279 (string-match comint-prompt-regexp oline)
3280 (= (match-beginning 0) 0))
3281
3282 (setq oline (replace-match "" nil nil oline)
3283 sql-output-newline-count (1- sql-output-newline-count)
3284 did-filter t))
3285
3286 (if (= sql-output-newline-count 0)
3287 (setq sql-output-newline-count nil
9d55215c 3288 oline (concat "\n" oline))
fbcc67e2
MM
3289
3290 (setq sql-preoutput-hold oline
3291 oline ""))
3292
3293 (unless did-filter
3294 (setq oline (or sql-preoutput-hold "")
3295 sql-preoutput-hold nil
3296 sql-output-newline-count nil)))
3297
3298 (setq sql-output-newline-count nil))
3299
3300 oline))
7492acc9 3301
95e4b2ef
RS
3302;;; Sending the region to the SQLi buffer.
3303
7492acc9
MM
3304(defun sql-send-string (str)
3305 "Send the string STR to the SQL process."
3306 (interactive "sSQL Text: ")
3307
3bd2cfef
MM
3308 (let ((comint-input-sender-no-newline nil)
3309 (s (replace-regexp-in-string "[[:space:]\n\r]+\\'" "" str)))
9250002f 3310 (if (sql-buffer-live-p sql-buffer)
7492acc9
MM
3311 (progn
3312 ;; Ignore the hoping around...
3313 (save-excursion
7492acc9
MM
3314 ;; Set product context
3315 (with-current-buffer sql-buffer
3bd2cfef
MM
3316 ;; Send the string (trim the trailing whitespace)
3317 (sql-input-sender (get-buffer-process sql-buffer) s)
7492acc9
MM
3318
3319 ;; Send a command terminator if we must
3320 (if sql-send-terminator
3bd2cfef 3321 (sql-send-magic-terminator sql-buffer s sql-send-terminator))
7492acc9 3322
9250002f 3323 (message "Sent string to buffer %s." sql-buffer)))
7492acc9
MM
3324
3325 ;; Display the sql buffer
3326 (if sql-pop-to-buffer-after-send-region
3327 (pop-to-buffer sql-buffer)
3328 (display-buffer sql-buffer)))
3329
3330 ;; We don't have no stinkin' sql
3331 (message "No SQL process started."))))
3332
95e4b2ef
RS
3333(defun sql-send-region (start end)
3334 "Send a region to the SQL process."
3335 (interactive "r")
7492acc9 3336 (sql-send-string (buffer-substring-no-properties start end)))
95e4b2ef 3337
dab100d7
RS
3338(defun sql-send-paragraph ()
3339 "Send the current paragraph to the SQL process."
3340 (interactive)
3341 (let ((start (save-excursion
3342 (backward-paragraph)
3343 (point)))
3344 (end (save-excursion
3345 (forward-paragraph)
3346 (point))))
3347 (sql-send-region start end)))
3348
95e4b2ef
RS
3349(defun sql-send-buffer ()
3350 "Send the buffer contents to the SQL process."
3351 (interactive)
3352 (sql-send-region (point-min) (point-max)))
3353
7492acc9 3354(defun sql-send-magic-terminator (buf str terminator)
c38762fd 3355 "Send TERMINATOR to buffer BUF if its not present in STR."
3bd2cfef 3356 (let (comint-input-sender-no-newline pat term)
7492acc9
MM
3357 ;; If flag is merely on(t), get product-specific terminator
3358 (if (eq terminator t)
3359 (setq terminator (sql-get-product-feature sql-product :terminator)))
3360
3361 ;; If there is no terminator specified, use default ";"
3362 (unless terminator
3363 (setq terminator ";"))
3364
3365 ;; Parse the setting into the pattern and the terminator string
3366 (cond ((stringp terminator)
3367 (setq pat (regexp-quote terminator)
3368 term terminator))
3369 ((consp terminator)
3370 (setq pat (car terminator)
3371 term (cdr terminator)))
3372 (t
3373 nil))
3374
3375 ;; Check to see if the pattern is present in the str already sent
3376 (unless (and pat term
3bd2cfef
MM
3377 (string-match (concat pat "\\'") str))
3378 (comint-simple-send (get-buffer-process buf) term)
3379 (setq sql-output-newline-count
3380 (if sql-output-newline-count
3381 (1+ sql-output-newline-count)
9d55215c 3382 1)))))
7492acc9
MM
3383
3384(defun sql-remove-tabs-filter (str)
3385 "Replace tab characters with spaces."
3386 (replace-regexp-in-string "\t" " " str nil t))
9fd8cb36 3387
95e4b2ef
RS
3388(defun sql-toggle-pop-to-buffer-after-send-region (&optional value)
3389 "Toggle `sql-pop-to-buffer-after-send-region'.
3390
3391If given the optional parameter VALUE, sets
063c6324 3392`sql-toggle-pop-to-buffer-after-send-region' to VALUE."
95e4b2ef
RS
3393 (interactive "P")
3394 (if value
3395 (setq sql-pop-to-buffer-after-send-region value)
801d1cb0 3396 (setq sql-pop-to-buffer-after-send-region
7492acc9 3397 (null sql-pop-to-buffer-after-send-region))))
95e4b2ef
RS
3398
3399\f
3400
a386ac70
MM
3401;;; Redirect output functions
3402
fbcc67e2
MM
3403(defvar sql-debug-redirect nil
3404 "If non-nil, display messages related to the use of redirection.")
3405
3406(defun sql-str-literal (s)
3407 (concat "'" (replace-regexp-in-string "[']" "''" s) "'"))
3408
3409(defun sql-redirect (sqlbuf command &optional outbuf save-prior)
a386ac70
MM
3410 "Execute the SQL command and send output to OUTBUF.
3411
fbcc67e2 3412SQLBUF must be an active SQL interactive buffer. OUTBUF may be
a386ac70
MM
3413an existing buffer, or the name of a non-existing buffer. If
3414omitted the output is sent to a temporary buffer which will be
3415killed after the command completes. COMMAND should be a string
fbcc67e2
MM
3416of commands accepted by the SQLi program. COMMAND may also be a
3417list of SQLi command strings."
3418
3419 (let* ((visible (and outbuf
3420 (not (string= " " (substring outbuf 0 1))))))
3421 (when visible
3422 (message "Executing SQL command..."))
3423 (if (consp command)
3424 (mapc (lambda (c) (sql-redirect-one sqlbuf c outbuf save-prior))
3425 command)
3426 (sql-redirect-one sqlbuf command outbuf save-prior))
3427 (when visible
3428 (message "Executing SQL command...done"))))
3429
3430(defun sql-redirect-one (sqlbuf command outbuf save-prior)
3431 (with-current-buffer sqlbuf
a386ac70
MM
3432 (let ((buf (get-buffer-create (or outbuf " *SQL-Redirect*")))
3433 (proc (get-buffer-process (current-buffer)))
3434 (comint-prompt-regexp (sql-get-product-feature sql-product
3435 :prompt-regexp))
3436 (start nil))
3437 (with-current-buffer buf
bb5aa5d6 3438 (setq view-read-only nil)
a386ac70
MM
3439 (unless save-prior
3440 (erase-buffer))
3441 (goto-char (point-max))
74790210
MM
3442 (unless (zerop (buffer-size))
3443 (insert "\n"))
a386ac70
MM
3444 (setq start (point)))
3445
fbcc67e2
MM
3446 (when sql-debug-redirect
3447 (message ">>SQL> %S" command))
3448
a386ac70
MM
3449 ;; Run the command
3450 (comint-redirect-send-command-to-process command buf proc nil t)
3451 (while (null comint-redirect-completed)
3452 (accept-process-output nil 1))
3453
74790210 3454 ;; Clean up the output results
a386ac70 3455 (with-current-buffer buf
74790210
MM
3456 ;; Remove trailing whitespace
3457 (goto-char (point-max))
3458 (when (looking-back "[ \t\f\n\r]*" start)
3459 (delete-region (match-beginning 0) (match-end 0)))
3460 ;; Remove echo if there was one
a386ac70
MM
3461 (goto-char start)
3462 (when (looking-at (concat "^" (regexp-quote command) "[\\n]"))
3463 (delete-region (match-beginning 0) (match-end 0)))
fbcc67e2
MM
3464 ;; Remove Ctrl-Ms
3465 (goto-char start)
3466 (while (re-search-forward "\r+$" nil t)
3467 (replace-match "" t t))
a386ac70
MM
3468 (goto-char start)))))
3469
fbcc67e2 3470(defun sql-redirect-value (sqlbuf command regexp &optional regexp-groups)
a386ac70
MM
3471 "Execute the SQL command and return part of result.
3472
fbcc67e2 3473SQLBUF must be an active SQL interactive buffer. COMMAND should
a386ac70
MM
3474be a string of commands accepted by the SQLi program. From the
3475output, the REGEXP is repeatedly matched and the list of
3476REGEXP-GROUPS submatches is returned. This behaves much like
3477\\[comint-redirect-results-list-from-process] but instead of
3478returning a single submatch it returns a list of each submatch
3479for each match."
3480
3481 (let ((outbuf " *SQL-Redirect-values*")
3482 (results nil))
fbcc67e2 3483 (sql-redirect sqlbuf command outbuf nil)
a386ac70
MM
3484 (with-current-buffer outbuf
3485 (while (re-search-forward regexp nil t)
3486 (push
3487 (cond
3488 ;; no groups-return all of them
3489 ((null regexp-groups)
fbcc67e2 3490 (let ((i (/ (length (match-data)) 2))
a386ac70 3491 (r nil))
fbcc67e2
MM
3492 (while (> i 0)
3493 (setq i (1- i))
a386ac70 3494 (push (match-string i) r))
fbcc67e2 3495 r))
a386ac70
MM
3496 ;; one group specified
3497 ((numberp regexp-groups)
3498 (match-string regexp-groups))
a386ac70
MM
3499 ;; list of numbers; return the specified matches only
3500 ((consp regexp-groups)
3501 (mapcar (lambda (c)
3502 (cond
3503 ((numberp c) (match-string c))
3504 ((stringp c) (match-substitute-replacement c))
3505 (t (error "sql-redirect-value: unknown REGEXP-GROUPS value - %s" c))))
3506 regexp-groups))
3507 ;; String is specified; return replacement string
3508 ((stringp regexp-groups)
3509 (match-substitute-replacement regexp-groups))
3510 (t
3511 (error "sql-redirect-value: unknown REGEXP-GROUPS value - %s"
3512 regexp-groups)))
3513 results)))
a386ac70 3514
fbcc67e2
MM
3515 (when sql-debug-redirect
3516 (message ">>SQL> = %S" (reverse results)))
3517
3518 (nreverse results)))
3519
3520(defun sql-execute (sqlbuf outbuf command enhanced arg)
93852cb0 3521 "Execute a command in a SQL interactive buffer and capture the output.
74790210
MM
3522
3523The commands are run in SQLBUF and the output saved in OUTBUF.
3524COMMAND must be a string, a function or a list of such elements.
3525Functions are called with SQLBUF, OUTBUF and ARG as parameters;
3526strings are formatted with ARG and executed.
3527
3528If the results are empty the OUTBUF is deleted, otherwise the
93852cb0 3529buffer is popped into a view window."
74790210
MM
3530 (mapc
3531 (lambda (c)
3532 (cond
3533 ((stringp c)
fbcc67e2 3534 (sql-redirect sqlbuf (if arg (format c arg) c) outbuf) t)
74790210 3535 ((functionp c)
fbcc67e2 3536 (apply c sqlbuf outbuf enhanced arg nil))
74790210
MM
3537 (t (error "Unknown sql-execute item %s" c))))
3538 (if (consp command) command (cons command nil)))
3539
3540 (setq outbuf (get-buffer outbuf))
3541 (if (zerop (buffer-size outbuf))
3542 (kill-buffer outbuf)
3543 (let ((one-win (eq (selected-window)
3544 (get-lru-window))))
3545 (with-current-buffer outbuf
3546 (set-buffer-modified-p nil)
bb5aa5d6 3547 (setq view-read-only t))
74790210
MM
3548 (view-buffer-other-window outbuf)
3549 (when one-win
3550 (shrink-window-if-larger-than-buffer)))))
3551
3552(defun sql-execute-feature (sqlbuf outbuf feature enhanced arg)
3553 "List objects or details in a separate display buffer."
3554 (let (command)
3555 (with-current-buffer sqlbuf
3556 (setq command (sql-get-product-feature sql-product feature)))
3557 (unless command
3558 (error "%s does not support %s" sql-product feature))
3559 (when (consp command)
3560 (setq command (if enhanced
3561 (cdr command)
3562 (car command))))
fbcc67e2
MM
3563 (sql-execute sqlbuf outbuf command enhanced arg)))
3564
3565(defvar sql-completion-object nil
3566 "A list of database objects used for completion.
3567
3568The list is maintained in SQL interactive buffers.")
3569
3570(defvar sql-completion-column nil
3571 "A list of column names used for completion.
3572
3573The list is maintained in SQL interactive buffers.")
3574
3575(defun sql-build-completions-1 (schema completion-list feature)
3576 "Generate a list of objects in the database for use as completions."
3577 (let ((f (sql-get-product-feature sql-product feature)))
3578 (when f
3579 (set completion-list
3580 (let (cl)
3581 (dolist (e (append (symbol-value completion-list)
3582 (apply f (current-buffer) (cons schema nil)))
3583 cl)
3584 (unless (member e cl) (setq cl (cons e cl))))
3585 (sort cl (function string<)))))))
3586
3587(defun sql-build-completions (schema)
3588 "Generate a list of names in the database for use as completions."
3589 (sql-build-completions-1 schema 'sql-completion-object :completion-object)
3590 (sql-build-completions-1 schema 'sql-completion-column :completion-column))
3591
3592(defvar sql-completion-sqlbuf nil)
3593
93852cb0 3594(defun sql--completion-table (string pred action)
fbcc67e2 3595 (when sql-completion-sqlbuf
93852cb0
SM
3596 (with-current-buffer sql-completion-sqlbuf
3597 (let ((schema (and (string-match "\\`\\(\\sw\\(:?\\sw\\|\\s_\\)*\\)[.]" string)
3598 (downcase (match-string 1 string)))))
3599
3600 ;; If we haven't loaded any object name yet, load local schema
3601 (unless sql-completion-object
3602 (sql-build-completions nil))
3603
3604 ;; If they want another schema, load it if we haven't yet
3605 (when schema
3606 (let ((schema-dot (concat schema "."))
3607 (schema-len (1+ (length schema)))
3608 (names sql-completion-object)
3609 has-schema)
3610
3611 (while (and (not has-schema) names)
3612 (setq has-schema (and
3613 (>= (length (car names)) schema-len)
3614 (string= schema-dot
3615 (downcase (substring (car names)
3616 0 schema-len))))
3617 names (cdr names)))
3618 (unless has-schema
3619 (sql-build-completions schema)))))
3620
3621 ;; Try to find the completion
3622 (complete-with-action action sql-completion-object string pred))))
74790210
MM
3623
3624(defun sql-read-table-name (prompt)
3625 "Read the name of a database table."
fbcc67e2
MM
3626 (let* ((tname
3627 (and (buffer-local-value 'sql-contains-names (current-buffer))
3628 (thing-at-point-looking-at
3629 (concat "\\_<\\sw\\(:?\\sw\\|\\s_\\)*"
3630 "\\(?:[.]+\\sw\\(?:\\sw\\|\\s_\\)*\\)*\\_>"))
3631 (buffer-substring-no-properties (match-beginning 0)
3632 (match-end 0))))
3633 (sql-completion-sqlbuf (sql-find-sqli-buffer))
3634 (product (with-current-buffer sql-completion-sqlbuf sql-product))
3635 (completion-ignore-case t))
3636
3637 (if (sql-get-product-feature product :completion-object)
93852cb0 3638 (completing-read prompt #'sql--completion-table
fbcc67e2
MM
3639 nil nil tname)
3640 (read-from-minibuffer prompt tname))))
74790210
MM
3641
3642(defun sql-list-all (&optional enhanced)
34e8a2da
GM
3643 "List all database objects.
3644With optional prefix argument ENHANCED, displays additional
3645details or extends the listing to include other schemas objects."
74790210
MM
3646 (interactive "P")
3647 (let ((sqlbuf (sql-find-sqli-buffer)))
3648 (unless sqlbuf
3649 (error "No SQL interactive buffer found"))
fbcc67e2
MM
3650 (sql-execute-feature sqlbuf "*List All*" :list-all enhanced nil)
3651 (with-current-buffer sqlbuf
3652 ;; Contains the name of database objects
3653 (set (make-local-variable 'sql-contains-names) t)
3654 (set (make-local-variable 'sql-buffer) sqlbuf))))
74790210
MM
3655
3656(defun sql-list-table (name &optional enhanced)
34e8a2da
GM
3657 "List the details of a database table named NAME.
3658Displays the columns in the relation. With optional prefix argument
3659ENHANCED, displays additional details about each column."
74790210
MM
3660 (interactive
3661 (list (sql-read-table-name "Table name: ")
3662 current-prefix-arg))
3663 (let ((sqlbuf (sql-find-sqli-buffer)))
3664 (unless sqlbuf
3665 (error "No SQL interactive buffer found"))
3666 (unless name
3667 (error "No table name specified"))
3668 (sql-execute-feature sqlbuf (format "*List %s*" name)
3669 :list-table enhanced name)))
a386ac70
MM
3670\f
3671
95e4b2ef
RS
3672;;; SQL mode -- uses SQL interactive mode
3673
3674;;;###autoload
175069ef 3675(define-derived-mode sql-mode prog-mode "SQL"
95e4b2ef
RS
3676 "Major mode to edit SQL.
3677
dab100d7 3678You can send SQL statements to the SQLi buffer using
95e4b2ef 3679\\[sql-send-region]. Such a buffer must exist before you can do this.
dab100d7 3680See `sql-help' on how to create SQLi buffers.
95e4b2ef 3681
801d1cb0 3682\\{sql-mode-map}
95e4b2ef
RS
3683Customization: Entry to this mode runs the `sql-mode-hook'.
3684
dab100d7
RS
3685When you put a buffer in SQL mode, the buffer stores the last SQLi
3686buffer created as its destination in the variable `sql-buffer'. This
3687will be the buffer \\[sql-send-region] sends the region to. If this
3688SQLi buffer is killed, \\[sql-send-region] is no longer able to
c7055d66
RS
3689determine where the strings should be sent to. You can set the
3690value of `sql-buffer' using \\[sql-set-sqli-buffer].
95e4b2ef 3691
dab100d7 3692For information on how to create multiple SQLi buffers, see
4da8ff79
RS
3693`sql-interactive-mode'.
3694
3695Note that SQL doesn't have an escape character unless you specify
865fe16f
CY
3696one. If you specify backslash as escape character in SQL, you
3697must tell Emacs. Here's how to do that in your init file:
4da8ff79
RS
3698
3699\(add-hook 'sql-mode-hook
3700 (lambda ()
3701 (modify-syntax-entry ?\\\\ \".\" sql-mode-syntax-table)))"
175069ef 3702 :abbrev-table sql-mode-abbrev-table
311e7a89
GM
3703 (if sql-mode-menu
3704 (easy-menu-add sql-mode-menu)); XEmacs
0d327994 3705
93852cb0 3706 ;; (smie-setup sql-smie-grammar #'sql-smie-rules)
175069ef 3707 (set (make-local-variable 'comment-start) "--")
801d1cb0 3708 ;; Make each buffer in sql-mode remember the "current" SQLi buffer.
dab100d7 3709 (make-local-variable 'sql-buffer)
801d1cb0
AS
3710 ;; Add imenu support for sql-mode. Note that imenu-generic-expression
3711 ;; is buffer-local, so we don't need a local-variable for it. SQL is
3712 ;; case-insensitive, that's why we have to set imenu-case-fold-search.
801d1cb0 3713 (setq imenu-generic-expression sql-imenu-generic-expression
78024f88 3714 imenu-case-fold-search t)
c7055d66
RS
3715 ;; Make `sql-send-paragraph' work on paragraphs that contain indented
3716 ;; lines.
175069ef
SM
3717 (set (make-local-variable 'paragraph-separate) "[\f]*$")
3718 (set (make-local-variable 'paragraph-start) "[\n\f]")
801d1cb0 3719 ;; Abbrevs
93852cb0 3720 (setq-local abbrev-all-caps 1)
fbcc67e2
MM
3721 ;; Contains the name of database objects
3722 (set (make-local-variable 'sql-contains-names) t)
78024f88 3723 ;; Catch changes to sql-product and highlight accordingly
78024f88 3724 (add-hook 'hack-local-variables-hook 'sql-highlight-product t t))
95e4b2ef
RS
3725
3726\f
3727
3728;;; SQL interactive mode
3729
3730(put 'sql-interactive-mode 'mode-class 'special)
3731
3732(defun sql-interactive-mode ()
3733 "Major mode to use a SQL interpreter interactively.
3734
3735Do not call this function by yourself. The environment must be
063c6324
JB
3736initialized by an entry function specific for the SQL interpreter.
3737See `sql-help' for a list of available entry functions.
95e4b2ef
RS
3738
3739\\[comint-send-input] after the end of the process' output sends the
3740text from the end of process to the end of the current line.
3741\\[comint-send-input] before end of process output copies the current
3742line minus the prompt to the end of the buffer and sends it.
3743\\[comint-copy-old-input] just copies the current line.
3744Use \\[sql-accumulate-and-indent] to enter multi-line statements.
3745
3746If you want to make multiple SQL buffers, rename the `*SQL*' buffer
3747using \\[rename-buffer] or \\[rename-uniquely] and start a new process.
dab100d7
RS
3748See `sql-help' for a list of available entry functions. The last buffer
3749created by such an entry function is the current SQLi buffer. SQL
3750buffers will send strings to the SQLi buffer current at the time of
3751their creation. See `sql-mode' for details.
3752
3753Sample session using two connections:
3754
37551. Create first SQLi buffer by calling an entry function.
37562. Rename buffer \"*SQL*\" to \"*Connection 1*\".
37573. Create a SQL buffer \"test1.sql\".
37584. Create second SQLi buffer by calling an entry function.
37595. Rename buffer \"*SQL*\" to \"*Connection 2*\".
37606. Create a SQL buffer \"test2.sql\".
3761
3762Now \\[sql-send-region] in buffer \"test1.sql\" will send the region to
3763buffer \"*Connection 1*\", \\[sql-send-region] in buffer \"test2.sql\"
3764will send the region to buffer \"*Connection 2*\".
95e4b2ef
RS
3765
3766If you accidentally suspend your process, use \\[comint-continue-subjob]
dab100d7
RS
3767to continue it. On some operating systems, this will not work because
3768the signals are not supported.
95e4b2ef
RS
3769
3770\\{sql-interactive-mode-map}
3771Customization: Entry to this mode runs the hooks on `comint-mode-hook'
3772and `sql-interactive-mode-hook' (in that order). Before each input, the
3773hooks on `comint-input-filter-functions' are run. After each SQL
3774interpreter output, the hooks on `comint-output-filter-functions' are
3775run.
3776
280412d8 3777Variable `sql-input-ring-file-name' controls the initialization of the
77d352a6 3778input ring history.
95e4b2ef
RS
3779
3780Variables `comint-output-filter-functions', a hook, and
3781`comint-scroll-to-bottom-on-input' and
3782`comint-scroll-to-bottom-on-output' control whether input and output
3783cause the window to scroll to the end of the buffer.
3784
3785If you want to make SQL buffers limited in length, add the function
3786`comint-truncate-buffer' to `comint-output-filter-functions'.
3787
865fe16f 3788Here is an example for your init file. It keeps the SQLi buffer a
c7055d66 3789certain length.
95e4b2ef
RS
3790
3791\(add-hook 'sql-interactive-mode-hook
3792 \(function (lambda ()
95e4b2ef
RS
3793 \(setq comint-output-filter-functions 'comint-truncate-buffer))))
3794
3795Here is another example. It will always put point back to the statement
3796you entered, right above the output it created.
3797
801d1cb0 3798\(setq comint-output-filter-functions
95e4b2ef 3799 \(function (lambda (STR) (comint-show-output))))"
03789b21 3800 (delay-mode-hooks (comint-mode))
7492acc9 3801
78024f88
AS
3802 ;; Get the `sql-product' for this interactive session.
3803 (set (make-local-variable 'sql-product)
3804 (or sql-interactive-product
3805 sql-product))
7492acc9 3806
78024f88 3807 ;; Setup the mode.
fbcc67e2 3808 (setq major-mode 'sql-interactive-mode)
175069ef
SM
3809 (setq mode-name
3810 (concat "SQLi[" (or (sql-get-product-feature sql-product :name)
3811 (symbol-name sql-product)) "]"))
95e4b2ef 3812 (use-local-map sql-interactive-mode-map)
311e7a89 3813 (if sql-interactive-mode-menu
78024f88 3814 (easy-menu-add sql-interactive-mode-menu)) ; XEmacs
95e4b2ef 3815 (set-syntax-table sql-mode-syntax-table)
7492acc9 3816
a081a529 3817 ;; Note that making KEYWORDS-ONLY nil will cause havoc if you try
801d1cb0 3818 ;; SELECT 'x' FROM DUAL with SQL*Plus, because the title of the column
e4769531 3819 ;; will have just one quote. Therefore syntactic highlighting is
78024f88
AS
3820 ;; disabled for interactive buffers. No imenu support.
3821 (sql-product-font-lock t nil)
7492acc9 3822
c7055d66 3823 ;; Enable commenting and uncommenting of the region.
175069ef 3824 (set (make-local-variable 'comment-start) "--")
78024f88 3825 ;; Abbreviation table init and case-insensitive. It is not activated
c7055d66 3826 ;; by default.
95e4b2ef
RS
3827 (setq local-abbrev-table sql-mode-abbrev-table)
3828 (setq abbrev-all-caps 1)
c7055d66 3829 ;; Exiting the process will call sql-stop.
9250002f 3830 (set-process-sentinel (get-buffer-process (current-buffer)) 'sql-stop)
fbcc67e2
MM
3831 ;; Save the connection and login params
3832 (set (make-local-variable 'sql-user) sql-user)
3833 (set (make-local-variable 'sql-database) sql-database)
3834 (set (make-local-variable 'sql-server) sql-server)
3835 (set (make-local-variable 'sql-port) sql-port)
3836 (set (make-local-variable 'sql-connection) sql-connection)
f6561e1f 3837 (setq-default sql-connection nil)
fbcc67e2
MM
3838 ;; Contains the name of database objects
3839 (set (make-local-variable 'sql-contains-names) t)
3840 ;; Keep track of existing object names
3841 (set (make-local-variable 'sql-completion-object) nil)
3842 (set (make-local-variable 'sql-completion-column) nil)
3843 ;; Create a useful name for renaming this buffer later.
175069ef
SM
3844 (set (make-local-variable 'sql-alternate-buffer-name)
3845 (sql-make-alternate-buffer-name))
78024f88
AS
3846 ;; User stuff. Initialize before the hook.
3847 (set (make-local-variable 'sql-prompt-regexp)
7492acc9 3848 (sql-get-product-feature sql-product :prompt-regexp))
78024f88 3849 (set (make-local-variable 'sql-prompt-length)
7492acc9 3850 (sql-get-product-feature sql-product :prompt-length))
3bd2cfef
MM
3851 (set (make-local-variable 'sql-prompt-cont-regexp)
3852 (sql-get-product-feature sql-product :prompt-cont-regexp))
3853 (make-local-variable 'sql-output-newline-count)
fbcc67e2 3854 (make-local-variable 'sql-preoutput-hold)
3bd2cfef
MM
3855 (add-hook 'comint-preoutput-filter-functions
3856 'sql-interactive-remove-continuation-prompt nil t)
78024f88
AS
3857 (make-local-variable 'sql-input-ring-separator)
3858 (make-local-variable 'sql-input-ring-file-name)
7492acc9 3859 ;; Run the mode hook (along with comint's hooks).
9a969196 3860 (run-mode-hooks 'sql-interactive-mode-hook)
78024f88 3861 ;; Set comint based on user overrides.
3bd2cfef
MM
3862 (setq comint-prompt-regexp
3863 (if sql-prompt-cont-regexp
3864 (concat "\\(" sql-prompt-regexp
3865 "\\|" sql-prompt-cont-regexp "\\)")
3866 sql-prompt-regexp))
78024f88 3867 (setq left-margin sql-prompt-length)
7492acc9
MM
3868 ;; Install input sender
3869 (set (make-local-variable 'comint-input-sender) 'sql-input-sender)
77d352a6
GM
3870 ;; People wanting a different history file for each
3871 ;; buffer/process/client/whatever can change separator and file-name
3872 ;; on the sql-interactive-mode-hook.
3873 (setq comint-input-ring-separator sql-input-ring-separator
3874 comint-input-ring-file-name sql-input-ring-file-name)
c7055d66 3875 ;; Calling the hook before calling comint-read-input-ring allows users
95e4b2ef 3876 ;; to set comint-input-ring-file-name in sql-interactive-mode-hook.
77d352a6 3877 (comint-read-input-ring t))
95e4b2ef
RS
3878
3879(defun sql-stop (process event)
3880 "Called when the SQL process is stopped.
3881
c7055d66
RS
3882Writes the input history to a history file using
3883`comint-write-input-ring' and inserts a short message in the SQL buffer.
95e4b2ef
RS
3884
3885This function is a sentinel watching the SQL interpreter process.
3886Sentinels will always get the two parameters PROCESS and EVENT."
77d352a6
GM
3887 (comint-write-input-ring)
3888 (if (and (eq (current-buffer) sql-buffer)
3889 (not buffer-read-only))
3890 (insert (format "\nProcess %s %s\n" process event))
3891 (message "Process %s %s" process event)))
95e4b2ef
RS
3892
3893\f
3894
5474c40f 3895;;; Connection handling
30c4d8dc 3896
74790210
MM
3897(defun sql-read-connection (prompt &optional initial default)
3898 "Read a connection name."
3899 (let ((completion-ignore-case t))
3900 (completing-read prompt
3901 (mapcar (lambda (c) (car c))
3902 sql-connection-alist)
3903 nil t initial 'sql-connection-history default)))
3904
30c4d8dc 3905;;;###autoload
fbcc67e2 3906(defun sql-connect (connection &optional new-name)
30c4d8dc
MM
3907 "Connect to an interactive session using CONNECTION settings.
3908
3909See `sql-connection-alist' to see how to define connections and
3910their settings.
3911
3912The user will not be prompted for any login parameters if a value
3913is specified in the connection settings."
3914
3915 ;; Prompt for the connection from those defined in the alist
3916 (interactive
3917 (if sql-connection-alist
fbcc67e2
MM
3918 (list (sql-read-connection "Connection: " nil '(nil))
3919 current-prefix-arg)
30c4d8dc
MM
3920 nil))
3921
3922 ;; Are there connections defined
3923 (if sql-connection-alist
3924 ;; Was one selected
3925 (when connection
3926 ;; Get connection settings
4586ce8a 3927 (let ((connect-set (assoc-string connection sql-connection-alist t)))
30c4d8dc
MM
3928 ;; Settings are defined
3929 (if connect-set
3930 ;; Set the desired parameters
f6561e1f
MM
3931 (let (param-var login-params set-params rem-params)
3932
3933 ;; :sqli-login params variable
3934 (setq param-var
3935 (sql-get-product-feature sql-product :sqli-login nil t))
3936
3937 ;; :sqli-login params value
3938 (setq login-params
3939 (sql-get-product-feature sql-product :sqli-login))
3940
3941 ;; Params in the connection
3942 (setq set-params
3943 (mapcar
3944 (lambda (v)
93852cb0
SM
3945 (pcase (car v)
3946 (`sql-user 'user)
3947 (`sql-password 'password)
3948 (`sql-server 'server)
3949 (`sql-database 'database)
3950 (`sql-port 'port)
3951 (s s)))
f6561e1f
MM
3952 (cdr connect-set)))
3953
3954 ;; the remaining params (w/o the connection params)
3955 (setq rem-params
3956 (sql-for-each-login login-params
3957 (lambda (token plist)
3958 (unless (member token set-params)
3959 (if plist (cons token plist) token)))))
3960
3961 ;; Set the parameters and start the interactive session
3962 (mapc
3963 (lambda (vv)
3964 (set-default (car vv) (eval (cadr vv))))
3965 (cdr connect-set))
3966 (setq-default sql-connection connection)
3967
3968 ;; Start the SQLi session with revised list of login parameters
3969 (eval `(let ((,param-var ',rem-params))
93852cb0 3970 (sql-product-interactive ',sql-product ',new-name))))
fbcc67e2 3971
d26b0ea9 3972 (message "SQL Connection <%s> does not exist" connection)
30c4d8dc 3973 nil)))
f6561e1f 3974
30c4d8dc
MM
3975 (message "No SQL Connections defined")
3976 nil))
78024f88 3977
d26b0ea9
MM
3978(defun sql-save-connection (name)
3979 "Captures the connection information of the current SQLi session.
3980
3981The information is appended to `sql-connection-alist' and
3982optionally is saved to the user's init file."
3983
3984 (interactive "sNew connection name: ")
3985
fbcc67e2
MM
3986 (unless (derived-mode-p 'sql-interactive-mode)
3987 (error "Not in a SQL interactive mode!"))
3988
3989 ;; Capture the buffer local settings
3990 (let* ((buf (current-buffer))
3991 (connection (buffer-local-value 'sql-connection buf))
3992 (product (buffer-local-value 'sql-product buf))
3993 (user (buffer-local-value 'sql-user buf))
3994 (database (buffer-local-value 'sql-database buf))
3995 (server (buffer-local-value 'sql-server buf))
3996 (port (buffer-local-value 'sql-port buf)))
3997
3998 (if connection
3999 (message "This session was started by a connection; it's already been saved.")
91af3942 4000
fbcc67e2
MM
4001 (let ((login (sql-get-product-feature product :sqli-login))
4002 (alist sql-connection-alist)
4003 connect)
91af3942 4004
fbcc67e2
MM
4005 ;; Remove the existing connection if the user says so
4006 (when (and (assoc name alist)
4007 (yes-or-no-p (format "Replace connection definition <%s>? " name)))
4008 (setq alist (assq-delete-all name alist)))
91af3942 4009
fbcc67e2
MM
4010 ;; Add the new connection if it doesn't exist
4011 (if (assoc name alist)
4012 (message "Connection <%s> already exists" name)
4013 (setq connect
93852cb0
SM
4014 (cons name
4015 (sql-for-each-login
4016 `(product ,@login)
4017 (lambda (token _plist)
4018 (pcase token
4019 (`product `(sql-product ',product))
4020 (`user `(sql-user ,user))
4021 (`database `(sql-database ,database))
4022 (`server `(sql-server ,server))
4023 (`port `(sql-port ,port)))))))
fbcc67e2
MM
4024
4025 (setq alist (append alist (list connect)))
4026
4027 ;; confirm whether we want to save the connections
4028 (if (yes-or-no-p "Save the connections for future sessions? ")
4029 (customize-save-variable 'sql-connection-alist alist)
4030 (customize-set-variable 'sql-connection-alist alist)))))))
d26b0ea9
MM
4031
4032(defun sql-connection-menu-filter (tail)
93852cb0 4033 "Generate menu entries for using each connection."
d26b0ea9
MM
4034 (append
4035 (mapcar
4036 (lambda (conn)
4037 (vector
fbcc67e2
MM
4038 (format "Connection <%s>\t%s" (car conn)
4039 (let ((sql-user "") (sql-database "")
4040 (sql-server "") (sql-port 0))
4041 (eval `(let ,(cdr conn) (sql-make-alternate-buffer-name)))))
d26b0ea9
MM
4042 (list 'sql-connect (car conn))
4043 t))
4044 sql-connection-alist)
4045 tail))
4046
5474c40f
MM
4047\f
4048
4049;;; Entry functions for different SQL interpreters.
4050
4051;;;###autoload
9250002f 4052(defun sql-product-interactive (&optional product new-name)
5474c40f
MM
4053 "Run PRODUCT interpreter as an inferior process.
4054
4055If buffer `*SQL*' exists but no process is running, make a new process.
4056If buffer exists and a process is running, just switch to buffer `*SQL*'.
4057
9250002f
MM
4058To specify the SQL product, prefix the call with
4059\\[universal-argument]. To set the buffer name as well, prefix
4060the call to \\[sql-product-interactive] with
4061\\[universal-argument] \\[universal-argument].
4062
5474c40f
MM
4063\(Type \\[describe-mode] in the SQL buffer for a list of commands.)"
4064 (interactive "P")
4065
9250002f
MM
4066 ;; Handle universal arguments if specified
4067 (when (not (or executing-kbd-macro noninteractive))
a386ac70 4068 (when (and (consp product)
9250002f
MM
4069 (not (cdr product))
4070 (numberp (car product)))
74790210 4071 (when (>= (prefix-numeric-value product) 16)
9250002f
MM
4072 (when (not new-name)
4073 (setq new-name '(4)))
4074 (setq product '(4)))))
4075
4076 ;; Get the value of product that we need
5474c40f
MM
4077 (setq product
4078 (cond
74790210
MM
4079 ((= (prefix-numeric-value product) 4) ; C-u, prompt for product
4080 (sql-read-product "SQL product: " sql-product))
fbcc67e2
MM
4081 ((and product ; Product specified
4082 (symbolp product)) product)
5474c40f
MM
4083 (t sql-product))) ; Default to sql-product
4084
9250002f 4085 ;; If we have a product and it has a interactive mode
5474c40f
MM
4086 (if product
4087 (when (sql-get-product-feature product :sqli-comint-func)
74790210
MM
4088 ;; If no new name specified, try to pop to an active SQL
4089 ;; interactive for the same product
fbcc67e2 4090 (let ((buf (sql-find-sqli-buffer product sql-connection)))
74790210
MM
4091 (if (and (not new-name) buf)
4092 (pop-to-buffer buf)
4093
4094 ;; We have a new name or sql-buffer doesn't exist or match
4095 ;; Start by remembering where we start
4096 (let ((start-buffer (current-buffer))
4097 new-sqli-buffer)
4098
4099 ;; Get credentials.
93852cb0
SM
4100 (apply #'sql-get-login
4101 (sql-get-product-feature product :sqli-login))
74790210
MM
4102
4103 ;; Connect to database.
4104 (message "Login...")
f6561e1f
MM
4105 (let ((sql-user (default-value 'sql-user))
4106 (sql-password (default-value 'sql-password))
4107 (sql-server (default-value 'sql-server))
4108 (sql-database (default-value 'sql-database))
4109 (sql-port (default-value 'sql-port)))
4110 (funcall (sql-get-product-feature product :sqli-comint-func)
4111 product
4112 (sql-get-product-feature product :sqli-options)))
74790210
MM
4113
4114 ;; Set SQLi mode.
74790210
MM
4115 (let ((sql-interactive-product product))
4116 (sql-interactive-mode))
4117
4118 ;; Set the new buffer name
fbcc67e2 4119 (setq new-sqli-buffer (current-buffer))
74790210
MM
4120 (when new-name
4121 (sql-rename-buffer new-name))
f6561e1f 4122 (set (make-local-variable 'sql-buffer)
bb5aa5d6 4123 (buffer-name new-sqli-buffer))
fbcc67e2
MM
4124
4125 ;; Set `sql-buffer' in the start buffer
74790210 4126 (with-current-buffer start-buffer
fbcc67e2
MM
4127 (when (derived-mode-p 'sql-mode)
4128 (setq sql-buffer (buffer-name new-sqli-buffer))
4129 (run-hooks 'sql-set-sqli-hook)))
5474c40f 4130
4586ce8a
MM
4131 ;; Make sure the connection is complete
4132 ;; (Sometimes start up can be slow)
4133 ;; and call the login hook
4134 (let ((proc (get-buffer-process new-sqli-buffer)))
4135 (while (and (memq (process-status proc) '(open run))
4136 (accept-process-output proc 2.5)
4137 (progn (goto-char (point-max))
4138 (not (looking-back sql-prompt-regexp))))))
4139 (run-hooks 'sql-login-hook)
74790210
MM
4140 ;; All done.
4141 (message "Login...done")
fbcc67e2 4142 (pop-to-buffer new-sqli-buffer)))))
5474c40f
MM
4143 (message "No default SQL product defined. Set `sql-product'.")))
4144
4145(defun sql-comint (product params)
4146 "Set up a comint buffer to run the SQL processor.
4147
4148PRODUCT is the SQL product. PARAMS is a list of strings which are
4149passed as command line arguments."
9250002f
MM
4150 (let ((program (sql-get-product-feature product :sqli-program))
4151 (buf-name "SQL"))
2bb1ae55
MA
4152 ;; Make sure we can find the program. `executable-find' does not
4153 ;; work for remote hosts; we suppress the check there.
4154 (unless (or (file-remote-p default-directory)
4155 (executable-find program))
74790210 4156 (error "Unable to locate SQL program \'%s\'" program))
2bb1ae55 4157 ;; Make sure buffer name is unique.
74790210 4158 (when (sql-buffer-live-p (format "*%s*" buf-name))
9250002f 4159 (setq buf-name (format "SQL-%s" product))
74790210 4160 (when (sql-buffer-live-p (format "*%s*" buf-name))
9250002f 4161 (let ((i 1))
74790210
MM
4162 (while (sql-buffer-live-p
4163 (format "*%s*"
4164 (setq buf-name (format "SQL-%s%d" product i))))
9250002f 4165 (setq i (1+ i))))))
5474c40f 4166 (set-buffer
9250002f 4167 (apply 'make-comint buf-name program nil params))))
5474c40f 4168
77d352a6 4169;;;###autoload
9250002f 4170(defun sql-oracle (&optional buffer)
95e4b2ef
RS
4171 "Run sqlplus by Oracle as an inferior process.
4172
dab100d7 4173If buffer `*SQL*' exists but no process is running, make a new process.
95e4b2ef
RS
4174If buffer exists and a process is running, just switch to buffer
4175`*SQL*'.
4176
dab100d7
RS
4177Interpreter used comes from variable `sql-oracle-program'. Login uses
4178the variables `sql-user', `sql-password', and `sql-database' as
9ef3882f
GM
4179defaults, if set. Additional command line parameters can be stored in
4180the list `sql-oracle-options'.
95e4b2ef 4181
063c6324 4182The buffer is put in SQL interactive mode, giving commands for sending
95e4b2ef
RS
4183input. See `sql-interactive-mode'.
4184
9250002f
MM
4185To set the buffer name directly, use \\[universal-argument]
4186before \\[sql-oracle]. Once session has started,
4187\\[sql-rename-buffer] can be called separately to rename the
4188buffer.
4189
95e4b2ef
RS
4190To specify a coding system for converting non-ASCII characters
4191in the input and output to the process, use \\[universal-coding-system-argument]
4192before \\[sql-oracle]. You can also specify this with \\[set-buffer-process-coding-system]
4193in the SQL buffer, after you start the process.
4194The default comes from `process-coding-system-alist' and
4195`default-process-coding-system'.
4196
4197\(Type \\[describe-mode] in the SQL buffer for a list of commands.)"
9250002f
MM
4198 (interactive "P")
4199 (sql-product-interactive 'oracle buffer))
78024f88 4200
30c4d8dc 4201(defun sql-comint-oracle (product options)
7492acc9 4202 "Create comint buffer and connect to Oracle."
78024f88
AS
4203 ;; Produce user/password@database construct. Password without user
4204 ;; is meaningless; database without user/password is meaningless,
4205 ;; because "@param" will ask sqlplus to interpret the script
4206 ;; "param".
4586ce8a 4207 (let (parameter nlslang coding)
7492acc9
MM
4208 (if (not (string= "" sql-user))
4209 (if (not (string= "" sql-password))
4210 (setq parameter (concat sql-user "/" sql-password))
4211 (setq parameter sql-user)))
78024f88
AS
4212 (if (and parameter (not (string= "" sql-database)))
4213 (setq parameter (concat parameter "@" sql-database)))
7492acc9
MM
4214 (if parameter
4215 (setq parameter (nconc (list parameter) options))
4216 (setq parameter options))
4586ce8a
MM
4217 (sql-comint product parameter)
4218 ;; Set process coding system to agree with the interpreter
4219 (setq nlslang (or (getenv "NLS_LANG") "")
4220 coding (dolist (cs
4221 ;; Are we missing any common NLS character sets
4222 '(("US8PC437" . cp437)
4223 ("EL8PC737" . cp737)
4224 ("WE8PC850" . cp850)
4225 ("EE8PC852" . cp852)
4226 ("TR8PC857" . cp857)
4227 ("WE8PC858" . cp858)
4228 ("IS8PC861" . cp861)
4229 ("IW8PC1507" . cp862)
4230 ("N8PC865" . cp865)
4231 ("RU8PC866" . cp866)
4232 ("US7ASCII" . us-ascii)
4233 ("UTF8" . utf-8)
4234 ("AL32UTF8" . utf-8)
4235 ("AL16UTF16" . utf-16))
4236 (or coding 'utf-8))
4237 (when (string-match (format "\\.%s\\'" (car cs)) nlslang)
4238 (setq coding (cdr cs)))))
4239 (set-buffer-process-coding-system coding coding)))
95e4b2ef 4240
fbcc67e2 4241(defun sql-oracle-save-settings (sqlbuf)
93852cb0 4242 "Save most SQL*Plus settings so they may be reset by \\[sql-redirect]."
fbcc67e2
MM
4243 ;; Note: does not capture the following settings:
4244 ;;
4245 ;; APPINFO
4246 ;; BTITLE
4247 ;; COMPATIBILITY
4248 ;; COPYTYPECHECK
4249 ;; MARKUP
4250 ;; RELEASE
4251 ;; REPFOOTER
4252 ;; REPHEADER
4253 ;; SQLPLUSCOMPATIBILITY
4254 ;; TTITLE
4255 ;; USER
4256 ;;
4257
4258 (append
4259 ;; (apply 'concat (append
4260 ;; '("SET")
4261
4262 ;; option value...
4263 (sql-redirect-value
4264 sqlbuf
4265 (concat "SHOW ARRAYSIZE AUTOCOMMIT AUTOPRINT AUTORECOVERY AUTOTRACE"
4266 " CMDSEP COLSEP COPYCOMMIT DESCRIBE ECHO EDITFILE EMBEDDED"
4267 " ESCAPE FLAGGER FLUSH HEADING INSTANCE LINESIZE LNO LOBOFFSET"
4268 " LOGSOURCE LONG LONGCHUNKSIZE NEWPAGE NULL NUMFORMAT NUMWIDTH"
4269 " PAGESIZE PAUSE PNO RECSEP SERVEROUTPUT SHIFTINOUT SHOWMODE"
4270 " SPOOL SQLBLANKLINES SQLCASE SQLCODE SQLCONTINUE SQLNUMBER"
4271 " SQLPROMPT SUFFIX TAB TERMOUT TIMING TRIMOUT TRIMSPOOL VERIFY")
4272 "^.+$"
4273 "SET \\&")
4274
4275 ;; option "c" (hex xx)
4276 (sql-redirect-value
4277 sqlbuf
4278 (concat "SHOW BLOCKTERMINATOR CONCAT DEFINE SQLPREFIX SQLTERMINATOR"
4279 " UNDERLINE HEADSEP RECSEPCHAR")
4280 "^\\(.+\\) (hex ..)$"
4281 "SET \\1")
4282
99d99081 4283 ;; FEEDBACK ON for 99 or more rows
fbcc67e2
MM
4284 ;; feedback OFF
4285 (sql-redirect-value
4286 sqlbuf
4287 "SHOW FEEDBACK"
4288 "^\\(?:FEEDBACK ON for \\([[:digit:]]+\\) or more rows\\|feedback \\(OFF\\)\\)"
4289 "SET FEEDBACK \\1\\2")
4290
4291 ;; wrap : lines will be wrapped
4292 ;; wrap : lines will be truncated
4293 (list (concat "SET WRAP "
4294 (if (string=
4295 (car (sql-redirect-value
4296 sqlbuf
4297 "SHOW WRAP"
4298 "^wrap : lines will be \\(wrapped\\|truncated\\)" 1))
4299 "wrapped")
4300 "ON" "OFF")))))
4301
4302(defun sql-oracle-restore-settings (sqlbuf saved-settings)
4303 "Restore the SQL*Plus settings in SAVED-SETTINGS."
4304
4305 ;; Remove any settings that haven't changed
4306 (mapc
4307 (lambda (one-cur-setting)
4308 (setq saved-settings (delete one-cur-setting saved-settings)))
4309 (sql-oracle-save-settings sqlbuf))
4310
4311 ;; Restore the changed settings
4312 (sql-redirect sqlbuf saved-settings))
4313
93852cb0 4314(defun sql-oracle-list-all (sqlbuf outbuf enhanced _table-name)
fbcc67e2
MM
4315 ;; Query from USER_OBJECTS or ALL_OBJECTS
4316 (let ((settings (sql-oracle-save-settings sqlbuf))
4317 (simple-sql
4318 (concat
4319 "SELECT INITCAP(x.object_type) AS SQL_EL_TYPE "
4320 ", x.object_name AS SQL_EL_NAME "
4321 "FROM user_objects x "
4322 "WHERE x.object_type NOT LIKE '%% BODY' "
4323 "ORDER BY 2, 1;"))
4324 (enhanced-sql
4325 (concat
4326 "SELECT INITCAP(x.object_type) AS SQL_EL_TYPE "
4327 ", x.owner ||'.'|| x.object_name AS SQL_EL_NAME "
4328 "FROM all_objects x "
4329 "WHERE x.object_type NOT LIKE '%% BODY' "
4330 "AND x.owner <> 'SYS' "
4331 "ORDER BY 2, 1;")))
4332
4333 (sql-redirect sqlbuf
4334 (concat "SET LINESIZE 80 PAGESIZE 50000 TRIMOUT ON"
4335 " TAB OFF TIMING OFF FEEDBACK OFF"))
4336
4337 (sql-redirect sqlbuf
4338 (list "COLUMN SQL_EL_TYPE HEADING \"Type\" FORMAT A19"
4339 "COLUMN SQL_EL_NAME HEADING \"Name\""
4340 (format "COLUMN SQL_EL_NAME FORMAT A%d"
4341 (if enhanced 60 35))))
4342
4343 (sql-redirect sqlbuf
4344 (if enhanced enhanced-sql simple-sql)
4345 outbuf)
4346
4347 (sql-redirect sqlbuf
4348 '("COLUMN SQL_EL_NAME CLEAR"
4349 "COLUMN SQL_EL_TYPE CLEAR"))
4350
4351 (sql-oracle-restore-settings sqlbuf settings)))
4352
93852cb0 4353(defun sql-oracle-list-table (sqlbuf outbuf _enhanced table-name)
fbcc67e2
MM
4354 "Implements :list-table under Oracle."
4355 (let ((settings (sql-oracle-save-settings sqlbuf)))
4356
4357 (sql-redirect sqlbuf
4358 (format
4359 (concat "SET LINESIZE %d PAGESIZE 50000"
4360 " DESCRIBE DEPTH 1 LINENUM OFF INDENT ON")
4361 (max 65 (min 120 (window-width)))))
4362
4363 (sql-redirect sqlbuf (format "DESCRIBE %s" table-name)
4364 outbuf)
4365
4366 (sql-oracle-restore-settings sqlbuf settings)))
4367
4368(defcustom sql-oracle-completion-types '("FUNCTION" "PACKAGE" "PROCEDURE"
4369 "SEQUENCE" "SYNONYM" "TABLE" "TRIGGER"
4370 "TYPE" "VIEW")
4371 "List of object types to include for completion under Oracle.
4372
4373See the distinct values in ALL_OBJECTS.OBJECT_TYPE for possible values."
4374 :version "24.1"
4375 :type '(repeat string)
4376 :group 'SQL)
4377
4378(defun sql-oracle-completion-object (sqlbuf schema)
4379 (sql-redirect-value
4380 sqlbuf
4381 (concat
4382 "SELECT CHR(1)||"
4383 (if schema
4384 (format "owner||'.'||object_name AS o FROM all_objects WHERE owner = %s AND "
4385 (sql-str-literal (upcase schema)))
4386 "object_name AS o FROM user_objects WHERE ")
4387 "temporary = 'N' AND generated = 'N' AND secondary = 'N' AND "
4388 "object_type IN ("
4389 (mapconcat (function sql-str-literal) sql-oracle-completion-types ",")
4390 ");")
4391 "^[\001]\\(.+\\)$" 1))
95e4b2ef
RS
4392\f
4393
77d352a6 4394;;;###autoload
9250002f 4395(defun sql-sybase (&optional buffer)
c38762fd 4396 "Run isql by Sybase as an inferior process.
95e4b2ef 4397
dab100d7 4398If buffer `*SQL*' exists but no process is running, make a new process.
95e4b2ef
RS
4399If buffer exists and a process is running, just switch to buffer
4400`*SQL*'.
4401
4402Interpreter used comes from variable `sql-sybase-program'. Login uses
9b5360aa 4403the variables `sql-server', `sql-user', `sql-password', and
7a65c85c
GM
4404`sql-database' as defaults, if set. Additional command line parameters
4405can be stored in the list `sql-sybase-options'.
95e4b2ef 4406
063c6324 4407The buffer is put in SQL interactive mode, giving commands for sending
95e4b2ef
RS
4408input. See `sql-interactive-mode'.
4409
9250002f
MM
4410To set the buffer name directly, use \\[universal-argument]
4411before \\[sql-sybase]. Once session has started,
4412\\[sql-rename-buffer] can be called separately to rename the
4413buffer.
4414
95e4b2ef
RS
4415To specify a coding system for converting non-ASCII characters
4416in the input and output to the process, use \\[universal-coding-system-argument]
4417before \\[sql-sybase]. You can also specify this with \\[set-buffer-process-coding-system]
4418in the SQL buffer, after you start the process.
4419The default comes from `process-coding-system-alist' and
4420`default-process-coding-system'.
4421
4422\(Type \\[describe-mode] in the SQL buffer for a list of commands.)"
9250002f
MM
4423 (interactive "P")
4424 (sql-product-interactive 'sybase buffer))
78024f88 4425
30c4d8dc 4426(defun sql-comint-sybase (product options)
7492acc9 4427 "Create comint buffer and connect to Sybase."
78024f88
AS
4428 ;; Put all parameters to the program (if defined) in a list and call
4429 ;; make-comint.
93852cb0
SM
4430 (let ((params
4431 (append
4432 (if (not (string= "" sql-user))
4433 (list "-U" sql-user))
4434 (if (not (string= "" sql-password))
4435 (list "-P" sql-password))
4436 (if (not (string= "" sql-database))
4437 (list "-D" sql-database))
4438 (if (not (string= "" sql-server))
4439 (list "-S" sql-server))
4440 options)))
30c4d8dc 4441 (sql-comint product params)))
95e4b2ef
RS
4442
4443\f
4444
77d352a6 4445;;;###autoload
9250002f 4446(defun sql-informix (&optional buffer)
95e4b2ef
RS
4447 "Run dbaccess by Informix as an inferior process.
4448
dab100d7 4449If buffer `*SQL*' exists but no process is running, make a new process.
95e4b2ef
RS
4450If buffer exists and a process is running, just switch to buffer
4451`*SQL*'.
4452
4453Interpreter used comes from variable `sql-informix-program'. Login uses
4454the variable `sql-database' as default, if set.
4455
063c6324 4456The buffer is put in SQL interactive mode, giving commands for sending
95e4b2ef
RS
4457input. See `sql-interactive-mode'.
4458
9250002f
MM
4459To set the buffer name directly, use \\[universal-argument]
4460before \\[sql-informix]. Once session has started,
4461\\[sql-rename-buffer] can be called separately to rename the
4462buffer.
4463
95e4b2ef
RS
4464To specify a coding system for converting non-ASCII characters
4465in the input and output to the process, use \\[universal-coding-system-argument]
4466before \\[sql-informix]. You can also specify this with \\[set-buffer-process-coding-system]
4467in the SQL buffer, after you start the process.
4468The default comes from `process-coding-system-alist' and
4469`default-process-coding-system'.
4470
4471\(Type \\[describe-mode] in the SQL buffer for a list of commands.)"
9250002f
MM
4472 (interactive "P")
4473 (sql-product-interactive 'informix buffer))
78024f88 4474
30c4d8dc 4475(defun sql-comint-informix (product options)
7492acc9 4476 "Create comint buffer and connect to Informix."
78024f88 4477 ;; username and password are ignored.
7492acc9
MM
4478 (let ((db (if (string= "" sql-database)
4479 "-"
4480 (if (string= "" sql-server)
4481 sql-database
4482 (concat sql-database "@" sql-server)))))
30c4d8dc 4483 (sql-comint product (append `(,db "-") options))))
a081a529
RS
4484
4485\f
4486
5d538ce3 4487;;;###autoload
9250002f 4488(defun sql-sqlite (&optional buffer)
5d538ce3
JB
4489 "Run sqlite as an inferior process.
4490
4491SQLite is free software.
4492
4493If buffer `*SQL*' exists but no process is running, make a new process.
4494If buffer exists and a process is running, just switch to buffer
4495`*SQL*'.
4496
4497Interpreter used comes from variable `sql-sqlite-program'. Login uses
4498the variables `sql-user', `sql-password', `sql-database', and
4499`sql-server' as defaults, if set. Additional command line parameters
4500can be stored in the list `sql-sqlite-options'.
4501
063c6324 4502The buffer is put in SQL interactive mode, giving commands for sending
5d538ce3
JB
4503input. See `sql-interactive-mode'.
4504
9250002f
MM
4505To set the buffer name directly, use \\[universal-argument]
4506before \\[sql-sqlite]. Once session has started,
4507\\[sql-rename-buffer] can be called separately to rename the
4508buffer.
4509
5d538ce3
JB
4510To specify a coding system for converting non-ASCII characters
4511in the input and output to the process, use \\[universal-coding-system-argument]
4512before \\[sql-sqlite]. You can also specify this with \\[set-buffer-process-coding-system]
4513in the SQL buffer, after you start the process.
4514The default comes from `process-coding-system-alist' and
4515`default-process-coding-system'.
4516
4517\(Type \\[describe-mode] in the SQL buffer for a list of commands.)"
9250002f
MM
4518 (interactive "P")
4519 (sql-product-interactive 'sqlite buffer))
78024f88 4520
30c4d8dc 4521(defun sql-comint-sqlite (product options)
7492acc9 4522 "Create comint buffer and connect to SQLite."
78024f88
AS
4523 ;; Put all parameters to the program (if defined) in a list and call
4524 ;; make-comint.
93852cb0
SM
4525 (let ((params
4526 (append options
4527 (if (not (string= "" sql-database))
4528 `(,(expand-file-name sql-database))))))
30c4d8dc 4529 (sql-comint product params)))
5d538ce3 4530
93852cb0 4531(defun sql-sqlite-completion-object (sqlbuf _schema)
fbcc67e2
MM
4532 (sql-redirect-value sqlbuf ".tables" "\\sw\\(?:\\sw\\|\\s_\\)*" 0))
4533
5d538ce3
JB
4534\f
4535
77d352a6 4536;;;###autoload
9250002f 4537(defun sql-mysql (&optional buffer)
a081a529 4538 "Run mysql by TcX as an inferior process.
dab100d7 4539
058fb10a 4540Mysql versions 3.23 and up are free software.
a081a529 4541
50842164 4542If buffer `*SQL*' exists but no process is running, make a new process.
a081a529
RS
4543If buffer exists and a process is running, just switch to buffer
4544`*SQL*'.
4545
4546Interpreter used comes from variable `sql-mysql-program'. Login uses
dab100d7 4547the variables `sql-user', `sql-password', `sql-database', and
7a65c85c
GM
4548`sql-server' as defaults, if set. Additional command line parameters
4549can be stored in the list `sql-mysql-options'.
a081a529 4550
063c6324 4551The buffer is put in SQL interactive mode, giving commands for sending
a081a529
RS
4552input. See `sql-interactive-mode'.
4553
9250002f
MM
4554To set the buffer name directly, use \\[universal-argument]
4555before \\[sql-mysql]. Once session has started,
4556\\[sql-rename-buffer] can be called separately to rename the
4557buffer.
4558
a081a529
RS
4559To specify a coding system for converting non-ASCII characters
4560in the input and output to the process, use \\[universal-coding-system-argument]
dab100d7 4561before \\[sql-mysql]. You can also specify this with \\[set-buffer-process-coding-system]
a081a529
RS
4562in the SQL buffer, after you start the process.
4563The default comes from `process-coding-system-alist' and
4564`default-process-coding-system'.
4565
4566\(Type \\[describe-mode] in the SQL buffer for a list of commands.)"
9250002f
MM
4567 (interactive "P")
4568 (sql-product-interactive 'mysql buffer))
78024f88 4569
30c4d8dc 4570(defun sql-comint-mysql (product options)
7492acc9 4571 "Create comint buffer and connect to MySQL."
78024f88
AS
4572 ;; Put all parameters to the program (if defined) in a list and call
4573 ;; make-comint.
93852cb0
SM
4574 (let ((params
4575 (append
4576 options
4577 (if (not (string= "" sql-user))
4578 (list (concat "--user=" sql-user)))
4579 (if (not (string= "" sql-password))
4580 (list (concat "--password=" sql-password)))
4581 (if (not (= 0 sql-port))
4582 (list (concat "--port=" (number-to-string sql-port))))
4583 (if (not (string= "" sql-server))
4584 (list (concat "--host=" sql-server)))
4585 (if (not (string= "" sql-database))
4586 (list sql-database)))))
30c4d8dc 4587 (sql-comint product params)))
95e4b2ef
RS
4588
4589\f
4590
77d352a6 4591;;;###autoload
9250002f 4592(defun sql-solid (&optional buffer)
dab100d7
RS
4593 "Run solsql by Solid as an inferior process.
4594
4595If buffer `*SQL*' exists but no process is running, make a new process.
4596If buffer exists and a process is running, just switch to buffer
4597`*SQL*'.
4598
4599Interpreter used comes from variable `sql-solid-program'. Login uses
4600the variables `sql-user', `sql-password', and `sql-server' as
4601defaults, if set.
4602
063c6324 4603The buffer is put in SQL interactive mode, giving commands for sending
dab100d7
RS
4604input. See `sql-interactive-mode'.
4605
9250002f
MM
4606To set the buffer name directly, use \\[universal-argument]
4607before \\[sql-solid]. Once session has started,
4608\\[sql-rename-buffer] can be called separately to rename the
4609buffer.
4610
dab100d7
RS
4611To specify a coding system for converting non-ASCII characters
4612in the input and output to the process, use \\[universal-coding-system-argument]
4613before \\[sql-solid]. You can also specify this with \\[set-buffer-process-coding-system]
4614in the SQL buffer, after you start the process.
4615The default comes from `process-coding-system-alist' and
4616`default-process-coding-system'.
4617
4618\(Type \\[describe-mode] in the SQL buffer for a list of commands.)"
9250002f
MM
4619 (interactive "P")
4620 (sql-product-interactive 'solid buffer))
78024f88 4621
30c4d8dc 4622(defun sql-comint-solid (product options)
7492acc9 4623 "Create comint buffer and connect to Solid."
78024f88
AS
4624 ;; Put all parameters to the program (if defined) in a list and call
4625 ;; make-comint.
93852cb0
SM
4626 (let ((params
4627 (append
4628 (if (not (string= "" sql-server))
4629 (list sql-server))
4630 ;; It only makes sense if both username and password are there.
4631 (if (not (or (string= "" sql-user)
4632 (string= "" sql-password)))
4633 (list sql-user sql-password))
4634 options)))
30c4d8dc 4635 (sql-comint product params)))
dab100d7
RS
4636
4637\f
4638
77d352a6 4639;;;###autoload
9250002f 4640(defun sql-ingres (&optional buffer)
95e4b2ef
RS
4641 "Run sql by Ingres as an inferior process.
4642
dab100d7 4643If buffer `*SQL*' exists but no process is running, make a new process.
95e4b2ef
RS
4644If buffer exists and a process is running, just switch to buffer
4645`*SQL*'.
4646
4647Interpreter used comes from variable `sql-ingres-program'. Login uses
4648the variable `sql-database' as default, if set.
4649
063c6324 4650The buffer is put in SQL interactive mode, giving commands for sending
95e4b2ef
RS
4651input. See `sql-interactive-mode'.
4652
9250002f
MM
4653To set the buffer name directly, use \\[universal-argument]
4654before \\[sql-ingres]. Once session has started,
4655\\[sql-rename-buffer] can be called separately to rename the
4656buffer.
4657
95e4b2ef
RS
4658To specify a coding system for converting non-ASCII characters
4659in the input and output to the process, use \\[universal-coding-system-argument]
4660before \\[sql-ingres]. You can also specify this with \\[set-buffer-process-coding-system]
4661in the SQL buffer, after you start the process.
4662The default comes from `process-coding-system-alist' and
4663`default-process-coding-system'.
4664
4665\(Type \\[describe-mode] in the SQL buffer for a list of commands.)"
9250002f
MM
4666 (interactive "P")
4667 (sql-product-interactive 'ingres buffer))
78024f88 4668
30c4d8dc 4669(defun sql-comint-ingres (product options)
7492acc9 4670 "Create comint buffer and connect to Ingres."
78024f88 4671 ;; username and password are ignored.
30c4d8dc 4672 (sql-comint product
7492acc9
MM
4673 (append (if (string= "" sql-database)
4674 nil
4675 (list sql-database))
4676 options)))
95e4b2ef
RS
4677
4678\f
4679
77d352a6 4680;;;###autoload
9250002f 4681(defun sql-ms (&optional buffer)
78024f88 4682 "Run osql by Microsoft as an inferior process.
95e4b2ef 4683
dab100d7 4684If buffer `*SQL*' exists but no process is running, make a new process.
95e4b2ef
RS
4685If buffer exists and a process is running, just switch to buffer
4686`*SQL*'.
4687
4688Interpreter used comes from variable `sql-ms-program'. Login uses the
dab100d7 4689variables `sql-user', `sql-password', `sql-database', and `sql-server'
f4df536d
JB
4690as defaults, if set. Additional command line parameters can be stored
4691in the list `sql-ms-options'.
95e4b2ef 4692
063c6324 4693The buffer is put in SQL interactive mode, giving commands for sending
95e4b2ef
RS
4694input. See `sql-interactive-mode'.
4695
9250002f
MM
4696To set the buffer name directly, use \\[universal-argument]
4697before \\[sql-ms]. Once session has started,
4698\\[sql-rename-buffer] can be called separately to rename the
4699buffer.
4700
95e4b2ef
RS
4701To specify a coding system for converting non-ASCII characters
4702in the input and output to the process, use \\[universal-coding-system-argument]
dab100d7 4703before \\[sql-ms]. You can also specify this with \\[set-buffer-process-coding-system]
95e4b2ef
RS
4704in the SQL buffer, after you start the process.
4705The default comes from `process-coding-system-alist' and
4706`default-process-coding-system'.
4707
4708\(Type \\[describe-mode] in the SQL buffer for a list of commands.)"
9250002f
MM
4709 (interactive "P")
4710 (sql-product-interactive 'ms buffer))
78024f88 4711
30c4d8dc 4712(defun sql-comint-ms (product options)
7492acc9 4713 "Create comint buffer and connect to Microsoft SQL Server."
78024f88
AS
4714 ;; Put all parameters to the program (if defined) in a list and call
4715 ;; make-comint.
93852cb0
SM
4716 (let ((params
4717 (append
4718 (if (not (string= "" sql-user))
4719 (list "-U" sql-user))
4720 (if (not (string= "" sql-database))
4721 (list "-d" sql-database))
4722 (if (not (string= "" sql-server))
4723 (list "-S" sql-server))
4724 options)))
4725 (setq params
4726 (if (not (string= "" sql-password))
4727 `("-P" ,sql-password ,@params)
4728 (if (string= "" sql-user)
4729 ;; If neither user nor password is provided, use system
4730 ;; credentials.
4731 `("-E" ,@params)
4732 ;; If -P is passed to ISQL as the last argument without a
4733 ;; password, it's considered null.
4734 `(,@params "-P"))))
30c4d8dc 4735 (sql-comint product params)))
95e4b2ef 4736
95e4b2ef
RS
4737\f
4738
4739;;;###autoload
9250002f 4740(defun sql-postgres (&optional buffer)
95e4b2ef
RS
4741 "Run psql by Postgres as an inferior process.
4742
dab100d7 4743If buffer `*SQL*' exists but no process is running, make a new process.
95e4b2ef
RS
4744If buffer exists and a process is running, just switch to buffer
4745`*SQL*'.
4746
4747Interpreter used comes from variable `sql-postgres-program'. Login uses
c04bb32e 4748the variables `sql-database' and `sql-server' as default, if set.
7a65c85c
GM
4749Additional command line parameters can be stored in the list
4750`sql-postgres-options'.
95e4b2ef 4751
063c6324 4752The buffer is put in SQL interactive mode, giving commands for sending
95e4b2ef
RS
4753input. See `sql-interactive-mode'.
4754
9250002f
MM
4755To set the buffer name directly, use \\[universal-argument]
4756before \\[sql-postgres]. Once session has started,
4757\\[sql-rename-buffer] can be called separately to rename the
4758buffer.
4759
95e4b2ef
RS
4760To specify a coding system for converting non-ASCII characters
4761in the input and output to the process, use \\[universal-coding-system-argument]
4762before \\[sql-postgres]. You can also specify this with \\[set-buffer-process-coding-system]
4763in the SQL buffer, after you start the process.
4764The default comes from `process-coding-system-alist' and
801d1cb0 4765`default-process-coding-system'. If your output lines end with ^M,
95e4b2ef
RS
4766your might try undecided-dos as a coding system. If this doesn't help,
4767Try to set `comint-output-filter-functions' like this:
4768
4769\(setq comint-output-filter-functions (append comint-output-filter-functions
4770 '(comint-strip-ctrl-m)))
4771
4772\(Type \\[describe-mode] in the SQL buffer for a list of commands.)"
9250002f
MM
4773 (interactive "P")
4774 (sql-product-interactive 'postgres buffer))
78024f88 4775
30c4d8dc 4776(defun sql-comint-postgres (product options)
7492acc9 4777 "Create comint buffer and connect to Postgres."
93852cb0
SM
4778 ;; username and password are ignored. Mark Stosberg suggests to add
4779 ;; the database at the end. Jason Beegan suggests using --pset and
78024f88
AS
4780 ;; pager=off instead of \\o|cat. The later was the solution by
4781 ;; Gregor Zych. Jason's suggestion is the default value for
4782 ;; sql-postgres-options.
93852cb0
SM
4783 (let ((params
4784 (append
4785 (if (not (= 0 sql-port))
4786 (list "-p" (number-to-string sql-port)))
4787 (if (not (string= "" sql-user))
4788 (list "-U" sql-user))
4789 (if (not (string= "" sql-server))
4790 (list "-h" sql-server))
4791 options
4792 (if (not (string= "" sql-database))
4793 (list sql-database)))))
30c4d8dc 4794 (sql-comint product params)))
95e4b2ef 4795
fbcc67e2 4796(defun sql-postgres-completion-object (sqlbuf schema)
93852cb0
SM
4797 (sql-redirect sqlbuf "\\t on")
4798 (let ((aligned
4799 (string= "aligned"
4800 (car (sql-redirect-value
4801 sqlbuf "\\a"
4802 "Output format is \\(.*\\)[.]$" 1)))))
4803 (when aligned
fbcc67e2 4804 (sql-redirect sqlbuf "\\a"))
93852cb0
SM
4805 (let* ((fs (or (car (sql-redirect-value
4806 sqlbuf "\\f" "Field separator is \"\\(.\\)[.]$" 1))
4807 "|"))
4808 (re (concat "^\\([^" fs "]*\\)" fs "\\([^" fs "]*\\)"
4809 fs "[^" fs "]*" fs "[^" fs "]*$"))
4810 (cl (if (not schema)
4811 (sql-redirect-value sqlbuf "\\d" re '(1 2))
4812 (append (sql-redirect-value
4813 sqlbuf (format "\\dt %s.*" schema) re '(1 2))
4814 (sql-redirect-value
4815 sqlbuf (format "\\dv %s.*" schema) re '(1 2))
4816 (sql-redirect-value
4817 sqlbuf (format "\\ds %s.*" schema) re '(1 2))))))
4818
4819 ;; Restore tuples and alignment to what they were.
4820 (sql-redirect sqlbuf "\\t off")
4821 (when (not aligned)
4822 (sql-redirect sqlbuf "\\a"))
4823
4824 ;; Return the list of table names (public schema name can be omitted)
4825 (mapcar (lambda (tbl)
4826 (if (string= (car tbl) "public")
4827 (cadr tbl)
4828 (format "%s.%s" (car tbl) (cadr tbl))))
4829 cl))))
fbcc67e2 4830
eb3f61dd
GM
4831\f
4832
4833;;;###autoload
9250002f 4834(defun sql-interbase (&optional buffer)
eb3f61dd
GM
4835 "Run isql by Interbase as an inferior process.
4836
4837If buffer `*SQL*' exists but no process is running, make a new process.
4838If buffer exists and a process is running, just switch to buffer
4839`*SQL*'.
4840
4841Interpreter used comes from variable `sql-interbase-program'. Login
4842uses the variables `sql-user', `sql-password', and `sql-database' as
4843defaults, if set.
4844
063c6324 4845The buffer is put in SQL interactive mode, giving commands for sending
eb3f61dd
GM
4846input. See `sql-interactive-mode'.
4847
9250002f
MM
4848To set the buffer name directly, use \\[universal-argument]
4849before \\[sql-interbase]. Once session has started,
4850\\[sql-rename-buffer] can be called separately to rename the
4851buffer.
4852
eb3f61dd
GM
4853To specify a coding system for converting non-ASCII characters
4854in the input and output to the process, use \\[universal-coding-system-argument]
4855before \\[sql-interbase]. You can also specify this with \\[set-buffer-process-coding-system]
4856in the SQL buffer, after you start the process.
4857The default comes from `process-coding-system-alist' and
4858`default-process-coding-system'.
4859
4860\(Type \\[describe-mode] in the SQL buffer for a list of commands.)"
9250002f
MM
4861 (interactive "P")
4862 (sql-product-interactive 'interbase buffer))
78024f88 4863
30c4d8dc 4864(defun sql-comint-interbase (product options)
7492acc9 4865 "Create comint buffer and connect to Interbase."
78024f88
AS
4866 ;; Put all parameters to the program (if defined) in a list and call
4867 ;; make-comint.
93852cb0
SM
4868 (let ((params
4869 (append
4870 (if (not (string= "" sql-database))
4871 (list sql-database)) ; Add to the front!
4872 (if (not (string= "" sql-password))
4873 (list "-p" sql-password))
4874 (if (not (string= "" sql-user))
4875 (list "-u" sql-user))
4876 options)))
30c4d8dc 4877 (sql-comint product params)))
eb3f61dd 4878
624ef9b3
GM
4879\f
4880
4881;;;###autoload
9250002f 4882(defun sql-db2 (&optional buffer)
624ef9b3
GM
4883 "Run db2 by IBM as an inferior process.
4884
4885If buffer `*SQL*' exists but no process is running, make a new process.
4886If buffer exists and a process is running, just switch to buffer
4887`*SQL*'.
4888
4889Interpreter used comes from variable `sql-db2-program'. There is not
4890automatic login.
4891
063c6324 4892The buffer is put in SQL interactive mode, giving commands for sending
624ef9b3
GM
4893input. See `sql-interactive-mode'.
4894
aa88e662
GM
4895If you use \\[sql-accumulate-and-indent] to send multiline commands to
4896db2, newlines will be escaped if necessary. If you don't want that, set
4897`comint-input-sender' back to `comint-simple-send' by writing an after
4898advice. See the elisp manual for more information.
624ef9b3 4899
9250002f
MM
4900To set the buffer name directly, use \\[universal-argument]
4901before \\[sql-db2]. Once session has started,
4902\\[sql-rename-buffer] can be called separately to rename the
4903buffer.
4904
624ef9b3
GM
4905To specify a coding system for converting non-ASCII characters
4906in the input and output to the process, use \\[universal-coding-system-argument]
4907before \\[sql-db2]. You can also specify this with \\[set-buffer-process-coding-system]
4908in the SQL buffer, after you start the process.
4909The default comes from `process-coding-system-alist' and
4910`default-process-coding-system'.
4911
4912\(Type \\[describe-mode] in the SQL buffer for a list of commands.)"
9250002f
MM
4913 (interactive "P")
4914 (sql-product-interactive 'db2 buffer))
78024f88 4915
30c4d8dc 4916(defun sql-comint-db2 (product options)
7492acc9 4917 "Create comint buffer and connect to DB2."
78024f88
AS
4918 ;; Put all parameters to the program (if defined) in a list and call
4919 ;; make-comint.
fbcc67e2 4920 (sql-comint product options))
624ef9b3 4921
f4df536d 4922;;;###autoload
9250002f 4923(defun sql-linter (&optional buffer)
f4df536d
JB
4924 "Run inl by RELEX as an inferior process.
4925
4926If buffer `*SQL*' exists but no process is running, make a new process.
4927If buffer exists and a process is running, just switch to buffer
4928`*SQL*'.
4929
4930Interpreter used comes from variable `sql-linter-program' - usually `inl'.
4931Login uses the variables `sql-user', `sql-password', `sql-database' and
4932`sql-server' as defaults, if set. Additional command line parameters
7492acc9 4933can be stored in the list `sql-linter-options'. Run inl -h to get help on
f4df536d
JB
4934parameters.
4935
4936`sql-database' is used to set the LINTER_MBX environment variable for
4937local connections, `sql-server' refers to the server name from the
4938`nodetab' file for the network connection (dbc_tcp or friends must run
4939for this to work). If `sql-password' is an empty string, inl will use
4940an empty password.
4941
063c6324 4942The buffer is put in SQL interactive mode, giving commands for sending
f4df536d
JB
4943input. See `sql-interactive-mode'.
4944
9250002f
MM
4945To set the buffer name directly, use \\[universal-argument]
4946before \\[sql-linter]. Once session has started,
4947\\[sql-rename-buffer] can be called separately to rename the
4948buffer.
4949
f4df536d 4950\(Type \\[describe-mode] in the SQL buffer for a list of commands.)"
9250002f
MM
4951 (interactive "P")
4952 (sql-product-interactive 'linter buffer))
78024f88 4953
30c4d8dc 4954(defun sql-comint-linter (product options)
7492acc9 4955 "Create comint buffer and connect to Linter."
78024f88
AS
4956 ;; Put all parameters to the program (if defined) in a list and call
4957 ;; make-comint.
93852cb0
SM
4958 (let* ((login
4959 (if (not (string= "" sql-user))
4960 (concat sql-user "/" sql-password)))
4961 (params
4962 (append
4963 (if (not (string= "" sql-server))
4964 (list "-n" sql-server))
4965 (list "-u" login)
4966 options)))
4967 (cl-letf (((getenv "LINTER_MBX")
4968 (unless (string= "" sql-database) sql-database)))
4969 (sql-comint product params))))
f4df536d
JB
4970
4971\f
4972
95e4b2ef
RS
4973(provide 'sql)
4974
4975;;; sql.el ends here
fbcc67e2
MM
4976
4977; LocalWords: sql SQL SQLite sqlite Sybase Informix MySQL
4978; LocalWords: Postgres SQLServer SQLi