From b23f21866ebd485ba8a3df536131deb4f6fe8f73 Mon Sep 17 00:00:00 2001 From: Phil Estival Date: Sun, 19 Jan 2025 09:32:29 +0100 Subject: [PATCH 27/27] ob-sql: connect a session with `sql-product-interactive' * lisp/ob-sql.el: removes the variant of `sql-product-interactive' and connects with `sql-product-interactive' patched with 'no-prompt' in signature. Provides environment variables to SQL on comint Provides environment variables to comit specific for each SQL client as a list of cons whose car is the name of the variable and the cdr an expression. These variables are stored with (sql-set-product-feature product :sql-environment). --- lisp/ob-sql.el | 122 ++++++++++++------------------------------------- 1 file changed, 28 insertions(+), 94 deletions(-) diff --git a/lisp/ob-sql.el b/lisp/ob-sql.el index 83d292ac8..845c59c60 100644 --- a/lisp/ob-sql.el +++ b/lisp/ob-sql.el @@ -553,18 +553,31 @@ buffer." "\\|\\(" org-sql-session--batch-terminate "\n\\)" (when prompt-cont-regexp (concat "\\|\\(" prompt-cont-regexp "\\)")))))) - (save-window-excursion - (setq ob-sql-buffer ; start the client - (org-babel-sql-connect in-engine buffer-name params))) - (let ((sql-term-proc (get-buffer-process ob-sql-buffer))) - (unless sql-term-proc - (user-error (format "SQL %s didn't start" in-engine))) - - (with-current-buffer (get-buffer ob-sql-buffer) - ;; preamble commands - (let ((preamble (plist-get org-sql-session-preamble in-engine))) - (when preamble - (process-send-string ob-sql-buffer preamble) - (comint-send-input)))) - ;; let the preamble execution finish and be filtered - (sleep-for 0.1))) + + (let ((sql-server (cdr (assoc :dbhost params))) + ;; (sql-port (cdr (assoc :port params))) ; todo + (sql-database (cdr (assoc :database params))) + (sql-user (cdr (assoc :dbuser params))) + (sql-password (cdr (assoc :dbpassword params)))) + + ;; provides environment expressions to the comint service + (let ((process-environment (copy-sequence process-environment)) + (variables (sql-get-product-feature in-engine :sql-environment))) + (mapc (lambda (elem) ; evaluate environment expressions + (setenv (car elem) (eval (cadr elem)))) + variables) + (save-window-excursion + (sql-product-interactive in-engine buffer-name t))) + + (let ((sql-term-proc (get-buffer-process ob-sql-buffer))) + (unless sql-term-proc + (user-error (format "SQL %s didn't start" in-engine))) + + (with-current-buffer (get-buffer ob-sql-buffer) + ;; preamble commands + (let ((preamble (plist-get org-sql-session-preamble in-engine))) + (when preamble + (process-send-string ob-sql-buffer preamble) + (comint-send-input)))) + ;; let the preamble execution finish and be filtered + (sleep-for 0.1)))) ;; set the redirection filter and return the SQL client buffer (set-process-filter (get-buffer-process ob-sql-buffer) #'org-sql-session-comint-output-filter) (get-buffer ob-sql-buffer))) -(defun org-babel-sql-connect (&optional engine sql-cnx params) - "Run ENGINE interpreter as an inferior process. -SQL-CNX is the client buffer. This is a variant from sql.el that prompt -parametrs for authentication only if there's a missing parameter. -Depending on the sql client the password should also be prompted." - - (setq sql-product(cond - ((assoc engine sql-product-alist) ; Product specified - engine) - (t sql-product))) ; or default to sql-engine - - (when (sql-get-product-feature sql-product :sqli-comint-func) - (let (;(buf (sql-find-sqli-buffer sql-product sql-connection)) ; unused yet - (sql-server (cdr (assoc :dbhost params))) - ;; (sql-port (cdr (assoc :port params))) ; todo - (sql-database (cdr (assoc :database params))) - (sql-user (cdr (assoc :dbuser params))) - (sql-password (cdr (assoc :dbpassword params))) - (prompt-regexp (sql-get-product-feature engine :prompt-regexp )) - sqli-buffer - rpt) - ;; Get credentials. - ;; either all fields are provided - ;; or there's a specific case were no login is needed - ;; or trigger the prompt - (or (and sql-database sql-user sql-server) - (eq sql-product 'sqlite) ;; sqlite allows in-memory db, w/o login - (apply #'sql-get-login - (sql-get-product-feature engine :sqli-login))) - ;; depending on client, password is forcefully prompted - - ;; The password wallet returns a function - ;; which supplies the password. (untested) - (when (functionp sql-password) - (setq sql-password (funcall sql-password))) - - ;; Erase previous sql-buffer. - ;; Will look for it's prompt to indicate session readyness. - (let ((previous-session - (get-buffer (format "*SQL: %s*" sql-cnx)))) - (when previous-session - (with-current-buffer - previous-session (erase-buffer))) - - (setq sqli-buffer - (let ((process-environment (copy-sequence process-environment)) - (variables (plist-get org-sql-environment engine))) - (mapc (lambda (elem) ; environment variables, evaluated here - (setenv (car elem) (eval (cadr elem)))) - variables) - (funcall (sql-get-product-feature engine :sqli-comint-func) - engine - (sql-get-product-feature engine :sqli-options) - (format "SQL: %s" sql-cnx)))) - (setq sql-buffer (buffer-name sqli-buffer)) - - (setq rpt (sql-make-progress-reporter nil "Login")) - (with-current-buffer sql-buffer - (let ((proc (get-buffer-process sqli-buffer)) - (secs org-sql-timeout) - (step 0.2)) - (while (and proc - (memq (process-status proc) '(open run)) - (or (accept-process-output proc step) - (<= 0.0 (setq secs (- secs step)))) - (progn (goto-char (point-max)) - (not (re-search-backward - prompt-regexp 0 t)))) - (sql-progress-reporter-update rpt))) - - ;; no prompt, connexion failed (and process is terminated) - (goto-char (point-max)) - (unless (re-search-backward prompt-regexp 0 t) - (user-error "Connection failed"))) ;is this a _user_ error? - ;;(run-hooks 'sql-login-hook) ; don't - ) - (sql-progress-reporter-done rpt) - (get-buffer sqli-buffer)))) - (defun org-sql-session-format-query (str in-engine) "Process then send the command STR to the SQL process. Provide IN-ENGINE to retrieve product features. -- 2.39.5