Misc changes
[emacs.git] / lisp / progmodes / sql.el
blob65a4094d70d4560a7a1ed4010ea5b5e473baa5d6
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 (defvar sql-mode-ansi-font-lock-keywords)
1550 (eval-and-compile
1551 (defun sql-font-lock-keywords-builder (face boundaries &rest keywords)
1552 "Generation of regexp matching any one of KEYWORDS."
1554 (let ((bdy (or boundaries '("\\b" . "\\b")))
1555 kwd)
1557 ;; Remove keywords that are defined in ANSI
1558 (setq kwd keywords)
1559 ;; (dolist (k keywords)
1560 ;; (catch 'next
1561 ;; (dolist (a sql-mode-ansi-font-lock-keywords)
1562 ;; (when (and (eq face (cdr a))
1563 ;; (eq (string-match (car a) k 0) 0)
1564 ;; (eq (match-end 0) (length k)))
1565 ;; (setq kwd (delq k kwd))
1566 ;; (throw 'next nil)))))
1568 ;; Create a properly formed font-lock-keywords item
1569 (cons (concat (car bdy)
1570 (regexp-opt kwd t)
1571 (cdr bdy))
1572 face)))
1574 (defun sql-regexp-abbrev (keyword)
1575 (let ((brk (string-match "[~]" keyword))
1576 (len (length keyword))
1577 (sep "\\(?:")
1578 re i)
1579 (if (not brk)
1580 keyword
1581 (setq re (substring keyword 0 brk)
1582 i (+ 2 brk)
1583 brk (1+ brk))
1584 (while (<= i len)
1585 (setq re (concat re sep (substring keyword brk i))
1586 sep "\\|"
1587 i (1+ i)))
1588 (concat re "\\)?"))))
1590 (defun sql-regexp-abbrev-list (&rest keyw-list)
1591 (let ((re nil)
1592 (sep "\\<\\(?:"))
1593 (while keyw-list
1594 (setq re (concat re sep (sql-regexp-abbrev (car keyw-list)))
1595 sep "\\|"
1596 keyw-list (cdr keyw-list)))
1597 (concat re "\\)\\>"))))
1599 (eval-when-compile
1600 (setq sql-mode-ansi-font-lock-keywords
1601 (list
1602 ;; ANSI Non Reserved keywords
1603 (sql-font-lock-keywords-builder 'font-lock-keyword-face nil
1604 "ada" "asensitive" "assignment" "asymmetric" "atomic" "between"
1605 "bitvar" "called" "catalog_name" "chain" "character_set_catalog"
1606 "character_set_name" "character_set_schema" "checked" "class_origin"
1607 "cobol" "collation_catalog" "collation_name" "collation_schema"
1608 "column_name" "command_function" "command_function_code" "committed"
1609 "condition_number" "connection_name" "constraint_catalog"
1610 "constraint_name" "constraint_schema" "contains" "cursor_name"
1611 "datetime_interval_code" "datetime_interval_precision" "defined"
1612 "definer" "dispatch" "dynamic_function" "dynamic_function_code"
1613 "existing" "exists" "final" "fortran" "generated" "granted"
1614 "hierarchy" "hold" "implementation" "infix" "insensitive" "instance"
1615 "instantiable" "invoker" "key_member" "key_type" "length" "m"
1616 "message_length" "message_octet_length" "message_text" "method" "more"
1617 "mumps" "name" "nullable" "number" "options" "overlaps" "overriding"
1618 "parameter_mode" "parameter_name" "parameter_ordinal_position"
1619 "parameter_specific_catalog" "parameter_specific_name"
1620 "parameter_specific_schema" "pascal" "pli" "position" "repeatable"
1621 "returned_length" "returned_octet_length" "returned_sqlstate"
1622 "routine_catalog" "routine_name" "routine_schema" "row_count" "scale"
1623 "schema_name" "security" "self" "sensitive" "serializable"
1624 "server_name" "similar" "simple" "source" "specific_name" "style"
1625 "subclass_origin" "sublist" "symmetric" "system" "table_name"
1626 "transaction_active" "transactions_committed"
1627 "transactions_rolled_back" "transform" "transforms" "trigger_catalog"
1628 "trigger_name" "trigger_schema" "type" "uncommitted" "unnamed"
1629 "user_defined_type_catalog" "user_defined_type_name"
1630 "user_defined_type_schema"
1633 ;; ANSI Reserved keywords
1634 (sql-font-lock-keywords-builder 'font-lock-keyword-face nil
1635 "absolute" "action" "add" "admin" "after" "aggregate" "alias" "all"
1636 "allocate" "alter" "and" "any" "are" "as" "asc" "assertion" "at"
1637 "authorization" "before" "begin" "both" "breadth" "by" "call"
1638 "cascade" "cascaded" "case" "catalog" "check" "class" "close"
1639 "collate" "collation" "column" "commit" "completion" "connect"
1640 "connection" "constraint" "constraints" "constructor" "continue"
1641 "corresponding" "create" "cross" "cube" "current" "cursor" "cycle"
1642 "data" "day" "deallocate" "declare" "default" "deferrable" "deferred"
1643 "delete" "depth" "deref" "desc" "describe" "descriptor" "destroy"
1644 "destructor" "deterministic" "diagnostics" "dictionary" "disconnect"
1645 "distinct" "domain" "drop" "dynamic" "each" "else" "end" "equals"
1646 "escape" "every" "except" "exception" "exec" "execute" "external"
1647 "false" "fetch" "first" "for" "foreign" "found" "free" "from" "full"
1648 "function" "general" "get" "global" "go" "goto" "grant" "group"
1649 "grouping" "having" "host" "hour" "identity" "ignore" "immediate" "in"
1650 "indicator" "initialize" "initially" "inner" "inout" "input" "insert"
1651 "intersect" "into" "is" "isolation" "iterate" "join" "key" "language"
1652 "last" "lateral" "leading" "left" "less" "level" "like" "limit"
1653 "local" "locator" "map" "match" "minute" "modifies" "modify" "module"
1654 "month" "names" "natural" "new" "next" "no" "none" "not" "null" "of"
1655 "off" "old" "on" "only" "open" "operation" "option" "or" "order"
1656 "ordinality" "out" "outer" "output" "pad" "parameter" "parameters"
1657 "partial" "path" "postfix" "prefix" "preorder" "prepare" "preserve"
1658 "primary" "prior" "privileges" "procedure" "public" "read" "reads"
1659 "recursive" "references" "referencing" "relative" "restrict" "result"
1660 "return" "returns" "revoke" "right" "role" "rollback" "rollup"
1661 "routine" "rows" "savepoint" "schema" "scroll" "search" "second"
1662 "section" "select" "sequence" "session" "set" "sets" "size" "some"
1663 "space" "specific" "specifictype" "sql" "sqlexception" "sqlstate"
1664 "sqlwarning" "start" "state" "statement" "static" "structure" "table"
1665 "temporary" "terminate" "than" "then" "timezone_hour"
1666 "timezone_minute" "to" "trailing" "transaction" "translation"
1667 "trigger" "true" "under" "union" "unique" "unknown" "unnest" "update"
1668 "usage" "using" "value" "values" "variable" "view" "when" "whenever"
1669 "where" "with" "without" "work" "write" "year"
1672 ;; ANSI Functions
1673 (sql-font-lock-keywords-builder 'font-lock-builtin-face nil
1674 "abs" "avg" "bit_length" "cardinality" "cast" "char_length"
1675 "character_length" "coalesce" "convert" "count" "current_date"
1676 "current_path" "current_role" "current_time" "current_timestamp"
1677 "current_user" "extract" "localtime" "localtimestamp" "lower" "max"
1678 "min" "mod" "nullif" "octet_length" "overlay" "placing" "session_user"
1679 "substring" "sum" "system_user" "translate" "treat" "trim" "upper"
1680 "user"
1683 ;; ANSI Data Types
1684 (sql-font-lock-keywords-builder 'font-lock-type-face nil
1685 "array" "binary" "bit" "blob" "boolean" "char" "character" "clob"
1686 "date" "dec" "decimal" "double" "float" "int" "integer" "interval"
1687 "large" "national" "nchar" "nclob" "numeric" "object" "precision"
1688 "real" "ref" "row" "scope" "smallint" "time" "timestamp" "varchar"
1689 "varying" "zone"
1690 ))))
1692 (defvar sql-mode-ansi-font-lock-keywords
1693 (eval-when-compile sql-mode-ansi-font-lock-keywords)
1694 "ANSI SQL keywords used by font-lock.
1696 This variable is used by `sql-mode' and `sql-interactive-mode'. The
1697 regular expressions are created during compilation by calling the
1698 function `regexp-opt'. Therefore, take a look at the source before
1699 you define your own `sql-mode-ansi-font-lock-keywords'. You may want
1700 to add functions and PL/SQL keywords.")
1702 (defun sql--oracle-show-reserved-words ()
1703 ;; This function is for use by the maintainer of SQL.EL only.
1704 (if (or (and (not (derived-mode-p 'sql-mode))
1705 (not (derived-mode-p 'sql-interactive-mode)))
1706 (not sql-buffer)
1707 (not (eq sql-product 'oracle)))
1708 (user-error "Not an Oracle buffer")
1710 (let ((b "*RESERVED WORDS*"))
1711 (sql-execute sql-buffer b
1712 (concat "SELECT "
1713 " keyword "
1714 ", reserved AS \"Res\" "
1715 ", res_type AS \"Type\" "
1716 ", res_attr AS \"Attr\" "
1717 ", res_semi AS \"Semi\" "
1718 ", duplicate AS \"Dup\" "
1719 "FROM V$RESERVED_WORDS "
1720 "WHERE length > 1 "
1721 "AND SUBSTR(keyword, 1, 1) BETWEEN 'A' AND 'Z' "
1722 "ORDER BY 2 DESC, 3 DESC, 4 DESC, 5 DESC, 6 DESC, 1;")
1723 nil nil)
1724 (with-current-buffer b
1725 (setq-local sql-product 'oracle)
1726 (sql-product-font-lock t nil)
1727 (font-lock-mode +1)))))
1729 (defvar sql-mode-oracle-font-lock-keywords
1730 (eval-when-compile
1731 (list
1732 ;; Oracle SQL*Plus Commands
1733 ;; Only recognized in they start in column 1 and the
1734 ;; abbreviation is followed by a space or the end of line.
1735 (list (concat "^" (sql-regexp-abbrev "rem~ark") "\\(?:\\s-.*\\)?$")
1736 0 'font-lock-comment-face t)
1738 (list
1739 (concat
1740 "^\\(?:"
1741 (sql-regexp-abbrev-list
1742 "[@]\\{1,2\\}" "acc~ept" "a~ppend" "archive" "attribute"
1743 "bre~ak" "bti~tle" "c~hange" "cl~ear" "col~umn" "conn~ect"
1744 "copy" "def~ine" "del" "desc~ribe" "disc~onnect" "ed~it"
1745 "exec~ute" "exit" "get" "help" "ho~st" "[$]" "i~nput" "l~ist"
1746 "passw~ord" "pau~se" "pri~nt" "pro~mpt" "quit" "recover"
1747 "repf~ooter" "reph~eader" "r~un" "sav~e" "sho~w" "shutdown"
1748 "spo~ol" "sta~rt" "startup" "store" "tim~ing" "tti~tle"
1749 "undef~ine" "var~iable" "whenever")
1750 "\\|"
1751 (concat "\\(?:"
1752 (sql-regexp-abbrev "comp~ute")
1753 "\\s-+"
1754 (sql-regexp-abbrev-list
1755 "avg" "cou~nt" "min~imum" "max~imum" "num~ber" "sum"
1756 "std" "var~iance")
1757 "\\)")
1758 "\\|"
1759 (concat "\\(?:set\\s-+"
1760 (sql-regexp-abbrev-list
1761 "appi~nfo" "array~size" "auto~commit" "autop~rint"
1762 "autorecovery" "autot~race" "blo~ckterminator"
1763 "cmds~ep" "colsep" "com~patibility" "con~cat"
1764 "copyc~ommit" "copytypecheck" "def~ine" "describe"
1765 "echo" "editf~ile" "emb~edded" "esc~ape" "feed~back"
1766 "flagger" "flu~sh" "hea~ding" "heads~ep" "instance"
1767 "lin~esize" "lobof~fset" "long" "longc~hunksize"
1768 "mark~up" "newp~age" "null" "numf~ormat" "num~width"
1769 "pages~ize" "pau~se" "recsep" "recsepchar"
1770 "scan" "serverout~put" "shift~inout" "show~mode"
1771 "sqlbl~anklines" "sqlc~ase" "sqlco~ntinue"
1772 "sqln~umber" "sqlpluscompat~ibility" "sqlpre~fix"
1773 "sqlp~rompt" "sqlt~erminator" "suf~fix" "tab"
1774 "term~out" "ti~me" "timi~ng" "trim~out" "trims~pool"
1775 "und~erline" "ver~ify" "wra~p")
1776 "\\)")
1778 "\\)\\(?:\\s-.*\\)?\\(?:[-]\n.*\\)*$")
1779 0 'font-lock-doc-face t)
1780 '("&?&\\(?:\\sw\\|\\s_\\)+[.]?" 0 font-lock-preprocessor-face t)
1782 ;; Oracle PL/SQL Attributes (Declare these first to match %TYPE correctly)
1783 (sql-font-lock-keywords-builder 'font-lock-builtin-face '("%" . "\\b")
1784 "bulk_exceptions" "bulk_rowcount" "found" "isopen" "notfound"
1785 "rowcount" "rowtype" "type"
1787 ;; Oracle Functions
1788 (sql-font-lock-keywords-builder 'font-lock-builtin-face nil
1789 "abs" "acos" "add_months" "appendchildxml" "ascii" "asciistr" "asin"
1790 "atan" "atan2" "avg" "bfilename" "bin_to_num" "bitand" "cardinality"
1791 "cast" "ceil" "chartorowid" "chr" "cluster_id" "cluster_probability"
1792 "cluster_set" "coalesce" "collect" "compose" "concat" "convert" "corr"
1793 "connect_by_root" "connect_by_iscycle" "connect_by_isleaf"
1794 "corr_k" "corr_s" "cos" "cosh" "count" "covar_pop" "covar_samp"
1795 "cube_table" "cume_dist" "current_date" "current_timestamp" "cv"
1796 "dataobj_to_partition" "dbtimezone" "decode" "decompose" "deletexml"
1797 "dense_rank" "depth" "deref" "dump" "empty_blob" "empty_clob"
1798 "existsnode" "exp" "extract" "extractvalue" "feature_id" "feature_set"
1799 "feature_value" "first" "first_value" "floor" "from_tz" "greatest"
1800 "grouping" "grouping_id" "group_id" "hextoraw" "initcap"
1801 "insertchildxml" "insertchildxmlafter" "insertchildxmlbefore"
1802 "insertxmlafter" "insertxmlbefore" "instr" "instr2" "instr4" "instrb"
1803 "instrc" "iteration_number" "lag" "last" "last_day" "last_value"
1804 "lead" "least" "length" "length2" "length4" "lengthb" "lengthc"
1805 "listagg" "ln" "lnnvl" "localtimestamp" "log" "lower" "lpad" "ltrim"
1806 "make_ref" "max" "median" "min" "mod" "months_between" "nanvl" "nchr"
1807 "new_time" "next_day" "nlssort" "nls_charset_decl_len"
1808 "nls_charset_id" "nls_charset_name" "nls_initcap" "nls_lower"
1809 "nls_upper" "nth_value" "ntile" "nullif" "numtodsinterval"
1810 "numtoyminterval" "nvl" "nvl2" "ora_dst_affected" "ora_dst_convert"
1811 "ora_dst_error" "ora_hash" "path" "percentile_cont" "percentile_disc"
1812 "percent_rank" "power" "powermultiset" "powermultiset_by_cardinality"
1813 "prediction" "prediction_bounds" "prediction_cost"
1814 "prediction_details" "prediction_probability" "prediction_set"
1815 "presentnnv" "presentv" "previous" "rank" "ratio_to_report" "rawtohex"
1816 "rawtonhex" "ref" "reftohex" "regexp_count" "regexp_instr" "regexp_like"
1817 "regexp_replace" "regexp_substr" "regr_avgx" "regr_avgy" "regr_count"
1818 "regr_intercept" "regr_r2" "regr_slope" "regr_sxx" "regr_sxy"
1819 "regr_syy" "remainder" "replace" "round" "rowidtochar" "rowidtonchar"
1820 "row_number" "rpad" "rtrim" "scn_to_timestamp" "sessiontimezone" "set"
1821 "sign" "sin" "sinh" "soundex" "sqrt" "stats_binomial_test"
1822 "stats_crosstab" "stats_f_test" "stats_ks_test" "stats_mode"
1823 "stats_mw_test" "stats_one_way_anova" "stats_t_test_indep"
1824 "stats_t_test_indepu" "stats_t_test_one" "stats_t_test_paired"
1825 "stats_wsr_test" "stddev" "stddev_pop" "stddev_samp" "substr"
1826 "substr2" "substr4" "substrb" "substrc" "sum" "sysdate" "systimestamp"
1827 "sys_connect_by_path" "sys_context" "sys_dburigen" "sys_extract_utc"
1828 "sys_guid" "sys_typeid" "sys_xmlagg" "sys_xmlgen" "tan" "tanh"
1829 "timestamp_to_scn" "to_binary_double" "to_binary_float" "to_blob"
1830 "to_char" "to_clob" "to_date" "to_dsinterval" "to_lob" "to_multi_byte"
1831 "to_nchar" "to_nclob" "to_number" "to_single_byte" "to_timestamp"
1832 "to_timestamp_tz" "to_yminterval" "translate" "treat" "trim" "trunc"
1833 "tz_offset" "uid" "unistr" "updatexml" "upper" "user" "userenv"
1834 "value" "variance" "var_pop" "var_samp" "vsize" "width_bucket"
1835 "xmlagg" "xmlcast" "xmlcdata" "xmlcolattval" "xmlcomment" "xmlconcat"
1836 "xmldiff" "xmlelement" "xmlexists" "xmlforest" "xmlisvalid" "xmlparse"
1837 "xmlpatch" "xmlpi" "xmlquery" "xmlroot" "xmlsequence" "xmlserialize"
1838 "xmltable" "xmltransform"
1841 ;; See the table V$RESERVED_WORDS
1842 ;; Oracle Keywords
1843 (sql-font-lock-keywords-builder 'font-lock-keyword-face nil
1844 "abort" "access" "accessed" "account" "activate" "add" "admin"
1845 "advise" "after" "agent" "aggregate" "all" "allocate" "allow" "alter"
1846 "always" "analyze" "ancillary" "and" "any" "apply" "archive"
1847 "archivelog" "array" "as" "asc" "associate" "at" "attribute"
1848 "attributes" "audit" "authenticated" "authid" "authorization" "auto"
1849 "autoallocate" "automatic" "availability" "backup" "before" "begin"
1850 "behalf" "between" "binding" "bitmap" "block" "blocksize" "body"
1851 "both" "buffer_pool" "build" "by" "cache" "call" "cancel"
1852 "cascade" "case" "category" "certificate" "chained" "change" "check"
1853 "checkpoint" "child" "chunk" "class" "clear" "clone" "close" "cluster"
1854 "column" "column_value" "columns" "comment" "commit" "committed"
1855 "compatibility" "compile" "complete" "composite_limit" "compress"
1856 "compute" "connect" "connect_time" "consider" "consistent"
1857 "constraint" "constraints" "constructor" "contents" "context"
1858 "continue" "controlfile" "corruption" "cost" "cpu_per_call"
1859 "cpu_per_session" "create" "cross" "cube" "current" "currval" "cycle"
1860 "dangling" "data" "database" "datafile" "datafiles" "day" "ddl"
1861 "deallocate" "debug" "default" "deferrable" "deferred" "definer"
1862 "delay" "delete" "demand" "desc" "determines" "deterministic"
1863 "dictionary" "dimension" "directory" "disable" "disassociate"
1864 "disconnect" "distinct" "distinguished" "distributed" "dml" "drop"
1865 "each" "element" "else" "enable" "end" "equals_path" "escape"
1866 "estimate" "except" "exceptions" "exchange" "excluding" "exists"
1867 "expire" "explain" "extent" "external" "externally"
1868 "failed_login_attempts" "fast" "file" "final" "finish" "flush" "for"
1869 "force" "foreign" "freelist" "freelists" "freepools" "fresh" "from"
1870 "full" "function" "functions" "generated" "global" "global_name"
1871 "globally" "grant" "group" "grouping" "groups" "guard" "hash"
1872 "hashkeys" "having" "heap" "hierarchy" "id" "identified" "identifier"
1873 "idle_time" "immediate" "in" "including" "increment" "index" "indexed"
1874 "indexes" "indextype" "indextypes" "indicator" "initial" "initialized"
1875 "initially" "initrans" "inner" "insert" "instance" "instantiable"
1876 "instead" "intersect" "into" "invalidate" "is" "isolation" "java"
1877 "join" "keep" "key" "kill" "language" "left" "less" "level"
1878 "levels" "library" "like" "like2" "like4" "likec" "limit" "link"
1879 "list" "lob" "local" "location" "locator" "lock" "log" "logfile"
1880 "logging" "logical" "logical_reads_per_call"
1881 "logical_reads_per_session" "managed" "management" "manual" "map"
1882 "mapping" "master" "matched" "materialized" "maxdatafiles"
1883 "maxextents" "maximize" "maxinstances" "maxlogfiles" "maxloghistory"
1884 "maxlogmembers" "maxsize" "maxtrans" "maxvalue" "member" "memory"
1885 "merge" "migrate" "minextents" "minimize" "minimum" "minus" "minvalue"
1886 "mode" "modify" "monitoring" "month" "mount" "move" "movement" "name"
1887 "named" "natural" "nested" "never" "new" "next" "nextval" "no"
1888 "noarchivelog" "noaudit" "nocache" "nocompress" "nocopy" "nocycle"
1889 "nodelay" "noforce" "nologging" "nomapping" "nomaxvalue" "nominimize"
1890 "nominvalue" "nomonitoring" "none" "noorder" "noparallel" "norely"
1891 "noresetlogs" "noreverse" "normal" "norowdependencies" "nosort"
1892 "noswitch" "not" "nothing" "notimeout" "novalidate" "nowait" "null"
1893 "nulls" "object" "of" "off" "offline" "oidindex" "old" "on" "online"
1894 "only" "open" "operator" "optimal" "option" "or" "order"
1895 "organization" "out" "outer" "outline" "over" "overflow" "overriding"
1896 "package" "packages" "parallel" "parallel_enable" "parameters"
1897 "parent" "partition" "partitions" "password" "password_grace_time"
1898 "password_life_time" "password_lock_time" "password_reuse_max"
1899 "password_reuse_time" "password_verify_function" "pctfree"
1900 "pctincrease" "pctthreshold" "pctused" "pctversion" "percent"
1901 "performance" "permanent" "pfile" "physical" "pipelined" "pivot" "plan"
1902 "post_transaction" "pragma" "prebuilt" "preserve" "primary" "private"
1903 "private_sga" "privileges" "procedure" "profile" "protection" "public"
1904 "purge" "query" "quiesce" "quota" "range" "read" "reads" "rebuild"
1905 "records_per_block" "recover" "recovery" "recycle" "reduced" "ref"
1906 "references" "referencing" "refresh" "register" "reject" "relational"
1907 "rely" "rename" "reset" "resetlogs" "resize" "resolve" "resolver"
1908 "resource" "restrict" "restrict_references" "restricted" "result"
1909 "resumable" "resume" "retention" "return" "returning" "reuse"
1910 "reverse" "revoke" "rewrite" "right" "rnds" "rnps" "role" "roles"
1911 "rollback" "rollup" "row" "rowdependencies" "rownum" "rows" "sample"
1912 "savepoint" "scan" "schema" "scn" "scope" "segment" "select"
1913 "selectivity" "self" "sequence" "serializable" "session"
1914 "sessions_per_user" "set" "sets" "settings" "shared" "shared_pool"
1915 "shrink" "shutdown" "siblings" "sid" "single" "size" "skip" "some"
1916 "sort" "source" "space" "specification" "spfile" "split" "standby"
1917 "start" "statement_id" "static" "statistics" "stop" "storage" "store"
1918 "structure" "subpartition" "subpartitions" "substitutable"
1919 "successful" "supplemental" "suspend" "switch" "switchover" "synonym"
1920 "sys" "system" "table" "tables" "tablespace" "tempfile" "template"
1921 "temporary" "test" "than" "then" "thread" "through" "time_zone"
1922 "timeout" "to" "trace" "transaction" "trigger" "triggers" "truncate"
1923 "trust" "type" "types" "unarchived" "under" "under_path" "undo"
1924 "uniform" "union" "unique" "unlimited" "unlock" "unpivot" "unquiesce"
1925 "unrecoverable" "until" "unusable" "unused" "update" "upgrade" "usage"
1926 "use" "using" "validate" "validation" "value" "values" "variable"
1927 "varray" "version" "view" "wait" "when" "whenever" "where" "with"
1928 "without" "wnds" "wnps" "work" "write" "xmldata" "xmlschema" "xmltype"
1931 ;; Oracle Data Types
1932 (sql-font-lock-keywords-builder 'font-lock-type-face nil
1933 "bfile" "binary_double" "binary_float" "blob" "byte" "char" "charbyte"
1934 "clob" "date" "day" "float" "interval" "local" "long" "longraw"
1935 "minute" "month" "nchar" "nclob" "number" "nvarchar2" "raw" "rowid" "second"
1936 "time" "timestamp" "urowid" "varchar2" "with" "year" "zone"
1939 ;; Oracle PL/SQL Functions
1940 (sql-font-lock-keywords-builder 'font-lock-builtin-face nil
1941 "delete" "trim" "extend" "exists" "first" "last" "count" "limit"
1942 "prior" "next" "sqlcode" "sqlerrm"
1945 ;; Oracle PL/SQL Reserved words
1946 (sql-font-lock-keywords-builder 'font-lock-keyword-face nil
1947 "all" "alter" "and" "any" "as" "asc" "at" "begin" "between" "by"
1948 "case" "check" "clusters" "cluster" "colauth" "columns" "compress"
1949 "connect" "crash" "create" "cursor" "declare" "default" "desc"
1950 "distinct" "drop" "else" "end" "exception" "exclusive" "fetch" "for"
1951 "from" "function" "goto" "grant" "group" "having" "identified" "if"
1952 "in" "index" "indexes" "insert" "intersect" "into" "is" "like" "lock"
1953 "minus" "mode" "nocompress" "not" "nowait" "null" "of" "on" "option"
1954 "or" "order" "overlaps" "procedure" "public" "resource" "revoke"
1955 "select" "share" "size" "sql" "start" "subtype" "tabauth" "table"
1956 "then" "to" "type" "union" "unique" "update" "values" "view" "views"
1957 "when" "where" "with"
1959 "true" "false"
1960 "raise_application_error"
1963 ;; Oracle PL/SQL Keywords
1964 (sql-font-lock-keywords-builder 'font-lock-keyword-face nil
1965 "a" "add" "agent" "aggregate" "array" "attribute" "authid" "avg"
1966 "bfile_base" "binary" "blob_base" "block" "body" "both" "bound" "bulk"
1967 "byte" "c" "call" "calling" "cascade" "char" "char_base" "character"
1968 "charset" "charsetform" "charsetid" "clob_base" "close" "collect"
1969 "comment" "commit" "committed" "compiled" "constant" "constructor"
1970 "context" "continue" "convert" "count" "current" "customdatum"
1971 "dangling" "data" "date" "date_base" "day" "define" "delete"
1972 "deterministic" "double" "duration" "element" "elsif" "empty" "escape"
1973 "except" "exceptions" "execute" "exists" "exit" "external" "final"
1974 "fixed" "float" "forall" "force" "general" "hash" "heap" "hidden"
1975 "hour" "immediate" "including" "indicator" "indices" "infinite"
1976 "instantiable" "int" "interface" "interval" "invalidate" "isolation"
1977 "java" "language" "large" "leading" "length" "level" "library" "like2"
1978 "like4" "likec" "limit" "limited" "local" "long" "loop" "map" "max"
1979 "maxlen" "member" "merge" "min" "minute" "mod" "modify" "month"
1980 "multiset" "name" "nan" "national" "native" "nchar" "new" "nocopy"
1981 "number_base" "object" "ocicoll" "ocidate" "ocidatetime" "ociduration"
1982 "ociinterval" "ociloblocator" "ocinumber" "ociraw" "ociref"
1983 "ocirefcursor" "ocirowid" "ocistring" "ocitype" "old" "only" "opaque"
1984 "open" "operator" "oracle" "oradata" "organization" "orlany" "orlvary"
1985 "others" "out" "overriding" "package" "parallel_enable" "parameter"
1986 "parameters" "parent" "partition" "pascal" "pipe" "pipelined" "pragma"
1987 "precision" "prior" "private" "raise" "range" "raw" "read" "record"
1988 "ref" "reference" "relies_on" "rem" "remainder" "rename" "result"
1989 "result_cache" "return" "returning" "reverse" "rollback" "row"
1990 "sample" "save" "savepoint" "sb1" "sb2" "sb4" "second" "segment"
1991 "self" "separate" "sequence" "serializable" "set" "short" "size_t"
1992 "some" "sparse" "sqlcode" "sqldata" "sqlname" "sqlstate" "standard"
1993 "static" "stddev" "stored" "string" "struct" "style" "submultiset"
1994 "subpartition" "substitutable" "sum" "synonym" "tdo" "the" "time"
1995 "timestamp" "timezone_abbr" "timezone_hour" "timezone_minute"
1996 "timezone_region" "trailing" "transaction" "transactional" "trusted"
1997 "ub1" "ub2" "ub4" "under" "unsigned" "untrusted" "use" "using"
1998 "valist" "value" "variable" "variance" "varray" "varying" "void"
1999 "while" "work" "wrapped" "write" "year" "zone"
2000 ;; Pragma
2001 "autonomous_transaction" "exception_init" "inline"
2002 "restrict_references" "serially_reusable"
2005 ;; Oracle PL/SQL Data Types
2006 (sql-font-lock-keywords-builder 'font-lock-type-face nil
2007 "\"BINARY LARGE OBJECT\"" "\"CHAR LARGE OBJECT\"" "\"CHAR VARYING\""
2008 "\"CHARACTER LARGE OBJECT\"" "\"CHARACTER VARYING\""
2009 "\"DOUBLE PRECISION\"" "\"INTERVAL DAY TO SECOND\""
2010 "\"INTERVAL YEAR TO MONTH\"" "\"LONG RAW\"" "\"NATIONAL CHAR\""
2011 "\"NATIONAL CHARACTER LARGE OBJECT\"" "\"NATIONAL CHARACTER\""
2012 "\"NCHAR LARGE OBJECT\"" "\"NCHAR\"" "\"NCLOB\"" "\"NVARCHAR2\""
2013 "\"TIME WITH TIME ZONE\"" "\"TIMESTAMP WITH LOCAL TIME ZONE\""
2014 "\"TIMESTAMP WITH TIME ZONE\""
2015 "bfile" "bfile_base" "binary_double" "binary_float" "binary_integer"
2016 "blob" "blob_base" "boolean" "char" "character" "char_base" "clob"
2017 "clob_base" "cursor" "date" "day" "dec" "decimal"
2018 "dsinterval_unconstrained" "float" "int" "integer" "interval" "local"
2019 "long" "mlslabel" "month" "natural" "naturaln" "nchar_cs" "number"
2020 "number_base" "numeric" "pls_integer" "positive" "positiven" "raw"
2021 "real" "ref" "rowid" "second" "signtype" "simple_double"
2022 "simple_float" "simple_integer" "smallint" "string" "time" "timestamp"
2023 "timestamp_ltz_unconstrained" "timestamp_tz_unconstrained"
2024 "timestamp_unconstrained" "time_tz_unconstrained" "time_unconstrained"
2025 "to" "urowid" "varchar" "varchar2" "with" "year"
2026 "yminterval_unconstrained" "zone"
2029 ;; Oracle PL/SQL Exceptions
2030 (sql-font-lock-keywords-builder 'font-lock-warning-face nil
2031 "access_into_null" "case_not_found" "collection_is_null"
2032 "cursor_already_open" "dup_val_on_index" "invalid_cursor"
2033 "invalid_number" "login_denied" "no_data_found" "no_data_needed"
2034 "not_logged_on" "program_error" "rowtype_mismatch" "self_is_null"
2035 "storage_error" "subscript_beyond_count" "subscript_outside_limit"
2036 "sys_invalid_rowid" "timeout_on_resource" "too_many_rows"
2037 "value_error" "zero_divide"
2040 "Oracle SQL keywords used by font-lock.
2042 This variable is used by `sql-mode' and `sql-interactive-mode'. The
2043 regular expressions are created during compilation by calling the
2044 function `regexp-opt'. Therefore, take a look at the source before
2045 you define your own `sql-mode-oracle-font-lock-keywords'. You may want
2046 to add functions and PL/SQL keywords.")
2048 (defvar sql-mode-postgres-font-lock-keywords
2049 (eval-when-compile
2050 (list
2051 ;; Postgres psql commands
2052 '("^\\s-*\\\\.*$" . font-lock-doc-face)
2054 ;; Postgres unreserved words but may have meaning
2055 (sql-font-lock-keywords-builder 'font-lock-builtin-face nil "a"
2056 "abs" "absent" "according" "ada" "alias" "allocate" "are" "array_agg"
2057 "asensitive" "atomic" "attribute" "attributes" "avg" "base64"
2058 "bernoulli" "bit_length" "bitvar" "blob" "blocked" "bom" "breadth" "c"
2059 "call" "cardinality" "catalog_name" "ceil" "ceiling" "char_length"
2060 "character_length" "character_set_catalog" "character_set_name"
2061 "character_set_schema" "characters" "checked" "class_origin" "clob"
2062 "cobol" "collation" "collation_catalog" "collation_name"
2063 "collation_schema" "collect" "column_name" "columns"
2064 "command_function" "command_function_code" "completion" "condition"
2065 "condition_number" "connect" "connection_name" "constraint_catalog"
2066 "constraint_name" "constraint_schema" "constructor" "contains"
2067 "control" "convert" "corr" "corresponding" "count" "covar_pop"
2068 "covar_samp" "cube" "cume_dist" "current_default_transform_group"
2069 "current_path" "current_transform_group_for_type" "cursor_name"
2070 "datalink" "datetime_interval_code" "datetime_interval_precision" "db"
2071 "defined" "degree" "dense_rank" "depth" "deref" "derived" "describe"
2072 "descriptor" "destroy" "destructor" "deterministic" "diagnostics"
2073 "disconnect" "dispatch" "dlnewcopy" "dlpreviouscopy" "dlurlcomplete"
2074 "dlurlcompleteonly" "dlurlcompletewrite" "dlurlpath" "dlurlpathonly"
2075 "dlurlpathwrite" "dlurlscheme" "dlurlserver" "dlvalue" "dynamic"
2076 "dynamic_function" "dynamic_function_code" "element" "empty"
2077 "end-exec" "equals" "every" "exception" "exec" "existing" "exp" "file"
2078 "filter" "final" "first_value" "flag" "floor" "fortran" "found" "free"
2079 "fs" "fusion" "g" "general" "generated" "get" "go" "goto" "grouping"
2080 "hex" "hierarchy" "host" "id" "ignore" "implementation" "import"
2081 "indent" "indicator" "infix" "initialize" "instance" "instantiable"
2082 "integrity" "intersection" "iterate" "k" "key_member" "key_type" "lag"
2083 "last_value" "lateral" "lead" "length" "less" "library" "like_regex"
2084 "link" "ln" "locator" "lower" "m" "map" "matched" "max"
2085 "max_cardinality" "member" "merge" "message_length"
2086 "message_octet_length" "message_text" "method" "min" "mod" "modifies"
2087 "modify" "module" "more" "multiset" "mumps" "namespace" "nclob"
2088 "nesting" "new" "nfc" "nfd" "nfkc" "nfkd" "nil" "normalize"
2089 "normalized" "nth_value" "ntile" "nullable" "number"
2090 "occurrences_regex" "octet_length" "octets" "old" "open" "operation"
2091 "ordering" "ordinality" "others" "output" "overriding" "p" "pad"
2092 "parameter" "parameter_mode" "parameter_name"
2093 "parameter_ordinal_position" "parameter_specific_catalog"
2094 "parameter_specific_name" "parameter_specific_schema" "parameters"
2095 "pascal" "passing" "passthrough" "percent_rank" "percentile_cont"
2096 "percentile_disc" "permission" "pli" "position_regex" "postfix"
2097 "power" "prefix" "preorder" "public" "rank" "reads" "recovery" "ref"
2098 "referencing" "regr_avgx" "regr_avgy" "regr_count" "regr_intercept"
2099 "regr_r2" "regr_slope" "regr_sxx" "regr_sxy" "regr_syy" "requiring"
2100 "respect" "restore" "result" "return" "returned_cardinality"
2101 "returned_length" "returned_octet_length" "returned_sqlstate" "rollup"
2102 "routine" "routine_catalog" "routine_name" "routine_schema"
2103 "row_count" "row_number" "scale" "schema_name" "scope" "scope_catalog"
2104 "scope_name" "scope_schema" "section" "selective" "self" "sensitive"
2105 "server_name" "sets" "size" "source" "space" "specific"
2106 "specific_name" "specifictype" "sql" "sqlcode" "sqlerror"
2107 "sqlexception" "sqlstate" "sqlwarning" "sqrt" "state" "static"
2108 "stddev_pop" "stddev_samp" "structure" "style" "subclass_origin"
2109 "sublist" "submultiset" "substring_regex" "sum" "system_user" "t"
2110 "table_name" "tablesample" "terminate" "than" "ties" "timezone_hour"
2111 "timezone_minute" "token" "top_level_count" "transaction_active"
2112 "transactions_committed" "transactions_rolled_back" "transform"
2113 "transforms" "translate" "translate_regex" "translation"
2114 "trigger_catalog" "trigger_name" "trigger_schema" "trim_array"
2115 "uescape" "under" "unlink" "unnamed" "unnest" "untyped" "upper" "uri"
2116 "usage" "user_defined_type_catalog" "user_defined_type_code"
2117 "user_defined_type_name" "user_defined_type_schema" "var_pop"
2118 "var_samp" "varbinary" "variable" "whenever" "width_bucket" "within"
2119 "xmlagg" "xmlbinary" "xmlcast" "xmlcomment" "xmldeclaration"
2120 "xmldocument" "xmlexists" "xmliterate" "xmlnamespaces" "xmlquery"
2121 "xmlschema" "xmltable" "xmltext" "xmlvalidate"
2124 ;; Postgres non-reserved words
2125 (sql-font-lock-keywords-builder 'font-lock-builtin-face nil
2126 "abort" "absolute" "access" "action" "add" "admin" "after" "aggregate"
2127 "also" "alter" "always" "assertion" "assignment" "at" "attribute" "backward"
2128 "before" "begin" "between" "by" "cache" "called" "cascade" "cascaded"
2129 "catalog" "chain" "characteristics" "checkpoint" "class" "close"
2130 "cluster" "coalesce" "comment" "comments" "commit" "committed"
2131 "configuration" "connection" "constraints" "content" "continue"
2132 "conversion" "copy" "cost" "createdb" "createrole" "createuser" "csv"
2133 "current" "cursor" "cycle" "data" "database" "day" "deallocate" "dec"
2134 "declare" "defaults" "deferred" "definer" "delete" "delimiter"
2135 "delimiters" "dictionary" "disable" "discard" "document" "domain"
2136 "drop" "each" "enable" "encoding" "encrypted" "enum" "escape"
2137 "exclude" "excluding" "exclusive" "execute" "exists" "explain"
2138 "extension" "external" "extract" "family" "first" "float" "following" "force"
2139 "forward" "function" "functions" "global" "granted" "greatest"
2140 "handler" "header" "hold" "hour" "identity" "if" "immediate"
2141 "immutable" "implicit" "including" "increment" "index" "indexes"
2142 "inherit" "inherits" "inline" "inout" "input" "insensitive" "insert"
2143 "instead" "invoker" "isolation" "key" "label" "language" "large" "last"
2144 "lc_collate" "lc_ctype" "leakproof" "least" "level" "listen" "load" "local"
2145 "location" "lock" "login" "mapping" "match" "maxvalue" "minute"
2146 "minvalue" "mode" "month" "move" "names" "national" "nchar"
2147 "next" "no" "nocreatedb" "nocreaterole" "nocreateuser" "noinherit"
2148 "nologin" "none" "noreplication" "nosuperuser" "nothing" "notify" "nowait" "nullif"
2149 "nulls" "object" "of" "off" "oids" "operator" "option" "options" "out"
2150 "overlay" "owned" "owner" "parser" "partial" "partition" "passing" "password"
2151 "plans" "position" "preceding" "precision" "prepare" "prepared" "preserve" "prior"
2152 "privileges" "procedural" "procedure" "quote" "range" "read"
2153 "reassign" "recheck" "recursive" "ref" "reindex" "relative" "release"
2154 "rename" "repeatable" "replace" "replica" "replication" "reset" "restart" "restrict"
2155 "returns" "revoke" "role" "rollback" "row" "rows" "rule" "savepoint"
2156 "schema" "scroll" "search" "second" "security" "sequence"
2157 "serializable" "server" "session" "set" "setof" "share" "show"
2158 "simple" "snapshot" "stable" "standalone" "start" "statement" "statistics"
2159 "stdin" "stdout" "storage" "strict" "strip" "substring" "superuser"
2160 "sysid" "system" "tables" "tablespace" "temp" "template" "temporary"
2161 "transaction" "treat" "trim" "truncate" "trusted" "type" "types"
2162 "unbounded" "uncommitted" "unencrypted" "unlisten" "unlogged" "until"
2163 "update" "vacuum" "valid" "validate" "validator" "value" "values" "varying" "version"
2164 "view" "volatile" "whitespace" "without" "work" "wrapper" "write"
2165 "xmlattributes" "xmlconcat" "xmlelement" "xmlexists" "xmlforest" "xmlparse"
2166 "xmlpi" "xmlroot" "xmlserialize" "year" "yes" "zone"
2169 ;; Postgres Reserved
2170 (sql-font-lock-keywords-builder 'font-lock-keyword-face nil
2171 "all" "analyse" "analyze" "and" "array" "asc" "as" "asymmetric"
2172 "authorization" "binary" "both" "case" "cast" "check" "collate"
2173 "column" "concurrently" "constraint" "create" "cross"
2174 "current_catalog" "current_date" "current_role" "current_schema"
2175 "current_time" "current_timestamp" "current_user" "default"
2176 "deferrable" "desc" "distinct" "do" "else" "end" "except" "false"
2177 "fetch" "foreign" "for" "freeze" "from" "full" "grant" "group"
2178 "having" "ilike" "initially" "inner" "in" "intersect" "into" "isnull"
2179 "is" "join" "leading" "left" "like" "limit" "localtime"
2180 "localtimestamp" "natural" "notnull" "not" "null" "offset"
2181 "only" "on" "order" "or" "outer" "overlaps" "over" "placing" "primary"
2182 "references" "returning" "right" "select" "session_user" "similar"
2183 "some" "symmetric" "table" "then" "to" "trailing" "true" "union"
2184 "unique" "user" "using" "variadic" "verbose" "when" "where" "window"
2185 "with"
2188 ;; Postgres PL/pgSQL
2189 (sql-font-lock-keywords-builder 'font-lock-keyword-face nil
2190 "assign" "if" "case" "loop" "while" "for" "foreach" "exit" "elsif" "return"
2191 "raise" "execsql" "dynexecute" "perform" "getdiag" "open" "fetch" "move" "close"
2194 ;; Postgres Data Types
2195 (sql-font-lock-keywords-builder 'font-lock-type-face nil
2196 "bigint" "bigserial" "bit" "bool" "boolean" "box" "bytea" "char"
2197 "character" "cidr" "circle" "date" "decimal" "double" "float4"
2198 "float8" "inet" "int" "int2" "int4" "int8" "integer" "interval" "line"
2199 "lseg" "macaddr" "money" "name" "numeric" "path" "point" "polygon"
2200 "precision" "real" "serial" "serial4" "serial8" "sequences" "smallint" "text"
2201 "time" "timestamp" "timestamptz" "timetz" "tsquery" "tsvector"
2202 "txid_snapshot" "unknown" "uuid" "varbit" "varchar" "varying" "without"
2203 "xml" "zone"
2206 "Postgres SQL keywords used by font-lock.
2208 This variable is used by `sql-mode' and `sql-interactive-mode'. The
2209 regular expressions are created during compilation by calling the
2210 function `regexp-opt'. Therefore, take a look at the source before
2211 you define your own `sql-mode-postgres-font-lock-keywords'.")
2213 (defvar sql-mode-linter-font-lock-keywords
2214 (eval-when-compile
2215 (list
2216 ;; Linter Keywords
2217 (sql-font-lock-keywords-builder 'font-lock-keyword-face nil
2218 "autocommit" "autoinc" "autorowid" "cancel" "cascade" "channel"
2219 "committed" "count" "countblob" "cross" "current" "data" "database"
2220 "datafile" "datafiles" "datesplit" "dba" "dbname" "default" "deferred"
2221 "denied" "description" "device" "difference" "directory" "error"
2222 "escape" "euc" "exclusive" "external" "extfile" "false" "file"
2223 "filename" "filesize" "filetime" "filter" "findblob" "first" "foreign"
2224 "full" "fuzzy" "global" "granted" "ignore" "immediate" "increment"
2225 "indexes" "indexfile" "indexfiles" "indextime" "initial" "integrity"
2226 "internal" "key" "last_autoinc" "last_rowid" "limit" "linter"
2227 "linter_file_device" "linter_file_size" "linter_name_length" "ln"
2228 "local" "login" "maxisn" "maxrow" "maxrowid" "maxvalue" "message"
2229 "minvalue" "module" "names" "national" "natural" "new" "new_table"
2230 "no" "node" "noneuc" "nulliferror" "numbers" "off" "old" "old_table"
2231 "only" "operation" "optimistic" "option" "page" "partially" "password"
2232 "phrase" "plan" "precision" "primary" "priority" "privileges"
2233 "proc_info_size" "proc_par_name_len" "protocol" "quant" "range" "raw"
2234 "read" "record" "records" "references" "remote" "rename" "replication"
2235 "restart" "rewrite" "root" "row" "rule" "savepoint" "security"
2236 "sensitive" "sequence" "serializable" "server" "since" "size" "some"
2237 "startup" "statement" "station" "success" "sys_guid" "tables" "test"
2238 "timeout" "trace" "transaction" "translation" "trigger"
2239 "trigger_info_size" "true" "trunc" "uncommitted" "unicode" "unknown"
2240 "unlimited" "unlisted" "user" "utf8" "value" "varying" "volumes"
2241 "wait" "windows_code" "workspace" "write" "xml"
2244 ;; Linter Reserved
2245 (sql-font-lock-keywords-builder 'font-lock-keyword-face nil
2246 "access" "action" "add" "address" "after" "all" "alter" "always" "and"
2247 "any" "append" "as" "asc" "ascic" "async" "at_begin" "at_end" "audit"
2248 "aud_obj_name_len" "backup" "base" "before" "between" "blobfile"
2249 "blobfiles" "blobpct" "brief" "browse" "by" "case" "cast" "check"
2250 "clear" "close" "column" "comment" "commit" "connect" "contains"
2251 "correct" "create" "delete" "desc" "disable" "disconnect" "distinct"
2252 "drop" "each" "ef" "else" "enable" "end" "event" "except" "exclude"
2253 "execute" "exists" "extract" "fetch" "finish" "for" "from" "get"
2254 "grant" "group" "having" "identified" "in" "index" "inner" "insert"
2255 "instead" "intersect" "into" "is" "isolation" "join" "left" "level"
2256 "like" "lock" "mode" "modify" "not" "nowait" "null" "of" "on" "open"
2257 "or" "order" "outer" "owner" "press" "prior" "procedure" "public"
2258 "purge" "rebuild" "resource" "restrict" "revoke" "right" "role"
2259 "rollback" "rownum" "select" "session" "set" "share" "shutdown"
2260 "start" "stop" "sync" "synchronize" "synonym" "sysdate" "table" "then"
2261 "to" "union" "unique" "unlock" "until" "update" "using" "values"
2262 "view" "when" "where" "with" "without"
2265 ;; Linter Functions
2266 (sql-font-lock-keywords-builder 'font-lock-builtin-face nil
2267 "abs" "acos" "asin" "atan" "atan2" "avg" "ceil" "cos" "cosh" "divtime"
2268 "exp" "floor" "getbits" "getblob" "getbyte" "getlong" "getraw"
2269 "getstr" "gettext" "getword" "hextoraw" "lenblob" "length" "log"
2270 "lower" "lpad" "ltrim" "max" "min" "mod" "monthname" "nvl"
2271 "octet_length" "power" "rand" "rawtohex" "repeat_string"
2272 "right_substr" "round" "rpad" "rtrim" "sign" "sin" "sinh" "soundex"
2273 "sqrt" "sum" "tan" "tanh" "timeint_to_days" "to_char" "to_date"
2274 "to_gmtime" "to_localtime" "to_number" "trim" "upper" "decode"
2275 "substr" "substring" "chr" "dayname" "days" "greatest" "hex" "initcap"
2276 "instr" "least" "multime" "replace" "width"
2279 ;; Linter Data Types
2280 (sql-font-lock-keywords-builder 'font-lock-type-face nil
2281 "bigint" "bitmap" "blob" "boolean" "char" "character" "date"
2282 "datetime" "dec" "decimal" "double" "float" "int" "integer" "nchar"
2283 "number" "numeric" "real" "smallint" "varbyte" "varchar" "byte"
2284 "cursor" "long"
2287 "Linter SQL keywords used by font-lock.
2289 This variable is used by `sql-mode' and `sql-interactive-mode'. The
2290 regular expressions are created during compilation by calling the
2291 function `regexp-opt'.")
2293 (defvar sql-mode-ms-font-lock-keywords
2294 (eval-when-compile
2295 (list
2296 ;; MS isql/osql Commands
2297 (cons
2298 (concat
2299 "^\\(?:\\(?:set\\s-+\\(?:"
2300 (regexp-opt '(
2301 "datefirst" "dateformat" "deadlock_priority" "lock_timeout"
2302 "concat_null_yields_null" "cursor_close_on_commit"
2303 "disable_def_cnst_chk" "fips_flagger" "identity_insert" "language"
2304 "offsets" "quoted_identifier" "arithabort" "arithignore" "fmtonly"
2305 "nocount" "noexec" "numeric_roundabort" "parseonly"
2306 "query_governor_cost_limit" "rowcount" "textsize" "ansi_defaults"
2307 "ansi_null_dflt_off" "ansi_null_dflt_on" "ansi_nulls" "ansi_padding"
2308 "ansi_warnings" "forceplan" "showplan_all" "showplan_text"
2309 "statistics" "implicit_transactions" "remote_proc_transactions"
2310 "transaction" "xact_abort"
2313 "\\)\\)\\|go\\s-*\\|use\\s-+\\|setuser\\s-+\\|dbcc\\s-+\\).*$")
2314 'font-lock-doc-face)
2316 ;; MS Reserved
2317 (sql-font-lock-keywords-builder 'font-lock-keyword-face nil
2318 "absolute" "add" "all" "alter" "and" "any" "as" "asc" "authorization"
2319 "avg" "backup" "begin" "between" "break" "browse" "bulk" "by"
2320 "cascade" "case" "check" "checkpoint" "close" "clustered" "coalesce"
2321 "column" "commit" "committed" "compute" "confirm" "constraint"
2322 "contains" "containstable" "continue" "controlrow" "convert" "count"
2323 "create" "cross" "current" "current_date" "current_time"
2324 "current_timestamp" "current_user" "database" "deallocate" "declare"
2325 "default" "delete" "deny" "desc" "disk" "distinct" "distributed"
2326 "double" "drop" "dummy" "dump" "else" "end" "errlvl" "errorexit"
2327 "escape" "except" "exec" "execute" "exists" "exit" "fetch" "file"
2328 "fillfactor" "first" "floppy" "for" "foreign" "freetext"
2329 "freetexttable" "from" "full" "goto" "grant" "group" "having"
2330 "holdlock" "identity" "identity_insert" "identitycol" "if" "in"
2331 "index" "inner" "insert" "intersect" "into" "is" "isolation" "join"
2332 "key" "kill" "last" "left" "level" "like" "lineno" "load" "max" "min"
2333 "mirrorexit" "national" "next" "nocheck" "nolock" "nonclustered" "not"
2334 "null" "nullif" "of" "off" "offsets" "on" "once" "only" "open"
2335 "opendatasource" "openquery" "openrowset" "option" "or" "order"
2336 "outer" "output" "over" "paglock" "percent" "perm" "permanent" "pipe"
2337 "plan" "precision" "prepare" "primary" "print" "prior" "privileges"
2338 "proc" "procedure" "processexit" "public" "raiserror" "read"
2339 "readcommitted" "readpast" "readtext" "readuncommitted" "reconfigure"
2340 "references" "relative" "repeatable" "repeatableread" "replication"
2341 "restore" "restrict" "return" "revoke" "right" "rollback" "rowcount"
2342 "rowguidcol" "rowlock" "rule" "save" "schema" "select" "serializable"
2343 "session_user" "set" "shutdown" "some" "statistics" "sum"
2344 "system_user" "table" "tablock" "tablockx" "tape" "temp" "temporary"
2345 "textsize" "then" "to" "top" "tran" "transaction" "trigger" "truncate"
2346 "tsequal" "uncommitted" "union" "unique" "update" "updatetext"
2347 "updlock" "use" "user" "values" "view" "waitfor" "when" "where"
2348 "while" "with" "work" "writetext" "collate" "function" "openxml"
2349 "returns"
2352 ;; MS Functions
2353 (sql-font-lock-keywords-builder 'font-lock-builtin-face nil
2354 "@@connections" "@@cpu_busy" "@@cursor_rows" "@@datefirst" "@@dbts"
2355 "@@error" "@@fetch_status" "@@identity" "@@idle" "@@io_busy"
2356 "@@langid" "@@language" "@@lock_timeout" "@@max_connections"
2357 "@@max_precision" "@@nestlevel" "@@options" "@@pack_received"
2358 "@@pack_sent" "@@packet_errors" "@@procid" "@@remserver" "@@rowcount"
2359 "@@servername" "@@servicename" "@@spid" "@@textsize" "@@timeticks"
2360 "@@total_errors" "@@total_read" "@@total_write" "@@trancount"
2361 "@@version" "abs" "acos" "and" "app_name" "ascii" "asin" "atan" "atn2"
2362 "avg" "case" "cast" "ceiling" "char" "charindex" "coalesce"
2363 "col_length" "col_name" "columnproperty" "containstable" "convert"
2364 "cos" "cot" "count" "current_timestamp" "current_user" "cursor_status"
2365 "databaseproperty" "datalength" "dateadd" "datediff" "datename"
2366 "datepart" "day" "db_id" "db_name" "degrees" "difference" "exp"
2367 "file_id" "file_name" "filegroup_id" "filegroup_name"
2368 "filegroupproperty" "fileproperty" "floor" "formatmessage"
2369 "freetexttable" "fulltextcatalogproperty" "fulltextserviceproperty"
2370 "getansinull" "getdate" "grouping" "host_id" "host_name" "ident_incr"
2371 "ident_seed" "identity" "index_col" "indexproperty" "is_member"
2372 "is_srvrolemember" "isdate" "isnull" "isnumeric" "left" "len" "log"
2373 "log10" "lower" "ltrim" "max" "min" "month" "nchar" "newid" "nullif"
2374 "object_id" "object_name" "objectproperty" "openquery" "openrowset"
2375 "parsename" "patindex" "patindex" "permissions" "pi" "power"
2376 "quotename" "radians" "rand" "replace" "replicate" "reverse" "right"
2377 "round" "rtrim" "session_user" "sign" "sin" "soundex" "space" "sqrt"
2378 "square" "stats_date" "stdev" "stdevp" "str" "stuff" "substring" "sum"
2379 "suser_id" "suser_name" "suser_sid" "suser_sname" "system_user" "tan"
2380 "textptr" "textvalid" "typeproperty" "unicode" "upper" "user"
2381 "user_id" "user_name" "var" "varp" "year"
2384 ;; MS Variables
2385 '("\\b@[a-zA-Z0-9_]*\\b" . font-lock-variable-name-face)
2387 ;; MS Types
2388 (sql-font-lock-keywords-builder 'font-lock-type-face nil
2389 "binary" "bit" "char" "character" "cursor" "datetime" "dec" "decimal"
2390 "double" "float" "image" "int" "integer" "money" "national" "nchar"
2391 "ntext" "numeric" "numeric" "nvarchar" "precision" "real"
2392 "smalldatetime" "smallint" "smallmoney" "text" "timestamp" "tinyint"
2393 "uniqueidentifier" "varbinary" "varchar" "varying"
2396 "Microsoft SQLServer SQL keywords used by font-lock.
2398 This variable is used by `sql-mode' and `sql-interactive-mode'. The
2399 regular expressions are created during compilation by calling the
2400 function `regexp-opt'. Therefore, take a look at the source before
2401 you define your own `sql-mode-ms-font-lock-keywords'.")
2403 (defvar sql-mode-sybase-font-lock-keywords nil
2404 "Sybase SQL keywords used by font-lock.
2406 This variable is used by `sql-mode' and `sql-interactive-mode'. The
2407 regular expressions are created during compilation by calling the
2408 function `regexp-opt'. Therefore, take a look at the source before
2409 you define your own `sql-mode-sybase-font-lock-keywords'.")
2411 (defvar sql-mode-informix-font-lock-keywords nil
2412 "Informix SQL keywords used by font-lock.
2414 This variable is used by `sql-mode' and `sql-interactive-mode'. The
2415 regular expressions are created during compilation by calling the
2416 function `regexp-opt'. Therefore, take a look at the source before
2417 you define your own `sql-mode-informix-font-lock-keywords'.")
2419 (defvar sql-mode-interbase-font-lock-keywords nil
2420 "Interbase SQL keywords used by font-lock.
2422 This variable is used by `sql-mode' and `sql-interactive-mode'. The
2423 regular expressions are created during compilation by calling the
2424 function `regexp-opt'. Therefore, take a look at the source before
2425 you define your own `sql-mode-interbase-font-lock-keywords'.")
2427 (defvar sql-mode-ingres-font-lock-keywords nil
2428 "Ingres SQL keywords used by font-lock.
2430 This variable is used by `sql-mode' and `sql-interactive-mode'. The
2431 regular expressions are created during compilation by calling the
2432 function `regexp-opt'. Therefore, take a look at the source before
2433 you define your own `sql-mode-interbase-font-lock-keywords'.")
2435 (defvar sql-mode-solid-font-lock-keywords nil
2436 "Solid SQL keywords used by font-lock.
2438 This variable is used by `sql-mode' and `sql-interactive-mode'. The
2439 regular expressions are created during compilation by calling the
2440 function `regexp-opt'. Therefore, take a look at the source before
2441 you define your own `sql-mode-solid-font-lock-keywords'.")
2443 (defvaralias 'sql-mode-mariadb-font-lock-keywords 'sql-mode-mysql-font-lock-keywords
2444 "MariaDB is SQL compatible with MySQL.")
2446 (defvar sql-mode-mysql-font-lock-keywords
2447 (eval-when-compile
2448 (list
2449 ;; MySQL Functions
2450 (sql-font-lock-keywords-builder 'font-lock-builtin-face nil
2451 "acos" "adddate" "addtime" "aes_decrypt" "aes_encrypt" "area"
2452 "asbinary" "ascii" "asin" "astext" "aswkb" "aswkt" "atan" "atan2"
2453 "avg" "bdmpolyfromtext" "bdmpolyfromwkb" "bdpolyfromtext"
2454 "bdpolyfromwkb" "benchmark" "bin" "binlog_gtid_pos" "bit_and"
2455 "bit_count" "bit_length" "bit_or" "bit_xor" "both" "boundary" "buffer"
2456 "cast" "ceil" "ceiling" "centroid" "character_length" "char_length"
2457 "charset" "coalesce" "coercibility" "column_add" "column_check"
2458 "column_create" "column_delete" "column_exists" "column_get"
2459 "column_json" "column_list" "compress" "concat" "concat_ws"
2460 "connection_id" "conv" "convert" "convert_tz" "convexhull" "cos" "cot"
2461 "count" "crc32" "crosses" "cume_dist" "cume_dist" "curdate"
2462 "current_date" "current_time" "current_timestamp" "curtime" "date_add"
2463 "datediff" "date_format" "date_sub" "dayname" "dayofmonth" "dayofweek"
2464 "dayofyear" "decode" "decode_histogram" "degrees" "dense_rank"
2465 "dense_rank" "des_decrypt" "des_encrypt" "dimension" "disjoint" "div"
2466 "elt" "encode" "encrypt" "endpoint" "envelope" "exp" "export_set"
2467 "exteriorring" "extractvalue" "field" "find_in_set" "floor" "format"
2468 "found_rows" "from" "from_base64" "from_days" "from_unixtime"
2469 "geomcollfromtext" "geomcollfromwkb" "geometrycollectionfromtext"
2470 "geometrycollectionfromwkb" "geometryfromtext" "geometryfromwkb"
2471 "geometryn" "geometrytype" "geomfromtext" "geomfromwkb" "get_format"
2472 "get_lock" "glength" "greatest" "group_concat" "hex" "ifnull"
2473 "inet6_aton" "inet6_ntoa" "inet_aton" "inet_ntoa" "instr"
2474 "interiorringn" "intersects" "interval" "isclosed" "isempty"
2475 "is_free_lock" "is_ipv4" "is_ipv4_compat" "is_ipv4_mapped" "is_ipv6"
2476 "isnull" "isring" "issimple" "is_used_lock" "json_array"
2477 "json_array_append" "json_array_insert" "json_compact" "json_contains"
2478 "json_contains_path" "json_depth" "json_detailed" "json_exists"
2479 "json_extract" "json_insert" "json_keys" "json_length" "json_loose"
2480 "json_merge" "json_object" "json_query" "json_quote" "json_remove"
2481 "json_replace" "json_search" "json_set" "json_type" "json_unquote"
2482 "json_valid" "json_value" "lag" "last_day" "last_insert_id" "lastval"
2483 "last_value" "last_value" "lcase" "lead" "leading" "least" "length"
2484 "linefromtext" "linefromwkb" "linestringfromtext" "linestringfromwkb"
2485 "ln" "load_file" "locate" "log" "log10" "log2" "lower" "lpad" "ltrim"
2486 "makedate" "make_set" "maketime" "master_gtid_wait" "master_pos_wait"
2487 "max" "mbrcontains" "mbrdisjoint" "mbrequal" "mbrintersects"
2488 "mbroverlaps" "mbrtouches" "mbrwithin" "md5" "median"
2489 "mid" "min" "mlinefromtext" "mlinefromwkb" "monthname"
2490 "mpointfromtext" "mpointfromwkb" "mpolyfromtext" "mpolyfromwkb"
2491 "multilinestringfromtext" "multilinestringfromwkb"
2492 "multipointfromtext" "multipointfromwkb" "multipolygonfromtext"
2493 "multipolygonfromwkb" "name_const" "nextval" "now" "nth_value" "ntile"
2494 "ntile" "nullif" "numgeometries" "numinteriorrings" "numpoints" "oct"
2495 "octet_length" "old_password" "ord" "percentile_cont"
2496 "percentile_disc" "percent_rank" "percent_rank" "period_add"
2497 "period_diff" "pi" "pointfromtext" "pointfromwkb" "pointn"
2498 "pointonsurface" "polyfromtext" "polyfromwkb" "polygonfromtext"
2499 "polygonfromwkb" "position" "pow" "power" "quote" "radians"
2500 "rand" "rank" "rank" "regexp" "regexp_instr" "regexp_replace"
2501 "regexp_substr" "release_lock" "repeat" "replace" "reverse" "rlike"
2502 "row_number" "row_number" "rpad" "rtrim" "sec_to_time" "setval" "sha"
2503 "sha1" "sha2" "sign" "sin" "sleep" "soundex" "space"
2504 "spider_bg_direct_sql" "spider_copy_tables" "spider_direct_sql"
2505 "spider_flush_table_mon_cache" "sqrt" "srid" "st_area" "startpoint"
2506 "st_asbinary" "st_astext" "st_aswkb" "st_aswkt" "st_boundary"
2507 "st_buffer" "st_centroid" "st_contains" "st_convexhull" "st_crosses"
2508 "std" "stddev" "stddev_pop" "stddev_samp" "st_difference"
2509 "st_dimension" "st_disjoint" "st_distance" "st_endpoint" "st_envelope"
2510 "st_equals" "st_exteriorring" "st_geomcollfromtext"
2511 "st_geomcollfromwkb" "st_geometrycollectionfromtext"
2512 "st_geometrycollectionfromwkb" "st_geometryfromtext"
2513 "st_geometryfromwkb" "st_geometryn" "st_geometrytype"
2514 "st_geomfromtext" "st_geomfromwkb" "st_interiorringn"
2515 "st_intersection" "st_intersects" "st_isclosed" "st_isempty"
2516 "st_isring" "st_issimple" "st_length" "st_linefromtext"
2517 "st_linefromwkb" "st_linestringfromtext" "st_linestringfromwkb"
2518 "st_numgeometries" "st_numinteriorrings" "st_numpoints" "st_overlaps"
2519 "st_pointfromtext" "st_pointfromwkb" "st_pointn" "st_pointonsurface"
2520 "st_polyfromtext" "st_polyfromwkb" "st_polygonfromtext"
2521 "st_polygonfromwkb" "strcmp" "st_relate" "str_to_date" "st_srid"
2522 "st_startpoint" "st_symdifference" "st_touches" "st_union" "st_within"
2523 "st_x" "st_y" "subdate" "substr" "substring" "substring_index"
2524 "subtime" "sum" "sysdate" "tan" "timediff" "time_format"
2525 "timestampadd" "timestampdiff" "time_to_sec" "to_base64" "to_days"
2526 "to_seconds" "touches" "trailing" "trim" "ucase" "uncompress"
2527 "uncompressed_length" "unhex" "unix_timestamp" "updatexml" "upper"
2528 "user" "utc_date" "utc_time" "utc_timestamp" "uuid" "uuid_short"
2529 "variance" "var_pop" "var_samp" "version" "weekday"
2530 "weekofyear" "weight_string" "within"
2533 ;; MySQL Keywords
2534 (sql-font-lock-keywords-builder 'font-lock-keyword-face nil
2535 "accessible" "action" "add" "after" "against" "all" "alter" "analyze"
2536 "and" "as" "asc" "auto_increment" "avg_row_length" "bdb" "between"
2537 "body" "by" "cascade" "case" "change" "character" "check" "checksum"
2538 "close" "collate" "collation" "column" "columns" "comment" "committed"
2539 "concurrent" "condition" "constraint" "create" "cross" "data"
2540 "database" "databases" "default" "delayed" "delay_key_write" "delete"
2541 "desc" "directory" "disable" "distinct" "distinctrow" "do" "drop"
2542 "dual" "dumpfile" "duplicate" "else" "elseif" "elsif" "enable"
2543 "enclosed" "end" "escaped" "exists" "exit" "explain" "fields" "first"
2544 "for" "force" "foreign" "from" "full" "fulltext" "global" "group"
2545 "handler" "having" "heap" "high_priority" "history" "if" "ignore"
2546 "ignore_server_ids" "in" "index" "infile" "inner" "insert"
2547 "insert_method" "into" "is" "isam" "isolation" "join" "key" "keys"
2548 "kill" "last" "leave" "left" "level" "like" "limit" "linear" "lines"
2549 "load" "local" "lock" "long" "loop" "low_priority"
2550 "master_heartbeat_period" "master_ssl_verify_server_cert" "match"
2551 "max_rows" "maxvalue" "merge" "min_rows" "mode" "modify" "mrg_myisam"
2552 "myisam" "natural" "next" "no" "not" "no_write_to_binlog" "null"
2553 "offset" "oj" "on" "open" "optimize" "optionally" "or" "order" "outer"
2554 "outfile" "over" "package" "pack_keys" "partial" "partition"
2555 "password" "period" "prev" "primary" "procedure" "purge" "quick"
2556 "raid0" "raid_type" "raise" "range" "read" "read_write" "references"
2557 "release" "rename" "repeatable" "require" "resignal" "restrict"
2558 "returning" "right" "rollback" "rollup" "row_format" "rowtype"
2559 "savepoint" "schemas" "select" "separator" "serializable" "session"
2560 "set" "share" "show" "signal" "slow" "spatial" "sql_big_result"
2561 "sql_buffer_result" "sql_cache" "sql_calc_found_rows" "sql_no_cache"
2562 "sql_small_result" "ssl" "starting" "straight_join" "striped"
2563 "system_time" "table" "tables" "temporary" "terminated" "then" "to"
2564 "transaction" "truncate" "type" "uncommitted" "undo" "union" "unique"
2565 "unlock" "update" "use" "using" "values" "versioning" "when" "where"
2566 "while" "window" "with" "write" "xor"
2569 ;; MySQL Data Types
2570 (sql-font-lock-keywords-builder 'font-lock-type-face nil
2571 "bigint" "binary" "bit" "blob" "bool" "boolean" "byte" "char" "curve"
2572 "date" "datetime" "day" "day_hour" "day_microsecond" "day_minute"
2573 "day_second" "dec" "decimal" "double" "enum" "fixed" "float" "float4"
2574 "float8" "geometry" "geometrycollection" "hour" "hour_microsecond"
2575 "hour_minute" "hour_second" "int" "int1" "int2" "int3" "int4" "int8"
2576 "integer" "json" "line" "linearring" "linestring" "longblob"
2577 "longtext" "mediumblob" "mediumint" "mediumtext" "microsecond"
2578 "middleint" "minute" "minute_microsecond" "minute_second" "month"
2579 "multicurve" "multilinestring" "multipoint" "multipolygon"
2580 "multisurface" "national" "numeric" "point" "polygon" "precision"
2581 "quarter" "real" "second" "second_microsecond" "signed" "smallint"
2582 "surface" "text" "time" "timestamp" "tinyblob" "tinyint" "tinytext"
2583 "unsigned" "varbinary" "varchar" "varcharacter" "week" "year" "year2"
2584 "year4" "year_month" "zerofill"
2587 "MySQL SQL keywords used by font-lock.
2589 This variable is used by `sql-mode' and `sql-interactive-mode'. The
2590 regular expressions are created during compilation by calling the
2591 function `regexp-opt'. Therefore, take a look at the source before
2592 you define your own `sql-mode-mysql-font-lock-keywords'.")
2594 (defvar sql-mode-sqlite-font-lock-keywords
2595 (eval-when-compile
2596 (list
2597 ;; SQLite commands
2598 '("^[.].*$" . font-lock-doc-face)
2600 ;; SQLite Keyword
2601 (sql-font-lock-keywords-builder 'font-lock-keyword-face nil
2602 "abort" "action" "add" "after" "all" "alter" "analyze" "and" "as"
2603 "asc" "attach" "autoincrement" "before" "begin" "between" "by"
2604 "cascade" "case" "cast" "check" "collate" "column" "commit" "conflict"
2605 "constraint" "create" "cross" "database" "default" "deferrable"
2606 "deferred" "delete" "desc" "detach" "distinct" "drop" "each" "else"
2607 "end" "escape" "except" "exclusive" "exists" "explain" "fail" "for"
2608 "foreign" "from" "full" "glob" "group" "having" "if" "ignore"
2609 "immediate" "in" "index" "indexed" "initially" "inner" "insert"
2610 "instead" "intersect" "into" "is" "isnull" "join" "key" "left" "like"
2611 "limit" "match" "natural" "no" "not" "notnull" "null" "of" "offset"
2612 "on" "or" "order" "outer" "plan" "pragma" "primary" "query" "raise"
2613 "references" "regexp" "reindex" "release" "rename" "replace"
2614 "restrict" "right" "rollback" "row" "savepoint" "select" "set" "table"
2615 "temp" "temporary" "then" "to" "transaction" "trigger" "union"
2616 "unique" "update" "using" "vacuum" "values" "view" "virtual" "when"
2617 "where"
2619 ;; SQLite Data types
2620 (sql-font-lock-keywords-builder 'font-lock-type-face nil
2621 "int" "integer" "tinyint" "smallint" "mediumint" "bigint" "unsigned"
2622 "big" "int2" "int8" "character" "varchar" "varying" "nchar" "native"
2623 "nvarchar" "text" "clob" "blob" "real" "double" "precision" "float"
2624 "numeric" "number" "decimal" "boolean" "date" "datetime"
2626 ;; SQLite Functions
2627 (sql-font-lock-keywords-builder 'font-lock-builtin-face nil
2628 ;; Core functions
2629 "abs" "changes" "coalesce" "glob" "ifnull" "hex" "last_insert_rowid"
2630 "length" "like" "load_extension" "lower" "ltrim" "max" "min" "nullif"
2631 "quote" "random" "randomblob" "replace" "round" "rtrim" "soundex"
2632 "sqlite_compileoption_get" "sqlite_compileoption_used"
2633 "sqlite_source_id" "sqlite_version" "substr" "total_changes" "trim"
2634 "typeof" "upper" "zeroblob"
2635 ;; Date/time functions
2636 "time" "julianday" "strftime"
2637 "current_date" "current_time" "current_timestamp"
2638 ;; Aggregate functions
2639 "avg" "count" "group_concat" "max" "min" "sum" "total"
2642 "SQLite SQL keywords used by font-lock.
2644 This variable is used by `sql-mode' and `sql-interactive-mode'. The
2645 regular expressions are created during compilation by calling the
2646 function `regexp-opt'. Therefore, take a look at the source before
2647 you define your own `sql-mode-sqlite-font-lock-keywords'.")
2649 (defvar sql-mode-db2-font-lock-keywords nil
2650 "DB2 SQL keywords used by font-lock.
2652 This variable is used by `sql-mode' and `sql-interactive-mode'. The
2653 regular expressions are created during compilation by calling the
2654 function `regexp-opt'. Therefore, take a look at the source before
2655 you define your own `sql-mode-db2-font-lock-keywords'.")
2657 (defvar sql-mode-font-lock-keywords nil
2658 "SQL keywords used by font-lock.
2660 Setting this variable directly no longer has any affect. Use
2661 `sql-product' and `sql-add-product-keywords' to control the
2662 highlighting rules in SQL mode.")
2666 ;;; SQL Product support functions
2668 (defun sql-read-product (prompt &optional initial)
2669 "Read a valid SQL product."
2670 (let ((init (or (and initial (symbol-name initial)) "ansi")))
2671 (intern (completing-read
2672 prompt
2673 (mapcar (lambda (info) (symbol-name (car info)))
2674 sql-product-alist)
2675 nil 'require-match
2676 init 'sql-product-history init))))
2678 (defun sql-add-product (product display &rest plist)
2679 "Add support for a database product in `sql-mode'.
2681 Add PRODUCT to `sql-product-alist' which enables `sql-mode' to
2682 properly support syntax highlighting and interactive interaction.
2683 DISPLAY is the name of the SQL product that will appear in the
2684 menu bar and in messages. PLIST initializes the product
2685 configuration."
2687 ;; Don't do anything if the product is already supported
2688 (if (assoc product sql-product-alist)
2689 (user-error "Product `%s' is already defined" product)
2691 ;; Add product to the alist
2692 (add-to-list 'sql-product-alist `(,product :name ,display . ,plist))
2693 ;; Add a menu item to the SQL->Product menu
2694 (easy-menu-add-item sql-mode-menu '("Product")
2695 ;; Each product is represented by a radio
2696 ;; button with it's display name.
2697 `[,display
2698 (sql-set-product ',product)
2699 :style radio
2700 :selected (eq sql-product ',product)]
2701 ;; Maintain the product list in
2702 ;; (case-insensitive) alphabetic order of the
2703 ;; display names. Loop thru each keymap item
2704 ;; looking for an item whose display name is
2705 ;; after this product's name.
2706 (let ((next-item)
2707 (down-display (downcase display)))
2708 (map-keymap (lambda (k b)
2709 (when (and (not next-item)
2710 (string-lessp down-display
2711 (downcase (cadr b))))
2712 (setq next-item k)))
2713 (easy-menu-get-map sql-mode-menu '("Product")))
2714 next-item))
2715 product))
2717 (defun sql-del-product (product)
2718 "Remove support for PRODUCT in `sql-mode'."
2720 ;; Remove the menu item based on the display name
2721 (easy-menu-remove-item sql-mode-menu '("Product") (sql-get-product-feature product :name))
2722 ;; Remove the product alist item
2723 (setq sql-product-alist (assq-delete-all product sql-product-alist))
2724 nil)
2726 (defun sql-set-product-feature (product feature newvalue)
2727 "Set FEATURE of database PRODUCT to NEWVALUE.
2729 The PRODUCT must be a symbol which identifies the database
2730 product. The product must have already exist on the product
2731 list. See `sql-add-product' to add new products. The FEATURE
2732 argument must be a plist keyword accepted by
2733 `sql-product-alist'."
2735 (let* ((p (assoc product sql-product-alist)) ;; (PRODUCT :f v ...)
2736 (v (plist-member (cdr p) feature))) ;; (:FEATURE value ...) or null
2738 (if p
2739 (if (member feature sql-indirect-features) ; is indirect
2740 (if v
2741 (if (car (cdr v))
2742 (if (symbolp (car (cdr v)))
2743 ;; Indirect reference
2744 (set (car (cdr v)) newvalue)
2745 ;; indirect is not a symbol
2746 (error "The value of `%s' for `%s' is not a symbol" feature product))
2747 ;; keyword present, set the indirect variable name
2748 (if (symbolp newvalue)
2749 (if (cdr v)
2750 (setf (car (cdr v)) newvalue)
2751 (setf (cdr v) (list newvalue)))
2752 (error "The indirect variable of `%s' for `%s' must be a symbol" feature product)))
2753 ;; not present; insert list
2754 (setq v (list feature newvalue))
2755 (setf (cdr (cdr v)) (cdr p))
2756 (setf (cdr p) v))
2757 ;; Not an indirect feature
2758 (if v
2759 (if (cdr v)
2760 (setf (car (cdr v)) newvalue)
2761 (setf (cdr v) (list newvalue)))
2762 ;; no value; insert into the list
2763 (setq v (list feature newvalue))
2764 (setf (cdr (cdr v)) (cdr p))
2765 (setf (cdr p) v)))
2766 (error "`%s' is not a known product; use `sql-add-product' to add it first" product))))
2768 (defun sql-get-product-feature (product feature &optional fallback not-indirect)
2769 "Lookup FEATURE associated with a SQL PRODUCT.
2771 If the FEATURE is nil for PRODUCT, and FALLBACK is specified,
2772 then the FEATURE associated with the FALLBACK product is
2773 returned.
2775 If the FEATURE is in the list `sql-indirect-features', and the
2776 NOT-INDIRECT parameter is not set, then the value of the symbol
2777 stored in the connect alist is returned.
2779 See `sql-product-alist' for a list of products and supported features."
2780 (let* ((p (assoc product sql-product-alist))
2781 (v (plist-get (cdr p) feature)))
2783 (if p
2784 ;; If no value and fallback, lookup feature for fallback
2785 (if (and (not v)
2786 fallback
2787 (not (eq product fallback)))
2788 (sql-get-product-feature fallback feature)
2790 (if (and
2791 (member feature sql-indirect-features)
2792 (not not-indirect)
2793 (symbolp v))
2794 (symbol-value v)
2796 (error "`%s' is not a known product; use `sql-add-product' to add it first." product)
2797 nil)))
2799 (defun sql-product-font-lock (keywords-only imenu)
2800 "Configure font-lock and imenu with product-specific settings.
2802 The KEYWORDS-ONLY flag is passed to font-lock to specify whether
2803 only keywords should be highlighted and syntactic highlighting
2804 skipped. The IMENU flag indicates whether `imenu' should also be
2805 configured."
2807 (let
2808 ;; Get the product-specific syntax-alist.
2809 ((syntax-alist (sql-product-font-lock-syntax-alist)))
2811 ;; Get the product-specific keywords.
2812 (setq-local sql-mode-font-lock-keywords
2813 (append
2814 (unless (eq sql-product 'ansi)
2815 (sql-get-product-feature sql-product :font-lock))
2816 ;; Always highlight ANSI keywords
2817 (sql-get-product-feature 'ansi :font-lock)
2818 ;; Fontify object names in CREATE, DROP and ALTER DDL
2819 ;; statements
2820 (list sql-mode-font-lock-object-name)))
2822 ;; Setup font-lock. Force re-parsing of `font-lock-defaults'.
2823 (kill-local-variable 'font-lock-set-defaults)
2824 (setq-local font-lock-defaults
2825 (list 'sql-mode-font-lock-keywords
2826 keywords-only t syntax-alist))
2828 ;; Force font lock to reinitialize if it is already on
2829 ;; Otherwise, we can wait until it can be started.
2830 (when font-lock-mode
2831 (font-lock-mode-internal nil)
2832 (font-lock-mode-internal t))
2834 (add-hook 'font-lock-mode-hook
2835 (lambda ()
2836 ;; Provide defaults for new font-lock faces.
2837 (defvar font-lock-builtin-face
2838 (if (boundp 'font-lock-preprocessor-face)
2839 font-lock-preprocessor-face
2840 font-lock-keyword-face))
2841 (defvar font-lock-doc-face font-lock-string-face))
2842 nil t)
2844 ;; Setup imenu; it needs the same syntax-alist.
2845 (when imenu
2846 (setq imenu-syntax-alist syntax-alist))))
2848 ;;;###autoload
2849 (defun sql-add-product-keywords (product keywords &optional append)
2850 "Add highlighting KEYWORDS for SQL PRODUCT.
2852 PRODUCT should be a symbol, the name of a SQL product, such as
2853 `oracle'. KEYWORDS should be a list; see the variable
2854 `font-lock-keywords'. By default they are added at the beginning
2855 of the current highlighting list. If optional argument APPEND is
2856 `set', they are used to replace the current highlighting list.
2857 If APPEND is any other non-nil value, they are added at the end
2858 of the current highlighting list.
2860 For example:
2862 (sql-add-product-keywords \\='ms
2863 \\='((\"\\\\b\\\\w+_t\\\\b\" . font-lock-type-face)))
2865 adds a fontification pattern to fontify identifiers ending in
2866 `_t' as data types."
2868 (let* ((sql-indirect-features nil)
2869 (font-lock-var (sql-get-product-feature product :font-lock))
2870 (old-val))
2872 (setq old-val (symbol-value font-lock-var))
2873 (set font-lock-var
2874 (if (eq append 'set)
2875 keywords
2876 (if append
2877 (append old-val keywords)
2878 (append keywords old-val))))))
2880 (defun sql-for-each-login (login-params body)
2881 "Iterate through login parameters and return a list of results."
2882 (delq nil
2883 (mapcar
2884 (lambda (param)
2885 (let ((token (or (car-safe param) param))
2886 (plist (cdr-safe param)))
2887 (funcall body token plist)))
2888 login-params)))
2892 ;;; Functions to switch highlighting
2894 (defun sql-product-syntax-table ()
2895 (let ((table (copy-syntax-table sql-mode-syntax-table)))
2896 (mapc (lambda (entry)
2897 (modify-syntax-entry (car entry) (cdr entry) table))
2898 (sql-get-product-feature sql-product :syntax-alist))
2899 table))
2901 (defun sql-product-font-lock-syntax-alist ()
2902 (append
2903 ;; Change all symbol character to word characters
2904 (mapcar
2905 (lambda (entry) (if (string= (substring (cdr entry) 0 1) "_")
2906 (cons (car entry)
2907 (concat "w" (substring (cdr entry) 1)))
2908 entry))
2909 (sql-get-product-feature sql-product :syntax-alist))
2910 '((?_ . "w"))))
2912 (defun sql-highlight-product ()
2913 "Turn on the font highlighting for the SQL product selected."
2914 (when (derived-mode-p 'sql-mode)
2915 ;; Enhance the syntax table for the product
2916 (set-syntax-table (sql-product-syntax-table))
2918 ;; Setup font-lock
2919 (sql-product-font-lock nil t)
2921 ;; Set the mode name to include the product.
2922 (setq mode-name (concat "SQL[" (or (sql-get-product-feature sql-product :name)
2923 (symbol-name sql-product)) "]"))))
2925 (defun sql-set-product (product)
2926 "Set `sql-product' to PRODUCT and enable appropriate highlighting."
2927 (interactive
2928 (list (sql-read-product "SQL product: ")))
2929 (if (stringp product) (setq product (intern product)))
2930 (when (not (assoc product sql-product-alist))
2931 (user-error "SQL product %s is not supported; treated as ANSI" product)
2932 (setq product 'ansi))
2934 ;; Save product setting and fontify.
2935 (setq sql-product product)
2936 (sql-highlight-product))
2937 (defalias 'sql-set-dialect 'sql-set-product)
2939 (defun sql-buffer-hidden-p (buf)
2940 "Is the buffer hidden?"
2941 (string-prefix-p " "
2942 (cond
2943 ((stringp buf)
2944 (when (get-buffer buf)
2945 buf))
2946 ((bufferp buf)
2947 (buffer-name buf))
2948 (t nil))))
2950 (defun sql-display-buffer (buf)
2951 "Display a SQLi buffer based on `sql-display-sqli-buffer-function'.
2953 If BUF is hidden or `sql-display-sqli-buffer-function' is nil,
2954 then the buffer will not be displayed. Otherwise the BUF is
2955 displayed."
2956 (unless (sql-buffer-hidden-p buf)
2957 (cond
2958 ((eq sql-display-sqli-buffer-function t)
2959 (pop-to-buffer buf))
2960 ((not sql-display-sqli-buffer-function)
2961 nil)
2962 ((functionp sql-display-sqli-buffer-function)
2963 (funcall sql-display-sqli-buffer-function buf))
2965 (message "Invalid setting of `sql-display-sqli-buffer-function'")
2966 (pop-to-buffer buf)))))
2968 (defun sql-make-progress-reporter (buf message &optional min-value max-value current-value min-change min-time)
2969 "Make a progress reporter if BUF is not hidden."
2970 (unless (or (sql-buffer-hidden-p buf)
2971 (not sql-display-sqli-buffer-function))
2972 (make-progress-reporter message min-value max-value current-value min-change min-time)))
2974 (defun sql-progress-reporter-update (reporter &optional value)
2975 "Report progress of an operation in the echo area."
2976 (when reporter
2977 (progress-reporter-update reporter value)))
2979 (defun sql-progress-reporter-done (reporter)
2980 "Print reporter’s message followed by word \"done\" in echo area."
2981 (when reporter
2982 (progress-reporter-done reporter)))
2984 ;;; SMIE support
2986 ;; Needs a lot more love than I can provide. --Stef
2988 ;; (require 'smie)
2990 ;; (defconst sql-smie-grammar
2991 ;; (smie-prec2->grammar
2992 ;; (smie-bnf->prec2
2993 ;; ;; Partly based on https://www.h2database.com/html/grammar.html
2994 ;; '((cmd ("SELECT" select-exp "FROM" select-table-exp)
2995 ;; )
2996 ;; (select-exp ("*") (exp) (exp "AS" column-alias))
2997 ;; (column-alias)
2998 ;; (select-table-exp (table-exp "WHERE" exp) (table-exp))
2999 ;; (table-exp)
3000 ;; (exp ("CASE" exp "WHEN" exp "THEN" exp "ELSE" exp "END")
3001 ;; ("CASE" exp "WHEN" exp "THEN" exp "END"))
3002 ;; ;; Random ad-hoc additions.
3003 ;; (foo (foo "," foo))
3004 ;; )
3005 ;; '((assoc ",")))))
3007 ;; (defun sql-smie-rules (kind token)
3008 ;; (pcase (cons kind token)
3009 ;; (`(:list-intro . ,_) t)
3010 ;; (`(:before . "(") (smie-rule-parent))))
3012 ;;; Motion Functions
3014 (defun sql-statement-regexp (prod)
3015 (let* ((ansi-stmt (or (sql-get-product-feature 'ansi :statement) "select"))
3016 (prod-stmt (sql-get-product-feature prod :statement)))
3017 (concat "^\\<"
3018 (if prod-stmt
3019 (concat "\\(" ansi-stmt "\\|" prod-stmt "\\)")
3020 ansi-stmt)
3021 "\\>")))
3023 (defun sql-beginning-of-statement (arg)
3024 "Move to the beginning of the current SQL statement."
3025 (interactive "p")
3027 (let ((here (point))
3028 (regexp (sql-statement-regexp sql-product))
3029 last next)
3031 ;; Go to the end of the statement before the start we desire
3032 (setq last (or (sql-end-of-statement (- arg))
3033 (point-min)))
3034 ;; And find the end after that
3035 (setq next (or (sql-end-of-statement 1)
3036 (point-max)))
3038 ;; Our start must be between them
3039 (goto-char last)
3040 ;; Find a beginning-of-stmt that's not in a comment
3041 (while (and (re-search-forward regexp next t 1)
3042 (nth 7 (syntax-ppss)))
3043 (goto-char (match-end 0)))
3044 (goto-char
3045 (if (match-data)
3046 (match-beginning 0)
3047 last))
3048 (beginning-of-line)
3049 ;; If we didn't move, try again
3050 (when (= here (point))
3051 (sql-beginning-of-statement (* 2 (cl-signum arg))))))
3053 (defun sql-end-of-statement (arg)
3054 "Move to the end of the current SQL statement."
3055 (interactive "p")
3056 (let ((term (or (sql-get-product-feature sql-product :terminator) ";"))
3057 (re-search (if (> 0 arg) 're-search-backward 're-search-forward))
3058 (here (point))
3059 (n 0))
3060 (when (consp term)
3061 (setq term (car term)))
3062 ;; Iterate until we've moved the desired number of stmt ends
3063 (while (not (= (cl-signum arg) 0))
3064 ;; if we're looking at the terminator, jump by 2
3065 (if (or (and (> 0 arg) (looking-back term nil))
3066 (and (< 0 arg) (looking-at term)))
3067 (setq n 2)
3068 (setq n 1))
3069 ;; If we found another end-of-stmt
3070 (if (not (apply re-search term nil t n nil))
3071 (setq arg 0)
3072 ;; count it if we're not in a comment
3073 (unless (nth 7 (syntax-ppss))
3074 (setq arg (- arg (cl-signum arg))))))
3075 (goto-char (if (match-data)
3076 (match-end 0)
3077 here))))
3079 ;;; Small functions
3081 (defun sql-magic-go (arg)
3082 "Insert \"o\" and call `comint-send-input'.
3083 `sql-electric-stuff' must be the symbol `go'."
3084 (interactive "P")
3085 (self-insert-command (prefix-numeric-value arg))
3086 (if (and (equal sql-electric-stuff 'go)
3087 (save-excursion
3088 (comint-bol nil)
3089 (looking-at "go\\b")))
3090 (comint-send-input)))
3091 (put 'sql-magic-go 'delete-selection t)
3093 (defun sql-magic-semicolon (arg)
3094 "Insert semicolon and call `comint-send-input'.
3095 `sql-electric-stuff' must be the symbol `semicolon'."
3096 (interactive "P")
3097 (self-insert-command (prefix-numeric-value arg))
3098 (if (equal sql-electric-stuff 'semicolon)
3099 (comint-send-input)))
3100 (put 'sql-magic-semicolon 'delete-selection t)
3102 (defun sql-accumulate-and-indent ()
3103 "Continue SQL statement on the next line."
3104 (interactive)
3105 (if (fboundp 'comint-accumulate)
3106 (comint-accumulate)
3107 (newline))
3108 (indent-according-to-mode))
3110 (defun sql-help-list-products (indent freep)
3111 "Generate listing of products available for use under SQLi.
3113 List products with :free-software attribute set to FREEP. Indent
3114 each line with INDENT."
3116 (let (sqli-func doc)
3117 (setq doc "")
3118 (dolist (p sql-product-alist)
3119 (setq sqli-func (intern (concat "sql-" (symbol-name (car p)))))
3121 (if (and (fboundp sqli-func)
3122 (eq (sql-get-product-feature (car p) :free-software) freep))
3123 (setq doc
3124 (concat doc
3125 indent
3126 (or (sql-get-product-feature (car p) :name)
3127 (symbol-name (car p)))
3128 ":\t"
3129 "\\["
3130 (symbol-name sqli-func)
3131 "]\n"))))
3132 doc))
3134 (defun sql-help ()
3135 "Show short help for the SQL modes."
3136 (interactive)
3137 (describe-function 'sql-help))
3138 (put 'sql-help 'function-documentation '(sql--make-help-docstring))
3140 (defvar sql--help-docstring
3141 "Show short help for the SQL modes.
3142 Use an entry function to open an interactive SQL buffer. This buffer is
3143 usually named `*SQL*'. The name of the major mode is SQLi.
3145 Use the following commands to start a specific SQL interpreter:
3147 \\\\FREE
3149 Other non-free SQL implementations are also supported:
3151 \\\\NONFREE
3153 But we urge you to choose a free implementation instead of these.
3155 You can also use \\[sql-product-interactive] to invoke the
3156 interpreter for the current `sql-product'.
3158 Once you have the SQLi buffer, you can enter SQL statements in the
3159 buffer. The output generated is appended to the buffer and a new prompt
3160 is generated. See the In/Out menu in the SQLi buffer for some functions
3161 that help you navigate through the buffer, the input history, etc.
3163 If you have a really complex SQL statement or if you are writing a
3164 procedure, you can do this in a separate buffer. Put the new buffer in
3165 `sql-mode' by calling \\[sql-mode]. The name of this buffer can be
3166 anything. The name of the major mode is SQL.
3168 In this SQL buffer (SQL mode), you can send the region or the entire
3169 buffer to the interactive SQL buffer (SQLi mode). The results are
3170 appended to the SQLi buffer without disturbing your SQL buffer.")
3172 (defun sql--make-help-docstring ()
3173 "Return a docstring for `sql-help' listing loaded SQL products."
3174 (let ((doc sql--help-docstring))
3175 ;; Insert FREE software list
3176 (when (string-match "^\\(\\s-*\\)[\\][\\]FREE\\s-*$" doc 0)
3177 (setq doc (replace-match (sql-help-list-products (match-string 1 doc) t)
3178 t t doc 0)))
3179 ;; Insert non-FREE software list
3180 (when (string-match "^\\(\\s-*\\)[\\][\\]NONFREE\\s-*$" doc 0)
3181 (setq doc (replace-match (sql-help-list-products (match-string 1 doc) nil)
3182 t t doc 0)))
3183 doc))
3185 (defun sql-default-value (var)
3186 "Fetch the value of a variable.
3188 If the current buffer is in `sql-interactive-mode', then fetch
3189 the global value, otherwise use the buffer local value."
3190 (if (derived-mode-p 'sql-interactive-mode)
3191 (default-value var)
3192 (buffer-local-value var (current-buffer))))
3194 (defun sql-get-login-ext (symbol prompt history-var plist)
3195 "Prompt user with extended login parameters.
3197 The global value of SYMBOL is the last value and the global value
3198 of the SYMBOL is set based on the user's input.
3200 If PLIST is nil, then the user is simply prompted for a string
3201 value.
3203 The property `:default' specifies the default value. If the
3204 `:number' property is non-nil then ask for a number.
3206 The `:file' property prompts for a file name that must match the
3207 regexp pattern specified in its value.
3209 The `:completion' property prompts for a string specified by its
3210 value. (The property value is used as the PREDICATE argument to
3211 `completing-read'.)
3213 For both `:file' and `:completion', there can also be a
3214 `:must-match' property that controls REQUIRE-MATCH parameter to
3215 `completing-read'."
3217 (set-default
3218 symbol
3219 (let* ((default (plist-get plist :default))
3220 (last-value (sql-default-value symbol))
3221 (prompt-def
3222 (if default
3223 (if (string-match "\\(\\):[ \t]*\\'" prompt)
3224 (replace-match (format " (default \"%s\")" default) t t prompt 1)
3225 (replace-regexp-in-string "[ \t]*\\'"
3226 (format " (default \"%s\") " default)
3227 prompt t t))
3228 prompt))
3229 (use-dialog-box nil))
3230 (cond
3231 ((plist-member plist :file)
3232 (let ((file-name
3233 (read-file-name prompt
3234 (file-name-directory last-value)
3235 default
3236 (if (plist-member plist :must-match)
3237 (plist-get plist :must-match)
3239 (file-name-nondirectory last-value)
3240 (when (plist-get plist :file)
3241 `(lambda (f)
3242 (if (not (file-regular-p f))
3244 (string-match
3245 (concat "\\<" ,(plist-get plist :file) "\\>")
3246 (file-name-nondirectory f))))))))
3247 (if (string= file-name "")
3249 (expand-file-name file-name))))
3251 ((plist-member plist :completion)
3252 (completing-read prompt-def
3253 (plist-get plist :completion)
3255 (if (plist-member plist :must-match)
3256 (plist-get plist :must-match)
3258 last-value
3259 history-var
3260 default))
3262 ((plist-get plist :number)
3263 (read-number prompt (or default last-value 0)))
3266 (read-string prompt-def last-value history-var default))))))
3268 (defun sql-get-login (&rest what)
3269 "Get username, password and database from the user.
3271 The variables `sql-user', `sql-password', `sql-server', and
3272 `sql-database' can be customized. They are used as the default values.
3273 Usernames, servers and databases are stored in `sql-user-history',
3274 `sql-server-history' and `database-history'. Passwords are not stored
3275 in a history.
3277 Parameter WHAT is a list of tokens passed as arguments in the
3278 function call. The function asks for the username if WHAT
3279 contains the symbol `user', for the password if it contains the
3280 symbol `password', for the server if it contains the symbol
3281 `server', and for the database if it contains the symbol
3282 `database'. The members of WHAT are processed in the order in
3283 which they are provided.
3285 If the `sql-password-wallet' is non-nil and WHAT contains the
3286 `password' token, then the `password' token will be pushed to the
3287 end to be sure that all of the values can be fed to the wallet.
3289 Each token may also be a list with the token in the car and a
3290 plist of options as the cdr. The following properties are
3291 supported:
3293 :file <filename-regexp>
3294 :completion <list-of-strings-or-function>
3295 :default <default-value>
3296 :number t
3298 In order to ask the user for username, password and database, call the
3299 function like this: (sql-get-login \\='user \\='password \\='database)."
3301 ;; Push the password to the end if we have a wallet
3302 (when (and sql-password-wallet
3303 (fboundp sql-password-search-wallet-function)
3304 (member 'password what))
3305 (setq what (append (cl-delete 'password what)
3306 '(password))))
3308 ;; Prompt for each parameter
3309 (dolist (w what)
3310 (let ((plist (cdr-safe w)))
3311 (pcase (or (car-safe w) w)
3312 ('user
3313 (sql-get-login-ext 'sql-user "User: " 'sql-user-history plist))
3315 ('password
3316 (setq-default sql-password
3317 (if (and sql-password-wallet
3318 (fboundp sql-password-search-wallet-function))
3319 (let ((password (funcall sql-password-search-wallet-function
3320 sql-password-wallet
3321 sql-product
3322 sql-user
3323 sql-server
3324 sql-database
3325 sql-port)))
3326 (if password
3327 password
3328 (read-passwd "Password: " nil (sql-default-value 'sql-password))))
3329 (read-passwd "Password: " nil (sql-default-value 'sql-password)))))
3331 ('server
3332 (sql-get-login-ext 'sql-server "Server: " 'sql-server-history plist))
3334 ('database
3335 (sql-get-login-ext 'sql-database "Database: "
3336 'sql-database-history plist))
3338 ('port
3339 (sql-get-login-ext 'sql-port "Port: "
3340 nil (append '(:number t) plist)))))))
3342 (defun sql-find-sqli-buffer (&optional product connection)
3343 "Return the name of the current default SQLi buffer or nil.
3344 In order to qualify, the SQLi buffer must be alive, be in
3345 `sql-interactive-mode' and have a process."
3346 (let ((buf sql-buffer)
3347 (prod (or product sql-product)))
3349 ;; Current sql-buffer, if there is one.
3350 (and (sql-buffer-live-p buf prod connection)
3351 buf)
3352 ;; Global sql-buffer
3353 (and (setq buf (default-value 'sql-buffer))
3354 (sql-buffer-live-p buf prod connection)
3355 buf)
3356 ;; Look thru each buffer
3357 (car (apply #'append
3358 (mapcar (lambda (b)
3359 (and (sql-buffer-live-p b prod connection)
3360 (list (buffer-name b))))
3361 (buffer-list)))))))
3363 (defun sql-set-sqli-buffer-generally ()
3364 "Set SQLi buffer for all SQL buffers that have none.
3365 This function checks all SQL buffers for their SQLi buffer. If their
3366 SQLi buffer is nonexistent or has no process, it is set to the current
3367 default SQLi buffer. The current default SQLi buffer is determined
3368 using `sql-find-sqli-buffer'. If `sql-buffer' is set,
3369 `sql-set-sqli-hook' is run."
3370 (interactive)
3371 (save-excursion
3372 (let ((buflist (buffer-list))
3373 (default-buffer (sql-find-sqli-buffer)))
3374 (setq-default sql-buffer default-buffer)
3375 (while (not (null buflist))
3376 (let ((candidate (car buflist)))
3377 (set-buffer candidate)
3378 (if (and (derived-mode-p 'sql-mode)
3379 (not (sql-buffer-live-p sql-buffer)))
3380 (progn
3381 (setq sql-buffer default-buffer)
3382 (when default-buffer
3383 (run-hooks 'sql-set-sqli-hook)))))
3384 (setq buflist (cdr buflist))))))
3386 (defun sql-set-sqli-buffer ()
3387 "Set the SQLi buffer SQL strings are sent to.
3389 Call this function in a SQL buffer in order to set the SQLi buffer SQL
3390 strings are sent to. Calling this function sets `sql-buffer' and runs
3391 `sql-set-sqli-hook'.
3393 If you call it from a SQL buffer, this sets the local copy of
3394 `sql-buffer'.
3396 If you call it from anywhere else, it sets the global copy of
3397 `sql-buffer'."
3398 (interactive)
3399 (let ((default-buffer (sql-find-sqli-buffer)))
3400 (if (null default-buffer)
3401 (sql-product-interactive)
3402 (let ((new-buffer (read-buffer "New SQLi buffer: " default-buffer t)))
3403 (if (null (sql-buffer-live-p new-buffer))
3404 (user-error "Buffer %s is not a working SQLi buffer" new-buffer)
3405 (when new-buffer
3406 (setq sql-buffer new-buffer)
3407 (run-hooks 'sql-set-sqli-hook)))))))
3409 (defun sql-show-sqli-buffer ()
3410 "Display the current SQLi buffer.
3412 This is the buffer SQL strings are sent to.
3413 It is stored in the variable `sql-buffer'.
3415 See also `sql-help' on how to create such a buffer."
3416 (interactive)
3417 (unless (and sql-buffer (buffer-live-p (get-buffer sql-buffer))
3418 (get-buffer-process sql-buffer))
3419 (sql-set-sqli-buffer))
3420 (display-buffer sql-buffer))
3422 (defun sql-make-alternate-buffer-name (&optional product)
3423 "Return a string that can be used to rename a SQLi buffer.
3424 This is used to set `sql-alternate-buffer-name' within
3425 `sql-interactive-mode'.
3427 If the session was started with `sql-connect' then the alternate
3428 name would be the name of the connection.
3430 Otherwise, it uses the parameters identified by the :sqlilogin
3431 parameter.
3433 If all else fails, the alternate name would be the user and
3434 server/database name."
3436 (let ((name ""))
3438 ;; Build a name using the :sqli-login setting
3439 (setq name
3440 (apply #'concat
3441 (cdr
3442 (apply #'append nil
3443 (sql-for-each-login
3444 (sql-get-product-feature (or product sql-product) :sqli-login)
3445 (lambda (token plist)
3446 (pcase token
3447 ('user
3448 (unless (string= "" sql-user)
3449 (list "/" sql-user)))
3450 ('port
3451 (unless (or (not (numberp sql-port))
3452 (= 0 sql-port))
3453 (list ":" (number-to-string sql-port))))
3454 ('server
3455 (unless (string= "" sql-server)
3456 (list "."
3457 (if (plist-member plist :file)
3458 (file-name-nondirectory sql-server)
3459 sql-server))))
3460 ('database
3461 (unless (string= "" sql-database)
3462 (list "@"
3463 (if (plist-member plist :file)
3464 (file-name-nondirectory sql-database)
3465 sql-database))))
3467 ;; (`password nil)
3468 (_ nil))))))))
3470 ;; If there's a connection, use it and the name thus far
3471 (if sql-connection
3472 (format "<%s>%s" sql-connection (or name ""))
3474 ;; If there is no name, try to create something meaningful
3475 (if (string= "" (or name ""))
3476 (concat
3477 (if (string= "" sql-user)
3478 (if (string= "" (user-login-name))
3480 (concat (user-login-name) "/"))
3481 (concat sql-user "/"))
3482 (if (string= "" sql-database)
3483 (if (string= "" sql-server)
3484 (system-name)
3485 sql-server)
3486 sql-database))
3488 ;; Use the name we've got
3489 name))))
3491 (defun sql-generate-unique-sqli-buffer-name (product base)
3492 "Generate a new, unique buffer name for a SQLi buffer.
3494 Append a sequence number until a unique name is found."
3495 (let ((base-name (substring-no-properties
3496 (if base
3497 (if (stringp base)
3498 base
3499 (format "%S" base))
3500 (or (sql-get-product-feature product :name)
3501 (symbol-name product)))))
3502 buf-fmt-1st
3503 buf-fmt-rest)
3505 ;; Calculate buffer format
3506 (if (string-blank-p base-name)
3507 (setq buf-fmt-1st "*SQL*"
3508 buf-fmt-rest "*SQL-%d*")
3509 (setq buf-fmt-1st (format "*SQL: %s*" base-name)
3510 buf-fmt-rest (format "*SQL: %s-%%d*" base-name)))
3512 ;; See if we can find an unused buffer
3513 (let ((buf-name buf-fmt-1st)
3514 (i 1))
3515 (while (if (sql-is-sqli-buffer-p buf-name)
3516 (comint-check-proc buf-name)
3517 (buffer-live-p (get-buffer buf-name)))
3518 ;; Check a sequence number on the BASE
3519 (setq buf-name (format buf-fmt-rest i)
3520 i (1+ i)))
3522 buf-name)))
3524 (defun sql-rename-buffer (&optional new-name)
3525 "Rename a SQL interactive buffer.
3527 Prompts for the new name if command is preceded by
3528 \\[universal-argument]. If no buffer name is provided, then the
3529 `sql-alternate-buffer-name' is used.
3531 The actual buffer name set will be \"*SQL: NEW-NAME*\". If
3532 NEW-NAME is empty, then the buffer name will be \"*SQL*\"."
3533 (interactive "P")
3535 (if (not (derived-mode-p 'sql-interactive-mode))
3536 (user-error "Current buffer is not a SQL interactive buffer")
3538 (setq sql-alternate-buffer-name
3539 (substring-no-properties
3540 (cond
3541 ((stringp new-name)
3542 new-name)
3543 ((consp new-name)
3544 (read-string "Buffer name (\"*SQL: XXX*\"; enter `XXX'): "
3545 sql-alternate-buffer-name))
3547 sql-alternate-buffer-name))))
3549 (rename-buffer
3550 (sql-generate-unique-sqli-buffer-name sql-product
3551 sql-alternate-buffer-name)
3552 t)))
3554 (defun sql-copy-column ()
3555 "Copy current column to the end of buffer.
3556 Inserts SELECT or commas if appropriate."
3557 (interactive)
3558 (let ((column))
3559 (save-excursion
3560 (setq column (buffer-substring-no-properties
3561 (progn (forward-char 1) (backward-sexp 1) (point))
3562 (progn (forward-sexp 1) (point))))
3563 (goto-char (point-max))
3564 (let ((bol (comint-line-beginning-position)))
3565 (cond
3566 ;; if empty command line, insert SELECT
3567 ((= bol (point))
3568 (insert "SELECT "))
3569 ;; else if appending to INTO .* (, SELECT or ORDER BY, insert a comma
3570 ((save-excursion
3571 (re-search-backward "\\b\\(\\(into\\s-+\\S-+\\s-+(\\)\\|select\\|order by\\) .+"
3572 bol t))
3573 (insert ", "))
3574 ;; else insert a space
3576 (if (eq (preceding-char) ?\s)
3578 (insert " ")))))
3579 ;; in any case, insert the column
3580 (insert column)
3581 (message "%s" column))))
3583 ;; On Windows, SQL*Plus for Oracle turns on full buffering for stdout
3584 ;; if it is not attached to a character device; therefore placeholder
3585 ;; replacement by SQL*Plus is fully buffered. The workaround lets
3586 ;; Emacs query for the placeholders.
3588 (defvar sql-placeholder-history nil
3589 "History of placeholder values used.")
3591 (defun sql-placeholders-filter (string)
3592 "Replace placeholders in STRING.
3593 Placeholders are words starting with an ampersand like &this."
3595 (when sql-oracle-scan-on
3596 (let ((start 0)
3597 (replacement ""))
3598 (while (string-match "&?&\\(\\(?:\\sw\\|\\s_\\)+\\)[.]?" string start)
3599 (setq replacement (read-from-minibuffer
3600 (format "Enter value for %s: "
3601 (propertize (match-string 1 string)
3602 'face 'font-lock-variable-name-face))
3603 nil nil nil 'sql-placeholder-history)
3604 string (replace-match replacement t t string)
3605 start (+ (match-beginning 1) (length replacement))))))
3606 string)
3608 ;; Using DB2 interactively, newlines must be escaped with " \".
3609 ;; The space before the backslash is relevant.
3611 (defun sql-escape-newlines-filter (string)
3612 "Escape newlines in STRING.
3613 Every newline in STRING will be preceded with a space and a backslash."
3614 (if (not sql-db2-escape-newlines)
3615 string
3616 (let ((result "") (start 0) mb me)
3617 (while (string-match "\n" string start)
3618 (setq mb (match-beginning 0)
3619 me (match-end 0)
3620 result (concat result
3621 (substring string start mb)
3622 (if (and (> mb 1)
3623 (string-equal " \\" (substring string (- mb 2) mb)))
3624 "" " \\\n"))
3625 start me))
3626 (concat result (substring string start)))))
3630 ;;; Input sender for SQLi buffers
3632 (defvar sql-output-newline-count 0
3633 "Number of newlines in the input string.
3635 Allows the suppression of continuation prompts.")
3637 (defun sql-input-sender (proc string)
3638 "Send STRING to PROC after applying filters."
3640 (let* ((product (buffer-local-value 'sql-product (process-buffer proc)))
3641 (filter (sql-get-product-feature product :input-filter)))
3643 ;; Apply filter(s)
3644 (cond
3645 ((not filter)
3646 nil)
3647 ((functionp filter)
3648 (setq string (funcall filter string)))
3649 ((listp filter)
3650 (mapc (lambda (f) (setq string (funcall f string))) filter))
3651 (t nil))
3653 ;; Count how many newlines in the string
3654 (setq sql-output-newline-count
3655 (apply #'+ (mapcar (lambda (ch) (if (eq ch ?\n) 1 0))
3656 string)))
3658 ;; Send the string
3659 (comint-simple-send proc string)))
3661 ;;; Strip out continuation prompts
3663 (defvar sql-preoutput-hold nil)
3665 (defun sql-starts-with-prompt-re ()
3666 "Anchor the prompt expression at the beginning of the output line.
3667 Remove the start of line regexp."
3668 (concat "\\`" comint-prompt-regexp))
3670 (defun sql-ends-with-prompt-re ()
3671 "Anchor the prompt expression at the end of the output line.
3672 Match a SQL prompt or a password prompt."
3673 (concat "\\(?:\\(?:" sql-prompt-regexp "\\)\\|"
3674 "\\(?:" comint-password-prompt-regexp "\\)\\)\\'"))
3676 (defun sql-interactive-remove-continuation-prompt (oline)
3677 "Strip out continuation prompts out of the OLINE.
3679 Added to the `comint-preoutput-filter-functions' hook in a SQL
3680 interactive buffer. If `sql-output-newline-count' is greater than
3681 zero, then an output line matching the continuation prompt is filtered
3682 out. If the count is zero, then a newline is inserted into the output
3683 to force the output from the query to appear on a new line.
3685 The complication to this filter is that the continuation prompts
3686 may arrive in multiple chunks. If they do, then the function
3687 saves any unfiltered output in a buffer and prepends that buffer
3688 to the next chunk to properly match the broken-up prompt.
3690 If the filter gets confused, it should reset and stop filtering
3691 to avoid deleting non-prompt output."
3693 ;; continue gathering lines of text iff
3694 ;; + we know what a prompt looks like, and
3695 ;; + there is held text, or
3696 ;; + there are continuation prompt yet to come, or
3697 ;; + not just a prompt string
3698 (when (and comint-prompt-regexp
3699 (or (> (length (or sql-preoutput-hold "")) 0)
3700 (> (or sql-output-newline-count 0) 0)
3701 (not (or (string-match sql-prompt-regexp oline)
3702 (and sql-prompt-cont-regexp
3703 (string-match sql-prompt-cont-regexp oline))))))
3705 (save-match-data
3706 (let (prompt-found last-nl)
3708 ;; Add this text to what's left from the last pass
3709 (setq oline (concat sql-preoutput-hold oline)
3710 sql-preoutput-hold "")
3712 ;; If we are looking for multiple prompts
3713 (when (and (integerp sql-output-newline-count)
3714 (>= sql-output-newline-count 1))
3715 ;; Loop thru each starting prompt and remove it
3716 (let ((start-re (sql-starts-with-prompt-re)))
3717 (while (and (not (string= oline ""))
3718 (> sql-output-newline-count 0)
3719 (string-match start-re oline))
3720 (setq oline (replace-match "" nil nil oline)
3721 sql-output-newline-count (1- sql-output-newline-count)
3722 prompt-found t)))
3724 ;; If we've found all the expected prompts, stop looking
3725 (if (= sql-output-newline-count 0)
3726 (setq sql-output-newline-count nil
3727 oline (concat "\n" oline))
3729 ;; Still more possible prompts, leave them for the next pass
3730 (setq sql-preoutput-hold oline
3731 oline "")))
3733 ;; If no prompts were found, stop looking
3734 (unless prompt-found
3735 (setq sql-output-newline-count nil
3736 oline (concat oline sql-preoutput-hold)
3737 sql-preoutput-hold ""))
3739 ;; Break up output by physical lines if we haven't hit the final prompt
3740 (let ((end-re (sql-ends-with-prompt-re)))
3741 (unless (and (not (string= oline ""))
3742 (string-match end-re oline)
3743 (>= (match-end 0) (length oline)))
3744 ;; Find everything upto the last nl
3745 (setq last-nl 0)
3746 (while (string-match "\n" oline last-nl)
3747 (setq last-nl (match-end 0)))
3748 ;; Hold after the last nl, return upto last nl
3749 (setq sql-preoutput-hold (concat (substring oline last-nl)
3750 sql-preoutput-hold)
3751 oline (substring oline 0 last-nl)))))))
3752 oline)
3754 ;;; Sending the region to the SQLi buffer.
3755 (defvar sql-debug-send nil
3756 "Display text sent to SQL process pragmatically.")
3758 (defun sql-send-string (str)
3759 "Send the string STR to the SQL process."
3760 (interactive "sSQL Text: ")
3762 (let ((comint-input-sender-no-newline nil)
3763 (s (replace-regexp-in-string "[[:space:]\n\r]+\\'" "" str)))
3764 (if (sql-buffer-live-p sql-buffer)
3765 (progn
3766 ;; Ignore the hoping around...
3767 (save-excursion
3768 ;; Set product context
3769 (with-current-buffer sql-buffer
3770 (when sql-debug-send
3771 (message ">>SQL> %S" s))
3773 ;; Send the string (trim the trailing whitespace)
3774 (sql-input-sender (get-buffer-process (current-buffer)) s)
3776 ;; Send a command terminator if we must
3777 (sql-send-magic-terminator sql-buffer s sql-send-terminator)
3779 (when sql-pop-to-buffer-after-send-region
3780 (message "Sent string to buffer %s" sql-buffer))))
3782 ;; Display the sql buffer
3783 (sql-display-buffer sql-buffer))
3785 ;; We don't have no stinkin' sql
3786 (user-error "No SQL process started"))))
3788 (defun sql-send-region (start end)
3789 "Send a region to the SQL process."
3790 (interactive "r")
3791 (sql-send-string (buffer-substring-no-properties start end)))
3793 (defun sql-send-paragraph ()
3794 "Send the current paragraph to the SQL process."
3795 (interactive)
3796 (let ((start (save-excursion
3797 (backward-paragraph)
3798 (point)))
3799 (end (save-excursion
3800 (forward-paragraph)
3801 (point))))
3802 (sql-send-region start end)))
3804 (defun sql-send-buffer ()
3805 "Send the buffer contents to the SQL process."
3806 (interactive)
3807 (sql-send-region (point-min) (point-max)))
3809 (defun sql-send-line-and-next ()
3810 "Send the current line to the SQL process and go to the next line."
3811 (interactive)
3812 (sql-send-region (line-beginning-position 1) (line-beginning-position 2))
3813 (beginning-of-line 2)
3814 (while (forward-comment 1))) ; skip all comments and whitespace
3816 (defun sql-send-magic-terminator (buf str terminator)
3817 "Send TERMINATOR to buffer BUF if its not present in STR."
3818 (let (comint-input-sender-no-newline pat term)
3819 ;; If flag is merely on(t), get product-specific terminator
3820 (if (eq terminator t)
3821 (setq terminator (sql-get-product-feature sql-product :terminator)))
3823 ;; If there is no terminator specified, use default ";"
3824 (unless terminator
3825 (setq terminator ";"))
3827 ;; Parse the setting into the pattern and the terminator string
3828 (cond ((stringp terminator)
3829 (setq pat (regexp-quote terminator)
3830 term terminator))
3831 ((consp terminator)
3832 (setq pat (car terminator)
3833 term (cdr terminator)))
3835 nil))
3837 ;; Check to see if the pattern is present in the str already sent
3838 (unless (and pat term
3839 (string-match-p (concat pat "\\'") str))
3840 (sql-input-sender (get-buffer-process buf) term))))
3842 (defun sql-remove-tabs-filter (str)
3843 "Replace tab characters with spaces."
3844 (replace-regexp-in-string "\t" " " str nil t))
3846 (defun sql-toggle-pop-to-buffer-after-send-region (&optional value)
3847 "Toggle `sql-pop-to-buffer-after-send-region'.
3849 If given the optional parameter VALUE, sets
3850 `sql-toggle-pop-to-buffer-after-send-region' to VALUE."
3851 (interactive "P")
3852 (if value
3853 (setq sql-pop-to-buffer-after-send-region value)
3854 (setq sql-pop-to-buffer-after-send-region
3855 (null sql-pop-to-buffer-after-send-region))))
3859 ;;; Redirect output functions
3861 (defvar sql-debug-redirect nil
3862 "If non-nil, display messages related to the use of redirection.")
3864 (defun sql-str-literal (s)
3865 (concat "'" (replace-regexp-in-string "[']" "''" s) "'"))
3867 (defun sql-redirect (sqlbuf command &optional outbuf save-prior)
3868 "Execute the SQL command and send output to OUTBUF.
3870 SQLBUF must be an active SQL interactive buffer. OUTBUF may be
3871 an existing buffer, or the name of a non-existing buffer. If
3872 omitted the output is sent to a temporary buffer which will be
3873 killed after the command completes. COMMAND should be a string
3874 of commands accepted by the SQLi program. COMMAND may also be a
3875 list of SQLi command strings."
3877 (let* ((visible (and outbuf
3878 (not (sql-buffer-hidden-p outbuf))))
3879 (this-save save-prior)
3880 (next-save t))
3882 (when visible
3883 (message "Executing SQL command..."))
3885 (if (consp command)
3886 (dolist (onecmd command)
3887 (sql-redirect-one sqlbuf onecmd outbuf this-save)
3888 (setq this-save next-save))
3889 (sql-redirect-one sqlbuf command outbuf save-prior))
3891 (when visible
3892 (message "Executing SQL command...done"))
3893 nil))
3895 (defun sql-redirect-one (sqlbuf command outbuf save-prior)
3896 (when command
3897 (with-current-buffer sqlbuf
3898 (let ((buf (get-buffer-create (or outbuf " *SQL-Redirect*")))
3899 (proc (get-buffer-process (current-buffer)))
3900 (comint-prompt-regexp (sql-get-product-feature sql-product
3901 :prompt-regexp))
3902 (start nil))
3903 (with-current-buffer buf
3904 (setq-local view-no-disable-on-exit t)
3905 (read-only-mode -1)
3906 (unless save-prior
3907 (erase-buffer))
3908 (goto-char (point-max))
3909 (unless (zerop (buffer-size))
3910 (insert "\n"))
3911 (setq start (point)))
3913 (when sql-debug-redirect
3914 (message ">>SQL> %S" command))
3916 ;; Run the command
3917 (let ((inhibit-quit t)
3918 comint-preoutput-filter-functions)
3919 (with-local-quit
3920 (comint-redirect-send-command-to-process command buf proc nil t)
3921 (while (or quit-flag (null comint-redirect-completed))
3922 (accept-process-output nil 1)))
3924 (if quit-flag
3925 (comint-redirect-cleanup)
3926 ;; Clean up the output results
3927 (with-current-buffer buf
3928 ;; Remove trailing whitespace
3929 (goto-char (point-max))
3930 (when (looking-back "[ \t\f\n\r]*" start)
3931 (delete-region (match-beginning 0) (match-end 0)))
3932 ;; Remove echo if there was one
3933 (goto-char start)
3934 (when (looking-at (concat "^" (regexp-quote command) "[\\n]"))
3935 (delete-region (match-beginning 0) (match-end 0)))
3936 ;; Remove Ctrl-Ms
3937 (goto-char start)
3938 (while (re-search-forward "\r+$" nil t)
3939 (replace-match "" t t))
3940 (goto-char start))))))))
3942 (defun sql-redirect-value (sqlbuf command &optional regexp regexp-groups)
3943 "Execute the SQL command and return part of result.
3945 SQLBUF must be an active SQL interactive buffer. COMMAND should
3946 be a string of commands accepted by the SQLi program. From the
3947 output, the REGEXP is repeatedly matched and the list of
3948 REGEXP-GROUPS submatches is returned. This behaves much like
3949 \\[comint-redirect-results-list-from-process] but instead of
3950 returning a single submatch it returns a list of each submatch
3951 for each match."
3953 (let ((outbuf " *SQL-Redirect-values*")
3954 (results nil))
3955 (sql-redirect sqlbuf command outbuf nil)
3956 (with-current-buffer outbuf
3957 (while (re-search-forward (or regexp "^.+$") nil t)
3958 (push
3959 (cond
3960 ;; no groups-return all of them
3961 ((null regexp-groups)
3962 (let ((i (/ (length (match-data)) 2))
3963 (r nil))
3964 (while (> i 0)
3965 (setq i (1- i))
3966 (push (match-string i) r))
3968 ;; one group specified
3969 ((numberp regexp-groups)
3970 (match-string regexp-groups))
3971 ;; list of numbers; return the specified matches only
3972 ((consp regexp-groups)
3973 (mapcar (lambda (c)
3974 (cond
3975 ((numberp c) (match-string c))
3976 ((stringp c) (match-substitute-replacement c))
3977 (t (error "sql-redirect-value: unknown REGEXP-GROUPS value - %s" c))))
3978 regexp-groups))
3979 ;; String is specified; return replacement string
3980 ((stringp regexp-groups)
3981 (match-substitute-replacement regexp-groups))
3983 (error "sql-redirect-value: unknown REGEXP-GROUPS value - %s"
3984 regexp-groups)))
3985 results)))
3987 (when sql-debug-redirect
3988 (message ">>SQL> = %S" (reverse results)))
3990 (nreverse results)))
3992 (defun sql-execute (sqlbuf outbuf command enhanced arg)
3993 "Execute a command in a SQL interactive buffer and capture the output.
3995 The commands are run in SQLBUF and the output saved in OUTBUF.
3996 COMMAND must be a string, a function or a list of such elements.
3997 Functions are called with SQLBUF, OUTBUF and ARG as parameters;
3998 strings are formatted with ARG and executed.
4000 If the results are empty the OUTBUF is deleted, otherwise the
4001 buffer is popped into a view window."
4002 (mapc
4003 (lambda (c)
4004 (cond
4005 ((stringp c)
4006 (sql-redirect sqlbuf (if arg (format c arg) c) outbuf) t)
4007 ((functionp c)