|
79 | 79 | (require 'ob) |
80 | 80 | (require 'sql) |
81 | 81 |
|
82 | | - |
83 | 82 | (defvar org-babel-sql-session-start-time) |
84 | 83 | (defvar org-sql-session-preamble |
85 | 84 | (list |
@@ -531,137 +530,120 @@ argument mechanism." |
531 | 530 | PARAMS provides the sql connection parameters for a new or |
532 | 531 | existing SESSION. Clear the intermediate buffer from previous |
533 | 532 | output, and set the process filter. Return the comint process |
534 | | -buffer. |
535 | | -
|
536 | | -The buffer naming was shortened from |
537 | | -*[session] engine://user@host/database*, |
538 | | -that clearly identifies the connexion from Emacs, |
539 | | -to *SQL [session]* in order to retrieve a session with its |
540 | | -name alone, the other parameters in the header args beeing |
541 | | -no longer needed while the session stays open." |
542 | | - (let* ((sql-server (cdr (assoc :dbhost params))) |
543 | | - ;; (sql-port (cdr (assoc :port params))) |
544 | | - (sql-database (cdr (assoc :database params))) |
545 | | - (sql-user (cdr (assoc :dbuser params))) |
546 | | - (sql-password (cdr (assoc :dbpassword params))) |
547 | | - (buffer-name (format "%s" (if (string= session "none") "" |
548 | | - (format "[%s]" session)))) |
549 | | - (ob-sql-buffer (format "*SQL: %s*" buffer-name))) |
550 | | - |
551 | | - (if (org-babel-comint-buffer-livep ob-sql-buffer) |
552 | | - (progn ; set again the filter |
553 | | - (set-process-filter (get-buffer-process ob-sql-buffer) |
554 | | - #'org-sql-session-comint-output-filter) |
555 | | - ob-sql-buffer) ; and return the buffer |
556 | | - ;; otherwise initiate a new connection |
557 | | - (save-window-excursion |
558 | | - (setq ob-sql-buffer ; start the client |
559 | | - (org-babel-sql-connect in-engine buffer-name))) |
560 | | - (let ((sql-term-proc (get-buffer-process ob-sql-buffer))) |
561 | | - (unless sql-term-proc |
562 | | - (user-error (format "SQL %s didn't start" in-engine))) |
563 | | - |
564 | | - (with-current-buffer (get-buffer ob-sql-buffer) |
565 | | - (let ((preamble (plist-get org-sql-session-preamble in-engine))) |
566 | | - (when preamble |
567 | | - (process-send-string ob-sql-buffer preamble) |
568 | | - (comint-send-input)))) |
569 | | - (sleep-for 0.1) ; or the result of the preamble will be in the process filter |
570 | | - ;; set the redirection filter |
571 | | - (set-process-filter sql-term-proc |
572 | | - #'org-sql-session-comint-output-filter) |
573 | | - ;; return that buffer |
574 | | - (get-buffer ob-sql-buffer))))) |
575 | | - |
576 | | -(defun org-babel-sql-connect (&optional engine sql-cnx) |
577 | | - "Run ENGINE interpreter as an inferior process, with SQL-CNX as client buffer. |
578 | | -
|
579 | | -Imported from sql.el with a few modification in order |
580 | | -to prompt for authentication only if there's a missing |
581 | | -parameter. Depending on the sql client the password |
582 | | -should also be prompted." |
583 | | - |
584 | | - ;; Get the value of engine that we need |
585 | | - (setq sql-product |
586 | | - (cond |
587 | | - ((assoc engine sql-product-alist) ; Product specified |
588 | | - engine) |
589 | | - (t sql-product))) ; Default to sql-engine |
590 | | - |
591 | | - (when (sql-get-product-feature sql-product :sqli-comint-func) |
592 | | - ;; If no new name specified or new name in buffer name, |
593 | | - ;; try to pop to an active SQL interactive for the same engine |
594 | | - (let (;(buf (sql-find-sqli-buffer sql-product sql-connection)) ; unused yet |
595 | | - (prompt-regexp (sql-get-product-feature engine :prompt-regexp )) |
596 | | - (prompt-cont-regexp (sql-get-product-feature engine :prompt-cont-regexp)) |
597 | | - sqli-buffer |
598 | | - rpt) |
599 | | - |
600 | | - ;; store the regexp used to clear output (prompt1|indicator|prompt2) |
601 | | - (setq org-sql-session-clean-output |
| 533 | +buffer." |
| 534 | + (let* ((buffer-name (format "%s" (if (string= session "none") "" |
| 535 | + (format "[%s]" session)))) |
| 536 | + (ob-sql-buffer (format "*SQL: %s*" buffer-name))) |
| 537 | + |
| 538 | + ;; initiate a new connection |
| 539 | + (when (not (org-babel-comint-buffer-livep ob-sql-buffer)) |
| 540 | + (save-window-excursion |
| 541 | + (setq ob-sql-buffer ; start the client |
| 542 | + (org-babel-sql-connect in-engine buffer-name params))) |
| 543 | + (let ((sql-term-proc (get-buffer-process ob-sql-buffer))) |
| 544 | + (unless sql-term-proc |
| 545 | + (user-error (format "SQL %s didn't start" in-engine))) |
| 546 | + |
| 547 | + (with-current-buffer (get-buffer ob-sql-buffer) |
| 548 | + ;; preamble commands |
| 549 | + (let ((preamble (plist-get org-sql-session-preamble in-engine))) |
| 550 | + (when preamble |
| 551 | + (process-send-string ob-sql-buffer preamble) |
| 552 | + (comint-send-input)))) |
| 553 | + ;; let the preamble execution finish and be filtered |
| 554 | + (sleep-for 0.1))) |
| 555 | + |
| 556 | + ;; set the redirection filter and return the SQL client buffer |
| 557 | + (set-process-filter (get-buffer-process ob-sql-buffer) |
| 558 | + #'org-sql-session-comint-output-filter) |
| 559 | + (get-buffer ob-sql-buffer))) |
| 560 | + |
| 561 | +(defun org-babel-sql-connect (&optional engine sql-cnx params) |
| 562 | + "Run ENGINE interpreter as an inferior process. |
| 563 | +SQL-CNX is the client buffer. This is a variant from sql.el that prompt |
| 564 | +parametrs for authentication only if there's a missing parameter. |
| 565 | +Depending on the sql client the password should also be prompted." |
| 566 | + |
| 567 | + (setq sql-product(cond |
| 568 | + ((assoc engine sql-product-alist) ; Product specified |
| 569 | + engine) |
| 570 | + (t sql-product))) ; or default to sql-engine |
| 571 | + |
| 572 | + (when (sql-get-product-feature sql-product :sqli-comint-func) |
| 573 | + (let (;(buf (sql-find-sqli-buffer sql-product sql-connection)) ; unused yet |
| 574 | + (sql-server (cdr (assoc :dbhost params))) |
| 575 | + ;; (sql-port (cdr (assoc :port params))) ; todo |
| 576 | + (sql-database (cdr (assoc :database params))) |
| 577 | + (sql-user (cdr (assoc :dbuser params))) |
| 578 | + (sql-password (cdr (assoc :dbpassword params))) |
| 579 | + (prompt-regexp (sql-get-product-feature engine :prompt-regexp )) |
| 580 | + (prompt-cont-regexp (sql-get-product-feature engine :prompt-cont-regexp)) |
| 581 | + sqli-buffer |
| 582 | + rpt) |
| 583 | + ;; store the regexp used to clear output (prompt1|indicator|prompt2) |
| 584 | + (setq org-sql-session-clean-output |
602 | 585 | (plist-put org-sql-session-clean-output engine |
603 | 586 | (concat "\\(" prompt-regexp "\\)" |
604 | 587 | "\\|\\(" org-sql-session--batch-terminate "\n\\)" |
605 | 588 | (when prompt-cont-regexp |
606 | 589 | (concat "\\|\\(" prompt-cont-regexp "\\)"))))) |
607 | | - |
608 | | - ;; Get credentials. |
609 | | - ;; either all fields are provided |
610 | | - ;; or there's a specific case were no login is needed |
611 | | - ;; or trigger the prompt |
612 | | - (or (and sql-database sql-user sql-server) |
613 | | - (eq sql-product 'sqlite) ;; sqlite allows in-memory db, w/o login |
614 | | - (apply #'sql-get-login |
615 | | - (sql-get-product-feature engine :sqli-login))) |
616 | | - ;; depending on client, password is forcefully prompted |
617 | | - |
618 | | - ;; The password wallet returns a function |
619 | | - ;; which supplies the password. (untested) |
620 | | - (when (functionp sql-password) |
621 | | - (setq sql-password (funcall sql-password))) |
622 | | - |
623 | | - ;; Erase previous sql-buffer as we'll be looking for it's prompt |
624 | | - ;; to indicate session readyness |
625 | | - (let ((previous-session |
626 | | - (get-buffer (format "*SQL: %s*" sql-cnx)))) |
627 | | - (when previous-session |
628 | | - (with-current-buffer |
629 | | - previous-session (erase-buffer))) |
630 | | - |
631 | | - (setq sqli-buffer |
632 | | - (let ((process-environment (copy-sequence process-environment)) |
633 | | - (variables (plist-get org-sql-environment engine))) |
634 | | - (mapc (lambda (elem) ; environment variables, evaluated here |
635 | | - (setenv (car elem) (eval (cadr elem)))) |
636 | | - variables) |
637 | | - (funcall (sql-get-product-feature engine :sqli-comint-func) |
638 | | - engine |
639 | | - (sql-get-product-feature engine :sqli-options) |
640 | | - (format "SQL: %s" sql-cnx)))) |
641 | | - (setq sql-buffer (buffer-name sqli-buffer)) |
642 | | - |
643 | | - (setq rpt (sql-make-progress-reporter nil "Login")) |
644 | | - (with-current-buffer sql-buffer |
645 | | - (let ((proc (get-buffer-process sqli-buffer)) |
646 | | - (secs org-sql-timeout) |
647 | | - (step 0.2)) |
648 | | - (while (and proc |
649 | | - (memq (process-status proc) '(open run)) |
650 | | - (or (accept-process-output proc step) |
651 | | - (<= 0.0 (setq secs (- secs step)))) |
652 | | - (progn (goto-char (point-max)) |
653 | | - (not (re-search-backward |
654 | | - prompt-regexp 0 t)))) |
655 | | - (sql-progress-reporter-update rpt))) |
656 | | - |
657 | | - ;; no prompt, connexion failed (and process is terminated) |
658 | | - (goto-char (point-max)) |
659 | | - (unless (re-search-backward prompt-regexp 0 t) |
660 | | - (user-error "Connection failed"))) ;is this a _user_ error? |
661 | | - ;;(run-hooks 'sql-login-hook) ; don't |
662 | | - ) |
663 | | - (sql-progress-reporter-done rpt) |
664 | | - (get-buffer sqli-buffer)))) |
| 590 | + ;; Get credentials. |
| 591 | + ;; either all fields are provided |
| 592 | + ;; or there's a specific case were no login is needed |
| 593 | + ;; or trigger the prompt |
| 594 | + (or (and sql-database sql-user sql-server) |
| 595 | + (eq sql-product 'sqlite) ;; sqlite allows in-memory db, w/o login |
| 596 | + (apply #'sql-get-login |
| 597 | + (sql-get-product-feature engine :sqli-login))) |
| 598 | + ;; depending on client, password is forcefully prompted |
| 599 | + |
| 600 | + ;; The password wallet returns a function |
| 601 | + ;; which supplies the password. (untested) |
| 602 | + (when (functionp sql-password) |
| 603 | + (setq sql-password (funcall sql-password))) |
| 604 | + |
| 605 | + ;; Erase previous sql-buffer. |
| 606 | + ;; Will look for it's prompt to indicate session readyness. |
| 607 | + (let ((previous-session |
| 608 | + (get-buffer (format "*SQL: %s*" sql-cnx)))) |
| 609 | + (when previous-session |
| 610 | + (with-current-buffer |
| 611 | + previous-session (erase-buffer))) |
| 612 | + |
| 613 | + (setq sqli-buffer |
| 614 | + (let ((process-environment (copy-sequence process-environment)) |
| 615 | + (variables (plist-get org-sql-environment engine))) |
| 616 | + (mapc (lambda (elem) ; environment variables, evaluated here |
| 617 | + (setenv (car elem) (eval (cadr elem)))) |
| 618 | + variables) |
| 619 | + (funcall (sql-get-product-feature engine :sqli-comint-func) |
| 620 | + engine |
| 621 | + (sql-get-product-feature engine :sqli-options) |
| 622 | + (format "SQL: %s" sql-cnx)))) |
| 623 | + (setq sql-buffer (buffer-name sqli-buffer)) |
| 624 | + |
| 625 | + (setq rpt (sql-make-progress-reporter nil "Login")) |
| 626 | + (with-current-buffer sql-buffer |
| 627 | + (let ((proc (get-buffer-process sqli-buffer)) |
| 628 | + (secs org-sql-timeout) |
| 629 | + (step 0.2)) |
| 630 | + (while (and proc |
| 631 | + (memq (process-status proc) '(open run)) |
| 632 | + (or (accept-process-output proc step) |
| 633 | + (<= 0.0 (setq secs (- secs step)))) |
| 634 | + (progn (goto-char (point-max)) |
| 635 | + (not (re-search-backward |
| 636 | + prompt-regexp 0 t)))) |
| 637 | + (sql-progress-reporter-update rpt))) |
| 638 | + |
| 639 | + ;; no prompt, connexion failed (and process is terminated) |
| 640 | + (goto-char (point-max)) |
| 641 | + (unless (re-search-backward prompt-regexp 0 t) |
| 642 | + (user-error "Connection failed"))) ;is this a _user_ error? |
| 643 | + ;;(run-hooks 'sql-login-hook) ; don't |
| 644 | + ) |
| 645 | + (sql-progress-reporter-done rpt) |
| 646 | + (get-buffer sqli-buffer)))) |
665 | 647 |
|
666 | 648 | (defun org-sql-session-format-query (str in-engine) |
667 | 649 | "Process then send the command STR to the SQL process. |
|
0 commit comments