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