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 cNeKN4nTHmCQfQAA0tVLHw (envelope-from ) for ; Sat, 06 Feb 2021 17:36:09 +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 8BlPM4nTHmCVPwAAB5/wlQ (envelope-from ) for ; Sat, 06 Feb 2021 17:36:09 +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 B7EF3940466 for ; Sat, 6 Feb 2021 17:36:08 +0000 (UTC) Received: from localhost ([::1]:60630 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1l8RV9-0001Qi-LL for larch@yhetil.org; Sat, 06 Feb 2021 12:36:07 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:39114) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1l7PCr-0004Rv-7A for emacs-orgmode@gnu.org; Wed, 03 Feb 2021 15:56:57 -0500 Received: from mail-lf1-x135.google.com ([2a00:1450:4864:20::135]:35025) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1l7PCk-0008Bl-Gz for emacs-orgmode@gnu.org; Wed, 03 Feb 2021 15:56:56 -0500 Received: by mail-lf1-x135.google.com with SMTP id u25so1237302lfc.2 for ; Wed, 03 Feb 2021 12:56:47 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=robinjoy-net.20150623.gappssmtp.com; s=20150623; h=mime-version:from:date:message-id:subject:to; bh=ZCZLyM9L9k53gif2gPTi6ygFUGRIeNhZ3kmVFn9a1uQ=; b=XLrs/7FJ0jGz8r/ghu61boH0x3VKA+5SX69z2V97RSJTfYOVGg6tddx53Tntbf7NCq 6p+cFSc5wd3vYTFVCEQ7jx/fZF+DitCbhxQPJ3qlQ8yVPpf1oZwkBQVH9X0gHQBv0xCG 4NKBmOzJnLNr7cicJ57QHLx9xRJT9dpYFcUzn6HhFdFuLXG193aU+XbhnrtMgVjZPeKB Y+8eFRniZso94ayKPKA0x6FI3B93t5ZT+V0U8+GW/gKv+P15EBYGOHvjMFzXsVzFnHSR nwi5xNps/4+AnbMFcRNCUwY9wuIt3b4DWU0luYV7ttVvPSrZtd+/2jzQl72/fT5d7mvs qBhg== 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=ZCZLyM9L9k53gif2gPTi6ygFUGRIeNhZ3kmVFn9a1uQ=; b=hF0sblhxXzsqKCS2MdTqefoFRsdDTzWyWtYS+Qg3MUcpQI63m1BxpnNoMZnUf4vB94 941CbebwXV90csULS/g7VrzuXgN5I+cXkH/Ik0y/1sffk0GzgRPDLuPm7Jx1q/32f7ae W2ok3h3EaDk1aVRPng5Da3rrgMXNvsToTyXwTYLcIYTwMDOlKP7hOTdlfoFKoCLX82uO vj3qa3FzfhqbtI7+vUEFBMMd47kYFwtJ4Rvy9xNPpHyslvvYchyC6a6I55lbFMZHBiK7 1L5DZUTHX0+QuuYBDwi+iz/rQm+YEMkMt1sEv3sGX/WiHx8wms4Cw8FYuttZ9McIOGai mDfw== X-Gm-Message-State: AOAM533SiqIXQeWRLh/gziT4RaWiLcVCFL9rXt0HSHxn2GNy9kTp3Stu WK2gneSx2AKJPlbC8F1pYfg7Ufecr7DaO2hil4HnDGY5WBLtKQ== X-Google-Smtp-Source: ABdhPJwEce5iTXGsLD0lcCwonQezQ3cht8mrbJg9WsZLxrA+9rI+HbIEIzOpzQeH1r/nT7L1QUR72YTJNBtDxTDlXCI= X-Received: by 2002:a19:3f04:: with SMTP id m4mr2876912lfa.301.1612385806003; Wed, 03 Feb 2021 12:56:46 -0800 (PST) MIME-Version: 1.0 From: Robin Campbell Joy Date: Wed, 3 Feb 2021 21:56:35 +0100 Message-ID: Subject: [PATCH] ob-sql.el: Add support for SAP HANA To: emacs-orgmode@gnu.org Content-Type: multipart/alternative; boundary="00000000000035569305ba74d32e" Received-SPF: none client-ip=2a00:1450:4864:20::135; envelope-from=rcj@robinjoy.net; helo=mail-lf1-x135.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, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, HTML_MESSAGE=0.001, RCVD_IN_DNSWL_NONE=-0.0001, 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:26:16 -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.56 Authentication-Results: aspmx1.migadu.com; dkim=pass header.d=robinjoy-net.20150623.gappssmtp.com header.s=20150623 header.b="XLrs/7FJ"; 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: B7EF3940466 X-Spam-Score: -1.56 X-Migadu-Scanner: scn1.migadu.com X-TUID: Rd8Mc62X9B0g --00000000000035569305ba74d32e 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 -- --00000000000035569305ba74d32e 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(= dbpassword =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= ."
=C2=A0 =C2=A0(when database (format "-d %s" databas= e))))
=C2=A0 =C2=A0 =C2=A0 =C2=A0" "))
=C2=A0
+(defun o= rg-babel-sql-dbstring-saphana (host port instance user password database)+ =C2=A0"Make SAP HANA command line args for database connection. Pa= ss 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 (no= t 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 (for= mat "-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" 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" (s= hell-quote-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" 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 (:db= port . sql-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 @@ T= his function 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 (dbpassword (org-babel-find-db-connection-param params :dbpassword))=
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 (dbinstance (org-babel-find-db-connection= -param params :dbinstance))
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (database= (org-babel-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 :col= names params)))))
@@ -276,6 +293,12 @@ footer=3Doff -F \"\t\" = =C2=A0%s -f %s -o %s %s"
=C2=A0 =C2=A0 =C2=A0 =C2=A0dbhost dbpor= t dbuser dbpassword database)
=C2=A0 =C2=A0 =C2=A0 (org-babel-process= -file-name in-file)
=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 c= mdline "")))
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0(t (user-error "No support for the %s SQL e= ngine" 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-contents-literally out-file) (buffer-st= ring)))
=C2=A0 =C2=A0 =C2=A0 =C2=A0(with-temp-buffer
=C2=A0 (cond
= - ((memq (intern engine) '(dbi mysql postgresql postgres sqsh vertica)= )
+ ((memq (intern engine) '(dbi mysql postgresql postgres saphana = sqsh vertica))
=C2=A0 =C2=A0;; Add header row delimiter after column-na= mes header in first line
=C2=A0 =C2=A0(cond
=C2=A0 =C2=A0 (colnames= -p
diff --git a/testing/lisp/test-ob-sql.el b/testing/lisp/test-ob-sql.e= l
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 <rcj@robinjo= y.net>
+;; Keywords: lisp
+
+;; This program is free softwa= re; you can redistribute it and/or modify
+;; it under the terms of the = GNU General Public License as published by
+;; the Free Software Foundat= ion, either version 3 of the License, or
+;; (at your option) any later = version.
+
+;; This program is distributed in the hope that it will b= e useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warrant= y of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.=C2=A0 See = the
+;; GNU General Public License for more details.
+
+;; You sho= uld have received a copy of the GNU General Public License
+;; along wit= h this program.=C2=A0 If not, see <http://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(requ= ire 'org-test)
+(require 'ob-sql)
+(unless (featurep 'ob-= sql)
+ =C2=A0(signal 'missing-test-dependency "Support for sql = code blocks"))
+
+(defmacro ob-sql/command (&rest body)
+= =C2=A0"Execute body and return the command that would have been execu= ted."
+ =C2=A0`(cl-letf (((symbol-function 'org-babel-eval)
= + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(lambda (command &res= t _) (throw 'sql-command command))))
+ =C2=A0 =C2=A0 (catch 'sql= -command
+ =C2=A0 =C2=A0 =C2=A0 ,@body)))
+
+(defmacro ob-sql/comm= and-should-contain (regexp sql-block)
+ =C2=A0"Check that REGEXP is= contained in the command executed when evaluating SQL-BLOCK."
+ = =C2=A0`(let ((regexps ,(if (listp regexp) regexp `(list ,regexp)))
+ =C2= =A0 =C2=A0 =C2=A0 =C2=A0 (command (ob-sql/command (org-test-with-temp-text<= br>+ =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-ex= ecute-src-block)))))
+ =C2=A0 =C2=A0 (dolist (regexp regexps)
+ =C2= =A0 =C2=A0 =C2=A0 (should (string-match-p regexp command)))))
+
+(def= macro ob-sql/command-should-not-contain (regexp sql-block)
+ =C2=A0"= ;Check that REGEXP is not contained in the command executed when evaluating= SQL-BLOCK."
+ =C2=A0`(let ((command (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-next-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-deftest ob-sql/engine-dbi-uses-dbish ()
= + =C2=A0(ob-sql/command-should-contain "^dbish " "
+#+beg= in_src sql :engine dbi
+ =C2=A0select * 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-cmdl= ine-params ()
+ =C2=A0(ob-sql/command-should-contain " cmdlineparam= s " "
+#+begin_src sql :engine 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 "^mclient " "
+#+beg= in_src sql :engine monetdb
+ =C2=A0select * from dummy;
+#+end_src&qu= ot;))
+
+(ert-deftest ob-sql/engine-monetdb-outputs-values-tab-separa= ted ()
+ =C2=A0(ob-sql/command-should-contain " -f tab " "= ;
+#+begin_src sql :engine monetdb
+ =C2=A0select * from dummy;
+#= +end_src"))
+
+(ert-deftest ob-sql/engine-monetdb-can-pass-addit= ional-cmdline-params ()
+ =C2=A0(ob-sql/command-should-contain " cm= dlineparams " "
+#+begin_src sql :engine monetdb :dbpassword d= ummy :cmdline cmdlineparams
+ =C2=A0select * from dummy;
+#+end_src&q= uot;))
+
+;;; mssql
+(ert-deftest ob-sql/engine-mssql-uses-sqlcmd = ()
+ =C2=A0(ob-sql/command-should-contain "^sqlcmd " "+#+begin_src sql :engine mssql
+ =C2=A0select * from dummy;
+#+end_s= rc"))
+
+(ert-deftest ob-sql/engine-mssql-outputs-values-tab-sep= arated ()
+ =C2=A0(ob-sql/command-should-contain " -s \"\t\&qu= ot; " "
+#+begin_src sql :engine mssql
+ =C2=A0select * fro= m dummy;
+#+end_src"))
+
+(ert-deftest ob-sql/engine-mssql-ca= n-pass-additional-cmdline-params ()
+ =C2=A0(ob-sql/command-should-conta= in " cmdlineparams " "
+#+begin_src sql :engine mssql :db= password dummy :cmdline cmdlineparams
+ =C2=A0select * from dummy;
+#= +end_src"))
+
+(ert-deftest ob-sql/engine-mssql-passes-user-if-p= rovided ()
+ =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-s= ql/engine-mssql-passes-password-if-provided ()
+ =C2=A0(ob-sql/command-s= hould-contain " -P \"dummy\" " "
+#+begin_src s= ql :engine mssql :dbpassword dummy
+ =C2=A0select * from dummy;
+#+en= d_src"))
+
+(ert-deftest ob-sql/engine-mssql-passes-dbhost-if-pr= ovided ()
+ =C2=A0(ob-sql/command-should-contain " -S \"localh= ost\" " "
+#+begin_src sql :engine mssql :dbhost localhos= t
+ =C2=A0select * from dummy;
+#+end_src"))
+
+(ert-defte= st ob-sql/engine-mssql-passes-database-if-provided ()
+ =C2=A0(ob-sql/co= mmand-should-contain " -d \"R01\" " "
+#+begin_= src sql :engine mssql :database R01
+ =C2=A0select * from dummy;
+#+e= nd_src"))
+
+(ert-deftest ob-sql/engine-mssql-passes-all-paramet= er-provided ()
+ =C2=A0(ob-sql/command-should-contain '(" -d \&= quot;R01\" " " -S \"localhost\" " " -P \= "pwd\" " " -U \"usr\" ") "
+#+be= gin_src sql :engine mssql :database R01 :dbhost localhost :dbport 30101 :db= instance 1 :dbuser usr :dbpassword pwd
+ =C2=A0select * from dummy;
+= #+end_src"))
+
+;;; MySQL
+(ert-deftest ob-sql/engine-mysql-u= ses-mysql ()
+ =C2=A0(ob-sql/command-should-contain "^mysql " = "
+#+begin_src sql :engine mysql
+ =C2=A0select * from dummy;+#+end_src"))
+
+(ert-deftest ob-sql/engine-mysql-passes-user-i= f-provided ()
+ =C2=A0(ob-sql/command-should-contain " -udummy &quo= t; "
+#+begin_src sql :engine mysql :dbuser dummy
+ =C2=A0select= * from dummy;
+#+end_src"))
+
+(ert-deftest ob-sql/engine-my= sql-passes-password-if-provided ()
+ =C2=A0(ob-sql/command-should-contai= n " -pdummy " "
+#+begin_src sql :engine mysql :dbpasswor= d dummy
+ =C2=A0select * from dummy;
+#+end_src"))
+
+(ert= -deftest ob-sql/engine-mysql-passes-dbhost-if-provided ()
+ =C2=A0(ob-sq= l/command-should-contain " -hlocalhost " "
+#+begin_src s= ql :engine mysql :dbhost localhost
+ =C2=A0select * from dummy;
+#+en= d_src"))
+
+(ert-deftest ob-sql/engine-mysql-passes-host-if-prov= ided ()
+ =C2=A0(ob-sql/command-should-contain " -P30101 " &qu= ot;
+#+begin_src sql :engine mysql :dbport 30101
+ =C2=A0select * fro= m dummy;
+#+end_src"))
+
+(ert-deftest ob-sql/engine-mysql-pa= sses-database-if-provided ()
+ =C2=A0(ob-sql/command-should-contain &quo= t; -dR01 " "
+#+begin_src 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/comman= d-should-contain '(" -dR01 " " -hlocalhost " "= -P30101 " " -ppwd " " -uusr ") "
+#+begin= _src sql :engine mysql :database R01 :dbhost localhost :dbport 30101 :dbins= tance 1 :dbuser usr :dbpassword pwd
+ =C2=A0select * from dummy;
+#+e= nd_src"))
+
+;;; oracle
+(ert-deftest ob-sql/engine-oracle-us= es-sqlplus ()
+ =C2=A0(ob-sql/command-should-contain "^sqlplus &quo= t; "
+#+begin_src sql :engine oracle :dbuser dummy :dbpassword dumm= y :database dummy
+ =C2=A0select * from dummy;
+#+end_src"))
= +
+(ert-deftest ob-sql/engine-oracle-passes-user-pwd-database-host-port-= if-provided ()
+ =C2=A0(ob-sql/command-should-contain " dummy/dummy= pwd@localhost:12345/R01 " "
+#+begin_src sql :engine oracle :d= buser dummy :dbpassword dummypwd :dbhost localhost :database R01 :dbport 12= 345
+ =C2=A0select * from dummy;
+#+end_src"))
+
+(ert-def= test ob-sql/engine-oracle-passes-user-pwd-database-if-no-host-port-provided= ()
+ =C2=A0(ob-sql/command-should-contain " dummy/dummypwd@R01 &qu= ot; "
+#+begin_src sql :engine oracle :dbuser dummy :dbpassword dum= mypwd :database R01
+ =C2=A0select * from dummy;
+#+end_src"))+
+;;; postgresql
+(ert-deftest ob-sql/engine-postgresql-uses-psql = ()
+ =C2=A0(ob-sql/command-should-contain "^psql " "
+= #+begin_src sql :engine postgresql
+ =C2=A0select * from dummy;
+#+en= d_src"))
+
+(ert-deftest ob-sql/engine-postgresql-passes-passwor= d-if-provided ()
+ =C2=A0(ob-sql/command-should-contain "^PGPASSWOR= D=3Ddummy " "
+#+begin_src sql :engine postgresql :dbpassword = dummy
+ =C2=A0select * from dummy;
+#+end_src"))
+
+(ert-d= eftest ob-sql/engine-postgresql-stop-on-error ()
+ =C2=A0(ob-sql/command= -should-contain " --set=3D\"ON_ERROR_STOP=3D1\" " "= ;
+#+begin_src sql :engine postgresql
+ =C2=A0select * from dummy;+#+end_src"))
+
+(ert-deftest ob-sql/engine-postgresql-does-not= -output-column-names-if-requested ()
+ =C2=A0(ob-sql/command-should-cont= ain " -t " "
+#+begin_src sql :engine postgresql :colname= s no
+ =C2=A0select * from dummy;
+#+end_src"))
+
+(ert-de= ftest ob-sql/engine-postgresql-outputs-column-names-by-default ()
+ =C2= =A0(ob-sql/command-should-not-contain " -t " "
+#+begin_s= rc sql :engine postgresql
+ =C2=A0select * from dummy;
+#+end_src&quo= t;))
+
+(ert-deftest ob-sql/engine-postgresql-can-pass-additional-cmd= line-params ()
+ =C2=A0(ob-sql/command-should-contain " cmdlinepara= ms$" "
+#+begin_src sql :engine postgresql :dbpassword dummy := cmdline cmdlineparams
+ =C2=A0select * from dummy;
+#+end_src"))=
+
+;;; SAP HANA
+(ert-deftest ob-sql/engine-saphana-uses-hdbsql (= )
+ =C2=A0(ob-sql/command-should-contain "^hdbsql " "
= +#+begin_src sql :engine saphana
+ =C2=A0select * from dummy;
+#+end_= src"))
+
+(ert-deftest ob-sql/engine-saphana-passes-user-if-prov= ided ()
+ =C2=A0(ob-sql/command-should-contain " -u dummy " &q= uot;
+#+begin_src sql :engine saphana :dbuser dummy
+ =C2=A0select * = from dummy;
+#+end_src"))
+
+(ert-deftest ob-sql/engine-sapha= na-passes-password-if-provided ()
+ =C2=A0(ob-sql/command-should-contain= " -p dummy " "
+#+begin_src sql :engine saphana :dbpassw= ord dummy
+ =C2=A0select * from dummy;
+#+end_src"))
+
+(e= rt-deftest ob-sql/engine-saphana-passes-dbinstance-if-provided ()
+ =C2= =A0(ob-sql/command-should-contain " -i 1 " "
+#+begin_src= sql :engine saphana :dbinstance 1
+ =C2=A0select * from dummy;
+#+en= d_src"))
+
+(ert-deftest ob-sql/engine-saphana-passes-dbhost-if-= provided ()
+ =C2=A0(ob-sql/command-should-contain " -n localhost &= quot; "
+#+begin_src sql :engine saphana :dbhost localhost
+ =C2= =A0select * from dummy;
+#+end_src"))
+
+(ert-deftest ob-sql/= engine-saphana-passes-dbhost-and-dbport-if-provided ()
+ =C2=A0(ob-sql/c= ommand-should-contain " -n localhost:30101 " "
+#+begin_s= rc sql :engine saphana :dbhost localhost :dbport 30101
+ =C2=A0select * = from dummy;
+#+end_src"))
+
+(ert-deftest ob-sql/engine-sapha= na-does-not-pass-host-port-if-only-port-provided ()
+ =C2=A0(ob-sql/comm= and-should-not-contain " -n" "
+#+begin_src sql :engine s= aphana :dbport 30101
+ =C2=A0select * from dummy;
+#+end_src"))<= br>+
+(ert-deftest ob-sql/engine-saphana-passes-database-if-provided ()<= br>+ =C2=A0(ob-sql/command-should-contain " -d R01 " "
+#= +begin_src sql :engine saphana :database R01
+ =C2=A0select * from dummy= ;
+#+end_src"))
+
+(ert-deftest ob-sql/engine-saphana-passes-= all-parameter-provided ()
+ =C2=A0(ob-sql/command-should-contain '(&= quot; -d R01 " " -n localhost:30101 " " -i 1 " &qu= ot; -p pwd " " -u usr") "
+#+begin_src sql :engine s= aphana :database R01 :dbhost localhost :dbport 30101 :dbinstance 1 :dbuser = usr :dbpassword pwd
+ =C2=A0select * from dummy;
+#+end_src"))+
+(ert-deftest ob-sql/engine-saphana-can-pass-additional-cmdline-para= ms ()
+ =C2=A0(ob-sql/command-should-contain " cmdlineparams$"= "
+#+begin_src sql :engine saphana :dbpassword dummy :cmdline cmdl= ineparams
+ =C2=A0select * from dummy;
+#+end_src"))
+
+;;= ; sqsh
+(ert-deftest ob-sql/engine-sqsh-uses-sqsh ()
+ =C2=A0(ob-sql/= command-should-contain "^sqsh " "
+#+begin_src sql :engin= e sqsh
+ =C2=A0select * from dummy;
+#+end_src"))
+
+(ert-= deftest ob-sql/engine-sqsh-can-pass-additional-cmdline-params ()
+ =C2= =A0(ob-sql/command-should-contain " cmdlineparams " "
+#+= begin_src sql :engine sqsh :dbpassword dummy :cmdline cmdlineparams
+ = =C2=A0select * from dummy;
+#+end_src"))
+
+(ert-deftest ob-s= ql/engine-sqsh-passes-user-if-provided ()
+ =C2=A0(ob-sql/command-should= -contain " -U \"dummy\" " "
+#+begin_src sql :e= ngine sqsh :dbuser dummy
+ =C2=A0select * from dummy;
+#+end_src"= ;))
+
+(ert-deftest ob-sql/engine-sqsh-passes-password-if-provided ()=
+ =C2=A0(ob-sql/command-should-contain " -P \"dummy\" &q= uot; "
+#+begin_src sql :engine sqsh :dbpassword dummy
+ =C2=A0s= elect * from dummy;
+#+end_src"))
+
+(ert-deftest ob-sql/engi= ne-sqsh-passes-host-if-provided ()
+ =C2=A0(ob-sql/command-should-contai= n " -S \"localhost\" " "
+#+begin_src sql :engi= ne sqsh :dbhost localhost
+ =C2=A0select * from dummy;
+#+end_src&quo= t;))
+
+(ert-deftest ob-sql/engine-sqsh-passes-database-if-provided (= )
+ =C2=A0(ob-sql/command-should-contain " -D \"R01\" &qu= ot; "
+#+begin_src sql :engine sqsh :database R01
+ =C2=A0select= * from dummy;
+#+end_src"))
+
+
+;;; vertica
+(ert-def= test ob-sql/engine-vertica-uses-vsql ()
+ =C2=A0(ob-sql/command-should-c= ontain "^vsql " "
+#+begin_src sql :engine vertica
+ = =C2=A0select * from dummy;
+#+end_src"))
+
+(ert-deftest ob-s= ql/engine-vertica-can-pass-additional-cmdline-params ()
+ =C2=A0(ob-sql/= command-should-contain " cmdlineparams$" "
+#+begin_src s= ql :engine vertica :dbpassword dummy :cmdline cmdlineparams
+ =C2=A0sele= ct * from dummy;
+#+end_src"))
+
+(ert-deftest ob-sql/engine-= vertica-passes-user-if-provided ()
+ =C2=A0(ob-sql/command-should-contai= n " -U dummy " "
+#+begin_src sql :engine vertica :dbuser= dummy
+ =C2=A0select * from dummy;
+#+end_src"))
+
+(ert-= deftest ob-sql/engine-vertica-passes-password-if-provided ()
+ =C2=A0(ob= -sql/command-should-contain " -w dummy " "
+#+begin_src s= ql :engine vertica :dbpassword dummy
+ =C2=A0select * from dummy;
+#+= end_src"))
+
+(ert-deftest ob-sql/engine-vertica-passes-host-if-= provided ()
+ =C2=A0(ob-sql/command-should-contain " -h localhost &= quot; "
+#+begin_src sql :engine vertica :dbhost localhost
+ =C2= =A0select * from dummy;
+#+end_src"))
+
+(ert-deftest ob-sql/= engine-vertica-passes-database-if-provided ()
+ =C2=A0(ob-sql/command-sh= ould-contain " -d R01 " "
+#+begin_src sql :engine vertic= a :database R01
+ =C2=A0select * from dummy;
+#+end_src"))
+<= br>+(ert-deftest ob-sql/engine-vertica-passes-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-sqlite.el ends here
--
--00000000000035569305ba74d32e--