diff options
Diffstat (limited to 'lisp/progmodes/sql.el')
-rw-r--r-- | lisp/progmodes/sql.el | 236 |
1 files changed, 159 insertions, 77 deletions
diff --git a/lisp/progmodes/sql.el b/lisp/progmodes/sql.el index 13d4178116e..e8a95eccdd2 100644 --- a/lisp/progmodes/sql.el +++ b/lisp/progmodes/sql.el @@ -212,11 +212,11 @@ ;; Michael Mauger <michael@mauger.com> -- improved product support ;; Drew Adams <drew.adams@oracle.com> -- Emacs 20 support ;; Harald Maier <maierh@myself.com> -- sql-send-string -;; Stefan Monnier <monnier@iro.umontreal.ca> -- font-lock corrections; +;; Stefan Monnier <monnier@iro.umontreal.ca> -- font-lock corrections; ;; code polish ;; Paul Sleigh <bat@flurf.net> -- MySQL keyword enhancement ;; Andrew Schein <andrew@andrewschein.com> -- sql-port bug -;; Ian Bjorhovde <idbjorh@dataproxy.com> -- db2 escape newlines +;; Ian Bjorhovde <idbjorh@dataproxy.com> -- db2 escape newlines ;; incorrectly enabled by default ;; Roman Scherer <roman.scherer@nugg.ad> -- Connection documentation ;; Mark Wilkinson <wilkinsonmr@gmail.com> -- file-local variables ignored @@ -282,6 +282,13 @@ file. Since that is a plaintext file, this could be dangerous." :group 'SQL :safe 'numberp) +(defcustom sql-default-directory nil + "Default directory for SQL processes." + :version "25.1" + :type '(choice (const nil) string) + :group 'SQL + :safe 'stringp) + ;; Login parameter type (define-widget 'sql-login-params 'lazy @@ -498,6 +505,18 @@ file. Since that is a plaintext file, this could be dangerous." :prompt-length 5 :syntax-alist ((?@ . "_")) :terminator ("^go" . "go")) + + (vertica + :name "Vertica" + :sqli-program sql-vertica-program + :sqli-options sql-vertica-options + :sqli-login sql-vertica-login-params + :sqli-comint-func sql-comint-vertica + :list-all ("\\d" . "\\dS") + :list-table "\\d %s" + :prompt-regexp "^\\w*=[#>] " + :prompt-length 5 + :prompt-cont-regexp "^\\w*[-(][#>] ") ) "An alist of product specific configuration settings. @@ -1221,7 +1240,9 @@ Based on `comint-mode-map'.") (define-key map (kbd "C-c C-r") 'sql-send-region) (define-key map (kbd "C-c C-s") 'sql-send-string) (define-key map (kbd "C-c C-b") 'sql-send-buffer) + (define-key map (kbd "C-c C-n") 'sql-send-line-and-next) (define-key map (kbd "C-c C-i") 'sql-product-interactive) + (define-key map (kbd "C-c C-z") 'sql-show-sqli-buffer) (define-key map (kbd "C-c C-l a") 'sql-list-all) (define-key map (kbd "C-c C-l t") 'sql-list-table) (define-key map [remap beginning-of-defun] 'sql-beginning-of-statement) @@ -1556,8 +1577,6 @@ to add functions and PL/SQL keywords.") ;; Oracle SQL*Plus Commands ;; Only recognized in they start in column 1 and the ;; abbreviation is followed by a space or the end of line. - - "\\|" (list (concat "^" (sql-regexp-abbrev "rem~ark") "\\(?:\\s-.*\\)?$") 0 'font-lock-comment-face t) @@ -1605,6 +1624,11 @@ to add functions and PL/SQL keywords.") 0 'font-lock-doc-face t) '("&?&\\(?:\\sw\\|\\s_\\)+[.]?" 0 font-lock-preprocessor-face t) + ;; Oracle PL/SQL Attributes (Declare these first to match %TYPE correctly) + (sql-font-lock-keywords-builder 'font-lock-builtin-face '("%" . "\\b") +"bulk_exceptions" "bulk_rowcount" "found" "isopen" "notfound" +"rowcount" "rowtype" "type" +) ;; Oracle Functions (sql-font-lock-keywords-builder 'font-lock-builtin-face nil "abs" "acos" "add_months" "appendchildxml" "ascii" "asciistr" "asin" @@ -1634,7 +1658,7 @@ to add functions and PL/SQL keywords.") "prediction" "prediction_bounds" "prediction_cost" "prediction_details" "prediction_probability" "prediction_set" "presentnnv" "presentv" "previous" "rank" "ratio_to_report" "rawtohex" -"rawtonhex" "ref" "reftohex" "regexp_count" "regexp_instr" +"rawtonhex" "ref" "reftohex" "regexp_count" "regexp_instr" "regexp_like" "regexp_replace" "regexp_substr" "regr_avgx" "regr_avgy" "regr_count" "regr_intercept" "regr_r2" "regr_slope" "regr_sxx" "regr_sxy" "regr_syy" "remainder" "replace" "round" "rowidtochar" "rowidtonchar" @@ -1719,7 +1743,7 @@ to add functions and PL/SQL keywords.") "password_life_time" "password_lock_time" "password_reuse_max" "password_reuse_time" "password_verify_function" "pctfree" "pctincrease" "pctthreshold" "pctused" "pctversion" "percent" -"performance" "permanent" "pfile" "physical" "pipelined" "plan" +"performance" "permanent" "pfile" "physical" "pipelined" "pivot" "plan" "post_transaction" "pragma" "prebuilt" "preserve" "primary" "private" "private_sga" "privileges" "procedure" "profile" "protection" "public" "purge" "query" "quiesce" "quota" "range" "read" "reads" "rebuild" @@ -1742,7 +1766,7 @@ to add functions and PL/SQL keywords.") "temporary" "test" "than" "then" "thread" "through" "time_zone" "timeout" "to" "trace" "transaction" "trigger" "triggers" "truncate" "trust" "type" "types" "unarchived" "under" "under_path" "undo" -"uniform" "union" "unique" "unlimited" "unlock" "unquiesce" +"uniform" "union" "unique" "unlimited" "unlock" "unpivot" "unquiesce" "unrecoverable" "until" "unusable" "unused" "update" "upgrade" "usage" "use" "using" "validate" "validation" "value" "values" "variable" "varray" "version" "view" "wait" "when" "whenever" "where" "with" @@ -1757,12 +1781,6 @@ to add functions and PL/SQL keywords.") "time" "timestamp" "urowid" "varchar2" "with" "year" "zone" ) - ;; Oracle PL/SQL Attributes - (sql-font-lock-keywords-builder 'font-lock-builtin-face '("%" . "\\b") -"bulk_exceptions" "bulk_rowcount" "found" "isopen" "notfound" -"rowcount" "rowtype" "type" -) - ;; Oracle PL/SQL Functions (sql-font-lock-keywords-builder 'font-lock-builtin-face nil "delete" "trim" "extend" "exists" "first" "last" "count" "limit" @@ -3050,7 +3068,7 @@ If you call it from anywhere else, it sets the global copy of (interactive) (let ((default-buffer (sql-find-sqli-buffer))) (if (null default-buffer) - (user-error "There is no suitable SQLi buffer") + (sql-product-interactive) (let ((new-buffer (read-buffer "New SQLi buffer: " default-buffer t))) (if (null (sql-buffer-live-p new-buffer)) (user-error "Buffer %s is not a working SQLi buffer" new-buffer) @@ -3059,21 +3077,20 @@ If you call it from anywhere else, it sets the global copy of (run-hooks 'sql-set-sqli-hook))))))) (defun sql-show-sqli-buffer () - "Show the name of current SQLi buffer. + "Display the current SQLi buffer. -This is the buffer SQL strings are sent to. It is stored in the -variable `sql-buffer'. See `sql-help' on how to create such a buffer." +This is the buffer SQL strings are sent to. +It is stored in the variable `sql-buffer'. +I +See also `sql-help' on how to create such a buffer." (interactive) - (if (or (null sql-buffer) - (null (buffer-live-p (get-buffer sql-buffer)))) - (user-error "%s has no SQLi buffer set" (buffer-name (current-buffer))) - (if (null (get-buffer-process sql-buffer)) - (user-error "Buffer %s has no process" sql-buffer) - (user-error "Current SQLi buffer is %s" sql-buffer)))) + (unless (and sql-buffer (buffer-live-p (get-buffer sql-buffer)) + (get-buffer-process sql-buffer)) + (sql-set-sqli-buffer)) + (display-buffer sql-buffer)) (defun sql-make-alternate-buffer-name () "Return a string that can be used to rename a SQLi buffer. - This is used to set `sql-alternate-buffer-name' within `sql-interactive-mode'. @@ -3323,7 +3340,7 @@ to avoid deleting non-prompt output." (setq oline (replace-match "" nil nil oline) sql-output-newline-count (1- sql-output-newline-count) prompt-found t))) - + ;; If we've found all the expected prompts, stop looking (if (= sql-output-newline-count 0) (setq sql-output-newline-count nil @@ -3403,6 +3420,13 @@ to avoid deleting non-prompt output." (interactive) (sql-send-region (point-min) (point-max))) +(defun sql-send-line-and-next () + "Send the current line to the SQL process and go to the next line." + (interactive) + (sql-send-region (line-beginning-position 1) (line-beginning-position 2)) + (beginning-of-line 2) + (while (forward-comment 1))) ; skip all comments and whitespace + (defun sql-send-magic-terminator (buf str terminator) "Send TERMINATOR to buffer BUF if its not present in STR." (let (comint-input-sender-no-newline pat term) @@ -3480,45 +3504,51 @@ list of SQLi command strings." (message "Executing SQL command...done")))) (defun sql-redirect-one (sqlbuf command outbuf save-prior) - (with-current-buffer sqlbuf - (let ((buf (get-buffer-create (or outbuf " *SQL-Redirect*"))) - (proc (get-buffer-process (current-buffer))) - (comint-prompt-regexp (sql-get-product-feature sql-product - :prompt-regexp)) - (start nil)) - (with-current-buffer buf - (setq-local view-no-disable-on-exit t) - (read-only-mode -1) - (unless save-prior - (erase-buffer)) - (goto-char (point-max)) - (unless (zerop (buffer-size)) - (insert "\n")) - (setq start (point))) - - (when sql-debug-redirect - (message ">>SQL> %S" command)) - - ;; Run the command - (comint-redirect-send-command-to-process command buf proc nil t) - (while (null comint-redirect-completed) - (accept-process-output nil 1)) - - ;; Clean up the output results - (with-current-buffer buf - ;; Remove trailing whitespace - (goto-char (point-max)) - (when (looking-back "[ \t\f\n\r]*" start) - (delete-region (match-beginning 0) (match-end 0))) - ;; Remove echo if there was one - (goto-char start) - (when (looking-at (concat "^" (regexp-quote command) "[\\n]")) - (delete-region (match-beginning 0) (match-end 0))) - ;; Remove Ctrl-Ms - (goto-char start) - (while (re-search-forward "\r+$" nil t) - (replace-match "" t t)) - (goto-char start))))) + (when command + (with-current-buffer sqlbuf + (let ((buf (get-buffer-create (or outbuf " *SQL-Redirect*"))) + (proc (get-buffer-process (current-buffer))) + (comint-prompt-regexp (sql-get-product-feature sql-product + :prompt-regexp)) + (start nil)) + (with-current-buffer buf + (setq-local view-no-disable-on-exit t) + (read-only-mode -1) + (unless save-prior + (erase-buffer)) + (goto-char (point-max)) + (unless (zerop (buffer-size)) + (insert "\n")) + (setq start (point))) + + (when sql-debug-redirect + (message ">>SQL> %S" command)) + + ;; Run the command + (let ((inhibit-quit t) + comint-preoutput-filter-functions) + (with-local-quit + (comint-redirect-send-command-to-process command buf proc nil t) + (while (or quit-flag (null comint-redirect-completed)) + (accept-process-output nil 1))) + + (if quit-flag + (comint-redirect-cleanup) + ;; Clean up the output results + (with-current-buffer buf + ;; Remove trailing whitespace + (goto-char (point-max)) + (when (looking-back "[ \t\f\n\r]*" start) + (delete-region (match-beginning 0) (match-end 0))) + ;; Remove echo if there was one + (goto-char start) + (when (looking-at (concat "^" (regexp-quote command) "[\\n]")) + (delete-region (match-beginning 0) (match-end 0))) + ;; Remove Ctrl-Ms + (goto-char start) + (while (re-search-forward "\r+$" nil t) + (replace-match "" t t)) + (goto-char start)))))))) (defun sql-redirect-value (sqlbuf command regexp &optional regexp-groups) "Execute the SQL command and return part of result. @@ -3589,7 +3619,7 @@ buffer is popped into a view window." (apply c sqlbuf outbuf enhanced arg nil)) (t (error "Unknown sql-execute item %s" c)))) (if (consp command) command (cons command nil))) - + (setq outbuf (get-buffer outbuf)) (if (zerop (buffer-size outbuf)) (kill-buffer outbuf) @@ -3597,7 +3627,11 @@ buffer is popped into a view window." (get-lru-window)))) (with-current-buffer outbuf (set-buffer-modified-p nil) - (read-only-mode +1)) + (setq-local revert-buffer-function + (lambda (_ignore-auto _noconfirm) + (sql-execute sqlbuf (buffer-name outbuf) + command enhanced arg))) + (special-mode)) (pop-to-buffer outbuf) (when one-win (shrink-window-if-larger-than-buffer))))) @@ -3755,7 +3789,9 @@ must tell Emacs. Here's how to do that in your init file: \(add-hook 'sql-mode-hook (lambda () (modify-syntax-entry ?\\\\ \".\" sql-mode-syntax-table)))" + :group 'SQL :abbrev-table sql-mode-abbrev-table + (if sql-mode-menu (easy-menu-add sql-mode-menu)); XEmacs @@ -3786,6 +3822,7 @@ must tell Emacs. Here's how to do that in your init file: ;;; SQL interactive mode (put 'sql-interactive-mode 'mode-class 'special) +(put 'sql-interactive-mode 'custom-mode-group 'SQL) (defun sql-interactive-mode () "Major mode to use a SQL interpreter interactively. @@ -3928,11 +3965,10 @@ you entered, right above the output it created. ;; People wanting a different history file for each ;; buffer/process/client/whatever can change separator and file-name ;; on the sql-interactive-mode-hook. - (setq-local comint-input-ring-separator sql-input-ring-separator) - (setq comint-input-ring-file-name sql-input-ring-file-name) - ;; Calling the hook before calling comint-read-input-ring allows users - ;; to set comint-input-ring-file-name in sql-interactive-mode-hook. - (comint-read-input-ring t)) + (let + ((comint-input-ring-separator sql-input-ring-separator) + (comint-input-ring-file-name sql-input-ring-file-name)) + (comint-read-input-ring t))) (defun sql-stop (process event) "Called when the SQL process is stopped. @@ -3942,11 +3978,15 @@ Writes the input history to a history file using This function is a sentinel watching the SQL interpreter process. Sentinels will always get the two parameters PROCESS and EVENT." - (comint-write-input-ring) - (if (and (eq (current-buffer) sql-buffer) - (not buffer-read-only)) - (insert (format "\nProcess %s %s\n" process event)) - (message "Process %s %s" process event))) + (with-current-buffer (process-buffer process) + (let + ((comint-input-ring-separator sql-input-ring-separator) + (comint-input-ring-file-name sql-input-ring-file-name)) + (comint-write-input-ring)) + + (if (not buffer-read-only) + (insert (format "\nProcess %s %s\n" process event)) + (message "Process %s %s" process event)))) @@ -4164,7 +4204,9 @@ the call to \\[sql-product-interactive] with (sql-password (default-value 'sql-password)) (sql-server (default-value 'sql-server)) (sql-database (default-value 'sql-database)) - (sql-port (default-value 'sql-port))) + (sql-port (default-value 'sql-port)) + (default-directory (or sql-default-directory + default-directory))) (funcall (sql-get-product-feature product :sqli-comint-func) product (sql-get-product-feature product :sqli-options))) @@ -5039,6 +5081,46 @@ buffer. +(defcustom sql-vertica-program "vsql" + "Command to start the Vertica client." + :version "25.1" + :type 'file + :group 'SQL) + +(defcustom sql-vertica-options '("-P" "pager=off") + "List of additional options for `sql-vertica-program'. +The default value disables the internal pager." + :version "25.1" + :type '(repeat string) + :group 'SQL) + +(defcustom sql-vertica-login-params '(user password database server) + "List of login parameters needed to connect to Vertica." + :version "25.1" + :type 'sql-login-params + :group 'SQL) + +(defun sql-comint-vertica (product options) + "Create comint buffer and connect to Vertica." + (sql-comint product + (nconc + (and (not (string= "" sql-server)) + (list "-h" sql-server)) + (and (not (string= "" sql-database)) + (list "-d" sql-database)) + (and (not (string= "" sql-password)) + (list "-w" sql-password)) + (and (not (string= "" sql-user)) + (list "-U" sql-user)) + options))) + +;;;###autoload +(defun sql-vertica (&optional buffer) + "Run vsql as an inferior process." + (interactive "P") + (sql-product-interactive 'vertica buffer)) + + (provide 'sql) ;;; sql.el ends here |