* lisp/net/shr.el (shr-insert-document): Explain why bidi-display-reordering
[emacs.git] / lisp / progmodes / sql.el
blob6224b3b5f3fe361ef98dc428677065b17829035a
1 ;;; sql.el --- specialized comint.el for SQL interpreters -*- lexical-binding: t -*-
3 ;; Copyright (C) 1998-2021 Free Software Foundation, Inc.
5 ;; Author: Alex Schroeder <alex@gnu.org>
6 ;; Maintainer: Michael Mauger <michael@mauger.com>
7 ;; Version: 3.6
8 ;; Keywords: comm languages processes
10 ;; This file is part of GNU Emacs.
12 ;; GNU Emacs is free software: you can redistribute it and/or modify
13 ;; it under the terms of the GNU General Public License as published by
14 ;; the Free Software Foundation, either version 3 of the License, or
15 ;; (at your option) any later version.
17 ;; GNU Emacs is distributed in the hope that it will be useful,
18 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
19 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 ;; GNU General Public License for more details.
22 ;; You should have received a copy of the GNU General Public License
23 ;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
25 ;;; Commentary:
27 ;; Please send bug reports and bug fixes to the mailing list at
28 ;; bug-gnu-emacs@gnu.org.
29 ;; See also the general help list at
30 ;; https://lists.gnu.org/mailman/listinfo/help-gnu-emacs
31 ;; I monitor this list actively. If you send an e-mail
32 ;; to Alex Schroeder it usually makes it to me when Alex has a chance
33 ;; to forward them along (Thanks, Alex).
35 ;; This file provides a sql-mode and a sql-interactive-mode. The
36 ;; original goals were two simple modes providing syntactic
37 ;; highlighting. The interactive mode had to provide a command-line
38 ;; history; the other mode had to provide "send region/buffer to SQL
39 ;; interpreter" functions. "simple" in this context means easy to
40 ;; use, easy to maintain and little or no bells and whistles. This
41 ;; has changed somewhat as experience with the mode has accumulated.
43 ;; Support for different flavors of SQL and command interpreters was
44 ;; available in early versions of sql.el. This support has been
45 ;; extended and formalized in later versions. Part of the impetus for
46 ;; the improved support of SQL flavors was borne out of the current
47 ;; maintainers consulting experience. In the past twenty years, I
48 ;; have used Oracle, Sybase, Informix, MySQL, Postgres, and SQLServer.
49 ;; On some assignments, I have used two or more of these concurrently.
51 ;; If anybody feels like extending this sql mode, take a look at the
52 ;; above mentioned modes and write a sqlx-mode on top of this one. If
53 ;; this proves to be difficult, please suggest changes that will
54 ;; facilitate your plans. Facilities have been provided to add
55 ;; products and product-specific configuration.
57 ;; sql-interactive-mode is used to interact with a SQL interpreter
58 ;; process in a SQLi buffer (usually called `*SQL*'). The SQLi buffer
59 ;; is created by calling a SQL interpreter-specific entry function or
60 ;; sql-product-interactive. Do *not* call sql-interactive-mode by
61 ;; itself.
63 ;; The list of currently supported interpreters and the corresponding
64 ;; entry function used to create the SQLi buffers is shown with
65 ;; `sql-help' (M-x sql-help).
67 ;; Since sql-interactive-mode is built on top of the general
68 ;; command-interpreter-in-a-buffer mode (comint mode), it shares a
69 ;; common base functionality, and a common set of bindings, with all
70 ;; modes derived from comint mode. This makes these modes easier to
71 ;; use.
73 ;; sql-mode can be used to keep editing SQL statements. The SQL
74 ;; statements can be sent to the SQL process in the SQLi buffer.
76 ;; For documentation on the functionality provided by comint mode, and
77 ;; the hooks available for customizing it, see the file `comint.el'.
79 ;; Hint for newbies: take a look at `dabbrev-expand', `abbrev-mode', and
80 ;; `imenu-add-menubar-index'.
82 ;;; Bugs:
84 ;; sql-ms now uses osql instead of isql. Osql flushes its error
85 ;; stream more frequently than isql so that error messages are
86 ;; available. There is no prompt and some output still is buffered.
87 ;; This improves the interaction under Emacs but it still is somewhat
88 ;; awkward.
90 ;; Quoted identifiers are not supported for highlighting. Most
91 ;; databases support the use of double quoted strings in place of
92 ;; identifiers; ms (Microsoft SQLServer) also supports identifiers
93 ;; enclosed within brackets [].
95 ;;; Product Support:
97 ;; To add support for additional SQL products the following steps
98 ;; must be followed ("xyz" is the name of the product in the examples
99 ;; below):
101 ;; 1) Add the product to the list of known products.
103 ;; (sql-add-product 'xyz "XyzDB"
104 ;; '(:free-software t))
106 ;; 2) Define font lock settings. All ANSI keywords will be
107 ;; highlighted automatically, so only product specific keywords
108 ;; need to be defined here.
110 ;; (defvar my-sql-mode-xyz-font-lock-keywords
111 ;; '(("\\b\\(red\\|orange\\|yellow\\)\\b"
112 ;; . font-lock-keyword-face))
113 ;; "XyzDB SQL keywords used by font-lock.")
115 ;; (sql-set-product-feature 'xyz
116 ;; :font-lock
117 ;; 'my-sql-mode-xyz-font-lock-keywords)
119 ;; 3) Define any special syntax characters including comments and
120 ;; identifier characters.
122 ;; (sql-set-product-feature 'xyz
123 ;; :syntax-alist ((?# . "_")))
125 ;; 4) Define the interactive command interpreter for the database
126 ;; product.
128 ;; (defcustom my-sql-xyz-program "ixyz"
129 ;; "Command to start ixyz by XyzDB."
130 ;; :type 'file
131 ;; :group 'SQL)
133 ;; (sql-set-product-feature 'xyz
134 ;; :sqli-program 'my-sql-xyz-program)
135 ;; (sql-set-product-feature 'xyz
136 ;; :prompt-regexp "^xyzdb> ")
137 ;; (sql-set-product-feature 'xyz
138 ;; :prompt-length 7)
140 ;; 5) Define login parameters and command line formatting.
142 ;; (defcustom my-sql-xyz-login-params '(user password server database)
143 ;; "Login parameters to needed to connect to XyzDB."
144 ;; :type 'sql-login-params
145 ;; :group 'SQL)
147 ;; (sql-set-product-feature 'xyz
148 ;; :sqli-login 'my-sql-xyz-login-params)
150 ;; (defcustom my-sql-xyz-options '("-X" "-Y" "-Z")
151 ;; "List of additional options for `sql-xyz-program'."
152 ;; :type '(repeat string)
153 ;; :group 'SQL)
155 ;; (sql-set-product-feature 'xyz
156 ;; :sqli-options 'my-sql-xyz-options))
158 ;; (defun my-sql-comint-xyz (product options &optional buf-name)
159 ;; "Connect ti XyzDB in a comint buffer."
161 ;; ;; Do something with `sql-user', `sql-password',
162 ;; ;; `sql-database', and `sql-server'.
163 ;; (let ((params
164 ;; (append
165 ;; (if (not (string= "" sql-user))
166 ;; (list "-U" sql-user))
167 ;; (if (not (string= "" sql-password))
168 ;; (list "-P" sql-password))
169 ;; (if (not (string= "" sql-database))
170 ;; (list "-D" sql-database))
171 ;; (if (not (string= "" sql-server))
172 ;; (list "-S" sql-server))
173 ;; options)))
174 ;; (sql-comint product params buf-name)))
176 ;; (sql-set-product-feature 'xyz
177 ;; :sqli-comint-func 'my-sql-comint-xyz)
179 ;; 6) Define a convenience function to invoke the SQL interpreter.
181 ;; (defun my-sql-xyz (&optional buffer)
182 ;; "Run ixyz by XyzDB as an inferior process."
183 ;; (interactive "P")
184 ;; (sql-product-interactive 'xyz buffer))
186 ;;; To Do:
188 ;; Improve keyword highlighting for individual products. I have tried
189 ;; to update those database that I use. Feel free to send me updates,
190 ;; or direct me to the reference manuals for your favorite database.
192 ;; When there are no keywords defined, the ANSI keywords are
193 ;; highlighted. ANSI keywords are highlighted even if the keyword is
194 ;; not used for your current product. This should help identify
195 ;; portability concerns.
197 ;; Add different highlighting levels.
199 ;; Add support for listing available tables or the columns in a table.
201 ;;; Thanks to all the people who helped me out:
203 ;; Alex Schroeder <alex@gnu.org> -- the original author
204 ;; Kai Blauberg <kai.blauberg@metla.fi>
205 ;; <ibalaban@dalet.com>
206 ;; Yair Friedman <yfriedma@JohnBryce.Co.Il>
207 ;; Gregor Zych <zych@pool.informatik.rwth-aachen.de>
208 ;; nino <nino@inform.dk>
209 ;; Berend de Boer <berend@pobox.com>
210 ;; Adam Jenkins <adam@thejenkins.org>
211 ;; Michael Mauger <michael@mauger.com> -- improved product support
212 ;; Drew Adams <drew.adams@oracle.com> -- Emacs 20 support
213 ;; Harald Maier <maierh@myself.com> -- sql-send-string
214 ;; Stefan Monnier <monnier@iro.umontreal.ca> -- font-lock corrections;
215 ;; code polish; on-going guidance and mentorship
216 ;; Paul Sleigh <bat@flurf.net> -- MySQL keyword enhancement
217 ;; Andrew Schein <andrew@andrewschein.com> -- sql-port bug
218 ;; Ian Bjorhovde <idbjorh@dataproxy.com> -- db2 escape newlines
219 ;; incorrectly enabled by default
220 ;; Roman Scherer <roman.scherer@nugg.ad> -- Connection documentation
221 ;; Mark Wilkinson <wilkinsonmr@gmail.com> -- file-local variables ignored
222 ;; Simen Heggestøyl <simenheg@gmail.com> -- Postgres database completion
223 ;; Robert Cochran <robert-emacs@cochranmail.com> -- MariaDB support
224 ;; Alex Harsanyi <alexharsanyi@gmail.com> -- sql-indent package and support
225 ;; Roy Mathew <rmathew8@gmail.com> -- bug in `sql-send-string'
230 ;;; Code:
232 (require 'cl-lib)
233 (require 'comint)
234 (require 'thingatpt)
235 (require 'view)
236 (eval-when-compile (require 'subr-x)) ; string-empty-p
238 (defvar font-lock-keyword-face)
239 (defvar font-lock-set-defaults)
240 (defvar font-lock-string-face)
242 ;;; Allow customization
244 (defgroup SQL nil
245 "Running a SQL interpreter from within Emacs buffers."
246 :version "20.4"
247 :group 'languages
248 :group 'processes)
250 ;; These five variables will be used as defaults, if set.
252 (defcustom sql-user ""
253 "Default username."
254 :type 'string
255 :safe 'stringp)
257 (defcustom sql-password ""
258 "Default password.
259 If you customize this, the value will be stored in your init
260 file. Since that is a plaintext file, this could be dangerous."
261 :type 'string
262 :risky t)
264 (defcustom sql-database ""
265 "Default database."
266 :type 'string
267 :safe 'stringp)
269 (defcustom sql-server ""
270 "Default server or host."
271 :type 'string
272 :safe 'stringp)
274 (defcustom sql-port 0
275 "Default port for connecting to a MySQL or Postgres server."
276 :version "24.1"
277 :type 'number
278 :safe 'numberp)
280 (defcustom sql-default-directory nil
281 "Default directory for SQL processes."
282 :version "25.1"
283 :type '(choice (const nil) string)
284 :safe 'stringp)
286 ;; Login parameter type
288 ;; This seems too prescriptive. It probably fails to match some of
289 ;; the possible combinations. It would probably be better to just use
290 ;; plist for most of it.
291 (define-widget 'sql-login-params 'lazy
292 "Widget definition of the login parameters list"
293 :tag "Login Parameters"
294 :type '(set :tag "Login Parameters"
295 (choice :tag "user"
296 :value user
297 (const user)
298 (list :tag "Specify a default"
299 (const user)
300 (list :tag "Default"
301 :inline t (const :default) string)))
302 (const password)
303 (choice :tag "server"
304 :value server
305 (const server)
306 (list :tag "Specify a default"
307 (const server)
308 (list :tag "Default"
309 :inline t (const :default) string))
310 (list :tag "file"
311 (const :format "" server)
312 (const :format "" :file)
313 regexp)
314 (list :tag "completion"
315 (const :format "" server)
316 (const :format "" :completion)
317 (const :format "" :must-match)
318 (restricted-sexp
319 :match-alternatives (listp stringp))))
320 (choice :tag "database"
321 :value database
322 (const database)
323 (list :tag "Specify a default"
324 (const database)
325 (list :tag "Default"
326 :inline t (const :default) string))
327 (list :tag "file"
328 (const :format "" database)
329 (const :format "" :file)
330 (choice (const nil) regexp)
331 (const :format "" :must-match)
332 (symbol :tag ":must-match"))
333 (list :tag "completion"
334 (const :format "" database)
335 (const :format "" :default)
336 (string :tag ":default")
337 (const :format "" :completion)
338 (sexp :tag ":completion")
339 (const :format "" :must-match)
340 (symbol :tag ":must-match")))
341 (const port)))
343 ;; SQL Product support
345 (defvar sql-interactive-product nil
346 "Product under `sql-interactive-mode'.")
348 (defvar sql-connection nil
349 "Connection name if interactive session started by `sql-connect'.")
351 (defvar sql-product-alist
352 '((ansi
353 :name "ANSI"
354 :font-lock sql-mode-ansi-font-lock-keywords
355 :statement sql-ansi-statement-starters)
357 (db2
358 :name "DB2"
359 :font-lock sql-mode-db2-font-lock-keywords
360 :sqli-program sql-db2-program
361 :sqli-options sql-db2-options
362 :sqli-login sql-db2-login-params
363 :sqli-comint-func sql-comint-db2
364 :prompt-regexp "^db2 => "
365 :prompt-length 7
366 :prompt-cont-regexp "^db2 (cont\\.) => "
367 :input-filter sql-escape-newlines-filter)
369 (informix
370 :name "Informix"
371 :font-lock sql-mode-informix-font-lock-keywords
372 :sqli-program sql-informix-program
373 :sqli-options sql-informix-options
374 :sqli-login sql-informix-login-params
375 :sqli-comint-func sql-comint-informix
376 :prompt-regexp "^> "
377 :prompt-length 2
378 :syntax-alist ((?{ . "<") (?} . ">")))
380 (ingres
381 :name "Ingres"
382 :font-lock sql-mode-ingres-font-lock-keywords
383 :sqli-program sql-ingres-program
384 :sqli-options sql-ingres-options
385 :sqli-login sql-ingres-login-params
386 :sqli-comint-func sql-comint-ingres
387 :prompt-regexp "^\\* "
388 :prompt-length 2
389 :prompt-cont-regexp "^\\* ")
391 (interbase
392 :name "Interbase"
393 :font-lock sql-mode-interbase-font-lock-keywords
394 :sqli-program sql-interbase-program
395 :sqli-options sql-interbase-options
396 :sqli-login sql-interbase-login-params
397 :sqli-comint-func sql-comint-interbase
398 :prompt-regexp "^SQL> "
399 :prompt-length 5)
401 (linter
402 :name "Linter"
403 :font-lock sql-mode-linter-font-lock-keywords
404 :sqli-program sql-linter-program
405 :sqli-options sql-linter-options
406 :sqli-login sql-linter-login-params
407 :sqli-comint-func sql-comint-linter
408 :prompt-regexp "^SQL>"
409 :prompt-length 4)
411 (mariadb
412 :name "MariaDB"
413 :free-software t
414 :font-lock sql-mode-mariadb-font-lock-keywords
415 :sqli-program sql-mariadb-program
416 :sqli-options sql-mariadb-options
417 :sqli-login sql-mariadb-login-params
418 :sqli-comint-func sql-comint-mariadb
419 :list-all "SHOW TABLES;"
420 :list-table "DESCRIBE %s;"
421 :prompt-regexp "^MariaDB \\[.*]> "
422 :prompt-cont-regexp "^ [\"'`-]> "
423 :syntax-alist ((?# . "< b"))
424 :input-filter sql-remove-tabs-filter)
427 :name "Microsoft"
428 :font-lock sql-mode-ms-font-lock-keywords
429 :sqli-program sql-ms-program
430 :sqli-options sql-ms-options
431 :sqli-login sql-ms-login-params
432 :sqli-comint-func sql-comint-ms
433 :prompt-regexp "^[0-9]*>"
434 :prompt-cont-regexp "^[0-9]*>"
435 :prompt-length 5
436 :syntax-alist ((?@ . "_"))
437 :terminator ("^go" . "go"))
439 (mysql
440 :name "MySQL"
441 :free-software t
442 :font-lock sql-mode-mysql-font-lock-keywords
443 :sqli-program sql-mysql-program
444 :sqli-options sql-mysql-options
445 :sqli-login sql-mysql-login-params
446 :sqli-comint-func sql-comint-mysql
447 :list-all "SHOW TABLES;"
448 :list-table "DESCRIBE %s;"
449 :prompt-regexp "^mysql> "
450 :prompt-length 6
451 :prompt-cont-regexp "^ -> "
452 :syntax-alist ((?# . "< b") (?\\ . "\\"))
453 :input-filter sql-remove-tabs-filter)
455 (oracle
456 :name "Oracle"
457 :font-lock sql-mode-oracle-font-lock-keywords
458 :sqli-program sql-oracle-program
459 :sqli-options sql-oracle-options
460 :sqli-login sql-oracle-login-params
461 :sqli-comint-func sql-comint-oracle
462 :list-all sql-oracle-list-all
463 :list-table sql-oracle-list-table
464 :completion-object sql-oracle-completion-object
465 :prompt-regexp "^SQL> "
466 :prompt-length 5
467 :prompt-cont-regexp "^\\(?:[ ][ ][1-9]\\|[ ][1-9][0-9]\\|[1-9][0-9]\\{2\\}\\)[ ]\\{2\\}"
468 :statement sql-oracle-statement-starters
469 :syntax-alist ((?$ . "_") (?# . "_"))
470 :terminator ("\\(^/\\|;\\)" . "/")
471 :input-filter sql-placeholders-filter)
473 (postgres
474 :name "Postgres"
475 :free-software t
476 :font-lock sql-mode-postgres-font-lock-keywords
477 :sqli-program sql-postgres-program
478 :sqli-options sql-postgres-options
479 :sqli-login sql-postgres-login-params
480 :sqli-comint-func sql-comint-postgres
481 :list-all ("\\d+" . "\\dS+")
482 :list-table ("\\d+ %s" . "\\dS+ %s")
483 :completion-object sql-postgres-completion-object
484 :prompt-regexp "^[[:alnum:]_]*=[#>] "
485 :prompt-length 5
486 :prompt-cont-regexp "^[[:alnum:]_]*[-(][#>] "
487 :input-filter sql-remove-tabs-filter
488 :terminator ("\\(^\\s-*\\\\g\\|;\\)" . "\\g"))
490 (solid
491 :name "Solid"
492 :font-lock sql-mode-solid-font-lock-keywords
493 :sqli-program sql-solid-program
494 :sqli-options sql-solid-options
495 :sqli-login sql-solid-login-params
496 :sqli-comint-func sql-comint-solid
497 :prompt-regexp "^"
498 :prompt-length 0)
500 (sqlite
501 :name "SQLite"
502 :free-software t
503 :font-lock sql-mode-sqlite-font-lock-keywords
504 :sqli-program sql-sqlite-program
505 :sqli-options sql-sqlite-options
506 :sqli-login sql-sqlite-login-params
507 :sqli-comint-func sql-comint-sqlite
508 :list-all ".tables"
509 :list-table ".schema %s"
510 :completion-object sql-sqlite-completion-object
511 :prompt-regexp "^sqlite> "
512 :prompt-length 8
513 :prompt-cont-regexp "^ \\.\\.\\.> ")
515 (sybase
516 :name "Sybase"
517 :font-lock sql-mode-sybase-font-lock-keywords
518 :sqli-program sql-sybase-program
519 :sqli-options sql-sybase-options
520 :sqli-login sql-sybase-login-params
521 :sqli-comint-func sql-comint-sybase
522 :prompt-regexp "^SQL> "
523 :prompt-length 5
524 :syntax-alist ((?@ . "_"))
525 :terminator ("^go" . "go"))
527 (vertica
528 :name "Vertica"
529 :sqli-program sql-vertica-program
530 :sqli-options sql-vertica-options
531 :sqli-login sql-vertica-login-params
532 :sqli-comint-func sql-comint-vertica
533 :list-all ("\\d" . "\\dS")
534 :list-table "\\d %s"
535 :prompt-regexp "^[[:alnum:]_]*=[#>] "
536 :prompt-length 5
537 :prompt-cont-regexp "^[[:alnum:]_]*[-(][#>] ")
539 "An alist of product specific configuration settings.
541 Without an entry in this list a product will not be properly
542 highlighted and will not support `sql-interactive-mode'.
544 Each element in the list is in the following format:
546 (PRODUCT FEATURE VALUE ...)
548 where PRODUCT is the appropriate value of `sql-product'. The
549 product name is then followed by FEATURE-VALUE pairs. If a
550 FEATURE is not specified, its VALUE is treated as nil. FEATURE
551 may be any one of the following:
553 :name string containing the displayable name of
554 the product.
556 :free-software is the product Free (as in Freedom) software?
558 :font-lock name of the variable containing the product
559 specific font lock highlighting patterns.
561 :sqli-program name of the variable containing the product
562 specific interactive program name.
564 :sqli-options name of the variable containing the list
565 of product specific options.
567 :sqli-login name of the variable containing the list of
568 login parameters (i.e., user, password,
569 database and server) needed to connect to
570 the database.
572 :sqli-comint-func function of two arguments, PRODUCT
573 and OPTIONS, that will open a comint buffer
574 and connect to the database. PRODUCT is the
575 first argument to be passed to `sql-comint',
576 and OPTIONS should be included in its second
577 argument. The function should use the values
578 of `sql-user', `sql-password', `sql-database',
579 `sql-server' and `sql-port' to . Do product
580 specific configuration of comint in this
581 function. See `sql-comint-oracle' for an
582 example of such a function.
584 :list-all Command string or function which produces
585 a listing of all objects in the database.
586 If it's a cons cell, then the car
587 produces the standard list of objects and
588 the cdr produces an enhanced list of
589 objects. What \"enhanced\" means is
590 dependent on the SQL product and may not
591 exist. In general though, the
592 \"enhanced\" list should include visible
593 objects from other schemas.
595 :list-table Command string or function which produces
596 a detailed listing of a specific database
597 table. If its a cons cell, then the car
598 produces the standard list and the cdr
599 produces an enhanced list.
601 :completion-object A function that returns a list of
602 objects. Called with a single
603 parameter--if nil then list objects
604 accessible in the current schema, if
605 not-nil it is the name of a schema whose
606 objects should be listed.
608 :completion-column A function that returns a list of
609 columns. Called with a single
610 parameter--if nil then list objects
611 accessible in the current schema, if
612 not-nil it is the name of a schema whose
613 objects should be listed.
615 :prompt-regexp regular expression string that matches
616 the prompt issued by the product
617 interpreter.
619 :prompt-length length of the prompt on the line.
621 :prompt-cont-regexp regular expression string that matches
622 the continuation prompt issued by the
623 product interpreter.
625 :input-filter function which can filter strings sent to
626 the command interpreter. It is also used
627 by the `sql-send-string',
628 `sql-send-region', `sql-send-paragraph'
629 and `sql-send-buffer' functions. The
630 function is passed the string sent to the
631 command interpreter and must return the
632 filtered string. May also be a list of
633 such functions.
635 :statement name of a variable containing a regexp that
636 matches the beginning of SQL statements.
638 :terminator the terminator to be sent after a
639 `sql-send-string', `sql-send-region',
640 `sql-send-paragraph' and
641 `sql-send-buffer' command. May be the
642 literal string or a cons of a regexp to
643 match an existing terminator in the
644 string and the terminator to be used if
645 its absent. By default \";\".
647 :syntax-alist alist of syntax table entries to enable
648 special character treatment by font-lock
649 and imenu.
651 Other features can be stored but they will be ignored. However,
652 you can develop new functionality which is product independent by
653 using `sql-get-product-feature' to lookup the product specific
654 settings.")
656 (defvar sql-indirect-features
657 '(:font-lock :sqli-program :sqli-options :sqli-login :statement))
659 (defcustom sql-connection-alist nil
660 "An alist of connection parameters for interacting with a SQL product.
661 Each element of the alist is as follows:
663 (CONNECTION \(SQL-VARIABLE VALUE) ...)
665 Where CONNECTION is a case-insensitive string identifying the
666 connection, SQL-VARIABLE is the symbol name of a SQL mode
667 variable, and VALUE is the value to be assigned to the variable.
668 The most common SQL-VARIABLE settings associated with a
669 connection are: `sql-product', `sql-user', `sql-password',
670 `sql-port', `sql-server', and `sql-database'.
672 If a SQL-VARIABLE is part of the connection, it will not be
673 prompted for during login. The command `sql-connect' starts a
674 predefined SQLi session using the parameters from this list.
675 Connections defined here appear in the submenu SQL->Start... for
676 making new SQLi sessions."
677 :type `(alist :key-type (string :tag "Connection")
678 :value-type
679 (set
680 (group (const :tag "Product" sql-product)
681 (choice
682 ,@(mapcar
683 (lambda (prod-info)
684 `(const :tag
685 ,(or (plist-get (cdr prod-info) :name)
686 (capitalize
687 (symbol-name (car prod-info))))
688 (quote ,(car prod-info))))
689 sql-product-alist)))
690 (group (const :tag "Username" sql-user) string)
691 (group (const :tag "Password" sql-password) string)
692 (group (const :tag "Server" sql-server) string)
693 (group (const :tag "Database" sql-database) string)
694 (group (const :tag "Port" sql-port) integer)
695 (repeat :inline t
696 (list :tab "Other"
697 (symbol :tag " Variable Symbol")
698 ;; FIXME: Why "Value *Expression*"?
699 (sexp :tag "Value Expression")))))
700 :version "24.1")
702 (defvaralias 'sql-dialect 'sql-product)
704 (defcustom sql-product 'ansi
705 "Select the SQL database product used.
706 This allows highlighting buffers properly when you open them."
707 :type `(choice
708 ,@(mapcar (lambda (prod-info)
709 `(const :tag
710 ,(or (plist-get (cdr prod-info) :name)
711 (capitalize (symbol-name (car prod-info))))
712 ,(car prod-info)))
713 sql-product-alist))
714 :safe 'symbolp)
716 ;; SQL indent support
718 (defcustom sql-use-indent-support t
719 "If non-nil then use the SQL indent support features of sql-indent.
720 The `sql-indent' package in ELPA provides indentation support for
721 SQL statements with easy customizations to support varied layout
722 requirements.
724 The package must be available to be loaded and activated."
725 :link '(url-link "https://elpa.gnu.org/packages/sql-indent.html")
726 :type 'boolean
727 :version "27.1")
729 (defun sql-indent-enable ()
730 "Enable `sqlind-minor-mode' if available and requested."
731 (when (fboundp 'sqlind-minor-mode)
732 (sqlind-minor-mode (if sql-use-indent-support +1 -1))))
734 ;; Secure Password wallet
736 (require 'auth-source)
738 (defun sql-auth-source-search-wallet (wallet product user server database port)
739 "Read auth source WALLET to locate the USER secret.
740 Sets `auth-sources' to WALLET and uses `auth-source-search' to locate the entry.
741 The DATABASE and SERVER are concatenated with a slash between them as the
742 host key."
743 (let* ((auth-sources wallet)
744 host
745 secret h-secret sd-secret)
747 ;; product
748 (setq product (symbol-name product))
750 ;; user
751 (setq user (unless (string-empty-p user) user))
753 ;; port
754 (setq port
755 (when (and port (numberp port) (not (zerop port)))
756 (number-to-string port)))
758 ;; server
759 (setq server (unless (string-empty-p server) server))
761 ;; database
762 (setq database (unless (string-empty-p database) database))
764 ;; host
765 (setq host (if server
766 (if database
767 (concat server "/" database)
768 server)
769 database))
771 ;; Perform search
772 (dolist (s (auth-source-search :max 1000))
773 (when (and
774 ;; Is PRODUCT specified, in the enty, and they are equal
775 (if product
776 (if (plist-member s :product)
777 (equal (plist-get s :product) product)
780 ;; Is USER specified, in the entry, and they are equal
781 (if user
782 (if (plist-member s :user)
783 (equal (plist-get s :user) user)
786 ;; Is PORT specified, in the entry, and they are equal
787 (if port
788 (if (plist-member s :port)
789 (equal (plist-get s :port) port)
792 ;; Is HOST specified, in the entry, and they are equal
793 ;; then the H-SECRET list
794 (if (and host
795 (plist-member s :host)
796 (equal (plist-get s :host) host))
797 (push s h-secret)
798 ;; Are SERVER and DATABASE specified, present, and equal
799 ;; then the SD-SECRET list
800 (if (and server
801 (plist-member s :server)
802 database
803 (plist-member s :database)
804 (equal (plist-get s :server) server)
805 (equal (plist-get s :database) database))
806 (push s sd-secret)
807 ;; Is SERVER specified, in the entry, and they are equal
808 ;; then the base SECRET list
809 (if (and server
810 (plist-member s :server)
811 (equal (plist-get s :server) server))
812 (push s secret)
813 ;; Is DATABASE specified, in the entry, and they are equal
814 ;; then the base SECRET list
815 (if (and database
816 (plist-member s :database)
817 (equal (plist-get s :database) database))
818 (push s secret)))))))
819 (setq secret (or h-secret sd-secret secret))
821 ;; If we found a single secret, return the password
822 (when (= 1 (length secret))
823 (setq secret (car secret))
824 (if (plist-member secret :secret)
825 (plist-get secret :secret)
826 nil))))
828 (defcustom sql-password-wallet
829 (let (wallet w)
830 (dolist (ext '(".json.gpg" ".gpg" ".json" "") wallet)
831 (unless wallet
832 (setq w (locate-user-emacs-file (concat "sql-wallet" ext)
833 (concat ".sql-wallet" ext)))
834 (when (file-exists-p w)
835 (setq wallet (list w))))))
836 "Identification of the password wallet.
837 See `sql-password-search-wallet-function' to understand how this value
838 is used to locate the password wallet."
839 :type (plist-get (symbol-plist 'auth-sources) 'custom-type)
840 :version "27.1")
842 (defvar sql-password-search-wallet-function #'sql-auth-source-search-wallet
843 "Function to handle the lookup of the database password.
844 The specified function will be called as:
845 (wallet-func WALLET PRODUCT USER SERVER DATABASE PORT)
847 It is expected to return either a string containing the password,
848 a function returning the password, or nil. If you want to support
849 another format of password file, then implement a different
850 search wallet function and identify the location of the password
851 store with `sql-password-wallet'.")
853 ;; misc customization of sql.el behavior
855 (defcustom sql-electric-stuff nil
856 "Treat some input as electric.
857 If set to the symbol `semicolon', then hitting `;' will send current
858 input in the SQLi buffer to the process.
859 If set to the symbol `go', then hitting `go' on a line by itself will
860 send current input in the SQLi buffer to the process.
861 If set to nil, then you must use \\[comint-send-input] in order to send
862 current input in the SQLi buffer to the process."
863 :type '(choice (const :tag "Nothing" nil)
864 (const :tag "The semicolon `;'" semicolon)
865 (const :tag "The string `go' by itself" go))
866 :version "20.8")
868 (defcustom sql-send-terminator nil
869 "When non-nil, add a terminator to text sent to the SQL interpreter.
871 When text is sent to the SQL interpreter (via `sql-send-string',
872 `sql-send-region', `sql-send-paragraph' or `sql-send-buffer'), a
873 command terminator can be automatically sent as well. The
874 terminator is not sent, if the string sent already ends with the
875 terminator.
877 If this value is t, then the default command terminator for the
878 SQL interpreter is sent. If this value is a string, then the
879 string is sent.
881 If the value is a cons cell of the form (PAT . TERM), then PAT is
882 a regexp used to match the terminator in the string and TERM is
883 the terminator to be sent. This form is useful if the SQL
884 interpreter has more than one way of submitting a SQL command.
885 The PAT regexp can match any of them, and TERM is the way we do
886 it automatically."
888 :type '(choice (const :tag "No Terminator" nil)
889 (const :tag "Default Terminator" t)
890 (string :tag "Terminator String")
891 (cons :tag "Terminator Pattern and String"
892 (regexp :tag "Terminator Pattern")
893 (string :tag "Terminator String")))
894 :version "22.2")
896 (defvar sql-contains-names nil
897 "When non-nil, the current buffer contains database names.
899 Globally should be set to nil; it will be non-nil in `sql-mode',
900 `sql-interactive-mode' and list all buffers.")
902 (defvar sql-login-delay 7.5 ;; Secs
903 "Maximum number of seconds you are willing to wait for a login connection.")
905 (defvaralias 'sql-pop-to-buffer-after-send-region 'sql-display-sqli-buffer-function)
907 (defcustom sql-display-sqli-buffer-function #'display-buffer
908 "Function to be called to display a SQLi buffer after `sql-send-*'.
910 When set to a function, it will be called to display the buffer.
911 When set to t, the default function `pop-to-buffer' will be
912 called. If not set, no attempt will be made to display the
913 buffer."
915 :type '(choice (const :tag "Default" t)
916 (const :tag "No display" nil)
917 (function :tag "Display Buffer function"))
918 :version "27.1")
920 ;; imenu support for sql-mode.
922 (defvar sql-imenu-generic-expression
923 ;; Items are in reverse order because they are rendered in reverse.
924 '(("Rules/Defaults" "^\\s-*create\\s-+\\(?:\\w+\\s-+\\)*\\(?:rule\\|default\\)\\(?:if\\s-+not\\s-+exists\\s-+\\)?\\s-+\\(\\(?:\\w+\\s-*[.]\\s-*\\)*\\w+\\)" 1)
925 ("Sequences" "^\\s-*create\\s-+\\(?:\\w+\\s-+\\)*sequence\\s-+\\(?:if\\s-+not\\s-+exists\\s-+\\)?\\(\\(?:\\w+\\s-*[.]\\s-*\\)*\\w+\\)" 1)
926 ("Triggers" "^\\s-*create\\s-+\\(?:\\w+\\s-+\\)*trigger\\s-+\\(?:if\\s-+not\\s-+exists\\s-+\\)?\\(\\(?:\\w+\\s-*[.]\\s-*\\)*\\w+\\)" 1)
927 ("Functions" "^\\s-*\\(?:create\\s-+\\(?:\\w+\\s-+\\)*\\)?function\\s-+\\(?:if\\s-+not\\s-+exists\\s-+\\)?\\(\\(?:\\w+\\s-*[.]\\s-*\\)*\\w+\\)" 1)
928 ("Procedures" "^\\s-*\\(?:create\\s-+\\(?:\\w+\\s-+\\)*\\)?proc\\(?:edure\\)?\\s-+\\(?:if\\s-+not\\s-+exists\\s-+\\)?\\(\\(?:\\w+\\s-*[.]\\s-*\\)*\\w+\\)" 1)
929 ("Packages" "^\\s-*create\\s-+\\(?:\\w+\\s-+\\)*package\\s-+\\(?:body\\s-+\\)?\\(?:if\\s-+not\\s-+exists\\s-+\\)?\\(\\(?:\\w+\\s-*[.]\\s-*\\)*\\w+\\)" 1)
930 ("Types" "^\\s-*create\\s-+\\(?:\\w+\\s-+\\)*type\\s-+\\(?:body\\s-+\\)?\\(?:if\\s-+not\\s-+exists\\s-+\\)?\\(\\(?:\\w+\\s-*[.]\\s-*\\)*\\w+\\)" 1)
931 ("Indexes" "^\\s-*create\\s-+\\(?:\\w+\\s-+\\)*index\\s-+\\(?:if\\s-+not\\s-+exists\\s-+\\)?\\(\\(?:\\w+\\s-*[.]\\s-*\\)*\\w+\\)" 1)
932 ("Tables/Views" "^\\s-*create\\s-+\\(?:\\w+\\s-+\\)*\\(?:table\\|view\\)\\s-+\\(?:if\\s-+not\\s-+exists\\s-+\\)?\\(\\(?:\\w+\\s-*[.]\\s-*\\)*\\w+\\)" 1))
933 "Define interesting points in the SQL buffer for `imenu'.
935 This is used to set `imenu-generic-expression' when SQL mode is
936 entered. Subsequent changes to `sql-imenu-generic-expression' will
937 not affect existing SQL buffers because `imenu-generic-expression' is
938 a local variable.")
940 ;; history file
942 (defcustom sql-input-ring-file-name nil
943 "If non-nil, name of the file to read/write input history.
945 You have to set this variable if you want the history of your commands
946 saved from one Emacs session to the next. If this variable is set,
947 exiting the SQL interpreter in an SQLi buffer will write the input
948 history to the specified file. Starting a new process in a SQLi buffer
949 will read the input history from the specified file.
951 This is used to initialize `comint-input-ring-file-name'.
953 Note that the size of the input history is determined by the variable
954 `comint-input-ring-size'."
955 :type '(choice (const :tag "none" nil)
956 (file)))
958 (defcustom sql-input-ring-separator "\n--\n"
959 "Separator between commands in the history file.
961 If set to \"\\n\", each line in the history file will be interpreted as
962 one command. Multi-line commands are split into several commands when
963 the input ring is initialized from a history file.
965 This variable used to initialize `comint-input-ring-separator'.
966 `comint-input-ring-separator' is part of Emacs 21; if your Emacs
967 does not have it, setting `sql-input-ring-separator' will have no
968 effect. In that case multiline commands will be split into several
969 commands when the input history is read, as if you had set
970 `sql-input-ring-separator' to \"\\n\"."
971 :type 'string)
973 ;; The usual hooks
975 (defcustom sql-interactive-mode-hook '(sql-indent-enable)
976 "Hook for customizing `sql-interactive-mode'."
977 :type 'hook
978 :version "27.1")
980 (defcustom sql-mode-hook '(sql-indent-enable)
981 "Hook for customizing `sql-mode'."
982 :type 'hook
983 :version "27.1")
985 (defcustom sql-set-sqli-hook '()
986 "Hook for reacting to changes of `sql-buffer'.
988 This is called by `sql-set-sqli-buffer' when the value of `sql-buffer'
989 is changed."
990 :type 'hook)
992 (defcustom sql-login-hook '()
993 "Hook for interacting with a buffer in `sql-interactive-mode'.
995 This hook is invoked in a buffer once it is ready to accept input
996 for the first time."
997 :version "24.1"
998 :type 'hook)
1000 ;; Customization for ANSI
1002 (defcustom sql-ansi-statement-starters
1003 (regexp-opt '("create" "alter" "drop"
1004 "select" "insert" "update" "delete" "merge"
1005 "grant" "revoke"))
1006 "Regexp of keywords that start SQL commands.
1008 All products share this list; products should define a regexp to
1009 identify additional keywords in a variable defined by
1010 the :statement feature."
1011 :version "24.1"
1012 :type 'regexp)
1014 ;; Customization for Oracle
1016 (defcustom sql-oracle-program "sqlplus"
1017 "Command to start sqlplus by Oracle.
1019 Starts `sql-interactive-mode' after doing some setup.
1021 On Windows, \"sqlplus\" usually starts the sqlplus \"GUI\". In order
1022 to start the sqlplus console, use \"plus33\" or something similar.
1023 You will find the file in your Orant\\bin directory."
1024 :type 'file)
1026 (defcustom sql-oracle-options '("-L")
1027 "List of additional options for `sql-oracle-program'."
1028 :type '(repeat string)
1029 :version "24.4")
1031 (defcustom sql-oracle-login-params '(user password database)
1032 "List of login parameters needed to connect to Oracle."
1033 :type 'sql-login-params
1034 :version "24.1")
1036 (defcustom sql-oracle-statement-starters
1037 (regexp-opt '("declare" "begin" "with"))
1038 "Additional statement starting keywords in Oracle."
1039 :version "24.1"
1040 :type 'string)
1042 (defcustom sql-oracle-scan-on t
1043 "Non-nil if placeholders should be replaced in Oracle SQLi.
1045 When non-nil, Emacs will scan text sent to sqlplus and prompt
1046 for replacement text for & placeholders as sqlplus does. This
1047 is needed on Windows where SQL*Plus output is buffered and the
1048 prompts are not shown until after the text is entered.
1050 You need to issue the following command in SQL*Plus to be safe:
1052 SET DEFINE OFF
1054 In older versions of SQL*Plus, this was the SET SCAN OFF command."
1055 :version "24.1"
1056 :type 'boolean)
1058 (defcustom sql-db2-escape-newlines nil
1059 "Non-nil if newlines should be escaped by a backslash in DB2 SQLi.
1061 When non-nil, Emacs will automatically insert a space and
1062 backslash prior to every newline in multi-line SQL statements as
1063 they are submitted to an interactive DB2 session."
1064 :version "24.3"
1065 :type 'boolean)
1067 ;; Customization for SQLite
1069 (defcustom sql-sqlite-program (or (executable-find "sqlite3")
1070 (executable-find "sqlite")
1071 "sqlite")
1072 "Command to start SQLite.
1074 Starts `sql-interactive-mode' after doing some setup."
1075 :type 'file)
1077 (defcustom sql-sqlite-options nil
1078 "List of additional options for `sql-sqlite-program'."
1079 :type '(repeat string)
1080 :version "20.8")
1082 (defcustom sql-sqlite-login-params '((database :file nil
1083 :must-match confirm))
1084 "List of login parameters needed to connect to SQLite."
1085 :type 'sql-login-params
1086 :version "26.1")
1088 ;; Customization for MariaDB
1090 ;; MariaDB is a drop-in replacement for MySQL, so just make the
1091 ;; MariaDB variables aliases of the MySQL ones.
1093 (defvaralias 'sql-mariadb-program 'sql-mysql-program)
1094 (defvaralias 'sql-mariadb-options 'sql-mysql-options)
1095 (defvaralias 'sql-mariadb-login-params 'sql-mysql-login-params)
1097 ;; Customization for MySQL
1099 (defcustom sql-mysql-program "mysql"
1100 "Command to start mysql by Oracle.
1102 Starts `sql-interactive-mode' after doing some setup."
1103 :type 'file)
1105 (defcustom sql-mysql-options nil
1106 "List of additional options for `sql-mysql-program'.
1107 The following list of options is reported to make things work
1108 on Windows: \"-C\" \"-t\" \"-f\" \"-n\"."
1109 :type '(repeat string)
1110 :version "20.8")
1112 (defcustom sql-mysql-login-params '(user password database server)
1113 "List of login parameters needed to connect to MySQL."
1114 :type 'sql-login-params
1115 :version "24.1")
1117 ;; Customization for Solid
1119 (defcustom sql-solid-program "solsql"
1120 "Command to start SOLID SQL Editor.
1122 Starts `sql-interactive-mode' after doing some setup."
1123 :type 'file)
1125 (defcustom sql-solid-login-params '(user password server)
1126 "List of login parameters needed to connect to Solid."
1127 :type 'sql-login-params
1128 :version "24.1")
1130 ;; Customization for Sybase
1132 (defcustom sql-sybase-program "isql"
1133 "Command to start isql by Sybase.
1135 Starts `sql-interactive-mode' after doing some setup."
1136 :type 'file)
1138 (defcustom sql-sybase-options nil
1139 "List of additional options for `sql-sybase-program'.
1140 Some versions of isql might require the -n option in order to work."
1141 :type '(repeat string)
1142 :version "20.8")
1144 (defcustom sql-sybase-login-params '(server user password database)
1145 "List of login parameters needed to connect to Sybase."
1146 :type 'sql-login-params
1147 :version "24.1")
1149 ;; Customization for Informix
1151 (defcustom sql-informix-program "dbaccess"
1152 "Command to start dbaccess by Informix.
1154 Starts `sql-interactive-mode' after doing some setup."
1155 :type 'file)
1157 (defcustom sql-informix-login-params '(database)
1158 "List of login parameters needed to connect to Informix."
1159 :type 'sql-login-params
1160 :version "24.1")
1162 ;; Customization for Ingres
1164 (defcustom sql-ingres-program "sql"
1165 "Command to start sql by Ingres.
1167 Starts `sql-interactive-mode' after doing some setup."
1168 :type 'file)
1170 (defcustom sql-ingres-login-params '(database)
1171 "List of login parameters needed to connect to Ingres."
1172 :type 'sql-login-params
1173 :version "24.1")
1175 ;; Customization for Microsoft
1177 ;; Microsoft documentation seems to indicate that ISQL and OSQL are
1178 ;; going away and being replaced by SQLCMD. If anyone has experience
1179 ;; using SQLCMD, modified product configuration and feedback on its
1180 ;; use would be greatly appreciated.
1182 (defcustom sql-ms-program "osql"
1183 "Command to start osql by Microsoft.
1185 Starts `sql-interactive-mode' after doing some setup."
1186 :type 'file)
1188 (defcustom sql-ms-options '("-w" "300" "-n")
1189 ;; -w is the linesize
1190 "List of additional options for `sql-ms-program'."
1191 :type '(repeat string)
1192 :version "22.1")
1194 (defcustom sql-ms-login-params '(user password server database)
1195 "List of login parameters needed to connect to Microsoft."
1196 :type 'sql-login-params
1197 :version "24.1")
1199 ;; Customization for Postgres
1201 (defcustom sql-postgres-program "psql"
1202 "Command to start psql by Postgres.
1204 Starts `sql-interactive-mode' after doing some setup."
1205 :type 'file)
1207 (defcustom sql-postgres-options '("-P" "pager=off")
1208 "List of additional options for `sql-postgres-program'.
1209 The default setting includes the -P option which breaks older versions
1210 of the psql client (such as version 6.5.3). The -P option is equivalent
1211 to the --pset option. If you want the psql to prompt you for a user
1212 name, add the string \"-u\" to the list of options. If you want to
1213 provide a user name on the command line (newer versions such as 7.1),
1214 add your name with a \"-U\" prefix (such as \"-Umark\") to the list."
1215 :type '(repeat string)
1216 :version "20.8")
1218 (defcustom sql-postgres-login-params
1219 `((user :default ,(user-login-name))
1220 (database :default ,(user-login-name)
1221 :completion ,(completion-table-dynamic
1222 (lambda (_) (sql-postgres-list-databases)))
1223 :must-match confirm)
1224 server)
1225 "List of login parameters needed to connect to Postgres."
1226 :type 'sql-login-params
1227 :version "26.1")
1229 (defun sql-postgres-list-databases ()
1230 "Return a list of available PostgreSQL databases."
1231 (when (executable-find sql-postgres-program)
1232 (let ((res '()))
1233 (ignore-errors
1234 (dolist (row (process-lines sql-postgres-program
1235 "--list"
1236 "--no-psqlrc"
1237 "--tuples-only"))
1238 (when (string-match "^ \\([^ |]+\\) +|.*" row)
1239 (push (match-string 1 row) res))))
1240 (nreverse res))))
1242 ;; Customization for Interbase
1244 (defcustom sql-interbase-program "isql"
1245 "Command to start isql by Interbase.
1247 Starts `sql-interactive-mode' after doing some setup."
1248 :type 'file)
1250 (defcustom sql-interbase-options nil
1251 "List of additional options for `sql-interbase-program'."
1252 :type '(repeat string)
1253 :version "20.8")
1255 (defcustom sql-interbase-login-params '(user password database)
1256 "List of login parameters needed to connect to Interbase."
1257 :type 'sql-login-params
1258 :version "24.1")
1260 ;; Customization for DB2
1262 (defcustom sql-db2-program "db2"
1263 "Command to start db2 by IBM.
1265 Starts `sql-interactive-mode' after doing some setup."
1266 :type 'file)
1268 (defcustom sql-db2-options nil
1269 "List of additional options for `sql-db2-program'."
1270 :type '(repeat string)
1271 :version "20.8")
1273 (defcustom sql-db2-login-params nil
1274 "List of login parameters needed to connect to DB2."
1275 :type 'sql-login-params
1276 :version "24.1")
1278 ;; Customization for Linter
1280 (defcustom sql-linter-program "inl"
1281 "Command to start inl by RELEX.
1283 Starts `sql-interactive-mode' after doing some setup."
1284 :type 'file)
1286 (defcustom sql-linter-options nil
1287 "List of additional options for `sql-linter-program'."
1288 :type '(repeat string)
1289 :version "21.3")
1291 (defcustom sql-linter-login-params '(user password database server)
1292 "Login parameters to needed to connect to Linter."
1293 :type 'sql-login-params
1294 :version "24.1")
1298 ;;; Variables which do not need customization
1300 (defvar sql-user-history nil
1301 "History of usernames used.")
1303 (defvar sql-database-history nil
1304 "History of databases used.")
1306 (defvar sql-server-history nil
1307 "History of servers used.")
1309 ;; Passwords are not kept in a history.
1311 (defvar sql-product-history nil
1312 "History of products used.")
1314 (defvar sql-connection-history nil
1315 "History of connections used.")
1317 (defvar sql-buffer nil
1318 "Current SQLi buffer.
1320 The global value of `sql-buffer' is the name of the latest SQLi buffer
1321 created. Any SQL buffer created will make a local copy of this value.
1322 See `sql-interactive-mode' for more on multiple sessions. If you want
1323 to change the SQLi buffer a SQL mode sends its SQL strings to, change
1324 the local value of `sql-buffer' using \\[sql-set-sqli-buffer].")
1326 (defvar sql-prompt-regexp nil
1327 "Prompt used to initialize `comint-prompt-regexp'.
1329 You can change `sql-prompt-regexp' on `sql-interactive-mode-hook'.")
1331 (defvar sql-prompt-length 0
1332 "Prompt used to set `left-margin' in `sql-interactive-mode'.
1334 You can change `sql-prompt-length' on `sql-interactive-mode-hook'.")
1336 (defvar sql-prompt-cont-regexp nil
1337 "Prompt pattern of statement continuation prompts.")
1339 (defvar sql-alternate-buffer-name nil
1340 "Buffer-local string used to possibly rename the SQLi buffer.
1342 Used by `sql-rename-buffer'.")
1344 (defun sql-buffer-live-p (buffer &optional product connection)
1345 "Return non-nil if the process associated with buffer is live.
1347 BUFFER can be a buffer object or a buffer name. The buffer must
1348 be a live buffer, have a running process attached to it, be in
1349 `sql-interactive-mode', and, if PRODUCT or CONNECTION are
1350 specified, it's `sql-product' or `sql-connection' must match."
1352 (when buffer
1353 (setq buffer (get-buffer buffer))
1354 (and buffer
1355 (buffer-live-p buffer)
1356 (comint-check-proc buffer)
1357 (with-current-buffer buffer
1358 (and (derived-mode-p 'sql-interactive-mode)
1359 (or (not product)
1360 (eq product sql-product))
1361 (or (not connection)
1362 (and (stringp connection)
1363 (string= connection sql-connection))))))))
1365 (defun sql-is-sqli-buffer-p (buffer)
1366 "Return non-nil if buffer is a SQLi buffer."
1367 (when buffer
1368 (setq buffer (get-buffer buffer))
1369 (and buffer
1370 (buffer-live-p buffer)
1371 (with-current-buffer buffer
1372 (derived-mode-p 'sql-interactive-mode)))))
1374 ;; Keymap for sql-interactive-mode.
1376 (defvar sql-interactive-mode-map
1377 (let ((map (make-sparse-keymap)))
1378 (set-keymap-parent map comint-mode-map)
1379 (if (fboundp 'set-keymap-name)
1380 (set-keymap-name map 'sql-interactive-mode-map)); XEmacs
1381 (define-key map (kbd "C-j") 'sql-accumulate-and-indent)
1382 (define-key map (kbd "C-c C-w") 'sql-copy-column)
1383 (define-key map (kbd "O") 'sql-magic-go)
1384 (define-key map (kbd "o") 'sql-magic-go)
1385 (define-key map (kbd ";") 'sql-magic-semicolon)
1386 (define-key map (kbd "C-c C-l a") 'sql-list-all)
1387 (define-key map (kbd "C-c C-l t") 'sql-list-table)
1388 map)
1389 "Mode map used for `sql-interactive-mode'.
1390 Based on `comint-mode-map'.")
1392 ;; Keymap for sql-mode.
1394 (defvar sql-mode-map
1395 (let ((map (make-sparse-keymap)))
1396 (define-key map (kbd "C-c C-c") 'sql-send-paragraph)
1397 (define-key map (kbd "C-c C-r") 'sql-send-region)
1398 (define-key map (kbd "C-c C-s") 'sql-send-string)
1399 (define-key map (kbd "C-c C-b") 'sql-send-buffer)
1400 (define-key map (kbd "C-c C-n") 'sql-send-line-and-next)
1401 (define-key map (kbd "C-c C-i") 'sql-product-interactive)
1402 (define-key map (kbd "C-c C-z") 'sql-show-sqli-buffer)
1403 (define-key map (kbd "C-c C-l a") 'sql-list-all)
1404 (define-key map (kbd "C-c C-l t") 'sql-list-table)
1405 (define-key map [remap beginning-of-defun] 'sql-beginning-of-statement)
1406 (define-key map [remap end-of-defun] 'sql-end-of-statement)
1407 map)
1408 "Mode map used for `sql-mode'.")
1410 ;; easy menu for sql-mode.
1412 (easy-menu-define
1413 sql-mode-menu sql-mode-map
1414 "Menu for `sql-mode'."
1415 `("SQL"
1416 ["Send Paragraph" sql-send-paragraph (sql-buffer-live-p sql-buffer)]
1417 ["Send Region" sql-send-region (and mark-active
1418 (sql-buffer-live-p sql-buffer))]
1419 ["Send Buffer" sql-send-buffer (sql-buffer-live-p sql-buffer)]
1420 ["Send String" sql-send-string (sql-buffer-live-p sql-buffer)]
1421 "--"
1422 ["List all objects" sql-list-all (and (sql-buffer-live-p sql-buffer)
1423 (sql-get-product-feature sql-product :list-all))]
1424 ["List table details" sql-list-table (and (sql-buffer-live-p sql-buffer)
1425 (sql-get-product-feature sql-product :list-table))]
1426 "--"
1427 ["Start SQLi session" sql-product-interactive
1428 :visible (not sql-connection-alist)
1429 :enable (sql-get-product-feature sql-product :sqli-comint-func)]
1430 ("Start..."
1431 :visible sql-connection-alist
1432 :filter sql-connection-menu-filter
1433 "--"
1434 ["New SQLi Session" sql-product-interactive (sql-get-product-feature sql-product :sqli-comint-func)])
1435 ["--"
1436 :visible sql-connection-alist]
1437 ["Show SQLi buffer" sql-show-sqli-buffer t]
1438 ["Set SQLi buffer" sql-set-sqli-buffer t]
1439 ["Pop to SQLi buffer after send"
1440 sql-toggle-pop-to-buffer-after-send-region
1441 :style toggle
1442 :selected sql-pop-to-buffer-after-send-region]
1443 ["--" nil nil]
1444 ("Product"
1445 ,@(mapcar (lambda (prod-info)
1446 (let* ((prod (pop prod-info))
1447 (name (or (plist-get prod-info :name)
1448 (capitalize (symbol-name prod))))
1449 (cmd (intern (format "sql-highlight-%s-keywords" prod))))
1450 (fset cmd `(lambda () ,(format "Highlight %s SQL keywords." name)
1451 (interactive)
1452 (sql-set-product ',prod)))
1453 (vector name cmd
1454 :style 'radio
1455 :selected `(eq sql-product ',prod))))
1456 sql-product-alist))))
1458 ;; easy menu for sql-interactive-mode.
1460 (easy-menu-define
1461 sql-interactive-mode-menu sql-interactive-mode-map
1462 "Menu for `sql-interactive-mode'."
1463 '("SQL"
1464 ["Rename Buffer" sql-rename-buffer t]
1465 ["Save Connection" sql-save-connection (not sql-connection)]
1466 "--"
1467 ["List all objects" sql-list-all (sql-get-product-feature sql-product :list-all)]
1468 ["List table details" sql-list-table (sql-get-product-feature sql-product :list-table)]))
1470 ;; Abbreviations -- if you want more of them, define them in your init
1471 ;; file. Abbrevs have to be enabled in your init file, too.
1473 (define-abbrev-table 'sql-mode-abbrev-table
1474 '(("ins" "insert" nil nil t)
1475 ("upd" "update" nil nil t)
1476 ("del" "delete" nil nil t)
1477 ("sel" "select" nil nil t)
1478 ("proc" "procedure" nil nil t)
1479 ("func" "function" nil nil t)
1480 ("cr" "create" nil nil t))
1481 "Abbrev table used in `sql-mode' and `sql-interactive-mode'.")
1483 ;; Syntax Table
1485 (defvar sql-mode-syntax-table
1486 (let ((table (make-syntax-table)))
1487 ;; C-style comments /**/ (see elisp manual "Syntax Flags"))
1488 (modify-syntax-entry ?/ ". 14" table)
1489 (modify-syntax-entry ?* ". 23" table)
1490 ;; double-dash starts comments
1491 (modify-syntax-entry ?- ". 12b" table)
1492 ;; newline and formfeed end comments
1493 (modify-syntax-entry ?\n "> b" table)
1494 (modify-syntax-entry ?\f "> b" table)
1495 ;; single quotes (') delimit strings
1496 (modify-syntax-entry ?' "\"" table)
1497 ;; double quotes (") don't delimit strings
1498 (modify-syntax-entry ?\" "." table)
1499 ;; Make these all punctuation
1500 (mapc (lambda (c) (modify-syntax-entry c "." table))
1501 (string-to-list "!#$%&+,.:;<=>?@\\|"))
1502 table)
1503 "Syntax table used in `sql-mode' and `sql-interactive-mode'.")
1505 ;; Font lock support
1507 (defvar sql-mode-font-lock-object-name
1508 (eval-when-compile
1509 (list (concat "^\\s-*\\(?:create\\|drop\\|alter\\)\\s-+" ;; lead off with CREATE, DROP or ALTER
1510 "\\(?:\\w+\\s-+\\)*" ;; optional intervening keywords
1511 "\\(?:table\\|view\\|\\(?:package\\|type\\)\\(?:\\s-+body\\)?\\|proc\\(?:edure\\)?"
1512 "\\|function\\|trigger\\|sequence\\|rule\\|default\\)\\s-+"
1513 "\\(?:if\\s-+not\\s-+exists\\s-+\\)?" ;; IF NOT EXISTS
1514 "\\(\\w+\\(?:\\s-*[.]\\s-*\\w+\\)*\\)")
1515 1 'font-lock-function-name-face))
1517 "Pattern to match the names of top-level objects.
1519 The pattern matches the name in a CREATE, DROP or ALTER
1520 statement. The format of variable should be a valid
1521 `font-lock-keywords' entry.")
1523 ;; While there are international and American standards for SQL, they
1524 ;; are not followed closely, and most vendors offer significant
1525 ;; capabilities beyond those defined in the standard specifications.
1527 ;; SQL mode provides support for highlighting based on the product. In
1528 ;; addition to highlighting the product keywords, any ANSI keywords not
1529 ;; used by the product are also highlighted. This will help identify
1530 ;; keywords that could be restricted in future versions of the product
1531 ;; or might be a problem if ported to another product.
1533 ;; To reduce the complexity and size of the regular expressions
1534 ;; generated to match keywords, ANSI keywords are filtered out of
1535 ;; product keywords if they are equivalent. To do this, we define a
1536 ;; function `sql-font-lock-keywords-builder' that removes any keywords
1537 ;; that are matched by the ANSI patterns and results in the same face
1538 ;; being applied. For this to work properly, we must play some games
1539 ;; with the execution and compile time behavior. This code is a
1540 ;; little tricky but works properly.
1542 ;; When defining the keywords for individual products you should
1543 ;; include all of the keywords that you want matched. The filtering
1544 ;; against the ANSI keywords will be automatic if you use the
1545 ;; `sql-font-lock-keywords-builder' function and follow the
1546 ;; implementation pattern used for the other products in this file.
1548 (eval-when-compile
1549 (defvar sql-mode-ansi-font-lock-keywords)
1550 (setq sql-mode-ansi-font-lock-keywords nil))
1552 (eval-and-compile
1553 (defun sql-font-lock-keywords-builder (face boundaries &rest keywords)
1554 "Generation of regexp matching any one of KEYWORDS."
1556 (let ((bdy (or boundaries '("\\b" . "\\b")))
1557 kwd)
1559 ;; Remove keywords that are defined in ANSI
1560 (setq kwd keywords)
1561 ;; (dolist (k keywords)
1562 ;; (catch 'next
1563 ;; (dolist (a sql-mode-ansi-font-lock-keywords)
1564 ;; (when (and (eq face (cdr a))
1565 ;; (eq (string-match (car a) k 0) 0)
1566 ;; (eq (match-end 0) (length k)))
1567 ;; (setq kwd (delq k kwd))
1568 ;; (throw 'next nil)))))
1570 ;; Create a properly formed font-lock-keywords item
1571 (cons (concat (car bdy)
1572 (regexp-opt kwd t)
1573 (cdr bdy))
1574 face)))
1576 (defun sql-regexp-abbrev (keyword)
1577 (let ((brk (string-match "[~]" keyword))
1578 (len (length keyword))
1579 (sep "\\(?:")
1580 re i)
1581 (if (not brk)
1582 keyword
1583 (setq re (substring keyword 0 brk)
1584 i (+ 2 brk)
1585 brk (1+ brk))
1586 (while (<= i len)
1587 (setq re (concat re sep (substring keyword brk i))
1588 sep "\\|"
1589 i (1+ i)))
1590 (concat re "\\)?"))))
1592 (defun sql-regexp-abbrev-list (&rest keyw-list)
1593 (let ((re nil)
1594 (sep "\\<\\(?:"))
1595 (while keyw-list
1596 (setq re (concat re sep (sql-regexp-abbrev (car keyw-list)))
1597 sep "\\|"
1598 keyw-list (cdr keyw-list)))
1599 (concat re "\\)\\>"))))
1601 (eval-when-compile
1602 (setq sql-mode-ansi-font-lock-keywords
1603 (list
1604 ;; ANSI Non Reserved keywords
1605 (sql-font-lock-keywords-builder 'font-lock-keyword-face nil
1606 "ada" "asensitive" "assignment" "asymmetric" "atomic" "between"
1607 "bitvar" "called" "catalog_name" "chain" "character_set_catalog"
1608 "character_set_name" "character_set_schema" "checked" "class_origin"
1609 "cobol" "collation_catalog" "collation_name" "collation_schema"
1610 "column_name" "command_function" "command_function_code" "committed"
1611 "condition_number" "connection_name" "constraint_catalog"
1612 "constraint_name" "constraint_schema" "contains" "cursor_name"
1613 "datetime_interval_code" "datetime_interval_precision" "defined"
1614 "definer" "dispatch" "dynamic_function" "dynamic_function_code"
1615 "existing" "exists" "final" "fortran" "generated" "granted"
1616 "hierarchy" "hold" "implementation" "infix" "insensitive" "instance"
1617 "instantiable" "invoker" "key_member" "key_type" "length" "m"
1618 "message_length" "message_octet_length" "message_text" "method" "more"
1619 "mumps" "name" "nullable" "number" "options" "overlaps" "overriding"
1620 "parameter_mode" "parameter_name" "parameter_ordinal_position"
1621 "parameter_specific_catalog" "parameter_specific_name"
1622 "parameter_specific_schema" "pascal" "pli" "position" "repeatable"
1623 "returned_length" "returned_octet_length" "returned_sqlstate"
1624 "routine_catalog" "routine_name" "routine_schema" "row_count" "scale"
1625 "schema_name" "security" "self" "sensitive" "serializable"
1626 "server_name" "similar" "simple" "source" "specific_name" "style"
1627 "subclass_origin" "sublist" "symmetric" "system" "table_name"
1628 "transaction_active" "transactions_committed"
1629 "transactions_rolled_back" "transform" "transforms" "trigger_catalog"
1630 "trigger_name" "trigger_schema" "type" "uncommitted" "unnamed"
1631 "user_defined_type_catalog" "user_defined_type_name"
1632 "user_defined_type_schema"
1635 ;; ANSI Reserved keywords
1636 (sql-font-lock-keywords-builder 'font-lock-keyword-face nil
1637 "absolute" "action" "add" "admin" "after" "aggregate" "alias" "all"
1638 "allocate" "alter" "and" "any" "are" "as" "asc" "assertion" "at"
1639 "authorization" "before" "begin" "both" "breadth" "by" "call"
1640 "cascade" "cascaded" "case" "catalog" "check" "class" "close"
1641 "collate" "collation" "column" "commit" "completion" "connect"
1642 "connection" "constraint" "constraints" "constructor" "continue"
1643 "corresponding" "create" "cross" "cube" "current" "cursor" "cycle"
1644 "data" "day" "deallocate" "declare" "default" "deferrable" "deferred"
1645 "delete" "depth" "deref" "desc" "describe" "descriptor" "destroy"
1646 "destructor" "deterministic" "diagnostics" "dictionary" "disconnect"
1647 "distinct" "domain" "drop" "dynamic" "each" "else" "end" "equals"
1648 "escape" "every" "except" "exception" "exec" "execute" "external"
1649 "false" "fetch" "first" "for" "foreign" "found" "free" "from" "full"
1650 "function" "general" "get" "global" "go" "goto" "grant" "group"
1651 "grouping" "having" "host" "hour" "identity" "ignore" "immediate" "in"
1652 "indicator" "initialize" "initially" "inner" "inout" "input" "insert"
1653 "intersect" "into" "is" "isolation" "iterate" "join" "key" "language"
1654 "last" "lateral" "leading" "left" "less" "level" "like" "limit"
1655 "local" "locator" "map" "match" "minute" "modifies" "modify" "module"
1656 "month" "names" "natural" "new" "next" "no" "none" "not" "null" "of"
1657 "off" "old" "on" "only" "open" "operation" "option" "or" "order"
1658 "ordinality" "out" "outer" "output" "pad" "parameter" "parameters"
1659 "partial" "path" "postfix" "prefix" "preorder" "prepare" "preserve"
1660 "primary" "prior" "privileges" "procedure" "public" "read" "reads"
1661 "recursive" "references" "referencing" "relative" "restrict" "result"
1662 "return" "returns" "revoke" "right" "role" "rollback" "rollup"
1663 "routine" "rows" "savepoint" "schema" "scroll" "search" "second"
1664 "section" "select" "sequence" "session" "set" "sets" "size" "some"
1665 "space" "specific" "specifictype" "sql" "sqlexception" "sqlstate"
1666 "sqlwarning" "start" "state" "statement" "static" "structure" "table"
1667 "temporary" "terminate" "than" "then" "timezone_hour"
1668 "timezone_minute" "to" "trailing" "transaction" "translation"
1669 "trigger" "true" "under" "union" "unique" "unknown" "unnest" "update"
1670 "usage" "using" "value" "values" "variable" "view" "when" "whenever"
1671 "where" "with" "without" "work" "write" "year"
1674 ;; ANSI Functions
1675 (sql-font-lock-keywords-builder 'font-lock-builtin-face nil
1676 "abs" "avg" "bit_length" "cardinality" "cast" "char_length"
1677 "character_length" "coalesce" "convert" "count" "current_date"
1678 "current_path" "current_role" "current_time" "current_timestamp"
1679 "current_user" "extract" "localtime" "localtimestamp" "lower" "max"
1680 "min" "mod" "nullif" "octet_length" "overlay" "placing" "session_user"
1681 "substring" "sum" "system_user" "translate" "treat" "trim" "upper"
1682 "user"
1685 ;; ANSI Data Types
1686 (sql-font-lock-keywords-builder 'font-lock-type-face nil
1687 "array" "binary" "bit" "blob" "boolean" "char" "character" "clob"
1688 "date" "dec" "decimal" "double" "float" "int" "integer" "interval"
1689 "large" "national" "nchar" "nclob" "numeric" "object" "precision"
1690 "real" "ref" "row" "scope" "smallint" "time" "timestamp" "varchar"
1691 "varying" "zone"
1692 ))))
1694 (defvar sql-mode-ansi-font-lock-keywords
1695 (eval-when-compile sql-mode-ansi-font-lock-keywords)
1696 "ANSI SQL keywords used by font-lock.
1698 This variable is used by `sql-mode' and `sql-interactive-mode'. The
1699 regular expressions are created during compilation by calling the
1700 function `regexp-opt'. Therefore, take a look at the source before
1701 you define your own `sql-mode-ansi-font-lock-keywords'. You may want
1702 to add functions and PL/SQL keywords.")
1704 (defun sql--oracle-show-reserved-words ()
1705 ;; This function is for use by the maintainer of SQL.EL only.
1706 (if (or (and (not (derived-mode-p 'sql-mode))
1707 (not (derived-mode-p 'sql-interactive-mode)))
1708 (not sql-buffer)
1709 (not (eq sql-product 'oracle)))
1710 (user-error "Not an Oracle buffer")
1712 (let ((b "*RESERVED WORDS*"))
1713 (sql-execute sql-buffer b
1714 (concat "SELECT "
1715 " keyword "
1716 ", reserved AS \"Res\" "
1717 ", res_type AS \"Type\" "
1718 ", res_attr AS \"Attr\" "
1719 ", res_semi AS \"Semi\" "
1720 ", duplicate AS \"Dup\" "
1721 "FROM V$RESERVED_WORDS "
1722 "WHERE length > 1 "
1723 "AND SUBSTR(keyword, 1, 1) BETWEEN 'A' AND 'Z' "
1724 "ORDER BY 2 DESC, 3 DESC, 4 DESC, 5 DESC, 6 DESC, 1;")
1725 nil nil)
1726 (with-current-buffer b
1727 (setq-local sql-product 'oracle)
1728 (sql-product-font-lock t nil)
1729 (font-lock-mode +1)))))
1731 (defvar sql-mode-oracle-font-lock-keywords
1732 (eval-when-compile
1733 (list
1734 ;; Oracle SQL*Plus Commands
1735 ;; Only recognized in they start in column 1 and the
1736 ;; abbreviation is followed by a space or the end of line.
1737 (list (concat "^" (sql-regexp-abbrev "rem~ark") "\\(?:\\s-.*\\)?$")
1738 0 'font-lock-comment-face t)
1740 (list
1741 (concat
1742 "^\\(?:"
1743 (sql-regexp-abbrev-list
1744 "[@]\\{1,2\\}" "acc~ept" "a~ppend" "archive" "attribute"
1745 "bre~ak" "bti~tle" "c~hange" "cl~ear" "col~umn" "conn~ect"
1746 "copy" "def~ine" "del" "desc~ribe" "disc~onnect" "ed~it"
1747 "exec~ute" "exit" "get" "help" "ho~st" "[$]" "i~nput" "l~ist"
1748 "passw~ord" "pau~se" "pri~nt" "pro~mpt" "quit" "recover"
1749 "repf~ooter" "reph~eader" "r~un" "sav~e" "sho~w" "shutdown"
1750 "spo~ol" "sta~rt" "startup" "store" "tim~ing" "tti~tle"
1751 "undef~ine" "var~iable" "whenever")
1752 "\\|"
1753 (concat "\\(?:"
1754 (sql-regexp-abbrev "comp~ute")
1755 "\\s-+"
1756 (sql-regexp-abbrev-list
1757 "avg" "cou~nt" "min~imum" "max~imum" "num~ber" "sum"
1758 "std" "var~iance")
1759 "\\)")
1760 "\\|"
1761 (concat "\\(?:set\\s-+"
1762 (sql-regexp-abbrev-list
1763 "appi~nfo" "array~size" "auto~commit" "autop~rint"
1764 "autorecovery" "autot~race" "blo~ckterminator"
1765 "cmds~ep" "colsep" "com~patibility" "con~cat"
1766 "copyc~ommit" "copytypecheck" "def~ine" "describe"
1767 "echo" "editf~ile" "emb~edded" "esc~ape" "feed~back"
1768 "flagger" "flu~sh" "hea~ding" "heads~ep" "instance"
1769 "lin~esize" "lobof~fset" "long" "longc~hunksize"
1770 "mark~up" "newp~age" "null" "numf~ormat" "num~width"
1771 "pages~ize" "pau~se" "recsep" "recsepchar"
1772 "scan" "serverout~put" "shift~inout" "show~mode"
1773 "sqlbl~anklines" "sqlc~ase" "sqlco~ntinue"
1774 "sqln~umber" "sqlpluscompat~ibility" "sqlpre~fix"
1775 "sqlp~rompt" "sqlt~erminator" "suf~fix" "tab"
1776 "term~out" "ti~me" "timi~ng" "trim~out" "trims~pool"
1777 "und~erline" "ver~ify" "wra~p")
1778 "\\)")
1780 "\\)\\(?:\\s-.*\\)?\\(?:[-]\n.*\\)*$")
1781 0 'font-lock-doc-face t)
1782 '("&?&\\(?:\\sw\\|\\s_\\)+[.]?" 0 font-lock-preprocessor-face t)
1784 ;; Oracle PL/SQL Attributes (Declare these first to match %TYPE correctly)
1785 (sql-font-lock-keywords-builder 'font-lock-builtin-face '("%" . "\\b")
1786 "bulk_exceptions" "bulk_rowcount" "found" "isopen" "notfound"
1787 "rowcount" "rowtype" "type"
1789 ;; Oracle Functions
1790 (sql-font-lock-keywords-builder 'font-lock-builtin-face nil
1791 "abs" "acos" "add_months" "appendchildxml" "ascii" "asciistr" "asin"
1792 "atan" "atan2" "avg" "bfilename" "bin_to_num" "bitand" "cardinality"
1793 "cast" "ceil" "chartorowid" "chr" "cluster_id" "cluster_probability"
1794 "cluster_set" "coalesce" "collect" "compose" "concat" "convert" "corr"
1795 "connect_by_root" "connect_by_iscycle" "connect_by_isleaf"
1796 "corr_k" "corr_s" "cos" "cosh" "count" "covar_pop" "covar_samp"
1797 "cube_table" "cume_dist" "current_date" "current_timestamp" "cv"
1798 "dataobj_to_partition" "dbtimezone" "decode" "decompose" "deletexml"
1799 "dense_rank" "depth" "deref" "dump" "empty_blob" "empty_clob"
1800 "existsnode" "exp" "extract" "extractvalue" "feature_id" "feature_set"
1801 "feature_value" "first" "first_value" "floor" "from_tz" "greatest"
1802 "grouping" "grouping_id" "group_id" "hextoraw" "initcap"
1803 "insertchildxml" "insertchildxmlafter" "insertchildxmlbefore"
1804 "insertxmlafter" "insertxmlbefore" "instr" "instr2" "instr4" "instrb"
1805 "instrc" "iteration_number" "lag" "last" "last_day" "last_value"
1806 "lead" "least" "length" "length2" "length4" "lengthb" "lengthc"
1807 "listagg" "ln" "lnnvl" "localtimestamp" "log" "lower" "lpad" "ltrim"
1808 "make_ref" "max" "median" "min" "mod" "months_between" "nanvl" "nchr"
1809 "new_time" "next_day" "nlssort" "nls_charset_decl_len"
1810 "nls_charset_id" "nls_charset_name" "nls_initcap" "nls_lower"
1811 "nls_upper" "nth_value" "ntile" "nullif" "numtodsinterval"
1812 "numtoyminterval" "nvl" "nvl2" "ora_dst_affected" "ora_dst_convert"
1813 "ora_dst_error" "ora_hash" "path" "percentile_cont" "percentile_disc"
1814 "percent_rank" "power" "powermultiset" "powermultiset_by_cardinality"
1815 "prediction" "prediction_bounds" "prediction_cost"
1816 "prediction_details" "prediction_probability" "prediction_set"
1817 "presentnnv" "presentv" "previous" "rank" "ratio_to_report" "rawtohex"
1818 "rawtonhex" "ref" "reftohex" "regexp_count" "regexp_instr" "regexp_like"
1819 "regexp_replace" "regexp_substr" "regr_avgx" "regr_avgy" "regr_count"
1820 "regr_intercept" "regr_r2" "regr_slope" "regr_sxx" "regr_sxy"
1821 "regr_syy" "remainder" "replace" "round" "rowidtochar" "rowidtonchar"
1822 "row_number" "rpad" "rtrim" "scn_to_timestamp" "sessiontimezone" "set"
1823 "sign" "sin" "sinh" "soundex" "sqrt" "stats_binomial_test"
1824 "stats_crosstab" "stats_f_test" "stats_ks_test" "stats_mode"
1825 "stats_mw_test" "stats_one_way_anova" "stats_t_test_indep"
1826 "stats_t_test_indepu" "stats_t_test_one" "stats_t_test_paired"
1827 "stats_wsr_test" "stddev" "stddev_pop" "stddev_samp" "substr"
1828 "substr2" "substr4" "substrb" "substrc" "sum" "sysdate" "systimestamp"
1829 "sys_connect_by_path" "sys_context" "sys_dburigen" "sys_extract_utc"
1830 "sys_guid" "sys_typeid" "sys_xmlagg" "sys_xmlgen" "tan" "tanh"
1831 "timestamp_to_scn" "to_binary_double" "to_binary_float" "to_blob"
1832 "to_char" "to_clob" "to_date" "to_dsinterval" "to_lob" "to_multi_byte"
1833 "to_nchar" "to_nclob" "to_number" "to_single_byte" "to_timestamp"
1834 "to_timestamp_tz" "to_yminterval" "translate" "treat" "trim" "trunc"
1835 "tz_offset" "uid" "unistr" "updatexml" "upper" "user" "userenv"
1836 "value" "variance" "var_pop" "var_samp" "vsize" "width_bucket"
1837 "xmlagg" "xmlcast" "xmlcdata" "xmlcolattval" "xmlcomment" "xmlconcat"
1838 "xmldiff" "xmlelement" "xmlexists" "xmlforest" "xmlisvalid" "xmlparse"
1839 "xmlpatch" "xmlpi" "xmlquery" "xmlroot" "xmlsequence" "xmlserialize"
1840 "xmltable" "xmltransform"
1843 ;; See the table V$RESERVED_WORDS
1844 ;; Oracle Keywords
1845 (sql-font-lock-keywords-builder 'font-lock-keyword-face nil
1846 "abort" "access" "accessed" "account" "activate" "add" "admin"
1847 "advise" "after" "agent" "aggregate" "all" "allocate" "allow" "alter"
1848 "always" "analyze" "ancillary" "and" "any" "apply" "archive"
1849 "archivelog" "array" "as" "asc" "associate" "at" "attribute"
1850 "attributes" "audit" "authenticated" "authid" "authorization" "auto"
1851 "autoallocate" "automatic" "availability" "backup" "before" "begin"
1852 "behalf" "between" "binding" "bitmap" "block" "blocksize" "body"
1853 "both" "buffer_pool" "build" "by" "cache" "call" "cancel"
1854 "cascade" "case" "category" "certificate" "chained" "change" "check"
1855 "checkpoint" "child" "chunk" "class" "clear" "clone" "close" "cluster"
1856 "column" "column_value" "columns" "comment" "commit" "committed"
1857 "compatibility" "compile" "complete" "composite_limit" "compress"
1858 "compute" "connect" "connect_time" "consider" "consistent"
1859 "constraint" "constraints" "constructor" "contents" "context"
1860 "continue" "controlfile" "corruption" "cost" "cpu_per_call"
1861 "cpu_per_session" "create" "cross" "cube" "current" "currval" "cycle"
1862 "dangling" "data" "database" "datafile" "datafiles" "day" "ddl"
1863 "deallocate" "debug" "default" "deferrable" "deferred" "definer"
1864 "delay" "delete" "demand" "desc" "determines" "deterministic"
1865 "dictionary" "dimension" "directory" "disable" "disassociate"
1866 "disconnect" "distinct" "distinguished" "distributed" "dml" "drop"
1867 "each" "element" "else" "enable" "end" "equals_path" "escape"
1868 "estimate" "except" "exceptions" "exchange" "excluding" "exists"
1869 "expire" "explain" "extent" "external" "externally"
1870 "failed_login_attempts" "fast" "file" "final" "finish" "flush" "for"
1871 "force" "foreign" "freelist" "freelists" "freepools" "fresh" "from"
1872 "full" "function" "functions" "generated" "global" "global_name"
1873 "globally" "grant" "group" "grouping" "groups" "guard" "hash"
1874 "hashkeys" "having" "heap" "hierarchy" "id" "identified" "identifier"
1875 "idle_time" "immediate" "in" "including" "increment" "index" "indexed"
1876 "indexes" "indextype" "indextypes" "indicator" "initial" "initialized"
1877 "initially" "initrans" "inner" "insert" "instance" "instantiable"
1878 "instead" "intersect" "into" "invalidate" "is" "isolation" "java"
1879 "join" "keep" "key" "kill" "language" "left" "less" "level"
1880 "levels" "library" "like" "like2" "like4" "likec" "limit" "link"
1881 "list" "lob" "local" "location" "locator" "lock" "log" "logfile"
1882 "logging" "logical" "logical_reads_per_call"
1883 "logical_reads_per_session" "managed" "management" "manual" "map"
1884 "mapping" "master" "matched" "materialized" "maxdatafiles"
1885 "maxextents" "maximize" "maxinstances" "maxlogfiles" "maxloghistory"
1886 "maxlogmembers" "maxsize" "maxtrans" "maxvalue" "member" "memory"
1887 "merge" "migrate" "minextents" "minimize" "minimum" "minus" "minvalue"
1888 "mode" "modify" "monitoring" "month" "mount" "move" "movement" "name"
1889 "named" "natural" "nested" "never" "new" "next" "nextval" "no"
1890 "noarchivelog" "noaudit" "nocache" "nocompress" "nocopy" "nocycle"
1891 "nodelay" "noforce" "nologging" "nomapping" "nomaxvalue" "nominimize"
1892 "nominvalue" "nomonitoring" "none" "noorder" "noparallel" "norely"
1893 "noresetlogs" "noreverse" "normal" "norowdependencies" "nosort"
1894 "noswitch" "not" "nothing" "notimeout" "novalidate" "nowait" "null"
1895 "nulls" "object" "of" "off" "offline" "oidindex" "old" "on" "online"
1896 "only" "open" "operator" "optimal" "option" "or" "order"
1897 "organization" "out" "outer" "outline" "over" "overflow" "overriding"
1898 "package" "packages" "parallel" "parallel_enable" "parameters"
1899 "parent" "partition" "partitions" "password" "password_grace_time"
1900 "password_life_time" "password_lock_time" "password_reuse_max"
1901 "password_reuse_time" "password_verify_function" "pctfree"
1902 "pctincrease" "pctthreshold" "pctused" "pctversion" "percent"
1903 "performance" "permanent" "pfile" "physical" "pipelined" "pivot" "plan"
1904 "post_transaction" "pragma" "prebuilt" "preserve" "primary" "private"
1905 "private_sga" "privileges" "procedure" "profile" "protection" "public"
1906 "purge" "query" "quiesce" "quota" "range" "read" "reads" "rebuild"
1907 "records_per_block" "recover" "recovery" "recycle" "reduced" "ref"
1908 "references" "referencing" "refresh" "register" "reject" "relational"
1909 "rely" "rename" "reset" "resetlogs" "resize" "resolve" "resolver"
1910 "resource" "restrict" "restrict_references" "restricted" "result"
1911 "resumable" "resume" "retention" "return" "returning" "reuse"
1912 "reverse" "revoke" "rewrite" "right" "rnds" "rnps" "role" "roles"
1913 "rollback" "rollup" "row" "rowdependencies" "rownum" "rows" "sample"
1914 "savepoint" "scan" "schema" "scn" "scope" "segment" "select"
1915 "selectivity" "self" "sequence" "serializable" "session"
1916 "sessions_per_user" "set" "sets" "settings" "shared" "shared_pool"
1917 "shrink" "shutdown" "siblings" "sid" "single" "size" "skip" "some"
1918 "sort" "source" "space" "specification" "spfile" "split" "standby"
1919 "start" "statement_id" "static" "statistics" "stop" "storage" "store"
1920 "structure" "subpartition" "subpartitions" "substitutable"
1921 "successful" "supplemental" "suspend" "switch" "switchover" "synonym"
1922 "sys" "system" "table" "tables" "tablespace" "tempfile" "template"
1923 "temporary" "test" "than" "then" "thread" "through" "time_zone"
1924 "timeout" "to" "trace" "transaction" "trigger" "triggers" "truncate"
1925 "trust" "type" "types" "unarchived" "under" "under_path" "undo"
1926 "uniform" "union" "unique" "unlimited" "unlock" "unpivot" "unquiesce"
1927 "unrecoverable" "until" "unusable" "unused" "update" "upgrade" "usage"
1928 "use" "using" "validate" "validation" "value" "values" "variable"
1929 "varray" "version" "view" "wait" "when" "whenever" "where" "with"
1930 "without" "wnds" "wnps" "work" "write" "xmldata" "xmlschema" "xmltype"
1933 ;; Oracle Data Types
1934 (sql-font-lock-keywords-builder 'font-lock-type-face nil
1935 "bfile" "binary_double" "binary_float" "blob" "byte" "char" "charbyte"
1936 "clob" "date" "day" "float" "interval" "local" "long" "longraw"
1937 "minute" "month" "nchar" "nclob" "number" "nvarchar2" "raw" "rowid" "second"
1938 "time" "timestamp" "urowid" "varchar2" "with" "year" "zone"
1941 ;; Oracle PL/SQL Functions
1942 (sql-font-lock-keywords-builder 'font-lock-builtin-face nil
1943 "delete" "trim" "extend" "exists" "first" "last" "count" "limit"
1944 "prior" "next" "sqlcode" "sqlerrm"
1947 ;; Oracle PL/SQL Reserved words
1948 (sql-font-lock-keywords-builder 'font-lock-keyword-face nil
1949 "all" "alter" "and" "any" "as" "asc" "at" "begin" "between" "by"
1950 "case" "check" "clusters" "cluster" "colauth" "columns" "compress"
1951 "connect" "crash" "create" "cursor" "declare" "default" "desc"
1952 "distinct" "drop" "else" "end" "exception" "exclusive" "fetch" "for"
1953 "from" "function" "goto" "grant" "group" "having" "identified" "if"
1954 "in" "index" "indexes" "insert" "intersect" "into" "is" "like" "lock"
1955 "minus" "mode" "nocompress" "not" "nowait" "null" "of" "on" "option"
1956 "or" "order" "overlaps" "procedure" "public" "resource" "revoke"
1957 "select" "share" "size" "sql" "start" "subtype" "tabauth" "table"
1958 "then" "to" "type" "union" "unique" "update" "values" "view" "views"
1959 "when" "where" "with"
1961 "true" "false"
1962 "raise_application_error"
1965 ;; Oracle PL/SQL Keywords
1966 (sql-font-lock-keywords-builder 'font-lock-keyword-face nil
1967 "a" "add" "agent" "aggregate" "array" "attribute" "authid" "avg"
1968 "bfile_base" "binary" "blob_base" "block" "body" "both" "bound" "bulk"
1969 "byte" "c" "call" "calling" "cascade" "char" "char_base" "character"
1970 "charset" "charsetform" "charsetid" "clob_base" "close" "collect"
1971 "comment" "commit" "committed" "compiled" "constant" "constructor"
1972 "context" "continue" "convert" "count" "current" "customdatum"
1973 "dangling" "data" "date" "date_base" "day" "define" "delete"
1974 "deterministic" "double" "duration" "element" "elsif" "empty" "escape"
1975 "except" "exceptions" "execute" "exists" "exit" "external" "final"
1976 "fixed" "float" "forall" "force" "general" "hash" "heap" "hidden"
1977 "hour" "immediate" "including" "indicator" "indices" "infinite"
1978 "instantiable" "int" "interface" "interval" "invalidate" "isolation"
1979 "java" "language" "large" "leading" "length" "level" "library" "like2"
1980 "like4" "likec" "limit" "limited" "local" "long" "loop" "map" "max"
1981 "maxlen" "member" "merge" "min" "minute" "mod" "modify" "month"
1982 "multiset" "name" "nan" "national" "native" "nchar" "new" "nocopy"
1983 "number_base" "object" "ocicoll" "ocidate" "ocidatetime" "ociduration"
1984 "ociinterval" "ociloblocator" "ocinumber" "ociraw" "ociref"
1985 "ocirefcursor" "ocirowid" "ocistring" "ocitype" "old" "only" "opaque"
1986 "open" "operator" "oracle" "oradata" "organization" "orlany" "orlvary"
1987 "others" "out" "overriding" "package" "parallel_enable" "parameter"
1988 "parameters" "parent" "partition" "pascal" "pipe" "pipelined" "pragma"
1989 "precision" "prior" "private" "raise" "range" "raw" "read" "record"
1990 "ref" "reference" "relies_on" "rem" "remainder" "rename" "result"
1991 "result_cache" "return" "returning" "reverse" "rollback" "row"
1992 "sample" "save" "savepoint" "sb1" "sb2" "sb4" "second" "segment"
1993 "self" "separate" "sequence" "serializable" "set" "short" "size_t"
1994 "some" "sparse" "sqlcode" "sqldata" "sqlname" "sqlstate" "standard"
1995 "static" "stddev" "stored" "string" "struct" "style" "submultiset"
1996 "subpartition" "substitutable" "sum" "synonym" "tdo" "the" "time"
1997 "timestamp" "timezone_abbr" "timezone_hour" "timezone_minute"
1998 "timezone_region" "trailing" "transaction" "transactional" "trusted"
1999 "ub1" "ub2" "ub4" "under" "unsigned" "untrusted" "use" "using"
2000 "valist" "value" "variable" "variance" "varray" "varying" "void"
2001 "while" "work" "wrapped" "write" "year" "zone"
2002 ;; Pragma
2003 "autonomous_transaction" "exception_init" "inline"
2004 "restrict_references" "serially_reusable"
2007 ;; Oracle PL/SQL Data Types
2008 (sql-font-lock-keywords-builder 'font-lock-type-face nil
2009 "\"BINARY LARGE OBJECT\"" "\"CHAR LARGE OBJECT\"" "\"CHAR VARYING\""
2010 "\"CHARACTER LARGE OBJECT\"" "\"CHARACTER VARYING\""
2011 "\"DOUBLE PRECISION\"" "\"INTERVAL DAY TO SECOND\""
2012 "\"INTERVAL YEAR TO MONTH\"" "\"LONG RAW\"" "\"NATIONAL CHAR\""
2013 "\"NATIONAL CHARACTER LARGE OBJECT\"" "\"NATIONAL CHARACTER\""
2014 "\"NCHAR LARGE OBJECT\"" "\"NCHAR\"" "\"NCLOB\"" "\"NVARCHAR2\""
2015 "\"TIME WITH TIME ZONE\"" "\"TIMESTAMP WITH LOCAL TIME ZONE\""
2016 "\"TIMESTAMP WITH TIME ZONE\""
2017 "bfile" "bfile_base" "binary_double" "binary_float" "binary_integer"
2018 "blob" "blob_base" "boolean" "char" "character" "char_base" "clob"
2019 "clob_base" "cursor" "date" "day" "dec" "decimal"
2020 "dsinterval_unconstrained" "float" "int" "integer" "interval" "local"
2021 "long" "mlslabel" "month" "natural" "naturaln" "nchar_cs" "number"
2022 "number_base" "numeric" "pls_integer" "positive" "positiven" "raw"
2023 "real" "ref" "rowid" "second" "signtype" "simple_double"
2024 "simple_float" "simple_integer" "smallint" "string" "time" "timestamp"
2025 "timestamp_ltz_unconstrained" "timestamp_tz_unconstrained"
2026 "timestamp_unconstrained" "time_tz_unconstrained" "time_unconstrained"
2027 "to" "urowid" "varchar" "varchar2" "with" "year"
2028 "yminterval_unconstrained" "zone"
2031 ;; Oracle PL/SQL Exceptions
2032 (sql-font-lock-keywords-builder 'font-lock-warning-face nil
2033 "access_into_null" "case_not_found" "collection_is_null"
2034 "cursor_already_open" "dup_val_on_index" "invalid_cursor"
2035 "invalid_number" "login_denied" "no_data_found" "no_data_needed"
2036 "not_logged_on" "program_error" "rowtype_mismatch" "self_is_null"
2037 "storage_error" "subscript_beyond_count" "subscript_outside_limit"
2038 "sys_invalid_rowid" "timeout_on_resource" "too_many_rows"
2039 "value_error" "zero_divide"
2042 "Oracle SQL keywords used by font-lock.
2044 This variable is used by `sql-mode' and `sql-interactive-mode'. The
2045 regular expressions are created during compilation by calling the
2046 function `regexp-opt'. Therefore, take a look at the source before
2047 you define your own `sql-mode-oracle-font-lock-keywords'. You may want
2048 to add functions and PL/SQL keywords.")
2050 (defvar sql-mode-postgres-font-lock-keywords
2051 (eval-when-compile
2052 (list
2053 ;; Postgres psql commands
2054 '("^\\s-*\\\\.*$" . font-lock-doc-face)
2056 ;; Postgres unreserved words but may have meaning
2057 (sql-font-lock-keywords-builder 'font-lock-builtin-face nil "a"
2058 "abs" "absent" "according" "ada" "alias" "allocate" "are" "array_agg"
2059 "asensitive" "atomic" "attribute" "attributes" "avg" "base64"
2060 "bernoulli" "bit_length" "bitvar" "blob" "blocked" "bom" "breadth" "c"
2061 "call" "cardinality" "catalog_name" "ceil" "ceiling" "char_length"
2062 "character_length" "character_set_catalog" "character_set_name"
2063 "character_set_schema" "characters" "checked" "class_origin" "clob"
2064 "cobol" "collation" "collation_catalog" "collation_name"
2065 "collation_schema" "collect" "column_name" "columns"
2066 "command_function" "command_function_code" "completion" "condition"
2067 "condition_number" "connect" "connection_name" "constraint_catalog"
2068 "constraint_name" "constraint_schema" "constructor" "contains"
2069 "control" "convert" "corr" "corresponding" "count" "covar_pop"
2070 "covar_samp" "cube" "cume_dist" "current_default_transform_group"
2071 "current_path" "current_transform_group_for_type" "cursor_name"
2072 "datalink" "datetime_interval_code" "datetime_interval_precision" "db"
2073 "defined" "degree" "dense_rank" "depth" "deref" "derived" "describe"
2074 "descriptor" "destroy" "destructor" "deterministic" "diagnostics"
2075 "disconnect" "dispatch" "dlnewcopy" "dlpreviouscopy" "dlurlcomplete"
2076 "dlurlcompleteonly" "dlurlcompletewrite" "dlurlpath" "dlurlpathonly"
2077 "dlurlpathwrite" "dlurlscheme" "dlurlserver" "dlvalue" "dynamic"
2078 "dynamic_function" "dynamic_function_code" "element" "empty"
2079 "end-exec" "equals" "every" "exception" "exec" "existing" "exp" "file"
2080 "filter" "final" "first_value" "flag" "floor" "fortran" "found" "free"
2081 "fs" "fusion" "g" "general" "generated" "get" "go" "goto" "grouping"
2082 "hex" "hierarchy" "host" "id" "ignore" "implementation" "import"
2083 "indent" "indicator" "infix" "initialize" "instance" "instantiable"
2084 "integrity" "intersection" "iterate" "k" "key_member" "key_type" "lag"
2085 "last_value" "lateral" "lead" "length" "less" "library" "like_regex"
2086 "link" "ln" "locator" "lower" "m" "map" "matched" "max"
2087 "max_cardinality" "member" "merge" "message_length"
2088 "message_octet_length" "message_text" "method" "min" "mod" "modifies"
2089 "modify" "module" "more" "multiset" "mumps" "namespace" "nclob"
2090 "nesting" "new" "nfc" "nfd" "nfkc" "nfkd" "nil" "normalize"
2091 "normalized" "nth_value" "ntile" "nullable" "number"
2092 "occurrences_regex" "octet_length" "octets" "old" "open" "operation"
2093 "ordering" "ordinality" "others" "output" "overriding" "p" "pad"
2094 "parameter" "parameter_mode" "parameter_name"
2095 "parameter_ordinal_position" "parameter_specific_catalog"
2096 "parameter_specific_name" "parameter_specific_schema" "parameters"
2097 "pascal" "passing" "passthrough" "percent_rank" "percentile_cont"
2098 "percentile_disc" "permission" "pli" "position_regex" "postfix"
2099 "power" "prefix" "preorder" "public" "rank" "reads" "recovery" "ref"
2100 "referencing" "regr_avgx" "regr_avgy" "regr_count" "regr_intercept"
2101 "regr_r2" "regr_slope" "regr_sxx" "regr_sxy" "regr_syy" "requiring"
2102 "respect" "restore" "result" "return" "returned_cardinality"
2103 "returned_length" "returned_octet_length" "returned_sqlstate" "rollup"
2104 "routine" "routine_catalog" "routine_name" "routine_schema"
2105 "row_count" "row_number" "scale" "schema_name" "scope" "scope_catalog"
2106 "scope_name" "scope_schema" "section" "selective" "self" "sensitive"
2107 "server_name" "sets" "size" "source" "space" "specific"
2108 "specific_name" "specifictype" "sql" "sqlcode" "sqlerror"
2109 "sqlexception" "sqlstate" "sqlwarning" "sqrt" "state" "static"
2110 "stddev_pop" "stddev_samp" "structure" "style" "subclass_origin"
2111 "sublist" "submultiset" "substring_regex" "sum" "system_user" "t"
2112 "table_name" "tablesample" "terminate" "than" "ties" "timezone_hour"
2113 "timezone_minute" "token" "top_level_count" "transaction_active"
2114 "transactions_committed" "transactions_rolled_back" "transform"
2115 "transforms" "translate" "translate_regex" "translation"
2116 "trigger_catalog" "trigger_name" "trigger_schema" "trim_array"
2117 "uescape" "under" "unlink" "unnamed" "unnest" "untyped" "upper" "uri"
2118 "usage" "user_defined_type_catalog" "user_defined_type_code"
2119 "user_defined_type_name" "user_defined_type_schema" "var_pop"
2120 "var_samp" "varbinary" "variable" "whenever" "width_bucket" "within"
2121 "xmlagg" "xmlbinary" "xmlcast" "xmlcomment" "xmldeclaration"
2122 "xmldocument" "xmlexists" "xmliterate" "xmlnamespaces" "xmlquery"
2123 "xmlschema" "xmltable" "xmltext" "xmlvalidate"
2126 ;; Postgres non-reserved words
2127 (sql-font-lock-keywords-builder 'font-lock-builtin-face nil
2128 "abort" "absolute" "access" "action" "add" "admin" "after" "aggregate"
2129 "also" "alter" "always" "assertion" "assignment" "at" "attribute" "backward"
2130 "before" "begin" "between" "by" "cache" "called" "cascade" "cascaded"
2131 "catalog" "chain" "characteristics" "checkpoint" "class" "close"
2132 "cluster" "coalesce" "comment" "comments" "commit" "committed"
2133 "configuration" "connection" "constraints" "content" "continue"
2134 "conversion" "copy" "cost" "createdb" "createrole" "createuser" "csv"
2135 "current" "cursor" "cycle" "data" "database" "day" "deallocate" "dec"
2136 "declare" "defaults" "deferred" "definer" "delete" "delimiter"
2137 "delimiters" "dictionary" "disable" "discard" "document" "domain"
2138 "drop" "each" "enable" "encoding" "encrypted" "enum" "escape"
2139 "exclude" "excluding" "exclusive" "execute" "exists" "explain"
2140 "extension" "external" "extract" "family" "first" "float" "following" "force"
2141 "forward" "function" "functions" "global" "granted" "greatest"
2142 "handler" "header" "hold" "hour" "identity" "if" "immediate"
2143 "immutable" "implicit" "including" "increment" "index" "indexes"
2144 "inherit" "inherits" "inline" "inout" "input" "insensitive" "insert"
2145 "instead" "invoker" "isolation" "key" "label" "language" "large" "last"
2146 "lc_collate" "lc_ctype" "leakproof" "least" "level" "listen" "load" "local"
2147 "location" "lock" "login" "mapping" "match" "maxvalue" "minute"
2148 "minvalue" "mode" "month" "move" "names" "national" "nchar"
2149 "next" "no" "nocreatedb" "nocreaterole" "nocreateuser" "noinherit"
2150 "nologin" "none" "noreplication" "nosuperuser" "nothing" "notify" "nowait" "nullif"
2151 "nulls" "object" "of" "off" "oids" "operator" "option" "options" "out"
2152 "overlay" "owned" "owner" "parser" "partial" "partition" "passing" "password"
2153 "plans" "position" "preceding" "precision" "prepare" "prepared" "preserve" "prior"
2154 "privileges" "procedural" "procedure" "quote" "range" "read"
2155 "reassign" "recheck" "recursive" "ref" "reindex" "relative" "release"
2156 "rename" "repeatable" "replace" "replica" "replication" "reset" "restart" "restrict"
2157 "returns" "revoke" "role" "rollback" "row" "rows" "rule" "savepoint"
2158 "schema" "scroll" "search" "second" "security" "sequence"
2159 "serializable" "server" "session" "set" "setof" "share" "show"
2160 "simple" "snapshot" "stable" "standalone" "start" "statement" "statistics"
2161 "stdin" "stdout" "storage" "strict" "strip" "substring" "superuser"
2162 "sysid" "system" "tables" "tablespace" "temp" "template" "temporary"
2163 "transaction" "treat" "trim" "truncate" "trusted" "type" "types"
2164 "unbounded" "uncommitted" "unencrypted" "unlisten" "unlogged" "until"
2165 "update" "vacuum" "valid" "validate" "validator" "value" "values" "varying" "version"
2166 "view" "volatile" "whitespace" "without" "work" "wrapper" "write"
2167 "xmlattributes" "xmlconcat" "xmlelement" "xmlexists" "xmlforest" "xmlparse"
2168 "xmlpi" "xmlroot" "xmlserialize" "year" "yes" "zone"
2171 ;; Postgres Reserved
2172 (sql-font-lock-keywords-builder 'font-lock-keyword-face nil
2173 "all" "analyse" "analyze" "and" "array" "asc" "as" "asymmetric"
2174 "authorization" "binary" "both" "case" "cast" "check" "collate"
2175 "column" "concurrently" "constraint" "create" "cross"
2176 "current_catalog" "current_date" "current_role" "current_schema"
2177 "current_time" "current_timestamp" "current_user" "default"
2178 "deferrable" "desc" "distinct" "do" "else" "end" "except" "false"
2179 "fetch" "foreign" "for" "freeze" "from" "full" "grant" "group"
2180 "having" "ilike" "initially" "inner" "in" "intersect" "into" "isnull"
2181 "is" "join" "leading" "left" "like" "limit" "localtime"
2182 "localtimestamp" "natural" "notnull" "not" "null" "offset"
2183 "only" "on" "order" "or" "outer" "overlaps" "over" "placing" "primary"
2184 "references" "returning" "right" "select" "session_user" "similar"
2185 "some" "symmetric" "table" "then" "to" "trailing" "true" "union"
2186 "unique" "user" "using" "variadic" "verbose" "when" "where" "window"
2187 "with"
2190 ;; Postgres PL/pgSQL
2191 (sql-font-lock-keywords-builder 'font-lock-keyword-face nil
2192 "assign" "if" "case" "loop" "while" "for" "foreach" "exit" "elsif" "return"
2193 "raise" "execsql" "dynexecute" "perform" "getdiag" "open" "fetch" "move" "close"
2196 ;; Postgres Data Types
2197 (sql-font-lock-keywords-builder 'font-lock-type-face nil
2198 "bigint" "bigserial" "bit" "bool" "boolean" "box" "bytea" "char"
2199 "character" "cidr" "circle" "date" "decimal" "double" "float4"
2200 "float8" "inet" "int" "int2" "int4" "int8" "integer" "interval" "line"
2201 "lseg" "macaddr" "money" "name" "numeric" "path" "point" "polygon"
2202 "precision" "real" "serial" "serial4" "serial8" "sequences" "smallint" "text"
2203 "time" "timestamp" "timestamptz" "timetz" "tsquery" "tsvector"
2204 "txid_snapshot" "unknown" "uuid" "varbit" "varchar" "varying" "without"
2205 "xml" "zone"
2208 "Postgres SQL keywords used by font-lock.
2210 This variable is used by `sql-mode' and `sql-interactive-mode'. The
2211 regular expressions are created during compilation by calling the
2212 function `regexp-opt'. Therefore, take a look at the source before
2213 you define your own `sql-mode-postgres-font-lock-keywords'.")
2215 (defvar sql-mode-linter-font-lock-keywords
2216 (eval-when-compile
2217 (list
2218 ;; Linter Keywords
2219 (sql-font-lock-keywords-builder 'font-lock-keyword-face nil
2220 "autocommit" "autoinc" "autorowid" "cancel" "cascade" "channel"
2221 "committed" "count" "countblob" "cross" "current" "data" "database"
2222 "datafile" "datafiles" "datesplit" "dba" "dbname" "default" "deferred"
2223 "denied" "description" "device" "difference" "directory" "error"
2224 "escape" "euc" "exclusive" "external" "extfile" "false" "file"
2225 "filename" "filesize" "filetime" "filter" "findblob" "first" "foreign"
2226 "full" "fuzzy" "global" "granted" "ignore" "immediate" "increment"
2227 "indexes" "indexfile" "indexfiles" "indextime" "initial" "integrity"
2228 "internal" "key" "last_autoinc" "last_rowid" "limit" "linter"
2229 "linter_file_device" "linter_file_size" "linter_name_length" "ln"
2230 "local" "login" "maxisn" "maxrow" "maxrowid" "maxvalue" "message"
2231 "minvalue" "module" "names" "national" "natural" "new" "new_table"
2232 "no" "node" "noneuc" "nulliferror" "numbers" "off" "old" "old_table"
2233 "only" "operation" "optimistic" "option" "page" "partially" "password"
2234 "phrase" "plan" "precision" "primary" "priority" "privileges"
2235 "proc_info_size" "proc_par_name_len" "protocol" "quant" "range" "raw"
2236 "read" "record" "records" "references" "remote" "rename" "replication"
2237 "restart" "rewrite" "root" "row" "rule" "savepoint" "security"
2238 "sensitive" "sequence" "serializable" "server" "since" "size" "some"
2239 "startup" "statement" "station" "success" "sys_guid" "tables" "test"
2240 "timeout" "trace" "transaction" "translation" "trigger"
2241 "trigger_info_size" "true" "trunc" "uncommitted" "unicode" "unknown"
2242 "unlimited" "unlisted" "user" "utf8" "value" "varying" "volumes"
2243 "wait" "windows_code" "workspace" "write" "xml"
2246 ;; Linter Reserved
2247 (sql-font-lock-keywords-builder 'font-lock-keyword-face nil
2248 "access" "action" "add" "address" "after" "all" "alter" "always" "and"
2249 "any" "append" "as" "asc" "ascic" "async" "at_begin" "at_end" "audit"
2250 "aud_obj_name_len" "backup" "base" "before" "between" "blobfile"
2251 "blobfiles" "blobpct" "brief" "browse" "by" "case" "cast" "check"
2252 "clear" "close" "column" "comment" "commit" "connect" "contains"
2253 "correct" "create" "delete" "desc" "disable" "disconnect" "distinct"
2254 "drop" "each" "ef" "else" "enable" "end" "event" "except" "exclude"
2255 "execute" "exists" "extract" "fetch" "finish" "for" "from" "get"
2256 "grant" "group" "having" "identified" "in" "index" "inner" "insert"
2257 "instead" "intersect" "into" "is" "isolation" "join" "left" "level"
2258 "like" "lock" "mode" "modify" "not" "nowait" "null" "of" "on" "open"
2259 "or" "order" "outer" "owner" "press" "prior" "procedure" "public"
2260 "purge" "rebuild" "resource" "restrict" "revoke" "right" "role"
2261 "rollback" "rownum" "select" "session" "set" "share" "shutdown"
2262 "start" "stop" "sync" "synchronize" "synonym" "sysdate" "table" "then"
2263 "to" "union" "unique" "unlock" "until" "update" "using" "values"
2264 "view" "when" "where" "with" "without"
2267 ;; Linter Functions
2268 (sql-font-lock-keywords-builder 'font-lock-builtin-face nil
2269 "abs" "acos" "asin" "atan" "atan2" "avg" "ceil" "cos" "cosh" "divtime"
2270 "exp" "floor" "getbits" "getblob" "getbyte" "getlong" "getraw"
2271 "getstr" "gettext" "getword" "hextoraw" "lenblob" "length" "log"
2272 "lower" "lpad" "ltrim" "max" "min" "mod" "monthname" "nvl"
2273 "octet_length" "power" "rand" "rawtohex" "repeat_string"
2274 "right_substr" "round" "rpad" "rtrim" "sign" "sin" "sinh" "soundex"
2275 "sqrt" "sum" "tan" "tanh" "timeint_to_days" "to_char" "to_date"
2276 "to_gmtime" "to_localtime" "to_number" "trim" "upper" "decode"
2277 "substr" "substring" "chr" "dayname" "days" "greatest" "hex" "initcap"
2278 "instr" "least" "multime" "replace" "width"
2281 ;; Linter Data Types
2282 (sql-font-lock-keywords-builder 'font-lock-type-face nil
2283 "bigint" "bitmap" "blob" "boolean" "char" "character" "date"
2284 "datetime" "dec" "decimal" "double" "float" "int" "integer" "nchar"
2285 "number" "numeric" "real" "smallint" "varbyte" "varchar" "byte"
2286 "cursor" "long"
2289 "Linter SQL keywords used by font-lock.
2291 This variable is used by `sql-mode' and `sql-interactive-mode'. The
2292 regular expressions are created during compilation by calling the
2293 function `regexp-opt'.")
2295 (defvar sql-mode-ms-font-lock-keywords
2296 (eval-when-compile
2297 (list
2298 ;; MS isql/osql Commands
2299 (cons
2300 (concat
2301 "^\\(?:\\(?:set\\s-+\\(?:"
2302 (regexp-opt '(
2303 "datefirst" "dateformat" "deadlock_priority" "lock_timeout"
2304 "concat_null_yields_null" "cursor_close_on_commit"
2305 "disable_def_cnst_chk" "fips_flagger" "identity_insert" "language"
2306 "offsets" "quoted_identifier" "arithabort" "arithignore" "fmtonly"
2307 "nocount" "noexec" "numeric_roundabort" "parseonly"
2308 "query_governor_cost_limit" "rowcount" "textsize" "ansi_defaults"
2309 "ansi_null_dflt_off" "ansi_null_dflt_on" "ansi_nulls" "ansi_padding"
2310 "ansi_warnings" "forceplan" "showplan_all" "showplan_text"
2311 "statistics" "implicit_transactions" "remote_proc_transactions"
2312 "transaction" "xact_abort"
2315 "\\)\\)\\|go\\s-*\\|use\\s-+\\|setuser\\s-+\\|dbcc\\s-+\\).*$")
2316 'font-lock-doc-face)
2318 ;; MS Reserved
2319 (sql-font-lock-keywords-builder 'font-lock-keyword-face nil
2320 "absolute" "add" "all" "alter" "and" "any" "as" "asc" "authorization"
2321 "avg" "backup" "begin" "between" "break" "browse" "bulk" "by"
2322 "cascade" "case" "check" "checkpoint" "close" "clustered" "coalesce"
2323 "column" "commit" "committed" "compute" "confirm" "constraint"
2324 "contains" "containstable" "continue" "controlrow" "convert" "count"
2325 "create" "cross" "current" "current_date" "current_time"
2326 "current_timestamp" "current_user" "database" "deallocate" "declare"
2327 "default" "delete" "deny" "desc" "disk" "distinct" "distributed"
2328 "double" "drop" "dummy" "dump" "else" "end" "errlvl" "errorexit"
2329 "escape" "except" "exec" "execute" "exists" "exit" "fetch" "file"
2330 "fillfactor" "first" "floppy" "for" "foreign" "freetext"
2331 "freetexttable" "from" "full" "goto" "grant" "group" "having"
2332 "holdlock" "identity" "identity_insert" "identitycol" "if" "in"
2333 "index" "inner" "insert" "intersect" "into" "is" "isolation" "join"
2334 "key" "kill" "last" "left" "level" "like" "lineno" "load" "max" "min"
2335 "mirrorexit" "national" "next" "nocheck" "nolock" "nonclustered" "not"
2336 "null" "nullif" "of" "off" "offsets" "on" "once" "only" "open"
2337 "opendatasource" "openquery" "openrowset" "option" "or" "order"
2338 "outer" "output" "over" "paglock" "percent" "perm" "permanent" "pipe"
2339 "plan" "precision" "prepare" "primary" "print" "prior" "privileges"
2340 "proc" "procedure" "processexit" "public" "raiserror" "read"
2341 "readcommitted" "readpast" "readtext" "readuncommitted" "reconfigure"
2342 "references" "relative" "repeatable" "repeatableread" "replication"
2343 "restore" "restrict" "return" "revoke" "right" "rollback" "rowcount"
2344 "rowguidcol" "rowlock" "rule" "save" "schema" "select" "serializable"
2345 "session_user" "set" "shutdown" "some" "statistics" "sum"
2346 "system_user" "table" "tablock" "tablockx" "tape" "temp" "temporary"
2347 "textsize" "then" "to" "top" "tran" "transaction" "trigger" "truncate"
2348 "tsequal" "uncommitted" "union" "unique" "update" "updatetext"
2349 "updlock" "use" "user" "values" "view" "waitfor" "when" "where"
2350 "while" "with" "work" "writetext" "collate" "function" "openxml"
2351 "returns"
2354 ;; MS Functions
2355 (sql-font-lock-keywords-builder 'font-lock-builtin-face nil
2356 "@@connections" "@@cpu_busy" "@@cursor_rows" "@@datefirst" "@@dbts"
2357 "@@error" "@@fetch_status" "@@identity" "@@idle" "@@io_busy"
2358 "@@langid" "@@language" "@@lock_timeout" "@@max_connections"
2359 "@@max_precision" "@@nestlevel" "@@options" "@@pack_received"
2360 "@@pack_sent" "@@packet_errors" "@@procid" "@@remserver" "@@rowcount"
2361 "@@servername" "@@servicename" "@@spid" "@@textsize" "@@timeticks"
2362 "@@total_errors" "@@total_read" "@@total_write" "@@trancount"
2363 "@@version" "abs" "acos" "and" "app_name" "ascii" "asin" "atan" "atn2"
2364 "avg" "case" "cast" "ceiling" "char" "charindex" "coalesce"
2365 "col_length" "col_name" "columnproperty" "containstable" "convert"
2366 "cos" "cot" "count" "current_timestamp" "current_user" "cursor_status"
2367 "databaseproperty" "datalength" "dateadd" "datediff" "datename"
2368 "datepart" "day" "db_id" "db_name" "degrees" "difference" "exp"
2369 "file_id" "file_name" "filegroup_id" "filegroup_name"
2370 "filegroupproperty" "fileproperty" "floor" "formatmessage"
2371 "freetexttable" "fulltextcatalogproperty" "fulltextserviceproperty"
2372 "getansinull" "getdate" "grouping" "host_id" "host_name" "ident_incr"
2373 "ident_seed" "identity" "index_col" "indexproperty" "is_member"
2374 "is_srvrolemember" "isdate" "isnull" "isnumeric" "left" "len" "log"
2375 "log10" "lower" "ltrim" "max" "min" "month" "nchar" "newid" "nullif"
2376 "object_id" "object_name" "objectproperty" "openquery" "openrowset"
2377 "parsename" "patindex" "patindex" "permissions" "pi" "power"
2378 "quotename" "radians" "rand" "replace" "replicate" "reverse" "right"
2379 "round" "rtrim" "session_user" "sign" "sin" "soundex" "space" "sqrt"
2380 "square" "stats_date" "stdev" "stdevp" "str" "stuff" "substring" "sum"
2381 "suser_id" "suser_name" "suser_sid" "suser_sname" "system_user" "tan"
2382 "textptr" "textvalid" "typeproperty" "unicode" "upper" "user"
2383 "user_id" "user_name" "var" "varp" "year"
2386 ;; MS Variables
2387 '("\\b@[a-zA-Z0-9_]*\\b" . font-lock-variable-name-face)
2389 ;; MS Types
2390 (sql-font-lock-keywords-builder 'font-lock-type-face nil
2391 "binary" "bit" "char" "character" "cursor" "datetime" "dec" "decimal"
2392 "double" "float" "image" "int" "integer" "money" "national" "nchar"
2393 "ntext" "numeric" "numeric" "nvarchar" "precision" "real"
2394 "smalldatetime" "smallint" "smallmoney" "text" "timestamp" "tinyint"
2395 "uniqueidentifier" "varbinary" "varchar" "varying"
2398 "Microsoft SQLServer SQL keywords used by font-lock.
2400 This variable is used by `sql-mode' and `sql-interactive-mode'. The
2401 regular expressions are created during compilation by calling the
2402 function `regexp-opt'. Therefore, take a look at the source before
2403 you define your own `sql-mode-ms-font-lock-keywords'.")
2405 (defvar sql-mode-sybase-font-lock-keywords nil
2406 "Sybase SQL keywords used by font-lock.
2408 This variable is used by `sql-mode' and `sql-interactive-mode'. The
2409 regular expressions are created during compilation by calling the
2410 function `regexp-opt'. Therefore, take a look at the source before
2411 you define your own `sql-mode-sybase-font-lock-keywords'.")
2413 (defvar sql-mode-informix-font-lock-keywords nil
2414 "Informix SQL keywords used by font-lock.
2416 This variable is used by `sql-mode' and `sql-interactive-mode'. The
2417 regular expressions are created during compilation by calling the
2418 function `regexp-opt'. Therefore, take a look at the source before
2419 you define your own `sql-mode-informix-font-lock-keywords'.")
2421 (defvar sql-mode-interbase-font-lock-keywords nil
2422 "Interbase SQL keywords used by font-lock.
2424 This variable is used by `sql-mode' and `sql-interactive-mode'. The
2425 regular expressions are created during compilation by calling the
2426 function `regexp-opt'. Therefore, take a look at the source before
2427 you define your own `sql-mode-interbase-font-lock-keywords'.")
2429 (defvar sql-mode-ingres-font-lock-keywords nil
2430 "Ingres SQL keywords used by font-lock.
2432 This variable is used by `sql-mode' and `sql-interactive-mode'. The
2433 regular expressions are created during compilation by calling the
2434 function `regexp-opt'. Therefore, take a look at the source before
2435 you define your own `sql-mode-interbase-font-lock-keywords'.")
2437 (defvar sql-mode-solid-font-lock-keywords nil
2438 "Solid SQL keywords used by font-lock.
2440 This variable is used by `sql-mode' and `sql-interactive-mode'. The
2441 regular expressions are created during compilation by calling the
2442 function `regexp-opt'. Therefore, take a look at the source before
2443 you define your own `sql-mode-solid-font-lock-keywords'.")
2445 (defvaralias 'sql-mode-mariadb-font-lock-keywords 'sql-mode-mysql-font-lock-keywords
2446 "MariaDB is SQL compatible with MySQL.")
2448 (defvar sql-mode-mysql-font-lock-keywords
2449 (eval-when-compile
2450 (list
2451 ;; MySQL Functions
2452 (sql-font-lock-keywords-builder 'font-lock-builtin-face nil
2453 "acos" "adddate" "addtime" "aes_decrypt" "aes_encrypt" "area"
2454 "asbinary" "ascii" "asin" "astext" "aswkb" "aswkt" "atan" "atan2"
2455 "avg" "bdmpolyfromtext" "bdmpolyfromwkb" "bdpolyfromtext"
2456 "bdpolyfromwkb" "benchmark" "bin" "binlog_gtid_pos" "bit_and"
2457 "bit_count" "bit_length" "bit_or" "bit_xor" "both" "boundary" "buffer"
2458 "cast" "ceil" "ceiling" "centroid" "character_length" "char_length"
2459 "charset" "coalesce" "coercibility" "column_add" "column_check"
2460 "column_create" "column_delete" "column_exists" "column_get"
2461 "column_json" "column_list" "compress" "concat" "concat_ws"
2462 "connection_id" "conv" "convert" "convert_tz" "convexhull" "cos" "cot"
2463 "count" "crc32" "crosses" "cume_dist" "cume_dist" "curdate"
2464 "current_date" "current_time" "current_timestamp" "curtime" "date_add"
2465 "datediff" "date_format" "date_sub" "dayname" "dayofmonth" "dayofweek"
2466 "dayofyear" "decode" "decode_histogram" "degrees" "dense_rank"
2467 "dense_rank" "des_decrypt" "des_encrypt" "dimension" "disjoint" "div"
2468 "elt" "encode" "encrypt" "endpoint" "envelope" "exp" "export_set"
2469 "exteriorring" "extractvalue" "field" "find_in_set" "floor" "format"
2470 "found_rows" "from" "from_base64" "from_days" "from_unixtime"
2471 "geomcollfromtext" "geomcollfromwkb" "geometrycollectionfromtext"
2472 "geometrycollectionfromwkb" "geometryfromtext" "geometryfromwkb"
2473 "geometryn" "geometrytype" "geomfromtext" "geomfromwkb" "get_format"
2474 "get_lock" "glength" "greatest" "group_concat" "hex" "ifnull"
2475 "inet6_aton" "inet6_ntoa" "inet_aton" "inet_ntoa" "instr"
2476 "interiorringn" "intersects" "interval" "isclosed" "isempty"
2477 "is_free_lock" "is_ipv4" "is_ipv4_compat" "is_ipv4_mapped" "is_ipv6"
2478 "isnull" "isring" "issimple" "is_used_lock" "json_array"
2479 "json_array_append" "json_array_insert" "json_compact" "json_contains"
2480 "json_contains_path" "json_depth" "json_detailed" "json_exists"
2481 "json_extract" "json_insert" "json_keys" "json_length" "json_loose"
2482 "json_merge" "json_object" "json_query" "json_quote" "json_remove"
2483 "json_replace" "json_search" "json_set" "json_type" "json_unquote"
2484 "json_valid" "json_value" "lag" "last_day" "last_insert_id" "lastval"
2485 "last_value" "last_value" "lcase" "lead" "leading" "least" "length"
2486 "linefromtext" "linefromwkb" "linestringfromtext" "linestringfromwkb"
2487 "ln" "load_file" "locate" "log" "log10" "log2" "lower" "lpad" "ltrim"
2488 "makedate" "make_set" "maketime" "master_gtid_wait" "master_pos_wait"
2489 "max" "mbrcontains" "mbrdisjoint" "mbrequal" "mbrintersects"
2490 "mbroverlaps" "mbrtouches" "mbrwithin" "md5" "median"
2491 "mid" "min" "mlinefromtext" "mlinefromwkb" "monthname"
2492 "mpointfromtext" "mpointfromwkb" "mpolyfromtext" "mpolyfromwkb"
2493 "multilinestringfromtext" "multilinestringfromwkb"
2494 "multipointfromtext" "multipointfromwkb" "multipolygonfromtext"
2495 "multipolygonfromwkb" "name_const" "nextval" "now" "nth_value" "ntile"
2496 "ntile" "nullif" "numgeometries" "numinteriorrings" "numpoints" "oct"
2497 "octet_length" "old_password" "ord" "percentile_cont"
2498 "percentile_disc" "percent_rank" "percent_rank" "period_add"
2499 "period_diff" "pi" "pointfromtext" "pointfromwkb" "pointn"
2500 "pointonsurface" "polyfromtext" "polyfromwkb" "polygonfromtext"
2501 "polygonfromwkb" "position" "pow" "power" "quote" "radians"
2502 "rand" "rank" "rank" "regexp" "regexp_instr" "regexp_replace"
2503 "regexp_substr" "release_lock" "repeat" "replace" "reverse" "rlike"
2504 "row_number" "row_number" "rpad" "rtrim" "sec_to_time" "setval" "sha"
2505 "sha1" "sha2" "sign" "sin" "sleep" "soundex" "space"
2506 "spider_bg_direct_sql" "spider_copy_tables" "spider_direct_sql"
2507 "spider_flush_table_mon_cache" "sqrt" "srid" "st_area" "startpoint"
2508 "st_asbinary" "st_astext" "st_aswkb" "st_aswkt" "st_boundary"
2509 "st_buffer" "st_centroid" "st_contains" "st_convexhull" "st_crosses"
2510 "std" "stddev" "stddev_pop" "stddev_samp" "st_difference"
2511 "st_dimension" "st_disjoint" "st_distance" "st_endpoint" "st_envelope"
2512 "st_equals" "st_exteriorring" "st_geomcollfromtext"
2513 "st_geomcollfromwkb" "st_geometrycollectionfromtext"
2514 "st_geometrycollectionfromwkb" "st_geometryfromtext"
2515 "st_geometryfromwkb" "st_geometryn" "st_geometrytype"
2516 "st_geomfromtext" "st_geomfromwkb" "st_interiorringn"
2517 "st_intersection" "st_intersects" "st_isclosed" "st_isempty"
2518 "st_isring" "st_issimple" "st_length" "st_linefromtext"
2519 "st_linefromwkb" "st_linestringfromtext" "st_linestringfromwkb"
2520 "st_numgeometries" "st_numinteriorrings" "st_numpoints" "st_overlaps"
2521 "st_pointfromtext" "st_pointfromwkb" "st_pointn" "st_pointonsurface"
2522 "st_polyfromtext" "st_polyfromwkb" "st_polygonfromtext"
2523 "st_polygonfromwkb" "strcmp" "st_relate" "str_to_date" "st_srid"
2524 "st_startpoint" "st_symdifference" "st_touches" "st_union" "st_within"
2525 "st_x" "st_y" "subdate" "substr" "substring" "substring_index"
2526 "subtime" "sum" "sysdate" "tan" "timediff" "time_format"
2527 "timestampadd" "timestampdiff" "time_to_sec" "to_base64" "to_days"
2528 "to_seconds" "touches" "trailing" "trim" "ucase" "uncompress"
2529 "uncompressed_length" "unhex" "unix_timestamp" "updatexml" "upper"
2530 "user" "utc_date" "utc_time" "utc_timestamp" "uuid" "uuid_short"
2531 "variance" "var_pop" "var_samp" "version" "weekday"
2532 "weekofyear" "weight_string" "within"
2535 ;; MySQL Keywords
2536 (sql-font-lock-keywords-builder 'font-lock-keyword-face nil
2537 "accessible" "action" "add" "after" "against" "all" "alter" "analyze"
2538 "and" "as" "asc" "auto_increment" "avg_row_length" "bdb" "between"
2539 "body" "by" "cascade" "case" "change" "character" "check" "checksum"
2540 "close" "collate" "collation" "column" "columns" "comment" "committed"
2541 "concurrent" "condition" "constraint" "create" "cross" "data"
2542 "database" "databases" "default" "delayed" "delay_key_write" "delete"
2543 "desc" "directory" "disable" "distinct" "distinctrow" "do" "drop"
2544 "dual" "dumpfile" "duplicate" "else" "elseif" "elsif" "enable"
2545 "enclosed" "end" "escaped" "exists" "exit" "explain" "fields" "first"
2546 "for" "force" "foreign" "from" "full" "fulltext" "global" "group"
2547 "handler" "having" "heap" "high_priority" "history" "if" "ignore"
2548 "ignore_server_ids" "in" "index" "infile" "inner" "insert"
2549 "insert_method" "into" "is" "isam" "isolation" "join" "key" "keys"
2550 "kill" "last" "leave" "left" "level" "like" "limit" "linear" "lines"
2551 "load" "local" "lock" "long" "loop" "low_priority"
2552 "master_heartbeat_period" "master_ssl_verify_server_cert" "match"
2553 "max_rows" "maxvalue" "merge" "min_rows" "mode" "modify" "mrg_myisam"
2554 "myisam" "natural" "next" "no" "not" "no_write_to_binlog" "null"
2555 "offset" "oj" "on" "open" "optimize" "optionally" "or" "order" "outer"
2556 "outfile" "over" "package" "pack_keys" "partial" "partition"
2557 "password" "period" "prev" "primary" "procedure" "purge" "quick"
2558 "raid0" "raid_type" "raise" "range" "read" "read_write" "references"
2559 "release" "rename" "repeatable" "require" "resignal" "restrict"
2560 "returning" "right" "rollback" "rollup" "row_format" "rowtype"
2561 "savepoint" "schemas" "select" "separator" "serializable" "session"
2562 "set" "share" "show" "signal" "slow" "spatial" "sql_big_result"
2563 "sql_buffer_result" "sql_cache" "sql_calc_found_rows" "sql_no_cache"
2564 "sql_small_result" "ssl" "starting" "straight_join" "striped"
2565 "system_time" "table" "tables" "temporary" "terminated" "then" "to"
2566 "transaction" "truncate" "type" "uncommitted" "undo" "union" "unique"
2567 "unlock" "update" "use" "using" "values" "versioning" "when" "where"
2568 "while" "window" "with" "write" "xor"
2571 ;; MySQL Data Types
2572 (sql-font-lock-keywords-builder 'font-lock-type-face nil
2573 "bigint" "binary" "bit" "blob" "bool" "boolean" "byte" "char" "curve"
2574 "date" "datetime" "day" "day_hour" "day_microsecond" "day_minute"
2575 "day_second" "dec" "decimal" "double" "enum" "fixed" "float" "float4"
2576 "float8" "geometry" "geometrycollection" "hour" "hour_microsecond"
2577 "hour_minute" "hour_second" "int" "int1" "int2" "int3" "int4" "int8"
2578 "integer" "json" "line" "linearring" "linestring" "longblob"
2579 "longtext" "mediumblob" "mediumint" "mediumtext" "microsecond"
2580 "middleint" "minute" "minute_microsecond" "minute_second" "month"
2581 "multicurve" "multilinestring" "multipoint" "multipolygon"
2582 "multisurface" "national" "numeric" "point" "polygon" "precision"
2583 "quarter" "real" "second" "second_microsecond" "signed" "smallint"
2584 "surface" "text" "time" "timestamp" "tinyblob" "tinyint" "tinytext"
2585 "unsigned" "varbinary" "varchar" "varcharacter" "week" "year" "year2"
2586 "year4" "year_month" "zerofill"
2589 "MySQL SQL keywords used by font-lock.
2591 This variable is used by `sql-mode' and `sql-interactive-mode'. The
2592 regular expressions are created during compilation by calling the
2593 function `regexp-opt'. Therefore, take a look at the source before
2594 you define your own `sql-mode-mysql-font-lock-keywords'.")
2596 (defvar sql-mode-sqlite-font-lock-keywords
2597 (eval-when-compile
2598 (list
2599 ;; SQLite commands
2600 '("^[.].*$" . font-lock-doc-face)
2602 ;; SQLite Keyword
2603 (sql-font-lock-keywords-builder 'font-lock-keyword-face nil
2604 "abort" "action" "add" "after" "all" "alter" "analyze" "and" "as"
2605 "asc" "attach" "autoincrement" "before" "begin" "between" "by"
2606 "cascade" "case" "cast" "check" "collate" "column" "commit" "conflict"
2607 "constraint" "create" "cross" "database" "default" "deferrable"
2608 "deferred" "delete" "desc" "detach" "distinct" "drop" "each" "else"
2609 "end" "escape" "except" "exclusive" "exists" "explain" "fail" "for"
2610 "foreign" "from" "full" "glob" "group" "having" "if" "ignore"
2611 "immediate" "in" "index" "indexed" "initially" "inner" "insert"
2612 "instead" "intersect" "into" "is" "isnull" "join" "key" "left" "like"
2613 "limit" "match" "natural" "no" "not" "notnull" "null" "of" "offset"
2614 "on" "or" "order" "outer" "plan" "pragma" "primary" "query" "raise"
2615 "references" "regexp" "reindex" "release" "rename" "replace"
2616 "restrict" "right" "rollback" "row" "savepoint" "select" "set" "table"
2617 "temp" "temporary" "then" "to" "transaction" "trigger" "union"
2618 "unique" "update" "using" "vacuum" "values" "view" "virtual" "when"
2619 "where"
2621 ;; SQLite Data types
2622 (sql-font-lock-keywords-builder 'font-lock-type-face nil
2623 "int" "integer" "tinyint" "smallint" "mediumint" "bigint" "unsigned"
2624 "big" "int2" "int8" "character" "varchar" "varying" "nchar" "native"
2625 "nvarchar" "text" "clob" "blob" "real" "double" "precision" "float"
2626 "numeric" "number" "decimal" "boolean" "date" "datetime"
2628 ;; SQLite Functions
2629 (sql-font-lock-keywords-builder 'font-lock-builtin-face nil
2630 ;; Core functions
2631 "abs" "changes" "coalesce" "glob" "ifnull" "hex" "last_insert_rowid"
2632 "length" "like" "load_extension" "lower" "ltrim" "max" "min" "nullif"
2633 "quote" "random" "randomblob" "replace" "round" "rtrim" "soundex"
2634 "sqlite_compileoption_get" "sqlite_compileoption_used"
2635 "sqlite_source_id" "sqlite_version" "substr" "total_changes" "trim"
2636 "typeof" "upper" "zeroblob"
2637 ;; Date/time functions
2638 "time" "julianday" "strftime"
2639 "current_date" "current_time" "current_timestamp"
2640 ;; Aggregate functions
2641 "avg" "count" "group_concat" "max" "min" "sum" "total"
2644 "SQLite SQL keywords used by font-lock.
2646 This variable is used by `sql-mode' and `sql-interactive-mode'. The
2647 regular expressions are created during compilation by calling the
2648 function `regexp-opt'. Therefore, take a look at the source before
2649 you define your own `sql-mode-sqlite-font-lock-keywords'.")
2651 (defvar sql-mode-db2-font-lock-keywords nil
2652 "DB2 SQL keywords used by font-lock.
2654 This variable is used by `sql-mode' and `sql-interactive-mode'. The
2655 regular expressions are created during compilation by calling the
2656 function `regexp-opt'. Therefore, take a look at the source before
2657 you define your own `sql-mode-db2-font-lock-keywords'.")
2659 (defvar sql-mode-font-lock-keywords nil
2660 "SQL keywords used by font-lock.
2662 Setting this variable directly no longer has any affect. Use
2663 `sql-product' and `sql-add-product-keywords' to control the
2664 highlighting rules in SQL mode.")
2668 ;;; SQL Product support functions
2670 (defun sql-read-product (prompt &optional initial)
2671 "Read a valid SQL product."
2672 (let ((init (or (and initial (symbol-name initial)) "ansi")))
2673 (intern (completing-read
2674 prompt
2675 (mapcar (lambda (info) (symbol-name (car info)))
2676 sql-product-alist)
2677 nil 'require-match
2678 init 'sql-product-history init))))
2680 (defun sql-add-product (product display &rest plist)
2681 "Add support for a database product in `sql-mode'.
2683 Add PRODUCT to `sql-product-alist' which enables `sql-mode' to
2684 properly support syntax highlighting and interactive interaction.
2685 DISPLAY is the name of the SQL product that will appear in the
2686 menu bar and in messages. PLIST initializes the product
2687 configuration."
2689 ;; Don't do anything if the product is already supported
2690 (if (assoc product sql-product-alist)
2691 (user-error "Product `%s' is already defined" product)
2693 ;; Add product to the alist
2694 (add-to-list 'sql-product-alist `(,product :name ,display . ,plist))
2695 ;; Add a menu item to the SQL->Product menu
2696 (easy-menu-add-item sql-mode-menu '("Product")
2697 ;; Each product is represented by a radio
2698 ;; button with it's display name.
2699 `[,display
2700 (sql-set-product ',product)
2701 :style radio
2702 :selected (eq sql-product ',product)]
2703 ;; Maintain the product list in
2704 ;; (case-insensitive) alphabetic order of the
2705 ;; display names. Loop thru each keymap item
2706 ;; looking for an item whose display name is
2707 ;; after this product's name.
2708 (let ((next-item)
2709 (down-display (downcase display)))
2710 (map-keymap (lambda (k b)
2711 (when (and (not next-item)
2712 (string-lessp down-display
2713 (downcase (cadr b))))
2714 (setq next-item k)))
2715 (easy-menu-get-map sql-mode-menu '("Product")))
2716 next-item))
2717 product))
2719 (defun sql-del-product (product)
2720 "Remove support for PRODUCT in `sql-mode'."
2722 ;; Remove the menu item based on the display name
2723 (easy-menu-remove-item sql-mode-menu '("Product") (sql-get-product-feature product :name))
2724 ;; Remove the product alist item
2725 (setq sql-product-alist (assq-delete-all product sql-product-alist))
2726 nil)
2728 (defun sql-set-product-feature (product feature newvalue)
2729 "Set FEATURE of database PRODUCT to NEWVALUE.
2731 The PRODUCT must be a symbol which identifies the database
2732 product. The product must have already exist on the product
2733 list. See `sql-add-product' to add new products. The FEATURE
2734 argument must be a plist keyword accepted by
2735 `sql-product-alist'."
2737 (let* ((p (assoc product sql-product-alist)) ;; (PRODUCT :f v ...)
2738 (v (plist-member (cdr p) feature))) ;; (:FEATURE value ...) or null
2740 (if p
2741 (if (member feature sql-indirect-features) ; is indirect
2742 (if v
2743 (if (car (cdr v))
2744 (if (symbolp (car (cdr v)))
2745 ;; Indirect reference
2746 (set (car (cdr v)) newvalue)
2747 ;; indirect is not a symbol
2748 (error "The value of `%s' for `%s' is not a symbol" feature product))
2749 ;; keyword present, set the indirect variable name
2750 (if (symbolp newvalue)
2751 (if (cdr v)
2752 (setf (car (cdr v)) newvalue)
2753 (setf (cdr v) (list newvalue)))
2754 (error "The indirect variable of `%s' for `%s' must be a symbol" feature product)))
2755 ;; not present; insert list
2756 (setq v (list feature newvalue))
2757 (setf (cdr (cdr v)) (cdr p))
2758 (setf (cdr p) v))
2759 ;; Not an indirect feature
2760 (if v
2761 (if (cdr v)
2762 (setf (car (cdr v)) newvalue)
2763 (setf (cdr v) (list newvalue)))
2764 ;; no value; insert into the list
2765 (setq v (list feature newvalue))
2766 (setf (cdr (cdr v)) (cdr p))
2767 (setf (cdr p) v)))
2768 (error "`%s' is not a known product; use `sql-add-product' to add it first" product))))
2770 (defun sql-get-product-feature (product feature &optional fallback not-indirect)
2771 "Lookup FEATURE associated with a SQL PRODUCT.
2773 If the FEATURE is nil for PRODUCT, and FALLBACK is specified,
2774 then the FEATURE associated with the FALLBACK product is
2775 returned.
2777 If the FEATURE is in the list `sql-indirect-features', and the
2778 NOT-INDIRECT parameter is not set, then the value of the symbol
2779 stored in the connect alist is returned.
2781 See `sql-product-alist' for a list of products and supported features."
2782 (let* ((p (assoc product sql-product-alist))
2783 (v (plist-get (cdr p) feature)))
2785 (if p
2786 ;; If no value and fallback, lookup feature for fallback
2787 (if (and (not v)
2788 fallback
2789 (not (eq product fallback)))
2790 (sql-get-product-feature fallback feature)
2792 (if (and
2793 (member feature sql-indirect-features)
2794 (not not-indirect)
2795 (symbolp v))
2796 (symbol-value v)
2798 (error "`%s' is not a known product; use `sql-add-product' to add it first." product)
2799 nil)))
2801 (defun sql-product-font-lock (keywords-only imenu)
2802 "Configure font-lock and imenu with product-specific settings.
2804 The KEYWORDS-ONLY flag is passed to font-lock to specify whether
2805 only keywords should be highlighted and syntactic highlighting
2806 skipped. The IMENU flag indicates whether `imenu' should also be
2807 configured."
2809 (let
2810 ;; Get the product-specific syntax-alist.
2811 ((syntax-alist (sql-product-font-lock-syntax-alist)))
2813 ;; Get the product-specific keywords.
2814 (setq-local sql-mode-font-lock-keywords
2815 (append
2816 (unless (eq sql-product 'ansi)
2817 (sql-get-product-feature sql-product :font-lock))
2818 ;; Always highlight ANSI keywords
2819 (sql-get-product-feature 'ansi :font-lock)
2820 ;; Fontify object names in CREATE, DROP and ALTER DDL
2821 ;; statements
2822 (list sql-mode-font-lock-object-name)))
2824 ;; Setup font-lock. Force re-parsing of `font-lock-defaults'.
2825 (kill-local-variable 'font-lock-set-defaults)
2826 (setq-local font-lock-defaults
2827 (list 'sql-mode-font-lock-keywords
2828 keywords-only t syntax-alist))
2830 ;; Force font lock to reinitialize if it is already on
2831 ;; Otherwise, we can wait until it can be started.
2832 (when font-lock-mode
2833 (font-lock-mode-internal nil)
2834 (font-lock-mode-internal t))
2836 (add-hook 'font-lock-mode-hook
2837 (lambda ()
2838 ;; Provide defaults for new font-lock faces.
2839 (defvar font-lock-builtin-face
2840 (if (boundp 'font-lock-preprocessor-face)
2841 font-lock-preprocessor-face
2842 font-lock-keyword-face))
2843 (defvar font-lock-doc-face font-lock-string-face))
2844 nil t)
2846 ;; Setup imenu; it needs the same syntax-alist.
2847 (when imenu
2848 (setq imenu-syntax-alist syntax-alist))))
2850 ;;;###autoload
2851 (defun sql-add-product-keywords (product keywords &optional append)
2852 "Add highlighting KEYWORDS for SQL PRODUCT.
2854 PRODUCT should be a symbol, the name of a SQL product, such as
2855 `oracle'. KEYWORDS should be a list; see the variable
2856 `font-lock-keywords'. By default they are added at the beginning
2857 of the current highlighting list. If optional argument APPEND is
2858 `set', they are used to replace the current highlighting list.
2859 If APPEND is any other non-nil value, they are added at the end
2860 of the current highlighting list.
2862 For example:
2864 (sql-add-product-keywords \\='ms
2865 \\='((\"\\\\b\\\\w+_t\\\\b\" . font-lock-type-face)))
2867 adds a fontification pattern to fontify identifiers ending in
2868 `_t' as data types."
2870 (let* ((sql-indirect-features nil)
2871 (font-lock-var (sql-get-product-feature product :font-lock))
2872 (old-val))
2874 (setq old-val (symbol-value font-lock-var))
2875 (set font-lock-var
2876 (if (eq append 'set)
2877 keywords
2878 (if append
2879 (append old-val keywords)
2880 (append keywords old-val))))))
2882 (defun sql-for-each-login (login-params body)
2883 "Iterate through login parameters and return a list of results."
2884 (delq nil
2885 (mapcar
2886 (lambda (param)
2887 (let ((token (or (car-safe param) param))
2888 (plist (cdr-safe param)))
2889 (funcall body token plist)))
2890 login-params)))
2894 ;;; Functions to switch highlighting
2896 (defun sql-product-syntax-table ()
2897 (let ((table (copy-syntax-table sql-mode-syntax-table)))
2898 (mapc (lambda (entry)
2899 (modify-syntax-entry (car entry) (cdr entry) table))
2900 (sql-get-product-feature sql-product :syntax-alist))
2901 table))
2903 (defun sql-product-font-lock-syntax-alist ()
2904 (append
2905 ;; Change all symbol character to word characters
2906 (mapcar
2907 (lambda (entry) (if (string= (substring (cdr entry) 0 1) "_")
2908 (cons (car entry)
2909 (concat "w" (substring (cdr entry) 1)))
2910 entry))
2911 (sql-get-product-feature sql-product :syntax-alist))
2912 '((?_ . "w"))))
2914 (defun sql-highlight-product ()
2915 "Turn on the font highlighting for the SQL product selected."
2916 (when (derived-mode-p 'sql-mode)
2917 ;; Enhance the syntax table for the product
2918 (set-syntax-table (sql-product-syntax-table))
2920 ;; Setup font-lock
2921 (sql-product-font-lock nil t)
2923 ;; Set the mode name to include the product.
2924 (setq mode-name (concat "SQL[" (or (sql-get-product-feature sql-product :name)
2925 (symbol-name sql-product)) "]"))))
2927 (defun sql-set-product (product)
2928 "Set `sql-product' to PRODUCT and enable appropriate highlighting."
2929 (interactive
2930 (list (sql-read-product "SQL product: ")))
2931 (if (stringp product) (setq product (intern product)))
2932 (when (not (assoc product sql-product-alist))
2933 (user-error "SQL product %s is not supported; treated as ANSI" product)
2934 (setq product 'ansi))
2936 ;; Save product setting and fontify.
2937 (setq sql-product product)
2938 (sql-highlight-product))
2939 (defalias 'sql-set-dialect 'sql-set-product)
2941 (defun sql-buffer-hidden-p (buf)
2942 "Is the buffer hidden?"
2943 (string-prefix-p " "
2944 (cond
2945 ((stringp buf)
2946 (when (get-buffer buf)
2947 buf))
2948 ((bufferp buf)
2949 (buffer-name buf))
2950 (t nil))))
2952 (defun sql-display-buffer (buf)
2953 "Display a SQLi buffer based on `sql-display-sqli-buffer-function'.
2955 If BUF is hidden or `sql-display-sqli-buffer-function' is nil,
2956 then the buffer will not be displayed. Otherwise the BUF is
2957 displayed."
2958 (unless (sql-buffer-hidden-p buf)
2959 (cond
2960 ((eq sql-display-sqli-buffer-function t)
2961 (pop-to-buffer buf))
2962 ((not sql-display-sqli-buffer-function)
2963 nil)
2964 ((functionp sql-display-sqli-buffer-function)
2965 (funcall sql-display-sqli-buffer-function buf))
2967 (message "Invalid setting of `sql-display-sqli-buffer-function'")
2968 (pop-to-buffer buf)))))
2970 (defun sql-make-progress-reporter (buf message &optional min-value max-value current-value min-change min-time)
2971 "Make a progress reporter if BUF is not hidden."
2972 (unless (or (sql-buffer-hidden-p buf)
2973 (not sql-display-sqli-buffer-function))
2974 (make-progress-reporter message min-value max-value current-value min-change min-time)))
2976 (defun sql-progress-reporter-update (reporter &optional value)
2977 "Report progress of an operation in the echo area."
2978 (when reporter
2979 (progress-reporter-update reporter value)))
2981 (defun sql-progress-reporter-done (reporter)
2982 "Print reporter’s message followed by word \"done\" in echo area."
2983 (when reporter
2984 (progress-reporter-done reporter)))
2986 ;;; SMIE support
2988 ;; Needs a lot more love than I can provide. --Stef
2990 ;; (require 'smie)
2992 ;; (defconst sql-smie-grammar
2993 ;; (smie-prec2->grammar
2994 ;; (smie-bnf->prec2
2995 ;; ;; Partly based on https://www.h2database.com/html/grammar.html
2996 ;; '((cmd ("SELECT" select-exp "FROM" select-table-exp)
2997 ;; )
2998 ;; (select-exp ("*") (exp) (exp "AS" column-alias))
2999 ;; (column-alias)
3000 ;; (select-table-exp (table-exp "WHERE" exp) (table-exp))
3001 ;; (table-exp)
3002 ;; (exp ("CASE" exp "WHEN" exp "THEN" exp "ELSE" exp "END")
3003 ;; ("CASE" exp "WHEN" exp "THEN" exp "END"))
3004 ;; ;; Random ad-hoc additions.
3005 ;; (foo (foo "," foo))
3006 ;; )
3007 ;; '((assoc ",")))))
3009 ;; (defun sql-smie-rules (kind token)
3010 ;; (pcase (cons kind token)
3011 ;; (`(:list-intro . ,_) t)
3012 ;; (`(:before . "(") (smie-rule-parent))))
3014 ;;; Motion Functions
3016 (defun sql-statement-regexp (prod)
3017 (let* ((ansi-stmt (or (sql-get-product-feature 'ansi :statement) "select"))
3018 (prod-stmt (sql-get-product-feature prod :statement)))
3019 (concat "^\\<"
3020 (if prod-stmt
3021 (concat "\\(" ansi-stmt "\\|" prod-stmt "\\)")
3022 ansi-stmt)
3023 "\\>")))
3025 (defun sql-beginning-of-statement (arg)
3026 "Move to the beginning of the current SQL statement."
3027 (interactive "p")
3029 (let ((here (point))
3030 (regexp (sql-statement-regexp sql-product))
3031 last next)
3033 ;; Go to the end of the statement before the start we desire
3034 (setq last (or (sql-end-of-statement (- arg))
3035 (point-min)))
3036 ;; And find the end after that
3037 (setq next (or (sql-end-of-statement 1)
3038 (point-max)))
3040 ;; Our start must be between them
3041 (goto-char last)
3042 ;; Find a beginning-of-stmt that's not in a comment
3043 (while (and (re-search-forward regexp next t 1)
3044 (nth 7 (syntax-ppss)))
3045 (goto-char (match-end 0)))
3046 (goto-char
3047 (if (match-data)
3048 (match-beginning 0)
3049 last))
3050 (beginning-of-line)
3051 ;; If we didn't move, try again
3052 (when (= here (point))
3053 (sql-beginning-of-statement (* 2 (cl-signum arg))))))
3055 (defun sql-end-of-statement (arg)
3056 "Move to the end of the current SQL statement."
3057 (interactive "p")
3058 (let ((term (or (sql-get-product-feature sql-product :terminator) ";"))
3059 (re-search (if (> 0 arg) 're-search-backward 're-search-forward))
3060 (here (point))
3061 (n 0))
3062 (when (consp term)
3063 (setq term (car term)))
3064 ;; Iterate until we've moved the desired number of stmt ends
3065 (while (not (= (cl-signum arg) 0))
3066 ;; if we're looking at the terminator, jump by 2
3067 (if (or (and (> 0 arg) (looking-back term nil))
3068 (and (< 0 arg) (looking-at term)))
3069 (setq n 2)
3070 (setq n 1))
3071 ;; If we found another end-of-stmt
3072 (if (not (apply re-search term nil t n nil))
3073 (setq arg 0)
3074 ;; count it if we're not in a comment
3075 (unless (nth 7 (syntax-ppss))
3076 (setq arg (- arg (cl-signum arg))))))
3077 (goto-char (if (match-data)
3078 (match-end 0)
3079 here))))
3081 ;;; Small functions
3083 (defun sql-magic-go (arg)
3084 "Insert \"o\" and call `comint-send-input'.
3085 `sql-electric-stuff' must be the symbol `go'."
3086 (interactive "P")
3087 (self-insert-command (prefix-numeric-value arg))
3088 (if (and (equal sql-electric-stuff 'go)
3089 (save-excursion
3090 (comint-bol nil)
3091 (looking-at "go\\b")))
3092 (comint-send-input)))
3093 (put 'sql-magic-go 'delete-selection t)
3095 (defun sql-magic-semicolon (arg)
3096 "Insert semicolon and call `comint-send-input'.
3097 `sql-electric-stuff' must be the symbol `semicolon'."
3098 (interactive "P")
3099 (self-insert-command (prefix-numeric-value arg))
3100 (if (equal sql-electric-stuff 'semicolon)
3101 (comint-send-input)))
3102 (put 'sql-magic-semicolon 'delete-selection t)
3104 (defun sql-accumulate-and-indent ()
3105 "Continue SQL statement on the next line."
3106 (interactive)
3107 (if (fboundp 'comint-accumulate)
3108 (comint-accumulate)
3109 (newline))
3110 (indent-according-to-mode))
3112 (defun sql-help-list-products (indent freep)
3113 "Generate listing of products available for use under SQLi.
3115 List products with :free-software attribute set to FREEP. Indent
3116 each line with INDENT."
3118 (let (sqli-func doc)
3119 (setq doc "")
3120 (dolist (p sql-product-alist)
3121 (setq sqli-func (intern (concat "sql-" (symbol-name (car p)))))
3123 (if (and (fboundp sqli-func)
3124 (eq (sql-get-product-feature (car p) :free-software) freep))
3125 (setq doc
3126 (concat doc
3127 indent
3128 (or (sql-get-product-feature (car p) :name)
3129 (symbol-name (car p)))
3130 ":\t"
3131 "\\["
3132 (symbol-name sqli-func)
3133 "]\n"))))
3134 doc))
3136 (defun sql-help ()
3137 "Show short help for the SQL modes."
3138 (interactive)
3139 (describe-function 'sql-help))
3140 (put 'sql-help 'function-documentation '(sql--make-help-docstring))
3142 (defvar sql--help-docstring
3143 "Show short help for the SQL modes.
3144 Use an entry function to open an interactive SQL buffer. This buffer is
3145 usually named `*SQL*'. The name of the major mode is SQLi.
3147 Use the following commands to start a specific SQL interpreter:
3149 \\\\FREE
3151 Other non-free SQL implementations are also supported:
3153 \\\\NONFREE
3155 But we urge you to choose a free implementation instead of these.
3157 You can also use \\[sql-product-interactive] to invoke the
3158 interpreter for the current `sql-product'.
3160 Once you have the SQLi buffer, you can enter SQL statements in the
3161 buffer. The output generated is appended to the buffer and a new prompt
3162 is generated. See the In/Out menu in the SQLi buffer for some functions
3163 that help you navigate through the buffer, the input history, etc.
3165 If you have a really complex SQL statement or if you are writing a
3166 procedure, you can do this in a separate buffer. Put the new buffer in
3167 `sql-mode' by calling \\[sql-mode]. The name of this buffer can be
3168 anything. The name of the major mode is SQL.
3170 In this SQL buffer (SQL mode), you can send the region or the entire
3171 buffer to the interactive SQL buffer (SQLi mode). The results are
3172 appended to the SQLi buffer without disturbing your SQL buffer.")
3174 (defun sql--make-help-docstring ()
3175 "Return a docstring for `sql-help' listing loaded SQL products."
3176 (let ((doc sql--help-docstring))
3177 ;; Insert FREE software list
3178 (when (string-match "^\\(\\s-*\\)[\\][\\]FREE\\s-*$" doc 0)
3179 (setq doc (replace-match (sql-help-list-products (match-string 1 doc) t)
3180 t t doc 0)))
3181 ;; Insert non-FREE software list
3182 (when (string-match "^\\(\\s-*\\)[\\][\\]NONFREE\\s-*$" doc 0)
3183 (setq doc (replace-match (sql-help-list-products (match-string 1 doc) nil)
3184 t t doc 0)))
3185 doc))
3187 (defun sql-default-value (var)
3188 "Fetch the value of a variable.
3190 If the current buffer is in `sql-interactive-mode', then fetch
3191 the global value, otherwise use the buffer local value."
3192 (if (derived-mode-p 'sql-interactive-mode)
3193 (default-value var)
3194 (buffer-local-value var (current-buffer))))
3196 (defun sql-get-login-ext (symbol prompt history-var plist)
3197 "Prompt user with extended login parameters.
3199 The global value of SYMBOL is the last value and the global value
3200 of the SYMBOL is set based on the user's input.
3202 If PLIST is nil, then the user is simply prompted for a string
3203 value.
3205 The property `:default' specifies the default value. If the
3206 `:number' property is non-nil then ask for a number.
3208 The `:file' property prompts for a file name that must match the
3209 regexp pattern specified in its value.
3211 The `:completion' property prompts for a string specified by its
3212 value. (The property value is used as the PREDICATE argument to
3213 `completing-read'.)
3215 For both `:file' and `:completion', there can also be a
3216 `:must-match' property that controls REQUIRE-MATCH parameter to
3217 `completing-read'."
3219 (set-default
3220 symbol
3221 (let* ((default (plist-get plist :default))
3222 (last-value (sql-default-value symbol))
3223 (prompt-def
3224 (if default
3225 (if (string-match "\\(\\):[ \t]*\\'" prompt)
3226 (replace-match (format " (default \"%s\")" default) t t prompt 1)
3227 (replace-regexp-in-string "[ \t]*\\'"
3228 (format " (default \"%s\") " default)
3229 prompt t t))
3230 prompt))
3231 (use-dialog-box nil))
3232 (cond
3233 ((plist-member plist :file)
3234 (let ((file-name
3235 (read-file-name prompt
3236 (file-name-directory last-value)
3237 default
3238 (if (plist-member plist :must-match)
3239 (plist-get plist :must-match)
3241 (file-name-nondirectory last-value)
3242 (when (plist-get plist :file)
3243 `(lambda (f)
3244 (if (not (file-regular-p f))
3246 (string-match
3247 (concat "\\<" ,(plist-get plist :file) "\\>")
3248 (file-name-nondirectory f))))))))
3249 (if (string= file-name "")
3251 (expand-file-name file-name))))
3253 ((plist-member plist :completion)
3254 (completing-read prompt-def
3255 (plist-get plist :completion)
3257 (if (plist-member plist :must-match)
3258 (plist-get plist :must-match)
3260 last-value
3261 history-var
3262 default))
3264 ((plist-get plist :number)
3265 (read-number prompt (or default last-value 0)))
3268 (read-string prompt-def last-value history-var default))))))
3270 (defun sql-get-login (&rest what)
3271 "Get username, password and database from the user.
3273 The variables `sql-user', `sql-password', `sql-server', and
3274 `sql-database' can be customized. They are used as the default values.
3275 Usernames, servers and databases are stored in `sql-user-history',
3276 `sql-server-history' and `database-history'. Passwords are not stored
3277 in a history.
3279 Parameter WHAT is a list of tokens passed as arguments in the
3280 function call. The function asks for the username if WHAT
3281 contains the symbol `user', for the password if it contains the
3282 symbol `password', for the server if it contains the symbol
3283 `server', and for the database if it contains the symbol
3284 `database'. The members of WHAT are processed in the order in
3285 which they are provided.
3287 If the `sql-password-wallet' is non-nil and WHAT contains the
3288 `password' token, then the `password' token will be pushed to the
3289 end to be sure that all of the values can be fed to the wallet.
3291 Each token may also be a list with the token in the car and a
3292 plist of options as the cdr. The following properties are
3293 supported:
3295 :file <filename-regexp>
3296 :completion <list-of-strings-or-function>
3297 :default <default-value>
3298 :number t
3300 In order to ask the user for username, password and database, call the
3301 function like this: (sql-get-login \\='user \\='password \\='database)."
3303 ;; Push the password to the end if we have a wallet
3304 (when (and sql-password-wallet
3305 (fboundp sql-password-search-wallet-function)
3306 (member 'password what))
3307 (setq what (append (cl-delete 'password what)
3308 '(password))))
3310 ;; Prompt for each parameter
3311 (dolist (w what)
3312 (let ((plist (cdr-safe w)))
3313 (pcase (or (car-safe w) w)
3314 ('user
3315 (sql-get-login-ext 'sql-user "User: " 'sql-user-history plist))
3317 ('password
3318 (setq-default sql-password
3319 (if (and sql-password-wallet
3320 (fboundp sql-password-search-wallet-function))
3321 (let ((password (funcall sql-password-search-wallet-function
3322 sql-password-wallet
3323 sql-product
3324 sql-user
3325 sql-server
3326 sql-database
3327 sql-port)))
3328 (if password
3329 password
3330 (read-passwd "Password: " nil (sql-default-value 'sql-password))))
3331 (read-passwd "Password: " nil (sql-default-value 'sql-password)))))
3333 ('server
3334 (sql-get-login-ext 'sql-server "Server: " 'sql-server-history plist))
3336 ('database
3337 (sql-get-login-ext 'sql-database "Database: "
3338 'sql-database-history plist))
3340 ('port
3341 (sql-get-login-ext 'sql-port "Port: "
3342 nil (append '(:number t) plist)))))))
3344 (defun sql-find-sqli-buffer (&optional product connection)
3345 "Return the name of the current default SQLi buffer or nil.
3346 In order to qualify, the SQLi buffer must be alive, be in
3347 `sql-interactive-mode' and have a process."
3348 (let ((buf sql-buffer)
3349 (prod (or product sql-product)))
3351 ;; Current sql-buffer, if there is one.
3352 (and (sql-buffer-live-p buf prod connection)
3353 buf)
3354 ;; Global sql-buffer
3355 (and (setq buf (default-value 'sql-buffer))
3356 (sql-buffer-live-p buf prod connection)
3357 buf)
3358 ;; Look thru each buffer
3359 (car (apply #'append
3360 (mapcar (lambda (b)
3361 (and (sql-buffer-live-p b prod connection)
3362 (list (buffer-name b))))
3363 (buffer-list)))))))
3365 (defun sql-set-sqli-buffer-generally ()
3366 "Set SQLi buffer for all SQL buffers that have none.
3367 This function checks all SQL buffers for their SQLi buffer. If their
3368 SQLi buffer is nonexistent or has no process, it is set to the current
3369 default SQLi buffer. The current default SQLi buffer is determined
3370 using `sql-find-sqli-buffer'. If `sql-buffer' is set,
3371 `sql-set-sqli-hook' is run."
3372 (interactive)
3373 (save-excursion
3374 (let ((buflist (buffer-list))
3375 (default-buffer (sql-find-sqli-buffer)))
3376 (setq-default sql-buffer default-buffer)
3377 (while (not (null buflist))
3378 (let ((candidate (car buflist)))
3379 (set-buffer candidate)
3380 (if (and (derived-mode-p 'sql-mode)
3381 (not (sql-buffer-live-p sql-buffer)))
3382 (progn
3383 (setq sql-buffer default-buffer)
3384 (when default-buffer
3385 (run-hooks 'sql-set-sqli-hook)))))
3386 (setq buflist (cdr buflist))))))
3388 (defun sql-set-sqli-buffer ()
3389 "Set the SQLi buffer SQL strings are sent to.
3391 Call this function in a SQL buffer in order to set the SQLi buffer SQL
3392 strings are sent to. Calling this function sets `sql-buffer' and runs
3393 `sql-set-sqli-hook'.
3395 If you call it from a SQL buffer, this sets the local copy of
3396 `sql-buffer'.
3398 If you call it from anywhere else, it sets the global copy of
3399 `sql-buffer'."
3400 (interactive)
3401 (let ((default-buffer (sql-find-sqli-buffer)))
3402 (if (null default-buffer)
3403 (sql-product-interactive)
3404 (let ((new-buffer (read-buffer "New SQLi buffer: " default-buffer t)))
3405 (if (null (sql-buffer-live-p new-buffer))
3406 (user-error "Buffer %s is not a working SQLi buffer" new-buffer)
3407 (when new-buffer
3408 (setq sql-buffer new-buffer)
3409 (run-hooks 'sql-set-sqli-hook)))))))
3411 (defun sql-show-sqli-buffer ()
3412 "Display the current SQLi buffer.
3414 This is the buffer SQL strings are sent to.
3415 It is stored in the variable `sql-buffer'.
3417 See also `sql-help' on how to create such a buffer."
3418 (interactive)
3419 (unless (and sql-buffer (buffer-live-p (get-buffer sql-buffer))
3420 (get-buffer-process sql-buffer))
3421 (sql-set-sqli-buffer))
3422 (display-buffer sql-buffer))
3424 (defun sql-make-alternate-buffer-name (&optional product)
3425 "Return a string that can be used to rename a SQLi buffer.
3426 This is used to set `sql-alternate-buffer-name' within
3427 `sql-interactive-mode'.
3429 If the session was started with `sql-connect' then the alternate
3430 name would be the name of the connection.
3432 Otherwise, it uses the parameters identified by the :sqlilogin
3433 parameter.
3435 If all else fails, the alternate name would be the user and
3436 server/database name."
3438 (let ((name ""))
3440 ;; Build a name using the :sqli-login setting
3441 (setq name
3442 (apply #'concat
3443 (cdr
3444 (apply #'append nil
3445 (sql-for-each-login
3446 (sql-get-product-feature (or product sql-product) :sqli-login)
3447 (lambda (token plist)
3448 (pcase token
3449 ('user
3450 (unless (string= "" sql-user)
3451 (list "/" sql-user)))
3452 ('port
3453 (unless (or (not (numberp sql-port))
3454 (= 0 sql-port))
3455 (list ":" (number-to-string sql-port))))
3456 ('server
3457 (unless (string= "" sql-server)
3458 (list "."
3459 (if (plist-member plist :file)
3460 (file-name-nondirectory sql-server)
3461 sql-server))))
3462 ('database
3463 (unless (string= "" sql-database)
3464 (list "@"
3465 (if (plist-member plist :file)
3466 (file-name-nondirectory sql-database)
3467 sql-database))))
3469 ;; (`password nil)
3470 (_ nil))))))))
3472 ;; If there's a connection, use it and the name thus far
3473 (if sql-connection
3474 (format "<%s>%s" sql-connection (or name ""))
3476 ;; If there is no name, try to create something meaningful
3477 (if (string= "" (or name ""))
3478 (concat
3479 (if (string= "" sql-user)
3480 (if (string= "" (user-login-name))
3482 (concat (user-login-name) "/"))
3483 (concat sql-user "/"))
3484 (if (string= "" sql-database)
3485 (if (string= "" sql-server)
3486 (system-name)
3487 sql-server)
3488 sql-database))
3490 ;; Use the name we've got
3491 name))))
3493 (defun sql-generate-unique-sqli-buffer-name (product base)
3494 "Generate a new, unique buffer name for a SQLi buffer.
3496 Append a sequence number until a unique name is found."
3497 (let ((base-name (substring-no-properties
3498 (if base
3499 (if (stringp base)
3500 base
3501 (format "%S" base))
3502 (or (sql-get-product-feature product :name)
3503 (symbol-name product)))))
3504 buf-fmt-1st
3505 buf-fmt-rest)
3507 ;; Calculate buffer format
3508 (if (string-blank-p base-name)
3509 (setq buf-fmt-1st "*SQL*"
3510 buf-fmt-rest "*SQL-%d*")
3511 (setq buf-fmt-1st (format "*SQL: %s*" base-name)
3512 buf-fmt-rest (format "*SQL: %s-%%d*" base-name)))
3514 ;; See if we can find an unused buffer
3515 (let ((buf-name buf-fmt-1st)
3516 (i 1))
3517 (while (if (sql-is-sqli-buffer-p buf-name)
3518 (comint-check-proc buf-name)
3519 (buffer-live-p (get-buffer buf-name)))
3520 ;; Check a sequence number on the BASE
3521 (setq buf-name (format buf-fmt-rest i)
3522 i (1+ i)))
3524 buf-name)))
3526 (defun sql-rename-buffer (&optional new-name)
3527 "Rename a SQL interactive buffer.
3529 Prompts for the new name if command is preceded by
3530 \\[universal-argument]. If no buffer name is provided, then the
3531 `sql-alternate-buffer-name' is used.
3533 The actual buffer name set will be \"*SQL: NEW-NAME*\". If
3534 NEW-NAME is empty, then the buffer name will be \"*SQL*\"."
3535 (interactive "P")
3537 (if (not (derived-mode-p 'sql-interactive-mode))
3538 (user-error "Current buffer is not a SQL interactive buffer")
3540 (setq sql-alternate-buffer-name
3541 (substring-no-properties
3542 (cond
3543 ((stringp new-name)
3544 new-name)
3545 ((consp new-name)
3546 (read-string "Buffer name (\"*SQL: XXX*\"; enter `XXX'): "
3547 sql-alternate-buffer-name))
3549 sql-alternate-buffer-name))))
3551 (rename-buffer
3552 (sql-generate-unique-sqli-buffer-name sql-product
3553 sql-alternate-buffer-name)
3554 t)))
3556 (defun sql-copy-column ()
3557 "Copy current column to the end of buffer.
3558 Inserts SELECT or commas if appropriate."
3559 (interactive)
3560 (let ((column))
3561 (save-excursion
3562 (setq column (buffer-substring-no-properties
3563 (progn (forward-char 1) (backward-sexp 1) (point))
3564 (progn (forward-sexp 1) (point))))
3565 (goto-char (point-max))
3566 (let ((bol (comint-line-beginning-position)))
3567 (cond
3568 ;; if empty command line, insert SELECT
3569 ((= bol (point))
3570 (insert "SELECT "))
3571 ;; else if appending to INTO .* (, SELECT or ORDER BY, insert a comma
3572 ((save-excursion
3573 (re-search-backward "\\b\\(\\(into\\s-+\\S-+\\s-+(\\)\\|select\\|order by\\) .+"
3574 bol t))
3575 (insert ", "))
3576 ;; else insert a space
3578 (if (eq (preceding-char) ?\s)
3580 (insert " ")))))
3581 ;; in any case, insert the column
3582 (insert column)
3583 (message "%s" column))))
3585 ;; On Windows, SQL*Plus for Oracle turns on full buffering for stdout
3586 ;; if it is not attached to a character device; therefore placeholder
3587 ;; replacement by SQL*Plus is fully buffered. The workaround lets
3588 ;; Emacs query for the placeholders.
3590 (defvar sql-placeholder-history nil
3591 "History of placeholder values used.")
3593 (defun sql-placeholders-filter (string)
3594 "Replace placeholders in STRING.
3595 Placeholders are words starting with an ampersand like &this."
3597 (when sql-oracle-scan-on
3598 (let ((start 0)
3599 (replacement ""))
3600 (while (string-match "&?&\\(\\(?:\\sw\\|\\s_\\)+\\)[.]?" string start)
3601 (setq replacement (read-from-minibuffer
3602 (format "Enter value for %s: "
3603 (propertize (match-string 1 string)
3604 'face 'font-lock-variable-name-face))
3605 nil nil nil 'sql-placeholder-history)
3606 string (replace-match replacement t t string)
3607 start (+ (match-beginning 1) (length replacement))))))
3608 string)
3610 ;; Using DB2 interactively, newlines must be escaped with " \".
3611 ;; The space before the backslash is relevant.
3613 (defun sql-escape-newlines-filter (string)
3614 "Escape newlines in STRING.
3615 Every newline in STRING will be preceded with a space and a backslash."
3616 (if (not sql-db2-escape-newlines)
3617 string
3618 (let ((result "") (start 0) mb me)
3619 (while (string-match "\n" string start)
3620 (setq mb (match-beginning 0)
3621 me (match-end 0)
3622 result (concat result
3623 (substring string start mb)
3624 (if (and (> mb 1)
3625 (string-equal " \\" (substring string (- mb 2) mb)))
3626 "" " \\\n"))
3627 start me))
3628 (concat result (substring string start)))))
3632 ;;; Input sender for SQLi buffers
3634 (defvar sql-output-newline-count 0
3635 "Number of newlines in the input string.
3637 Allows the suppression of continuation prompts.")
3639 (defun sql-input-sender (proc string)
3640 "Send STRING to PROC after applying filters."
3642 (let* ((product (buffer-local-value 'sql-product (process-buffer proc)))
3643 (filter (sql-get-product-feature product :input-filter)))
3645 ;; Apply filter(s)
3646 (cond
3647 ((not filter)
3648 nil)
3649 ((functionp filter)
3650 (setq string (funcall filter string)))
3651 ((listp filter)
3652 (mapc (lambda (f) (setq string (funcall f string))) filter))
3653 (t nil))
3655 ;; Count how many newlines in the string
3656 (setq sql-output-newline-count
3657 (apply #'+ (mapcar (lambda (ch) (if (eq ch ?\n) 1 0))
3658 string)))
3660 ;; Send the string
3661 (comint-simple-send proc string)))
3663 ;;; Strip out continuation prompts
3665 (defvar sql-preoutput-hold nil)
3667 (defun sql-starts-with-prompt-re ()
3668 "Anchor the prompt expression at the beginning of the output line.
3669 Remove the start of line regexp."
3670 (concat "\\`" comint-prompt-regexp))
3672 (defun sql-ends-with-prompt-re ()
3673 "Anchor the prompt expression at the end of the output line.
3674 Match a SQL prompt or a password prompt."
3675 (concat "\\(?:\\(?:" sql-prompt-regexp "\\)\\|"
3676 "\\(?:" comint-password-prompt-regexp "\\)\\)\\'"))
3678 (defun sql-interactive-remove-continuation-prompt (oline)
3679 "Strip out continuation prompts out of the OLINE.
3681 Added to the `comint-preoutput-filter-functions' hook in a SQL
3682 interactive buffer. If `sql-output-newline-count' is greater than
3683 zero, then an output line matching the continuation prompt is filtered
3684 out. If the count is zero, then a newline is inserted into the output
3685 to force the output from the query to appear on a new line.
3687 The complication to this filter is that the continuation prompts
3688 may arrive in multiple chunks. If they do, then the function
3689 saves any unfiltered output in a buffer and prepends that buffer
3690 to the next chunk to properly match the broken-up prompt.
3692 If the filter gets confused, it should reset and stop filtering
3693 to avoid deleting non-prompt output."
3695 ;; continue gathering lines of text iff
3696 ;; + we know what a prompt looks like, and
3697 ;; + there is held text, or
3698 ;; + there are continuation prompt yet to come, or
3699 ;; + not just a prompt string
3700 (when (and comint-prompt-regexp
3701 (or (> (length (or sql-preoutput-hold "")) 0)
3702 (> (or sql-output-newline-count 0) 0)
3703 (not (or (string-match sql-prompt-regexp oline)
3704 (and sql-prompt-cont-regexp
3705 (string-match sql-prompt-cont-regexp oline))))))
3707 (save-match-data
3708 (let (prompt-found last-nl)
3710 ;; Add this text to what's left from the last pass
3711 (setq oline (concat sql-preoutput-hold oline)
3712 sql-preoutput-hold "")
3714 ;; If we are looking for multiple prompts
3715 (when (and (integerp sql-output-newline-count)
3716 (>= sql-output-newline-count 1))
3717 ;; Loop thru each starting prompt and remove it
3718 (let ((start-re (sql-starts-with-prompt-re)))
3719 (while (and (not (string= oline ""))
3720 (> sql-output-newline-count 0)
3721 (string-match start-re oline))
3722 (setq oline (replace-match "" nil nil oline)
3723 sql-output-newline-count (1- sql-output-newline-count)
3724 prompt-found t)))
3726 ;; If we've found all the expected prompts, stop looking
3727 (if (= sql-output-newline-count 0)
3728 (setq sql-output-newline-count nil
3729 oline (concat "\n" oline))
3731 ;; Still more possible prompts, leave them for the next pass
3732 (setq sql-preoutput-hold oline
3733 oline "")))
3735 ;; If no prompts were found, stop looking
3736 (unless prompt-found
3737 (setq sql-output-newline-count nil
3738 oline (concat oline sql-preoutput-hold)
3739 sql-preoutput-hold ""))
3741 ;; Break up output by physical lines if we haven't hit the final prompt
3742 (let ((end-re (sql-ends-with-prompt-re)))
3743 (unless (and (not (string= oline ""))
3744 (string-match end-re oline)
3745 (>= (match-end 0) (length oline)))
3746 ;; Find everything upto the last nl
3747 (setq last-nl 0)
3748 (while (string-match "\n" oline last-nl)
3749 (setq last-nl (match-end 0)))
3750 ;; Hold after the last nl, return upto last nl
3751 (setq sql-preoutput-hold (concat (substring oline last-nl)
3752 sql-preoutput-hold)
3753 oline (substring oline 0 last-nl)))))))
3754 oline)
3756 ;;; Sending the region to the SQLi buffer.
3757 (defvar sql-debug-send nil
3758 "Display text sent to SQL process pragmatically.")
3760 (defun sql-send-string (str)
3761 "Send the string STR to the SQL process."
3762 (interactive "sSQL Text: ")
3764 (let ((comint-input-sender-no-newline nil)
3765 (s (replace-regexp-in-string "[[:space:]\n\r]+\\'" "" str)))
3766 (if (sql-buffer-live-p sql-buffer)
3767 (progn
3768 ;; Ignore the hoping around...
3769 (save-excursion
3770 ;; Set product context
3771 (with-current-buffer sql-buffer
3772 (when sql-debug-send
3773 (message ">>SQL> %S" s))
3775 ;; Send the string (trim the trailing whitespace)
3776 (sql-input-sender (get-buffer-process (current-buffer)) s)
3778 ;; Send a command terminator if we must
3779 (sql-send-magic-terminator sql-buffer s sql-send-terminator)
3781 (when sql-pop-to-buffer-after-send-region
3782 (message "Sent string to buffer %s" sql-buffer))))
3784 ;; Display the sql buffer
3785 (sql-display-buffer sql-buffer))
3787 ;; We don't have no stinkin' sql
3788 (user-error "No SQL process started"))))
3790 (defun sql-send-region (start end)
3791 "Send a region to the SQL process."
3792 (interactive "r")
3793 (sql-send-string (buffer-substring-no-properties start end)))
3795 (defun sql-send-paragraph ()
3796 "Send the current paragraph to the SQL process."
3797 (interactive)
3798 (let ((start (save-excursion
3799 (backward-paragraph)
3800 (point)))
3801 (end (save-excursion
3802 (forward-paragraph)
3803 (point))))
3804 (sql-send-region start end)))
3806 (defun sql-send-buffer ()
3807 "Send the buffer contents to the SQL process."
3808 (interactive)
3809 (sql-send-region (point-min) (point-max)))
3811 (defun sql-send-line-and-next ()
3812 "Send the current line to the SQL process and go to the next line."
3813 (interactive)
3814 (sql-send-region (line-beginning-position 1) (line-beginning-position 2))
3815 (beginning-of-line 2)
3816 (while (forward-comment 1))) ; skip all comments and whitespace
3818 (defun sql-send-magic-terminator (buf str terminator)
3819 "Send TERMINATOR to buffer BUF if its not present in STR."
3820 (let (comint-input-sender-no-newline pat term)
3821 ;; If flag is merely on(t), get product-specific terminator
3822 (if (eq terminator t)
3823 (setq terminator (sql-get-product-feature sql-product :terminator)))
3825 ;; If there is no terminator specified, use default ";"
3826 (unless terminator
3827 (setq terminator ";"))
3829 ;; Parse the setting into the pattern and the terminator string
3830 (cond ((stringp terminator)
3831 (setq pat (regexp-quote terminator)
3832 term terminator))
3833 ((consp terminator)
3834 (setq pat (car terminator)
3835 term (cdr terminator)))
3837 nil))
3839 ;; Check to see if the pattern is present in the str already sent
3840 (unless (and pat term
3841 (string-match-p (concat pat "\\'") str))
3842 (sql-input-sender (get-buffer-process buf) term))))
3844 (defun sql-remove-tabs-filter (str)
3845 "Replace tab characters with spaces."
3846 (replace-regexp-in-string "\t" " " str nil t))
3848 (defun sql-toggle-pop-to-buffer-after-send-region (&optional value)
3849 "Toggle `sql-pop-to-buffer-after-send-region'.
3851 If given the optional parameter VALUE, sets
3852 `sql-toggle-pop-to-buffer-after-send-region' to VALUE."
3853 (interactive "P")
3854 (if value
3855 (setq sql-pop-to-buffer-after-send-region value)
3856 (setq sql-pop-to-buffer-after-send-region
3857 (null sql-pop-to-buffer-after-send-region))))
3861 ;;; Redirect output functions
3863 (defvar sql-debug-redirect nil
3864 "If non-nil, display messages related to the use of redirection.")
3866 (defun sql-str-literal (s)
3867 (concat "'" (replace-regexp-in-string "[']" "''" s) "'"))
3869 (defun sql-redirect (sqlbuf command &optional outbuf save-prior)
3870 "Execute the SQL command and send output to OUTBUF.
3872 SQLBUF must be an active SQL interactive buffer. OUTBUF may be
3873 an existing buffer, or the name of a non-existing buffer. If
3874 omitted the output is sent to a temporary buffer which will be
3875 killed after the command completes. COMMAND should be a string
3876 of commands accepted by the SQLi program. COMMAND may also be a
3877 list of SQLi command strings."
3879 (let* ((visible (and outbuf
3880 (not (sql-buffer-hidden-p outbuf))))
3881 (this-save save-prior)
3882 (next-save t))
3884 (when visible
3885 (message "Executing SQL command..."))
3887 (if (consp command)
3888 (dolist (onecmd command)
3889 (sql-redirect-one sqlbuf onecmd outbuf this-save)
3890 (setq this-save next-save))
3891 (sql-redirect-one sqlbuf command outbuf save-prior))
3893 (when visible
3894 (message "Executing SQL command...done"))
3895 nil))
3897 (defun sql-redirect-one (sqlbuf command outbuf save-prior)
3898 (when command
3899 (with-current-buffer sqlbuf
3900 (let ((buf (get-buffer-create (or outbuf " *SQL-Redirect*")))
3901 (proc (get-buffer-process (current-buffer)))
3902 (comint-prompt-regexp (sql-get-product-feature sql-product
3903 :prompt-regexp))
3904 (start nil))
3905 (with-current-buffer buf
3906 (setq-local view-no-disable-on-exit t)
3907 (read-only-mode -1)
3908 (unless save-prior
3909 (erase-buffer))
3910 (goto-char (point-max))
3911 (unless (zerop (buffer-size))
3912 (insert "\n"))
3913 (setq start (point)))
3915 (when sql-debug-redirect
3916 (message ">>SQL> %S" command))
3918 ;; Run the command
3919 (let ((inhibit-quit t)
3920 comint-preoutput-filter-functions)
3921 (with-local-quit
3922 (comint-redirect-send-command-to-process command buf proc nil t)
3923 (while (or quit-flag (null comint-redirect-completed))
3924 (accept-process-output nil 1)))
3926 (if quit-flag
3927 (comint-redirect-cleanup)
3928 ;; Clean up the output results
3929 (with-current-buffer buf
3930 ;; Remove trailing whitespace
3931 (goto-char (point-max))
3932 (when (looking-back "[ \t\f\n\r]*" start)
3933 (delete-region (match-beginning 0) (match-end 0)))
3934 ;; Remove echo if there was one
3935 (goto-char start)
3936 (when (looking-at (concat "^" (regexp-quote command) "[\\n]"))
3937 (delete-region (match-beginning 0) (match-end 0)))
3938 ;; Remove Ctrl-Ms
3939 (goto-char start)
3940 (while (re-search-forward "\r+$" nil t)
3941 (replace-match "" t t))
3942 (goto-char start))))))))
3944 (defun sql-redirect-value (sqlbuf command &optional regexp regexp-groups)
3945 "Execute the SQL command and return part of result.
3947 SQLBUF must be an active SQL interactive buffer. COMMAND should
3948 be a string of commands accepted by the SQLi program. From the
3949 output, the REGEXP is repeatedly matched and the list of
3950 REGEXP-GROUPS submatches is returned. This behaves much like
3951 \\[comint-redirect-results-list-from-process] but instead of
3952 returning a single submatch it returns a list of each submatch
3953 for each match."
3955 (let ((outbuf " *SQL-Redirect-values*")
3956 (results nil))
3957 (sql-redirect sqlbuf command outbuf nil)
3958 (with-current-buffer outbuf
3959 (while (re-search-forward (or regexp "^.+$") nil t)
3960 (push
3961 (cond
3962 ;; no groups-return all of them
3963 ((null regexp-groups)
3964 (let ((i (/ (length (match-data)) 2))
3965 (r nil))
3966 (while (> i 0)
3967 (setq i (1- i))
3968 (push (match-string i) r))
3970 ;; one group specified
3971 ((numberp regexp-groups)
3972 (match-string regexp-groups))
3973 ;; list of numbers; return the specified matches only
3974 ((consp regexp-groups)
3975 (mapcar (lambda (c)
3976 (cond
3977 ((numberp c) (match-string c))
3978 ((stringp c) (match-substitute-replacement c))
3979 (t (error "sql-redirect-value: unknown REGEXP-GROUPS value - %s" c))))
3980 regexp-groups))
3981 ;; String is specified; return replacement string
3982 ((stringp regexp-groups)
3983 (match-substitute-replacement regexp-groups))
3985 (error "sql-redirect-value: unknown REGEXP-GROUPS value - %s"
3986 regexp-groups)))
3987 results)))
3989 (when sql-debug-redirect
3990 (message ">>SQL> = %S" (reverse results)))
3992 (nreverse results)))
3994 (defun sql-execute (sqlbuf outbuf command enhanced arg)
3995 "Execute a command in a SQL interactive buffer and capture the output.
3997 The commands are run in SQLBUF and the output saved in OUTBUF.
3998 COMMAND must be a string, a function or a list of such elements.
3999 Functions are called with SQLBUF, OUTBUF and ARG as parameters;
4000 strings are formatted with ARG and executed.
4002 If the results are empty the OUTBUF is deleted, otherwise the
4003 buffer is popped into a view window."
4004 (mapc
4005 (lambda (c)
4006 (cond
4007 ((stringp c)
4008 (sql-red