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