]> code.delx.au - gnu-emacs/blob - lisp/progmodes/sql.el
Suppress continuation prompts in SQL interactive mode
[gnu-emacs] / lisp / progmodes / sql.el
1 ;;; sql.el --- specialized comint.el for SQL interpreters
2
3 ;; Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
4 ;; 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
5
6 ;; Author: Alex Schroeder <alex@gnu.org>
7 ;; Maintainer: Michael Mauger <mmaug@yahoo.com>
8 ;; Version: 2.5
9 ;; Keywords: comm languages processes
10 ;; URL: http://savannah.gnu.org/cgi-bin/viewcvs/emacs/emacs/lisp/progmodes/sql.el
11 ;; URL: http://www.emacswiki.org/cgi-bin/wiki.pl?SqlMode
12
13 ;; This file is part of GNU Emacs.
14
15 ;; GNU Emacs is free software: you can redistribute it and/or modify
16 ;; it under the terms of the GNU General Public License as published by
17 ;; the Free Software Foundation, either version 3 of the License, or
18 ;; (at your option) any later version.
19
20 ;; GNU Emacs is distributed in the hope that it will be useful,
21 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
22 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 ;; GNU General Public License for more details.
24
25 ;; You should have received a copy of the GNU General Public License
26 ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
27
28 ;;; Commentary:
29
30 ;; Please send bug reports and bug fixes to the mailing list at
31 ;; help-gnu-emacs@gnu.org. If you want to subscribe to the mailing
32 ;; list, see the web page at
33 ;; http://lists.gnu.org/mailman/listinfo/help-gnu-emacs for
34 ;; instructions. I monitor this list actively. If you send an e-mail
35 ;; to Alex Schroeder it usually makes it to me when Alex has a chance
36 ;; to forward them along (Thanks, Alex).
37
38 ;; This file provides a sql-mode and a sql-interactive-mode. The
39 ;; original goals were two simple modes providing syntactic
40 ;; highlighting. The interactive mode had to provide a command-line
41 ;; history; the other mode had to provide "send region/buffer to SQL
42 ;; interpreter" functions. "simple" in this context means easy to
43 ;; use, easy to maintain and little or no bells and whistles. This
44 ;; has changed somewhat as experience with the mode has accumulated.
45
46 ;; Support for different flavors of SQL and command interpreters was
47 ;; available in early versions of sql.el. This support has been
48 ;; extended and formalized in later versions. Part of the impetus for
49 ;; the improved support of SQL flavors was borne out of the current
50 ;; maintainer's consulting experience. In the past fifteen years, I
51 ;; have used Oracle, Sybase, Informix, MySQL, Postgres, and SQLServer.
52 ;; On some assignments, I have used two or more of these concurrently.
53
54 ;; If anybody feels like extending this sql mode, take a look at the
55 ;; above mentioned modes and write a sqlx-mode on top of this one. If
56 ;; this proves to be difficult, please suggest changes that will
57 ;; facilitate your plans. Facilities have been provided to add
58 ;; products and product-specific configuration.
59
60 ;; sql-interactive-mode is used to interact with a SQL interpreter
61 ;; process in a SQLi buffer (usually called `*SQL*'). The SQLi buffer
62 ;; is created by calling a SQL interpreter-specific entry function or
63 ;; sql-product-interactive. Do *not* call sql-interactive-mode by
64 ;; itself.
65
66 ;; The list of currently supported interpreters and the corresponding
67 ;; entry function used to create the SQLi buffers is shown with
68 ;; `sql-help' (M-x sql-help).
69
70 ;; Since sql-interactive-mode is built on top of the general
71 ;; command-interpreter-in-a-buffer mode (comint mode), it shares a
72 ;; common base functionality, and a common set of bindings, with all
73 ;; modes derived from comint mode. This makes these modes easier to
74 ;; use.
75
76 ;; sql-mode can be used to keep editing SQL statements. The SQL
77 ;; statements can be sent to the SQL process in the SQLi buffer.
78
79 ;; For documentation on the functionality provided by comint mode, and
80 ;; the hooks available for customizing it, see the file `comint.el'.
81
82 ;; Hint for newbies: take a look at `dabbrev-expand', `abbrev-mode', and
83 ;; `imenu-add-menubar-index'.
84
85 ;;; Requirements for Emacs 19.34:
86
87 ;; If you are using Emacs 19.34, you will have to get and install
88 ;; the file regexp-opt.el
89 ;; <URL:ftp://ftp.ifi.uio.no/pub/emacs/emacs-20.3/lisp/emacs-lisp/regexp-opt.el>
90 ;; and the custom package
91 ;; <URL:http://www.dina.kvl.dk/~abraham/custom/>.
92
93 ;;; Bugs:
94
95 ;; sql-ms now uses osql instead of isql. Osql flushes its error
96 ;; stream more frequently than isql so that error messages are
97 ;; available. There is no prompt and some output still is buffered.
98 ;; This improves the interaction under Emacs but it still is somewhat
99 ;; awkward.
100
101 ;; Quoted identifiers are not supported for hilighting. Most
102 ;; databases support the use of double quoted strings in place of
103 ;; identifiers; ms (Microsoft SQLServer) also supports identifiers
104 ;; enclosed within brackets [].
105
106 ;;; Product Support:
107
108 ;; To add support for additional SQL products the following steps
109 ;; must be followed ("xyz" is the name of the product in the examples
110 ;; below):
111
112 ;; 1) Add the product to the list of known products.
113
114 ;; (sql-add-product 'xyz "XyzDB"
115 ;; '(:free-software t))
116
117 ;; 2) Define font lock settings. All ANSI keywords will be
118 ;; highlighted automatically, so only product specific keywords
119 ;; need to be defined here.
120
121 ;; (defvar my-sql-mode-xyz-font-lock-keywords
122 ;; '(("\\b\\(red\\|orange\\|yellow\\)\\b"
123 ;; . font-lock-keyword-face))
124 ;; "XyzDB SQL keywords used by font-lock.")
125
126 ;; (sql-set-product-feature 'xyz
127 ;; :font-lock
128 ;; 'my-sql-mode-xyz-font-lock-keywords)
129
130 ;; 3) Define any special syntax characters including comments and
131 ;; identifier characters.
132
133 ;; (sql-set-product-feature 'xyz
134 ;; :syntax-alist ((?# . "w")))
135
136 ;; 4) Define the interactive command interpreter for the database
137 ;; product.
138
139 ;; (defcustom my-sql-xyz-program "ixyz"
140 ;; "Command to start ixyz by XyzDB."
141 ;; :type 'file
142 ;; :group 'SQL)
143 ;;
144 ;; (sql-set-product-feature 'xyz
145 ;; :sqli-program 'my-sql-xyz-program)
146 ;; (sql-set-product-feature 'xyz
147 ;; :prompt-regexp "^xyzdb> ")
148 ;; (sql-set-product-feature 'xyz
149 ;; :prompt-length 7)
150
151 ;; 5) Define login parameters and command line formatting.
152
153 ;; (defcustom my-sql-xyz-login-params '(user password server database)
154 ;; "Login parameters to needed to connect to XyzDB."
155 ;; :type 'sql-login-params
156 ;; :group 'SQL)
157 ;;
158 ;; (sql-set-product-feature 'xyz
159 ;; :sqli-login 'my-sql-xyz-login-params)
160
161 ;; (defcustom my-sql-xyz-options '("-X" "-Y" "-Z")
162 ;; "List of additional options for `sql-xyz-program'."
163 ;; :type '(repeat string)
164 ;; :group 'SQL)
165 ;;
166 ;; (sql-set-product-feature 'xyz
167 ;; :sqli-options 'my-sql-xyz-options))
168
169 ;; (defun my-sql-comint-xyz (product options)
170 ;; "Connect ti XyzDB in a comint buffer."
171 ;;
172 ;; ;; Do something with `sql-user', `sql-password',
173 ;; ;; `sql-database', and `sql-server'.
174 ;; (let ((params options))
175 ;; (if (not (string= "" sql-server))
176 ;; (setq params (append (list "-S" sql-server) params)))
177 ;; (if (not (string= "" sql-database))
178 ;; (setq params (append (list "-D" sql-database) params)))
179 ;; (if (not (string= "" sql-password))
180 ;; (setq params (append (list "-P" sql-password) params)))
181 ;; (if (not (string= "" sql-user))
182 ;; (setq params (append (list "-U" sql-user) params)))
183 ;; (sql-comint product params)))
184 ;;
185 ;; (sql-set-product-feature 'xyz
186 ;; :sqli-comint-func 'my-sql-comint-xyz)
187
188 ;; 6) Define a convienence function to invoke the SQL interpreter.
189
190 ;; (defun my-sql-xyz ()
191 ;; "Run ixyz by XyzDB as an inferior process."
192 ;; (interactive)
193 ;; (sql-product-interactive 'xyz))
194
195 ;;; To Do:
196
197 ;; Improve keyword highlighting for individual products. I have tried
198 ;; to update those database that I use. Feel free to send me updates,
199 ;; or direct me to the reference manuals for your favorite database.
200
201 ;; When there are no keywords defined, the ANSI keywords are
202 ;; highlighted. ANSI keywords are highlighted even if the keyword is
203 ;; not used for your current product. This should help identify
204 ;; portability concerns.
205
206 ;; Add different highlighting levels.
207
208 ;; Add support for listing available tables or the columns in a table.
209
210 ;;; Thanks to all the people who helped me out:
211
212 ;; Alex Schroeder <alex@gnu.org> -- the original author
213 ;; Kai Blauberg <kai.blauberg@metla.fi>
214 ;; <ibalaban@dalet.com>
215 ;; Yair Friedman <yfriedma@JohnBryce.Co.Il>
216 ;; Gregor Zych <zych@pool.informatik.rwth-aachen.de>
217 ;; nino <nino@inform.dk>
218 ;; Berend de Boer <berend@pobox.com>
219 ;; Adam Jenkins <adam@thejenkins.org>
220 ;; Michael Mauger <mmaug@yahoo.com> -- improved product support
221 ;; Drew Adams <drew.adams@oracle.com> -- Emacs 20 support
222 ;; Harald Maier <maierh@myself.com> -- sql-send-string
223 ;; Stefan Monnier <monnier@iro.umontreal.ca> -- font-lock corrections; code polish
224
225 \f
226
227 ;;; Code:
228
229 (require 'comint)
230 ;; Need the following to allow GNU Emacs 19 to compile the file.
231 (eval-when-compile
232 (require 'regexp-opt))
233 (require 'custom)
234 (eval-when-compile ;; needed in Emacs 19, 20
235 (setq max-specpdl-size (max max-specpdl-size 2000)))
236
237 (defvar font-lock-keyword-face)
238 (defvar font-lock-set-defaults)
239 (defvar font-lock-string-face)
240
241 ;;; Allow customization
242
243 (defgroup SQL nil
244 "Running a SQL interpreter from within Emacs buffers."
245 :version "20.4"
246 :group 'languages
247 :group 'processes)
248
249 ;; These four variables will be used as defaults, if set.
250
251 (defcustom sql-user ""
252 "Default username."
253 :type 'string
254 :group 'SQL
255 :safe 'stringp)
256
257 (defcustom sql-password ""
258 "Default password.
259
260 Storing your password in a textfile such as ~/.emacs could be dangerous.
261 Customizing your password will store it in your ~/.emacs file."
262 :type 'string
263 :group 'SQL
264 :risky t)
265
266 (defcustom sql-database ""
267 "Default database."
268 :type 'string
269 :group 'SQL
270 :safe 'stringp)
271
272 (defcustom sql-server ""
273 "Default server or host."
274 :type 'string
275 :group 'SQL
276 :safe 'stringp)
277
278 (defcustom sql-port nil
279 "Default server or host."
280 :version "24.1"
281 :type 'number
282 :group 'SQL
283 :safe 'numberp)
284
285 ;; Login parameter type
286
287 (define-widget 'sql-login-params 'lazy
288 "Widget definition of the login parameters list"
289 :tag "Login Parameters"
290 :type '(repeat (choice
291 (const user)
292 (const password)
293 (choice :tag "server"
294 (const server)
295 (list :tag "file"
296 (const :format "" server)
297 (const :format "" :file)
298 regexp)
299 (list :tag "completion"
300 (const :format "" server)
301 (const :format "" :completion)
302 (restricted-sexp
303 :match-alternatives (listp symbolp))))
304 (choice :tag "database"
305 (const database)
306 (list :tag "file"
307 (const :format "" database)
308 (const :format "" :file)
309 regexp)
310 (list :tag "completion"
311 (const :format "" database)
312 (const :format "" :completion)
313 (restricted-sexp
314 :match-alternatives (listp symbolp))))
315 (const port))))
316
317 ;; SQL Product support
318
319 (defvar sql-interactive-product nil
320 "Product under `sql-interactive-mode'.")
321
322 (defvar sql-connection nil
323 "Connection name if interactive session started by `sql-connect'.")
324
325 (defvar sql-product-alist
326 '((ansi
327 :name "ANSI"
328 :font-lock sql-mode-ansi-font-lock-keywords)
329
330 (db2
331 :name "DB2"
332 :font-lock sql-mode-db2-font-lock-keywords
333 :sqli-program sql-db2-program
334 :sqli-options sql-db2-options
335 :sqli-login sql-db2-login-params
336 :sqli-comint-func sql-comint-db2
337 :prompt-regexp "^db2 => "
338 :prompt-length 7
339 :prompt-cont-regexp "^db2 (cont\.) => "
340 :input-filter sql-escape-newlines-filter)
341
342 (informix
343 :name "Informix"
344 :font-lock sql-mode-informix-font-lock-keywords
345 :sqli-program sql-informix-program
346 :sqli-options sql-informix-options
347 :sqli-login sql-informix-login-params
348 :sqli-comint-func sql-comint-informix
349 :prompt-regexp "^> "
350 :prompt-length 2
351 :syntax-alist ((?{ . "<") (?} . ">")))
352
353 (ingres
354 :name "Ingres"
355 :font-lock sql-mode-ingres-font-lock-keywords
356 :sqli-program sql-ingres-program
357 :sqli-options sql-ingres-options
358 :sqli-login sql-ingres-login-params
359 :sqli-comint-func sql-comint-ingres
360 :prompt-regexp "^\* "
361 :prompt-length 2
362 :prompt-cont-regexp "^\* ")
363
364 (interbase
365 :name "Interbase"
366 :font-lock sql-mode-interbase-font-lock-keywords
367 :sqli-program sql-interbase-program
368 :sqli-options sql-interbase-options
369 :sqli-login sql-interbase-login-params
370 :sqli-comint-func sql-comint-interbase
371 :prompt-regexp "^SQL> "
372 :prompt-length 5)
373
374 (linter
375 :name "Linter"
376 :font-lock sql-mode-linter-font-lock-keywords
377 :sqli-program sql-linter-program
378 :sqli-options sql-linter-options
379 :sqli-login sql-linter-login-params
380 :sqli-comint-func sql-comint-linter
381 :prompt-regexp "^SQL>"
382 :prompt-length 4)
383
384 (ms
385 :name "Microsoft"
386 :font-lock sql-mode-ms-font-lock-keywords
387 :sqli-program sql-ms-program
388 :sqli-options sql-ms-options
389 :sqli-login sql-ms-login-params
390 :sqli-comint-func sql-comint-ms
391 :prompt-regexp "^[0-9]*>"
392 :prompt-length 5
393 :syntax-alist ((?@ . "w"))
394 :terminator ("^go" . "go"))
395
396 (mysql
397 :name "MySQL"
398 :free-software t
399 :font-lock sql-mode-mysql-font-lock-keywords
400 :sqli-program sql-mysql-program
401 :sqli-options sql-mysql-options
402 :sqli-login sql-mysql-login-params
403 :sqli-comint-func sql-comint-mysql
404 :prompt-regexp "^mysql> "
405 :prompt-length 6
406 :prompt-cont-regexp "^ -> "
407 :input-filter sql-remove-tabs-filter)
408
409 (oracle
410 :name "Oracle"
411 :font-lock sql-mode-oracle-font-lock-keywords
412 :sqli-program sql-oracle-program
413 :sqli-options sql-oracle-options
414 :sqli-login sql-oracle-login-params
415 :sqli-comint-func sql-comint-oracle
416 :prompt-regexp "^SQL> "
417 :prompt-length 5
418 :prompt-cont-regexp "^\\s-*\\d+> "
419 :syntax-alist ((?$ . "w") (?# . "w"))
420 :terminator ("\\(^/\\|;\\)" . "/")
421 :input-filter sql-placeholders-filter)
422
423 (postgres
424 :name "Postgres"
425 :free-software t
426 :font-lock sql-mode-postgres-font-lock-keywords
427 :sqli-program sql-postgres-program
428 :sqli-options sql-postgres-options
429 :sqli-login sql-postgres-login-params
430 :sqli-comint-func sql-comint-postgres
431 :prompt-regexp "^.*=[#>] "
432 :prompt-length 5
433 :prompt-cont-regexp "^.*-[#>] "
434 :input-filter sql-remove-tabs-filter
435 :terminator ("\\(^[\\]g\\|;\\)" . ";"))
436
437 (solid
438 :name "Solid"
439 :font-lock sql-mode-solid-font-lock-keywords
440 :sqli-program sql-solid-program
441 :sqli-options sql-solid-options
442 :sqli-login sql-solid-login-params
443 :sqli-comint-func sql-comint-solid
444 :prompt-regexp "^"
445 :prompt-length 0)
446
447 (sqlite
448 :name "SQLite"
449 :free-software t
450 :font-lock sql-mode-sqlite-font-lock-keywords
451 :sqli-program sql-sqlite-program
452 :sqli-options sql-sqlite-options
453 :sqli-login sql-sqlite-login-params
454 :sqli-comint-func sql-comint-sqlite
455 :prompt-regexp "^sqlite> "
456 :prompt-length 8
457 :prompt-cont-regexp "^ ...> "
458 :terminator ";")
459
460 (sybase
461 :name "Sybase"
462 :font-lock sql-mode-sybase-font-lock-keywords
463 :sqli-program sql-sybase-program
464 :sqli-options sql-sybase-options
465 :sqli-login sql-sybase-login-params
466 :sqli-comint-func sql-comint-sybase
467 :prompt-regexp "^SQL> "
468 :prompt-length 5
469 :syntax-alist ((?@ . "w"))
470 :terminator ("^go" . "go"))
471 )
472 "An alist of product specific configuration settings.
473
474 Without an entry in this list a product will not be properly
475 highlighted and will not support `sql-interactive-mode'.
476
477 Each element in the list is in the following format:
478
479 \(PRODUCT FEATURE VALUE ...)
480
481 where PRODUCT is the appropriate value of `sql-product'. The
482 product name is then followed by FEATURE-VALUE pairs. If a
483 FEATURE is not specified, its VALUE is treated as nil. FEATURE
484 may be any one of the following:
485
486 :name string containing the displayable name of
487 the product.
488
489 :free-software is the product Free (as in Freedom) software?
490
491 :font-lock name of the variable containing the product
492 specific font lock highlighting patterns.
493
494 :sqli-program name of the variable containing the product
495 specific interactive program name.
496
497 :sqli-options name of the variable containing the list
498 of product specific options.
499
500 :sqli-login name of the variable containing the list of
501 login parameters (i.e., user, password,
502 database and server) needed to connect to
503 the database.
504
505 :sqli-comint-func name of a function which accepts no
506 parameters that will use the values of
507 `sql-user', `sql-password',
508 `sql-database' and `sql-server' to open a
509 comint buffer and connect to the
510 database. Do product specific
511 configuration of comint in this function.
512
513 :prompt-regexp regular expression string that matches
514 the prompt issued by the product
515 interpreter.
516
517 :prompt-length length of the prompt on the line.
518
519 :prompt-cont-regexp regular expression string that matches
520 the continuation prompt issued by the
521 product interpreter.
522
523 :input-filter function which can filter strings sent to
524 the command interpreter. It is also used
525 by the `sql-send-string',
526 `sql-send-region', `sql-send-paragraph'
527 and `sql-send-buffer' functions. The
528 function is passed the string sent to the
529 command interpreter and must return the
530 filtered string. May also be a list of
531 such functions.
532
533 :terminator the terminator to be sent after a
534 `sql-send-string', `sql-send-region',
535 `sql-send-paragraph' and
536 `sql-send-buffer' command. May be the
537 literal string or a cons of a regexp to
538 match an existing terminator in the
539 string and the terminator to be used if
540 its absent. By default \";\".
541
542 :syntax-alist alist of syntax table entries to enable
543 special character treatment by font-lock
544 and imenu.
545
546 Other features can be stored but they will be ignored. However,
547 you can develop new functionality which is product independent by
548 using `sql-get-product-feature' to lookup the product specific
549 settings.")
550
551 (defvar sql-indirect-features
552 '(:font-lock :sqli-program :sqli-options :sqli-login))
553
554 ;;;###autoload
555 (defcustom sql-connection-alist nil
556 "An alist of connection parameters for interacting with a SQL
557 product.
558
559 Each element of the alist is as follows:
560
561 \(CONNECTION \(SQL-VARIABLE VALUE) ...)
562
563 Where CONNECTION is a symbol identifying the connection, SQL-VARIABLE
564 is the symbol name of a SQL mode variable, and VALUE is the value to
565 be assigned to the variable.
566
567 The most common SQL-VARIABLE settings associated with a connection
568 are:
569
570 `sql-product'
571 `sql-user'
572 `sql-password'
573 `sql-port'
574 `sql-server'
575 `sql-database'
576
577 If a SQL-VARIABLE is part of the connection, it will not be
578 prompted for during login."
579
580 :type `(alist :key-type (string :tag "Connection")
581 :value-type
582 (set
583 (group (const :tag "Product" sql-product)
584 (choice
585 ,@(mapcar (lambda (prod-info)
586 `(const :tag
587 ,(or (plist-get (cdr prod-info) :name)
588 (capitalize (symbol-name (car prod-info))))
589 (quote ,(car prod-info))))
590 sql-product-alist)))
591 (group (const :tag "Username" sql-user) string)
592 (group (const :tag "Password" sql-password) string)
593 (group (const :tag "Server" sql-server) string)
594 (group (const :tag "Database" sql-database) string)
595 (group (const :tag "Port" sql-port) integer)
596 (repeat :inline t
597 (list :tab "Other"
598 (symbol :tag " Variable Symbol")
599 (sexp :tag "Value Expression")))))
600 :version "24.1"
601 :group 'SQL)
602
603 ;;;###autoload
604 (defcustom sql-product 'ansi
605 "Select the SQL database product used so that buffers can be
606 highlighted properly when you open them."
607 :type `(choice
608 ,@(mapcar (lambda (prod-info)
609 `(const :tag
610 ,(or (plist-get (cdr prod-info) :name)
611 (capitalize (symbol-name (car prod-info))))
612 ,(car prod-info)))
613 sql-product-alist))
614 :group 'SQL
615 :safe 'symbolp)
616
617 ;; misc customization of sql.el behaviour
618
619 (defcustom sql-electric-stuff nil
620 "Treat some input as electric.
621 If set to the symbol `semicolon', then hitting `;' will send current
622 input in the SQLi buffer to the process.
623 If set to the symbol `go', then hitting `go' on a line by itself will
624 send current input in the SQLi buffer to the process.
625 If set to nil, then you must use \\[comint-send-input] in order to send
626 current input in the SQLi buffer to the process."
627 :type '(choice (const :tag "Nothing" nil)
628 (const :tag "The semicolon `;'" semicolon)
629 (const :tag "The string `go' by itself" go))
630 :version "20.8"
631 :group 'SQL)
632
633 (defcustom sql-send-terminator nil
634 "When non-nil, add a terminator to text sent to the SQL interpreter.
635
636 When text is sent to the SQL interpreter (via `sql-send-string',
637 `sql-send-region', `sql-send-paragraph' or `sql-send-buffer'), a
638 command terminator can be automatically sent as well. The
639 terminator is not sent, if the string sent already ends with the
640 terminator.
641
642 If this value is t, then the default command terminator for the
643 SQL interpreter is sent. If this value is a string, then the
644 string is sent.
645
646 If the value is a cons cell of the form (PAT . TERM), then PAT is
647 a regexp used to match the terminator in the string and TERM is
648 the terminator to be sent. This form is useful if the SQL
649 interpreter has more than one way of submitting a SQL command.
650 The PAT regexp can match any of them, and TERM is the way we do
651 it automatically."
652
653 :type '(choice (const :tag "No Terminator" nil)
654 (const :tag "Default Terminator" t)
655 (string :tag "Terminator String")
656 (cons :tag "Terminator Pattern and String"
657 (string :tag "Terminator Pattern")
658 (string :tag "Terminator String")))
659 :version "22.2"
660 :group 'SQL)
661
662 (defcustom sql-pop-to-buffer-after-send-region nil
663 "When non-nil, pop to the buffer SQL statements are sent to.
664
665 After a call to `sql-sent-string', `sql-send-region',
666 `sql-send-paragraph' or `sql-send-buffer', the window is split
667 and the SQLi buffer is shown. If this variable is not nil, that
668 buffer's window will be selected by calling `pop-to-buffer'. If
669 this variable is nil, that buffer is shown using
670 `display-buffer'."
671 :type 'boolean
672 :group 'SQL)
673
674 ;; imenu support for sql-mode.
675
676 (defvar sql-imenu-generic-expression
677 ;; Items are in reverse order because they are rendered in reverse.
678 '(("Rules/Defaults" "^\\s-*create\\s-+\\(\\w+\\s-+\\)*\\(rule\\|default\\)\\s-+\\(\\w+\\)" 3)
679 ("Sequences" "^\\s-*create\\s-+\\(\\w+\\s-+\\)*sequence\\s-+\\(\\w+\\)" 2)
680 ("Triggers" "^\\s-*create\\s-+\\(\\w+\\s-+\\)*trigger\\s-+\\(\\w+\\)" 2)
681 ("Functions" "^\\s-*\\(create\\s-+\\(\\w+\\s-+\\)*\\)?function\\s-+\\(\\w+\\)" 3)
682 ("Procedures" "^\\s-*\\(create\\s-+\\(\\w+\\s-+\\)*\\)?proc\\(edure\\)?\\s-+\\(\\w+\\)" 4)
683 ("Packages" "^\\s-*create\\s-+\\(\\w+\\s-+\\)*package\\s-+\\(body\\s-+\\)?\\(\\w+\\)" 3)
684 ("Types" "^\\s-*create\\s-+\\(\\w+\\s-+\\)*type\\s-+\\(body\\s-+\\)?\\(\\w+\\)" 3)
685 ("Indexes" "^\\s-*create\\s-+\\(\\w+\\s-+\\)*index\\s-+\\(\\w+\\)" 2)
686 ("Tables/Views" "^\\s-*create\\s-+\\(\\w+\\s-+\\)*\\(table\\|view\\)\\s-+\\(\\w+\\)" 3))
687 "Define interesting points in the SQL buffer for `imenu'.
688
689 This is used to set `imenu-generic-expression' when SQL mode is
690 entered. Subsequent changes to `sql-imenu-generic-expression' will
691 not affect existing SQL buffers because imenu-generic-expression is
692 a local variable.")
693
694 ;; history file
695
696 (defcustom sql-input-ring-file-name nil
697 "If non-nil, name of the file to read/write input history.
698
699 You have to set this variable if you want the history of your commands
700 saved from one Emacs session to the next. If this variable is set,
701 exiting the SQL interpreter in an SQLi buffer will write the input
702 history to the specified file. Starting a new process in a SQLi buffer
703 will read the input history from the specified file.
704
705 This is used to initialize `comint-input-ring-file-name'.
706
707 Note that the size of the input history is determined by the variable
708 `comint-input-ring-size'."
709 :type '(choice (const :tag "none" nil)
710 (file))
711 :group 'SQL)
712
713 (defcustom sql-input-ring-separator "\n--\n"
714 "Separator between commands in the history file.
715
716 If set to \"\\n\", each line in the history file will be interpreted as
717 one command. Multi-line commands are split into several commands when
718 the input ring is initialized from a history file.
719
720 This variable used to initialize `comint-input-ring-separator'.
721 `comint-input-ring-separator' is part of Emacs 21; if your Emacs
722 does not have it, setting `sql-input-ring-separator' will have no
723 effect. In that case multiline commands will be split into several
724 commands when the input history is read, as if you had set
725 `sql-input-ring-separator' to \"\\n\"."
726 :type 'string
727 :group 'SQL)
728
729 ;; The usual hooks
730
731 (defcustom sql-interactive-mode-hook '()
732 "Hook for customizing `sql-interactive-mode'."
733 :type 'hook
734 :group 'SQL)
735
736 (defcustom sql-mode-hook '()
737 "Hook for customizing `sql-mode'."
738 :type 'hook
739 :group 'SQL)
740
741 (defcustom sql-set-sqli-hook '()
742 "Hook for reacting to changes of `sql-buffer'.
743
744 This is called by `sql-set-sqli-buffer' when the value of `sql-buffer'
745 is changed."
746 :type 'hook
747 :group 'SQL)
748
749 ;; Customization for Oracle
750
751 (defcustom sql-oracle-program "sqlplus"
752 "Command to start sqlplus by Oracle.
753
754 Starts `sql-interactive-mode' after doing some setup.
755
756 On Windows, \"sqlplus\" usually starts the sqlplus \"GUI\". In order
757 to start the sqlplus console, use \"plus33\" or something similar.
758 You will find the file in your Orant\\bin directory."
759 :type 'file
760 :group 'SQL)
761
762 (defcustom sql-oracle-options nil
763 "List of additional options for `sql-oracle-program'."
764 :type '(repeat string)
765 :version "20.8"
766 :group 'SQL)
767
768 (defcustom sql-oracle-login-params '(user password database)
769 "List of login parameters needed to connect to Oracle."
770 :type 'sql-login-params
771 :version "24.1"
772 :group 'SQL)
773
774 (defcustom sql-oracle-scan-on t
775 "Non-nil if placeholders should be replaced in Oracle SQLi.
776
777 When non-nil, Emacs will scan text sent to sqlplus and prompt
778 for replacement text for & placeholders as sqlplus does. This
779 is needed on Windows where sqlplus output is buffered and the
780 prompts are not shown until after the text is entered.
781
782 You will probably want to issue the following command in sqlplus
783 to be safe:
784
785 SET SCAN OFF"
786 :type 'boolean
787 :group 'SQL)
788
789 ;; Customization for SQLite
790
791 (defcustom sql-sqlite-program "sqlite3"
792 "Command to start SQLite.
793
794 Starts `sql-interactive-mode' after doing some setup."
795 :type 'file
796 :group 'SQL)
797
798 (defcustom sql-sqlite-options nil
799 "List of additional options for `sql-sqlite-program'."
800 :type '(repeat string)
801 :version "20.8"
802 :group 'SQL)
803
804 (defcustom sql-sqlite-login-params '((database :file ".*\\.db"))
805 "List of login parameters needed to connect to SQLite."
806 :type 'sql-login-params
807 :version "24.1"
808 :group 'SQL)
809
810 ;; Customization for MySql
811
812 (defcustom sql-mysql-program "mysql"
813 "Command to start mysql by TcX.
814
815 Starts `sql-interactive-mode' after doing some setup."
816 :type 'file
817 :group 'SQL)
818
819 (defcustom sql-mysql-options nil
820 "List of additional options for `sql-mysql-program'.
821 The following list of options is reported to make things work
822 on Windows: \"-C\" \"-t\" \"-f\" \"-n\"."
823 :type '(repeat string)
824 :version "20.8"
825 :group 'SQL)
826
827 (defcustom sql-mysql-login-params '(user password database server)
828 "List of login parameters needed to connect to MySql."
829 :type 'sql-login-params
830 :version "24.1"
831 :group 'SQL)
832
833 ;; Customization for Solid
834
835 (defcustom sql-solid-program "solsql"
836 "Command to start SOLID SQL Editor.
837
838 Starts `sql-interactive-mode' after doing some setup."
839 :type 'file
840 :group 'SQL)
841
842 (defcustom sql-solid-login-params '(user password server)
843 "List of login parameters needed to connect to Solid."
844 :type 'sql-login-params
845 :version "24.1"
846 :group 'SQL)
847
848 ;; Customization for Sybase
849
850 (defcustom sql-sybase-program "isql"
851 "Command to start isql by Sybase.
852
853 Starts `sql-interactive-mode' after doing some setup."
854 :type 'file
855 :group 'SQL)
856
857 (defcustom sql-sybase-options nil
858 "List of additional options for `sql-sybase-program'.
859 Some versions of isql might require the -n option in order to work."
860 :type '(repeat string)
861 :version "20.8"
862 :group 'SQL)
863
864 (defcustom sql-sybase-login-params '(server user password database)
865 "List of login parameters needed to connect to Sybase."
866 :type 'sql-login-params
867 :version "24.1"
868 :group 'SQL)
869
870 ;; Customization for Informix
871
872 (defcustom sql-informix-program "dbaccess"
873 "Command to start dbaccess by Informix.
874
875 Starts `sql-interactive-mode' after doing some setup."
876 :type 'file
877 :group 'SQL)
878
879 (defcustom sql-informix-login-params '(database)
880 "List of login parameters needed to connect to Informix."
881 :type 'sql-login-params
882 :version "24.1"
883 :group 'SQL)
884
885 ;; Customization for Ingres
886
887 (defcustom sql-ingres-program "sql"
888 "Command to start sql by Ingres.
889
890 Starts `sql-interactive-mode' after doing some setup."
891 :type 'file
892 :group 'SQL)
893
894 (defcustom sql-ingres-login-params '(database)
895 "List of login parameters needed to connect to Ingres."
896 :type 'sql-login-params
897 :version "24.1"
898 :group 'SQL)
899
900 ;; Customization for Microsoft
901
902 (defcustom sql-ms-program "osql"
903 "Command to start osql by Microsoft.
904
905 Starts `sql-interactive-mode' after doing some setup."
906 :type 'file
907 :group 'SQL)
908
909 (defcustom sql-ms-options '("-w" "300" "-n")
910 ;; -w is the linesize
911 "List of additional options for `sql-ms-program'."
912 :type '(repeat string)
913 :version "22.1"
914 :group 'SQL)
915
916 (defcustom sql-ms-login-params '(user password server database)
917 "List of login parameters needed to connect to Microsoft."
918 :type 'sql-login-params
919 :version "24.1"
920 :group 'SQL)
921
922 ;; Customization for Postgres
923
924 (defcustom sql-postgres-program "psql"
925 "Command to start psql by Postgres.
926
927 Starts `sql-interactive-mode' after doing some setup."
928 :type 'file
929 :group 'SQL)
930
931 (defcustom sql-postgres-options '("-P" "pager=off")
932 "List of additional options for `sql-postgres-program'.
933 The default setting includes the -P option which breaks older versions
934 of the psql client (such as version 6.5.3). The -P option is equivalent
935 to the --pset option. If you want the psql to prompt you for a user
936 name, add the string \"-u\" to the list of options. If you want to
937 provide a user name on the command line (newer versions such as 7.1),
938 add your name with a \"-U\" prefix (such as \"-Umark\") to the list."
939 :type '(repeat string)
940 :version "20.8"
941 :group 'SQL)
942
943 (defcustom sql-postgres-login-params '(user database server)
944 "List of login parameters needed to connect to Postgres."
945 :type 'sql-login-params
946 :version "24.1"
947 :group 'SQL)
948
949 ;; Customization for Interbase
950
951 (defcustom sql-interbase-program "isql"
952 "Command to start isql by Interbase.
953
954 Starts `sql-interactive-mode' after doing some setup."
955 :type 'file
956 :group 'SQL)
957
958 (defcustom sql-interbase-options nil
959 "List of additional options for `sql-interbase-program'."
960 :type '(repeat string)
961 :version "20.8"
962 :group 'SQL)
963
964 (defcustom sql-interbase-login-params '(user password database)
965 "List of login parameters needed to connect to Interbase."
966 :type 'sql-login-params
967 :version "24.1"
968 :group 'SQL)
969
970 ;; Customization for DB2
971
972 (defcustom sql-db2-program "db2"
973 "Command to start db2 by IBM.
974
975 Starts `sql-interactive-mode' after doing some setup."
976 :type 'file
977 :group 'SQL)
978
979 (defcustom sql-db2-options nil
980 "List of additional options for `sql-db2-program'."
981 :type '(repeat string)
982 :version "20.8"
983 :group 'SQL)
984
985 (defcustom sql-db2-login-params nil
986 "List of login parameters needed to connect to DB2."
987 :type 'sql-login-params
988 :version "24.1"
989 :group 'SQL)
990
991 ;; Customization for Linter
992
993 (defcustom sql-linter-program "inl"
994 "Command to start inl by RELEX.
995
996 Starts `sql-interactive-mode' after doing some setup."
997 :type 'file
998 :group 'SQL)
999
1000 (defcustom sql-linter-options nil
1001 "List of additional options for `sql-linter-program'."
1002 :type '(repeat string)
1003 :version "21.3"
1004 :group 'SQL)
1005
1006 (defcustom sql-linter-login-params '(user password database server)
1007 "Login parameters to needed to connect to Linter."
1008 :type 'sql-login-params
1009 :version "24.1"
1010 :group 'SQL)
1011
1012 \f
1013
1014 ;;; Variables which do not need customization
1015
1016 (defvar sql-user-history nil
1017 "History of usernames used.")
1018
1019 (defvar sql-database-history nil
1020 "History of databases used.")
1021
1022 (defvar sql-server-history nil
1023 "History of servers used.")
1024
1025 (defvar sql-port-history nil
1026 "History of ports used.")
1027
1028 ;; Passwords are not kept in a history.
1029
1030 (defvar sql-buffer nil
1031 "Current SQLi buffer.
1032
1033 The global value of `sql-buffer' is the name of the latest SQLi buffer
1034 created. Any SQL buffer created will make a local copy of this value.
1035 See `sql-interactive-mode' for more on multiple sessions. If you want
1036 to change the SQLi buffer a SQL mode sends its SQL strings to, change
1037 the local value of `sql-buffer' using \\[sql-set-sqli-buffer].")
1038
1039 (defvar sql-prompt-regexp nil
1040 "Prompt used to initialize `comint-prompt-regexp'.
1041
1042 You can change `sql-prompt-regexp' on `sql-interactive-mode-hook'.")
1043
1044 (defvar sql-prompt-length 0
1045 "Prompt used to set `left-margin' in `sql-interactive-mode'.
1046
1047 You can change `sql-prompt-length' on `sql-interactive-mode-hook'.")
1048
1049 (defvar sql-prompt-cont-regexp nil
1050 "Prompt pattern of statement continuation prompts.")
1051
1052 (defvar sql-alternate-buffer-name nil
1053 "Buffer-local string used to possibly rename the SQLi buffer.
1054
1055 Used by `sql-rename-buffer'.")
1056
1057 ;; Keymap for sql-interactive-mode.
1058
1059 (defvar sql-interactive-mode-map
1060 (let ((map (make-sparse-keymap)))
1061 (if (fboundp 'set-keymap-parent)
1062 (set-keymap-parent map comint-mode-map); Emacs
1063 (if (fboundp 'set-keymap-parents)
1064 (set-keymap-parents map (list comint-mode-map)))); XEmacs
1065 (if (fboundp 'set-keymap-name)
1066 (set-keymap-name map 'sql-interactive-mode-map)); XEmacs
1067 (define-key map (kbd "C-j") 'sql-accumulate-and-indent)
1068 (define-key map (kbd "C-c C-w") 'sql-copy-column)
1069 (define-key map (kbd "O") 'sql-magic-go)
1070 (define-key map (kbd "o") 'sql-magic-go)
1071 (define-key map (kbd ";") 'sql-magic-semicolon)
1072 map)
1073 "Mode map used for `sql-interactive-mode'.
1074 Based on `comint-mode-map'.")
1075
1076 ;; Keymap for sql-mode.
1077
1078 (defvar sql-mode-map
1079 (let ((map (make-sparse-keymap)))
1080 (define-key map (kbd "C-c C-c") 'sql-send-paragraph)
1081 (define-key map (kbd "C-c C-r") 'sql-send-region)
1082 (define-key map (kbd "C-c C-s") 'sql-send-string)
1083 (define-key map (kbd "C-c C-b") 'sql-send-buffer)
1084 (define-key map (kbd "C-c C-i") 'sql-product-interactive)
1085 map)
1086 "Mode map used for `sql-mode'.")
1087
1088 ;; easy menu for sql-mode.
1089
1090 (easy-menu-define
1091 sql-mode-menu sql-mode-map
1092 "Menu for `sql-mode'."
1093 `("SQL"
1094 ["Send Paragraph" sql-send-paragraph (and (buffer-live-p sql-buffer)
1095 (get-buffer-process sql-buffer))]
1096 ["Send Region" sql-send-region (and mark-active
1097 (buffer-live-p sql-buffer)
1098 (get-buffer-process sql-buffer))]
1099 ["Send Buffer" sql-send-buffer (and (buffer-live-p sql-buffer)
1100 (get-buffer-process sql-buffer))]
1101 ["Send String" sql-send-string (and (buffer-live-p sql-buffer)
1102 (get-buffer-process sql-buffer))]
1103 "--"
1104 ["Start SQLi session" sql-product-interactive
1105 :visible (not sql-connection-alist)
1106 :enable (sql-get-product-feature sql-product :sqli-comint-func)]
1107 ("Start..."
1108 :visible sql-connection-alist
1109 :filter sql-connection-menu-filter
1110 "--"
1111 ["New SQLi Session" sql-product-interactive (sql-get-product-feature sql-product :sqli-comint-func)])
1112 ["--"
1113 :visible sql-connection-alist]
1114 ["Show SQLi buffer" sql-show-sqli-buffer t]
1115 ["Set SQLi buffer" sql-set-sqli-buffer t]
1116 ["Pop to SQLi buffer after send"
1117 sql-toggle-pop-to-buffer-after-send-region
1118 :style toggle
1119 :selected sql-pop-to-buffer-after-send-region]
1120 ["--" nil nil]
1121 ("Product"
1122 ,@(mapcar (lambda (prod-info)
1123 (let* ((prod (pop prod-info))
1124 (name (or (plist-get prod-info :name)
1125 (capitalize (symbol-name prod))))
1126 (cmd (intern (format "sql-highlight-%s-keywords" prod))))
1127 (fset cmd `(lambda () ,(format "Highlight %s SQL keywords." name)
1128 (interactive)
1129 (sql-set-product ',prod)))
1130 (vector name cmd
1131 :style 'radio
1132 :selected `(eq sql-product ',prod))))
1133 sql-product-alist))))
1134
1135 ;; easy menu for sql-interactive-mode.
1136
1137 (easy-menu-define
1138 sql-interactive-mode-menu sql-interactive-mode-map
1139 "Menu for `sql-interactive-mode'."
1140 '("SQL"
1141 ["Rename Buffer" sql-rename-buffer t]
1142 ["Save Connection" sql-save-connection (not sql-connection)]))
1143
1144 ;; Abbreviations -- if you want more of them, define them in your
1145 ;; ~/.emacs file. Abbrevs have to be enabled in your ~/.emacs, too.
1146
1147 (defvar sql-mode-abbrev-table nil
1148 "Abbrev table used in `sql-mode' and `sql-interactive-mode'.")
1149 (unless sql-mode-abbrev-table
1150 (define-abbrev-table 'sql-mode-abbrev-table nil))
1151
1152 (mapc
1153 ;; In Emacs 22+, provide SYSTEM-FLAG to define-abbrev.
1154 '(lambda (abbrev)
1155 (let ((name (car abbrev))
1156 (expansion (cdr abbrev)))
1157 (condition-case nil
1158 (define-abbrev sql-mode-abbrev-table name expansion nil 0 t)
1159 (error
1160 (define-abbrev sql-mode-abbrev-table name expansion)))))
1161 '(("ins" . "insert")
1162 ("upd" . "update")
1163 ("del" . "delete")
1164 ("sel" . "select")
1165 ("proc" . "procedure")
1166 ("func" . "function")
1167 ("cr" . "create")))
1168
1169 ;; Syntax Table
1170
1171 (defvar sql-mode-syntax-table
1172 (let ((table (make-syntax-table)))
1173 ;; C-style comments /**/ (see elisp manual "Syntax Flags"))
1174 (modify-syntax-entry ?/ ". 14" table)
1175 (modify-syntax-entry ?* ". 23" table)
1176 ;; double-dash starts comments
1177 (modify-syntax-entry ?- ". 12b" table)
1178 ;; newline and formfeed end comments
1179 (modify-syntax-entry ?\n "> b" table)
1180 (modify-syntax-entry ?\f "> b" table)
1181 ;; single quotes (') delimit strings
1182 (modify-syntax-entry ?' "\"" table)
1183 ;; double quotes (") don't delimit strings
1184 (modify-syntax-entry ?\" "." table)
1185 ;; backslash is no escape character
1186 (modify-syntax-entry ?\\ "." table)
1187 table)
1188 "Syntax table used in `sql-mode' and `sql-interactive-mode'.")
1189
1190 ;; Font lock support
1191
1192 (defvar sql-mode-font-lock-object-name
1193 (eval-when-compile
1194 (list (concat "^\\s-*\\(?:create\\|drop\\|alter\\)\\s-+" ;; lead off with CREATE, DROP or ALTER
1195 "\\(?:\\w+\\s-+\\)*" ;; optional intervening keywords
1196 "\\(?:table\\|view\\|\\(?:package\\|type\\)\\(?:\\s-+body\\)?\\|proc\\(?:edure\\)?"
1197 "\\|function\\|trigger\\|sequence\\|rule\\|default\\)\\s-+"
1198 "\\(\\w+\\)")
1199 1 'font-lock-function-name-face))
1200
1201 "Pattern to match the names of top-level objects.
1202
1203 The pattern matches the name in a CREATE, DROP or ALTER
1204 statement. The format of variable should be a valid
1205 `font-lock-keywords' entry.")
1206
1207 ;; While there are international and American standards for SQL, they
1208 ;; are not followed closely, and most vendors offer significant
1209 ;; capabilities beyond those defined in the standard specifications.
1210
1211 ;; SQL mode provides support for hilighting based on the product. In
1212 ;; addition to hilighting the product keywords, any ANSI keywords not
1213 ;; used by the product are also hilighted. This will help identify
1214 ;; keywords that could be restricted in future versions of the product
1215 ;; or might be a problem if ported to another product.
1216
1217 ;; To reduce the complexity and size of the regular expressions
1218 ;; generated to match keywords, ANSI keywords are filtered out of
1219 ;; product keywords if they are equivalent. To do this, we define a
1220 ;; function `sql-font-lock-keywords-builder' that removes any keywords
1221 ;; that are matched by the ANSI patterns and results in the same face
1222 ;; being applied. For this to work properly, we must play some games
1223 ;; with the execution and compile time behavior. This code is a
1224 ;; little tricky but works properly.
1225
1226 ;; When defining the keywords for individual products you should
1227 ;; include all of the keywords that you want matched. The filtering
1228 ;; against the ANSI keywords will be automatic if you use the
1229 ;; `sql-font-lock-keywords-builder' function and follow the
1230 ;; implementation pattern used for the other products in this file.
1231
1232 (eval-when-compile
1233 (defvar sql-mode-ansi-font-lock-keywords)
1234 (setq sql-mode-ansi-font-lock-keywords nil))
1235
1236 (eval-and-compile
1237 (defun sql-font-lock-keywords-builder (face boundaries &rest keywords)
1238 "Generation of regexp matching any one of KEYWORDS."
1239
1240 (let ((bdy (or boundaries '("\\b" . "\\b")))
1241 kwd)
1242
1243 ;; Remove keywords that are defined in ANSI
1244 (setq kwd keywords)
1245 (dolist (k keywords)
1246 (catch 'next
1247 (dolist (a sql-mode-ansi-font-lock-keywords)
1248 (when (and (eq face (cdr a))
1249 (eq (string-match (car a) k 0) 0)
1250 (eq (match-end 0) (length k)))
1251 (setq kwd (delq k kwd))
1252 (throw 'next nil)))))
1253
1254 ;; Create a properly formed font-lock-keywords item
1255 (cons (concat (car bdy)
1256 (regexp-opt kwd t)
1257 (cdr bdy))
1258 face))))
1259
1260 (eval-when-compile
1261 (setq sql-mode-ansi-font-lock-keywords
1262 (list
1263 ;; ANSI Non Reserved keywords
1264 (sql-font-lock-keywords-builder 'font-lock-keyword-face nil
1265 "ada" "asensitive" "assignment" "asymmetric" "atomic" "between"
1266 "bitvar" "called" "catalog_name" "chain" "character_set_catalog"
1267 "character_set_name" "character_set_schema" "checked" "class_origin"
1268 "cobol" "collation_catalog" "collation_name" "collation_schema"
1269 "column_name" "command_function" "command_function_code" "committed"
1270 "condition_number" "connection_name" "constraint_catalog"
1271 "constraint_name" "constraint_schema" "contains" "cursor_name"
1272 "datetime_interval_code" "datetime_interval_precision" "defined"
1273 "definer" "dispatch" "dynamic_function" "dynamic_function_code"
1274 "existing" "exists" "final" "fortran" "generated" "granted"
1275 "hierarchy" "hold" "implementation" "infix" "insensitive" "instance"
1276 "instantiable" "invoker" "key_member" "key_type" "length" "m"
1277 "message_length" "message_octet_length" "message_text" "method" "more"
1278 "mumps" "name" "nullable" "number" "options" "overlaps" "overriding"
1279 "parameter_mode" "parameter_name" "parameter_ordinal_position"
1280 "parameter_specific_catalog" "parameter_specific_name"
1281 "parameter_specific_schema" "pascal" "pli" "position" "repeatable"
1282 "returned_length" "returned_octet_length" "returned_sqlstate"
1283 "routine_catalog" "routine_name" "routine_schema" "row_count" "scale"
1284 "schema_name" "security" "self" "sensitive" "serializable"
1285 "server_name" "similar" "simple" "source" "specific_name" "style"
1286 "subclass_origin" "sublist" "symmetric" "system" "table_name"
1287 "transaction_active" "transactions_committed"
1288 "transactions_rolled_back" "transform" "transforms" "trigger_catalog"
1289 "trigger_name" "trigger_schema" "type" "uncommitted" "unnamed"
1290 "user_defined_type_catalog" "user_defined_type_name"
1291 "user_defined_type_schema"
1292 )
1293 ;; ANSI Reserved keywords
1294 (sql-font-lock-keywords-builder 'font-lock-keyword-face nil
1295 "absolute" "action" "add" "admin" "after" "aggregate" "alias" "all"
1296 "allocate" "alter" "and" "any" "are" "as" "asc" "assertion" "at"
1297 "authorization" "before" "begin" "both" "breadth" "by" "call"
1298 "cascade" "cascaded" "case" "catalog" "check" "class" "close"
1299 "collate" "collation" "column" "commit" "completion" "connect"
1300 "connection" "constraint" "constraints" "constructor" "continue"
1301 "corresponding" "create" "cross" "cube" "current" "cursor" "cycle"
1302 "data" "day" "deallocate" "declare" "default" "deferrable" "deferred"
1303 "delete" "depth" "deref" "desc" "describe" "descriptor" "destroy"
1304 "destructor" "deterministic" "diagnostics" "dictionary" "disconnect"
1305 "distinct" "domain" "drop" "dynamic" "each" "else" "end" "equals"
1306 "escape" "every" "except" "exception" "exec" "execute" "external"
1307 "false" "fetch" "first" "for" "foreign" "found" "free" "from" "full"
1308 "function" "general" "get" "global" "go" "goto" "grant" "group"
1309 "grouping" "having" "host" "hour" "identity" "ignore" "immediate" "in"
1310 "indicator" "initialize" "initially" "inner" "inout" "input" "insert"
1311 "intersect" "into" "is" "isolation" "iterate" "join" "key" "language"
1312 "last" "lateral" "leading" "left" "less" "level" "like" "limit"
1313 "local" "locator" "map" "match" "minute" "modifies" "modify" "module"
1314 "month" "names" "natural" "new" "next" "no" "none" "not" "null" "of"
1315 "off" "old" "on" "only" "open" "operation" "option" "or" "order"
1316 "ordinality" "out" "outer" "output" "pad" "parameter" "parameters"
1317 "partial" "path" "postfix" "prefix" "preorder" "prepare" "preserve"
1318 "primary" "prior" "privileges" "procedure" "public" "read" "reads"
1319 "recursive" "references" "referencing" "relative" "restrict" "result"
1320 "return" "returns" "revoke" "right" "role" "rollback" "rollup"
1321 "routine" "rows" "savepoint" "schema" "scroll" "search" "second"
1322 "section" "select" "sequence" "session" "set" "sets" "size" "some"
1323 "space" "specific" "specifictype" "sql" "sqlexception" "sqlstate"
1324 "sqlwarning" "start" "state" "statement" "static" "structure" "table"
1325 "temporary" "terminate" "than" "then" "timezone_hour"
1326 "timezone_minute" "to" "trailing" "transaction" "translation"
1327 "trigger" "true" "under" "union" "unique" "unknown" "unnest" "update"
1328 "usage" "using" "value" "values" "variable" "view" "when" "whenever"
1329 "where" "with" "without" "work" "write" "year"
1330 )
1331
1332 ;; ANSI Functions
1333 (sql-font-lock-keywords-builder 'font-lock-builtin-face nil
1334 "abs" "avg" "bit_length" "cardinality" "cast" "char_length"
1335 "character_length" "coalesce" "convert" "count" "current_date"
1336 "current_path" "current_role" "current_time" "current_timestamp"
1337 "current_user" "extract" "localtime" "localtimestamp" "lower" "max"
1338 "min" "mod" "nullif" "octet_length" "overlay" "placing" "session_user"
1339 "substring" "sum" "system_user" "translate" "treat" "trim" "upper"
1340 "user"
1341 )
1342 ;; ANSI Data Types
1343 (sql-font-lock-keywords-builder 'font-lock-type-face nil
1344 "array" "binary" "bit" "blob" "boolean" "char" "character" "clob"
1345 "date" "dec" "decimal" "double" "float" "int" "integer" "interval"
1346 "large" "national" "nchar" "nclob" "numeric" "object" "precision"
1347 "real" "ref" "row" "scope" "smallint" "time" "timestamp" "varchar"
1348 "varying" "zone"
1349 ))))
1350
1351 (defvar sql-mode-ansi-font-lock-keywords
1352 (eval-when-compile sql-mode-ansi-font-lock-keywords)
1353 "ANSI SQL keywords used by font-lock.
1354
1355 This variable is used by `sql-mode' and `sql-interactive-mode'. The
1356 regular expressions are created during compilation by calling the
1357 function `regexp-opt'. Therefore, take a look at the source before
1358 you define your own `sql-mode-ansi-font-lock-keywords'. You may want
1359 to add functions and PL/SQL keywords.")
1360
1361 (defvar sql-mode-oracle-font-lock-keywords
1362 (eval-when-compile
1363 (list
1364 ;; Oracle SQL*Plus Commands
1365 (cons
1366 (concat
1367 "^\\(?:\\(?:" (regexp-opt '(
1368 "@" "@@" "accept" "append" "archive" "attribute" "break"
1369 "btitle" "change" "clear" "column" "connect" "copy" "define"
1370 "del" "describe" "disconnect" "edit" "execute" "exit" "get" "help"
1371 "host" "input" "list" "password" "pause" "print" "prompt" "recover"
1372 "remark" "repfooter" "repheader" "run" "save" "show" "shutdown"
1373 "spool" "start" "startup" "store" "timing" "ttitle" "undefine"
1374 "variable" "whenever"
1375 ) t)
1376
1377 "\\)\\|"
1378 "\\(?:compute\\s-+\\(?:avg\\|cou\\|min\\|max\\|num\\|sum\\|std\\|var\\)\\)\\|"
1379 "\\(?:set\\s-+\\("
1380
1381 (regexp-opt
1382 '("appi" "appinfo" "array" "arraysize" "auto" "autocommit"
1383 "autop" "autoprint" "autorecovery" "autot" "autotrace" "blo"
1384 "blockterminator" "buffer" "closecursor" "cmds" "cmdsep"
1385 "colsep" "com" "compatibility" "con" "concat" "constraint"
1386 "constraints" "copyc" "copycommit" "copytypecheck" "database"
1387 "def" "define" "document" "echo" "editf" "editfile" "emb"
1388 "embedded" "esc" "escape" "feed" "feedback" "flagger" "flu"
1389 "flush" "hea" "heading" "heads" "headsep" "instance" "lin"
1390 "linesize" "lobof" "loboffset" "logsource" "long" "longc"
1391 "longchunksize" "maxdata" "newp" "newpage" "null" "num"
1392 "numf" "numformat" "numwidth" "pages" "pagesize" "pau"
1393 "pause" "recsep" "recsepchar" "role" "scan" "serveroutput"
1394 "shift" "shiftinout" "show" "showmode" "space" "sqlbl"
1395 "sqlblanklines" "sqlc" "sqlcase" "sqlco" "sqlcontinue" "sqln"
1396 "sqlnumber" "sqlp" "sqlpluscompat" "sqlpluscompatibility"
1397 "sqlpre" "sqlprefix" "sqlprompt" "sqlt" "sqlterminator"
1398 "statement_id" "suf" "suffix" "tab" "term" "termout" "ti"
1399 "time" "timi" "timing" "transaction" "trim" "trimout" "trims"
1400 "trimspool" "truncate" "und" "underline" "ver" "verify" "wra"
1401 "wrap")) "\\)\\)"
1402
1403 "\\)\\b.*"
1404 )
1405 'font-lock-doc-face)
1406 '("^[ \t]*rem\\(?:ark\\)?.*" . font-lock-comment-face)
1407
1408 ;; Oracle Functions
1409 (sql-font-lock-keywords-builder 'font-lock-builtin-face nil
1410 "abs" "acos" "add_months" "ascii" "asciistr" "asin" "atan" "atan2"
1411 "avg" "bfilename" "bin_to_num" "bitand" "cast" "ceil" "chartorowid"
1412 "chr" "coalesce" "compose" "concat" "convert" "corr" "cos" "cosh"
1413 "count" "covar_pop" "covar_samp" "cume_dist" "current_date"
1414 "current_timestamp" "current_user" "dbtimezone" "decode" "decompose"
1415 "dense_rank" "depth" "deref" "dump" "empty_clob" "existsnode" "exp"
1416 "extract" "extractvalue" "first" "first_value" "floor" "following"
1417 "from_tz" "greatest" "group_id" "grouping_id" "hextoraw" "initcap"
1418 "instr" "lag" "last" "last_day" "last_value" "lead" "least" "length"
1419 "ln" "localtimestamp" "lower" "lpad" "ltrim" "make_ref" "max" "min"
1420 "mod" "months_between" "new_time" "next_day" "nls_charset_decl_len"
1421 "nls_charset_id" "nls_charset_name" "nls_initcap" "nls_lower"
1422 "nls_upper" "nlssort" "ntile" "nullif" "numtodsinterval"
1423 "numtoyminterval" "nvl" "nvl2" "over" "path" "percent_rank"
1424 "percentile_cont" "percentile_disc" "power" "preceding" "rank"
1425 "ratio_to_report" "rawtohex" "rawtonhex" "reftohex" "regr_"
1426 "regr_avgx" "regr_avgy" "regr_count" "regr_intercept" "regr_r2"
1427 "regr_slope" "regr_sxx" "regr_sxy" "regr_syy" "replace" "round"
1428 "row_number" "rowidtochar" "rowidtonchar" "rpad" "rtrim"
1429 "sessiontimezone" "sign" "sin" "sinh" "soundex" "sqrt" "stddev"
1430 "stddev_pop" "stddev_samp" "substr" "sum" "sys_connect_by_path"
1431 "sys_context" "sys_dburigen" "sys_extract_utc" "sys_guid" "sys_typeid"
1432 "sys_xmlagg" "sys_xmlgen" "sysdate" "systimestamp" "tan" "tanh"
1433 "to_char" "to_clob" "to_date" "to_dsinterval" "to_lob" "to_multi_byte"
1434 "to_nchar" "to_nclob" "to_number" "to_single_byte" "to_timestamp"
1435 "to_timestamp_tz" "to_yminterval" "translate" "treat" "trim" "trunc"
1436 "tz_offset" "uid" "unbounded" "unistr" "updatexml" "upper" "user"
1437 "userenv" "var_pop" "var_samp" "variance" "vsize" "width_bucket" "xml"
1438 "xmlagg" "xmlattribute" "xmlcolattval" "xmlconcat" "xmlelement"
1439 "xmlforest" "xmlsequence" "xmltransform"
1440 )
1441 ;; Oracle Keywords
1442 (sql-font-lock-keywords-builder 'font-lock-keyword-face nil
1443 "abort" "access" "accessed" "account" "activate" "add" "admin"
1444 "advise" "after" "agent" "aggregate" "all" "allocate" "allow" "alter"
1445 "always" "analyze" "ancillary" "and" "any" "apply" "archive"
1446 "archivelog" "array" "as" "asc" "associate" "at" "attribute"
1447 "attributes" "audit" "authenticated" "authid" "authorization" "auto"
1448 "autoallocate" "automatic" "availability" "backup" "before" "begin"
1449 "behalf" "between" "binding" "bitmap" "block" "blocksize" "body"
1450 "both" "buffer_pool" "build" "by" "cache" "call" "cancel"
1451 "cascade" "case" "category" "certificate" "chained" "change" "check"
1452 "checkpoint" "child" "chunk" "class" "clear" "clone" "close" "cluster"
1453 "column" "column_value" "columns" "comment" "commit" "committed"
1454 "compatibility" "compile" "complete" "composite_limit" "compress"
1455 "compute" "connect" "connect_time" "consider" "consistent"
1456 "constraint" "constraints" "constructor" "contents" "context"
1457 "continue" "controlfile" "corruption" "cost" "cpu_per_call"
1458 "cpu_per_session" "create" "cross" "cube" "current" "currval" "cycle"
1459 "dangling" "data" "database" "datafile" "datafiles" "day" "ddl"
1460 "deallocate" "debug" "default" "deferrable" "deferred" "definer"
1461 "delay" "delete" "demand" "desc" "determines" "deterministic"
1462 "dictionary" "dimension" "directory" "disable" "disassociate"
1463 "disconnect" "distinct" "distinguished" "distributed" "dml" "drop"
1464 "each" "element" "else" "enable" "end" "equals_path" "escape"
1465 "estimate" "except" "exceptions" "exchange" "excluding" "exists"
1466 "expire" "explain" "extent" "external" "externally"
1467 "failed_login_attempts" "fast" "file" "final" "finish" "flush" "for"
1468 "force" "foreign" "freelist" "freelists" "freepools" "fresh" "from"
1469 "full" "function" "functions" "generated" "global" "global_name"
1470 "globally" "grant" "group" "grouping" "groups" "guard" "hash"
1471 "hashkeys" "having" "heap" "hierarchy" "id" "identified" "identifier"
1472 "idle_time" "immediate" "in" "including" "increment" "index" "indexed"
1473 "indexes" "indextype" "indextypes" "indicator" "initial" "initialized"
1474 "initially" "initrans" "inner" "insert" "instance" "instantiable"
1475 "instead" "intersect" "into" "invalidate" "is" "isolation" "java"
1476 "join" "keep" "key" "kill" "language" "left" "less" "level"
1477 "levels" "library" "like" "like2" "like4" "likec" "limit" "link"
1478 "list" "lob" "local" "location" "locator" "lock" "log" "logfile"
1479 "logging" "logical" "logical_reads_per_call"
1480 "logical_reads_per_session" "managed" "management" "manual" "map"
1481 "mapping" "master" "matched" "materialized" "maxdatafiles"
1482 "maxextents" "maximize" "maxinstances" "maxlogfiles" "maxloghistory"
1483 "maxlogmembers" "maxsize" "maxtrans" "maxvalue" "member" "memory"
1484 "merge" "migrate" "minextents" "minimize" "minimum" "minus" "minvalue"
1485 "mode" "modify" "monitoring" "month" "mount" "move" "movement" "name"
1486 "named" "natural" "nested" "never" "new" "next" "nextval" "no"
1487 "noarchivelog" "noaudit" "nocache" "nocompress" "nocopy" "nocycle"
1488 "nodelay" "noforce" "nologging" "nomapping" "nomaxvalue" "nominimize"
1489 "nominvalue" "nomonitoring" "none" "noorder" "noparallel" "norely"
1490 "noresetlogs" "noreverse" "normal" "norowdependencies" "nosort"
1491 "noswitch" "not" "nothing" "notimeout" "novalidate" "nowait" "null"
1492 "nulls" "object" "of" "off" "offline" "oidindex" "old" "on" "online"
1493 "only" "open" "operator" "optimal" "option" "or" "order"
1494 "organization" "out" "outer" "outline" "overflow" "overriding"
1495 "package" "packages" "parallel" "parallel_enable" "parameters"
1496 "parent" "partition" "partitions" "password" "password_grace_time"
1497 "password_life_time" "password_lock_time" "password_reuse_max"
1498 "password_reuse_time" "password_verify_function" "pctfree"
1499 "pctincrease" "pctthreshold" "pctused" "pctversion" "percent"
1500 "performance" "permanent" "pfile" "physical" "pipelined" "plan"
1501 "post_transaction" "pragma" "prebuilt" "preserve" "primary" "private"
1502 "private_sga" "privileges" "procedure" "profile" "protection" "public"
1503 "purge" "query" "quiesce" "quota" "range" "read" "reads" "rebuild"
1504 "records_per_block" "recover" "recovery" "recycle" "reduced" "ref"
1505 "references" "referencing" "refresh" "register" "reject" "relational"
1506 "rely" "rename" "reset" "resetlogs" "resize" "resolve" "resolver"
1507 "resource" "restrict" "restrict_references" "restricted" "result"
1508 "resumable" "resume" "retention" "return" "returning" "reuse"
1509 "reverse" "revoke" "rewrite" "right" "rnds" "rnps" "role" "roles"
1510 "rollback" "rollup" "row" "rowdependencies" "rownum" "rows" "sample"
1511 "savepoint" "scan" "schema" "scn" "scope" "segment" "select"
1512 "selectivity" "self" "sequence" "serializable" "session"
1513 "sessions_per_user" "set" "sets" "settings" "shared" "shared_pool"
1514 "shrink" "shutdown" "siblings" "sid" "single" "size" "skip" "some"
1515 "sort" "source" "space" "specification" "spfile" "split" "standby"
1516 "start" "statement_id" "static" "statistics" "stop" "storage" "store"
1517 "structure" "subpartition" "subpartitions" "substitutable"
1518 "successful" "supplemental" "suspend" "switch" "switchover" "synonym"
1519 "sys" "system" "table" "tables" "tablespace" "tempfile" "template"
1520 "temporary" "test" "than" "then" "thread" "through" "time_zone"
1521 "timeout" "to" "trace" "transaction" "trigger" "triggers" "truncate"
1522 "trust" "type" "types" "unarchived" "under" "under_path" "undo"
1523 "uniform" "union" "unique" "unlimited" "unlock" "unquiesce"
1524 "unrecoverable" "until" "unusable" "unused" "update" "upgrade" "usage"
1525 "use" "using" "validate" "validation" "value" "values" "variable"
1526 "varray" "version" "view" "wait" "when" "whenever" "where" "with"
1527 "without" "wnds" "wnps" "work" "write" "xmldata" "xmlschema" "xmltype"
1528 )
1529 ;; Oracle Data Types
1530 (sql-font-lock-keywords-builder 'font-lock-type-face nil
1531 "bfile" "blob" "byte" "char" "character" "clob" "date" "dec" "decimal"
1532 "double" "float" "int" "integer" "interval" "long" "national" "nchar"
1533 "nclob" "number" "numeric" "nvarchar2" "precision" "raw" "real"
1534 "rowid" "second" "smallint" "time" "timestamp" "urowid" "varchar"
1535 "varchar2" "varying" "year" "zone"
1536 )
1537
1538 ;; Oracle PL/SQL Attributes
1539 (sql-font-lock-keywords-builder 'font-lock-builtin-face '("" . "\\b")
1540 "%bulk_rowcount" "%found" "%isopen" "%notfound" "%rowcount" "%rowtype"
1541 "%type"
1542 )
1543
1544 ;; Oracle PL/SQL Functions
1545 (sql-font-lock-keywords-builder 'font-lock-builtin-face nil
1546 "extend" "prior"
1547 )
1548
1549 ;; Oracle PL/SQL Keywords
1550 (sql-font-lock-keywords-builder 'font-lock-keyword-face nil
1551 "autonomous_transaction" "bulk" "char_base" "collect" "constant"
1552 "cursor" "declare" "do" "elsif" "exception_init" "execute" "exit"
1553 "extends" "false" "fetch" "forall" "goto" "hour" "if" "interface"
1554 "loop" "minute" "number_base" "ocirowid" "opaque" "others" "rowtype"
1555 "separate" "serially_reusable" "sql" "sqlcode" "sqlerrm" "subtype"
1556 "the" "timezone_abbr" "timezone_hour" "timezone_minute"
1557 "timezone_region" "true" "varrying" "while"
1558 )
1559
1560 ;; Oracle PL/SQL Data Types
1561 (sql-font-lock-keywords-builder 'font-lock-type-face nil
1562 "binary_integer" "boolean" "naturaln" "pls_integer" "positive"
1563 "positiven" "record" "signtype" "string"
1564 )
1565
1566 ;; Oracle PL/SQL Exceptions
1567 (sql-font-lock-keywords-builder 'font-lock-warning-face nil
1568 "access_into_null" "case_not_found" "collection_is_null"
1569 "cursor_already_open" "dup_val_on_index" "invalid_cursor"
1570 "invalid_number" "login_denied" "no_data_found" "not_logged_on"
1571 "program_error" "rowtype_mismatch" "self_is_null" "storage_error"
1572 "subscript_beyond_count" "subscript_outside_limit" "sys_invalid_rowid"
1573 "timeout_on_resource" "too_many_rows" "value_error" "zero_divide"
1574 "exception" "notfound"
1575 )))
1576
1577 "Oracle SQL keywords used by font-lock.
1578
1579 This variable is used by `sql-mode' and `sql-interactive-mode'. The
1580 regular expressions are created during compilation by calling the
1581 function `regexp-opt'. Therefore, take a look at the source before
1582 you define your own `sql-mode-oracle-font-lock-keywords'. You may want
1583 to add functions and PL/SQL keywords.")
1584
1585 (defvar sql-mode-postgres-font-lock-keywords
1586 (eval-when-compile
1587 (list
1588 ;; Postgres Functions
1589 (sql-font-lock-keywords-builder 'font-lock-builtin-face nil
1590 "abbrev" "abs" "acos" "age" "area" "ascii" "asin" "atab2" "atan"
1591 "atan2" "avg" "bit_length" "both" "broadcast" "btrim" "cbrt" "ceil"
1592 "center" "char_length" "chr" "coalesce" "col_description" "convert"
1593 "cos" "cot" "count" "current_database" "current_date" "current_schema"
1594 "current_schemas" "current_setting" "current_time" "current_timestamp"
1595 "current_user" "currval" "date_part" "date_trunc" "decode" "degrees"
1596 "diameter" "encode" "exp" "extract" "floor" "get_bit" "get_byte"
1597 "has_database_privilege" "has_function_privilege"
1598 "has_language_privilege" "has_schema_privilege" "has_table_privilege"
1599 "height" "host" "initcap" "isclosed" "isfinite" "isopen" "leading"
1600 "length" "ln" "localtime" "localtimestamp" "log" "lower" "lpad"
1601 "ltrim" "masklen" "max" "min" "mod" "netmask" "network" "nextval"
1602 "now" "npoints" "nullif" "obj_description" "octet_length" "overlay"
1603 "pclose" "pg_client_encoding" "pg_function_is_visible"
1604 "pg_get_constraintdef" "pg_get_indexdef" "pg_get_ruledef"
1605 "pg_get_userbyid" "pg_get_viewdef" "pg_opclass_is_visible"
1606 "pg_operator_is_visible" "pg_table_is_visible" "pg_type_is_visible"
1607 "pi" "popen" "position" "pow" "quote_ident" "quote_literal" "radians"
1608 "radius" "random" "repeat" "replace" "round" "rpad" "rtrim"
1609 "session_user" "set_bit" "set_byte" "set_config" "set_masklen"
1610 "setval" "sign" "sin" "split_part" "sqrt" "stddev" "strpos" "substr"
1611 "substring" "sum" "tan" "timeofday" "to_ascii" "to_char" "to_date"
1612 "to_hex" "to_number" "to_timestamp" "trailing" "translate" "trim"
1613 "trunc" "upper" "variance" "version" "width"
1614 )
1615 ;; Postgres Reserved
1616 (sql-font-lock-keywords-builder 'font-lock-keyword-face nil
1617 "abort" "access" "add" "after" "aggregate" "alignment" "all" "alter"
1618 "analyze" "and" "any" "as" "asc" "assignment" "authorization"
1619 "backward" "basetype" "before" "begin" "between" "binary" "by" "cache"
1620 "called" "cascade" "case" "cast" "characteristics" "check"
1621 "checkpoint" "class" "close" "cluster" "column" "comment" "commit"
1622 "committed" "commutator" "constraint" "constraints" "conversion"
1623 "copy" "create" "createdb" "createuser" "cursor" "cycle" "database"
1624 "deallocate" "declare" "default" "deferrable" "deferred" "definer"
1625 "delete" "delimiter" "desc" "distinct" "do" "domain" "drop" "each"
1626 "element" "else" "encoding" "encrypted" "end" "escape" "except"
1627 "exclusive" "execute" "exists" "explain" "extended" "external" "false"
1628 "fetch" "finalfunc" "for" "force" "foreign" "forward" "freeze" "from"
1629 "full" "function" "grant" "group" "gtcmp" "handler" "hashes" "having"
1630 "immediate" "immutable" "implicit" "in" "increment" "index" "inherits"
1631 "initcond" "initially" "input" "insensitive" "insert" "instead"
1632 "internallength" "intersect" "into" "invoker" "is" "isnull"
1633 "isolation" "join" "key" "language" "leftarg" "level" "like" "limit"
1634 "listen" "load" "local" "location" "lock" "ltcmp" "main" "match"
1635 "maxvalue" "merges" "minvalue" "mode" "move" "natural" "negator"
1636 "next" "nocreatedb" "nocreateuser" "none" "not" "nothing" "notify"
1637 "notnull" "null" "of" "offset" "oids" "on" "only" "operator" "or"
1638 "order" "output" "owner" "partial" "passedbyvalue" "password" "plain"
1639 "prepare" "primary" "prior" "privileges" "procedural" "procedure"
1640 "public" "read" "recheck" "references" "reindex" "relative" "rename"
1641 "reset" "restrict" "returns" "revoke" "rightarg" "rollback" "row"
1642 "rule" "schema" "scroll" "security" "select" "sequence" "serializable"
1643 "session" "set" "sfunc" "share" "show" "similar" "some" "sort1"
1644 "sort2" "stable" "start" "statement" "statistics" "storage" "strict"
1645 "stype" "sysid" "table" "temp" "template" "temporary" "then" "to"
1646 "transaction" "trigger" "true" "truncate" "trusted" "type"
1647 "unencrypted" "union" "unique" "unknown" "unlisten" "until" "update"
1648 "usage" "user" "using" "vacuum" "valid" "validator" "values"
1649 "variable" "verbose" "view" "volatile" "when" "where" "with" "without"
1650 "work"
1651 )
1652
1653 ;; Postgres Data Types
1654 (sql-font-lock-keywords-builder 'font-lock-type-face nil
1655 "anyarray" "bigint" "bigserial" "bit" "boolean" "box" "bytea" "char"
1656 "character" "cidr" "circle" "cstring" "date" "decimal" "double"
1657 "float4" "float8" "inet" "int2" "int4" "int8" "integer" "internal"
1658 "interval" "language_handler" "line" "lseg" "macaddr" "money"
1659 "numeric" "oid" "opaque" "path" "point" "polygon" "precision" "real"
1660 "record" "regclass" "regoper" "regoperator" "regproc" "regprocedure"
1661 "regtype" "serial" "serial4" "serial8" "smallint" "text" "time"
1662 "timestamp" "varchar" "varying" "void" "zone"
1663 )))
1664
1665 "Postgres SQL keywords used by font-lock.
1666
1667 This variable is used by `sql-mode' and `sql-interactive-mode'. The
1668 regular expressions are created during compilation by calling the
1669 function `regexp-opt'. Therefore, take a look at the source before
1670 you define your own `sql-mode-postgres-font-lock-keywords'.")
1671
1672 (defvar sql-mode-linter-font-lock-keywords
1673 (eval-when-compile
1674 (list
1675 ;; Linter Keywords
1676 (sql-font-lock-keywords-builder 'font-lock-keyword-face nil
1677 "autocommit" "autoinc" "autorowid" "cancel" "cascade" "channel"
1678 "committed" "count" "countblob" "cross" "current" "data" "database"
1679 "datafile" "datafiles" "datesplit" "dba" "dbname" "default" "deferred"
1680 "denied" "description" "device" "difference" "directory" "error"
1681 "escape" "euc" "exclusive" "external" "extfile" "false" "file"
1682 "filename" "filesize" "filetime" "filter" "findblob" "first" "foreign"
1683 "full" "fuzzy" "global" "granted" "ignore" "immediate" "increment"
1684 "indexes" "indexfile" "indexfiles" "indextime" "initial" "integrity"
1685 "internal" "key" "last_autoinc" "last_rowid" "limit" "linter"
1686 "linter_file_device" "linter_file_size" "linter_name_length" "ln"
1687 "local" "login" "maxisn" "maxrow" "maxrowid" "maxvalue" "message"
1688 "minvalue" "module" "names" "national" "natural" "new" "new_table"
1689 "no" "node" "noneuc" "nulliferror" "numbers" "off" "old" "old_table"
1690 "only" "operation" "optimistic" "option" "page" "partially" "password"
1691 "phrase" "plan" "precision" "primary" "priority" "privileges"
1692 "proc_info_size" "proc_par_name_len" "protocol" "quant" "range" "raw"
1693 "read" "record" "records" "references" "remote" "rename" "replication"
1694 "restart" "rewrite" "root" "row" "rule" "savepoint" "security"
1695 "sensitive" "sequence" "serializable" "server" "since" "size" "some"
1696 "startup" "statement" "station" "success" "sys_guid" "tables" "test"
1697 "timeout" "trace" "transaction" "translation" "trigger"
1698 "trigger_info_size" "true" "trunc" "uncommitted" "unicode" "unknown"
1699 "unlimited" "unlisted" "user" "utf8" "value" "varying" "volumes"
1700 "wait" "windows_code" "workspace" "write" "xml"
1701 )
1702
1703 ;; Linter Reserved
1704 (sql-font-lock-keywords-builder 'font-lock-keyword-face nil
1705 "access" "action" "add" "address" "after" "all" "alter" "always" "and"
1706 "any" "append" "as" "asc" "ascic" "async" "at_begin" "at_end" "audit"
1707 "aud_obj_name_len" "backup" "base" "before" "between" "blobfile"
1708 "blobfiles" "blobpct" "brief" "browse" "by" "case" "cast" "check"
1709 "clear" "close" "column" "comment" "commit" "connect" "contains"
1710 "correct" "create" "delete" "desc" "disable" "disconnect" "distinct"
1711 "drop" "each" "ef" "else" "enable" "end" "event" "except" "exclude"
1712 "execute" "exists" "extract" "fetch" "finish" "for" "from" "get"
1713 "grant" "group" "having" "identified" "in" "index" "inner" "insert"
1714 "instead" "intersect" "into" "is" "isolation" "join" "left" "level"
1715 "like" "lock" "mode" "modify" "not" "nowait" "null" "of" "on" "open"
1716 "or" "order" "outer" "owner" "press" "prior" "procedure" "public"
1717 "purge" "rebuild" "resource" "restrict" "revoke" "right" "role"
1718 "rollback" "rownum" "select" "session" "set" "share" "shutdown"
1719 "start" "stop" "sync" "synchronize" "synonym" "sysdate" "table" "then"
1720 "to" "union" "unique" "unlock" "until" "update" "using" "values"
1721 "view" "when" "where" "with" "without"
1722 )
1723
1724 ;; Linter Functions
1725 (sql-font-lock-keywords-builder 'font-lock-builtin-face nil
1726 "abs" "acos" "asin" "atan" "atan2" "avg" "ceil" "cos" "cosh" "divtime"
1727 "exp" "floor" "getbits" "getblob" "getbyte" "getlong" "getraw"
1728 "getstr" "gettext" "getword" "hextoraw" "lenblob" "length" "log"
1729 "lower" "lpad" "ltrim" "max" "min" "mod" "monthname" "nvl"
1730 "octet_length" "power" "rand" "rawtohex" "repeat_string"
1731 "right_substr" "round" "rpad" "rtrim" "sign" "sin" "sinh" "soundex"
1732 "sqrt" "sum" "tan" "tanh" "timeint_to_days" "to_char" "to_date"
1733 "to_gmtime" "to_localtime" "to_number" "trim" "upper" "decode"
1734 "substr" "substring" "chr" "dayname" "days" "greatest" "hex" "initcap"
1735 "instr" "least" "multime" "replace" "width"
1736 )
1737
1738 ;; Linter Data Types
1739 (sql-font-lock-keywords-builder 'font-lock-type-face nil
1740 "bigint" "bitmap" "blob" "boolean" "char" "character" "date"
1741 "datetime" "dec" "decimal" "double" "float" "int" "integer" "nchar"
1742 "number" "numeric" "real" "smallint" "varbyte" "varchar" "byte"
1743 "cursor" "long"
1744 )))
1745
1746 "Linter SQL keywords used by font-lock.
1747
1748 This variable is used by `sql-mode' and `sql-interactive-mode'. The
1749 regular expressions are created during compilation by calling the
1750 function `regexp-opt'.")
1751
1752 (defvar sql-mode-ms-font-lock-keywords
1753 (eval-when-compile
1754 (list
1755 ;; MS isql/osql Commands
1756 (cons
1757 (concat
1758 "^\\(?:\\(?:set\\s-+\\(?:"
1759 (regexp-opt '(
1760 "datefirst" "dateformat" "deadlock_priority" "lock_timeout"
1761 "concat_null_yields_null" "cursor_close_on_commit"
1762 "disable_def_cnst_chk" "fips_flagger" "identity_insert" "language"
1763 "offsets" "quoted_identifier" "arithabort" "arithignore" "fmtonly"
1764 "nocount" "noexec" "numeric_roundabort" "parseonly"
1765 "query_governor_cost_limit" "rowcount" "textsize" "ansi_defaults"
1766 "ansi_null_dflt_off" "ansi_null_dflt_on" "ansi_nulls" "ansi_padding"
1767 "ansi_warnings" "forceplan" "showplan_all" "showplan_text"
1768 "statistics" "implicit_transactions" "remote_proc_transactions"
1769 "transaction" "xact_abort"
1770 ) t)
1771 "\\)\\)\\|go\\s-*\\|use\\s-+\\|setuser\\s-+\\|dbcc\\s-+\\).*$")
1772 'font-lock-doc-face)
1773
1774 ;; MS Reserved
1775 (sql-font-lock-keywords-builder 'font-lock-keyword-face nil
1776 "absolute" "add" "all" "alter" "and" "any" "as" "asc" "authorization"
1777 "avg" "backup" "begin" "between" "break" "browse" "bulk" "by"
1778 "cascade" "case" "check" "checkpoint" "close" "clustered" "coalesce"
1779 "column" "commit" "committed" "compute" "confirm" "constraint"
1780 "contains" "containstable" "continue" "controlrow" "convert" "count"
1781 "create" "cross" "current" "current_date" "current_time"
1782 "current_timestamp" "current_user" "database" "deallocate" "declare"
1783 "default" "delete" "deny" "desc" "disk" "distinct" "distributed"
1784 "double" "drop" "dummy" "dump" "else" "end" "errlvl" "errorexit"
1785 "escape" "except" "exec" "execute" "exists" "exit" "fetch" "file"
1786 "fillfactor" "first" "floppy" "for" "foreign" "freetext"
1787 "freetexttable" "from" "full" "goto" "grant" "group" "having"
1788 "holdlock" "identity" "identity_insert" "identitycol" "if" "in"
1789 "index" "inner" "insert" "intersect" "into" "is" "isolation" "join"
1790 "key" "kill" "last" "left" "level" "like" "lineno" "load" "max" "min"
1791 "mirrorexit" "national" "next" "nocheck" "nolock" "nonclustered" "not"
1792 "null" "nullif" "of" "off" "offsets" "on" "once" "only" "open"
1793 "opendatasource" "openquery" "openrowset" "option" "or" "order"
1794 "outer" "output" "over" "paglock" "percent" "perm" "permanent" "pipe"
1795 "plan" "precision" "prepare" "primary" "print" "prior" "privileges"
1796 "proc" "procedure" "processexit" "public" "raiserror" "read"
1797 "readcommitted" "readpast" "readtext" "readuncommitted" "reconfigure"
1798 "references" "relative" "repeatable" "repeatableread" "replication"
1799 "restore" "restrict" "return" "revoke" "right" "rollback" "rowcount"
1800 "rowguidcol" "rowlock" "rule" "save" "schema" "select" "serializable"
1801 "session_user" "set" "shutdown" "some" "statistics" "sum"
1802 "system_user" "table" "tablock" "tablockx" "tape" "temp" "temporary"
1803 "textsize" "then" "to" "top" "tran" "transaction" "trigger" "truncate"
1804 "tsequal" "uncommitted" "union" "unique" "update" "updatetext"
1805 "updlock" "use" "user" "values" "view" "waitfor" "when" "where"
1806 "while" "with" "work" "writetext" "collate" "function" "openxml"
1807 "returns"
1808 )
1809
1810 ;; MS Functions
1811 (sql-font-lock-keywords-builder 'font-lock-builtin-face nil
1812 "@@connections" "@@cpu_busy" "@@cursor_rows" "@@datefirst" "@@dbts"
1813 "@@error" "@@fetch_status" "@@identity" "@@idle" "@@io_busy"
1814 "@@langid" "@@language" "@@lock_timeout" "@@max_connections"
1815 "@@max_precision" "@@nestlevel" "@@options" "@@pack_received"
1816 "@@pack_sent" "@@packet_errors" "@@procid" "@@remserver" "@@rowcount"
1817 "@@servername" "@@servicename" "@@spid" "@@textsize" "@@timeticks"
1818 "@@total_errors" "@@total_read" "@@total_write" "@@trancount"
1819 "@@version" "abs" "acos" "and" "app_name" "ascii" "asin" "atan" "atn2"
1820 "avg" "case" "cast" "ceiling" "char" "charindex" "coalesce"
1821 "col_length" "col_name" "columnproperty" "containstable" "convert"
1822 "cos" "cot" "count" "current_timestamp" "current_user" "cursor_status"
1823 "databaseproperty" "datalength" "dateadd" "datediff" "datename"
1824 "datepart" "day" "db_id" "db_name" "degrees" "difference" "exp"
1825 "file_id" "file_name" "filegroup_id" "filegroup_name"
1826 "filegroupproperty" "fileproperty" "floor" "formatmessage"
1827 "freetexttable" "fulltextcatalogproperty" "fulltextserviceproperty"
1828 "getansinull" "getdate" "grouping" "host_id" "host_name" "ident_incr"
1829 "ident_seed" "identity" "index_col" "indexproperty" "is_member"
1830 "is_srvrolemember" "isdate" "isnull" "isnumeric" "left" "len" "log"
1831 "log10" "lower" "ltrim" "max" "min" "month" "nchar" "newid" "nullif"
1832 "object_id" "object_name" "objectproperty" "openquery" "openrowset"
1833 "parsename" "patindex" "patindex" "permissions" "pi" "power"
1834 "quotename" "radians" "rand" "replace" "replicate" "reverse" "right"
1835 "round" "rtrim" "session_user" "sign" "sin" "soundex" "space" "sqrt"
1836 "square" "stats_date" "stdev" "stdevp" "str" "stuff" "substring" "sum"
1837 "suser_id" "suser_name" "suser_sid" "suser_sname" "system_user" "tan"
1838 "textptr" "textvalid" "typeproperty" "unicode" "upper" "user"
1839 "user_id" "user_name" "var" "varp" "year"
1840 )
1841
1842 ;; MS Variables
1843 '("\\b@[a-zA-Z0-9_]*\\b" . font-lock-variable-name-face)
1844
1845 ;; MS Types
1846 (sql-font-lock-keywords-builder 'font-lock-type-face nil
1847 "binary" "bit" "char" "character" "cursor" "datetime" "dec" "decimal"
1848 "double" "float" "image" "int" "integer" "money" "national" "nchar"
1849 "ntext" "numeric" "numeric" "nvarchar" "precision" "real"
1850 "smalldatetime" "smallint" "smallmoney" "text" "timestamp" "tinyint"
1851 "uniqueidentifier" "varbinary" "varchar" "varying"
1852 )))
1853
1854 "Microsoft SQLServer SQL keywords used by font-lock.
1855
1856 This variable is used by `sql-mode' and `sql-interactive-mode'. The
1857 regular expressions are created during compilation by calling the
1858 function `regexp-opt'. Therefore, take a look at the source before
1859 you define your own `sql-mode-ms-font-lock-keywords'.")
1860
1861 (defvar sql-mode-sybase-font-lock-keywords nil
1862 "Sybase SQL keywords used by font-lock.
1863
1864 This variable is used by `sql-mode' and `sql-interactive-mode'. The
1865 regular expressions are created during compilation by calling the
1866 function `regexp-opt'. Therefore, take a look at the source before
1867 you define your own `sql-mode-sybase-font-lock-keywords'.")
1868
1869 (defvar sql-mode-informix-font-lock-keywords nil
1870 "Informix SQL keywords used by font-lock.
1871
1872 This variable is used by `sql-mode' and `sql-interactive-mode'. The
1873 regular expressions are created during compilation by calling the
1874 function `regexp-opt'. Therefore, take a look at the source before
1875 you define your own `sql-mode-informix-font-lock-keywords'.")
1876
1877 (defvar sql-mode-interbase-font-lock-keywords nil
1878 "Interbase SQL keywords used by font-lock.
1879
1880 This variable is used by `sql-mode' and `sql-interactive-mode'. The
1881 regular expressions are created during compilation by calling the
1882 function `regexp-opt'. Therefore, take a look at the source before
1883 you define your own `sql-mode-interbase-font-lock-keywords'.")
1884
1885 (defvar sql-mode-ingres-font-lock-keywords nil
1886 "Ingres SQL keywords used by font-lock.
1887
1888 This variable is used by `sql-mode' and `sql-interactive-mode'. The
1889 regular expressions are created during compilation by calling the
1890 function `regexp-opt'. Therefore, take a look at the source before
1891 you define your own `sql-mode-interbase-font-lock-keywords'.")
1892
1893 (defvar sql-mode-solid-font-lock-keywords nil
1894 "Solid SQL keywords used by font-lock.
1895
1896 This variable is used by `sql-mode' and `sql-interactive-mode'. The
1897 regular expressions are created during compilation by calling the
1898 function `regexp-opt'. Therefore, take a look at the source before
1899 you define your own `sql-mode-solid-font-lock-keywords'.")
1900
1901 (defvar sql-mode-mysql-font-lock-keywords
1902 (eval-when-compile
1903 (list
1904 ;; MySQL Functions
1905 (sql-font-lock-keywords-builder 'font-lock-builtin-face nil
1906 "ascii" "avg" "bdmpolyfromtext" "bdmpolyfromwkb" "bdpolyfromtext"
1907 "bdpolyfromwkb" "benchmark" "bin" "bit_and" "bit_length" "bit_or"
1908 "bit_xor" "both" "cast" "char_length" "character_length" "coalesce"
1909 "concat" "concat_ws" "connection_id" "conv" "convert" "count"
1910 "curdate" "current_date" "current_time" "current_timestamp" "curtime"
1911 "elt" "encrypt" "export_set" "field" "find_in_set" "found_rows" "from"
1912 "geomcollfromtext" "geomcollfromwkb" "geometrycollectionfromtext"
1913 "geometrycollectionfromwkb" "geometryfromtext" "geometryfromwkb"
1914 "geomfromtext" "geomfromwkb" "get_lock" "group_concat" "hex" "ifnull"
1915 "instr" "interval" "isnull" "last_insert_id" "lcase" "leading"
1916 "length" "linefromtext" "linefromwkb" "linestringfromtext"
1917 "linestringfromwkb" "load_file" "locate" "lower" "lpad" "ltrim"
1918 "make_set" "master_pos_wait" "max" "mid" "min" "mlinefromtext"
1919 "mlinefromwkb" "mpointfromtext" "mpointfromwkb" "mpolyfromtext"
1920 "mpolyfromwkb" "multilinestringfromtext" "multilinestringfromwkb"
1921 "multipointfromtext" "multipointfromwkb" "multipolygonfromtext"
1922 "multipolygonfromwkb" "now" "nullif" "oct" "octet_length" "ord"
1923 "pointfromtext" "pointfromwkb" "polyfromtext" "polyfromwkb"
1924 "polygonfromtext" "polygonfromwkb" "position" "quote" "rand"
1925 "release_lock" "repeat" "replace" "reverse" "rpad" "rtrim" "soundex"
1926 "space" "std" "stddev" "substring" "substring_index" "sum" "sysdate"
1927 "trailing" "trim" "ucase" "unix_timestamp" "upper" "user" "variance"
1928 )
1929
1930 ;; MySQL Keywords
1931 (sql-font-lock-keywords-builder 'font-lock-keyword-face nil
1932 "action" "add" "after" "against" "all" "alter" "and" "as" "asc"
1933 "auto_increment" "avg_row_length" "bdb" "between" "by" "cascade"
1934 "case" "change" "character" "check" "checksum" "close" "collate"
1935 "collation" "column" "columns" "comment" "committed" "concurrent"
1936 "constraint" "create" "cross" "data" "database" "default"
1937 "delay_key_write" "delayed" "delete" "desc" "directory" "disable"
1938 "distinct" "distinctrow" "do" "drop" "dumpfile" "duplicate" "else"
1939 "enable" "enclosed" "end" "escaped" "exists" "fields" "first" "for"
1940 "force" "foreign" "from" "full" "fulltext" "global" "group" "handler"
1941 "having" "heap" "high_priority" "if" "ignore" "in" "index" "infile"
1942 "inner" "insert" "insert_method" "into" "is" "isam" "isolation" "join"
1943 "key" "keys" "last" "left" "level" "like" "limit" "lines" "load"
1944 "local" "lock" "low_priority" "match" "max_rows" "merge" "min_rows"
1945 "mode" "modify" "mrg_myisam" "myisam" "natural" "next" "no" "not"
1946 "null" "offset" "oj" "on" "open" "optionally" "or" "order" "outer"
1947 "outfile" "pack_keys" "partial" "password" "prev" "primary"
1948 "procedure" "quick" "raid0" "raid_type" "read" "references" "rename"
1949 "repeatable" "restrict" "right" "rollback" "rollup" "row_format"
1950 "savepoint" "select" "separator" "serializable" "session" "set"
1951 "share" "show" "sql_big_result" "sql_buffer_result" "sql_cache"
1952 "sql_calc_found_rows" "sql_no_cache" "sql_small_result" "starting"
1953 "straight_join" "striped" "table" "tables" "temporary" "terminated"
1954 "then" "to" "transaction" "truncate" "type" "uncommitted" "union"
1955 "unique" "unlock" "update" "use" "using" "values" "when" "where"
1956 "with" "write" "xor"
1957 )
1958
1959 ;; MySQL Data Types
1960 (sql-font-lock-keywords-builder 'font-lock-type-face nil
1961 "bigint" "binary" "bit" "blob" "bool" "boolean" "char" "curve" "date"
1962 "datetime" "dec" "decimal" "double" "enum" "fixed" "float" "geometry"
1963 "geometrycollection" "int" "integer" "line" "linearring" "linestring"
1964 "longblob" "longtext" "mediumblob" "mediumint" "mediumtext"
1965 "multicurve" "multilinestring" "multipoint" "multipolygon"
1966 "multisurface" "national" "numeric" "point" "polygon" "precision"
1967 "real" "smallint" "surface" "text" "time" "timestamp" "tinyblob"
1968 "tinyint" "tinytext" "unsigned" "varchar" "year" "year2" "year4"
1969 "zerofill"
1970 )))
1971
1972 "MySQL SQL keywords used by font-lock.
1973
1974 This variable is used by `sql-mode' and `sql-interactive-mode'. The
1975 regular expressions are created during compilation by calling the
1976 function `regexp-opt'. Therefore, take a look at the source before
1977 you define your own `sql-mode-mysql-font-lock-keywords'.")
1978
1979 (defvar sql-mode-sqlite-font-lock-keywords
1980 (eval-when-compile
1981 (list
1982 ;; SQLite Keyword
1983 (sql-font-lock-keywords-builder 'font-lock-keyword-face nil
1984 "abort" "action" "add" "after" "all" "alter" "analyze" "and" "as"
1985 "asc" "attach" "autoincrement" "before" "begin" "between" "by"
1986 "cascade" "case" "cast" "check" "collate" "column" "commit" "conflict"
1987 "constraint" "create" "cross" "database" "default" "deferrable"
1988 "deferred" "delete" "desc" "detach" "distinct" "drop" "each" "else"
1989 "end" "escape" "except" "exclusive" "exists" "explain" "fail" "for"
1990 "foreign" "from" "full" "glob" "group" "having" "if" "ignore"
1991 "immediate" "in" "index" "indexed" "initially" "inner" "insert"
1992 "instead" "intersect" "into" "is" "isnull" "join" "key" "left" "like"
1993 "limit" "match" "natural" "no" "not" "notnull" "null" "of" "offset"
1994 "on" "or" "order" "outer" "plan" "pragma" "primary" "query" "raise"
1995 "references" "regexp" "reindex" "release" "rename" "replace"
1996 "restrict" "right" "rollback" "row" "savepoint" "select" "set" "table"
1997 "temp" "temporary" "then" "to" "transaction" "trigger" "union"
1998 "unique" "update" "using" "vacuum" "values" "view" "virtual" "when"
1999 "where"
2000 )
2001 ;; SQLite Data types
2002 (sql-font-lock-keywords-builder 'font-lock-type-face nil
2003 "int" "integer" "tinyint" "smallint" "mediumint" "bigint" "unsigned"
2004 "big" "int2" "int8" "character" "varchar" "varying" "nchar" "native"
2005 "nvarchar" "text" "clob" "blob" "real" "double" "precision" "float"
2006 "numeric" "number" "decimal" "boolean" "date" "datetime"
2007 )
2008 ;; SQLite Functions
2009 (sql-font-lock-keywords-builder 'font-lock-builtin-face nil
2010 ;; Core functions
2011 "abs" "changes" "coalesce" "glob" "ifnull" "hex" "last_insert_rowid"
2012 "length" "like" "load_extension" "lower" "ltrim" "max" "min" "nullif"
2013 "quote" "random" "randomblob" "replace" "round" "rtrim" "soundex"
2014 "sqlite_compileoption_get" "sqlite_compileoption_used"
2015 "sqlite_source_id" "sqlite_version" "substr" "total_changes" "trim"
2016 "typeof" "upper" "zeroblob"
2017 ;; Date/time functions
2018 "time" "julianday" "strftime"
2019 "current_date" "current_time" "current_timestamp"
2020 ;; Aggregate functions
2021 "avg" "count" "group_concat" "max" "min" "sum" "total"
2022 )))
2023
2024 "SQLite SQL keywords used by font-lock.
2025
2026 This variable is used by `sql-mode' and `sql-interactive-mode'. The
2027 regular expressions are created during compilation by calling the
2028 function `regexp-opt'. Therefore, take a look at the source before
2029 you define your own `sql-mode-sqlite-font-lock-keywords'.")
2030
2031 (defvar sql-mode-db2-font-lock-keywords nil
2032 "DB2 SQL keywords used by font-lock.
2033
2034 This variable is used by `sql-mode' and `sql-interactive-mode'. The
2035 regular expressions are created during compilation by calling the
2036 function `regexp-opt'. Therefore, take a look at the source before
2037 you define your own `sql-mode-db2-font-lock-keywords'.")
2038
2039 (defvar sql-mode-font-lock-keywords nil
2040 "SQL keywords used by font-lock.
2041
2042 Setting this variable directly no longer has any affect. Use
2043 `sql-product' and `sql-add-product-keywords' to control the
2044 highlighting rules in SQL mode.")
2045
2046 \f
2047
2048 ;;; SQL Product support functions
2049
2050 (defun sql-add-product (product display &rest plist)
2051 "Add support for a database product in `sql-mode'.
2052
2053 Add PRODUCT to `sql-product-alist' which enables `sql-mode' to
2054 properly support syntax highlighting and interactive interaction.
2055 DISPLAY is the name of the SQL product that will appear in the
2056 menu bar and in messages. PLIST initializes the product
2057 configuration."
2058
2059 ;; Don't do anything if the product is already supported
2060 (if (assoc product sql-product-alist)
2061 (message "Product `%s' is already defined" product)
2062
2063 ;; Add product to the alist
2064 (add-to-list 'sql-product-alist `((,product :name ,display . ,plist)))
2065 ;; Add a menu item to the SQL->Product menu
2066 (easy-menu-add-item sql-mode-menu '("Product")
2067 ;; Each product is represented by a radio
2068 ;; button with it's display name.
2069 `[,display
2070 (sql-set-product ',product)
2071 :style radio
2072 :selected (eq sql-product ',product)]
2073 ;; Maintain the product list in
2074 ;; (case-insensitive) alphabetic order of the
2075 ;; display names. Loop thru each keymap item
2076 ;; looking for an item whose display name is
2077 ;; after this product's name.
2078 (let ((next-item)
2079 (down-display (downcase display)))
2080 (map-keymap (lambda (k b)
2081 (when (and (not next-item)
2082 (string-lessp down-display
2083 (downcase (cadr b))))
2084 (setq next-item k)))
2085 (easy-menu-get-map sql-mode-menu '("Product")))
2086 next-item))
2087 product))
2088
2089 (defun sql-del-product (product)
2090 "Remove support for PRODUCT in `sql-mode'."
2091
2092 ;; Remove the menu item based on the display name
2093 (easy-menu-remove-item sql-mode-menu '("Product") (sql-get-product-feature product :name))
2094 ;; Remove the product alist item
2095 (setq sql-product-alist (assq-delete-all product sql-product-alist))
2096 nil)
2097
2098 (defun sql-set-product-feature (product feature newvalue)
2099 "Set FEATURE of database PRODUCT to NEWVALUE.
2100
2101 The PRODUCT must be a symbol which identifies the database
2102 product. The product must have already exist on the product
2103 list. See `sql-add-product' to add new products. The FEATURE
2104 argument must be a plist keyword accepted by
2105 `sql-product-alist'."
2106
2107 (let* ((p (assoc product sql-product-alist))
2108 (v (plist-get (cdr p) feature)))
2109 (if p
2110 (if (and
2111 (member feature sql-indirect-features)
2112 (symbolp v))
2113 (set v newvalue)
2114 (setcdr p (plist-put (cdr p) feature newvalue)))
2115 (message "`%s' is not a known product; use `sql-add-product' to add it first." product))))
2116
2117 (defun sql-get-product-feature (product feature &optional fallback not-indirect)
2118 "Lookup FEATURE associated with a SQL PRODUCT.
2119
2120 If the FEATURE is nil for PRODUCT, and FALLBACK is specified,
2121 then the FEATURE associated with the FALLBACK product is
2122 returned.
2123
2124 If the FEATURE is in the list `sql-indirect-features', and the
2125 NOT-INDIRECT parameter is not set, then the value of the symbol
2126 stored in the connect alist is returned.
2127
2128 See `sql-product-alist' for a list of products and supported features."
2129 (let* ((p (assoc product sql-product-alist))
2130 (v (plist-get (cdr p) feature)))
2131
2132 (if p
2133 ;; If no value and fallback, lookup feature for fallback
2134 (if (and (not v)
2135 fallback
2136 (not (eq product fallback)))
2137 (sql-get-product-feature fallback feature)
2138
2139 (if (and
2140 (member feature sql-indirect-features)
2141 (not not-indirect)
2142 (symbolp v))
2143 (symbol-value v)
2144 v))
2145 (message "`%s' is not a known product; use `sql-add-product' to add it first." product)
2146 nil)))
2147
2148 (defun sql-product-font-lock (keywords-only imenu)
2149 "Configure font-lock and imenu with product-specific settings.
2150
2151 The KEYWORDS-ONLY flag is passed to font-lock to specify whether
2152 only keywords should be hilighted and syntactic hilighting
2153 skipped. The IMENU flag indicates whether `imenu-mode' should
2154 also be configured."
2155
2156 (let
2157 ;; Get the product-specific syntax-alist.
2158 ((syntax-alist
2159 (append
2160 (sql-get-product-feature sql-product :syntax-alist)
2161 '((?_ . "w") (?. . "w")))))
2162
2163 ;; Get the product-specific keywords.
2164 (setq sql-mode-font-lock-keywords
2165 (append
2166 (unless (eq sql-product 'ansi)
2167 (sql-get-product-feature sql-product :font-lock))
2168 ;; Always highlight ANSI keywords
2169 (sql-get-product-feature 'ansi :font-lock)
2170 ;; Fontify object names in CREATE, DROP and ALTER DDL
2171 ;; statements
2172 (list sql-mode-font-lock-object-name)))
2173
2174 ;; Setup font-lock. Force re-parsing of `font-lock-defaults'.
2175 (kill-local-variable 'font-lock-set-defaults)
2176 (setq font-lock-defaults (list 'sql-mode-font-lock-keywords
2177 keywords-only t syntax-alist))
2178
2179 ;; Force font lock to reinitialize if it is already on
2180 ;; Otherwise, we can wait until it can be started.
2181 (when (and (fboundp 'font-lock-mode)
2182 (boundp 'font-lock-mode)
2183 font-lock-mode)
2184 (font-lock-mode-internal nil)
2185 (font-lock-mode-internal t))
2186
2187 (add-hook 'font-lock-mode-hook
2188 (lambda ()
2189 ;; Provide defaults for new font-lock faces.
2190 (defvar font-lock-builtin-face
2191 (if (boundp 'font-lock-preprocessor-face)
2192 font-lock-preprocessor-face
2193 font-lock-keyword-face))
2194 (defvar font-lock-doc-face font-lock-string-face))
2195 nil t)
2196
2197 ;; Setup imenu; it needs the same syntax-alist.
2198 (when imenu
2199 (setq imenu-syntax-alist syntax-alist))))
2200
2201 ;;;###autoload
2202 (defun sql-add-product-keywords (product keywords &optional append)
2203 "Add highlighting KEYWORDS for SQL PRODUCT.
2204
2205 PRODUCT should be a symbol, the name of a SQL product, such as
2206 `oracle'. KEYWORDS should be a list; see the variable
2207 `font-lock-keywords'. By default they are added at the beginning
2208 of the current highlighting list. If optional argument APPEND is
2209 `set', they are used to replace the current highlighting list.
2210 If APPEND is any other non-nil value, they are added at the end
2211 of the current highlighting list.
2212
2213 For example:
2214
2215 (sql-add-product-keywords 'ms
2216 '((\"\\\\b\\\\w+_t\\\\b\" . font-lock-type-face)))
2217
2218 adds a fontification pattern to fontify identifiers ending in
2219 `_t' as data types."
2220
2221 (let* ((sql-indirect-features nil)
2222 (font-lock-var (sql-get-product-feature product :font-lock))
2223 (old-val))
2224
2225 (setq old-val (symbol-value font-lock-var))
2226 (set font-lock-var
2227 (if (eq append 'set)
2228 keywords
2229 (if append
2230 (append old-val keywords)
2231 (append keywords old-val))))))
2232
2233 (defun sql-for-each-login (login-params body)
2234 "Iterates through login parameters and returns a list of results."
2235
2236 (delq nil
2237 (mapcar
2238 (lambda (param)
2239 (let ((token (or (and (listp param) (car param)) param))
2240 (type (or (and (listp param) (nth 1 param)) nil))
2241 (arg (or (and (listp param) (nth 2 param)) nil)))
2242
2243 (funcall body token type arg)))
2244 login-params)))
2245
2246 \f
2247
2248 ;;; Functions to switch highlighting
2249
2250 (defun sql-highlight-product ()
2251 "Turn on the font highlighting for the SQL product selected."
2252 (when (derived-mode-p 'sql-mode)
2253 ;; Setup font-lock
2254 (sql-product-font-lock nil t)
2255
2256 ;; Set the mode name to include the product.
2257 (setq mode-name (concat "SQL[" (or (sql-get-product-feature sql-product :name)
2258 (symbol-name sql-product)) "]"))))
2259
2260 (defun sql-set-product (product)
2261 "Set `sql-product' to PRODUCT and enable appropriate highlighting."
2262 (interactive
2263 (list (completing-read "SQL product: "
2264 (mapcar (lambda (info) (symbol-name (car info)))
2265 sql-product-alist)
2266 nil 'require-match
2267 (or (and sql-product (symbol-name sql-product)) "ansi"))))
2268 (if (stringp product) (setq product (intern product)))
2269 (when (not (assoc product sql-product-alist))
2270 (error "SQL product %s is not supported; treated as ANSI" product)
2271 (setq product 'ansi))
2272
2273 ;; Save product setting and fontify.
2274 (setq sql-product product)
2275 (sql-highlight-product))
2276 \f
2277
2278 ;;; Compatibility functions
2279
2280 (if (not (fboundp 'comint-line-beginning-position))
2281 ;; comint-line-beginning-position is defined in Emacs 21
2282 (defun comint-line-beginning-position ()
2283 "Return the buffer position of the beginning of the line, after any prompt.
2284 The prompt is assumed to be any text at the beginning of the line matching
2285 the regular expression `comint-prompt-regexp', a buffer local variable."
2286 (save-excursion (comint-bol nil) (point))))
2287
2288 \f
2289
2290 ;;; Small functions
2291
2292 (defun sql-magic-go (arg)
2293 "Insert \"o\" and call `comint-send-input'.
2294 `sql-electric-stuff' must be the symbol `go'."
2295 (interactive "P")
2296 (self-insert-command (prefix-numeric-value arg))
2297 (if (and (equal sql-electric-stuff 'go)
2298 (save-excursion
2299 (comint-bol nil)
2300 (looking-at "go\\b")))
2301 (comint-send-input)))
2302
2303 (defun sql-magic-semicolon (arg)
2304 "Insert semicolon and call `comint-send-input'.
2305 `sql-electric-stuff' must be the symbol `semicolon'."
2306 (interactive "P")
2307 (self-insert-command (prefix-numeric-value arg))
2308 (if (equal sql-electric-stuff 'semicolon)
2309 (comint-send-input)))
2310
2311 (defun sql-accumulate-and-indent ()
2312 "Continue SQL statement on the next line."
2313 (interactive)
2314 (if (fboundp 'comint-accumulate)
2315 (comint-accumulate)
2316 (newline))
2317 (indent-according-to-mode))
2318
2319 (defun sql-help-list-products (indent freep)
2320 "Generate listing of products available for use under SQLi.
2321
2322 List products with :free-softare attribute set to FREEP. Indent
2323 each line with INDENT."
2324
2325 (let (sqli-func doc)
2326 (setq doc "")
2327 (dolist (p sql-product-alist)
2328 (setq sqli-func (intern (concat "sql-" (symbol-name (car p)))))
2329
2330 (if (and (fboundp sqli-func)
2331 (eq (sql-get-product-feature (car p) :free-software) freep))
2332 (setq doc
2333 (concat doc
2334 indent
2335 (or (sql-get-product-feature (car p) :name)
2336 (symbol-name (car p)))
2337 ":\t"
2338 "\\["
2339 (symbol-name sqli-func)
2340 "]\n"))))
2341 doc))
2342
2343 ;;;###autoload
2344 (defun sql-help ()
2345 "Show short help for the SQL modes.
2346
2347 Use an entry function to open an interactive SQL buffer. This buffer is
2348 usually named `*SQL*'. The name of the major mode is SQLi.
2349
2350 Use the following commands to start a specific SQL interpreter:
2351
2352 \\\\FREE
2353
2354 Other non-free SQL implementations are also supported:
2355
2356 \\\\NONFREE
2357
2358 But we urge you to choose a free implementation instead of these.
2359
2360 You can also use \\[sql-product-interactive] to invoke the
2361 interpreter for the current `sql-product'.
2362
2363 Once you have the SQLi buffer, you can enter SQL statements in the
2364 buffer. The output generated is appended to the buffer and a new prompt
2365 is generated. See the In/Out menu in the SQLi buffer for some functions
2366 that help you navigate through the buffer, the input history, etc.
2367
2368 If you have a really complex SQL statement or if you are writing a
2369 procedure, you can do this in a separate buffer. Put the new buffer in
2370 `sql-mode' by calling \\[sql-mode]. The name of this buffer can be
2371 anything. The name of the major mode is SQL.
2372
2373 In this SQL buffer (SQL mode), you can send the region or the entire
2374 buffer to the interactive SQL buffer (SQLi mode). The results are
2375 appended to the SQLi buffer without disturbing your SQL buffer."
2376 (interactive)
2377
2378 ;; Insert references to loaded products into the help buffer string
2379 (let ((doc (documentation 'sql-help t))
2380 changedp)
2381 (setq changedp nil)
2382
2383 ;; Insert FREE software list
2384 (when (string-match "^\\(\\s-*\\)[\\\\][\\\\]FREE\\s-*\n" doc 0)
2385 (setq doc (replace-match (sql-help-list-products (match-string 1 doc) t)
2386 t t doc 0)
2387 changedp t))
2388
2389 ;; Insert non-FREE software list
2390 (when (string-match "^\\(\\s-*\\)[\\\\][\\\\]NONFREE\\s-*\n" doc 0)
2391 (setq doc (replace-match (sql-help-list-products (match-string 1 doc) nil)
2392 t t doc 0)
2393 changedp t))
2394
2395 ;; If we changed the help text, save the change so that the help
2396 ;; sub-system will see it
2397 (when changedp
2398 (put 'sql-help 'function-documentation doc)))
2399
2400 ;; Call help on this function
2401 (describe-function 'sql-help))
2402
2403 (defun sql-read-passwd (prompt &optional default)
2404 "Read a password using PROMPT. Optional DEFAULT is password to start with."
2405 (read-passwd prompt nil default))
2406
2407 (defun sql-get-login-ext (prompt last-value history-var type arg)
2408 "Prompt user with extended login parameters.
2409
2410 If TYPE is nil, then the user is simply prompted for a string
2411 value.
2412
2413 If TYPE is `:file', then the user is prompted for a file
2414 name that must match the regexp pattern specified in the ARG
2415 argument.
2416
2417 If TYPE is `:completion', then the user is prompted for a string
2418 specified by ARG. (ARG is used as the PREDICATE argument to
2419 `completing-read'.)"
2420 (cond
2421 ((eq type nil)
2422 (read-from-minibuffer prompt last-value nil nil history-var))
2423
2424 ((eq type :file)
2425 (let ((use-dialog-box nil))
2426 (expand-file-name
2427 (read-file-name prompt
2428 (file-name-directory last-value) nil t
2429 (file-name-nondirectory last-value)
2430 (if arg
2431 `(lambda (f)
2432 (string-match (concat "\\<" ,arg "\\>")
2433 (file-name-nondirectory f)))
2434 nil)))))
2435
2436 ((eq type :completion)
2437 (completing-read prompt arg nil t last-value history-var))))
2438
2439 (defun sql-get-login (&rest what)
2440 "Get username, password and database from the user.
2441
2442 The variables `sql-user', `sql-password', `sql-server', and
2443 `sql-database' can be customized. They are used as the default values.
2444 Usernames, servers and databases are stored in `sql-user-history',
2445 `sql-server-history' and `database-history'. Passwords are not stored
2446 in a history.
2447
2448 Parameter WHAT is a list of tokens passed as arguments in the
2449 function call. The function asks for the username if WHAT
2450 contains the symbol `user', for the password if it contains the
2451 symbol `password', for the server if it contains the symbol
2452 `server', and for the database if it contains the symbol
2453 `database'. The members of WHAT are processed in the order in
2454 which they are provided.
2455
2456 The tokens for `database' and `server' may also be lists to
2457 control or limit the values that can be supplied. These can be
2458 of the form:
2459
2460 \(database :file \".+\\\\.EXT\")
2461 \(database :completion FUNCTION)
2462
2463 The `server' token supports the same forms.
2464
2465 In order to ask the user for username, password and database, call the
2466 function like this: (sql-get-login 'user 'password 'database)."
2467 (interactive)
2468 (mapcar
2469 (lambda (w)
2470 (let ((token (or (and (listp w) (car w)) w))
2471 (type (or (and (listp w) (nth 1 w)) nil))
2472 (arg (or (and (listp w) (nth 2 w)) nil)))
2473
2474 (cond
2475 ((eq token 'user) ; user
2476 (setq sql-user
2477 (read-from-minibuffer "User: " sql-user nil nil
2478 'sql-user-history)))
2479
2480 ((eq token 'password) ; password
2481 (setq sql-password
2482 (sql-read-passwd "Password: " sql-password)))
2483
2484 ((eq token 'server) ; server
2485 (setq sql-server
2486 (sql-get-login-ext "Server: " sql-server
2487 'sql-server-history type arg)))
2488
2489 ((eq token 'database) ; database
2490 (setq sql-database
2491 (sql-get-login-ext "Database: " sql-database
2492 'sql-database-history type arg)))
2493
2494 ((eq token 'port) ; port
2495 (setq sql-port
2496 (read-number "Port: " sql-port))))))
2497 what))
2498
2499 (defun sql-find-sqli-buffer ()
2500 "Returns the current default SQLi buffer or nil.
2501 In order to qualify, the SQLi buffer must be alive,
2502 be in `sql-interactive-mode' and have a process."
2503 (let ((default-buffer (default-value 'sql-buffer)))
2504 (if (and (buffer-live-p default-buffer)
2505 (get-buffer-process default-buffer))
2506 default-buffer
2507 (save-current-buffer
2508 (let ((buflist (buffer-list))
2509 (found))
2510 (while (not (or (null buflist)
2511 found))
2512 (let ((candidate (car buflist)))
2513 (set-buffer candidate)
2514 (if (and (derived-mode-p 'sql-interactive-mode)
2515 (get-buffer-process candidate))
2516 (setq found candidate))
2517 (setq buflist (cdr buflist))))
2518 found)))))
2519
2520 (defun sql-set-sqli-buffer-generally ()
2521 "Set SQLi buffer for all SQL buffers that have none.
2522 This function checks all SQL buffers for their SQLi buffer. If their
2523 SQLi buffer is nonexistent or has no process, it is set to the current
2524 default SQLi buffer. The current default SQLi buffer is determined
2525 using `sql-find-sqli-buffer'. If `sql-buffer' is set,
2526 `sql-set-sqli-hook' is run."
2527 (interactive)
2528 (save-excursion
2529 (let ((buflist (buffer-list))
2530 (default-sqli-buffer (sql-find-sqli-buffer)))
2531 (setq-default sql-buffer default-sqli-buffer)
2532 (while (not (null buflist))
2533 (let ((candidate (car buflist)))
2534 (set-buffer candidate)
2535 (if (and (derived-mode-p 'sql-mode)
2536 (not (buffer-live-p sql-buffer)))
2537 (progn
2538 (setq sql-buffer default-sqli-buffer)
2539 (run-hooks 'sql-set-sqli-hook))))
2540 (setq buflist (cdr buflist))))))
2541
2542 (defun sql-set-sqli-buffer ()
2543 "Set the SQLi buffer SQL strings are sent to.
2544
2545 Call this function in a SQL buffer in order to set the SQLi buffer SQL
2546 strings are sent to. Calling this function sets `sql-buffer' and runs
2547 `sql-set-sqli-hook'.
2548
2549 If you call it from a SQL buffer, this sets the local copy of
2550 `sql-buffer'.
2551
2552 If you call it from anywhere else, it sets the global copy of
2553 `sql-buffer'."
2554 (interactive)
2555 (let ((default-buffer (sql-find-sqli-buffer)))
2556 (if (null default-buffer)
2557 (error "There is no suitable SQLi buffer"))
2558 (let ((new-buffer
2559 (get-buffer
2560 (read-buffer "New SQLi buffer: " default-buffer t))))
2561 (if (null (get-buffer-process new-buffer))
2562 (error "Buffer %s has no process" (buffer-name new-buffer)))
2563 (if (null (with-current-buffer new-buffer
2564 (equal major-mode 'sql-interactive-mode)))
2565 (error "Buffer %s is no SQLi buffer" (buffer-name new-buffer)))
2566 (if new-buffer
2567 (progn
2568 (setq sql-buffer new-buffer)
2569 (run-hooks 'sql-set-sqli-hook))))))
2570
2571 (defun sql-show-sqli-buffer ()
2572 "Show the name of current SQLi buffer.
2573
2574 This is the buffer SQL strings are sent to. It is stored in the
2575 variable `sql-buffer'. See `sql-help' on how to create such a buffer."
2576 (interactive)
2577 (if (null (buffer-live-p sql-buffer))
2578 (message "%s has no SQLi buffer set." (buffer-name (current-buffer)))
2579 (if (null (get-buffer-process sql-buffer))
2580 (message "Buffer %s has no process." (buffer-name sql-buffer))
2581 (message "Current SQLi buffer is %s." (buffer-name sql-buffer)))))
2582
2583 (defun sql-make-alternate-buffer-name ()
2584 "Return a string that can be used to rename a SQLi buffer.
2585
2586 This is used to set `sql-alternate-buffer-name' within
2587 `sql-interactive-mode'.
2588
2589 If the session was started with `sql-connect' then the alternate
2590 name would be the name of the connection.
2591
2592 Otherwise, it uses the parameters identified by the :sqlilogin
2593 parameter.
2594
2595 If all else fails, the alternate name would be the user and
2596 server/database name."
2597
2598 (let ((name ""))
2599
2600 ;; Build a name using the :sqli-login setting
2601 (setq name
2602 (apply 'concat
2603 (cdr
2604 (apply 'append nil
2605 (sql-for-each-login
2606 (sql-get-product-feature sql-product :sqli-login)
2607 (lambda (token type arg)
2608 (cond
2609 ((eq token 'user)
2610 (unless (string= "" sql-user)
2611 (list "/" sql-user)))
2612 ((eq token 'port)
2613 (unless (= 0 sql-port)
2614 (list ":" sql-port)))
2615 ((eq token 'server)
2616 (unless (string= "" sql-server)
2617 (list "."
2618 (if (eq type :file)
2619 (file-name-nondirectory sql-server)
2620 sql-server))))
2621 ((eq token 'database)
2622 (when (string= "" sql-database)
2623 (list "@"
2624 (if (eq type :file)
2625 (file-name-nondirectory sql-database)
2626 sql-database))))
2627
2628 ((eq token 'password) nil)
2629 (t nil))))))))
2630
2631 ;; If there's a connection, use it and the name thus far
2632 (if sql-connection
2633 (format "<%s>%s" sql-connection (or name ""))
2634
2635 ;; If there is no name, try to create something meaningful
2636 (if (string= "" (or name ""))
2637 (concat
2638 (if (string= "" sql-user)
2639 (if (string= "" (user-login-name))
2640 ()
2641 (concat (user-login-name) "/"))
2642 (concat sql-user "/"))
2643 (if (string= "" sql-database)
2644 (if (string= "" sql-server)
2645 (system-name)
2646 sql-server)
2647 sql-database))
2648
2649 ;; Use the name we've got
2650 name))))
2651
2652 (defun sql-rename-buffer ()
2653 "Rename a SQLi buffer."
2654 (interactive)
2655 (rename-buffer (format "*SQL: %s*" sql-alternate-buffer-name) t))
2656
2657 (defun sql-copy-column ()
2658 "Copy current column to the end of buffer.
2659 Inserts SELECT or commas if appropriate."
2660 (interactive)
2661 (let ((column))
2662 (save-excursion
2663 (setq column (buffer-substring-no-properties
2664 (progn (forward-char 1) (backward-sexp 1) (point))
2665 (progn (forward-sexp 1) (point))))
2666 (goto-char (point-max))
2667 (let ((bol (comint-line-beginning-position)))
2668 (cond
2669 ;; if empty command line, insert SELECT
2670 ((= bol (point))
2671 (insert "SELECT "))
2672 ;; else if appending to INTO .* (, SELECT or ORDER BY, insert a comma
2673 ((save-excursion
2674 (re-search-backward "\\b\\(\\(into\\s-+\\S-+\\s-+(\\)\\|select\\|order by\\) .+"
2675 bol t))
2676 (insert ", "))
2677 ;; else insert a space
2678 (t
2679 (if (eq (preceding-char) ?\s)
2680 nil
2681 (insert " ")))))
2682 ;; in any case, insert the column
2683 (insert column)
2684 (message "%s" column))))
2685
2686 ;; On Windows, SQL*Plus for Oracle turns on full buffering for stdout
2687 ;; if it is not attached to a character device; therefore placeholder
2688 ;; replacement by SQL*Plus is fully buffered. The workaround lets
2689 ;; Emacs query for the placeholders.
2690
2691 (defvar sql-placeholder-history nil
2692 "History of placeholder values used.")
2693
2694 (defun sql-placeholders-filter (string)
2695 "Replace placeholders in STRING.
2696 Placeholders are words starting with an ampersand like &this."
2697
2698 (when sql-oracle-scan-on
2699 (while (string-match "&\\(\\sw+\\)" string)
2700 (setq string (replace-match
2701 (read-from-minibuffer
2702 (format "Enter value for %s: " (match-string 1 string))
2703 nil nil nil 'sql-placeholder-history)
2704 t t string))))
2705 string)
2706
2707 ;; Using DB2 interactively, newlines must be escaped with " \".
2708 ;; The space before the backslash is relevant.
2709 (defun sql-escape-newlines-filter (string)
2710 "Escape newlines in STRING.
2711 Every newline in STRING will be preceded with a space and a backslash."
2712 (let ((result "") (start 0) mb me)
2713 (while (string-match "\n" string start)
2714 (setq mb (match-beginning 0)
2715 me (match-end 0)
2716 result (concat result
2717 (substring string start mb)
2718 (if (and (> mb 1)
2719 (string-equal " \\" (substring string (- mb 2) mb)))
2720 "" " \\\n"))
2721 start me))
2722 (concat result (substring string start))))
2723
2724 \f
2725
2726 ;;; Input sender for SQLi buffers
2727
2728 (defvar sql-output-newline-count 0
2729 "Number of newlines in the input string.
2730
2731 Allows the suppression of continuation prompts.")
2732
2733 (defvar sql-output-by-send nil
2734 "Non-nil if the command in the input was generated by `sql-send-string'.")
2735
2736 (defun sql-input-sender (proc string)
2737 "Send STRING to PROC after applying filters."
2738
2739 (let* ((product (with-current-buffer (process-buffer proc) sql-product))
2740 (filter (sql-get-product-feature product :input-filter)))
2741
2742 ;; Apply filter(s)
2743 (cond
2744 ((not filter)
2745 nil)
2746 ((functionp filter)
2747 (setq string (funcall filter string)))
2748 ((listp filter)
2749 (mapc (lambda (f) (setq string (funcall f string))) filter))
2750 (t nil))
2751
2752 ;; Count how many newlines in the string
2753 (setq sql-output-newline-count 0)
2754 (mapc (lambda (ch)
2755 (when (eq ch ?\n)
2756 (setq sql-output-newline-count (1+ sql-output-newline-count))))
2757 string)
2758
2759 ;; Send the string
2760 (comint-simple-send proc string)))
2761
2762 ;;; Strip out continuation prompts
2763
2764 (defun sql-interactive-remove-continuation-prompt (oline)
2765 "Strip out continuation prompts out of the OLINE.
2766
2767 Added to the `comint-preoutput-filter-functions' hook in a SQL
2768 interactive buffer. If `sql-outut-newline-count' is greater than
2769 zero, then an output line matching the continuation prompt is filtered
2770 out. If the count is one, then the prompt is replaced with a newline
2771 to force the output from the query to appear on a new line."
2772 (if (and sql-prompt-cont-regexp
2773 sql-output-newline-count
2774 (numberp sql-output-newline-count)
2775 (>= sql-output-newline-count 1))
2776 (progn
2777 (while (and oline
2778 sql-output-newline-count
2779 (> sql-output-newline-count 0)
2780 (string-match sql-prompt-cont-regexp oline))
2781
2782 (setq oline
2783 (replace-match (if (and
2784 (= 1 sql-output-newline-count)
2785 sql-output-by-send)
2786 "\n" "")
2787 nil nil oline)
2788 sql-output-newline-count
2789 (1- sql-output-newline-count)))
2790 (if (= sql-output-newline-count 0)
2791 (setq sql-output-newline-count nil))
2792 (setq sql-output-by-send nil))
2793 (setq sql-output-newline-count nil))
2794 oline)
2795
2796 ;;; Sending the region to the SQLi buffer.
2797
2798 (defun sql-send-string (str)
2799 "Send the string STR to the SQL process."
2800 (interactive "sSQL Text: ")
2801
2802 (let ((comint-input-sender-no-newline nil)
2803 (s (replace-regexp-in-string "[[:space:]\n\r]+\\'" "" str)))
2804 (if (buffer-live-p sql-buffer)
2805 (progn
2806 ;; Ignore the hoping around...
2807 (save-excursion
2808 ;; Set product context
2809 (with-current-buffer sql-buffer
2810 ;; Send the string (trim the trailing whitespace)
2811 (sql-input-sender (get-buffer-process sql-buffer) s)
2812
2813 ;; Send a command terminator if we must
2814 (if sql-send-terminator
2815 (sql-send-magic-terminator sql-buffer s sql-send-terminator))
2816
2817 (message "Sent string to buffer %s." (buffer-name sql-buffer))))
2818
2819 ;; Display the sql buffer
2820 (if sql-pop-to-buffer-after-send-region
2821 (pop-to-buffer sql-buffer)
2822 (display-buffer sql-buffer)))
2823
2824 ;; We don't have no stinkin' sql
2825 (message "No SQL process started."))))
2826
2827 (defun sql-send-region (start end)
2828 "Send a region to the SQL process."
2829 (interactive "r")
2830 (sql-send-string (buffer-substring-no-properties start end)))
2831
2832 (defun sql-send-paragraph ()
2833 "Send the current paragraph to the SQL process."
2834 (interactive)
2835 (let ((start (save-excursion
2836 (backward-paragraph)
2837 (point)))
2838 (end (save-excursion
2839 (forward-paragraph)
2840 (point))))
2841 (sql-send-region start end)))
2842
2843 (defun sql-send-buffer ()
2844 "Send the buffer contents to the SQL process."
2845 (interactive)
2846 (sql-send-region (point-min) (point-max)))
2847
2848 (defun sql-send-magic-terminator (buf str terminator)
2849 "Send TERMINATOR to buffer BUF if its not present in STR."
2850 (let (comint-input-sender-no-newline pat term)
2851 ;; If flag is merely on(t), get product-specific terminator
2852 (if (eq terminator t)
2853 (setq terminator (sql-get-product-feature sql-product :terminator)))
2854
2855 ;; If there is no terminator specified, use default ";"
2856 (unless terminator
2857 (setq terminator ";"))
2858
2859 ;; Parse the setting into the pattern and the terminator string
2860 (cond ((stringp terminator)
2861 (setq pat (regexp-quote terminator)
2862 term terminator))
2863 ((consp terminator)
2864 (setq pat (car terminator)
2865 term (cdr terminator)))
2866 (t
2867 nil))
2868
2869 ;; Check to see if the pattern is present in the str already sent
2870 (unless (and pat term
2871 (string-match (concat pat "\\'") str))
2872 (comint-simple-send (get-buffer-process buf) term)
2873 (setq sql-output-newline-count
2874 (if sql-output-newline-count
2875 (1+ sql-output-newline-count)
2876 1)))
2877 (setq sql-output-by-send t)))
2878
2879 (defun sql-remove-tabs-filter (str)
2880 "Replace tab characters with spaces."
2881 (replace-regexp-in-string "\t" " " str nil t))
2882
2883 (defun sql-toggle-pop-to-buffer-after-send-region (&optional value)
2884 "Toggle `sql-pop-to-buffer-after-send-region'.
2885
2886 If given the optional parameter VALUE, sets
2887 `sql-toggle-pop-to-buffer-after-send-region' to VALUE."
2888 (interactive "P")
2889 (if value
2890 (setq sql-pop-to-buffer-after-send-region value)
2891 (setq sql-pop-to-buffer-after-send-region
2892 (null sql-pop-to-buffer-after-send-region))))
2893
2894 \f
2895
2896 ;;; SQL mode -- uses SQL interactive mode
2897
2898 ;;;###autoload
2899 (defun sql-mode ()
2900 "Major mode to edit SQL.
2901
2902 You can send SQL statements to the SQLi buffer using
2903 \\[sql-send-region]. Such a buffer must exist before you can do this.
2904 See `sql-help' on how to create SQLi buffers.
2905
2906 \\{sql-mode-map}
2907 Customization: Entry to this mode runs the `sql-mode-hook'.
2908
2909 When you put a buffer in SQL mode, the buffer stores the last SQLi
2910 buffer created as its destination in the variable `sql-buffer'. This
2911 will be the buffer \\[sql-send-region] sends the region to. If this
2912 SQLi buffer is killed, \\[sql-send-region] is no longer able to
2913 determine where the strings should be sent to. You can set the
2914 value of `sql-buffer' using \\[sql-set-sqli-buffer].
2915
2916 For information on how to create multiple SQLi buffers, see
2917 `sql-interactive-mode'.
2918
2919 Note that SQL doesn't have an escape character unless you specify
2920 one. If you specify backslash as escape character in SQL,
2921 you must tell Emacs. Here's how to do that in your `~/.emacs' file:
2922
2923 \(add-hook 'sql-mode-hook
2924 (lambda ()
2925 (modify-syntax-entry ?\\\\ \".\" sql-mode-syntax-table)))"
2926 (interactive)
2927 (kill-all-local-variables)
2928 (setq major-mode 'sql-mode)
2929 (setq mode-name "SQL")
2930 (use-local-map sql-mode-map)
2931 (if sql-mode-menu
2932 (easy-menu-add sql-mode-menu)); XEmacs
2933 (set-syntax-table sql-mode-syntax-table)
2934 (make-local-variable 'font-lock-defaults)
2935 (make-local-variable 'sql-mode-font-lock-keywords)
2936 (make-local-variable 'comment-start)
2937 (setq comment-start "--")
2938 ;; Make each buffer in sql-mode remember the "current" SQLi buffer.
2939 (make-local-variable 'sql-buffer)
2940 ;; Add imenu support for sql-mode. Note that imenu-generic-expression
2941 ;; is buffer-local, so we don't need a local-variable for it. SQL is
2942 ;; case-insensitive, that's why we have to set imenu-case-fold-search.
2943 (setq imenu-generic-expression sql-imenu-generic-expression
2944 imenu-case-fold-search t)
2945 ;; Make `sql-send-paragraph' work on paragraphs that contain indented
2946 ;; lines.
2947 (make-local-variable 'paragraph-separate)
2948 (make-local-variable 'paragraph-start)
2949 (setq paragraph-separate "[\f]*$"
2950 paragraph-start "[\n\f]")
2951 ;; Abbrevs
2952 (setq local-abbrev-table sql-mode-abbrev-table)
2953 (setq abbrev-all-caps 1)
2954 ;; Run hook
2955 (run-mode-hooks 'sql-mode-hook)
2956 ;; Catch changes to sql-product and highlight accordingly
2957 (sql-highlight-product)
2958 (add-hook 'hack-local-variables-hook 'sql-highlight-product t t))
2959
2960 \f
2961
2962 ;;; SQL interactive mode
2963
2964 (put 'sql-interactive-mode 'mode-class 'special)
2965
2966 (defun sql-interactive-mode ()
2967 "Major mode to use a SQL interpreter interactively.
2968
2969 Do not call this function by yourself. The environment must be
2970 initialized by an entry function specific for the SQL interpreter.
2971 See `sql-help' for a list of available entry functions.
2972
2973 \\[comint-send-input] after the end of the process' output sends the
2974 text from the end of process to the end of the current line.
2975 \\[comint-send-input] before end of process output copies the current
2976 line minus the prompt to the end of the buffer and sends it.
2977 \\[comint-copy-old-input] just copies the current line.
2978 Use \\[sql-accumulate-and-indent] to enter multi-line statements.
2979
2980 If you want to make multiple SQL buffers, rename the `*SQL*' buffer
2981 using \\[rename-buffer] or \\[rename-uniquely] and start a new process.
2982 See `sql-help' for a list of available entry functions. The last buffer
2983 created by such an entry function is the current SQLi buffer. SQL
2984 buffers will send strings to the SQLi buffer current at the time of
2985 their creation. See `sql-mode' for details.
2986
2987 Sample session using two connections:
2988
2989 1. Create first SQLi buffer by calling an entry function.
2990 2. Rename buffer \"*SQL*\" to \"*Connection 1*\".
2991 3. Create a SQL buffer \"test1.sql\".
2992 4. Create second SQLi buffer by calling an entry function.
2993 5. Rename buffer \"*SQL*\" to \"*Connection 2*\".
2994 6. Create a SQL buffer \"test2.sql\".
2995
2996 Now \\[sql-send-region] in buffer \"test1.sql\" will send the region to
2997 buffer \"*Connection 1*\", \\[sql-send-region] in buffer \"test2.sql\"
2998 will send the region to buffer \"*Connection 2*\".
2999
3000 If you accidentally suspend your process, use \\[comint-continue-subjob]
3001 to continue it. On some operating systems, this will not work because
3002 the signals are not supported.
3003
3004 \\{sql-interactive-mode-map}
3005 Customization: Entry to this mode runs the hooks on `comint-mode-hook'
3006 and `sql-interactive-mode-hook' (in that order). Before each input, the
3007 hooks on `comint-input-filter-functions' are run. After each SQL
3008 interpreter output, the hooks on `comint-output-filter-functions' are
3009 run.
3010
3011 Variable `sql-input-ring-file-name' controls the initialization of the
3012 input ring history.
3013
3014 Variables `comint-output-filter-functions', a hook, and
3015 `comint-scroll-to-bottom-on-input' and
3016 `comint-scroll-to-bottom-on-output' control whether input and output
3017 cause the window to scroll to the end of the buffer.
3018
3019 If you want to make SQL buffers limited in length, add the function
3020 `comint-truncate-buffer' to `comint-output-filter-functions'.
3021
3022 Here is an example for your .emacs file. It keeps the SQLi buffer a
3023 certain length.
3024
3025 \(add-hook 'sql-interactive-mode-hook
3026 \(function (lambda ()
3027 \(setq comint-output-filter-functions 'comint-truncate-buffer))))
3028
3029 Here is another example. It will always put point back to the statement
3030 you entered, right above the output it created.
3031
3032 \(setq comint-output-filter-functions
3033 \(function (lambda (STR) (comint-show-output))))"
3034 (delay-mode-hooks (comint-mode))
3035
3036 ;; Get the `sql-product' for this interactive session.
3037 (set (make-local-variable 'sql-product)
3038 (or sql-interactive-product
3039 sql-product))
3040
3041 ;; Setup the mode.
3042 (setq major-mode 'sql-interactive-mode)
3043 (setq mode-name (concat "SQLi[" (or (sql-get-product-feature sql-product :name)
3044 (symbol-name sql-product)) "]"))
3045 (use-local-map sql-interactive-mode-map)
3046 (if sql-interactive-mode-menu
3047 (easy-menu-add sql-interactive-mode-menu)) ; XEmacs
3048 (set-syntax-table sql-mode-syntax-table)
3049 (make-local-variable 'sql-mode-font-lock-keywords)
3050 (make-local-variable 'font-lock-defaults)
3051
3052 ;; Note that making KEYWORDS-ONLY nil will cause havoc if you try
3053 ;; SELECT 'x' FROM DUAL with SQL*Plus, because the title of the column
3054 ;; will have just one quote. Therefore syntactic hilighting is
3055 ;; disabled for interactive buffers. No imenu support.
3056 (sql-product-font-lock t nil)
3057
3058 ;; Enable commenting and uncommenting of the region.
3059 (make-local-variable 'comment-start)
3060 (setq comment-start "--")
3061 ;; Abbreviation table init and case-insensitive. It is not activated
3062 ;; by default.
3063 (setq local-abbrev-table sql-mode-abbrev-table)
3064 (setq abbrev-all-caps 1)
3065 ;; Exiting the process will call sql-stop.
3066 (set-process-sentinel (get-buffer-process sql-buffer) 'sql-stop)
3067 ;; Save the connection name
3068 (make-local-variable 'sql-connection)
3069 ;; Create a usefull name for renaming this buffer later.
3070 (make-local-variable 'sql-alternate-buffer-name)
3071 (setq sql-alternate-buffer-name (sql-make-alternate-buffer-name))
3072 ;; User stuff. Initialize before the hook.
3073 (set (make-local-variable 'sql-prompt-regexp)
3074 (sql-get-product-feature sql-product :prompt-regexp))
3075 (set (make-local-variable 'sql-prompt-length)
3076 (sql-get-product-feature sql-product :prompt-length))
3077 (set (make-local-variable 'sql-prompt-cont-regexp)
3078 (sql-get-product-feature sql-product :prompt-cont-regexp))
3079 (make-local-variable 'sql-output-newline-count)
3080 (make-local-variable 'sql-output-by-send)
3081 (add-hook 'comint-preoutput-filter-functions
3082 'sql-interactive-remove-continuation-prompt nil t)
3083 (make-local-variable 'sql-input-ring-separator)
3084 (make-local-variable 'sql-input-ring-file-name)
3085 ;; Run the mode hook (along with comint's hooks).
3086 (run-mode-hooks 'sql-interactive-mode-hook)
3087 ;; Set comint based on user overrides.
3088 (setq comint-prompt-regexp
3089 (if sql-prompt-cont-regexp
3090 (concat "\\(" sql-prompt-regexp
3091 "\\|" sql-prompt-cont-regexp "\\)")
3092 sql-prompt-regexp))
3093 (setq left-margin sql-prompt-length)
3094 ;; Install input sender
3095 (set (make-local-variable 'comint-input-sender) 'sql-input-sender)
3096 ;; People wanting a different history file for each
3097 ;; buffer/process/client/whatever can change separator and file-name
3098 ;; on the sql-interactive-mode-hook.
3099 (setq comint-input-ring-separator sql-input-ring-separator
3100 comint-input-ring-file-name sql-input-ring-file-name)
3101 ;; Calling the hook before calling comint-read-input-ring allows users
3102 ;; to set comint-input-ring-file-name in sql-interactive-mode-hook.
3103 (comint-read-input-ring t))
3104
3105 (defun sql-stop (process event)
3106 "Called when the SQL process is stopped.
3107
3108 Writes the input history to a history file using
3109 `comint-write-input-ring' and inserts a short message in the SQL buffer.
3110
3111 This function is a sentinel watching the SQL interpreter process.
3112 Sentinels will always get the two parameters PROCESS and EVENT."
3113 (comint-write-input-ring)
3114 (if (and (eq (current-buffer) sql-buffer)
3115 (not buffer-read-only))
3116 (insert (format "\nProcess %s %s\n" process event))
3117 (message "Process %s %s" process event)))
3118
3119 \f
3120
3121 ;;; Connection handling
3122
3123 ;;;###autoload
3124 (defun sql-connect (connection)
3125 "Connect to an interactive session using CONNECTION settings.
3126
3127 See `sql-connection-alist' to see how to define connections and
3128 their settings.
3129
3130 The user will not be prompted for any login parameters if a value
3131 is specified in the connection settings."
3132
3133 ;; Prompt for the connection from those defined in the alist
3134 (interactive
3135 (if sql-connection-alist
3136 (list
3137 (let ((completion-ignore-case t))
3138 (completing-read "Connection: "
3139 (mapcar (lambda (c) (car c))
3140 sql-connection-alist)
3141 nil t nil nil '(()))))
3142 nil))
3143
3144 ;; Are there connections defined
3145 (if sql-connection-alist
3146 ;; Was one selected
3147 (when connection
3148 ;; Get connection settings
3149 (let ((connect-set (assoc connection sql-connection-alist)))
3150 ;; Settings are defined
3151 (if connect-set
3152 ;; Set the desired parameters
3153 (eval `(let*
3154 (,@(cdr connect-set)
3155 ;; :sqli-login params variable
3156 (param-var (sql-get-product-feature sql-product
3157 :sqli-login nil t))
3158 ;; :sqli-login params value
3159 (login-params (sql-get-product-feature sql-product
3160 :sqli-login))
3161 ;; which params are in the connection
3162 (set-params (mapcar
3163 (lambda (v)
3164 (cond
3165 ((eq (car v) 'sql-user) 'user)
3166 ((eq (car v) 'sql-password) 'password)
3167 ((eq (car v) 'sql-server) 'server)
3168 ((eq (car v) 'sql-database) 'database)
3169 ((eq (car v) 'sql-port) 'port)
3170 (t (car v))))
3171 (cdr connect-set)))
3172 ;; the remaining params (w/o the connection params)
3173 (rem-params (sql-for-each-login
3174 login-params
3175 (lambda (token type arg)
3176 (unless (member token set-params)
3177 (if (or type arg)
3178 (list token type arg)
3179 token)))))
3180 ;; Remember the connection
3181 (sql-connection connection))
3182
3183 ;; Set the remaining parameters and start the
3184 ;; interactive session
3185 (eval `(let ((,param-var ',rem-params))
3186 (sql-product-interactive sql-product)))))
3187 (message "SQL Connection <%s> does not exist" connection)
3188 nil)))
3189 (message "No SQL Connections defined")
3190 nil))
3191
3192 (defun sql-save-connection (name)
3193 "Captures the connection information of the current SQLi session.
3194
3195 The information is appended to `sql-connection-alist' and
3196 optionally is saved to the user's init file."
3197
3198 (interactive "sNew connection name: ")
3199
3200 (if sql-connection
3201 (message "This session was started by a connection; it's already been saved.")
3202
3203 (let ((login (sql-get-product-feature sql-product :sqli-login))
3204 (alist sql-connection-alist)
3205 connect)
3206
3207 ;; Remove the existing connection if the user says so
3208 (when (and (assoc name alist)
3209 (yes-or-no-p (format "Replace connection definition <%s>? " name)))
3210 (setq alist (assq-delete-all name alist)))
3211
3212 ;; Add the new connection if it doesn't exist
3213 (if (assoc name alist)
3214 (message "Connection <%s> already exists" name)
3215 (setq connect
3216 (append (list name)
3217 (sql-for-each-login
3218 `(product ,@login)
3219 (lambda (token type arg)
3220 (cond
3221 ((eq token 'product) `(sql-product ',sql-product))
3222 ((eq token 'user) `(sql-user ,sql-user))
3223 ((eq token 'database) `(sql-database ,sql-database))
3224 ((eq token 'server) `(sql-server ,sql-server))
3225 ((eq token 'port) `(sql-port ,sql-port)))))))
3226
3227 (setq alist (append alist (list connect)))
3228
3229 ;; confirm whether we want to save the connections
3230 (if (yes-or-no-p "Save the connections for future sessions? ")
3231 (customize-save-variable 'sql-connection-alist alist)
3232 (customize-set-variable 'sql-connection-alist alist))))))
3233
3234 (defun sql-connection-menu-filter (tail)
3235 "Generates menu entries for using each connection."
3236 (append
3237 (mapcar
3238 (lambda (conn)
3239 (vector
3240 (format "Connection <%s>" (car conn))
3241 (list 'sql-connect (car conn))
3242 t))
3243 sql-connection-alist)
3244 tail))
3245
3246 \f
3247
3248 ;;; Entry functions for different SQL interpreters.
3249
3250 ;;;###autoload
3251 (defun sql-product-interactive (&optional product)
3252 "Run PRODUCT interpreter as an inferior process.
3253
3254 If buffer `*SQL*' exists but no process is running, make a new process.
3255 If buffer exists and a process is running, just switch to buffer `*SQL*'.
3256
3257 \(Type \\[describe-mode] in the SQL buffer for a list of commands.)"
3258 (interactive "P")
3259
3260 (setq product
3261 (cond
3262 ((equal product '(4)) ; Universal arg, prompt for product
3263 (intern (completing-read "SQL product: "
3264 (mapcar (lambda (info) (symbol-name (car info)))
3265 sql-product-alist)
3266 nil 'require-match
3267 (or (and sql-product (symbol-name sql-product)) "ansi"))))
3268 ((and product ; Product specified
3269 (symbolp product)) product)
3270 (t sql-product))) ; Default to sql-product
3271
3272 (if product
3273 (when (sql-get-product-feature product :sqli-comint-func)
3274 (if (and sql-buffer
3275 (buffer-live-p sql-buffer)
3276 (comint-check-proc sql-buffer))
3277 (pop-to-buffer sql-buffer)
3278
3279 ;; Is the current buffer in sql-mode and
3280 ;; there is a buffer local setting of sql-buffer
3281 (let* ((start-buffer
3282 (and (derived-mode-p 'sql-mode)
3283 (current-buffer)))
3284 (start-sql-buffer
3285 (and start-buffer
3286 (let (found)
3287 (dolist (var (buffer-local-variables))
3288 (and (consp var)
3289 (eq (car var) 'sql-buffer)
3290 (buffer-live-p (cdr var))
3291 (get-buffer-process (cdr var))
3292 (setq found (cdr var))))
3293 found)))
3294 new-sqli-buffer)
3295
3296 ;; Get credentials.
3297 (apply 'sql-get-login (sql-get-product-feature product :sqli-login))
3298
3299 ;; Connect to database.
3300 (message "Login...")
3301 (funcall (sql-get-product-feature product :sqli-comint-func)
3302 product
3303 (sql-get-product-feature product :sqli-options))
3304
3305 ;; Set SQLi mode.
3306 (setq sql-interactive-product product
3307 new-sqli-buffer (current-buffer)
3308 sql-buffer new-sqli-buffer)
3309 (sql-interactive-mode)
3310
3311 ;; Set `sql-buffer' in the start buffer
3312 (when (and start-buffer (not start-sql-buffer))
3313 (with-current-buffer start-buffer
3314 (setq sql-buffer new-sqli-buffer)))
3315
3316 ;; All done.
3317 (message "Login...done")
3318 (pop-to-buffer sql-buffer))))
3319 (message "No default SQL product defined. Set `sql-product'.")))
3320
3321 (defun sql-comint (product params)
3322 "Set up a comint buffer to run the SQL processor.
3323
3324 PRODUCT is the SQL product. PARAMS is a list of strings which are
3325 passed as command line arguments."
3326 (let ((program (sql-get-product-feature product :sqli-program)))
3327 (set-buffer
3328 (apply 'make-comint "SQL" program nil params))))
3329
3330 ;;;###autoload
3331 (defun sql-oracle ()
3332 "Run sqlplus by Oracle as an inferior process.
3333
3334 If buffer `*SQL*' exists but no process is running, make a new process.
3335 If buffer exists and a process is running, just switch to buffer
3336 `*SQL*'.
3337
3338 Interpreter used comes from variable `sql-oracle-program'. Login uses
3339 the variables `sql-user', `sql-password', and `sql-database' as
3340 defaults, if set. Additional command line parameters can be stored in
3341 the list `sql-oracle-options'.
3342
3343 The buffer is put in SQL interactive mode, giving commands for sending
3344 input. See `sql-interactive-mode'.
3345
3346 To specify a coding system for converting non-ASCII characters
3347 in the input and output to the process, use \\[universal-coding-system-argument]
3348 before \\[sql-oracle]. You can also specify this with \\[set-buffer-process-coding-system]
3349 in the SQL buffer, after you start the process.
3350 The default comes from `process-coding-system-alist' and
3351 `default-process-coding-system'.
3352
3353 \(Type \\[describe-mode] in the SQL buffer for a list of commands.)"
3354 (interactive)
3355 (sql-product-interactive 'oracle))
3356
3357 (defun sql-comint-oracle (product options)
3358 "Create comint buffer and connect to Oracle."
3359 ;; Produce user/password@database construct. Password without user
3360 ;; is meaningless; database without user/password is meaningless,
3361 ;; because "@param" will ask sqlplus to interpret the script
3362 ;; "param".
3363 (let ((parameter nil))
3364 (if (not (string= "" sql-user))
3365 (if (not (string= "" sql-password))
3366 (setq parameter (concat sql-user "/" sql-password))
3367 (setq parameter sql-user)))
3368 (if (and parameter (not (string= "" sql-database)))
3369 (setq parameter (concat parameter "@" sql-database)))
3370 (if parameter
3371 (setq parameter (nconc (list parameter) options))
3372 (setq parameter options))
3373 (sql-comint product parameter)))
3374
3375 \f
3376
3377 ;;;###autoload
3378 (defun sql-sybase ()
3379 "Run isql by Sybase as an inferior process.
3380
3381 If buffer `*SQL*' exists but no process is running, make a new process.
3382 If buffer exists and a process is running, just switch to buffer
3383 `*SQL*'.
3384
3385 Interpreter used comes from variable `sql-sybase-program'. Login uses
3386 the variables `sql-server', `sql-user', `sql-password', and
3387 `sql-database' as defaults, if set. Additional command line parameters
3388 can be stored in the list `sql-sybase-options'.
3389
3390 The buffer is put in SQL interactive mode, giving commands for sending
3391 input. See `sql-interactive-mode'.
3392
3393 To specify a coding system for converting non-ASCII characters
3394 in the input and output to the process, use \\[universal-coding-system-argument]
3395 before \\[sql-sybase]. You can also specify this with \\[set-buffer-process-coding-system]
3396 in the SQL buffer, after you start the process.
3397 The default comes from `process-coding-system-alist' and
3398 `default-process-coding-system'.
3399
3400 \(Type \\[describe-mode] in the SQL buffer for a list of commands.)"
3401 (interactive)
3402 (sql-product-interactive 'sybase))
3403
3404 (defun sql-comint-sybase (product options)
3405 "Create comint buffer and connect to Sybase."
3406 ;; Put all parameters to the program (if defined) in a list and call
3407 ;; make-comint.
3408 (let ((params options))
3409 (if (not (string= "" sql-server))
3410 (setq params (append (list "-S" sql-server) params)))
3411 (if (not (string= "" sql-database))
3412 (setq params (append (list "-D" sql-database) params)))
3413 (if (not (string= "" sql-password))
3414 (setq params (append (list "-P" sql-password) params)))
3415 (if (not (string= "" sql-user))
3416 (setq params (append (list "-U" sql-user) params)))
3417 (sql-comint product params)))
3418
3419 \f
3420
3421 ;;;###autoload
3422 (defun sql-informix ()
3423 "Run dbaccess by Informix as an inferior process.
3424
3425 If buffer `*SQL*' exists but no process is running, make a new process.
3426 If buffer exists and a process is running, just switch to buffer
3427 `*SQL*'.
3428
3429 Interpreter used comes from variable `sql-informix-program'. Login uses
3430 the variable `sql-database' as default, if set.
3431
3432 The buffer is put in SQL interactive mode, giving commands for sending
3433 input. See `sql-interactive-mode'.
3434
3435 To specify a coding system for converting non-ASCII characters
3436 in the input and output to the process, use \\[universal-coding-system-argument]
3437 before \\[sql-informix]. You can also specify this with \\[set-buffer-process-coding-system]
3438 in the SQL buffer, after you start the process.
3439 The default comes from `process-coding-system-alist' and
3440 `default-process-coding-system'.
3441
3442 \(Type \\[describe-mode] in the SQL buffer for a list of commands.)"
3443 (interactive)
3444 (sql-product-interactive 'informix))
3445
3446 (defun sql-comint-informix (product options)
3447 "Create comint buffer and connect to Informix."
3448 ;; username and password are ignored.
3449 (let ((db (if (string= "" sql-database)
3450 "-"
3451 (if (string= "" sql-server)
3452 sql-database
3453 (concat sql-database "@" sql-server)))))
3454 (sql-comint product (append `(,db "-") options))))
3455
3456 \f
3457
3458 ;;;###autoload
3459 (defun sql-sqlite ()
3460 "Run sqlite as an inferior process.
3461
3462 SQLite is free software.
3463
3464 If buffer `*SQL*' exists but no process is running, make a new process.
3465 If buffer exists and a process is running, just switch to buffer
3466 `*SQL*'.
3467
3468 Interpreter used comes from variable `sql-sqlite-program'. Login uses
3469 the variables `sql-user', `sql-password', `sql-database', and
3470 `sql-server' as defaults, if set. Additional command line parameters
3471 can be stored in the list `sql-sqlite-options'.
3472
3473 The buffer is put in SQL interactive mode, giving commands for sending
3474 input. See `sql-interactive-mode'.
3475
3476 To specify a coding system for converting non-ASCII characters
3477 in the input and output to the process, use \\[universal-coding-system-argument]
3478 before \\[sql-sqlite]. You can also specify this with \\[set-buffer-process-coding-system]
3479 in the SQL buffer, after you start the process.
3480 The default comes from `process-coding-system-alist' and
3481 `default-process-coding-system'.
3482
3483 \(Type \\[describe-mode] in the SQL buffer for a list of commands.)"
3484 (interactive)
3485 (sql-product-interactive 'sqlite))
3486
3487 (defun sql-comint-sqlite (product options)
3488 "Create comint buffer and connect to SQLite."
3489 ;; Put all parameters to the program (if defined) in a list and call
3490 ;; make-comint.
3491 (let ((params))
3492 (if (not (string= "" sql-database))
3493 (setq params (append (list (expand-file-name sql-database))
3494 params)))
3495 (setq params (append options params))
3496 (sql-comint product params)))
3497
3498 \f
3499
3500 ;;;###autoload
3501 (defun sql-mysql ()
3502 "Run mysql by TcX as an inferior process.
3503
3504 Mysql versions 3.23 and up are free software.
3505
3506 If buffer `*SQL*' exists but no process is running, make a new process.
3507 If buffer exists and a process is running, just switch to buffer
3508 `*SQL*'.
3509
3510 Interpreter used comes from variable `sql-mysql-program'. Login uses
3511 the variables `sql-user', `sql-password', `sql-database', and
3512 `sql-server' as defaults, if set. Additional command line parameters
3513 can be stored in the list `sql-mysql-options'.
3514
3515 The buffer is put in SQL interactive mode, giving commands for sending
3516 input. See `sql-interactive-mode'.
3517
3518 To specify a coding system for converting non-ASCII characters
3519 in the input and output to the process, use \\[universal-coding-system-argument]
3520 before \\[sql-mysql]. You can also specify this with \\[set-buffer-process-coding-system]
3521 in the SQL buffer, after you start the process.
3522 The default comes from `process-coding-system-alist' and
3523 `default-process-coding-system'.
3524
3525 \(Type \\[describe-mode] in the SQL buffer for a list of commands.)"
3526 (interactive)
3527 (sql-product-interactive 'mysql))
3528
3529 (defun sql-comint-mysql (product options)
3530 "Create comint buffer and connect to MySQL."
3531 ;; Put all parameters to the program (if defined) in a list and call
3532 ;; make-comint.
3533 (let ((params))
3534 (if (not (string= "" sql-database))
3535 (setq params (append (list sql-database) params)))
3536 (if (not (string= "" sql-server))
3537 (setq params (append (list (concat "--host=" sql-server)) params)))
3538 (if (and sql-port (numberp sql-port))
3539 (setq params (append (list (concat "--port=" (number-to-string sql-port))) params)))
3540 (if (not (string= "" sql-password))
3541 (setq params (append (list (concat "--password=" sql-password)) params)))
3542 (if (not (string= "" sql-user))
3543 (setq params (append (list (concat "--user=" sql-user)) params)))
3544 (setq params (append options params))
3545 (sql-comint product params)))
3546
3547 \f
3548
3549 ;;;###autoload
3550 (defun sql-solid ()
3551 "Run solsql by Solid as an inferior process.
3552
3553 If buffer `*SQL*' exists but no process is running, make a new process.
3554 If buffer exists and a process is running, just switch to buffer
3555 `*SQL*'.
3556
3557 Interpreter used comes from variable `sql-solid-program'. Login uses
3558 the variables `sql-user', `sql-password', and `sql-server' as
3559 defaults, if set.
3560
3561 The buffer is put in SQL interactive mode, giving commands for sending
3562 input. See `sql-interactive-mode'.
3563
3564 To specify a coding system for converting non-ASCII characters
3565 in the input and output to the process, use \\[universal-coding-system-argument]
3566 before \\[sql-solid]. You can also specify this with \\[set-buffer-process-coding-system]
3567 in the SQL buffer, after you start the process.
3568 The default comes from `process-coding-system-alist' and
3569 `default-process-coding-system'.
3570
3571 \(Type \\[describe-mode] in the SQL buffer for a list of commands.)"
3572 (interactive)
3573 (sql-product-interactive 'solid))
3574
3575 (defun sql-comint-solid (product options)
3576 "Create comint buffer and connect to Solid."
3577 ;; Put all parameters to the program (if defined) in a list and call
3578 ;; make-comint.
3579 (let ((params options))
3580 ;; It only makes sense if both username and password are there.
3581 (if (not (or (string= "" sql-user)
3582 (string= "" sql-password)))
3583 (setq params (append (list sql-user sql-password) params)))
3584 (if (not (string= "" sql-server))
3585 (setq params (append (list sql-server) params)))
3586 (sql-comint product params)))
3587
3588 \f
3589
3590 ;;;###autoload
3591 (defun sql-ingres ()
3592 "Run sql by Ingres as an inferior process.
3593
3594 If buffer `*SQL*' exists but no process is running, make a new process.
3595 If buffer exists and a process is running, just switch to buffer
3596 `*SQL*'.
3597
3598 Interpreter used comes from variable `sql-ingres-program'. Login uses
3599 the variable `sql-database' as default, if set.
3600
3601 The buffer is put in SQL interactive mode, giving commands for sending
3602 input. See `sql-interactive-mode'.
3603
3604 To specify a coding system for converting non-ASCII characters
3605 in the input and output to the process, use \\[universal-coding-system-argument]
3606 before \\[sql-ingres]. You can also specify this with \\[set-buffer-process-coding-system]
3607 in the SQL buffer, after you start the process.
3608 The default comes from `process-coding-system-alist' and
3609 `default-process-coding-system'.
3610
3611 \(Type \\[describe-mode] in the SQL buffer for a list of commands.)"
3612 (interactive)
3613 (sql-product-interactive 'ingres))
3614
3615 (defun sql-comint-ingres (product options)
3616 "Create comint buffer and connect to Ingres."
3617 ;; username and password are ignored.
3618 (sql-comint product
3619 (append (if (string= "" sql-database)
3620 nil
3621 (list sql-database))
3622 options)))
3623
3624 \f
3625
3626 ;;;###autoload
3627 (defun sql-ms ()
3628 "Run osql by Microsoft as an inferior process.
3629
3630 If buffer `*SQL*' exists but no process is running, make a new process.
3631 If buffer exists and a process is running, just switch to buffer
3632 `*SQL*'.
3633
3634 Interpreter used comes from variable `sql-ms-program'. Login uses the
3635 variables `sql-user', `sql-password', `sql-database', and `sql-server'
3636 as defaults, if set. Additional command line parameters can be stored
3637 in the list `sql-ms-options'.
3638
3639 The buffer is put in SQL interactive mode, giving commands for sending
3640 input. See `sql-interactive-mode'.
3641
3642 To specify a coding system for converting non-ASCII characters
3643 in the input and output to the process, use \\[universal-coding-system-argument]
3644 before \\[sql-ms]. You can also specify this with \\[set-buffer-process-coding-system]
3645 in the SQL buffer, after you start the process.
3646 The default comes from `process-coding-system-alist' and
3647 `default-process-coding-system'.
3648
3649 \(Type \\[describe-mode] in the SQL buffer for a list of commands.)"
3650 (interactive)
3651 (sql-product-interactive 'ms))
3652
3653 (defun sql-comint-ms (product options)
3654 "Create comint buffer and connect to Microsoft SQL Server."
3655 ;; Put all parameters to the program (if defined) in a list and call
3656 ;; make-comint.
3657 (let ((params options))
3658 (if (not (string= "" sql-server))
3659 (setq params (append (list "-S" sql-server) params)))
3660 (if (not (string= "" sql-database))
3661 (setq params (append (list "-d" sql-database) params)))
3662 (if (not (string= "" sql-user))
3663 (setq params (append (list "-U" sql-user) params)))
3664 (if (not (string= "" sql-password))
3665 (setq params (append (list "-P" sql-password) params))
3666 (if (string= "" sql-user)
3667 ;; if neither user nor password is provided, use system
3668 ;; credentials.
3669 (setq params (append (list "-E") params))
3670 ;; If -P is passed to ISQL as the last argument without a
3671 ;; password, it's considered null.
3672 (setq params (append params (list "-P")))))
3673 (sql-comint product params)))
3674
3675 \f
3676
3677 ;;;###autoload
3678 (defun sql-postgres ()
3679 "Run psql by Postgres as an inferior process.
3680
3681 If buffer `*SQL*' exists but no process is running, make a new process.
3682 If buffer exists and a process is running, just switch to buffer
3683 `*SQL*'.
3684
3685 Interpreter used comes from variable `sql-postgres-program'. Login uses
3686 the variables `sql-database' and `sql-server' as default, if set.
3687 Additional command line parameters can be stored in the list
3688 `sql-postgres-options'.
3689
3690 The buffer is put in SQL interactive mode, giving commands for sending
3691 input. See `sql-interactive-mode'.
3692
3693 To specify a coding system for converting non-ASCII characters
3694 in the input and output to the process, use \\[universal-coding-system-argument]
3695 before \\[sql-postgres]. You can also specify this with \\[set-buffer-process-coding-system]
3696 in the SQL buffer, after you start the process.
3697 The default comes from `process-coding-system-alist' and
3698 `default-process-coding-system'. If your output lines end with ^M,
3699 your might try undecided-dos as a coding system. If this doesn't help,
3700 Try to set `comint-output-filter-functions' like this:
3701
3702 \(setq comint-output-filter-functions (append comint-output-filter-functions
3703 '(comint-strip-ctrl-m)))
3704
3705 \(Type \\[describe-mode] in the SQL buffer for a list of commands.)"
3706 (interactive)
3707 (sql-product-interactive 'postgres))
3708
3709 (defun sql-comint-postgres (product options)
3710 "Create comint buffer and connect to Postgres."
3711 ;; username and password are ignored. Mark Stosberg suggest to add
3712 ;; the database at the end. Jason Beegan suggest using --pset and
3713 ;; pager=off instead of \\o|cat. The later was the solution by
3714 ;; Gregor Zych. Jason's suggestion is the default value for
3715 ;; sql-postgres-options.
3716 (let ((params options))
3717 (if (not (string= "" sql-database))
3718 (setq params (append params (list sql-database))))
3719 (if (not (string= "" sql-server))
3720 (setq params (append (list "-h" sql-server) params)))
3721 (if (not (string= "" sql-user))
3722 (setq params (append (list "-U" sql-user) params)))
3723 (sql-comint product params)))
3724
3725 \f
3726
3727 ;;;###autoload
3728 (defun sql-interbase ()
3729 "Run isql by Interbase as an inferior process.
3730
3731 If buffer `*SQL*' exists but no process is running, make a new process.
3732 If buffer exists and a process is running, just switch to buffer
3733 `*SQL*'.
3734
3735 Interpreter used comes from variable `sql-interbase-program'. Login
3736 uses the variables `sql-user', `sql-password', and `sql-database' as
3737 defaults, if set.
3738
3739 The buffer is put in SQL interactive mode, giving commands for sending
3740 input. See `sql-interactive-mode'.
3741
3742 To specify a coding system for converting non-ASCII characters
3743 in the input and output to the process, use \\[universal-coding-system-argument]
3744 before \\[sql-interbase]. You can also specify this with \\[set-buffer-process-coding-system]
3745 in the SQL buffer, after you start the process.
3746 The default comes from `process-coding-system-alist' and
3747 `default-process-coding-system'.
3748
3749 \(Type \\[describe-mode] in the SQL buffer for a list of commands.)"
3750 (interactive)
3751 (sql-product-interactive 'interbase))
3752
3753 (defun sql-comint-interbase (product options)
3754 "Create comint buffer and connect to Interbase."
3755 ;; Put all parameters to the program (if defined) in a list and call
3756 ;; make-comint.
3757 (let ((params options))
3758 (if (not (string= "" sql-user))
3759 (setq params (append (list "-u" sql-user) params)))
3760 (if (not (string= "" sql-password))
3761 (setq params (append (list "-p" sql-password) params)))
3762 (if (not (string= "" sql-database))
3763 (setq params (cons sql-database params))) ; add to the front!
3764 (sql-comint product params)))
3765
3766 \f
3767
3768 ;;;###autoload
3769 (defun sql-db2 ()
3770 "Run db2 by IBM as an inferior process.
3771
3772 If buffer `*SQL*' exists but no process is running, make a new process.
3773 If buffer exists and a process is running, just switch to buffer
3774 `*SQL*'.
3775
3776 Interpreter used comes from variable `sql-db2-program'. There is not
3777 automatic login.
3778
3779 The buffer is put in SQL interactive mode, giving commands for sending
3780 input. See `sql-interactive-mode'.
3781
3782 If you use \\[sql-accumulate-and-indent] to send multiline commands to
3783 db2, newlines will be escaped if necessary. If you don't want that, set
3784 `comint-input-sender' back to `comint-simple-send' by writing an after
3785 advice. See the elisp manual for more information.
3786
3787 To specify a coding system for converting non-ASCII characters
3788 in the input and output to the process, use \\[universal-coding-system-argument]
3789 before \\[sql-db2]. You can also specify this with \\[set-buffer-process-coding-system]
3790 in the SQL buffer, after you start the process.
3791 The default comes from `process-coding-system-alist' and
3792 `default-process-coding-system'.
3793
3794 \(Type \\[describe-mode] in the SQL buffer for a list of commands.)"
3795 (interactive)
3796 (sql-product-interactive 'db2))
3797
3798 (defun sql-comint-db2 (product options)
3799 "Create comint buffer and connect to DB2."
3800 ;; Put all parameters to the program (if defined) in a list and call
3801 ;; make-comint.
3802 (sql-comint product options)
3803 )
3804 ;; ;; Properly escape newlines when DB2 is interactive.
3805 ;; (setq comint-input-sender 'sql-escape-newlines-and-send))
3806
3807 ;;;###autoload
3808 (defun sql-linter ()
3809 "Run inl by RELEX as an inferior process.
3810
3811 If buffer `*SQL*' exists but no process is running, make a new process.
3812 If buffer exists and a process is running, just switch to buffer
3813 `*SQL*'.
3814
3815 Interpreter used comes from variable `sql-linter-program' - usually `inl'.
3816 Login uses the variables `sql-user', `sql-password', `sql-database' and
3817 `sql-server' as defaults, if set. Additional command line parameters
3818 can be stored in the list `sql-linter-options'. Run inl -h to get help on
3819 parameters.
3820
3821 `sql-database' is used to set the LINTER_MBX environment variable for
3822 local connections, `sql-server' refers to the server name from the
3823 `nodetab' file for the network connection (dbc_tcp or friends must run
3824 for this to work). If `sql-password' is an empty string, inl will use
3825 an empty password.
3826
3827 The buffer is put in SQL interactive mode, giving commands for sending
3828 input. See `sql-interactive-mode'.
3829
3830 \(Type \\[describe-mode] in the SQL buffer for a list of commands.)"
3831 (interactive)
3832 (sql-product-interactive 'linter))
3833
3834 (defun sql-comint-linter (product options)
3835 "Create comint buffer and connect to Linter."
3836 ;; Put all parameters to the program (if defined) in a list and call
3837 ;; make-comint.
3838 (let ((params options)
3839 (login nil)
3840 (old-mbx (getenv "LINTER_MBX")))
3841 (if (not (string= "" sql-user))
3842 (setq login (concat sql-user "/" sql-password)))
3843 (setq params (append (list "-u" login) params))
3844 (if (not (string= "" sql-server))
3845 (setq params (append (list "-n" sql-server) params)))
3846 (if (string= "" sql-database)
3847 (setenv "LINTER_MBX" nil)
3848 (setenv "LINTER_MBX" sql-database))
3849 (sql-comint product params)
3850 (setenv "LINTER_MBX" old-mbx)))
3851
3852 \f
3853
3854 (provide 'sql)
3855
3856 ;; arch-tag: 7e1fa1c4-9ca2-402e-87d2-83a5eccb7ac3
3857 ;;; sql.el ends here
3858