From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mp0 ([2001:41d0:2:bcc0::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by ms11 with LMTPS id eHSJFn56SGBGTwAA0tVLHw (envelope-from ) for ; Wed, 10 Mar 2021 07:51:26 +0000 Received: from aspmx1.migadu.com ([2001:41d0:2:bcc0::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by mp0 with LMTPS id sMdhEn56SGDZKAAA1q6Kng (envelope-from ) for ; Wed, 10 Mar 2021 07:51:26 +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 5A5C7CFF9 for ; Wed, 10 Mar 2021 08:51:25 +0100 (CET) Received: from localhost ([::1]:56212 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1lJtcp-0001eB-Ff for larch@yhetil.org; Wed, 10 Mar 2021 02:51:23 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:59828) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lJtcD-0001e1-2U for emacs-orgmode@gnu.org; Wed, 10 Mar 2021 02:50:45 -0500 Received: from mail-lj1-x234.google.com ([2a00:1450:4864:20::234]:36991) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1lJtc8-0005LY-HP for emacs-orgmode@gnu.org; Wed, 10 Mar 2021 02:50:44 -0500 Received: by mail-lj1-x234.google.com with SMTP id q14so24341668ljp.4 for ; Tue, 09 Mar 2021 23:50:38 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=robinjoy-net.20150623.gappssmtp.com; s=20150623; h=mime-version:references:in-reply-to:from:date:message-id:subject:to; bh=i6bdyfPqgem5fMDbHWD8qsyOwFLWyFdLDk0LwL0Z6+M=; b=uufuSWRu74QxA6Xoe0iARMqSihg/oH7PF8jBL2KbPhp5UYS12jQSiRj996Ix19GgBb fghJK2WtD2L65uiKWbBfQn9+TH4LCF+QrSDsLVS33WYu2aczV3C9tKSMY+khq0l0VLKT RqNnGI2CBkHLiEv1xmze7nb33XC0ehikMr5tKoVdatkzgCMYLGDBqyYnrc9BA5zdbjxy XKJSMJh8pz/rLIwxsKeninNR6qv/3jWTMYNIi0hNFJdG7BrjFnerZwnrhQ8QUMv31pW9 3NYEjqpCr4kAekc/9lXYTVpxtDbiXn6g09tjyqo03f5Vd3AP0S8ROkyDFme8n4KEFFqa 4omw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to; bh=i6bdyfPqgem5fMDbHWD8qsyOwFLWyFdLDk0LwL0Z6+M=; b=mrnV2bdLS3WhnoQkpwwgb6qPiaAbjrkQEhd+mCbArcE8xFsS4P1lBl/r1zVz/gZJY4 fu/6nHvloqFmHavonR43s96oRsn/SVK6wiD1w6S72y0RRhZlWN090XYj4F7HBk8hfv5+ 6/5yHcPJcOWNC/fwetzmJnQwjqO/JCSJo9a7XniGl6tIMOghSxVeex3PkqoeIvlbd37X ny9BEQaOOUPAa/9jtou9spLvoBtqNQ9MzySjQBUeW+IWi6EfNKCoMjmFqw8l+A/cgJUW 1WjbW41JmYk7RHLJ2vppiiY2EPDY/uVncLl+nGPvzb+FnqX9TShunbP1+W0mLjjgNCQz 4A5w== X-Gm-Message-State: AOAM5320RCO1aDurQe5eMhceM5Y13jkhHyEjyZZUyL7cAGZoNSH51JRT 7IlSxeiB1WEsJCvBQpfi8qsn0hp5k4s1IM7Vl5OCkLWiJYE= X-Google-Smtp-Source: ABdhPJwl9StszM+JJ22Wg22zb2n6JQ+tCyVbR07BbtwY8XtWYpPDjSJgrsw8naBtarE0klm2+BzIetppSGz4Xrjb5MU= X-Received: by 2002:a05:651c:200b:: with SMTP id s11mr1018880ljo.177.1615362637298; Tue, 09 Mar 2021 23:50:37 -0800 (PST) MIME-Version: 1.0 References: In-Reply-To: From: Robin Campbell Joy Date: Wed, 10 Mar 2021 08:50:26 +0100 Message-ID: Subject: Re: [PATCH] ob-sql.el: Add support for SAP HANA To: emacs-orgmode@gnu.org Content-Type: multipart/alternative; boundary="0000000000002e0e9b05bd29ec4d" Received-SPF: none client-ip=2a00:1450:4864:20::234; envelope-from=rcj@robinjoy.net; helo=mail-lj1-x234.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-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 ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=yhetil.org; s=key1; t=1615362685; h=from:from:sender:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:mime-version:mime-version: content-type:content-type:in-reply-to:in-reply-to: references:references:list-id:list-help:list-unsubscribe: list-subscribe:list-post:dkim-signature; bh=i6bdyfPqgem5fMDbHWD8qsyOwFLWyFdLDk0LwL0Z6+M=; b=LT2Ox7u5EXmRkvc2id2QthwxBjY/gRWuKi/2Xa/dYtpAvhFgw1aAjbluHc6+UF/Hl7P7OG cWYU/RQHpOLOqHxOJ/YMzocAXP2MX6HlQ/bH1T+ufD9geav8UqTQkGgcLUdHoJAmmd5NSA OnnX69/dNTc1uvxHzfvjAspkcTsygZ/HActRES+rjwAjK3igpkVKLMspDXmG+8eAR6Bkxo a7RVAqHBjzn2ecQeRheQqtgn249qTWOM7khZ+L2NMLDaoOXTzWi+6YhlgaLxYKsWAX5k5P /jdtJyqXvRZheB28+ymssQmF6LVnBX3lNpK4ZnfiAK04GV2Lpp9DX1zV4FvvSA== ARC-Seal: i=1; s=key1; d=yhetil.org; t=1615362685; a=rsa-sha256; cv=none; b=BlGlJkJh+Cwlw4VWMwfV8+icAkpXGYKtqart4hcwq+Nv2JkaHM0jfSfqfWB7pCoX3DU6AH sSL1Vxa6xkVksuE5x1SpZjxct+r+YTQ1xm6iQ1ZaNsSzvV0Ne+2FBuNGef1qAL0GjG0UKM 8PI0Sg0WLG2XR9KNbN0cK/CbccOxjXZnI8zpk3/qrHpe4H53mTZ/tyQEVFsxIxcarTuCMt O3C0iUShXhbOHc+XXqXbh3axRaWfi/MdOhJgCoE1JiX691ggN64Rtq5kUMxrE43ckTeMhq Jg5TpSDSYFEy5NH5UhhvbZ1G58elyXMJK8NgGPSa/3Aham+GIO/lot1sHZ9dww== ARC-Authentication-Results: i=1; aspmx1.migadu.com; dkim=pass header.d=robinjoy-net.20150623.gappssmtp.com header.s=20150623 header.b=uufuSWRu; 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-Spam-Score: -2.58 Authentication-Results: aspmx1.migadu.com; dkim=pass header.d=robinjoy-net.20150623.gappssmtp.com header.s=20150623 header.b=uufuSWRu; 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: 5A5C7CFF9 X-Spam-Score: -2.58 X-Migadu-Scanner: scn0.migadu.com X-TUID: rXSQgKmC9er0 --0000000000002e0e9b05bd29ec4d Content-Type: text/plain; charset="UTF-8" Hi, could someone please let me know if something is missing/incorrect? If everything should be fine, is there anything still required from my side to include this patch? I couldn't find anything else in the contributor guide. Thanks and best regards, Robin On Thu, 4 Feb 2021 at 08:55, Robin Campbell Joy wrote: > * 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 > -- > --0000000000002e0e9b05bd29ec4d Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
Hi,

could someone please let= me know if something is missing/incorrect?
If everything should = be fine, is there anything still required from my side to include this patc= h? I couldn't find anything else in the contributor guide.
Thanks and best regards,
Robin

On Thu, 4 Fe= b 2021 at 08:55, Robin Campbell Joy <rcj@robinjoy.net> wrote:
* lisp/ob-sql.el (org-b= abel-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 g= enerated 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 <rcj@robinjoy.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 insertions(+), 1 delet= ion(-)
=C2=A0create mode 100644 testing/lisp/test-ob-sql.el

diff = --git a/lisp/ob-sql.el b/lisp/ob-sql.el
index 902194ae8..5398c85aa 10064= 4
--- a/lisp/ob-sql.el
+++ b/lisp/ob-sql.el
@@ -40,6 +40,7 @@
= =C2=A0;; - dbuser
=C2=A0;; - dbpassword
=C2=A0;; - dbconnection (to r= eference connections in sql-connection-alist)
+;; - dbinstance
=C2=A0= ;; - database
=C2=A0;; - colnames (default, nil, means "yes")<= br>=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(dbus= er =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" database))))
=C2=A0 =C2=A0 = =C2=A0 =C2=A0" "))
=C2=A0
+(defun org-babel-sql-dbstring-sa= phana (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&quo= t; 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 "-i %d" insta= nce))
+ =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" (shell-quote-argument passw= ord)))
+ =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))))<= br>+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 " "))
+
=C2= =A0(defun org-babel-sql-convert-standard-filename (file)
=C2=A0 =C2=A0&q= uot;Convert FILE to OS standard file name.
=C2=A0If in Cygwin environmen= t, uses Cygwin specific function to
@@ -197,6 +212,7 @@ database connect= ions."
=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 . 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 (:dbi= nstance . 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 . sq= l-database)))
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (mapped-n= ame (cdr (assq name name-mapping))))
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(= cadr (assq mapped-name
@@ -212,6 +228,7 @@ This function is called by `o= rg-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 par= ams :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 (cd= r (assq :engine params)))
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (colnames-p= (not (equal "no" (cdr (assq :colnames 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 dbport 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 dbu= ser 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-error "No suppor= t 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-contents-literally out= -file) (buffer-string)))
=C2=A0 =C2=A0 =C2=A0 =C2=A0(with-temp-buffer=C2=A0 (cond
- ((memq (intern engine) '(dbi mysql postgresql postgr= es sqsh vertica))
+ ((memq (intern engine) '(dbi mysql postgresql po= stgres saphana sqsh vertica))
=C2=A0 =C2=A0;; Add header row delimiter a= fter column-names 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.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 Rob= in 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 distrib= uted in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; w= ithout even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A= PARTICULAR PURPOSE.=C2=A0 See the
+;; GNU General Public License for mo= re details.
+
+;; You should have received a copy of the GNU General = Public License
+;; along with this program.=C2=A0 If not, see <http://www.gnu.org/lic= enses/>.
+
+;;; Code:
+
+(require 'org-test)
+(re= quire 'ob-sql)
+(unless (featurep 'ob-sql)
+ =C2=A0(signal &#= 39;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 executed."
+ =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 &rest _) (throw 'sql-comma= nd command))))
+ =C2=A0 =C2=A0 (catch 'sql-command
+ =C2=A0 =C2= =A0 =C2=A0 ,@body)))
+
+(defmacro ob-sql/command-should-contain (rege= xp sql-block)
+ =C2=A0"Check that REGEXP is contained in the comman= d 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
+ =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)))))<= br>+ =C2=A0 =C2=A0 (dolist (regexp regexps)
+ =C2=A0 =C2=A0 =C2=A0 (shou= ld (string-match-p regexp command)))))
+
+(defmacro ob-sql/command-sh= ould-not-contain (regexp sql-block)
+ =C2=A0"Check that REGEXP is n= ot 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<= br>+ =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 " "
+#+begin_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-co= ntain " --batch " "
+#+begin_src sql :engine dbi :dbuser = dummy
+ =C2=A0select * from dummy;
+#+end_src"))
+
+(ert-d= eftest ob-sql/engine-dbish-can-pass-additional-cmdline-params ()
+ =C2= =A0(ob-sql/command-should-contain " cmdlineparams " "
+#+= 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-s= hould-contain "^mclient " "
+#+begin_src sql :engine mone= tdb
+ =C2=A0select * from dummy;
+#+end_src"))
+
+(ert-def= test ob-sql/engine-monetdb-outputs-values-tab-separated ()
+ =C2=A0(ob-s= ql/command-should-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 " &quo= t;
+#+begin_src sql :engine monetdb :dbpassword dummy :cmdline cmdlinepa= rams
+ =C2=A0select * from dummy;
+#+end_src"))
+
+;;; mss= ql
+(ert-deftest ob-sql/engine-mssql-uses-sqlcmd ()
+ =C2=A0(ob-sql/c= ommand-should-contain "^sqlcmd " "
+#+begin_src sql :engi= ne mssql
+ =C2=A0select * from dummy;
+#+end_src"))
+
+(er= t-deftest ob-sql/engine-mssql-outputs-values-tab-separated ()
+ =C2=A0(o= b-sql/command-should-contain " -s \"\t\" " "
+#= +begin_src sql :engine mssql
+ =C2=A0select * from dummy;
+#+end_src&= quot;))
+
+(ert-deftest ob-sql/engine-mssql-can-pass-additional-cmdli= ne-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-deftest 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 dum= my;
+#+end_src"))
+
+(ert-deftest ob-sql/engine-mssql-passes-= password-if-provided ()
+ =C2=A0(ob-sql/command-should-contain " -P= \"dummy\" " "
+#+begin_src sql :engine mssql :dbpas= sword dummy
+ =C2=A0select * from dummy;
+#+end_src"))
+
+= (ert-deftest ob-sql/engine-mssql-passes-dbhost-if-provided ()
+ =C2=A0(o= b-sql/command-should-contain " -S \"localhost\" " "= ;
+#+begin_src sql :engine mssql :dbhost localhost
+ =C2=A0select * f= rom dummy;
+#+end_src"))
+
+(ert-deftest ob-sql/engine-mssql-= passes-database-if-provided ()
+ =C2=A0(ob-sql/command-should-contain &q= uot; -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/command-should-contain '(" -d \"R01\" " = " -S \"localhost\" " " -P \"pwd\" "= " -U \"usr\" ") "
+#+begin_src sql :engine mss= ql :database R01 :dbhost localhost :dbport 30101 :dbinstance 1 :dbuser usr = :dbpassword pwd
+ =C2=A0select * from dummy;
+#+end_src"))
+<= br>+;;; MySQL
+(ert-deftest ob-sql/engine-mysql-uses-mysql ()
+ =C2= =A0(ob-sql/command-should-contain "^mysql " "
+#+begin_sr= c sql :engine mysql
+ =C2=A0select * from dummy;
+#+end_src"))+
+(ert-deftest ob-sql/engine-mysql-passes-user-if-provided ()
+ = =C2=A0(ob-sql/command-should-contain " -udummy " "
+#+beg= in_src sql :engine mysql :dbuser dummy
+ =C2=A0select * from dummy;
+= #+end_src"))
+
+(ert-deftest ob-sql/engine-mysql-passes-password= -if-provided ()
+ =C2=A0(ob-sql/command-should-contain " -pdummy &q= uot; "
+#+begin_src sql :engine mysql :dbpassword dummy
+ =C2=A0= select * from dummy;
+#+end_src"))
+
+(ert-deftest ob-sql/eng= ine-mysql-passes-dbhost-if-provided ()
+ =C2=A0(ob-sql/command-should-co= ntain " -hlocalhost " "
+#+begin_src sql :engine mysql :d= bhost localhost
+ =C2=A0select * from dummy;
+#+end_src"))
+<= br>+(ert-deftest ob-sql/engine-mysql-passes-host-if-provided ()
+ =C2=A0= (ob-sql/command-should-contain " -P30101 " "
+#+begin_src= sql :engine mysql :dbport 30101
+ =C2=A0select * from dummy;
+#+end_= src"))
+
+(ert-deftest ob-sql/engine-mysql-passes-database-if-pr= ovided ()
+ =C2=A0(ob-sql/command-should-contain " -dR01 " &qu= ot;
+#+begin_src sql :engine mysql :database R01
+ =C2=A0select * fro= m dummy;
+#+end_src"))
+
+(ert-deftest ob-sql/engine-mysql-pa= sses-all-parameter-provided ()
+ =C2=A0(ob-sql/command-should-contain &#= 39;(" -dR01 " " -hlocalhost " " -P30101 " &qu= ot; -ppwd " " -uusr ") "
+#+begin_src sql :engine my= sql :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/command-should-contain "^sqlplus " "
+#+beg= in_src sql :engine oracle :dbuser dummy :dbpassword dummy :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/dummypwd@localhost:12345= /R01 " "
+#+begin_src sql :engine oracle :dbuser dummy :dbpass= word dummypwd :dbhost localhost :database R01 :dbport 12345
+ =C2=A0sele= ct * 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 " "
+#+be= gin_src sql :engine oracle :dbuser dummy :dbpassword dummypwd :database R01=
+ =C2=A0select * from dummy;
+#+end_src"))
+
+;;; postgre= sql
+(ert-deftest ob-sql/engine-postgresql-uses-psql ()
+ =C2=A0(ob-s= ql/command-should-contain "^psql " "
+#+begin_src sql :en= gine postgresql
+ =C2=A0select * from dummy;
+#+end_src"))
+<= br>+(ert-deftest ob-sql/engine-postgresql-passes-password-if-provided ()+ =C2=A0(ob-sql/command-should-contain "^PGPASSWORD=3Ddummy " &q= uot;
+#+begin_src sql :engine postgresql :dbpassword dummy
+ =C2=A0se= lect * from dummy;
+#+end_src"))
+
+(ert-deftest ob-sql/engin= e-postgresql-stop-on-error ()
+ =C2=A0(ob-sql/command-should-contain &qu= ot; --set=3D\"ON_ERROR_STOP=3D1\" " "
+#+begin_src s= ql :engine postgresql
+ =C2=A0select * from dummy;
+#+end_src"))=
+
+(ert-deftest ob-sql/engine-postgresql-does-not-output-column-name= s-if-requested ()
+ =C2=A0(ob-sql/command-should-contain " -t "= ; "
+#+begin_src sql :engine postgresql :colnames no
+ =C2=A0sel= ect * from dummy;
+#+end_src"))
+
+(ert-deftest ob-sql/engine= -postgresql-outputs-column-names-by-default ()
+ =C2=A0(ob-sql/command-s= hould-not-contain " -t " "
+#+begin_src sql :engine postg= resql
+ =C2=A0select * from dummy;
+#+end_src"))
+
+(ert-d= eftest ob-sql/engine-postgresql-can-pass-additional-cmdline-params ()
+ = =C2=A0(ob-sql/command-should-contain " cmdlineparams$" "
= +#+begin_src sql :engine postgresql :dbpassword dummy :cmdline cmdlineparam= s
+ =C2=A0select * from dummy;
+#+end_src"))
+
+;;; SAP HA= NA
+(ert-deftest ob-sql/engine-saphana-uses-hdbsql ()
+ =C2=A0(ob-sql= /command-should-contain "^hdbsql " "
+#+begin_src sql :en= gine saphana
+ =C2=A0select * from dummy;
+#+end_src"))
+
= +(ert-deftest ob-sql/engine-saphana-passes-user-if-provided ()
+ =C2=A0(= ob-sql/command-should-contain " -u dummy " "
+#+begin_src= sql :engine saphana :dbuser dummy
+ =C2=A0select * from dummy;
+#+en= d_src"))
+
+(ert-deftest ob-sql/engine-saphana-passes-password-i= f-provided ()
+ =C2=A0(ob-sql/command-should-contain " -p dummy &qu= ot; "
+#+begin_src sql :engine saphana :dbpassword dummy
+ =C2= =A0select * from dummy;
+#+end_src"))
+
+(ert-deftest ob-sql/= engine-saphana-passes-dbinstance-if-provided ()
+ =C2=A0(ob-sql/command-= should-contain " -i 1 " "
+#+begin_src sql :engine saphan= a :dbinstance 1
+ =C2=A0select * from dummy;
+#+end_src"))
+<= br>+(ert-deftest ob-sql/engine-saphana-passes-dbhost-if-provided ()
+ = =C2=A0(ob-sql/command-should-contain " -n localhost " "
+= #+begin_src sql :engine saphana :dbhost localhost
+ =C2=A0select * from = dummy;
+#+end_src"))
+
+(ert-deftest ob-sql/engine-saphana-pa= sses-dbhost-and-dbport-if-provided ()
+ =C2=A0(ob-sql/command-should-con= tain " -n localhost:30101 " "
+#+begin_src sql :engine sa= phana :dbhost localhost :dbport 30101
+ =C2=A0select * from dummy;
+#= +end_src"))
+
+(ert-deftest ob-sql/engine-saphana-does-not-pass-= host-port-if-only-port-provided ()
+ =C2=A0(ob-sql/command-should-not-co= ntain " -n" "
+#+begin_src sql :engine saphana :dbport 30= 101
+ =C2=A0select * from dummy;
+#+end_src"))
+
+(ert-def= test ob-sql/engine-saphana-passes-database-if-provided ()
+ =C2=A0(ob-sq= l/command-should-contain " -d R01 " "
+#+begin_src sql :e= ngine saphana :database R01
+ =C2=A0select * from dummy;
+#+end_src&q= uot;))
+
+(ert-deftest ob-sql/engine-saphana-passes-all-parameter-pro= vided ()
+ =C2=A0(ob-sql/command-should-contain '(" -d R01 &quo= t; " -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 p= wd
+ =C2=A0select * from dummy;
+#+end_src"))
+
+(ert-deft= est ob-sql/engine-saphana-can-pass-additional-cmdline-params ()
+ =C2=A0= (ob-sql/command-should-contain " cmdlineparams$" "
+#+beg= in_src sql :engine saphana :dbpassword dummy :cmdline cmdlineparams
+ = =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 :engine sqsh
+ =C2= =A0select * from dummy;
+#+end_src"))
+
+(ert-deftest ob-sql/= engine-sqsh-can-pass-additional-cmdline-params ()
+ =C2=A0(ob-sql/comman= d-should-contain " cmdlineparams " "
+#+begin_src sql :en= gine sqsh :dbpassword dummy :cmdline cmdlineparams
+ =C2=A0select * from= dummy;
+#+end_src"))
+
+(ert-deftest ob-sql/engine-sqsh-pass= es-user-if-provided ()
+ =C2=A0(ob-sql/command-should-contain " -U = \"dummy\" " "
+#+begin_src sql :engine sqsh :dbuser = dummy
+ =C2=A0select * from dummy;
+#+end_src"))
+
+(ert-d= eftest ob-sql/engine-sqsh-passes-password-if-provided ()
+ =C2=A0(ob-sql= /command-should-contain " -P \"dummy\" " "
+#+b= egin_src sql :engine sqsh :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 loc= alhost
+ =C2=A0select * from dummy;
+#+end_src"))
+
+(ert-= deftest ob-sql/engine-sqsh-passes-database-if-provided ()
+ =C2=A0(ob-sq= l/command-should-contain " -D \"R01\" " "
+#+be= gin_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 = " "
+#+begin_src sql :engine vertica
+ =C2=A0select * from = dummy;
+#+end_src"))
+
+(ert-deftest ob-sql/engine-vertica-ca= n-pass-additional-cmdline-params ()
+ =C2=A0(ob-sql/command-should-conta= in " cmdlineparams$" "
+#+begin_src sql :engine vertica := dbpassword dummy :cmdline cmdlineparams
+ =C2=A0select * from dummy;
= +#+end_src"))
+
+(ert-deftest ob-sql/engine-vertica-passes-user-= if-provided ()
+ =C2=A0(ob-sql/command-should-contain " -U dummy &q= uot; "
+#+begin_src sql :engine vertica :dbuser dummy
+ =C2=A0se= lect * from dummy;
+#+end_src"))
+
+(ert-deftest ob-sql/engin= e-vertica-passes-password-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-sql/engine-vertica-passes-host-if-provided ()
+ =C2= =A0(ob-sql/command-should-contain " -h localhost " "
+#+b= egin_src sql :engine vertica :dbhost localhost
+ =C2=A0select * from dum= my;
+#+end_src"))
+
+(ert-deftest ob-sql/engine-vertica-passe= s-database-if-provided ()
+ =C2=A0(ob-sql/command-should-contain " = -d R01 " "
+#+begin_src sql :engine vertica :database R01
+= =C2=A0select * from dummy;
+#+end_src"))
+
+(ert-deftest ob-= sql/engine-vertica-passes-port-if-provided ()
+ =C2=A0(ob-sql/command-sh= ould-contain " -p 12345 " "
+#+begin_src sql :engine vert= ica :dbport 12345
+ =C2=A0select * from dummy;
+#+end_src"))
= +
+;;; test-ob-sqlite.el ends here
--
--0000000000002e0e9b05bd29ec4d--