From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mp2 ([2001:41d0:2:4a6f::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by ms11 with LMTPS id EPf/KoTRHmC1YgAA0tVLHw (envelope-from ) for ; Sat, 06 Feb 2021 17:27:32 +0000 Received: from aspmx1.migadu.com ([2001:41d0:2:4a6f::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by mp2 with LMTPS id kPi5JoTRHmCyOAAAB5/wlQ (envelope-from ) for ; Sat, 06 Feb 2021 17:27:32 +0000 Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by aspmx1.migadu.com (Postfix) with ESMTPS id D8A54940275 for ; Sat, 6 Feb 2021 17:27:31 +0000 (UTC) Received: from localhost ([::1]:47378 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1l8RMo-0003ir-9i for larch@yhetil.org; Sat, 06 Feb 2021 12:27:30 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:46140) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1l7YsD-0000Cj-3C for emacs-orgmode@gnu.org; Thu, 04 Feb 2021 02:16:17 -0500 Received: from mail-lf1-f45.google.com ([209.85.167.45]:37742) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1l7Ys6-0003Zr-15 for emacs-orgmode@gnu.org; Thu, 04 Feb 2021 02:16:16 -0500 Received: by mail-lf1-f45.google.com with SMTP id i187so3036972lfd.4 for ; Wed, 03 Feb 2021 23:16:08 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:from:date:message-id:subject:to; bh=SoXiwzAwpUrf8n7LdTJmzmXfrC1yRhkMEc+xqRDmcjE=; b=ciV4+mxFb4sadyUh8agWJZ0Me3zM9V04pYBDgpfcfI6ozhfxTaXZmw/6kZVrsoAZhG ZsmdpX06vl/OFEugWO4eBTVJy15+t3QA7PsXAWkKSR1ajGh20uzhNXUtmtCqMTdlfV82 VLubwX+AiJy2DfY2jb8Gv3gfxe+HKwHdffGhVV4ApagNzBWTj4G7BZJZ43f2HML5bQ/j Q1WIcvZTcbdj/Sa/5/FlhfdwSIACEEgMwUHQrQIsU7wo+sSabIvK3zk85oDQ3yTCK117 zA18+qG2RaRXZAefI+2fCggA02t05tUCVbv7RB3FYmR2pOc5UG0DonH/0B5OUrjB9SWF ZNbw== X-Gm-Message-State: AOAM530/Pdd0fRyuuI66JmryO/puvQPxpv0R9zkuqJfRrbBGLDMeKOM1 DpXiHv0Ee5tKXN7BdQ5vqYS8j54DFHoMEbhUP27VIccT00ybag== X-Google-Smtp-Source: ABdhPJwyyBbnSaYgMaB3+ekFIsc1I27/lszoBagXdvQXevMf7MA5BgQHW7Hfzz4LQJSIZ+5Qg5O73DDbbvZ+KscNM+E= X-Received: by 2002:ac2:5922:: with SMTP id v2mr4003416lfi.394.1612422967200; Wed, 03 Feb 2021 23:16:07 -0800 (PST) MIME-Version: 1.0 From: Robin Campbell Joy Date: Thu, 4 Feb 2021 08:15:56 +0100 Message-ID: Subject: [PATCH] ob-sql.el: Add support for SAP HANA To: emacs-orgmode@gnu.org Content-Type: multipart/alternative; boundary="00000000000030227905ba7d7a8a" Received-SPF: none client-ip=209.85.167.45; envelope-from=rcj@robinjoy.net; helo=mail-lf1-f45.google.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, HTML_MESSAGE=0.001, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=-0.001, SPF_HELO_NONE=0.001, SPF_NONE=0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-Mailman-Approved-At: Sat, 06 Feb 2021 12:25:40 -0500 X-BeenThere: emacs-orgmode@gnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: "General discussions about Org-mode." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-orgmode-bounces+larch=yhetil.org@gnu.org Sender: "Emacs-orgmode" X-Migadu-Flow: FLOW_IN X-Migadu-Spam-Score: -1.36 Authentication-Results: aspmx1.migadu.com; dkim=none; dmarc=none; spf=pass (aspmx1.migadu.com: domain of emacs-orgmode-bounces@gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=emacs-orgmode-bounces@gnu.org X-Migadu-Queue-Id: D8A54940275 X-Spam-Score: -1.36 X-Migadu-Scanner: scn0.migadu.com X-TUID: FIjLk7FrxR9u --00000000000030227905ba7d7a8a Content-Type: text/plain; charset="UTF-8" * lisp/ob-sql.el (org-babel-execute:sql, org-babel-sql-dbstring-saphana): Add basic support for SAP HANA to SQL blocks * testing/lisp/test-ob-sql.el: Basic tests for generated db connection string This change adds basic support for SAP HANA to SQL blocks by specifying saphana as :engine. It also adds a new header arg `dbinstance' in order to specify the SAP HANA instance to connect to. Signed-off-by: Robin Campbell Joy --- lisp/ob-sql.el | 25 ++- testing/lisp/test-ob-sql.el | 382 ++++++++++++++++++++++++++++++++++++ 2 files changed, 406 insertions(+), 1 deletion(-) create mode 100644 testing/lisp/test-ob-sql.el diff --git a/lisp/ob-sql.el b/lisp/ob-sql.el index 902194ae8..5398c85aa 100644 --- a/lisp/ob-sql.el +++ b/lisp/ob-sql.el @@ -40,6 +40,7 @@ ;; - dbuser ;; - dbpassword ;; - dbconnection (to reference connections in sql-connection-alist) +;; - dbinstance ;; - database ;; - colnames (default, nil, means "yes") ;; - result-params @@ -58,6 +59,7 @@ ;; - postgresql (postgres) ;; - oracle ;; - vertica +;; - saphana ;; ;; TODO: ;; @@ -85,6 +87,7 @@ (dbport . :any) (dbuser . :any) (dbpassword . :any) + (dbinstance . :any) (database . :any)) "SQL-specific header arguments.") @@ -174,6 +177,18 @@ SQL Server on Windows and Linux platform." (when database (format "-d %s" database)))) " ")) +(defun org-babel-sql-dbstring-saphana (host port instance user password database) + "Make SAP HANA command line args for database connection. Pass nil to omit that arg." + (mapconcat #'identity + (delq nil + (list (when (and host port) (format "-n %s:%s" host port)) + (when (and host (not port)) (format "-n %s" host)) + (when instance (format "-i %d" instance)) + (when user (format "-u %s" user)) + (when password (format "-p %s" (shell-quote-argument password))) + (when database (format "-d %s" database)))) + " ")) + (defun org-babel-sql-convert-standard-filename (file) "Convert FILE to OS standard file name. If in Cygwin environment, uses Cygwin specific function to @@ -197,6 +212,7 @@ database connections." (:dbport . sql-port) (:dbuser . sql-user) (:dbpassword . sql-password) + (:dbinstance . sql-dbinstance) (:database . sql-database))) (mapped-name (cdr (assq name name-mapping)))) (cadr (assq mapped-name @@ -212,6 +228,7 @@ This function is called by `org-babel-execute-src-block'." (dbport (org-babel-find-db-connection-param params :dbport)) (dbuser (org-babel-find-db-connection-param params :dbuser)) (dbpassword (org-babel-find-db-connection-param params :dbpassword)) + (dbinstance (org-babel-find-db-connection-param params :dbinstance)) (database (org-babel-find-db-connection-param params :database)) (engine (cdr (assq :engine params))) (colnames-p (not (equal "no" (cdr (assq :colnames params))))) @@ -276,6 +293,12 @@ footer=off -F \"\t\" %s -f %s -o %s %s" dbhost dbport dbuser dbpassword database) (org-babel-process-file-name in-file) (org-babel-process-file-name out-file))) + (saphana (format "hdbsql %s -I %s -o %s %s" + (org-babel-sql-dbstring-saphana + dbhost dbport dbinstance dbuser dbpassword database) + (org-babel-process-file-name in-file) + (org-babel-process-file-name out-file) + (or cmdline ""))) (t (user-error "No support for the %s SQL engine" engine))))) (with-temp-file in-file (insert @@ -309,7 +332,7 @@ SET COLSEP '|' (progn (insert-file-contents-literally out-file) (buffer-string))) (with-temp-buffer (cond - ((memq (intern engine) '(dbi mysql postgresql postgres sqsh vertica)) + ((memq (intern engine) '(dbi mysql postgresql postgres saphana sqsh vertica)) ;; Add header row delimiter after column-names header in first line (cond (colnames-p diff --git a/testing/lisp/test-ob-sql.el b/testing/lisp/test-ob-sql.el new file mode 100644 index 000000000..51edd2309 --- /dev/null +++ b/testing/lisp/test-ob-sql.el @@ -0,0 +1,382 @@ +;;; test-ob-sql.el --- tests for ob-sql.el + +;; Copyright (C) 2021 Robin Joy + +;; Author: Robin Joy +;; Keywords: lisp + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . + +;;; Code: + +(require 'org-test) +(require 'ob-sql) +(unless (featurep 'ob-sql) + (signal 'missing-test-dependency "Support for sql code blocks")) + +(defmacro ob-sql/command (&rest body) + "Execute body and return the command that would have been executed." + `(cl-letf (((symbol-function 'org-babel-eval) + (lambda (command &rest _) (throw 'sql-command command)))) + (catch 'sql-command + ,@body))) + +(defmacro ob-sql/command-should-contain (regexp sql-block) + "Check that REGEXP is contained in the command executed when evaluating SQL-BLOCK." + `(let ((regexps ,(if (listp regexp) regexp `(list ,regexp))) + (command (ob-sql/command (org-test-with-temp-text + ,sql-block + (org-babel-next-src-block) + (org-babel-execute-src-block))))) + (dolist (regexp regexps) + (should (string-match-p regexp command))))) + +(defmacro ob-sql/command-should-not-contain (regexp sql-block) + "Check that REGEXP is not contained in the command executed when evaluating SQL-BLOCK." + `(let ((command (ob-sql/command + (org-test-with-temp-text + ,sql-block + (org-babel-next-src-block) + (org-babel-execute-src-block))))) + (should-not (string-match-p ,regexp command)))) + +;;; dbish +(ert-deftest ob-sql/engine-dbi-uses-dbish () + (ob-sql/command-should-contain "^dbish " " +#+begin_src sql :engine dbi + select * from dummy; +#+end_src")) + +(ert-deftest ob-sql/engine-dbish-uses-batch-mode () + (ob-sql/command-should-contain " --batch " " +#+begin_src sql :engine dbi :dbuser dummy + select * from dummy; +#+end_src")) + +(ert-deftest ob-sql/engine-dbish-can-pass-additional-cmdline-params () + (ob-sql/command-should-contain " cmdlineparams " " +#+begin_src sql :engine dbi :dbpassword dummy :cmdline cmdlineparams + select * from dummy; +#+end_src")) + +;;; monetdb +(ert-deftest ob-sql/engine-monetdb-uses-mclient () + (ob-sql/command-should-contain "^mclient " " +#+begin_src sql :engine monetdb + select * from dummy; +#+end_src")) + +(ert-deftest ob-sql/engine-monetdb-outputs-values-tab-separated () + (ob-sql/command-should-contain " -f tab " " +#+begin_src sql :engine monetdb + select * from dummy; +#+end_src")) + +(ert-deftest ob-sql/engine-monetdb-can-pass-additional-cmdline-params () + (ob-sql/command-should-contain " cmdlineparams " " +#+begin_src sql :engine monetdb :dbpassword dummy :cmdline cmdlineparams + select * from dummy; +#+end_src")) + +;;; mssql +(ert-deftest ob-sql/engine-mssql-uses-sqlcmd () + (ob-sql/command-should-contain "^sqlcmd " " +#+begin_src sql :engine mssql + select * from dummy; +#+end_src")) + +(ert-deftest ob-sql/engine-mssql-outputs-values-tab-separated () + (ob-sql/command-should-contain " -s \"\t\" " " +#+begin_src sql :engine mssql + select * from dummy; +#+end_src")) + +(ert-deftest ob-sql/engine-mssql-can-pass-additional-cmdline-params () + (ob-sql/command-should-contain " cmdlineparams " " +#+begin_src sql :engine mssql :dbpassword dummy :cmdline cmdlineparams + select * from dummy; +#+end_src")) + +(ert-deftest ob-sql/engine-mssql-passes-user-if-provided () + (ob-sql/command-should-contain " -U \"dummy\" " " +#+begin_src sql :engine mssql :dbuser dummy + select * from dummy; +#+end_src")) + +(ert-deftest ob-sql/engine-mssql-passes-password-if-provided () + (ob-sql/command-should-contain " -P \"dummy\" " " +#+begin_src sql :engine mssql :dbpassword dummy + select * from dummy; +#+end_src")) + +(ert-deftest ob-sql/engine-mssql-passes-dbhost-if-provided () + (ob-sql/command-should-contain " -S \"localhost\" " " +#+begin_src sql :engine mssql :dbhost localhost + select * from dummy; +#+end_src")) + +(ert-deftest ob-sql/engine-mssql-passes-database-if-provided () + (ob-sql/command-should-contain " -d \"R01\" " " +#+begin_src sql :engine mssql :database R01 + select * from dummy; +#+end_src")) + +(ert-deftest ob-sql/engine-mssql-passes-all-parameter-provided () + (ob-sql/command-should-contain '(" -d \"R01\" " " -S \"localhost\" " " -P \"pwd\" " " -U \"usr\" ") " +#+begin_src sql :engine mssql :database R01 :dbhost localhost :dbport 30101 :dbinstance 1 :dbuser usr :dbpassword pwd + select * from dummy; +#+end_src")) + +;;; MySQL +(ert-deftest ob-sql/engine-mysql-uses-mysql () + (ob-sql/command-should-contain "^mysql " " +#+begin_src sql :engine mysql + select * from dummy; +#+end_src")) + +(ert-deftest ob-sql/engine-mysql-passes-user-if-provided () + (ob-sql/command-should-contain " -udummy " " +#+begin_src sql :engine mysql :dbuser dummy + select * from dummy; +#+end_src")) + +(ert-deftest ob-sql/engine-mysql-passes-password-if-provided () + (ob-sql/command-should-contain " -pdummy " " +#+begin_src sql :engine mysql :dbpassword dummy + select * from dummy; +#+end_src")) + +(ert-deftest ob-sql/engine-mysql-passes-dbhost-if-provided () + (ob-sql/command-should-contain " -hlocalhost " " +#+begin_src sql :engine mysql :dbhost localhost + select * from dummy; +#+end_src")) + +(ert-deftest ob-sql/engine-mysql-passes-host-if-provided () + (ob-sql/command-should-contain " -P30101 " " +#+begin_src sql :engine mysql :dbport 30101 + select * from dummy; +#+end_src")) + +(ert-deftest ob-sql/engine-mysql-passes-database-if-provided () + (ob-sql/command-should-contain " -dR01 " " +#+begin_src sql :engine mysql :database R01 + select * from dummy; +#+end_src")) + +(ert-deftest ob-sql/engine-mysql-passes-all-parameter-provided () + (ob-sql/command-should-contain '(" -dR01 " " -hlocalhost " " -P30101 " " -ppwd " " -uusr ") " +#+begin_src sql :engine mysql :database R01 :dbhost localhost :dbport 30101 :dbinstance 1 :dbuser usr :dbpassword pwd + select * from dummy; +#+end_src")) + +;;; oracle +(ert-deftest ob-sql/engine-oracle-uses-sqlplus () + (ob-sql/command-should-contain "^sqlplus " " +#+begin_src sql :engine oracle :dbuser dummy :dbpassword dummy :database dummy + select * from dummy; +#+end_src")) + +(ert-deftest ob-sql/engine-oracle-passes-user-pwd-database-host-port-if-provided () + (ob-sql/command-should-contain " dummy/dummypwd@localhost:12345/R01 " " +#+begin_src sql :engine oracle :dbuser dummy :dbpassword dummypwd :dbhost localhost :database R01 :dbport 12345 + select * from dummy; +#+end_src")) + +(ert-deftest ob-sql/engine-oracle-passes-user-pwd-database-if-no-host-port-provided () + (ob-sql/command-should-contain " dummy/dummypwd@R01 " " +#+begin_src sql :engine oracle :dbuser dummy :dbpassword dummypwd :database R01 + select * from dummy; +#+end_src")) + +;;; postgresql +(ert-deftest ob-sql/engine-postgresql-uses-psql () + (ob-sql/command-should-contain "^psql " " +#+begin_src sql :engine postgresql + select * from dummy; +#+end_src")) + +(ert-deftest ob-sql/engine-postgresql-passes-password-if-provided () + (ob-sql/command-should-contain "^PGPASSWORD=dummy " " +#+begin_src sql :engine postgresql :dbpassword dummy + select * from dummy; +#+end_src")) + +(ert-deftest ob-sql/engine-postgresql-stop-on-error () + (ob-sql/command-should-contain " --set=\"ON_ERROR_STOP=1\" " " +#+begin_src sql :engine postgresql + select * from dummy; +#+end_src")) + +(ert-deftest ob-sql/engine-postgresql-does-not-output-column-names-if-requested () + (ob-sql/command-should-contain " -t " " +#+begin_src sql :engine postgresql :colnames no + select * from dummy; +#+end_src")) + +(ert-deftest ob-sql/engine-postgresql-outputs-column-names-by-default () + (ob-sql/command-should-not-contain " -t " " +#+begin_src sql :engine postgresql + select * from dummy; +#+end_src")) + +(ert-deftest ob-sql/engine-postgresql-can-pass-additional-cmdline-params () + (ob-sql/command-should-contain " cmdlineparams$" " +#+begin_src sql :engine postgresql :dbpassword dummy :cmdline cmdlineparams + select * from dummy; +#+end_src")) + +;;; SAP HANA +(ert-deftest ob-sql/engine-saphana-uses-hdbsql () + (ob-sql/command-should-contain "^hdbsql " " +#+begin_src sql :engine saphana + select * from dummy; +#+end_src")) + +(ert-deftest ob-sql/engine-saphana-passes-user-if-provided () + (ob-sql/command-should-contain " -u dummy " " +#+begin_src sql :engine saphana :dbuser dummy + select * from dummy; +#+end_src")) + +(ert-deftest ob-sql/engine-saphana-passes-password-if-provided () + (ob-sql/command-should-contain " -p dummy " " +#+begin_src sql :engine saphana :dbpassword dummy + select * from dummy; +#+end_src")) + +(ert-deftest ob-sql/engine-saphana-passes-dbinstance-if-provided () + (ob-sql/command-should-contain " -i 1 " " +#+begin_src sql :engine saphana :dbinstance 1 + select * from dummy; +#+end_src")) + +(ert-deftest ob-sql/engine-saphana-passes-dbhost-if-provided () + (ob-sql/command-should-contain " -n localhost " " +#+begin_src sql :engine saphana :dbhost localhost + select * from dummy; +#+end_src")) + +(ert-deftest ob-sql/engine-saphana-passes-dbhost-and-dbport-if-provided () + (ob-sql/command-should-contain " -n localhost:30101 " " +#+begin_src sql :engine saphana :dbhost localhost :dbport 30101 + select * from dummy; +#+end_src")) + +(ert-deftest ob-sql/engine-saphana-does-not-pass-host-port-if-only-port-provided () + (ob-sql/command-should-not-contain " -n" " +#+begin_src sql :engine saphana :dbport 30101 + select * from dummy; +#+end_src")) + +(ert-deftest ob-sql/engine-saphana-passes-database-if-provided () + (ob-sql/command-should-contain " -d R01 " " +#+begin_src sql :engine saphana :database R01 + select * from dummy; +#+end_src")) + +(ert-deftest ob-sql/engine-saphana-passes-all-parameter-provided () + (ob-sql/command-should-contain '(" -d R01 " " -n localhost:30101 " " -i 1 " " -p pwd " " -u usr") " +#+begin_src sql :engine saphana :database R01 :dbhost localhost :dbport 30101 :dbinstance 1 :dbuser usr :dbpassword pwd + select * from dummy; +#+end_src")) + +(ert-deftest ob-sql/engine-saphana-can-pass-additional-cmdline-params () + (ob-sql/command-should-contain " cmdlineparams$" " +#+begin_src sql :engine saphana :dbpassword dummy :cmdline cmdlineparams + select * from dummy; +#+end_src")) + +;;; sqsh +(ert-deftest ob-sql/engine-sqsh-uses-sqsh () + (ob-sql/command-should-contain "^sqsh " " +#+begin_src sql :engine sqsh + select * from dummy; +#+end_src")) + +(ert-deftest ob-sql/engine-sqsh-can-pass-additional-cmdline-params () + (ob-sql/command-should-contain " cmdlineparams " " +#+begin_src sql :engine sqsh :dbpassword dummy :cmdline cmdlineparams + select * from dummy; +#+end_src")) + +(ert-deftest ob-sql/engine-sqsh-passes-user-if-provided () + (ob-sql/command-should-contain " -U \"dummy\" " " +#+begin_src sql :engine sqsh :dbuser dummy + select * from dummy; +#+end_src")) + +(ert-deftest ob-sql/engine-sqsh-passes-password-if-provided () + (ob-sql/command-should-contain " -P \"dummy\" " " +#+begin_src sql :engine sqsh :dbpassword dummy + select * from dummy; +#+end_src")) + +(ert-deftest ob-sql/engine-sqsh-passes-host-if-provided () + (ob-sql/command-should-contain " -S \"localhost\" " " +#+begin_src sql :engine sqsh :dbhost localhost + select * from dummy; +#+end_src")) + +(ert-deftest ob-sql/engine-sqsh-passes-database-if-provided () + (ob-sql/command-should-contain " -D \"R01\" " " +#+begin_src sql :engine sqsh :database R01 + select * from dummy; +#+end_src")) + + +;;; vertica +(ert-deftest ob-sql/engine-vertica-uses-vsql () + (ob-sql/command-should-contain "^vsql " " +#+begin_src sql :engine vertica + select * from dummy; +#+end_src")) + +(ert-deftest ob-sql/engine-vertica-can-pass-additional-cmdline-params () + (ob-sql/command-should-contain " cmdlineparams$" " +#+begin_src sql :engine vertica :dbpassword dummy :cmdline cmdlineparams + select * from dummy; +#+end_src")) + +(ert-deftest ob-sql/engine-vertica-passes-user-if-provided () + (ob-sql/command-should-contain " -U dummy " " +#+begin_src sql :engine vertica :dbuser dummy + select * from dummy; +#+end_src")) + +(ert-deftest ob-sql/engine-vertica-passes-password-if-provided () + (ob-sql/command-should-contain " -w dummy " " +#+begin_src sql :engine vertica :dbpassword dummy + select * from dummy; +#+end_src")) + +(ert-deftest ob-sql/engine-vertica-passes-host-if-provided () + (ob-sql/command-should-contain " -h localhost " " +#+begin_src sql :engine vertica :dbhost localhost + select * from dummy; +#+end_src")) + +(ert-deftest ob-sql/engine-vertica-passes-database-if-provided () + (ob-sql/command-should-contain " -d R01 " " +#+begin_src sql :engine vertica :database R01 + select * from dummy; +#+end_src")) + +(ert-deftest ob-sql/engine-vertica-passes-port-if-provided () + (ob-sql/command-should-contain " -p 12345 " " +#+begin_src sql :engine vertica :dbport 12345 + select * from dummy; +#+end_src")) + +;;; test-ob-sqlite.el ends here -- --00000000000030227905ba7d7a8a Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
* lisp/ob-sql.el (org-babel-execute:sql, org-babel-sql-dbs= tring-saphana):
Add basic support for SAP HANA to SQL blocks
* testin= g/lisp/test-ob-sql.el: Basic tests for generated db connection
string
This change adds basic support for SAP HANA to SQL blocks by
specif= ying saphana as :engine.

It also adds a new header arg `dbinstance&#= 39; in order to specify the SAP
HANA instance to connect to.

Sign= ed-off-by: Robin Campbell Joy <rcj@r= obinjoy.net>
---
=C2=A0lisp/ob-sql.el =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0| =C2=A025 ++-
=C2=A0testing/lisp/test-ob-sql.el= | 382 ++++++++++++++++++++++++++++++++++++
=C2=A02 files changed, 406 i= nsertions(+), 1 deletion(-)
=C2=A0create mode 100644 testing/lisp/test-o= b-sql.el

diff --git a/lisp/ob-sql.el b/lisp/ob-sql.el
index 90219= 4ae8..5398c85aa 100644
--- a/lisp/ob-sql.el
+++ b/lisp/ob-sql.el
@= @ -40,6 +40,7 @@
=C2=A0;; - dbuser
=C2=A0;; - dbpassword
=C2=A0;; = - dbconnection (to reference connections in sql-connection-alist)
+;; - = dbinstance
=C2=A0;; - database
=C2=A0;; - colnames (default, nil, mea= ns "yes")
=C2=A0;; - result-params
@@ -58,6 +59,7 @@
=C2= =A0;; - postgresql (postgres)
=C2=A0;; - oracle
=C2=A0;; - vertica+;; - saphana
=C2=A0;;
=C2=A0;; TODO:
=C2=A0;;
@@ -85,6 +87,7 = @@
=C2=A0 =C2=A0 =C2=A0(dbport =C2=A0 =C2=A0 =C2=A0 . :any)
=C2=A0 = =C2=A0 =C2=A0(dbuser =C2=A0 =C2=A0 =C2=A0 . :any)
=C2=A0 =C2=A0 =C2=A0(d= bpassword =C2=A0 =C2=A0 =C2=A0 . :any)
+ =C2=A0 =C2=A0(dbinstance =C2=A0= =C2=A0 =C2=A0 . :any)
=C2=A0 =C2=A0 =C2=A0(database =C2=A0 =C2=A0 =C2= =A0 . :any))
=C2=A0 =C2=A0"SQL-specific header arguments.")=C2=A0
@@ -174,6 +177,18 @@ SQL Server on Windows and Linux platform.&q= uot;
=C2=A0 =C2=A0(when database (format "-d %s" database))))<= br>=C2=A0 =C2=A0 =C2=A0 =C2=A0" "))
=C2=A0
+(defun org-babe= l-sql-dbstring-saphana (host port instance user password database)
+ =C2= =A0"Make SAP HANA command line args for database connection. Pass nil = to omit that arg."
+ =C2=A0(mapconcat #'identity
+ =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (delq nil
+ =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (list (when (and host port) (format = "-n %s:%s" host port))
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (when (and host (not port)= ) (format "-n %s" host))
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (when instance (format &qu= ot;-i %d" instance))
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (when user (format "-u %s&qu= ot; user))
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 (when password (format "-p %s" (shell-qu= ote-argument password)))
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (when database (format "-d %s&q= uot; database))))
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 " &qu= ot;))
+
=C2=A0(defun org-babel-sql-convert-standard-filename (file)=C2=A0 =C2=A0"Convert FILE to OS standard file name.
=C2=A0If in = Cygwin environment, uses Cygwin specific function to
@@ -197,6 +212,7 @@= database connections."
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (:dbport . s= ql-port)
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (:dbuser . sql-user)
=C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 (:dbpassword . sql-password)
+ =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 (:dbinstance . sql-dbinstance)
=C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 (:database . sql-database)))
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 (mapped-name (cdr (assq name name-mapping))))
=C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0(cadr (assq mapped-name
@@ -212,6 +228,7 @@ This fun= ction is called by `org-babel-execute-src-block'."
=C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 (dbport (org-babel-find-db-connection-param params= :dbport))
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (dbuser (org-babel-find-db= -connection-param params :dbuser))
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (d= bpassword (org-babel-find-db-connection-param params :dbpassword))
+ =C2= =A0 =C2=A0 =C2=A0 =C2=A0 (dbinstance (org-babel-find-db-connection-param pa= rams :dbinstance))
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (database (org-bab= el-find-db-connection-param params :database))
=C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 (engine (cdr (assq :engine params)))
=C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 (colnames-p (not (equal "no" (cdr (assq :colnames para= ms)))))
@@ -276,6 +293,12 @@ footer=3Doff -F \"\t\" =C2=A0%s -= f %s -o %s %s"
=C2=A0 =C2=A0 =C2=A0 =C2=A0dbhost dbport dbuser dbpa= ssword database)
=C2=A0 =C2=A0 =C2=A0 (org-babel-process-file-name in-fi= le)
=C2=A0 =C2=A0 =C2=A0 (org-babel-process-file-name out-file)))
+ = =C2=A0 =C2=A0(saphana (format "hdbsql %s -I %s -o %s %s"
+ =C2= =A0 =C2=A0 (org-babel-sql-dbstring-saphana
+ =C2=A0 =C2=A0 =C2=A0dbhost = dbport dbinstance dbuser dbpassword database)
+ =C2=A0 =C2=A0 (org-babel= -process-file-name in-file)
+ =C2=A0 =C2=A0 (org-babel-process-file-name= out-file)
+ =C2=A0 =C2=A0 (or cmdline "")))
=C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(t (user-erro= r "No support for the %s SQL engine" engine)))))
=C2=A0 =C2=A0= =C2=A0(with-temp-file in-file
=C2=A0 =C2=A0 =C2=A0 =C2=A0(insert
@@ = -309,7 +332,7 @@ SET COLSEP '|'
=C2=A0 (progn (insert-file-conte= nts-literally out-file) (buffer-string)))
=C2=A0 =C2=A0 =C2=A0 =C2=A0(wi= th-temp-buffer
=C2=A0 (cond
- ((memq (intern engine) '(dbi mysql = postgresql postgres sqsh vertica))
+ ((memq (intern engine) '(dbi my= sql postgresql postgres saphana sqsh vertica))
=C2=A0 =C2=A0;; Add heade= r row delimiter after column-names header in first line
=C2=A0 =C2=A0(co= nd
=C2=A0 =C2=A0 (colnames-p
diff --git a/testing/lisp/test-ob-sql.el= b/testing/lisp/test-ob-sql.el
new file mode 100644
index 000000000..= 51edd2309
--- /dev/null
+++ b/testing/lisp/test-ob-sql.el
@@ -0,0 = +1,382 @@
+;;; test-ob-sql.el --- tests for ob-sql.el
+
+;; Copyri= ght (C) 2021 Robin Joy
+
+;; Author: Robin Joy <rcj@robinjoy.net>
+;; Keywords: lisp
+
+;= ; This program is free software; you can redistribute it and/or modify
+= ;; it under the terms of the GNU General Public License as published by
= +;; the Free Software Foundation, either version 3 of the License, or
+;= ; (at your option) any later version.
+
+;; This program is distribut= ed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; wit= hout even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A P= ARTICULAR PURPOSE.=C2=A0 See the
+;; GNU General Public License for more= details.
+
+;; You should have received a copy of the GNU General Pu= blic License
+;; along with this program.=C2=A0 If not, see <http://www.gnu.org/licenses/>.
= +
+;;; Code:
+
+(require 'org-test)
+(require 'ob-sql)<= br>+(unless (featurep 'ob-sql)
+ =C2=A0(signal 'missing-test-dep= endency "Support for sql code blocks"))
+
+(defmacro ob-sql= /command (&rest body)
+ =C2=A0"Execute body and return the comm= and that would have been executed."
+ =C2=A0`(cl-letf (((symbol-fun= ction 'org-babel-eval)
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0(lambda (command &rest _) (throw 'sql-command command))))
= + =C2=A0 =C2=A0 (catch 'sql-command
+ =C2=A0 =C2=A0 =C2=A0 ,@body)))=
+
+(defmacro ob-sql/command-should-contain (regexp sql-block)
+ = =C2=A0"Check that REGEXP is contained in the command executed when eva= luating SQL-BLOCK."
+ =C2=A0`(let ((regexps ,(if (listp regexp) reg= exp `(list ,regexp)))
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 (command (ob-sql/com= mand (org-test-with-temp-text
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0,sql-block
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0(org-babel-next-src-block)
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0(org-babel-execute-src-block)))))
+ =C2=A0 =C2= =A0 (dolist (regexp regexps)
+ =C2=A0 =C2=A0 =C2=A0 (should (string-matc= h-p regexp command)))))
+
+(defmacro ob-sql/command-should-not-contai= n (regexp sql-block)
+ =C2=A0"Check that REGEXP is not contained in= the command executed when evaluating SQL-BLOCK."
+ =C2=A0`(let ((c= ommand (ob-sql/command
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 (org-test-with-temp-text
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ,sql-block
+ =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (org-babel-n= ext-src-block)
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 (org-babel-execute-src-block)))))
+ =C2=A0 =C2=A0 (should= -not (string-match-p ,regexp command))))
+
+;;; dbish
+(ert-deftes= t ob-sql/engine-dbi-uses-dbish ()
+ =C2=A0(ob-sql/command-should-contain= "^dbish " "
+#+begin_src sql :engine dbi
+ =C2=A0sele= ct * from dummy;
+#+end_src"))
+
+(ert-deftest ob-sql/engine-= dbish-uses-batch-mode ()
+ =C2=A0(ob-sql/command-should-contain " -= -batch " "
+#+begin_src sql :engine dbi :dbuser dummy
+ =C2= =A0select * from dummy;
+#+end_src"))
+
+(ert-deftest ob-sql/= engine-dbish-can-pass-additional-cmdline-params ()
+ =C2=A0(ob-sql/comma= nd-should-contain " cmdlineparams " "
+#+begin_src sql :e= ngine dbi :dbpassword dummy :cmdline cmdlineparams
+ =C2=A0select * from= dummy;
+#+end_src"))
+
+;;; monetdb
+(ert-deftest ob-sql/= engine-monetdb-uses-mclient ()
+ =C2=A0(ob-sql/command-should-contain &q= uot;^mclient " "
+#+begin_src sql :engine monetdb
+ =C2=A0s= elect * from dummy;
+#+end_src"))
+
+(ert-deftest ob-sql/engi= ne-monetdb-outputs-values-tab-separated ()
+ =C2=A0(ob-sql/command-shoul= d-contain " -f tab " "
+#+begin_src sql :engine monetdb+ =C2=A0select * from dummy;
+#+end_src"))
+
+(ert-deftest = ob-sql/engine-monetdb-can-pass-additional-cmdline-params ()
+ =C2=A0(ob-= sql/command-should-contain " cmdlineparams " "
+#+begin_s= rc sql :engine monetdb :dbpassword dummy :cmdline cmdlineparams
+ =C2=A0= select * from dummy;
+#+end_src"))
+
+;;; mssql
+(ert-deft= est ob-sql/engine-mssql-uses-sqlcmd ()
+ =C2=A0(ob-sql/command-should-co= ntain "^sqlcmd " "
+#+begin_src sql :engine mssql
+ = =C2=A0select * from dummy;
+#+end_src"))
+
+(ert-deftest ob-s= ql/engine-mssql-outputs-values-tab-separated ()
+ =C2=A0(ob-sql/command-= should-contain " -s \"\t\" " "
+#+begin_src sql= :engine mssql
+ =C2=A0select * from dummy;
+#+end_src"))
++(ert-deftest ob-sql/engine-mssql-can-pass-additional-cmdline-params ()+ =C2=A0(ob-sql/command-should-contain " cmdlineparams " "=
+#+begin_src sql :engine mssql :dbpassword dummy :cmdline cmdlineparams=
+ =C2=A0select * from dummy;
+#+end_src"))
+
+(ert-deftes= t ob-sql/engine-mssql-passes-user-if-provided ()
+ =C2=A0(ob-sql/command= -should-contain " -U \"dummy\" " "
+#+begin_src= sql :engine mssql :dbuser dummy
+ =C2=A0select * from dummy;
+#+end_= src"))
+
+(ert-deftest ob-sql/engine-mssql-passes-password-if-pr= ovided ()
+ =C2=A0(ob-sql/command-should-contain " -P \"dummy\= " " "
+#+begin_src sql :engine mssql :dbpassword dummy+ =C2=A0select * from dummy;
+#+end_src"))
+
+(ert-deftest o= b-sql/engine-mssql-passes-dbhost-if-provided ()
+ =C2=A0(ob-sql/command-= should-contain " -S \"localhost\" " "
+#+begin_= src sql :engine mssql :dbhost localhost
+ =C2=A0select * from dummy;
= +#+end_src"))
+
+(ert-deftest ob-sql/engine-mssql-passes-databas= e-if-provided ()
+ =C2=A0(ob-sql/command-should-contain " -d \"= ;R01\" " "
+#+begin_src sql :engine mssql :database R01+ =C2=A0select * from dummy;
+#+end_src"))
+
+(ert-deftest = ob-sql/engine-mssql-passes-all-parameter-provided ()
+ =C2=A0(ob-sql/com= mand-should-contain '(" -d \"R01\" " " -S \&qu= ot;localhost\" " " -P \"pwd\" " " -U \&q= uot;usr\" ") "
+#+begin_src sql :engine mssql :database R= 01 :dbhost localhost :dbport 30101 :dbinstance 1 :dbuser usr :dbpassword pw= d
+ =C2=A0select * from dummy;
+#+end_src"))
+
+;;; MySQL<= br>+(ert-deftest ob-sql/engine-mysql-uses-mysql ()
+ =C2=A0(ob-sql/comma= nd-should-contain "^mysql " "
+#+begin_src sql :engine my= sql
+ =C2=A0select * from dummy;
+#+end_src"))
+
+(ert-def= test ob-sql/engine-mysql-passes-user-if-provided ()
+ =C2=A0(ob-sql/comm= and-should-contain " -udummy " "
+#+begin_src sql :engine= mysql :dbuser dummy
+ =C2=A0select * from dummy;
+#+end_src"))<= br>+
+(ert-deftest ob-sql/engine-mysql-passes-password-if-provided ()+ =C2=A0(ob-sql/command-should-contain " -pdummy " "
+#+= begin_src sql :engine mysql :dbpassword dummy
+ =C2=A0select * from dumm= y;
+#+end_src"))
+
+(ert-deftest ob-sql/engine-mysql-passes-d= bhost-if-provided ()
+ =C2=A0(ob-sql/command-should-contain " -hloc= alhost " "
+#+begin_src sql :engine mysql :dbhost localhost+ =C2=A0select * from dummy;
+#+end_src"))
+
+(ert-deftest o= b-sql/engine-mysql-passes-host-if-provided ()
+ =C2=A0(ob-sql/command-sh= ould-contain " -P30101 " "
+#+begin_src sql :engine mysql= :dbport 30101
+ =C2=A0select * from dummy;
+#+end_src"))
++(ert-deftest ob-sql/engine-mysql-passes-database-if-provided ()
+ =C2= =A0(ob-sql/command-should-contain " -dR01 " "
+#+begin_sr= c sql :engine mysql :database R01
+ =C2=A0select * from dummy;
+#+end= _src"))
+
+(ert-deftest ob-sql/engine-mysql-passes-all-parameter= -provided ()
+ =C2=A0(ob-sql/command-should-contain '(" -dR01 &= quot; " -hlocalhost " " -P30101 " " -ppwd " &= quot; -uusr ") "
+#+begin_src sql :engine mysql :database R01 = :dbhost localhost :dbport 30101 :dbinstance 1 :dbuser usr :dbpassword pwd+ =C2=A0select * from dummy;
+#+end_src"))
+
+;;; oracle+(ert-deftest ob-sql/engine-oracle-uses-sqlplus ()
+ =C2=A0(ob-sql/comm= and-should-contain "^sqlplus " "
+#+begin_src sql :engine= oracle :dbuser dummy :dbpassword dummy :database dummy
+ =C2=A0select *= from dummy;
+#+end_src"))
+
+(ert-deftest ob-sql/engine-orac= le-passes-user-pwd-database-host-port-if-provided ()
+ =C2=A0(ob-sql/com= mand-should-contain " dummy/dummypwd@localhost:12345/R01 " "=
+#+begin_src sql :engine oracle :dbuser dummy :dbpassword dummypwd :dbh= ost localhost :database R01 :dbport 12345
+ =C2=A0select * from dummy;+#+end_src"))
+
+(ert-deftest ob-sql/engine-oracle-passes-user= -pwd-database-if-no-host-port-provided ()
+ =C2=A0(ob-sql/command-should= -contain " dummy/dummypwd@R01 " "
+#+begin_src sql :engin= e oracle :dbuser dummy :dbpassword dummypwd :database R01
+ =C2=A0select= * from dummy;
+#+end_src"))
+
+;;; postgresql
+(ert-defte= st ob-sql/engine-postgresql-uses-psql ()
+ =C2=A0(ob-sql/command-should-= contain "^psql " "
+#+begin_src sql :engine postgresql+ =C2=A0select * from dummy;
+#+end_src"))
+
+(ert-deftest o= b-sql/engine-postgresql-passes-password-if-provided ()
+ =C2=A0(ob-sql/c= ommand-should-contain "^PGPASSWORD=3Ddummy " "
+#+begin_s= rc sql :engine postgresql :dbpassword dummy
+ =C2=A0select * from dummy;=
+#+end_src"))
+
+(ert-deftest ob-sql/engine-postgresql-stop-= on-error ()
+ =C2=A0(ob-sql/command-should-contain " --set=3D\"= ;ON_ERROR_STOP=3D1\" " "
+#+begin_src sql :engine postgre= sql
+ =C2=A0select * from dummy;
+#+end_src"))
+
+(ert-def= test ob-sql/engine-postgresql-does-not-output-column-names-if-requested ()<= br>+ =C2=A0(ob-sql/command-should-contain " -t " "
+#+beg= in_src sql :engine postgresql :colnames no
+ =C2=A0select * from dummy;<= br>+#+end_src"))
+
+(ert-deftest ob-sql/engine-postgresql-output= s-column-names-by-default ()
+ =C2=A0(ob-sql/command-should-not-contain = " -t " "
+#+begin_src sql :engine postgresql
+ =C2=A0s= elect * from dummy;
+#+end_src"))
+
+(ert-deftest ob-sql/engi= ne-postgresql-can-pass-additional-cmdline-params ()
+ =C2=A0(ob-sql/comm= and-should-contain " cmdlineparams$" "
+#+begin_src sql := engine postgresql :dbpassword dummy :cmdline cmdlineparams
+ =C2=A0selec= t * from dummy;
+#+end_src"))
+
+;;; SAP HANA
+(ert-deftes= t ob-sql/engine-saphana-uses-hdbsql ()
+ =C2=A0(ob-sql/command-should-co= ntain "^hdbsql " "
+#+begin_src sql :engine saphana
+ = =C2=A0select * from dummy;
+#+end_src"))
+
+(ert-deftest ob-s= ql/engine-saphana-passes-user-if-provided ()
+ =C2=A0(ob-sql/command-sho= uld-contain " -u dummy " "
+#+begin_src sql :engine sapha= na :dbuser dummy
+ =C2=A0select * from dummy;
+#+end_src"))
+=
+(ert-deftest ob-sql/engine-saphana-passes-password-if-provided ()
+= =C2=A0(ob-sql/command-should-contain " -p dummy " "
+#+b= egin_src sql :engine saphana :dbpassword dummy
+ =C2=A0select * from dum= my;
+#+end_src"))
+
+(ert-deftest ob-sql/engine-saphana-passe= s-dbinstance-if-provided ()
+ =C2=A0(ob-sql/command-should-contain "= ; -i 1 " "
+#+begin_src sql :engine saphana :dbinstance 1
+= =C2=A0select * from dummy;
+#+end_src"))
+
+(ert-deftest ob-= sql/engine-saphana-passes-dbhost-if-provided ()
+ =C2=A0(ob-sql/command-= should-contain " -n localhost " "
+#+begin_src sql :engin= e saphana :dbhost localhost
+ =C2=A0select * from dummy;
+#+end_src&q= uot;))
+
+(ert-deftest ob-sql/engine-saphana-passes-dbhost-and-dbport= -if-provided ()
+ =C2=A0(ob-sql/command-should-contain " -n localho= st:30101 " "
+#+begin_src sql :engine saphana :dbhost localhos= t :dbport 30101
+ =C2=A0select * from dummy;
+#+end_src"))
+<= br>+(ert-deftest ob-sql/engine-saphana-does-not-pass-host-port-if-only-port= -provided ()
+ =C2=A0(ob-sql/command-should-not-contain " -n" = "
+#+begin_src sql :engine saphana :dbport 30101
+ =C2=A0select = * from dummy;
+#+end_src"))
+
+(ert-deftest ob-sql/engine-sap= hana-passes-database-if-provided ()
+ =C2=A0(ob-sql/command-should-conta= in " -d R01 " "
+#+begin_src sql :engine saphana :databas= e R01
+ =C2=A0select * from dummy;
+#+end_src"))
+
+(ert-d= eftest ob-sql/engine-saphana-passes-all-parameter-provided ()
+ =C2=A0(o= b-sql/command-should-contain '(" -d R01 " " -n localhost= :30101 " " -i 1 " " -p pwd " " -u usr") = "
+#+begin_src sql :engine saphana :database R01 :dbhost localhost = :dbport 30101 :dbinstance 1 :dbuser usr :dbpassword pwd
+ =C2=A0select *= from dummy;
+#+end_src"))
+
+(ert-deftest ob-sql/engine-saph= ana-can-pass-additional-cmdline-params ()
+ =C2=A0(ob-sql/command-should= -contain " cmdlineparams$" "
+#+begin_src sql :engine sap= hana :dbpassword dummy :cmdline cmdlineparams
+ =C2=A0select * from dumm= y;
+#+end_src"))
+
+;;; sqsh
+(ert-deftest ob-sql/engine-s= qsh-uses-sqsh ()
+ =C2=A0(ob-sql/command-should-contain "^sqsh &quo= t; "
+#+begin_src sql :engine sqsh
+ =C2=A0select * from dummy;<= br>+#+end_src"))
+
+(ert-deftest ob-sql/engine-sqsh-can-pass-add= itional-cmdline-params ()
+ =C2=A0(ob-sql/command-should-contain " = cmdlineparams " "
+#+begin_src sql :engine sqsh :dbpassword du= mmy :cmdline cmdlineparams
+ =C2=A0select * from dummy;
+#+end_src&qu= ot;))
+
+(ert-deftest ob-sql/engine-sqsh-passes-user-if-provided ()+ =C2=A0(ob-sql/command-should-contain " -U \"dummy\" &quo= t; "
+#+begin_src sql :engine sqsh :dbuser dummy
+ =C2=A0select = * from dummy;
+#+end_src"))
+
+(ert-deftest ob-sql/engine-sqs= h-passes-password-if-provided ()
+ =C2=A0(ob-sql/command-should-contain = " -P \"dummy\" " "
+#+begin_src sql :engine sqs= h :dbpassword dummy
+ =C2=A0select * from dummy;
+#+end_src"))+
+(ert-deftest ob-sql/engine-sqsh-passes-host-if-provided ()
+ =C2= =A0(ob-sql/command-should-contain " -S \"localhost\" " = "
+#+begin_src sql :engine sqsh :dbhost localhost
+ =C2=A0select= * from dummy;
+#+end_src"))
+
+(ert-deftest ob-sql/engine-sq= sh-passes-database-if-provided ()
+ =C2=A0(ob-sql/command-should-contain= " -D \"R01\" " "
+#+begin_src sql :engine sqsh= :database R01
+ =C2=A0select * from dummy;
+#+end_src"))
++
+;;; vertica
+(ert-deftest ob-sql/engine-vertica-uses-vsql ()
= + =C2=A0(ob-sql/command-should-contain "^vsql " "
+#+begi= n_src sql :engine vertica
+ =C2=A0select * from dummy;
+#+end_src&quo= t;))
+
+(ert-deftest ob-sql/engine-vertica-can-pass-additional-cmdlin= e-params ()
+ =C2=A0(ob-sql/command-should-contain " cmdlineparams$= " "
+#+begin_src sql :engine vertica :dbpassword dummy :cmdlin= e cmdlineparams
+ =C2=A0select * from dummy;
+#+end_src"))
+<= br>+(ert-deftest ob-sql/engine-vertica-passes-user-if-provided ()
+ =C2= =A0(ob-sql/command-should-contain " -U dummy " "
+#+begin= _src sql :engine vertica :dbuser dummy
+ =C2=A0select * from dummy;
+= #+end_src"))
+
+(ert-deftest ob-sql/engine-vertica-passes-passwo= rd-if-provided ()
+ =C2=A0(ob-sql/command-should-contain " -w dummy= " "
+#+begin_src sql :engine vertica :dbpassword dummy
+ = =C2=A0select * from dummy;
+#+end_src"))
+
+(ert-deftest ob-s= ql/engine-vertica-passes-host-if-provided ()
+ =C2=A0(ob-sql/command-sho= uld-contain " -h localhost " "
+#+begin_src sql :engine v= ertica :dbhost localhost
+ =C2=A0select * from dummy;
+#+end_src"= ;))
+
+(ert-deftest ob-sql/engine-vertica-passes-database-if-provided= ()
+ =C2=A0(ob-sql/command-should-contain " -d R01 " "+#+begin_src sql :engine vertica :database R01
+ =C2=A0select * from d= ummy;
+#+end_src"))
+
+(ert-deftest ob-sql/engine-vertica-pas= ses-port-if-provided ()
+ =C2=A0(ob-sql/command-should-contain " -p= 12345 " "
+#+begin_src sql :engine vertica :dbport 12345
+= =C2=A0select * from dummy;
+#+end_src"))
+
+;;; test-ob-sqli= te.el ends here
--
--00000000000030227905ba7d7a8a--