From 040552fbeeb1ea74a794d0e2542cd8c4b509ba5c Mon Sep 17 00:00:00 2001
From: Guian Gumpac <guiang@bitquilltech.com>
Date: Wed, 17 Nov 2021 13:48:34 -0800
Subject: [PATCH 01/28] Added Tableau Connector to OpenSearch SQL

Signed-off-by: Guian Gumpac <guiang@bitquilltech.com>
---
 .../opensearch_sql_jdbc/META-INF/MANIFEST.MF  |   3 +
 .../opensearch_sql_jdbc/connection-fields.xml |  44 +++
 .../connection-metadata.xml                   |   6 +
 .../opensearch_sql_jdbc/connectionBuilder.js  |  28 ++
 .../connectionResolver.tdr                    |  26 ++
 .../opensearch_sql_jdbc/dialect.tdd           | 349 ++++++++++++++++++
 .../opensearch_sql_jdbc/manifest.xml          |  53 +++
 .../opensearch_sql_jdbc_dev.taco              | Bin 0 -> 5259 bytes
 8 files changed, 509 insertions(+)
 create mode 100644 sql-jdbc/src/TableauConnector/opensearch_sql_jdbc/META-INF/MANIFEST.MF
 create mode 100644 sql-jdbc/src/TableauConnector/opensearch_sql_jdbc/connection-fields.xml
 create mode 100644 sql-jdbc/src/TableauConnector/opensearch_sql_jdbc/connection-metadata.xml
 create mode 100644 sql-jdbc/src/TableauConnector/opensearch_sql_jdbc/connectionBuilder.js
 create mode 100644 sql-jdbc/src/TableauConnector/opensearch_sql_jdbc/connectionResolver.tdr
 create mode 100644 sql-jdbc/src/TableauConnector/opensearch_sql_jdbc/dialect.tdd
 create mode 100644 sql-jdbc/src/TableauConnector/opensearch_sql_jdbc/manifest.xml
 create mode 100644 sql-jdbc/src/TableauConnector/opensearch_sql_jdbc/opensearch_sql_jdbc_dev.taco

diff --git a/sql-jdbc/src/TableauConnector/opensearch_sql_jdbc/META-INF/MANIFEST.MF b/sql-jdbc/src/TableauConnector/opensearch_sql_jdbc/META-INF/MANIFEST.MF
new file mode 100644
index 00000000000..97a662d62c5
--- /dev/null
+++ b/sql-jdbc/src/TableauConnector/opensearch_sql_jdbc/META-INF/MANIFEST.MF
@@ -0,0 +1,3 @@
+Manifest-Version: 1.0
+Created-By: 13 (Oracle Corporation)
+
diff --git a/sql-jdbc/src/TableauConnector/opensearch_sql_jdbc/connection-fields.xml b/sql-jdbc/src/TableauConnector/opensearch_sql_jdbc/connection-fields.xml
new file mode 100644
index 00000000000..54f5296f7e9
--- /dev/null
+++ b/sql-jdbc/src/TableauConnector/opensearch_sql_jdbc/connection-fields.xml
@@ -0,0 +1,44 @@
+<connection-fields>
+    <field name="authentication" label="Authentication" category="authentication" value-type="selection" default-value="auth-user-pass">
+        <selection-group>
+            <option value="auth-none" label="No authentication"/>
+            <option value="auth-user-pass" label="Username and Password"/>
+            <option value="auth-integrated" label="AWS_SIGV4"/>
+        </selection-group>
+    </field>
+    <field name="server" label="Server" value-type="string" category="endpoint" default-value="localhost">
+    </field>
+    <field name="port" label="Port" value-type="string" category="endpoint" default-value="9200">
+    </field>
+    <field name="username" label="Username" category="authentication" value-type="string">
+        <conditions>
+            <condition field="authentication" value="auth-user-pass"/>
+        </conditions>
+    </field>
+    <field name="password" label="Password" category="authentication" value-type="string" secure="true">
+        <conditions>
+            <condition field="authentication" value="auth-user-pass"/>
+        </conditions>
+    </field>
+    <field name="v-region" label="Region" category="authentication" value-type="string" optional="true">
+        <conditions>
+            <condition field="authentication" value="auth-integrated"/>
+        </conditions>
+    </field>
+    <field name="sslmode" label="Use SSL" value-type="boolean" category="general" default-value="require">
+        <boolean-options>
+            <false-value value=""/>
+            <true-value value="require"/>
+        </boolean-options>
+    </field>
+    <field name="v-trustSelfSigned" label="Trust Self-Signed Certificate" value-type="boolean" category="general" default-value="false">
+        <conditions>
+            <condition field="authentication" value="auth-user-pass"/>
+            <condition field="authentication" value="auth-none"/>
+        </conditions>
+        <boolean-options>
+            <false-value value="false"/>
+            <true-value value="true"/>
+        </boolean-options>
+    </field>
+</connection-fields>
diff --git a/sql-jdbc/src/TableauConnector/opensearch_sql_jdbc/connection-metadata.xml b/sql-jdbc/src/TableauConnector/opensearch_sql_jdbc/connection-metadata.xml
new file mode 100644
index 00000000000..1b3432c3177
--- /dev/null
+++ b/sql-jdbc/src/TableauConnector/opensearch_sql_jdbc/connection-metadata.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<connection-metadata>
+  <database enabled='false' />
+  <schema enabled='false' />
+  <table enabled='true' label="Table" />
+</connection-metadata>
diff --git a/sql-jdbc/src/TableauConnector/opensearch_sql_jdbc/connectionBuilder.js b/sql-jdbc/src/TableauConnector/opensearch_sql_jdbc/connectionBuilder.js
new file mode 100644
index 00000000000..1a16fddaec1
--- /dev/null
+++ b/sql-jdbc/src/TableauConnector/opensearch_sql_jdbc/connectionBuilder.js
@@ -0,0 +1,28 @@
+(function dsbuilder(attr){
+	var connStr = "jdbc:opensearch://";
+	// Set SSL value in connection string 
+	if (attr[connectionHelper.attributeSSLMode] == "require"){
+		connStr += "https://";
+	} else {
+		connStr += "http://";
+	}
+
+	// Set host information in connection string
+	connStr += attr[connectionHelper.attributeServer] + ":" + attr[connectionHelper.attributePort] + "?";
+
+	// Set authentication values in connection string
+	var authAttrValue = attr[connectionHelper.attributeAuthentication];
+	if (authAttrValue == "auth-none"){
+		connStr += "auth=NONE&trustSelfSigned=" + attr["v-trustSelfSigned"];
+	} else if (authAttrValue == "auth-integrated"){
+		connStr += "auth=AWS_SIGV4";
+		var region = attr["v-region"];
+		if (region){
+			connStr += "&Region=" + region;
+		}
+	} else { //if (authAttrValue == "auth-user-pass"){
+		connStr += "auth=BASIC&user=" + attr[connectionHelper.attributeUsername] + "&password=" + attr[connectionHelper.attributePassword] + "&trustSelfSigned=" + attr["v-trustSelfSigned"];
+	}
+
+	return [connStr];
+})
diff --git a/sql-jdbc/src/TableauConnector/opensearch_sql_jdbc/connectionResolver.tdr b/sql-jdbc/src/TableauConnector/opensearch_sql_jdbc/connectionResolver.tdr
new file mode 100644
index 00000000000..c51adc002ec
--- /dev/null
+++ b/sql-jdbc/src/TableauConnector/opensearch_sql_jdbc/connectionResolver.tdr
@@ -0,0 +1,26 @@
+<?xml version='1.0' encoding='utf-8' ?>
+<tdr class='opensearch_jdbc'>
+  <connection-resolver>
+    <connection-builder>
+      <script file='connectionBuilder.js'/>
+    </connection-builder>
+    <connection-normalizer>
+      <required-attributes>
+        <default-attributes>
+          <default-attribute name='server'>localhost</default-attribute>
+          <default-attribute name='port'>9200</default-attribute>
+        </default-attributes>
+         <attribute-list>
+          <attr>server</attr>
+          <attr>port</attr>
+          <attr>authentication</attr>
+          <attr>username</attr>
+          <attr>password</attr>
+          <attr>sslmode</attr>
+          <attr>v-region</attr>
+          <attr>v-trustSelfSigned</attr>
+        </attribute-list>
+      </required-attributes>
+    </connection-normalizer>
+  </connection-resolver>
+</tdr>
diff --git a/sql-jdbc/src/TableauConnector/opensearch_sql_jdbc/dialect.tdd b/sql-jdbc/src/TableauConnector/opensearch_sql_jdbc/dialect.tdd
new file mode 100644
index 00000000000..f33f42444e5
--- /dev/null
+++ b/sql-jdbc/src/TableauConnector/opensearch_sql_jdbc/dialect.tdd
@@ -0,0 +1,349 @@
+<?xml version="1.0" encoding="utf-8"?>
+<dialect name='OpenSearchSqlJdbcDialect'
+         class='opensearch_jdbc'
+         base='MySQL41UnicodeDriverDialect'
+         version='18.1'>   
+   <function-map>   
+        <function group='aggregate' name='STDEV' return-type='real'>
+            <formula>STDDEV_SAMP(%1)</formula>
+            <unagg-formula>NULL</unagg-formula>
+            <argument type='real' />
+        </function>
+        <function group='aggregate' name='VAR' return-type='real'>
+            <formula>VAR_SAMP(%1)</formula>
+            <unagg-formula>NULL</unagg-formula>
+            <argument type='real' />
+        </function>
+
+        <function group='cast' name='DATE' return-type='date'>
+            <formula>DATE_FORMAT(%1, &apos;%Y-%m-%d&apos;)</formula>
+            <argument type='str' />
+        </function>
+        <function group='cast' name='STR' return-type='str'>
+            <formula>DATE_FORMAT(%1, &apos;%Y-%m-%d %H:%i:%s&apos;)</formula>
+            <argument type='datetime' />
+        </function>
+        <function group='cast' name='DATETIME' return-type='datetime'>
+            <formula>CAST(%1 AS TIMESTAMP)</formula>
+            <argument type='str' />
+        </function>
+        <function group='cast' name='FLOAT' return-type='real'>
+            <!-- 693961 = TO_DAYS('1900-01-01'), since this represents the date of the Epoch. -->
+            <formula>TO_DAYS(%1) - 693961.0</formula>
+            <argument type='datetime' />
+        </function>
+
+        <function group='operator' name='!=' return-type='bool'>
+            <formula>(%1 AND NOT %2 OR NOT %1 AND %2)</formula>
+            <argument type='bool' />
+            <argument type='bool' />
+        </function>
+        <function group='operator' name='!=' return-type='bool'>
+            <formula>(%1 AND %2 = 0 OR NOT %1 AND %2 &lt;&gt; 0)</formula>
+            <argument type='bool' />
+            <argument type='int' />
+        </function>
+        <function group='operator' name='!=' return-type='bool'>
+            <formula>(%1 &lt;&gt; %2)</formula>
+            <argument type='real' />
+            <argument type='real' />
+        </function>
+        <function group='operator' name='!=' return-type='bool'>
+            <formula>(%1 = 0 AND %2 OR %1 &lt;&gt; 0 AND NOT %2)</formula>
+            <argument type='int' />
+            <argument type='bool' />
+        </function>
+        <function group='operator' name='!=' return-type='bool'>
+            <formula>(%1 &lt;&gt; %2)</formula>
+            <argument type='str' />
+            <argument type='str' />
+        </function>
+        <function group='operator' name='!=' return-type='bool'>
+            <formula>(%1 &lt;&gt; %2)</formula>
+            <argument type='datetime' />
+            <argument type='datetime' />
+        </function>
+        <function group='operator' name='!=' return-type='bool'>
+            <formula>(CAST(DATE_FORMAT(DATE(%1), '%Y-%m-%d 00:00:00') AS TIMESTAMP) &lt;&gt; %2)</formula>
+            <argument type='date' />
+            <argument type='datetime' />
+        </function>
+        <function group='operator' name='!=' return-type='bool'>
+            <formula>(%1 &lt;&gt; CAST(DATE_FORMAT(DATE(%2), '%Y-%m-%d 00:00:00') AS TIMESTAMP))</formula>
+            <argument type='datetime' />
+            <argument type='date' />
+        </function>
+        <function group='operator' name='+' return-type='datetime'>
+            <!-- 86400 as it represents seconds in a day -->
+            <formula>DATE_ADD(DATE_ADD(%1, INTERVAL FLOOR(%2) DAY), INTERVAL CAST(86400 * (%2 - FLOOR(%2)) AS INT) SECOND)</formula>
+            <argument type='datetime' />
+            <argument type='real' />
+        </function>
+        <function group='operator' name='-' return-type='int'>
+            <formula>(%1 * -1)</formula>
+            <argument type='int' />
+        </function>
+        <function group='operator' name='-' return-type='real'>
+            <formula>(%1 * -1)</formula>
+            <argument type='real' />
+        </function>
+        <function group='operator' name='-' return-type='datetime'>
+            <!-- 86400 as it represents seconds in a day -->
+            <formula>DATE_SUB(DATE_SUB(%1, INTERVAL FLOOR(%2) DAY), INTERVAL CAST(86400 * (%2 - FLOOR(%2)) AS INT) SECOND)</formula>
+            <argument type='datetime' />
+            <argument type='real' />
+        </function>
+        <function group='operator' name='/' return-type='real'>
+            <formula>CAST(%1 AS DOUBLE) / %2</formula>
+            <argument type='int' />
+            <argument type='int' />
+        </function>
+
+        <function group="numeric" name="COT" return-type="real">
+            <formula>CASE WHEN %1 = 0 THEN NULL ELSE COT(%1) END</formula>
+            <argument type="real" />
+        </function>
+        <function group='numeric' name='DIV' return-type='int'>
+            <formula>CASE WHEN %2 = 0 THEN NULL ELSE ( %1 / %2 ) END</formula>
+            <argument type='int' />
+            <argument type='int' />
+        </function>
+        <function group='numeric' name='DIV' return-type='real'>
+            <formula>CASE WHEN %2 = 0 THEN NULL ELSE ( %1 / %2 ) END</formula>
+            <argument type='real' />
+            <argument type='real' />
+        </function>
+        <function group="numeric" name="LN" return-type="real">
+            <formula>(CASE WHEN %1 &gt; 0 THEN LN(%1) ELSE NULL END)</formula>
+            <argument type="real" />
+        </function>
+        <function group="numeric" name="LOG" return-type="real">
+            <formula>CASE WHEN %1 &gt; 0 THEN LOG10(%1) ELSE NULL END</formula>
+            <argument type="real" />
+        </function>
+        <function group="numeric" name="LOG" return-type="real">
+            <formula>CASE WHEN %1 &gt; 0 AND %2 &gt; 0 AND %2 &lt;&gt; 1 THEN LOG(%2,%1) ELSE NULL END</formula>
+            <argument type="real" />
+            <argument type="real" />
+        </function>
+        <function group='numeric' name='MAX' return-type='int'>
+            <formula>CASE WHEN ISNULL(%1) THEN NULL
+                WHEN ISNULL(%2) THEN NULL
+	            WHEN %1 &gt; %2 THEN %1
+                ELSE %2 END</formula>
+            <argument type='int' />
+            <argument type='int' />
+        </function>
+        <function group='numeric' name='MAX' return-type='real'>
+            <formula>CASE WHEN ISNULL(%1) THEN NULL
+                WHEN ISNULL(%2) THEN NULL
+	            WHEN %1 &gt; %2 THEN %1
+                ELSE %2 END</formula>
+            <argument type='real' />
+            <argument type='real' />
+        </function>
+        <function group='numeric' name='MAX' return-type='datetime'>
+            <formula>CASE WHEN ISNULL(%1) THEN NULL
+                WHEN ISNULL(%2) THEN NULL
+	            WHEN %1 &gt; %2 THEN %1
+                ELSE %2 END</formula>
+            <argument type='datetime' />
+            <argument type='datetime' />
+        </function>
+        <function group='numeric' name='MIN' return-type='int'>
+            <formula>CASE WHEN ISNULL(%1) THEN NULL
+                WHEN ISNULL(%2) THEN NULL
+	            WHEN %1 &lt; %2 THEN %1
+                ELSE %2 END</formula>
+            <argument type='int' />
+            <argument type='int' />
+        </function>
+        <function group='numeric' name='MIN' return-type='real'>
+            <formula>CASE WHEN ISNULL(%1) THEN NULL
+                WHEN ISNULL(%2) THEN NULL
+	            WHEN %1 &lt; %2 THEN %1
+                ELSE %2 END</formula>
+            <argument type='real' />
+            <argument type='real' />
+        </function>
+        <function group='numeric' name='MIN' return-type='datetime'>
+            <formula>CASE WHEN ISNULL(%1) THEN NULL
+                WHEN ISNULL(%2) THEN NULL
+	            WHEN %1 &lt; %2 THEN %1
+                ELSE %2 END</formula>
+            <argument type='datetime' />
+            <argument type='datetime' />
+        </function>
+    
+        <function group='date' name='DAYOFYEAR' return-type='int'>
+            <formula>DAY_OF_YEAR(%1)</formula>
+            <argument type='date' />
+        </function>
+        <function group='date' name='DAYOFMONTH' return-type='int'>
+            <formula>DAY_OF_MONTH(%1)</formula>
+            <argument type='date' />
+        </function>
+        <function group='date' name='DAYOFWEEK' return-type='int'>
+            <formula>DAY_OF_WEEK(%1)</formula>
+            <argument type='date' />
+        </function>
+
+        <function group='string' name='MID' return-type='int'>
+            <formula>SUBSTR(%1,%2)</formula>
+            <argument type='str' />
+            <argument type='int' />
+        </function>
+        <function group='string' name='MID' return-type='int'>
+            <formula>SUBSTR(%1,CAST(%2 as int))</formula>
+            <argument type='str' />
+            <argument type='real' />
+        </function>
+        <function group='string' name='MID' return-type='int'>
+            <formula>SUBSTR(%1,%2,%3)</formula>
+            <argument type='str' />
+            <argument type='int' />
+            <argument type='int' />
+        </function>
+        <function group='string' name='MID' return-type='int'>
+            <formula>SUBSTR(%1,CAST(%2 as int),%3)</formula>
+            <argument type='str' />
+            <argument type='real' />
+            <argument type='int' />
+        </function>
+        <function group='string' name='MID' return-type='int'>
+            <formula>SUBSTR(%1,%2,CAST(%3 as int))</formula>
+            <argument type='str' />
+            <argument type='int' />
+            <argument type='real' />
+        </function>
+        <function group='string' name='MID' return-type='int'>
+            <formula>SUBSTR(%1,CAST(%2 as int),CAST(%3 as int))</formula>
+            <argument type='str' />
+            <argument type='real' />
+            <argument type='real' />
+        </function>
+
+        <function group='string' name='FIND' return-type='int'>
+<!--        The formula was simplified, because OS returns valid results even if the argument is NULL or <1 -->
+<!--        <formula>(CASE WHEN ISNULL(%3) THEN NULL WHEN %3 &gt;= 1 THEN LOCATE(%2,%1,CAST(%3 as int)) ELSE LOCATE(%2,%1,1) END)</formula>-->
+            <formula>LOCATE(%2,%1,CAST(%3 as int))</formula>
+            <argument type='str' />
+            <argument type='str' />
+            <argument type='real' />
+        </function>
+        <function group='string' name='FIND' return-type='int'>
+            <formula>LOCATE(%2,%1,%3)</formula>
+            <argument type='str' />
+            <argument type='str' />
+            <argument type='int' />
+        </function>
+
+        <date-function name='DATEDIFF' return-type='int'>
+            <formula part='year'>(YEAR(%3) - YEAR(%2))</formula>
+            <formula part='quarter'>((YEAR(%3) - YEAR(%2)) * 4 + (QUARTER(%3) - QUARTER(%2)))</formula>
+            <formula part='month'>((YEAR(%3) - YEAR(%2)) * 12 + (MONTH(%3) - MONTH(%2)))</formula>
+            <formula part='dayofyear'>(TO_DAYS(%3) - TO_DAYS(%2))</formula>
+            <formula part='day'>(TO_DAYS(%3) - TO_DAYS(%2))</formula>
+            <formula part='weekday'>(TO_DAYS(%3) - TO_DAYS(%2))</formula>
+            <formula part='week'>FLOOR(((TO_DAYS(%3) - (DAYOFWEEK(%3) - 1)) - (TO_DAYS(%2) - (DAYOFWEEK(%2) - 1)))/7)</formula>
+            <!-- 3600 as it represents seconds in an hour -->
+            <formula part='hour'>((TO_DAYS(%3) - TO_DAYS(%2)) * 24 + FLOOR(TIME_TO_SEC(%3) / 3600) - FLOOR(TIME_TO_SEC(%2) / 3600))</formula>
+            <!-- 1440 as it represents minutes in a day -->
+            <formula part='minute'>((TO_DAYS(%3) - TO_DAYS(%2)) * 1440 + FLOOR(TIME_TO_SEC(%3) / 60) - FLOOR(TIME_TO_SEC(%2) / 60))</formula>
+            <!-- 86400 as represents seconds in a day -->
+            <formula part='second'>((TO_DAYS(%3) - TO_DAYS(%2)) * 86400 + (TIME_TO_SEC(%3) - TIME_TO_SEC(%2)))</formula>
+            <argument type='localstr' />
+            <argument type='datetime' />
+            <argument type='datetime' />
+        </date-function>
+        <date-function name='DATEDIFF' return-type='int'>
+            <formula part='week'>FLOOR((( TO_DAYS(%3) - ((7 + DAYOFWEEK(%3) - 2) % 7)) - (TO_DAYS(%2) - ((7 + DAYOFWEEK(%2) - 2) % 7) ) )/7)</formula>
+            <argument type='localstr' />
+            <argument type='datetime' />
+            <argument type='datetime' />
+            <argument type='localstr' />
+        </date-function>
+        <date-function name='DATENAME' return-type='str'>
+            <formula part='year'>YEAR(%2)</formula>
+            <formula part='quarter'>QUARTER(%2)</formula>
+            <formula part='month'>MONTH(%2)</formula>
+            <formula part='dayofyear'>DAYOFYEAR(%2)</formula>
+            <formula part='day'>DAYOFMONTH(%2)</formula>
+            <formula part='weekday'>DAYNAME(%2)</formula>
+            <formula part='week'>FLOOR((7 + DAYOFYEAR(%2) - 1 + DAYOFWEEK(DATE_FORMAT(%2, '%Y-01-01 00:00:00')) - 1) / 7)</formula>
+            <formula part='hour'>HOUR(%2)</formula>
+            <formula part='minute'>MINUTE(%2)</formula>
+            <formula part='second'>SECOND(%2)</formula>
+            <argument type='localstr' />
+            <argument type='datetime' />
+        </date-function>
+        <date-function name='DATENAME' return-type='str'>
+            <formula part='week'>FLOOR((7 + DAYOFYEAR(%2) - 1 + ((7 + DAYOFWEEK(DATE_FORMAT(%2, '%Y-01-01 00:00:00')) - 2) % 7) ) / 7)</formula>
+            <argument type='localstr' />
+            <argument type='datetime' />
+            <argument type='localstr' />
+       </date-function>
+       <date-function name='DATETRUNC' return-type='datetime'>
+            <formula part='year'>DATE_FORMAT( %2, &apos;%Y-01-01 00:00:00&apos; )</formula>
+            <formula part='quarter'>CONCAT(DATE_FORMAT(%2, '%Y-'), CONCAT(CAST((3*(QUARTER(%2)-1)+1) AS STRING), '-01 00:00:00'))</formula>
+            <formula part='month'>DATE_FORMAT( %2, &apos;%Y-%m-01 00:00:00&apos; )</formula>
+            <formula part='dayofyear'>DATE_FORMAT( %2, &apos;%Y-%m-%d 00:00:00&apos; )</formula>
+            <formula part='day'>DATE_FORMAT( %2, &apos;%Y-%m-%d 00:00:00&apos; )</formula>
+            <formula part='weekday'>DATE_FORMAT( %2, &apos;%Y-%m-%d 00:00:00&apos; )</formula>
+            <formula part='week'>FROM_DAYS( TO_DAYS(%2) - (DAYOFWEEK(%2) - 1))</formula>
+            <formula part='hour'>DATE_FORMAT( %2, &apos;%Y-%m-%d %H:00:00&apos; )</formula>
+            <formula part='minute'>DATE_FORMAT( %2, &apos;%Y-%m-%d %H:%i:00&apos; )</formula>
+            <formula part='second'>DATE_FORMAT( %2, &apos;%Y-%m-%d %H:%i:%s&apos; )</formula>
+            <argument type='localstr' />
+            <argument type='datetime' />
+        </date-function>
+        <date-function name='DATETRUNC' return-type='datetime'>
+            <formula part='week'>FROM_DAYS( TO_DAYS(%2) - ((7 + DAYOFWEEK(%2) - 2) % 7) )</formula>
+            <argument type='localstr' />
+            <argument type='datetime' />
+            <argument type='localstr' />
+        </date-function>
+
+        <remove-function name='FINDNTH'>
+            <argument type='str' />
+            <argument type='str' />
+            <argument type='real' />        
+        </remove-function>
+
+        <remove-function name='DATEPARSE'>
+            <argument type='localstr' />
+            <argument type='str' />
+        </remove-function>
+        <remove-function name='ISDATE'>
+            <argument type='str' />
+        </remove-function>
+
+        <remove-function name='USEC_TO_TIMESTAMP'>
+            <argument type='int' />
+        </remove-function>
+
+        <remove-function name='TIMESTAMP_TO_USEC'>
+            <argument type='datetime' />
+        </remove-function>
+
+        <remove-function name='MAX'>
+            <argument type='str' />
+        </remove-function>
+        <remove-function name='MAX'>
+            <argument type='str' />
+            <argument type='str' />
+        </remove-function>
+
+        <remove-function name='SPACE'>
+            <argument type='int' />
+        </remove-function>
+
+        <remove-function name='MIN'>
+            <argument type='str' />
+        </remove-function>
+        <remove-function name='MIN'>
+            <argument type='str' />
+            <argument type='str' />
+        </remove-function>
+   </function-map>
+</dialect>
diff --git a/sql-jdbc/src/TableauConnector/opensearch_sql_jdbc/manifest.xml b/sql-jdbc/src/TableauConnector/opensearch_sql_jdbc/manifest.xml
new file mode 100644
index 00000000000..20c99b96be0
--- /dev/null
+++ b/sql-jdbc/src/TableauConnector/opensearch_sql_jdbc/manifest.xml
@@ -0,0 +1,53 @@
+<?xml version='1.0' encoding='utf-8' ?>
+
+<connector-plugin class='opensearch_jdbc' superclass='jdbc' plugin-version='1.1.0.0' name='OpenSearch' version='18.1' min-version-tableau='2021.1'>
+  <vendor-information>
+      <company name="OpenSearch for ES"/>
+      <support-link url="https://github.com/opensearch-project/sql"/>
+  </vendor-information>
+  <connection-customization class="opensearch_jdbc" enabled="true" version="10.0">
+    <vendor name="OpenSearch JDBC"/>
+    <driver name="SQL"/>
+    <customizations>
+      <customization name="CAP_CREATE_TEMP_TABLES" value="no"/>
+      <customization name="CAP_SUPPRESS_DISCOVERY_QUERIES" value="yes" />
+      <customization name="CAP_SELECT_INTO" value="no"/>
+      <customization name="CAP_SELECT_TOP_INTO" value="no"/>
+      <customization name="CAP_QUERY_BOOLEXPR_TO_INTEXPR" value="yes"/>
+      <customization name="CAP_QUERY_GROUP_BY_ALIAS" value="yes"/>
+      <customization name="CAP_QUERY_GROUP_BY_BOOL" value="yes"/>
+      <customization name="CAP_QUERY_GROUP_BY_DEGREE" value="no"/>
+      <customization name="CAP_QUERY_SORT_BY" value="yes"/>
+      <customization name="CAP_QUERY_SUBQUERIES" value="yes"/>
+      <customization name="CAP_QUERY_TOP_N" value="no"/>
+      <customization name="CAP_QUERY_SUPPORT_EMPTY_GROUPBY" value="no"/>
+      <customization name="CAP_QUERY_WHERE_FALSE_METADATA" value="yes"/>
+      <customization name="CAP_QUERY_SUBQUERIES_WITH_TOP" value="yes"/>
+      <customization name="CAP_SUPPORTS_SPLIT_FROM_LEFT" value="yes"/>
+      <customization name="CAP_SUPPORTS_SPLIT_FROM_RIGHT" value="yes"/>
+      <customization name="CAP_QUERY_ALLOW_PARTIAL_AGGREGATION" value="no"/>
+      <customization name="CAP_QUERY_TIME_REQUIRES_CAST" value="yes"/>
+      <customization name="CAP_JDBC_METADATA_USE_RESULTSET_FOR_TABLE" value="yes"/>
+      <customization name="CAP_JDBC_METADATA_GET_INDEX_INFO" value="no"/>
+      <customization name="CAP_JDBC_METADATA_IGNORE_NULLABILITY" value="yes"/>
+      <customization name="CAP_JDBC_METADATA_READ_FOREIGNKEYS" value="no"/>
+      <customization name="CAP_JDBC_METADATA_READ_PRIMARYKEYS" value="no"/>
+      <customization name="CAP_JDBC_SUPPRESS_ENUMERATE_DATABASES" value="yes"/>
+      <customization name="CAP_JDBC_SUPPRESS_ENUMERATE_SCHEMAS" value="yes"/>
+      <!-- OpenSearch SQL can't proceed queries longer than ~1.5k. This setting could help to avoid this limitation. It limits the max length of the string, not of the query. -->
+      <customization name="CAP_JDBC_MAX_STRING_LENGTH_MEDIUM" value="yes"/>
+      <customization name="CAP_CONNECT_STORED_PROCEDURE" value="no"/>
+      <customization name="CAP_SUPPORTS_UNION" value="no"/>
+      <!-- 
+      CAP_SUPPRESS_GET_SERVER_TIME will fix the error while creating extract in tableau.
+      This can be removed when OpenSearch supports query without FROM clause.
+      For smore details: https://community.tableau.com/message/1092123?et=watches.email.thread#1092123
+      -->
+      <customization name="CAP_SUPPRESS_GET_SERVER_TIME" value="yes"/>
+    </customizations>
+  </connection-customization>
+  <connection-fields file="connection-fields.xml" />
+  <connection-metadata file='connection-metadata.xml'/>
+  <connection-resolver file="connectionResolver.tdr"/>
+  <dialect file='dialect.tdd'/>
+</connector-plugin>
diff --git a/sql-jdbc/src/TableauConnector/opensearch_sql_jdbc/opensearch_sql_jdbc_dev.taco b/sql-jdbc/src/TableauConnector/opensearch_sql_jdbc/opensearch_sql_jdbc_dev.taco
new file mode 100644
index 0000000000000000000000000000000000000000..590a4ba3885a92283c35fbc65b7785be5b64837b
GIT binary patch
literal 5259
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
H902e?FS9+r

literal 0
HcmV?d00001


From 952ff012124d97244e1404b82976122adec4289b Mon Sep 17 00:00:00 2001
From: Guian Gumpac <guiang@bitquilltech.com>
Date: Thu, 18 Nov 2021 09:37:41 -0800
Subject: [PATCH 02/28] Added CEILING and FLOOR functions

Signed-off-by: Guian Gumpac <guiang@bitquilltech.com>
---
 .../src/TableauConnector/opensearch_sql_jdbc/dialect.tdd  | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/sql-jdbc/src/TableauConnector/opensearch_sql_jdbc/dialect.tdd b/sql-jdbc/src/TableauConnector/opensearch_sql_jdbc/dialect.tdd
index f33f42444e5..73cc10a08cb 100644
--- a/sql-jdbc/src/TableauConnector/opensearch_sql_jdbc/dialect.tdd
+++ b/sql-jdbc/src/TableauConnector/opensearch_sql_jdbc/dialect.tdd
@@ -174,6 +174,14 @@
             <argument type='datetime' />
             <argument type='datetime' />
         </function>
+        <function group='numeric' name='CEILING' return-type='int'>
+            <formula>CEIL(%1)</formula>
+            <argument type='real' />
+        </function>
+        <function group='numeric' name='FLOOR' return-type='int'>
+            <formula>FLOOR(%1)</formula>
+            <argument type='real' />
+        </function>
     
         <function group='date' name='DAYOFYEAR' return-type='int'>
             <formula>DAY_OF_YEAR(%1)</formula>

From 580e1affc3440bb10dfca6813b8ebe1b943b2bee Mon Sep 17 00:00:00 2001
From: Guian Gumpac <guiang@bitquilltech.com>
Date: Thu, 18 Nov 2021 10:52:07 -0800
Subject: [PATCH 03/28] Added IFNULL function

Signed-off-by: Guian Gumpac <guiang@bitquilltech.com>
---
 .../src/TableauConnector/opensearch_sql_jdbc/dialect.tdd    | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/sql-jdbc/src/TableauConnector/opensearch_sql_jdbc/dialect.tdd b/sql-jdbc/src/TableauConnector/opensearch_sql_jdbc/dialect.tdd
index 73cc10a08cb..ebf73c7eff4 100644
--- a/sql-jdbc/src/TableauConnector/opensearch_sql_jdbc/dialect.tdd
+++ b/sql-jdbc/src/TableauConnector/opensearch_sql_jdbc/dialect.tdd
@@ -33,6 +33,12 @@
             <argument type='datetime' />
         </function>
 
+        <function group='logical' name='IFNULL' return-type='datetime'>
+            <formula>CASE WHEN ISNULL(%1) THEN CAST(DATE_FORMAT(%2, &apos;%Y-%m-%d 00:00:00&apos;) AS TIMESTAMP) ELSE %1 END</formula>
+            <argument type='datetime' />
+            <argument type='date' />
+        </function>
+
         <function group='operator' name='!=' return-type='bool'>
             <formula>(%1 AND NOT %2 OR NOT %1 AND %2)</formula>
             <argument type='bool' />

From a4d2c0c7e6207ea9f7e0557aded792470db1ff83 Mon Sep 17 00:00:00 2001
From: Guian Gumpac <guiang@bitquilltech.com>
Date: Thu, 18 Nov 2021 15:17:11 -0800
Subject: [PATCH 04/28] Added Kyle's fix for ADDDATE and SUBDATE with resulting
 00:00:00 being unexpectedly null

Signed-off-by: Guian Gumpac <guiang@bitquilltech.com>
---
 .../org/opensearch/jdbc/types/TimestampType.java    | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/sql-jdbc/src/main/java/org/opensearch/jdbc/types/TimestampType.java b/sql-jdbc/src/main/java/org/opensearch/jdbc/types/TimestampType.java
index 3ae9463ea41..3f80eff0c71 100644
--- a/sql-jdbc/src/main/java/org/opensearch/jdbc/types/TimestampType.java
+++ b/sql-jdbc/src/main/java/org/opensearch/jdbc/types/TimestampType.java
@@ -8,6 +8,7 @@
 
 import java.sql.SQLException;
 import java.sql.Timestamp;
+import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.util.Calendar;
 import java.util.Map;
@@ -78,13 +79,17 @@ else if (value.charAt(23) == '+' || value.charAt(23) == '-') {
                 }
             }
 
-            if (calendar == null) {
-                return Timestamp.valueOf(value);
+            final Timestamp ts;
+            if (value.length() < 11) {
+                ts = Timestamp.valueOf(LocalDate.parse(value).atStartOfDay());
             } else {
-                Timestamp ts = Timestamp.valueOf(value);
-                return localDateTimeToTimestamp(ts.toLocalDateTime(), calendar);
+                ts = Timestamp.valueOf(value);
             }
 
+            if (calendar == null) {
+                return ts;
+            }
+            return localDateTimeToTimestamp(ts.toLocalDateTime(), calendar);
         } catch (IllegalArgumentException iae) {
             throw stringConversionException(value, iae);
         }

From 10aba05b3d0949e0cb7c6d9f93445a6383a0151c Mon Sep 17 00:00:00 2001
From: Guian Gumpac <guiang@bitquilltech.com>
Date: Thu, 18 Nov 2021 15:41:08 -0800
Subject: [PATCH 05/28] Added MIN and MAX for two string arguments

Signed-off-by: Guian Gumpac <guiang@bitquilltech.com>
---
 .../opensearch_sql_jdbc/dialect.tdd           | 32 +++++++++----------
 1 file changed, 16 insertions(+), 16 deletions(-)

diff --git a/sql-jdbc/src/TableauConnector/opensearch_sql_jdbc/dialect.tdd b/sql-jdbc/src/TableauConnector/opensearch_sql_jdbc/dialect.tdd
index ebf73c7eff4..406a639dbb2 100644
--- a/sql-jdbc/src/TableauConnector/opensearch_sql_jdbc/dialect.tdd
+++ b/sql-jdbc/src/TableauConnector/opensearch_sql_jdbc/dialect.tdd
@@ -156,6 +156,14 @@
             <argument type='datetime' />
             <argument type='datetime' />
         </function>
+        <function group='numeric' name='MAX' return-type='str'>
+            <formula>CASE WHEN ISNULL(%1) THEN NULL
+                WHEN ISNULL(%2) THEN NULL
+	            WHEN %1 &gt; %2 THEN %1
+                ELSE %2 END</formula>
+            <argument type='str' />
+            <argument type='str' />
+        </function>
         <function group='numeric' name='MIN' return-type='int'>
             <formula>CASE WHEN ISNULL(%1) THEN NULL
                 WHEN ISNULL(%2) THEN NULL
@@ -180,6 +188,14 @@
             <argument type='datetime' />
             <argument type='datetime' />
         </function>
+        <function group='numeric' name='MIN' return-type='str'>
+            <formula>CASE WHEN ISNULL(%1) THEN NULL
+                WHEN ISNULL(%2) THEN NULL
+	            WHEN %1 &lt; %2 THEN %1
+                ELSE %2 END</formula>
+            <argument type='str' />
+            <argument type='str' />
+        </function>
         <function group='numeric' name='CEILING' return-type='int'>
             <formula>CEIL(%1)</formula>
             <argument type='real' />
@@ -340,24 +356,8 @@
             <argument type='datetime' />
         </remove-function>
 
-        <remove-function name='MAX'>
-            <argument type='str' />
-        </remove-function>
-        <remove-function name='MAX'>
-            <argument type='str' />
-            <argument type='str' />
-        </remove-function>
-
         <remove-function name='SPACE'>
             <argument type='int' />
         </remove-function>
-
-        <remove-function name='MIN'>
-            <argument type='str' />
-        </remove-function>
-        <remove-function name='MIN'>
-            <argument type='str' />
-            <argument type='str' />
-        </remove-function>
    </function-map>
 </dialect>

From fa32866aa98a673c86f5d682a3a711f1db204e27 Mon Sep 17 00:00:00 2001
From: Yury Fridlyand <yuryf@bitquilltech.com>
Date: Thu, 18 Nov 2021 19:40:24 -0800
Subject: [PATCH 06/28] Fixed return type for MID function redefenitions, part
 of AOS-202

Signed-off-by: Yury Fridlyand <yuryf@bitquilltech.com>
---
 .../TableauConnector/opensearch_sql_jdbc/dialect.tdd | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/sql-jdbc/src/TableauConnector/opensearch_sql_jdbc/dialect.tdd b/sql-jdbc/src/TableauConnector/opensearch_sql_jdbc/dialect.tdd
index 73cc10a08cb..2b20aa37c8e 100644
--- a/sql-jdbc/src/TableauConnector/opensearch_sql_jdbc/dialect.tdd
+++ b/sql-jdbc/src/TableauConnector/opensearch_sql_jdbc/dialect.tdd
@@ -196,35 +196,35 @@
             <argument type='date' />
         </function>
 
-        <function group='string' name='MID' return-type='int'>
+        <function group='string' name='MID' return-type='str'>
             <formula>SUBSTR(%1,%2)</formula>
             <argument type='str' />
             <argument type='int' />
         </function>
-        <function group='string' name='MID' return-type='int'>
+        <function group='string' name='MID' return-type='str'>
             <formula>SUBSTR(%1,CAST(%2 as int))</formula>
             <argument type='str' />
             <argument type='real' />
         </function>
-        <function group='string' name='MID' return-type='int'>
+        <function group='string' name='MID' return-type='str'>
             <formula>SUBSTR(%1,%2,%3)</formula>
             <argument type='str' />
             <argument type='int' />
             <argument type='int' />
         </function>
-        <function group='string' name='MID' return-type='int'>
+        <function group='string' name='MID' return-type='str'>
             <formula>SUBSTR(%1,CAST(%2 as int),%3)</formula>
             <argument type='str' />
             <argument type='real' />
             <argument type='int' />
         </function>
-        <function group='string' name='MID' return-type='int'>
+        <function group='string' name='MID' return-type='str'>
             <formula>SUBSTR(%1,%2,CAST(%3 as int))</formula>
             <argument type='str' />
             <argument type='int' />
             <argument type='real' />
         </function>
-        <function group='string' name='MID' return-type='int'>
+        <function group='string' name='MID' return-type='str'>
             <formula>SUBSTR(%1,CAST(%2 as int),CAST(%3 as int))</formula>
             <argument type='str' />
             <argument type='real' />

From b852f9d4ce0f511edf270909cc76ea2f725885eb Mon Sep 17 00:00:00 2001
From: Yury Fridlyand <yuryf@bitquilltech.com>
Date: Fri, 19 Nov 2021 11:39:55 -0800
Subject: [PATCH 07/28] Added CAST functions to convert to int or string as
 part of AOS-202

Signed-off-by: Yury Fridlyand <yuryf@bitquilltech.com>
---
 .../opensearch_sql_jdbc/dialect.tdd           | 24 +++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/sql-jdbc/src/TableauConnector/opensearch_sql_jdbc/dialect.tdd b/sql-jdbc/src/TableauConnector/opensearch_sql_jdbc/dialect.tdd
index 73cc10a08cb..81708f3d050 100644
--- a/sql-jdbc/src/TableauConnector/opensearch_sql_jdbc/dialect.tdd
+++ b/sql-jdbc/src/TableauConnector/opensearch_sql_jdbc/dialect.tdd
@@ -32,6 +32,30 @@
             <formula>TO_DAYS(%1) - 693961.0</formula>
             <argument type='datetime' />
         </function>
+        <function group='cast' name='STR' return-type='str'>
+            <formula>CAST(%1 as string)</formula>
+            <argument type='real' />
+        </function>
+        <function group='cast' name='STR' return-type='str'>
+            <formula>CAST(%1 as string)</formula>
+            <argument type='int' />
+        </function>
+        <function group='cast' name='STR' return-type='str'>
+            <formula>CAST(%1 as string)</formula>
+            <argument type='date' />
+        </function>
+        <function group='cast' name='STR' return-type='str'>
+            <formula>CAST(%1 as string)</formula>
+            <argument type='bool' />
+        </function>
+        <function group='cast' name='INT' return-type='int'>
+            <formula>CAST(%1 as int)</formula>
+            <argument type='real' />
+        </function>
+        <function group='cast' name='INT' return-type='int'>
+            <formula>CAST(%1 as int)</formula>
+            <argument type='bool' />
+        </function>
 
         <function group='operator' name='!=' return-type='bool'>
             <formula>(%1 AND NOT %2 OR NOT %1 AND %2)</formula>

From 65437b203f9bcd246083959445f03aaf08d5fe7c Mon Sep 17 00:00:00 2001
From: Yury Fridlyand <yuryf@bitquilltech.com>
Date: Fri, 19 Nov 2021 17:29:38 -0800
Subject: [PATCH 08/28] Added HEXBINX and HEXBINY functions from the templace
 without any modifications

Signed-off-by: Yury Fridlyand <yuryf@bitquilltech.com>
---
 .../TableauConnector/opensearch_sql_jdbc/dialect.tdd | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/sql-jdbc/src/TableauConnector/opensearch_sql_jdbc/dialect.tdd b/sql-jdbc/src/TableauConnector/opensearch_sql_jdbc/dialect.tdd
index 73cc10a08cb..1ca6fe71826 100644
--- a/sql-jdbc/src/TableauConnector/opensearch_sql_jdbc/dialect.tdd
+++ b/sql-jdbc/src/TableauConnector/opensearch_sql_jdbc/dialect.tdd
@@ -182,7 +182,17 @@
             <formula>FLOOR(%1)</formula>
             <argument type='real' />
         </function>
-    
+        <function group='numeric' name='HEXBINX' return-type='real'>
+            <formula>(((CASE WHEN (ABS((%2) - (CAST( ( (%2) / SQRT(3.0) ) AS NUMERIC(18, 0) ) * SQRT(3.0)))) + SQRT(3.0) * ((ABS((%1) - (CAST( ( (%1) / 3.0 ) AS NUMERIC(18, 0) ) * 3.0))) - 1.0) &gt; 0.0 THEN 1.5 ELSE 0.0 END) - (CASE WHEN ((%1) - (CAST( ( (%1) / 3.0 ) AS NUMERIC(18, 0) ) * 3.0) &lt; 0.0) AND ((CASE WHEN (ABS((%2) - (CAST( ( (%2) / SQRT(3.0) ) AS NUMERIC(18, 0) ) * SQRT(3.0)))) + SQRT(3.0) * ((ABS((%1) - (CAST( ( (%1) / 3.0 ) AS NUMERIC(18, 0) ) * 3.0))) - 1.0) &gt; 0.0 THEN 1.5 ELSE 0.0 END) &gt; 0.0) THEN 3.0 ELSE 0.0 END)) + (CAST( ( (%1) / 3.0 ) AS NUMERIC(18, 0) ) * 3.0))</formula>
+            <argument type='real' />
+            <argument type='real' />
+        </function>
+        <function group='numeric' name='HEXBINY' return-type='real'>
+            <formula>CAST( (((CASE WHEN (ABS((%2) - (CAST( ( (%2) / SQRT(3.0) ) AS NUMERIC(18, 0) ) * SQRT(3.0)))) + SQRT(3.0) * ((ABS((%1) - (CAST( ( (%1) / 3.0 ) AS NUMERIC(18, 0) ) * 3.0))) - 1.0) &gt; 0.0 THEN SQRT(3.0) / 2.0 ELSE 0.0 END) - (CASE WHEN ((%2) - (CAST( ( (%2) / SQRT(3.0) ) AS NUMERIC(18, 0) ) * SQRT(3.0)) &lt; 0.0) AND ((CASE WHEN (ABS((%2) - (CAST( ( (%2) / SQRT(3.0) ) AS NUMERIC(18, 0) ) * SQRT(3.0)))) + SQRT(3.0) * ((ABS((%1) - (CAST( ( (%1) / 3.0 ) AS NUMERIC(18, 0) ) * 3.0))) - 1.0) &gt; 0.0 THEN SQRT(3.0) / 2.0 ELSE 0.0 END) &gt; 0.0) THEN SQRT(3.0) ELSE 0.0 END)) + (CAST( ( (%2) / SQRT(3.0) ) AS NUMERIC(18, 0) ) * SQRT(3.0))) AS NUMERIC(18,3) )</formula>
+            <argument type='real' />
+            <argument type='real' />
+        </function>
+
         <function group='date' name='DAYOFYEAR' return-type='int'>
             <formula>DAY_OF_YEAR(%1)</formula>
             <argument type='date' />

From 2e50a43b339f4b0f92feea29e162047ebdcfca36 Mon Sep 17 00:00:00 2001
From: Yury Fridlyand <yuryf@bitquilltech.com>
Date: Fri, 19 Nov 2021 17:35:22 -0800
Subject: [PATCH 09/28] Fixed cast to use the OSSQL type

Signed-off-by: Yury Fridlyand <yuryf@bitquilltech.com>
---
 sql-jdbc/src/TableauConnector/opensearch_sql_jdbc/dialect.tdd | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/sql-jdbc/src/TableauConnector/opensearch_sql_jdbc/dialect.tdd b/sql-jdbc/src/TableauConnector/opensearch_sql_jdbc/dialect.tdd
index 1ca6fe71826..599664b3901 100644
--- a/sql-jdbc/src/TableauConnector/opensearch_sql_jdbc/dialect.tdd
+++ b/sql-jdbc/src/TableauConnector/opensearch_sql_jdbc/dialect.tdd
@@ -183,12 +183,12 @@
             <argument type='real' />
         </function>
         <function group='numeric' name='HEXBINX' return-type='real'>
-            <formula>(((CASE WHEN (ABS((%2) - (CAST( ( (%2) / SQRT(3.0) ) AS NUMERIC(18, 0) ) * SQRT(3.0)))) + SQRT(3.0) * ((ABS((%1) - (CAST( ( (%1) / 3.0 ) AS NUMERIC(18, 0) ) * 3.0))) - 1.0) &gt; 0.0 THEN 1.5 ELSE 0.0 END) - (CASE WHEN ((%1) - (CAST( ( (%1) / 3.0 ) AS NUMERIC(18, 0) ) * 3.0) &lt; 0.0) AND ((CASE WHEN (ABS((%2) - (CAST( ( (%2) / SQRT(3.0) ) AS NUMERIC(18, 0) ) * SQRT(3.0)))) + SQRT(3.0) * ((ABS((%1) - (CAST( ( (%1) / 3.0 ) AS NUMERIC(18, 0) ) * 3.0))) - 1.0) &gt; 0.0 THEN 1.5 ELSE 0.0 END) &gt; 0.0) THEN 3.0 ELSE 0.0 END)) + (CAST( ( (%1) / 3.0 ) AS NUMERIC(18, 0) ) * 3.0))</formula>
+            <formula>(((CASE WHEN (ABS((%2) - (CAST( ( (%2) / SQRT(3.0) ) AS INT ) * SQRT(3.0)))) + SQRT(3.0) * ((ABS((%1) - (CAST( ( (%1) / 3.0 ) AS INT ) * 3.0))) - 1.0) &gt; 0.0 THEN 1.5 ELSE 0.0 END) - (CASE WHEN ((%1) - (CAST( ( (%1) / 3.0 ) AS INT ) * 3.0) &lt; 0.0) AND ((CASE WHEN (ABS((%2) - (CAST( ( (%2) / SQRT(3.0) ) AS INT ) * SQRT(3.0)))) + SQRT(3.0) * ((ABS((%1) - (CAST( ( (%1) / 3.0 ) AS INT ) * 3.0))) - 1.0) &gt; 0.0 THEN 1.5 ELSE 0.0 END) &gt; 0.0) THEN 3.0 ELSE 0.0 END)) + (CAST( ( (%1) / 3.0 ) AS INT ) * 3.0))</formula>
             <argument type='real' />
             <argument type='real' />
         </function>
         <function group='numeric' name='HEXBINY' return-type='real'>
-            <formula>CAST( (((CASE WHEN (ABS((%2) - (CAST( ( (%2) / SQRT(3.0) ) AS NUMERIC(18, 0) ) * SQRT(3.0)))) + SQRT(3.0) * ((ABS((%1) - (CAST( ( (%1) / 3.0 ) AS NUMERIC(18, 0) ) * 3.0))) - 1.0) &gt; 0.0 THEN SQRT(3.0) / 2.0 ELSE 0.0 END) - (CASE WHEN ((%2) - (CAST( ( (%2) / SQRT(3.0) ) AS NUMERIC(18, 0) ) * SQRT(3.0)) &lt; 0.0) AND ((CASE WHEN (ABS((%2) - (CAST( ( (%2) / SQRT(3.0) ) AS NUMERIC(18, 0) ) * SQRT(3.0)))) + SQRT(3.0) * ((ABS((%1) - (CAST( ( (%1) / 3.0 ) AS NUMERIC(18, 0) ) * 3.0))) - 1.0) &gt; 0.0 THEN SQRT(3.0) / 2.0 ELSE 0.0 END) &gt; 0.0) THEN SQRT(3.0) ELSE 0.0 END)) + (CAST( ( (%2) / SQRT(3.0) ) AS NUMERIC(18, 0) ) * SQRT(3.0))) AS NUMERIC(18,3) )</formula>
+            <formula>CAST( (((CASE WHEN (ABS((%2) - (CAST( ( (%2) / SQRT(3.0) ) AS INT ) * SQRT(3.0)))) + SQRT(3.0) * ((ABS((%1) - (CAST( ( (%1) / 3.0 ) AS INT ) * 3.0))) - 1.0) &gt; 0.0 THEN SQRT(3.0) / 2.0 ELSE 0.0 END) - (CASE WHEN ((%2) - (CAST( ( (%2) / SQRT(3.0) ) AS INT ) * SQRT(3.0)) &lt; 0.0) AND ((CASE WHEN (ABS((%2) - (CAST( ( (%2) / SQRT(3.0) ) AS INT ) * SQRT(3.0)))) + SQRT(3.0) * ((ABS((%1) - (CAST( ( (%1) / 3.0 ) AS INT ) * 3.0))) - 1.0) &gt; 0.0 THEN SQRT(3.0) / 2.0 ELSE 0.0 END) &gt; 0.0) THEN SQRT(3.0) ELSE 0.0 END)) + (CAST( ( (%2) / SQRT(3.0) ) AS INT ) * SQRT(3.0))) AS NUMERIC(18,3) )</formula>
             <argument type='real' />
             <argument type='real' />
         </function>

From 177d132ef0a5a3a7f291faa61e1626925c482163 Mon Sep 17 00:00:00 2001
From: Yury Fridlyand <yuryf@bitquilltech.com>
Date: Fri, 19 Nov 2021 17:37:09 -0800
Subject: [PATCH 10/28] Added parenthesis to avoid
 opensearch-project/sql/issues/293

Signed-off-by: Yury Fridlyand <yuryf@bitquilltech.com>
---
 sql-jdbc/src/TableauConnector/opensearch_sql_jdbc/dialect.tdd | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/sql-jdbc/src/TableauConnector/opensearch_sql_jdbc/dialect.tdd b/sql-jdbc/src/TableauConnector/opensearch_sql_jdbc/dialect.tdd
index 599664b3901..107b0fcfed4 100644
--- a/sql-jdbc/src/TableauConnector/opensearch_sql_jdbc/dialect.tdd
+++ b/sql-jdbc/src/TableauConnector/opensearch_sql_jdbc/dialect.tdd
@@ -183,12 +183,12 @@
             <argument type='real' />
         </function>
         <function group='numeric' name='HEXBINX' return-type='real'>
-            <formula>(((CASE WHEN (ABS((%2) - (CAST( ( (%2) / SQRT(3.0) ) AS INT ) * SQRT(3.0)))) + SQRT(3.0) * ((ABS((%1) - (CAST( ( (%1) / 3.0 ) AS INT ) * 3.0))) - 1.0) &gt; 0.0 THEN 1.5 ELSE 0.0 END) - (CASE WHEN ((%1) - (CAST( ( (%1) / 3.0 ) AS INT ) * 3.0) &lt; 0.0) AND ((CASE WHEN (ABS((%2) - (CAST( ( (%2) / SQRT(3.0) ) AS INT ) * SQRT(3.0)))) + SQRT(3.0) * ((ABS((%1) - (CAST( ( (%1) / 3.0 ) AS INT ) * 3.0))) - 1.0) &gt; 0.0 THEN 1.5 ELSE 0.0 END) &gt; 0.0) THEN 3.0 ELSE 0.0 END)) + (CAST( ( (%1) / 3.0 ) AS INT ) * 3.0))</formula>
+            <formula>(((CASE WHEN (ABS((%2) - (CAST( ( (%2) / SQRT(3.0) ) AS INT ) * SQRT(3.0)))) + (SQRT(3.0) * ((ABS((%1) - (CAST( ( (%1) / 3.0 ) AS INT ) * 3.0))) - 1.0)) &gt; 0.0 THEN 1.5 ELSE 0.0 END) - (CASE WHEN ((%1) - (CAST( ( (%1) / 3.0 ) AS INT ) * 3.0) &lt; 0.0) AND ((CASE WHEN (ABS((%2) - (CAST( ( (%2) / SQRT(3.0) ) AS INT ) * SQRT(3.0)))) + (SQRT(3.0) * ((ABS((%1) - (CAST( ( (%1) / 3.0 ) AS INT ) * 3.0))) - 1.0)) &gt; 0.0 THEN 1.5 ELSE 0.0 END) &gt; 0.0) THEN 3.0 ELSE 0.0 END)) + (CAST( ( (%1) / 3.0 ) AS INT ) * 3.0))</formula>
             <argument type='real' />
             <argument type='real' />
         </function>
         <function group='numeric' name='HEXBINY' return-type='real'>
-            <formula>CAST( (((CASE WHEN (ABS((%2) - (CAST( ( (%2) / SQRT(3.0) ) AS INT ) * SQRT(3.0)))) + SQRT(3.0) * ((ABS((%1) - (CAST( ( (%1) / 3.0 ) AS INT ) * 3.0))) - 1.0) &gt; 0.0 THEN SQRT(3.0) / 2.0 ELSE 0.0 END) - (CASE WHEN ((%2) - (CAST( ( (%2) / SQRT(3.0) ) AS INT ) * SQRT(3.0)) &lt; 0.0) AND ((CASE WHEN (ABS((%2) - (CAST( ( (%2) / SQRT(3.0) ) AS INT ) * SQRT(3.0)))) + SQRT(3.0) * ((ABS((%1) - (CAST( ( (%1) / 3.0 ) AS INT ) * 3.0))) - 1.0) &gt; 0.0 THEN SQRT(3.0) / 2.0 ELSE 0.0 END) &gt; 0.0) THEN SQRT(3.0) ELSE 0.0 END)) + (CAST( ( (%2) / SQRT(3.0) ) AS INT ) * SQRT(3.0))) AS NUMERIC(18,3) )</formula>
+            <formula>ROUND( (((CASE WHEN (ABS((%2) - (ROUND( ( (%2) / SQRT(3.0) ), 0 ) * SQRT(3.0)))) + (SQRT(3.0) * ((ABS((%1) - (ROUND( ( (%1) / 3.0 ), 0 ) * 3.0))) - 1.0)) &gt; 0.0 THEN SQRT(3.0) / 2.0 ELSE 0.0 END) - (CASE WHEN ((%2) - (ROUND( ( (%2) / SQRT(3.0) ), 0 ) * SQRT(3.0)) &lt; 0.0) AND ((CASE WHEN (ABS((%2) - (ROUND( ( (%2) / SQRT(3.0) ), 0 ) * SQRT(3.0)))) + (SQRT(3.0) * ((ABS((%1) - (ROUND( ( (%1) / 3.0 ), 0 ) * 3.0))) - 1.0)) &gt; 0.0 THEN SQRT(3.0) / 2.0 ELSE 0.0 END) &gt; 0.0) THEN SQRT(3.0) ELSE 0.0 END)) + (ROUND( ( (%2) / SQRT(3.0) ), 0 ) * SQRT(3.0))), 3)</formula>
             <argument type='real' />
             <argument type='real' />
         </function>

From f212e35b7acb025421073b6f3117490a015e1838 Mon Sep 17 00:00:00 2001
From: Guian Gumpac <guiang@bitquilltech.com>
Date: Mon, 22 Nov 2021 12:18:51 -0800
Subject: [PATCH 11/28] Modified Timestamp conversion formula

Signed-off-by: Guian Gumpac <guiang@bitquilltech.com>
---
 sql-jdbc/src/TableauConnector/opensearch_sql_jdbc/dialect.tdd | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/sql-jdbc/src/TableauConnector/opensearch_sql_jdbc/dialect.tdd b/sql-jdbc/src/TableauConnector/opensearch_sql_jdbc/dialect.tdd
index 406a639dbb2..e85feb33ab1 100644
--- a/sql-jdbc/src/TableauConnector/opensearch_sql_jdbc/dialect.tdd
+++ b/sql-jdbc/src/TableauConnector/opensearch_sql_jdbc/dialect.tdd
@@ -34,7 +34,7 @@
         </function>
 
         <function group='logical' name='IFNULL' return-type='datetime'>
-            <formula>CASE WHEN ISNULL(%1) THEN CAST(DATE_FORMAT(%2, &apos;%Y-%m-%d 00:00:00&apos;) AS TIMESTAMP) ELSE %1 END</formula>
+            <formula>CASE WHEN ISNULL(%1) THEN SUBDATE(TIMESTAMP(%2), INTERVAL HOUR(TIMESTAMP(%2)) HOUR) ELSE %1 END</formula>
             <argument type='datetime' />
             <argument type='date' />
         </function>

From 385a41bb6d9d54b85524b5d4c0ea20393962c5f3 Mon Sep 17 00:00:00 2001
From: Guian Gumpac <guiang@bitquilltech.com>
Date: Tue, 23 Nov 2021 11:10:37 -0800
Subject: [PATCH 12/28] Added comment to TimestampType

Signed-off-by: Guian Gumpac <guiang@bitquilltech.com>
---
 .../src/main/java/org/opensearch/jdbc/types/TimestampType.java   | 1 +
 1 file changed, 1 insertion(+)

diff --git a/sql-jdbc/src/main/java/org/opensearch/jdbc/types/TimestampType.java b/sql-jdbc/src/main/java/org/opensearch/jdbc/types/TimestampType.java
index 3f80eff0c71..4dcd94ae74f 100644
--- a/sql-jdbc/src/main/java/org/opensearch/jdbc/types/TimestampType.java
+++ b/sql-jdbc/src/main/java/org/opensearch/jdbc/types/TimestampType.java
@@ -80,6 +80,7 @@ else if (value.charAt(23) == '+' || value.charAt(23) == '-') {
             }
 
             final Timestamp ts;
+            // 11 to check if the value is in yyyy-MM-dd format
             if (value.length() < 11) {
                 ts = Timestamp.valueOf(LocalDate.parse(value).atStartOfDay());
             } else {

From 26dbb7e6bd0bb781429a34256d4613f1efd49902 Mon Sep 17 00:00:00 2001
From: Yury Fridlyand <yuryf@bitquilltech.com>
Date: Tue, 23 Nov 2021 15:40:39 -0800
Subject: [PATCH 13/28] Updated Company Name accroding to the customer's
 request

Signed-off-by: Yury Fridlyand <yuryf@bitquilltech.com>
---
 sql-jdbc/src/TableauConnector/opensearch_sql_jdbc/manifest.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/sql-jdbc/src/TableauConnector/opensearch_sql_jdbc/manifest.xml b/sql-jdbc/src/TableauConnector/opensearch_sql_jdbc/manifest.xml
index 20c99b96be0..45bacf0ac85 100644
--- a/sql-jdbc/src/TableauConnector/opensearch_sql_jdbc/manifest.xml
+++ b/sql-jdbc/src/TableauConnector/opensearch_sql_jdbc/manifest.xml
@@ -2,7 +2,7 @@
 
 <connector-plugin class='opensearch_jdbc' superclass='jdbc' plugin-version='1.1.0.0' name='OpenSearch' version='18.1' min-version-tableau='2021.1'>
   <vendor-information>
-      <company name="OpenSearch for ES"/>
+      <company name="OpenSearch Project"/>
       <support-link url="https://github.com/opensearch-project/sql"/>
   </vendor-information>
   <connection-customization class="opensearch_jdbc" enabled="true" version="10.0">

From 4c63b64e3988dfe6a61a43c844a93d92b7286037 Mon Sep 17 00:00:00 2001
From: Yury Fridlyand <yuryf@bitquilltech.com>
Date: Wed, 24 Nov 2021 11:41:12 -0800
Subject: [PATCH 14/28] Updated Vendor Name as well

Signed-off-by: Yury Fridlyand <yuryf@bitquilltech.com>
---
 sql-jdbc/src/TableauConnector/opensearch_sql_jdbc/manifest.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/sql-jdbc/src/TableauConnector/opensearch_sql_jdbc/manifest.xml b/sql-jdbc/src/TableauConnector/opensearch_sql_jdbc/manifest.xml
index 45bacf0ac85..55c64830b97 100644
--- a/sql-jdbc/src/TableauConnector/opensearch_sql_jdbc/manifest.xml
+++ b/sql-jdbc/src/TableauConnector/opensearch_sql_jdbc/manifest.xml
@@ -6,7 +6,7 @@
       <support-link url="https://github.com/opensearch-project/sql"/>
   </vendor-information>
   <connection-customization class="opensearch_jdbc" enabled="true" version="10.0">
-    <vendor name="OpenSearch JDBC"/>
+    <vendor name="OpenSearch Project"/>
     <driver name="SQL"/>
     <customizations>
       <customization name="CAP_CREATE_TEMP_TABLES" value="no"/>

From 3f3fa1f85f10e643c2e73afb4d2ce7e98491b2d2 Mon Sep 17 00:00:00 2001
From: Yury Fridlyand <yuryf@bitquilltech.com>
Date: Tue, 30 Nov 2021 18:32:09 -0800
Subject: [PATCH 15/28] Added few small changes to simplify connector
 developing and debugging

Signed-off-by: Yury Fridlyand <yuryf@bitquilltech.com>
---
 .../src/PowerBIConnector/SqlOdbcPBIConnector.mproj   |  2 ++
 sql-odbc/src/PowerBIConnector/SqlOdbcPBIConnector.pq | 12 ++++++++----
 .../PowerBIConnector/SqlOdbcPBIConnector.query.pq    |  5 ++---
 3 files changed, 12 insertions(+), 7 deletions(-)

diff --git a/sql-odbc/src/PowerBIConnector/SqlOdbcPBIConnector.mproj b/sql-odbc/src/PowerBIConnector/SqlOdbcPBIConnector.mproj
index b2b177c461f..53dff961de6 100644
--- a/sql-odbc/src/PowerBIConnector/SqlOdbcPBIConnector.mproj
+++ b/sql-odbc/src/PowerBIConnector/SqlOdbcPBIConnector.mproj
@@ -98,6 +98,8 @@
             archiveOut.CreateEntryFromFile(fullPath, filename, CompressionLevel.Optimal);
         }
     }
+
+    File.Copy(OutputFile, Path.Combine(Environment.GetEnvironmentVariable("USERPROFILE"), @"Documents\Power BI Desktop\Custom Connectors", Path.GetFileName(OutputFile)), true);
 ]]></Code>
     </Task>
   </UsingTask>
diff --git a/sql-odbc/src/PowerBIConnector/SqlOdbcPBIConnector.pq b/sql-odbc/src/PowerBIConnector/SqlOdbcPBIConnector.pq
index ba10c39e494..0a4bbf09eb4 100644
--- a/sql-odbc/src/PowerBIConnector/SqlOdbcPBIConnector.pq
+++ b/sql-odbc/src/PowerBIConnector/SqlOdbcPBIConnector.pq
@@ -106,8 +106,8 @@ SqlOdbcPBIConnectorImpl = (Server as text) as table =>
             SupportsOdbcTimestampLiterals = true
         ]),
 
-        OdbcDatasource = Odbc.DataSource(ConnectionString & CredentialConnectionString & EncryptedConnectionString, [
-            // Do not view the tables grouped by their schema names.
+        OdbcOptions = [
+             // Do not view the tables grouped by their schema names.
             HierarchicalNavigation = false,
             // Prevents execution of native SQL statements. Extensions should set this to true.
             HideNativeQuery = true,
@@ -129,7 +129,11 @@ SqlOdbcPBIConnectorImpl = (Server as text) as table =>
 
             // Connection string properties used for encrypted connections.
             CredentialConnectionString = EncryptedConnectionString
-        ])
+        ],
+
+        FullConnectionString = Diagnostics.LogValue("Connection String", ConnectionString & CredentialConnectionString & EncryptedConnectionString),
+
+        OdbcDatasource = Odbc.DataSource(FullConnectionString, OdbcOptions)
     in
         OdbcDatasource;
 
@@ -206,7 +210,7 @@ SqlOdbcPBIConnector.Publish = [
     LearnMoreUrl = "https://www.opensearch.org/",
     
     // Disabling direct query due to limited SQL query support
-    SupportsDirectQuery = false,
+    SupportsDirectQuery = true,
 
     SourceImage = SqlOdbcPBIConnector.Icons,
     SourceTypeImage = SqlOdbcPBIConnector.Icons
diff --git a/sql-odbc/src/PowerBIConnector/SqlOdbcPBIConnector.query.pq b/sql-odbc/src/PowerBIConnector/SqlOdbcPBIConnector.query.pq
index bde4c98a34e..51fe5f5aae8 100644
--- a/sql-odbc/src/PowerBIConnector/SqlOdbcPBIConnector.query.pq
+++ b/sql-odbc/src/PowerBIConnector/SqlOdbcPBIConnector.query.pq
@@ -4,15 +4,14 @@ section SqlOdbcPBIConnector.UnitTests;
 shared MyExtension.UnitTest =
 [
     // Common variables for all tests
-    Host = "localhost",
-    Port = 9200,
+    Host = "localhost:9200"
 
     facts =
     {        
         Fact("Connection Test",  
              7,                                    
              let
-                Source = SqlOdbcPBIConnector.Contents(Host,Port),
+                Source = SqlOdbcPBIConnector.Contents(Host),
                 no_of_columns = Table.ColumnCount(Source)
              in
                 no_of_columns                

From 6f046dc5f19676460f9b61e230f7ef38da4b5ae6 Mon Sep 17 00:00:00 2001
From: Yury Fridlyand <yuryf@bitquilltech.com>
Date: Tue, 30 Nov 2021 18:36:22 -0800
Subject: [PATCH 16/28] Typo fix

Signed-off-by: Yury Fridlyand <yuryf@bitquilltech.com>
---
 sql-odbc/src/PowerBIConnector/SqlOdbcPBIConnector.query.pq | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/sql-odbc/src/PowerBIConnector/SqlOdbcPBIConnector.query.pq b/sql-odbc/src/PowerBIConnector/SqlOdbcPBIConnector.query.pq
index 51fe5f5aae8..8ffb05f1fd0 100644
--- a/sql-odbc/src/PowerBIConnector/SqlOdbcPBIConnector.query.pq
+++ b/sql-odbc/src/PowerBIConnector/SqlOdbcPBIConnector.query.pq
@@ -4,7 +4,7 @@ section SqlOdbcPBIConnector.UnitTests;
 shared MyExtension.UnitTest =
 [
     // Common variables for all tests
-    Host = "localhost:9200"
+    Host = "localhost:9200",
 
     facts =
     {        

From f529282674497de7a6cb1261fe5a4e229bece63f Mon Sep 17 00:00:00 2001
From: Yury Fridlyand <yuryf@bitquilltech.com>
Date: Tue, 30 Nov 2021 20:43:05 -0800
Subject: [PATCH 17/28] Added a simple test from TDVT: case bool0 from test
 calcs_data (an expression test) Some mofidication were made in the test
 framework to make the output more readable

Signed-off-by: Yury Fridlyand <yuryf@bitquilltech.com>
---
 .../SqlOdbcPBIConnector.query.pq              | 23 ++++++++++++++-----
 1 file changed, 17 insertions(+), 6 deletions(-)

diff --git a/sql-odbc/src/PowerBIConnector/SqlOdbcPBIConnector.query.pq b/sql-odbc/src/PowerBIConnector/SqlOdbcPBIConnector.query.pq
index bde4c98a34e..8352609f650 100644
--- a/sql-odbc/src/PowerBIConnector/SqlOdbcPBIConnector.query.pq
+++ b/sql-odbc/src/PowerBIConnector/SqlOdbcPBIConnector.query.pq
@@ -4,18 +4,27 @@ section SqlOdbcPBIConnector.UnitTests;
 shared MyExtension.UnitTest =
 [
     // Common variables for all tests
-    Host = "localhost",
-    Port = 9200,
+    Host = "localhost:9200",
 
     facts =
     {        
         Fact("Connection Test",  
              7,                                    
              let
-                Source = SqlOdbcPBIConnector.Contents(Host,Port),
+                Source = SqlOdbcPBIConnector.Contents(Host),
                 no_of_columns = Table.ColumnCount(Source)
              in
                 no_of_columns                
+        ),
+        Fact("calcs_data:bool0",
+            #table(type table [bool0 = logical],
+                { {null}, {false}, {true} }),
+            let
+                Source = SqlOdbcPBIConnector.Contents("localhost:9200"),
+                calcs_null_null = Source{[Item="calcs",Schema=null,Catalog=null]}[Data],
+                grouped = Table.Group(calcs_null_null, {"bool0"}, {})
+            in
+                grouped
         )
     },
 
@@ -33,11 +42,13 @@ Fact = (_subject as text, _expected, _actual) as record =>
     resultOp = if result = "Success ✓" then " = " else " <> ",
     addendumEvalAttempt = if attempt[HasError] then @ValueToText(attempt[Error]) else "",
     addendumEvalExpected = try @ValueToText(safeExpected) otherwise "...",
-    addendumEvalActual = try @ValueToText (safeActual) otherwise "...",
+    addendumEvalActual = try @ValueToText(safeActual) otherwise "...",
+    ShortenedAddendumEvalExpected = if Text.Length(addendumEvalExpected) > 20 then Text.Range(addendumEvalExpected, 0, 20) & "..." else addendumEvalExpected,
+    ShortenedAddendumEvalActual = if Text.Length(addendumEvalActual) > 20 then Text.Range(addendumEvalActual, 0, 20) & "..." else addendumEvalActual,
     fact =
-    [   Result = result &" "& addendumEvalAttempt,
+    [   Result = result & " " & addendumEvalAttempt,
         Notes =_subject,
-        Details = " ("& addendumEvalExpected & resultOp & addendumEvalActual &")"
+        Details = ShortenedAddendumEvalExpected & resultOp & ShortenedAddendumEvalActual
     ]
 ][fact];
 

From b21535742f322bbab11f898c6da7ec1dcf53d82a Mon Sep 17 00:00:00 2001
From: Guian Gumpac <guiang@bitquilltech.com>
Date: Fri, 3 Dec 2021 16:53:19 -0800
Subject: [PATCH 18/28] Modified the driver to recognize its support for
 conversion of types

Signed-off-by: Guian Gumpac <guiang@bitquilltech.com>
---
 .../PowerBIConnector/SqlOdbcPBIConnector.pq   |  2 +-
 .../SqlOdbcPBIConnector.query.pq              | 27 ++++++++++--
 sql-odbc/src/sqlodbc/info.c                   | 42 +++++++++++++++----
 3 files changed, 59 insertions(+), 12 deletions(-)

diff --git a/sql-odbc/src/PowerBIConnector/SqlOdbcPBIConnector.pq b/sql-odbc/src/PowerBIConnector/SqlOdbcPBIConnector.pq
index ba10c39e494..23655caefb7 100644
--- a/sql-odbc/src/PowerBIConnector/SqlOdbcPBIConnector.pq
+++ b/sql-odbc/src/PowerBIConnector/SqlOdbcPBIConnector.pq
@@ -206,7 +206,7 @@ SqlOdbcPBIConnector.Publish = [
     LearnMoreUrl = "https://www.opensearch.org/",
     
     // Disabling direct query due to limited SQL query support
-    SupportsDirectQuery = false,
+    SupportsDirectQuery = true,
 
     SourceImage = SqlOdbcPBIConnector.Icons,
     SourceTypeImage = SqlOdbcPBIConnector.Icons
diff --git a/sql-odbc/src/PowerBIConnector/SqlOdbcPBIConnector.query.pq b/sql-odbc/src/PowerBIConnector/SqlOdbcPBIConnector.query.pq
index bde4c98a34e..df4e0163c56 100644
--- a/sql-odbc/src/PowerBIConnector/SqlOdbcPBIConnector.query.pq
+++ b/sql-odbc/src/PowerBIConnector/SqlOdbcPBIConnector.query.pq
@@ -16,6 +16,23 @@ shared MyExtension.UnitTest =
                 no_of_columns = Table.ColumnCount(Source)
              in
                 no_of_columns                
+        ),
+        Fact("calcs_data:bool0",
+            #table(type table [bool0 = logical],
+                { {null}, {false}, {true} }),
+            let
+                Source = SqlOdbcPBIConnector.Contents("localhost:9200"),
+                calcs_null_null = Source{[Item="calcs",Schema=null,Catalog=null]}[Data],
+                grouped = Table.Group(calcs_null_null, {"bool0"}, {})
+            in
+                grouped
+        ),
+         Fact("Integer test",  
+             {1,null,null,null,7,3,8,null,null,8,4,10,null,4,11,4,8},              
+             let 
+                calcs = Source{[Item="calcs",Schema=null,Catalog=null]}[Data]
+             in
+                Table.SelectColumns(calcs, "int0")        
         )
     },
 
@@ -33,11 +50,13 @@ Fact = (_subject as text, _expected, _actual) as record =>
     resultOp = if result = "Success ✓" then " = " else " <> ",
     addendumEvalAttempt = if attempt[HasError] then @ValueToText(attempt[Error]) else "",
     addendumEvalExpected = try @ValueToText(safeExpected) otherwise "...",
-    addendumEvalActual = try @ValueToText (safeActual) otherwise "...",
+    addendumEvalActual = try @ValueToText(safeActual) otherwise "...",
+    ShortenedAddendumEvalExpected = if Text.Length(addendumEvalExpected) > 20 then Text.Range(addendumEvalExpected, 0, 20) & "..." else addendumEvalExpected,
+    ShortenedAddendumEvalActual = if Text.Length(addendumEvalActual) > 20 then Text.Range(addendumEvalActual, 0, 20) & "..." else addendumEvalActual,
     fact =
-    [   Result = result &" "& addendumEvalAttempt,
+    [   Result = result & " " & addendumEvalAttempt,
         Notes =_subject,
-        Details = " ("& addendumEvalExpected & resultOp & addendumEvalActual &")"
+        Details = ShortenedAddendumEvalExpected & resultOp & ShortenedAddendumEvalActual
     ]
 ][fact];
 
@@ -307,4 +326,4 @@ ValueToText = (value, optional depth) =>
                            if x is type         then try Serialize.Type(x) otherwise "null /*serialize failed*/"          else 
                            "[#_unable_to_serialize_#]"                     
     in
-        try Serialize(value) otherwise "<serialization failed>";
+        try Serialize(value) otherwise "<serialization failed>";
\ No newline at end of file
diff --git a/sql-odbc/src/sqlodbc/info.c b/sql-odbc/src/sqlodbc/info.c
index fc859a0d9eb..f23d3a17e1f 100644
--- a/sql-odbc/src/sqlodbc/info.c
+++ b/sql-odbc/src/sqlodbc/info.c
@@ -104,20 +104,14 @@ RETCODE SQL_API OPENSEARCHAPI_GetInfo(HDBC hdbc, SQLUSMALLINT fInfoType,
             break;
 
         case SQL_CONVERT_GUID:
-        case SQL_CONVERT_INTEGER:
         case SQL_CONVERT_SMALLINT:
         case SQL_CONVERT_TINYINT:
-        case SQL_CONVERT_BIT:
         case SQL_CONVERT_VARCHAR:
-        case SQL_CONVERT_BIGINT:
         case SQL_CONVERT_DECIMAL:
-        case SQL_CONVERT_DOUBLE:
         case SQL_CONVERT_FLOAT:
         case SQL_CONVERT_NUMERIC:
-        case SQL_CONVERT_REAL:
         case SQL_CONVERT_DATE:
         case SQL_CONVERT_TIME:
-        case SQL_CONVERT_TIMESTAMP:
         case SQL_CONVERT_BINARY:
         case SQL_CONVERT_LONGVARBINARY:
         case SQL_CONVERT_VARBINARY: /* ODBC 1.0 */
@@ -126,12 +120,46 @@ RETCODE SQL_API OPENSEARCHAPI_GetInfo(HDBC hdbc, SQLUSMALLINT fInfoType,
 #ifdef UNICODE_SUPPORT
         case SQL_CONVERT_WCHAR:
         case SQL_CONVERT_WLONGVARCHAR:
-        case SQL_CONVERT_WVARCHAR:
 #endif /* UNICODE_SUPPORT */
             len = sizeof(SQLUINTEGER);
             value = 0; /* CONVERT is unavailable */
             break;
 
+        case SQL_CONVERT_INTEGER: /* ODBC 1.0 */
+            len = sizeof(SQLUINTEGER);
+            value = SQL_CVT_BIT | SQL_CVT_WVARCHAR | SQL_CVT_DOUBLE | SQL_CVT_BIGINT | SQL_CVT_REAL;
+            break;
+
+        case SQL_CONVERT_BIT: /* ODBC 1.0 */
+            len = sizeof(SQLUINTEGER);
+            value = SQL_CVT_INTEGER | SQL_CVT_WVARCHAR | SQL_CVT_DOUBLE | SQL_CVT_BIGINT | SQL_CVT_REAL;
+            break;
+
+        case SQL_CONVERT_WVARCHAR: /* ODBC 1.0 */
+            len = sizeof(SQLUINTEGER);
+            value = SQL_CVT_INTEGER | SQL_CVT_DOUBLE | SQL_CVT_BIGINT | SQL_CVT_REAL;
+            break;
+
+        case SQL_CONVERT_DOUBLE: /* ODBC 1.0 */
+            len = sizeof(SQLUINTEGER);
+            value = SQL_CVT_INTEGER | SQL_CVT_BIT | SQL_CVT_WVARCHAR | SQL_CVT_BIGINT | SQL_CVT_REAL;
+            break;
+
+        case SQL_CONVERT_BIGINT: /* ODBC 1.0 */
+            len = sizeof(SQLUINTEGER);
+            value = SQL_CVT_INTEGER | SQL_CVT_BIT | SQL_CVT_WVARCHAR | SQL_CVT_DOUBLE | SQL_CVT_REAL;
+            break;
+
+        case SQL_CONVERT_REAL: /* ODBC 1.0 */
+            len = sizeof(SQLUINTEGER);
+            value = SQL_CVT_INTEGER | SQL_CVT_BIT | SQL_CVT_WVARCHAR | SQL_CVT_DOUBLE | SQL_CVT_BIGINT;
+            break;
+
+        case SQL_CONVERT_TIMESTAMP: /* ODBC 1.0 */
+            len = sizeof(SQLUINTEGER);
+            value = SQL_CVT_WVARCHAR;
+            break;
+
         case SQL_CONVERT_FUNCTIONS: /* ODBC 1.0 */
             len = sizeof(SQLUINTEGER);
             value = SQL_FN_CVT_CAST;

From b4f3e91840a3fbe7f5ee02ed34d9643a472e6edd Mon Sep 17 00:00:00 2001
From: Guian Gumpac <guiang@bitquilltech.com>
Date: Fri, 3 Dec 2021 16:59:04 -0800
Subject: [PATCH 19/28] Removed changes from a different branch

Signed-off-by: Guian Gumpac <guiang@bitquilltech.com>
---
 .../SqlOdbcPBIConnector.query.pq              | 27 +++----------------
 1 file changed, 4 insertions(+), 23 deletions(-)

diff --git a/sql-odbc/src/PowerBIConnector/SqlOdbcPBIConnector.query.pq b/sql-odbc/src/PowerBIConnector/SqlOdbcPBIConnector.query.pq
index df4e0163c56..192d3df7030 100644
--- a/sql-odbc/src/PowerBIConnector/SqlOdbcPBIConnector.query.pq
+++ b/sql-odbc/src/PowerBIConnector/SqlOdbcPBIConnector.query.pq
@@ -16,23 +16,6 @@ shared MyExtension.UnitTest =
                 no_of_columns = Table.ColumnCount(Source)
              in
                 no_of_columns                
-        ),
-        Fact("calcs_data:bool0",
-            #table(type table [bool0 = logical],
-                { {null}, {false}, {true} }),
-            let
-                Source = SqlOdbcPBIConnector.Contents("localhost:9200"),
-                calcs_null_null = Source{[Item="calcs",Schema=null,Catalog=null]}[Data],
-                grouped = Table.Group(calcs_null_null, {"bool0"}, {})
-            in
-                grouped
-        ),
-         Fact("Integer test",  
-             {1,null,null,null,7,3,8,null,null,8,4,10,null,4,11,4,8},              
-             let 
-                calcs = Source{[Item="calcs",Schema=null,Catalog=null]}[Data]
-             in
-                Table.SelectColumns(calcs, "int0")        
         )
     },
 
@@ -50,13 +33,11 @@ Fact = (_subject as text, _expected, _actual) as record =>
     resultOp = if result = "Success ✓" then " = " else " <> ",
     addendumEvalAttempt = if attempt[HasError] then @ValueToText(attempt[Error]) else "",
     addendumEvalExpected = try @ValueToText(safeExpected) otherwise "...",
-    addendumEvalActual = try @ValueToText(safeActual) otherwise "...",
-    ShortenedAddendumEvalExpected = if Text.Length(addendumEvalExpected) > 20 then Text.Range(addendumEvalExpected, 0, 20) & "..." else addendumEvalExpected,
-    ShortenedAddendumEvalActual = if Text.Length(addendumEvalActual) > 20 then Text.Range(addendumEvalActual, 0, 20) & "..." else addendumEvalActual,
+    addendumEvalActual = try @ValueToText (safeActual) otherwise "...",
     fact =
-    [   Result = result & " " & addendumEvalAttempt,
+    [   Result = result &" "& addendumEvalAttempt,
         Notes =_subject,
-        Details = ShortenedAddendumEvalExpected & resultOp & ShortenedAddendumEvalActual
+        Details = Details = " ("& addendumEvalExpected & resultOp & addendumEvalActual &")"
     ]
 ][fact];
 
@@ -326,4 +307,4 @@ ValueToText = (value, optional depth) =>
                            if x is type         then try Serialize.Type(x) otherwise "null /*serialize failed*/"          else 
                            "[#_unable_to_serialize_#]"                     
     in
-        try Serialize(value) otherwise "<serialization failed>";
\ No newline at end of file
+        try Serialize(value) otherwise "<serialization failed>";

From 431e01abfe66b5911b0b0b133bcbe6fda701014f Mon Sep 17 00:00:00 2001
From: Guian Gumpac <guiang@bitquilltech.com>
Date: Fri, 3 Dec 2021 17:00:05 -0800
Subject: [PATCH 20/28] Removed changes from a different branch

Signed-off-by: Guian Gumpac <guiang@bitquilltech.com>
---
 sql-odbc/src/PowerBIConnector/SqlOdbcPBIConnector.query.pq | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/sql-odbc/src/PowerBIConnector/SqlOdbcPBIConnector.query.pq b/sql-odbc/src/PowerBIConnector/SqlOdbcPBIConnector.query.pq
index 192d3df7030..bde4c98a34e 100644
--- a/sql-odbc/src/PowerBIConnector/SqlOdbcPBIConnector.query.pq
+++ b/sql-odbc/src/PowerBIConnector/SqlOdbcPBIConnector.query.pq
@@ -37,7 +37,7 @@ Fact = (_subject as text, _expected, _actual) as record =>
     fact =
     [   Result = result &" "& addendumEvalAttempt,
         Notes =_subject,
-        Details = Details = " ("& addendumEvalExpected & resultOp & addendumEvalActual &")"
+        Details = " ("& addendumEvalExpected & resultOp & addendumEvalActual &")"
     ]
 ][fact];
 

From e8dafaaddc1ee13c3bf12d29f7aae12e3488de8e Mon Sep 17 00:00:00 2001
From: Guian Gumpac <guiang@bitquilltech.com>
Date: Mon, 6 Dec 2021 11:37:28 -0800
Subject: [PATCH 21/28] Made the connector convert keyword columns to string
 columns

Signed-off-by: Guian Gumpac <guiang@bitquilltech.com>
---
 .../src/PowerBIConnector/SqlOdbcPBIConnector.pq     | 13 +++++++++++--
 1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/sql-odbc/src/PowerBIConnector/SqlOdbcPBIConnector.pq b/sql-odbc/src/PowerBIConnector/SqlOdbcPBIConnector.pq
index 23655caefb7..8edd090d657 100644
--- a/sql-odbc/src/PowerBIConnector/SqlOdbcPBIConnector.pq
+++ b/sql-odbc/src/PowerBIConnector/SqlOdbcPBIConnector.pq
@@ -69,12 +69,21 @@ SqlOdbcPBIConnectorImpl = (Server as text) as table =>
         SQLGetTypeInfo = (types) => 
             if (EnableTraceOutput <> true) then types else
             let
+                // SELECT CAST(1 AS KEYWORD) does not work for OpenSearch
+                // SELECT CAST(1 AS STRING) works for OpenSearch
+                FixTypeName = (typeName) =>
+                    if typeName = "keyword" then "string"
+                    else typeName,
+
                 // Outputting the entire table might be too large, and result in the value being truncated.
                 // We can output a row at a time instead with Table.TransformRows()
                 rows = Table.TransformRows(types, each Diagnostics.LogValue("SQLGetTypeInfo " & _[TYPE_NAME], _)),
-                toTable = Table.FromRecords(rows)
+                toTable = Table.FromRecords(rows),
+
+                // Override the type name of columns
+                modifiedColumns = Table.TransformColumns(toTable, {{"TYPE_NAME", FixTypeName}})
             in
-                Value.ReplaceType(toTable, Value.Type(types)),
+                Value.ReplaceType(modifiedColumns, Value.Type(types)),
 
         // SQLColumns is a function handler that receives the results of an ODBC call to SQLColumns().
         SQLColumns = (catalogName, schemaName, tableName, columnName, source) =>

From a22afaca79df2be232847201d3c7f339e918d3c7 Mon Sep 17 00:00:00 2001
From: Yury Fridlyand <yuryf@bitquilltech.com>
Date: Tue, 7 Dec 2021 12:01:26 -0800
Subject: [PATCH 22/28] Fix requested by PR review

Signed-off-by: Yury Fridlyand <yuryf@bitquilltech.com>
---
 sql-odbc/src/PowerBIConnector/SqlOdbcPBIConnector.query.pq | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/sql-odbc/src/PowerBIConnector/SqlOdbcPBIConnector.query.pq b/sql-odbc/src/PowerBIConnector/SqlOdbcPBIConnector.query.pq
index 8352609f650..e2254d231af 100644
--- a/sql-odbc/src/PowerBIConnector/SqlOdbcPBIConnector.query.pq
+++ b/sql-odbc/src/PowerBIConnector/SqlOdbcPBIConnector.query.pq
@@ -20,7 +20,7 @@ shared MyExtension.UnitTest =
             #table(type table [bool0 = logical],
                 { {null}, {false}, {true} }),
             let
-                Source = SqlOdbcPBIConnector.Contents("localhost:9200"),
+                Source = SqlOdbcPBIConnector.Contents(Host),
                 calcs_null_null = Source{[Item="calcs",Schema=null,Catalog=null]}[Data],
                 grouped = Table.Group(calcs_null_null, {"bool0"}, {})
             in

From 4a97b6c352672f0cae2ee276792c2b293e91aea3 Mon Sep 17 00:00:00 2001
From: Guian Gumpac <guiang@bitquilltech.com>
Date: Tue, 7 Dec 2021 15:08:39 -0800
Subject: [PATCH 23/28] Modified integration tests to reflect support for
 conversion types

Signed-off-by: Guian Gumpac <guiang@bitquilltech.com>
---
 .../ITODBCInfo/test_odbc_info.cpp             | 21 ++++++++++++-------
 sql-odbc/src/sqlodbc/info.c                   | 14 ++++++-------
 2 files changed, 21 insertions(+), 14 deletions(-)

diff --git a/sql-odbc/src/IntegrationTests/ITODBCInfo/test_odbc_info.cpp b/sql-odbc/src/IntegrationTests/ITODBCInfo/test_odbc_info.cpp
index b19660f7e53..f54333fcb83 100644
--- a/sql-odbc/src/IntegrationTests/ITODBCInfo/test_odbc_info.cpp
+++ b/sql-odbc/src/IntegrationTests/ITODBCInfo/test_odbc_info.cpp
@@ -208,20 +208,26 @@ TEST_SQL_GET_INFO_STRING(SQLCatalogName, SQL_CATALOG_NAME, L"N");
 // Conversion //
 ////////////////
 
-TEST_SQL_GET_INFO_UINT_MASK(SQLConvertInteger, SQL_CONVERT_INTEGER, 0);
+// 8409288 = 0x008050C8 = SQL_CVT_INTEGER | SQL_CVT_REAL | SQL_CVT_DOUBLE | SQL_CVT_BIT | SQL_CVT_BIGINT | SQL_CVT_WVARCHAR
+TEST_SQL_GET_INFO_UINT_MASK(SQLConvertInteger, SQL_CONVERT_INTEGER, 8409288);
 TEST_SQL_GET_INFO_UINT_MASK(SQLConvertSmallint, SQL_CONVERT_SMALLINT, 0);
 TEST_SQL_GET_INFO_UINT_MASK(SQLConvertTinyint, SQL_CONVERT_TINYINT, 0);
-TEST_SQL_GET_INFO_UINT_MASK(SQLConvertBit, SQL_CONVERT_BIT, 0);
+// 8409288 = 0x008050C8 = SQL_CVT_INTEGER | SQL_CVT_REAL | SQL_CVT_DOUBLE | SQL_CVT_BIT | SQL_CVT_BIGINT | SQL_CVT_WVARCHAR
+TEST_SQL_GET_INFO_UINT_MASK(SQLConvertBit, SQL_CONVERT_BIT, 8409288);
 TEST_SQL_GET_INFO_UINT_MASK(SQLConvertVarchar, SQL_CONVERT_VARCHAR, 0);
-TEST_SQL_GET_INFO_UINT_MASK(SQLConvertBigint, SQL_CONVERT_BIGINT, 0);
+// 8409288 = 0x008050C8 = SQL_CVT_INTEGER | SQL_CVT_REAL | SQL_CVT_DOUBLE | SQL_CVT_BIT | SQL_CVT_BIGINT | SQL_CVT_WVARCHAR
+TEST_SQL_GET_INFO_UINT_MASK(SQLConvertBigint, SQL_CONVERT_BIGINT, 8409288);
 TEST_SQL_GET_INFO_UINT_MASK(SQLConvertDecimal, SQL_CONVERT_DECIMAL, 0);
-TEST_SQL_GET_INFO_UINT_MASK(SQLConvertDouble, SQL_CONVERT_DOUBLE, 0);
+// 8409288 = 0x008050C8 = SQL_CVT_INTEGER | SQL_CVT_REAL | SQL_CVT_DOUBLE | SQL_CVT_BIT | SQL_CVT_BIGINT | SQL_CVT_WVARCHAR
+TEST_SQL_GET_INFO_UINT_MASK(SQLConvertDouble, SQL_CONVERT_DOUBLE, 8409288);
 TEST_SQL_GET_INFO_UINT_MASK(SQLConvertFloat, SQL_CONVERT_FLOAT, 0);
 TEST_SQL_GET_INFO_UINT_MASK(SQLConvertNumeric, SQL_CONVERT_NUMERIC, 0);
-TEST_SQL_GET_INFO_UINT_MASK(SQLConvertReal, SQL_CONVERT_REAL, 0);
+// 8409288 = 0x008050C8 = SQL_CVT_INTEGER | SQL_CVT_REAL | SQL_CVT_DOUBLE | SQL_CVT_BIT | SQL_CVT_BIGINT | SQL_CVT_WVARCHAR
+TEST_SQL_GET_INFO_UINT_MASK(SQLConvertReal, SQL_CONVERT_REAL, 8409288);
 TEST_SQL_GET_INFO_UINT_MASK(SQLConvertDate, SQL_CONVERT_DATE, 0);
 TEST_SQL_GET_INFO_UINT_MASK(SQLConvertTime, SQL_CONVERT_TIME, 0);
-TEST_SQL_GET_INFO_UINT_MASK(SQLConvertTimestamp, SQL_CONVERT_TIMESTAMP, 0);
+// 8519680 = 0x00820000 = SQL_CVT_TIMESTAMP | SQL_CVT_WVARCHAR
+TEST_SQL_GET_INFO_UINT_MASK(SQLConvertTimestamp, SQL_CONVERT_TIMESTAMP, 8519680);
 TEST_SQL_GET_INFO_UINT_MASK(SQLConvertBinary, SQL_CONVERT_BINARY, 0);
 TEST_SQL_GET_INFO_UINT_MASK(SQLConvertLongvarbinary, SQL_CONVERT_LONGVARBINARY,
                             0);
@@ -231,7 +237,8 @@ TEST_SQL_GET_INFO_UINT_MASK(SQLConvertLongVarchar, SQL_CONVERT_LONGVARCHAR, 0);
 TEST_SQL_GET_INFO_UINT_MASK(SQLConvertWChar, SQL_CONVERT_WCHAR, 0);
 TEST_SQL_GET_INFO_UINT_MASK(SQLConvertWLongVarchar, SQL_CONVERT_WLONGVARCHAR,
                             0);
-TEST_SQL_GET_INFO_UINT_MASK(SQLConvertWVarchar, SQL_CONVERT_WVARCHAR, 0);
+// 8405192 = 0x008040C8 = SQL_CVT_INTEGER | SQL_CVT_REAL | SQL_CVT_DOUBLE | SQL_CVT_BIGINT | SQL_CVT_WVARCHAR
+TEST_SQL_GET_INFO_UINT_MASK(SQLConvertWVarchar, SQL_CONVERT_WVARCHAR, 8405192);
 TEST_SQL_GET_INFO_UINT_MASK(SQLConvertGuid, SQL_CONVERT_GUID, 0);
 
 //////////////////////
diff --git a/sql-odbc/src/sqlodbc/info.c b/sql-odbc/src/sqlodbc/info.c
index f23d3a17e1f..1f7295502c2 100644
--- a/sql-odbc/src/sqlodbc/info.c
+++ b/sql-odbc/src/sqlodbc/info.c
@@ -127,37 +127,37 @@ RETCODE SQL_API OPENSEARCHAPI_GetInfo(HDBC hdbc, SQLUSMALLINT fInfoType,
 
         case SQL_CONVERT_INTEGER: /* ODBC 1.0 */
             len = sizeof(SQLUINTEGER);
-            value = SQL_CVT_BIT | SQL_CVT_WVARCHAR | SQL_CVT_DOUBLE | SQL_CVT_BIGINT | SQL_CVT_REAL;
+            value = SQL_CVT_INTEGER | SQL_CVT_BIT | SQL_CVT_WVARCHAR | SQL_CVT_DOUBLE | SQL_CVT_BIGINT | SQL_CVT_REAL;
             break;
 
         case SQL_CONVERT_BIT: /* ODBC 1.0 */
             len = sizeof(SQLUINTEGER);
-            value = SQL_CVT_INTEGER | SQL_CVT_WVARCHAR | SQL_CVT_DOUBLE | SQL_CVT_BIGINT | SQL_CVT_REAL;
+            value = SQL_CVT_BIT | SQL_CVT_INTEGER | SQL_CVT_WVARCHAR | SQL_CVT_DOUBLE | SQL_CVT_BIGINT | SQL_CVT_REAL;
             break;
 
         case SQL_CONVERT_WVARCHAR: /* ODBC 1.0 */
             len = sizeof(SQLUINTEGER);
-            value = SQL_CVT_INTEGER | SQL_CVT_DOUBLE | SQL_CVT_BIGINT | SQL_CVT_REAL;
+            value = SQL_CVT_WVARCHAR | SQL_CVT_INTEGER | SQL_CVT_DOUBLE | SQL_CVT_BIGINT | SQL_CVT_REAL;
             break;
 
         case SQL_CONVERT_DOUBLE: /* ODBC 1.0 */
             len = sizeof(SQLUINTEGER);
-            value = SQL_CVT_INTEGER | SQL_CVT_BIT | SQL_CVT_WVARCHAR | SQL_CVT_BIGINT | SQL_CVT_REAL;
+            value = SQL_CVT_DOUBLE | SQL_CVT_INTEGER | SQL_CVT_BIT | SQL_CVT_WVARCHAR | SQL_CVT_BIGINT | SQL_CVT_REAL;
             break;
 
         case SQL_CONVERT_BIGINT: /* ODBC 1.0 */
             len = sizeof(SQLUINTEGER);
-            value = SQL_CVT_INTEGER | SQL_CVT_BIT | SQL_CVT_WVARCHAR | SQL_CVT_DOUBLE | SQL_CVT_REAL;
+            value = SQL_CVT_BIGINT | SQL_CVT_INTEGER | SQL_CVT_BIT | SQL_CVT_WVARCHAR | SQL_CVT_DOUBLE | SQL_CVT_REAL;
             break;
 
         case SQL_CONVERT_REAL: /* ODBC 1.0 */
             len = sizeof(SQLUINTEGER);
-            value = SQL_CVT_INTEGER | SQL_CVT_BIT | SQL_CVT_WVARCHAR | SQL_CVT_DOUBLE | SQL_CVT_BIGINT;
+            value = SQL_CVT_REAL | SQL_CVT_INTEGER | SQL_CVT_BIT | SQL_CVT_WVARCHAR | SQL_CVT_DOUBLE | SQL_CVT_BIGINT;
             break;
 
         case SQL_CONVERT_TIMESTAMP: /* ODBC 1.0 */
             len = sizeof(SQLUINTEGER);
-            value = SQL_CVT_WVARCHAR;
+            value = SQL_CVT_TIMESTAMP | SQL_CVT_WVARCHAR;
             break;
 
         case SQL_CONVERT_FUNCTIONS: /* ODBC 1.0 */

From f295608190729f0afb94bfbad96ca83453d78bda Mon Sep 17 00:00:00 2001
From: Guian Gumpac <guiang@bitquilltech.com>
Date: Tue, 7 Dec 2021 15:16:07 -0800
Subject: [PATCH 24/28] Removed connector changes

Signed-off-by: Guian Gumpac <guiang@bitquilltech.com>
---
 .../src/PowerBIConnector/SqlOdbcPBIConnector.pq   | 15 +++------------
 1 file changed, 3 insertions(+), 12 deletions(-)

diff --git a/sql-odbc/src/PowerBIConnector/SqlOdbcPBIConnector.pq b/sql-odbc/src/PowerBIConnector/SqlOdbcPBIConnector.pq
index 8edd090d657..ba10c39e494 100644
--- a/sql-odbc/src/PowerBIConnector/SqlOdbcPBIConnector.pq
+++ b/sql-odbc/src/PowerBIConnector/SqlOdbcPBIConnector.pq
@@ -69,21 +69,12 @@ SqlOdbcPBIConnectorImpl = (Server as text) as table =>
         SQLGetTypeInfo = (types) => 
             if (EnableTraceOutput <> true) then types else
             let
-                // SELECT CAST(1 AS KEYWORD) does not work for OpenSearch
-                // SELECT CAST(1 AS STRING) works for OpenSearch
-                FixTypeName = (typeName) =>
-                    if typeName = "keyword" then "string"
-                    else typeName,
-
                 // Outputting the entire table might be too large, and result in the value being truncated.
                 // We can output a row at a time instead with Table.TransformRows()
                 rows = Table.TransformRows(types, each Diagnostics.LogValue("SQLGetTypeInfo " & _[TYPE_NAME], _)),
-                toTable = Table.FromRecords(rows),
-
-                // Override the type name of columns
-                modifiedColumns = Table.TransformColumns(toTable, {{"TYPE_NAME", FixTypeName}})
+                toTable = Table.FromRecords(rows)
             in
-                Value.ReplaceType(modifiedColumns, Value.Type(types)),
+                Value.ReplaceType(toTable, Value.Type(types)),
 
         // SQLColumns is a function handler that receives the results of an ODBC call to SQLColumns().
         SQLColumns = (catalogName, schemaName, tableName, columnName, source) =>
@@ -215,7 +206,7 @@ SqlOdbcPBIConnector.Publish = [
     LearnMoreUrl = "https://www.opensearch.org/",
     
     // Disabling direct query due to limited SQL query support
-    SupportsDirectQuery = true,
+    SupportsDirectQuery = false,
 
     SourceImage = SqlOdbcPBIConnector.Icons,
     SourceTypeImage = SqlOdbcPBIConnector.Icons

From 284376ee2e7f84592b88b06c94eb6d9791aa4d00 Mon Sep 17 00:00:00 2001
From: Guian Gumpac <guiang@bitquilltech.com>
Date: Wed, 8 Dec 2021 11:34:40 -0800
Subject: [PATCH 25/28] Change values to bitmasks

Signed-off-by: Guian Gumpac <guiang@bitquilltech.com>
---
 .../ITODBCInfo/test_odbc_info.cpp             | 21 +++++++------------
 1 file changed, 7 insertions(+), 14 deletions(-)

diff --git a/sql-odbc/src/IntegrationTests/ITODBCInfo/test_odbc_info.cpp b/sql-odbc/src/IntegrationTests/ITODBCInfo/test_odbc_info.cpp
index f54333fcb83..69b3b4a48a8 100644
--- a/sql-odbc/src/IntegrationTests/ITODBCInfo/test_odbc_info.cpp
+++ b/sql-odbc/src/IntegrationTests/ITODBCInfo/test_odbc_info.cpp
@@ -208,26 +208,20 @@ TEST_SQL_GET_INFO_STRING(SQLCatalogName, SQL_CATALOG_NAME, L"N");
 // Conversion //
 ////////////////
 
-// 8409288 = 0x008050C8 = SQL_CVT_INTEGER | SQL_CVT_REAL | SQL_CVT_DOUBLE | SQL_CVT_BIT | SQL_CVT_BIGINT | SQL_CVT_WVARCHAR
-TEST_SQL_GET_INFO_UINT_MASK(SQLConvertInteger, SQL_CONVERT_INTEGER, 8409288);
+TEST_SQL_GET_INFO_UINT_MASK(SQLConvertInteger, SQL_CONVERT_INTEGER, SQL_CVT_INTEGER | SQL_CVT_REAL | SQL_CVT_DOUBLE | SQL_CVT_BIT | SQL_CVT_BIGINT | SQL_CVT_WVARCHAR);
 TEST_SQL_GET_INFO_UINT_MASK(SQLConvertSmallint, SQL_CONVERT_SMALLINT, 0);
 TEST_SQL_GET_INFO_UINT_MASK(SQLConvertTinyint, SQL_CONVERT_TINYINT, 0);
-// 8409288 = 0x008050C8 = SQL_CVT_INTEGER | SQL_CVT_REAL | SQL_CVT_DOUBLE | SQL_CVT_BIT | SQL_CVT_BIGINT | SQL_CVT_WVARCHAR
-TEST_SQL_GET_INFO_UINT_MASK(SQLConvertBit, SQL_CONVERT_BIT, 8409288);
+TEST_SQL_GET_INFO_UINT_MASK(SQLConvertBit, SQL_CONVERT_BIT, SQL_CVT_INTEGER | SQL_CVT_REAL | SQL_CVT_DOUBLE | SQL_CVT_BIT | SQL_CVT_BIGINT | SQL_CVT_WVARCHAR);
 TEST_SQL_GET_INFO_UINT_MASK(SQLConvertVarchar, SQL_CONVERT_VARCHAR, 0);
-// 8409288 = 0x008050C8 = SQL_CVT_INTEGER | SQL_CVT_REAL | SQL_CVT_DOUBLE | SQL_CVT_BIT | SQL_CVT_BIGINT | SQL_CVT_WVARCHAR
-TEST_SQL_GET_INFO_UINT_MASK(SQLConvertBigint, SQL_CONVERT_BIGINT, 8409288);
+TEST_SQL_GET_INFO_UINT_MASK(SQLConvertBigint, SQL_CONVERT_BIGINT, SQL_CVT_INTEGER | SQL_CVT_REAL | SQL_CVT_DOUBLE | SQL_CVT_BIT | SQL_CVT_BIGINT | SQL_CVT_WVARCHAR);
 TEST_SQL_GET_INFO_UINT_MASK(SQLConvertDecimal, SQL_CONVERT_DECIMAL, 0);
-// 8409288 = 0x008050C8 = SQL_CVT_INTEGER | SQL_CVT_REAL | SQL_CVT_DOUBLE | SQL_CVT_BIT | SQL_CVT_BIGINT | SQL_CVT_WVARCHAR
-TEST_SQL_GET_INFO_UINT_MASK(SQLConvertDouble, SQL_CONVERT_DOUBLE, 8409288);
+TEST_SQL_GET_INFO_UINT_MASK(SQLConvertDouble, SQL_CONVERT_DOUBLE, SQL_CVT_INTEGER | SQL_CVT_REAL | SQL_CVT_DOUBLE | SQL_CVT_BIT | SQL_CVT_BIGINT | SQL_CVT_WVARCHAR);
 TEST_SQL_GET_INFO_UINT_MASK(SQLConvertFloat, SQL_CONVERT_FLOAT, 0);
 TEST_SQL_GET_INFO_UINT_MASK(SQLConvertNumeric, SQL_CONVERT_NUMERIC, 0);
-// 8409288 = 0x008050C8 = SQL_CVT_INTEGER | SQL_CVT_REAL | SQL_CVT_DOUBLE | SQL_CVT_BIT | SQL_CVT_BIGINT | SQL_CVT_WVARCHAR
-TEST_SQL_GET_INFO_UINT_MASK(SQLConvertReal, SQL_CONVERT_REAL, 8409288);
+TEST_SQL_GET_INFO_UINT_MASK(SQLConvertReal, SQL_CONVERT_REAL, SQL_CVT_INTEGER | SQL_CVT_REAL | SQL_CVT_DOUBLE | SQL_CVT_BIT | SQL_CVT_BIGINT | SQL_CVT_WVARCHAR);
 TEST_SQL_GET_INFO_UINT_MASK(SQLConvertDate, SQL_CONVERT_DATE, 0);
 TEST_SQL_GET_INFO_UINT_MASK(SQLConvertTime, SQL_CONVERT_TIME, 0);
-// 8519680 = 0x00820000 = SQL_CVT_TIMESTAMP | SQL_CVT_WVARCHAR
-TEST_SQL_GET_INFO_UINT_MASK(SQLConvertTimestamp, SQL_CONVERT_TIMESTAMP, 8519680);
+TEST_SQL_GET_INFO_UINT_MASK(SQLConvertTimestamp, SQL_CONVERT_TIMESTAMP, SQL_CVT_TIMESTAMP | SQL_CVT_WVARCHAR);
 TEST_SQL_GET_INFO_UINT_MASK(SQLConvertBinary, SQL_CONVERT_BINARY, 0);
 TEST_SQL_GET_INFO_UINT_MASK(SQLConvertLongvarbinary, SQL_CONVERT_LONGVARBINARY,
                             0);
@@ -237,8 +231,7 @@ TEST_SQL_GET_INFO_UINT_MASK(SQLConvertLongVarchar, SQL_CONVERT_LONGVARCHAR, 0);
 TEST_SQL_GET_INFO_UINT_MASK(SQLConvertWChar, SQL_CONVERT_WCHAR, 0);
 TEST_SQL_GET_INFO_UINT_MASK(SQLConvertWLongVarchar, SQL_CONVERT_WLONGVARCHAR,
                             0);
-// 8405192 = 0x008040C8 = SQL_CVT_INTEGER | SQL_CVT_REAL | SQL_CVT_DOUBLE | SQL_CVT_BIGINT | SQL_CVT_WVARCHAR
-TEST_SQL_GET_INFO_UINT_MASK(SQLConvertWVarchar, SQL_CONVERT_WVARCHAR, 8405192);
+TEST_SQL_GET_INFO_UINT_MASK(SQLConvertWVarchar, SQL_CONVERT_WVARCHAR, SQL_CVT_INTEGER | SQL_CVT_REAL | SQL_CVT_DOUBLE | SQL_CVT_BIGINT | SQL_CVT_WVARCHAR);
 TEST_SQL_GET_INFO_UINT_MASK(SQLConvertGuid, SQL_CONVERT_GUID, 0);
 
 //////////////////////

From 2736d1c2458fc376684802efe705f02a821f4a36 Mon Sep 17 00:00:00 2001
From: Guian Gumpac <guiang@bitquilltech.com>
Date: Thu, 9 Dec 2021 14:36:15 -0800
Subject: [PATCH 26/28] Remove changes from irrelevant commits

Signed-off-by: Guian Gumpac <guiang@bitquilltech.com>
---
 .../opensearch_sql_jdbc/dialect.tdd           | 96 +++++--------------
 .../opensearch_sql_jdbc/manifest.xml          |  6 +-
 .../opensearch/jdbc/types/TimestampType.java  | 16 +---
 .../ITODBCInfo/test_odbc_info.cpp             | 16 ++--
 sql-odbc/src/sqlodbc/info.c                   | 44 ++-------
 5 files changed, 48 insertions(+), 130 deletions(-)

diff --git a/sql-jdbc/src/TableauConnector/opensearch_sql_jdbc/dialect.tdd b/sql-jdbc/src/TableauConnector/opensearch_sql_jdbc/dialect.tdd
index f410db3e2c1..2105ac7fd21 100644
--- a/sql-jdbc/src/TableauConnector/opensearch_sql_jdbc/dialect.tdd
+++ b/sql-jdbc/src/TableauConnector/opensearch_sql_jdbc/dialect.tdd
@@ -32,36 +32,6 @@
             <formula>TO_DAYS(%1) - 693961.0</formula>
             <argument type='datetime' />
         </function>
-        <function group='cast' name='STR' return-type='str'>
-            <formula>CAST(%1 as string)</formula>
-            <argument type='real' />
-        </function>
-        <function group='cast' name='STR' return-type='str'>
-            <formula>CAST(%1 as string)</formula>
-            <argument type='int' />
-        </function>
-        <function group='cast' name='STR' return-type='str'>
-            <formula>CAST(%1 as string)</formula>
-            <argument type='date' />
-        </function>
-        <function group='cast' name='STR' return-type='str'>
-            <formula>CAST(%1 as string)</formula>
-            <argument type='bool' />
-        </function>
-        <function group='cast' name='INT' return-type='int'>
-            <formula>CAST(%1 as int)</formula>
-            <argument type='real' />
-        </function>
-        <function group='cast' name='INT' return-type='int'>
-            <formula>CAST(%1 as int)</formula>
-            <argument type='bool' />
-        </function>
-
-        <function group='logical' name='IFNULL' return-type='datetime'>
-            <formula>CASE WHEN ISNULL(%1) THEN SUBDATE(TIMESTAMP(%2), INTERVAL HOUR(TIMESTAMP(%2)) HOUR) ELSE %1 END</formula>
-            <argument type='datetime' />
-            <argument type='date' />
-        </function>
 
         <function group='operator' name='!=' return-type='bool'>
             <formula>(%1 AND NOT %2 OR NOT %1 AND %2)</formula>
@@ -180,14 +150,6 @@
             <argument type='datetime' />
             <argument type='datetime' />
         </function>
-        <function group='numeric' name='MAX' return-type='str'>
-            <formula>CASE WHEN ISNULL(%1) THEN NULL
-                WHEN ISNULL(%2) THEN NULL
-	            WHEN %1 &gt; %2 THEN %1
-                ELSE %2 END</formula>
-            <argument type='str' />
-            <argument type='str' />
-        </function>
         <function group='numeric' name='MIN' return-type='int'>
             <formula>CASE WHEN ISNULL(%1) THEN NULL
                 WHEN ISNULL(%2) THEN NULL
@@ -212,33 +174,7 @@
             <argument type='datetime' />
             <argument type='datetime' />
         </function>
-        <function group='numeric' name='MIN' return-type='str'>
-            <formula>CASE WHEN ISNULL(%1) THEN NULL
-                WHEN ISNULL(%2) THEN NULL
-	            WHEN %1 &lt; %2 THEN %1
-                ELSE %2 END</formula>
-            <argument type='str' />
-            <argument type='str' />
-        </function>
-        <function group='numeric' name='CEILING' return-type='int'>
-            <formula>CEIL(%1)</formula>
-            <argument type='real' />
-        </function>
-        <function group='numeric' name='FLOOR' return-type='int'>
-            <formula>FLOOR(%1)</formula>
-            <argument type='real' />
-        </function>
-        <function group='numeric' name='HEXBINX' return-type='real'>
-            <formula>(((CASE WHEN (ABS((%2) - (CAST( ( (%2) / SQRT(3.0) ) AS INT ) * SQRT(3.0)))) + (SQRT(3.0) * ((ABS((%1) - (CAST( ( (%1) / 3.0 ) AS INT ) * 3.0))) - 1.0)) &gt; 0.0 THEN 1.5 ELSE 0.0 END) - (CASE WHEN ((%1) - (CAST( ( (%1) / 3.0 ) AS INT ) * 3.0) &lt; 0.0) AND ((CASE WHEN (ABS((%2) - (CAST( ( (%2) / SQRT(3.0) ) AS INT ) * SQRT(3.0)))) + (SQRT(3.0) * ((ABS((%1) - (CAST( ( (%1) / 3.0 ) AS INT ) * 3.0))) - 1.0)) &gt; 0.0 THEN 1.5 ELSE 0.0 END) &gt; 0.0) THEN 3.0 ELSE 0.0 END)) + (CAST( ( (%1) / 3.0 ) AS INT ) * 3.0))</formula>
-            <argument type='real' />
-            <argument type='real' />
-        </function>
-        <function group='numeric' name='HEXBINY' return-type='real'>
-            <formula>ROUND( (((CASE WHEN (ABS((%2) - (ROUND( ( (%2) / SQRT(3.0) ), 0 ) * SQRT(3.0)))) + (SQRT(3.0) * ((ABS((%1) - (ROUND( ( (%1) / 3.0 ), 0 ) * 3.0))) - 1.0)) &gt; 0.0 THEN SQRT(3.0) / 2.0 ELSE 0.0 END) - (CASE WHEN ((%2) - (ROUND( ( (%2) / SQRT(3.0) ), 0 ) * SQRT(3.0)) &lt; 0.0) AND ((CASE WHEN (ABS((%2) - (ROUND( ( (%2) / SQRT(3.0) ), 0 ) * SQRT(3.0)))) + (SQRT(3.0) * ((ABS((%1) - (ROUND( ( (%1) / 3.0 ), 0 ) * 3.0))) - 1.0)) &gt; 0.0 THEN SQRT(3.0) / 2.0 ELSE 0.0 END) &gt; 0.0) THEN SQRT(3.0) ELSE 0.0 END)) + (ROUND( ( (%2) / SQRT(3.0) ), 0 ) * SQRT(3.0))), 3)</formula>
-            <argument type='real' />
-            <argument type='real' />
-        </function>
-
+    
         <function group='date' name='DAYOFYEAR' return-type='int'>
             <formula>DAY_OF_YEAR(%1)</formula>
             <argument type='date' />
@@ -252,35 +188,35 @@
             <argument type='date' />
         </function>
 
-        <function group='string' name='MID' return-type='str'>
+        <function group='string' name='MID' return-type='int'>
             <formula>SUBSTR(%1,%2)</formula>
             <argument type='str' />
             <argument type='int' />
         </function>
-        <function group='string' name='MID' return-type='str'>
+        <function group='string' name='MID' return-type='int'>
             <formula>SUBSTR(%1,CAST(%2 as int))</formula>
             <argument type='str' />
             <argument type='real' />
         </function>
-        <function group='string' name='MID' return-type='str'>
+        <function group='string' name='MID' return-type='int'>
             <formula>SUBSTR(%1,%2,%3)</formula>
             <argument type='str' />
             <argument type='int' />
             <argument type='int' />
         </function>
-        <function group='string' name='MID' return-type='str'>
+        <function group='string' name='MID' return-type='int'>
             <formula>SUBSTR(%1,CAST(%2 as int),%3)</formula>
             <argument type='str' />
             <argument type='real' />
             <argument type='int' />
         </function>
-        <function group='string' name='MID' return-type='str'>
+        <function group='string' name='MID' return-type='int'>
             <formula>SUBSTR(%1,%2,CAST(%3 as int))</formula>
             <argument type='str' />
             <argument type='int' />
             <argument type='real' />
         </function>
-        <function group='string' name='MID' return-type='str'>
+        <function group='string' name='MID' return-type='int'>
             <formula>SUBSTR(%1,CAST(%2 as int),CAST(%3 as int))</formula>
             <argument type='str' />
             <argument type='real' />
@@ -390,8 +326,24 @@
             <argument type='datetime' />
         </remove-function>
 
+        <remove-function name='MAX'>
+            <argument type='str' />
+        </remove-function>
+        <remove-function name='MAX'>
+            <argument type='str' />
+            <argument type='str' />
+        </remove-function>
+
         <remove-function name='SPACE'>
             <argument type='int' />
         </remove-function>
+
+        <remove-function name='MIN'>
+            <argument type='str' />
+        </remove-function>
+        <remove-function name='MIN'>
+            <argument type='str' />
+            <argument type='str' />
+        </remove-function>
    </function-map>
-</dialect>
+</dialect>
\ No newline at end of file
diff --git a/sql-jdbc/src/TableauConnector/opensearch_sql_jdbc/manifest.xml b/sql-jdbc/src/TableauConnector/opensearch_sql_jdbc/manifest.xml
index 55c64830b97..c0df5ebb288 100644
--- a/sql-jdbc/src/TableauConnector/opensearch_sql_jdbc/manifest.xml
+++ b/sql-jdbc/src/TableauConnector/opensearch_sql_jdbc/manifest.xml
@@ -2,11 +2,11 @@
 
 <connector-plugin class='opensearch_jdbc' superclass='jdbc' plugin-version='1.1.0.0' name='OpenSearch' version='18.1' min-version-tableau='2021.1'>
   <vendor-information>
-      <company name="OpenSearch Project"/>
+      <company name="OpenSearch for ES"/>
       <support-link url="https://github.com/opensearch-project/sql"/>
   </vendor-information>
   <connection-customization class="opensearch_jdbc" enabled="true" version="10.0">
-    <vendor name="OpenSearch Project"/>
+    <vendor name="OpenSearch JDBC"/>
     <driver name="SQL"/>
     <customizations>
       <customization name="CAP_CREATE_TEMP_TABLES" value="no"/>
@@ -50,4 +50,4 @@
   <connection-metadata file='connection-metadata.xml'/>
   <connection-resolver file="connectionResolver.tdr"/>
   <dialect file='dialect.tdd'/>
-</connector-plugin>
+</connector-plugin>
\ No newline at end of file
diff --git a/sql-jdbc/src/main/java/org/opensearch/jdbc/types/TimestampType.java b/sql-jdbc/src/main/java/org/opensearch/jdbc/types/TimestampType.java
index 4dcd94ae74f..459d2d07d96 100644
--- a/sql-jdbc/src/main/java/org/opensearch/jdbc/types/TimestampType.java
+++ b/sql-jdbc/src/main/java/org/opensearch/jdbc/types/TimestampType.java
@@ -8,7 +8,6 @@
 
 import java.sql.SQLException;
 import java.sql.Timestamp;
-import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.util.Calendar;
 import java.util.Map;
@@ -79,18 +78,13 @@ else if (value.charAt(23) == '+' || value.charAt(23) == '-') {
                 }
             }
 
-            final Timestamp ts;
-            // 11 to check if the value is in yyyy-MM-dd format
-            if (value.length() < 11) {
-                ts = Timestamp.valueOf(LocalDate.parse(value).atStartOfDay());
+            if (calendar == null) {
+                return Timestamp.valueOf(value);
             } else {
-                ts = Timestamp.valueOf(value);
+                Timestamp ts = Timestamp.valueOf(value);
+                return localDateTimeToTimestamp(ts.toLocalDateTime(), calendar);
             }
 
-            if (calendar == null) {
-                return ts;
-            }
-            return localDateTimeToTimestamp(ts.toLocalDateTime(), calendar);
         } catch (IllegalArgumentException iae) {
             throw stringConversionException(value, iae);
         }
@@ -105,4 +99,4 @@ public String getTypeName() {
         return "Timestamp";
     }
 
-}
+}
\ No newline at end of file
diff --git a/sql-odbc/src/IntegrationTests/ITODBCInfo/test_odbc_info.cpp b/sql-odbc/src/IntegrationTests/ITODBCInfo/test_odbc_info.cpp
index 69b3b4a48a8..5568494303b 100644
--- a/sql-odbc/src/IntegrationTests/ITODBCInfo/test_odbc_info.cpp
+++ b/sql-odbc/src/IntegrationTests/ITODBCInfo/test_odbc_info.cpp
@@ -208,20 +208,20 @@ TEST_SQL_GET_INFO_STRING(SQLCatalogName, SQL_CATALOG_NAME, L"N");
 // Conversion //
 ////////////////
 
-TEST_SQL_GET_INFO_UINT_MASK(SQLConvertInteger, SQL_CONVERT_INTEGER, SQL_CVT_INTEGER | SQL_CVT_REAL | SQL_CVT_DOUBLE | SQL_CVT_BIT | SQL_CVT_BIGINT | SQL_CVT_WVARCHAR);
+TEST_SQL_GET_INFO_UINT_MASK(SQLConvertInteger, SQL_CONVERT_INTEGER, 0);
 TEST_SQL_GET_INFO_UINT_MASK(SQLConvertSmallint, SQL_CONVERT_SMALLINT, 0);
 TEST_SQL_GET_INFO_UINT_MASK(SQLConvertTinyint, SQL_CONVERT_TINYINT, 0);
-TEST_SQL_GET_INFO_UINT_MASK(SQLConvertBit, SQL_CONVERT_BIT, SQL_CVT_INTEGER | SQL_CVT_REAL | SQL_CVT_DOUBLE | SQL_CVT_BIT | SQL_CVT_BIGINT | SQL_CVT_WVARCHAR);
+TEST_SQL_GET_INFO_UINT_MASK(SQLConvertBit, SQL_CONVERT_BIT, 0);
 TEST_SQL_GET_INFO_UINT_MASK(SQLConvertVarchar, SQL_CONVERT_VARCHAR, 0);
-TEST_SQL_GET_INFO_UINT_MASK(SQLConvertBigint, SQL_CONVERT_BIGINT, SQL_CVT_INTEGER | SQL_CVT_REAL | SQL_CVT_DOUBLE | SQL_CVT_BIT | SQL_CVT_BIGINT | SQL_CVT_WVARCHAR);
+TEST_SQL_GET_INFO_UINT_MASK(SQLConvertBigint, SQL_CONVERT_BIGINT, 0);
 TEST_SQL_GET_INFO_UINT_MASK(SQLConvertDecimal, SQL_CONVERT_DECIMAL, 0);
-TEST_SQL_GET_INFO_UINT_MASK(SQLConvertDouble, SQL_CONVERT_DOUBLE, SQL_CVT_INTEGER | SQL_CVT_REAL | SQL_CVT_DOUBLE | SQL_CVT_BIT | SQL_CVT_BIGINT | SQL_CVT_WVARCHAR);
+TEST_SQL_GET_INFO_UINT_MASK(SQLConvertDouble, SQL_CONVERT_DOUBLE, 0);
 TEST_SQL_GET_INFO_UINT_MASK(SQLConvertFloat, SQL_CONVERT_FLOAT, 0);
 TEST_SQL_GET_INFO_UINT_MASK(SQLConvertNumeric, SQL_CONVERT_NUMERIC, 0);
-TEST_SQL_GET_INFO_UINT_MASK(SQLConvertReal, SQL_CONVERT_REAL, SQL_CVT_INTEGER | SQL_CVT_REAL | SQL_CVT_DOUBLE | SQL_CVT_BIT | SQL_CVT_BIGINT | SQL_CVT_WVARCHAR);
+TEST_SQL_GET_INFO_UINT_MASK(SQLConvertReal, SQL_CONVERT_REAL, 0);
 TEST_SQL_GET_INFO_UINT_MASK(SQLConvertDate, SQL_CONVERT_DATE, 0);
 TEST_SQL_GET_INFO_UINT_MASK(SQLConvertTime, SQL_CONVERT_TIME, 0);
-TEST_SQL_GET_INFO_UINT_MASK(SQLConvertTimestamp, SQL_CONVERT_TIMESTAMP, SQL_CVT_TIMESTAMP | SQL_CVT_WVARCHAR);
+TEST_SQL_GET_INFO_UINT_MASK(SQLConvertTimestamp, SQL_CONVERT_TIMESTAMP, 0);
 TEST_SQL_GET_INFO_UINT_MASK(SQLConvertBinary, SQL_CONVERT_BINARY, 0);
 TEST_SQL_GET_INFO_UINT_MASK(SQLConvertLongvarbinary, SQL_CONVERT_LONGVARBINARY,
                             0);
@@ -231,7 +231,7 @@ TEST_SQL_GET_INFO_UINT_MASK(SQLConvertLongVarchar, SQL_CONVERT_LONGVARCHAR, 0);
 TEST_SQL_GET_INFO_UINT_MASK(SQLConvertWChar, SQL_CONVERT_WCHAR, 0);
 TEST_SQL_GET_INFO_UINT_MASK(SQLConvertWLongVarchar, SQL_CONVERT_WLONGVARCHAR,
                             0);
-TEST_SQL_GET_INFO_UINT_MASK(SQLConvertWVarchar, SQL_CONVERT_WVARCHAR, SQL_CVT_INTEGER | SQL_CVT_REAL | SQL_CVT_DOUBLE | SQL_CVT_BIGINT | SQL_CVT_WVARCHAR);
+TEST_SQL_GET_INFO_UINT_MASK(SQLConvertWVarchar, SQL_CONVERT_WVARCHAR, 0);
 TEST_SQL_GET_INFO_UINT_MASK(SQLConvertGuid, SQL_CONVERT_GUID, 0);
 
 //////////////////////
@@ -303,4 +303,4 @@ int main(int argc, char** argv) {
     system("leaks itodbc_info > leaks_itodbc_info");
 #endif
     return failures;
-}
+}
\ No newline at end of file
diff --git a/sql-odbc/src/sqlodbc/info.c b/sql-odbc/src/sqlodbc/info.c
index 1f7295502c2..13fdd2fef90 100644
--- a/sql-odbc/src/sqlodbc/info.c
+++ b/sql-odbc/src/sqlodbc/info.c
@@ -104,14 +104,20 @@ RETCODE SQL_API OPENSEARCHAPI_GetInfo(HDBC hdbc, SQLUSMALLINT fInfoType,
             break;
 
         case SQL_CONVERT_GUID:
+        case SQL_CONVERT_INTEGER:
         case SQL_CONVERT_SMALLINT:
         case SQL_CONVERT_TINYINT:
+        case SQL_CONVERT_BIT:
         case SQL_CONVERT_VARCHAR:
+        case SQL_CONVERT_BIGINT:
         case SQL_CONVERT_DECIMAL:
+        case SQL_CONVERT_DOUBLE:
         case SQL_CONVERT_FLOAT:
         case SQL_CONVERT_NUMERIC:
+        case SQL_CONVERT_REAL:
         case SQL_CONVERT_DATE:
         case SQL_CONVERT_TIME:
+        case SQL_CONVERT_TIMESTAMP:
         case SQL_CONVERT_BINARY:
         case SQL_CONVERT_LONGVARBINARY:
         case SQL_CONVERT_VARBINARY: /* ODBC 1.0 */
@@ -120,46 +126,12 @@ RETCODE SQL_API OPENSEARCHAPI_GetInfo(HDBC hdbc, SQLUSMALLINT fInfoType,
 #ifdef UNICODE_SUPPORT
         case SQL_CONVERT_WCHAR:
         case SQL_CONVERT_WLONGVARCHAR:
+        case SQL_CONVERT_WVARCHAR:
 #endif /* UNICODE_SUPPORT */
             len = sizeof(SQLUINTEGER);
             value = 0; /* CONVERT is unavailable */
             break;
 
-        case SQL_CONVERT_INTEGER: /* ODBC 1.0 */
-            len = sizeof(SQLUINTEGER);
-            value = SQL_CVT_INTEGER | SQL_CVT_BIT | SQL_CVT_WVARCHAR | SQL_CVT_DOUBLE | SQL_CVT_BIGINT | SQL_CVT_REAL;
-            break;
-
-        case SQL_CONVERT_BIT: /* ODBC 1.0 */
-            len = sizeof(SQLUINTEGER);
-            value = SQL_CVT_BIT | SQL_CVT_INTEGER | SQL_CVT_WVARCHAR | SQL_CVT_DOUBLE | SQL_CVT_BIGINT | SQL_CVT_REAL;
-            break;
-
-        case SQL_CONVERT_WVARCHAR: /* ODBC 1.0 */
-            len = sizeof(SQLUINTEGER);
-            value = SQL_CVT_WVARCHAR | SQL_CVT_INTEGER | SQL_CVT_DOUBLE | SQL_CVT_BIGINT | SQL_CVT_REAL;
-            break;
-
-        case SQL_CONVERT_DOUBLE: /* ODBC 1.0 */
-            len = sizeof(SQLUINTEGER);
-            value = SQL_CVT_DOUBLE | SQL_CVT_INTEGER | SQL_CVT_BIT | SQL_CVT_WVARCHAR | SQL_CVT_BIGINT | SQL_CVT_REAL;
-            break;
-
-        case SQL_CONVERT_BIGINT: /* ODBC 1.0 */
-            len = sizeof(SQLUINTEGER);
-            value = SQL_CVT_BIGINT | SQL_CVT_INTEGER | SQL_CVT_BIT | SQL_CVT_WVARCHAR | SQL_CVT_DOUBLE | SQL_CVT_REAL;
-            break;
-
-        case SQL_CONVERT_REAL: /* ODBC 1.0 */
-            len = sizeof(SQLUINTEGER);
-            value = SQL_CVT_REAL | SQL_CVT_INTEGER | SQL_CVT_BIT | SQL_CVT_WVARCHAR | SQL_CVT_DOUBLE | SQL_CVT_BIGINT;
-            break;
-
-        case SQL_CONVERT_TIMESTAMP: /* ODBC 1.0 */
-            len = sizeof(SQLUINTEGER);
-            value = SQL_CVT_TIMESTAMP | SQL_CVT_WVARCHAR;
-            break;
-
         case SQL_CONVERT_FUNCTIONS: /* ODBC 1.0 */
             len = sizeof(SQLUINTEGER);
             value = SQL_FN_CVT_CAST;
@@ -1903,4 +1875,4 @@ RETCODE SQL_API OPENSEARCHAPI_TablePrivileges(HSTMT hstmt,
     SC_set_current_col(stmt, -1);
 
     return SQL_SUCCESS;
-}
+}
\ No newline at end of file

From 858bd646168f0331fc5383a82ff3952f996409c6 Mon Sep 17 00:00:00 2001
From: Guian Gumpac <guiang@bitquilltech.com>
Date: Thu, 9 Dec 2021 14:38:48 -0800
Subject: [PATCH 27/28] Remove changes from irrelevant commits

Signed-off-by: Guian Gumpac <guiang@bitquilltech.com>
---
 sql-jdbc/src/TableauConnector/opensearch_sql_jdbc/dialect.tdd   | 2 +-
 sql-jdbc/src/TableauConnector/opensearch_sql_jdbc/manifest.xml  | 2 +-
 .../src/main/java/org/opensearch/jdbc/types/TimestampType.java  | 2 +-
 sql-odbc/src/IntegrationTests/ITODBCInfo/test_odbc_info.cpp     | 2 +-
 sql-odbc/src/sqlodbc/info.c                                     | 2 +-
 5 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/sql-jdbc/src/TableauConnector/opensearch_sql_jdbc/dialect.tdd b/sql-jdbc/src/TableauConnector/opensearch_sql_jdbc/dialect.tdd
index 2105ac7fd21..f33f42444e5 100644
--- a/sql-jdbc/src/TableauConnector/opensearch_sql_jdbc/dialect.tdd
+++ b/sql-jdbc/src/TableauConnector/opensearch_sql_jdbc/dialect.tdd
@@ -346,4 +346,4 @@
             <argument type='str' />
         </remove-function>
    </function-map>
-</dialect>
\ No newline at end of file
+</dialect>
diff --git a/sql-jdbc/src/TableauConnector/opensearch_sql_jdbc/manifest.xml b/sql-jdbc/src/TableauConnector/opensearch_sql_jdbc/manifest.xml
index c0df5ebb288..20c99b96be0 100644
--- a/sql-jdbc/src/TableauConnector/opensearch_sql_jdbc/manifest.xml
+++ b/sql-jdbc/src/TableauConnector/opensearch_sql_jdbc/manifest.xml
@@ -50,4 +50,4 @@
   <connection-metadata file='connection-metadata.xml'/>
   <connection-resolver file="connectionResolver.tdr"/>
   <dialect file='dialect.tdd'/>
-</connector-plugin>
\ No newline at end of file
+</connector-plugin>
diff --git a/sql-jdbc/src/main/java/org/opensearch/jdbc/types/TimestampType.java b/sql-jdbc/src/main/java/org/opensearch/jdbc/types/TimestampType.java
index 459d2d07d96..3ae9463ea41 100644
--- a/sql-jdbc/src/main/java/org/opensearch/jdbc/types/TimestampType.java
+++ b/sql-jdbc/src/main/java/org/opensearch/jdbc/types/TimestampType.java
@@ -99,4 +99,4 @@ public String getTypeName() {
         return "Timestamp";
     }
 
-}
\ No newline at end of file
+}
diff --git a/sql-odbc/src/IntegrationTests/ITODBCInfo/test_odbc_info.cpp b/sql-odbc/src/IntegrationTests/ITODBCInfo/test_odbc_info.cpp
index 5568494303b..b19660f7e53 100644
--- a/sql-odbc/src/IntegrationTests/ITODBCInfo/test_odbc_info.cpp
+++ b/sql-odbc/src/IntegrationTests/ITODBCInfo/test_odbc_info.cpp
@@ -303,4 +303,4 @@ int main(int argc, char** argv) {
     system("leaks itodbc_info > leaks_itodbc_info");
 #endif
     return failures;
-}
\ No newline at end of file
+}
diff --git a/sql-odbc/src/sqlodbc/info.c b/sql-odbc/src/sqlodbc/info.c
index 13fdd2fef90..fc859a0d9eb 100644
--- a/sql-odbc/src/sqlodbc/info.c
+++ b/sql-odbc/src/sqlodbc/info.c
@@ -1875,4 +1875,4 @@ RETCODE SQL_API OPENSEARCHAPI_TablePrivileges(HSTMT hstmt,
     SC_set_current_col(stmt, -1);
 
     return SQL_SUCCESS;
-}
\ No newline at end of file
+}

From 28abae993b098671a641161749201c9e71a9f4a9 Mon Sep 17 00:00:00 2001
From: Guian Gumpac <guiang@bitquilltech.com>
Date: Thu, 9 Dec 2021 14:46:15 -0800
Subject: [PATCH 28/28] Updated the mez file

Signed-off-by: Guian Gumpac <guiang@bitquilltech.com>
---
 .../bin/Release/SqlOdbcPBIConnector.mez       | Bin 32630 -> 32552 bytes
 1 file changed, 0 insertions(+), 0 deletions(-)

diff --git a/sql-odbc/src/PowerBIConnector/bin/Release/SqlOdbcPBIConnector.mez b/sql-odbc/src/PowerBIConnector/bin/Release/SqlOdbcPBIConnector.mez
index 2dc7d88dde04658da32a33a8317e41baa9617b97..e830c80222de41818481267af836205326976f47 100644
GIT binary patch
delta 16690
zcmZv@V{~o}uQpoSw(YLktE;wcx2v{$*S2ljwr$(C-Sg~cpK;!^_xH_T*UU&VlKCge
zHIwIW;L>kkfV>na7#a`|5ERgehPP5rdUeq`ED(^XG!PKtKT=@}12Y?2M<)v-M+Q54
z>n80jn+<N1ZUH$#s$M_s*H-Iwn--C*t;}aM_~t2UoEuvtuyC1?KPEI4Im<S4lp7J=
zh2B9~*zx&fQqkgLowf97pPZR{a3L&--!C~oqP!n~FhO@zh!zsr2D@z8?U5D$Y<^|~
z^}`KHHynr2Gq`Q!>SLjzV=|cI^}>ngcaT^DOI>7wb8Ju@7Ry@l*JNkPWB{XpRCCht
z;sjmxoy>6s!oJl|LXE+A+Dka4L}sm4wn<)V5?ZDksmw%c()9s;{|Mcl1%ZhX#tyNy
z;2;Ko7pB>3&QbhB%&2{-D=O}oqJIa%AdzzL9u8>ODlLNRISfn@lulE#UEIw)Fms9i
zQ$c|eE$Mtuv8mMyv#^KQwFc`}i`7v9IbU=1+~^o}q|p2?zyw+{R*Z=E2@zN)3b2lS
zx0A4YU6ucmKoCd>(}(Jv0dB!e7OR!b_QM9C(MxnMqLtgGxLc=`q-eOpuXzSRxhr6r
zGFMKL_2QZbIhOVc6IjuV!EVBj(hPoOK#B;Zq(-nQ0)Tcw=ZuUQ8v7(e{|LK=UcUHV
zs|km?+C_(>nVCHGI2^=^MLg(FE#&JJF&*vKxD@|X>wo?-_G34tHQrLZBuX8-tkDPH
z!0yY6p=7+OE7BSp8H8#k?RyY}>b<S`N6={p^Y*D`NJcOeMXwim9dFbyv7)`WA`Tx$
zrC}Dnjs?7hcMEcz;;KLZ=s=w*wdYH6<^F=A?XIMo0sBOxGQfgLU<SrHpkRJ!gF~12
zDAb(cCMx>ap24#A8VR_Z^n05ijFtfAwrGC4OxquadwCC_#`g#aq}2=X8Znu&o7EIw
z4v{h)g?0Yyx3&GezNUVs%IWbs7VOEm;hM^@>Z{59n74a8Z^HDL(sZEdmpS9ofzy7i
z+|s57%%x54JK}`LJa{>zzh&H!&f*;}0^jzQ;bZ(_BJ{WF-aoTIyVAtU_!9s~8!{ed
zhldy~etkd|$4&$ZLO{*+bA3P#tsB%Wr83LN=5QKGgK0_TBo=htA`2@bL9Tm(Wf79X
zWG2tF!7F9yPDZshZZDLky<&7jflzpjlJkKV0g4_|-cAusbr<7s+7SCGE4`R#H?5DH
z9m8RktAgs-we^p*JVkj0u|WkiPNkY>$LIK#CIIe<h*4sLnJ>bgi80nBV@f&JGxTXC
zF8Xumv}p-cUISX<#Jn{EdrW;ryopuBRhh@P=_~^Yf$%j}r9I@FK)f(d$ftKlerFPQ
zBIW^6HX#Fm9%1dK2J_*&CagX%U{me?Hs{qfv(iUg;!3N_^!5P3OZx*Jv5*%braVMA
z#{CLv*-0uVWwA!c&qtTUe@;lU@x>J*K^&39XCZ_RnPN*pgb*{2yCCqv6lI?UiS4`h
zcNb{Yl$M~VA!Bl1EDW;290(&{qA=EJ45BkA;8j(7g)VZ==Uwa#(W{T3W&ctK00#ou
z35}!e(%fGnQc^mEoGAbX<;E8dxR-wPE||uj@LQKJEH`P_-+!<SsNdg0neen98}R^Z
zi=ZIMr8%!X4@fR;Ri{?QBl3u@@yUP8_ci+)c#-3+*~010`skmGf2~nUIVHGm?c6j+
zU|2KAo;-MEi5)`sIR#Rmm1Hsw8w{@m;xb@wr+Q>ZV&b&usOAAu3744|Y^uWPVSO%f
zJ-l$I1H_|r;kQZ$O&8bid1LZ*ilJLKwlg-hmf4xJM*JD%1#yNrCk$X;(-gEPK#*Za
zh2q(`q-Fvf1@I)=+{8$b2*L(17&B=GW9)HE_b`1ZlJlS%szec%oaJ5}eQ;TOf94@~
zM)@zh|7bACWgP=nDA6aAUY<VN8`&6~iyF7HZ-UkR%s+JaH9;;!*%tQDG;g)wrw0d}
zc~-Nt)*FTWy~;7lQT8BUsVdgxZLIfdo>yBm>`>EYMe7`AZkuQ9-0NJhB`47P9`y>f
z@h}JMaY(q6?^YIzY&Eev7OjlxCMinuHQ<IE-sm3CiE03S$P@a*#JTuL&pH`M^sC~{
zAK&TB+0y|$)eF@5CS3Q?p9RR)eq*=Za2S{xvBur?`!rM3`Usx^_t^U>J-Yff&(zwy
z_l1<__`iU5Rz$Z`#4qF_LT!vjHN~1rs*taA?H!qlPH%gBbN-TxjrpTvaaA_b@5T_S
z^cIloBSHec3qknhg24dy$^lAoKkyLWm4DulQTUNwX`c_({cwYxgESFBdI4Ua+WQ$6
zVb?L~sR575MVmO|f=8Xv6QXUeXIKq%XES*!3n<R?5%T0B);&$VAob-X9mv6lrhKze
zI;b3Po??yTnk^eG^W4$_Sxe1_xM&inbi-fgNvr_oGCvvesJ&DeniCL+QM#mnpQFVM
zZzyX#VNB<cfOY$-P?YO1-*`BL@6B%jZu^{H%{*7F2}3B;tv3m_8qr^^@d3z7*R6Zm
zksRH67Q0MUgK-<qY~=~1)kq)$<x%xcV?VB(#NZZ^(fh!kFg`bPRN>kNn6l_3YKd3e
z`zye%KSW5$P_M&c{$H%lKN>;x#jGT5Uc!I5i#(;c4iw*8cytb5I8asc!q0Uk)x7Y{
z<IR<vpwbVoZ+v9Cq79KM$3*bs<xZ8h<&c-T1G>uT*@TA0tx{-<Y?a{J=hi~!3#pQ;
zkFU;6579jSo+>o7oX&p8CZEm76kDXM{0ax$4$z}4|CZIzf|m%ID_xr;+2&<ZiX>ni
z6U<g>yje)Dh0iu651@0hLh|9N#d%TY5Dcdg2H}kX4+c<&`o9}yWZgF{XBC;?N#x7B
zrjnuI!DW)xb3PWFE_)%>5pkhk%5x~2H5snyRq?oUiaC=rBFw>?uBUC|?*$z!mjVNl
z5xTJSJDt|gntv}qhtTkD;}pVXb*tQ-J3yHqZBQ9Ivw_tzT_S<j<*}|z(cQpGNZ`ST
zV+!>uHcI>N%gtEGDUYx&tVnNlrv{njA^>gZYr4QQ+@Hy$8;ttC%jm7QwnrUe(i%7$
z;0gN=S3RD-AmyG*_XsCp2Anb#dnExt2IOePHwv&?-}$}lxM%K(!kg(Zb3{H>knj-+
zJf7gx3wl(iX4bFgvJ5xqis%D$?<+c>v{*w>_x>VqWuEGf_vLnuYP@f}Gi<y&u&$5T
zHGrkpN<ETzQerq`6M5(+l3)sl$Cq!;iewsx0~^U57YZI+#Y8K^@`uc25_AH(2Zhg6
zxCGt2-%^keL)%=>P;3^9lEt<p!uADZ#^l;>T$HmQ0N_-fj~$JOrFf+E*GTAI*mDEF
z3M&;q69Z)M8<!+>u-8@{-d~*Ia7hWzaAXLdT6T-!Dt*;m8a{<x1>nzEOzPm`z8NvO
z+B^r$pWL1EpF$Rgtd`$jYEJ->Af-!<^!FNEUcMlSlO4iEK#q$C_UIoE6Gd~WTh}+g
zOT#><w`C|21Y1vZt|UCwNbrj~UuwlL>KgI2oTM(cUA66vyoKY!C%8mtUhq{H3p&*h
zg2x_n@70}F>@%>~A5(%`TA3ELK|4^j>g!w-bw?DsF_N($PMqpEQDFhyaZKIp-3@NV
z(MP@cVRAO-k3gv@BMjK%H*82q2(@mGB&&$aOE~IuLD^eI2wlsJ)T%tms|;dAM<e%s
zdVh6X>l+tz9O|@LG411urARfO4!hLI@;%ZPmYYg0mn1LdTA>tFo*KJ7qIV4U@&@?v
zC*8)5(GX2I;ukX06cYha8dArq2AX)~MQ$v|SH`nS7)gR_*Sw>lyG1Wb@~P*00sdai
zaQ&f-`ks}0JXb5M@H8ark^vs_Q_&!hI8@(_A;Hr8sHQ?8sPGii>(Zcn1xr~7JUC87
z%~6Q&TuGq!c~Blrv+|uK`@XF5gAyqaIE!;F0n-xrZ8k-M-?jiL(Uhr73cudxTHpu4
zXsc6M5b)ZU*xw`d+H}flD9XwWNnj0PoSAWndrdAlrrh*qlrTIvcJ^yxpxI_TwTft>
z?NJb(q}Fnv3<n?P@@4x%v%5M3IwyaE(+}by?VXO;mKksVR@(>d7rV+^n784HJIHnB
zpiLG5Gjy?5oLP%W9%O}&(6hzRs!Vz2rSH@k(QtGtTKrUamq$r4(*E^~iL;RRrj?uc
z@F;y=`T_pWxDe<Vpkxcb`Z-7h1SA!gzzv57;Eeyy*6XuPx#X-PpNQ^qbW}l;Si_Sl
zlvZ@<)S^x{VnJP6S5%ERqi}Bd`D(xW!|n@VedEoiQWOs)cThBE?gR>N2M~DudfqEr
zgV5u+7}?#hdGY>O`TE*P?y!~9<KL_zd@-BonDXfOZr_+Wuz&3S+}@<`VYsnzop|~S
z_?Z}ZpZGqwa#^u@u1Tr*cp}{RIy$!je9VL#&uoR*+J1ji`0gC;J-1ljO5HwJypCM4
zyQ$l_-uUZ%(;~gSYWcu#%Mw2cwaXCn-1vxJcDVLkYc;?i_#Yc=H139&u6*MH7M|XD
z5*bft(p4JTw%BZUx&!Wix&t2rx`;FZ0zMkm>7K7SRIfdV-%su{R0A)THaFdZ%sBx+
ziAQ1=B}=kR*KFjm7{+ojdg)UkcMdNj4jYFVE!M{;d`q22J=<5{t1hK)C4Cj?>&Yf;
zHRjE7h&)rp)RF62hZ`L>P^xe~H&Nnrj3rO*sY457uOeihT|*RW=xE%hG@x7nzd(Z&
zdDR9OMFeOvYGf7^=o}S%k%oxnmnbE{w$S`Sx}o3eVNcGQSt}OoV^i#8B5|0pkJ*Jq
zYbu;F2hD_ip7X<WH3zjYb%_C>1sbbQR5R7_`3~vqvNQ8=A1=b&9I_3yt$l;YGHA60
z4CLI1bwOeyf%FDJSKRO7T<ArB2D|VwN-{RRND<6v*^a?6R>Zpa1JLyo8ZN2YY@_}#
zi|j0&prF5f%q9bd$!OHkQ_N=yaiJJ^3EzpcrDc~N%xB6;)3q8SBc_TPK@D8RfWou2
zC>q~Kxb&s_o7Y8gwW%++U8lmLS5CX&>d~4kgA7dfM6x<+g)@z0%rI(zXyxh97;70A
zn;^q6r&}HMt31)NEV)3WksnT5y~iTs)`;~=ps;Qp>o~*JjoF0?DK0e%S_#58Z>+%5
zw2j>c-qNb<_&VNFudMGn9-F2xh|}_KdkLw0S;BHBaxrfA!gwu<Wo$~C0$isgP)DWX
zRFq1G5bl;F$RuX&Q<z4;gDiJ`^_YB&<W-^aF&rZIC-xLp6ZT(>i9=My`AV7Ldx`pN
z0utNRqqTkddodk;1X*Cos&0w?{OltQ=V}E?I2r`ozw<D2P(f`JnRxR~DRZRh)}~pp
zl?@^|6UG`deHkvQ;YYpc@pG(<sFvC2Z=31H*tPxXMk0z7Dtw552)p2i$5{oShT8<C
zjCANH*0I`PqYx^3ouW8c(fxKo3R@0=ZPct5qA@2;SEb{xFolzE{zaU`spA(@RI8*o
z^i2*u1M(dj;TEI=wCB&~mm=zv9YEWLO&=HwPn;aZJdwkgKeTxsGZh_HNXOH_!U2qQ
zlMJet*7goZmPIT8HoD8d`|aVwV`GztZhH7z_fxMOn6}MI1U+9>!zSQqrH0X*U#O*i
zSe%ttQy{Qo%k=HY0@CH-%XAEW4N_8pz2mFF6q944W31l26_8!p)E;1~PmicC>W|;)
z?hlBP4UlON;c7$duI2!f025F8Y3%x{defJZLt8c!`EUii@*@n94MAL`DO-=R8E!j0
zaOW_XYItY&x2I6g@0RE@tzK{vLR$z%OKHGvyW~GkGn|pM5f8zw8Gg@w%9D&@f@{*k
zH<VY~979t_PAW(B+Gvy-L4d!rQCsbfa70h0ymj6?{1kN(64*P)g{KJRK9F5lj&&<0
z0bL0#1M2`tiYc=?{~|5oQ4GUn5m+;aw11nL2`=x<Nf=w5tw}R9U9I{}+_!EbCs=di
zhs*`Zf8(I~XxO@Vkl48H`fh{o<aG1)>SY{1`*eA{A{SO{d9@&$1V+%Luq`QSjCLXd
zEZHw|eySAZJ=CTMX+ExYw`O#5%1I{2naUM~H4Xp}qH@}dzceCQk*x<RgX)Nk>M|(v
zc5R~EhILWt{hQ!<vwDJxRh)lMUjBkTIdZqbvEYnUGr@x_=rd=+`&4ncQVJ$nLM8&&
z-|<iAY4=q3d3~P7Hmt+piR?WCj%*#hznGlgmh=JFk+C<<%3`D;L8`u$GW269JNHtM
z*v|vhNQM_A4;gCi4I)20&5~auZN2AT;Ji_kRnC=FXrgJrtFHfPb!Na8;e<>1ZXB|$
zlGD%S_k!Kt|Asd&+wJKUf494h?hOssfjThO7cW+|3?}nGa-yh|5vRD8AyCne8k_Xc
zMMwE<?5OKop-}9A&Ci)Ttbit~!j~)+$!-bQ(yUV;pvAJMXc%%Te~KqQ)n_bLP(Kn`
zNmnX(tewI_+F*e-tFQDk@G*3tTL|$gF`;mNEneXLn-Uzbu+YV^2^IELkBOiNfhX-0
zr&yG4^TSgdTb0jAf1<?nHt}eS5qs=a{6*Ubje$?5pC##cdP(D=R47X!znIIEwlDz@
znU~}sMqabPKp&$UE1wDE_yb#NQ2S05FM+Q}{A-o{iv_*m!5HJ0`7C>Fu$DPemR))d
z^X&w9>8iwf92RWTAB%S4IE*-JR(Ch?(mu8_`}jo>tdgAB0_=5FDi{eMh;5AI75&#e
zqSb33Ue-Qq%cQ^hueV5rwaGWV<5uhdHHQ*RYX^mXAgUZy#3>hC-ff$2V2Goy`->G*
z(AN;c=q0N6gLZ34BPOL01)|Jn&O^3=Q59G*-9CQPrCu@B>M&CvSB=#8l1^<UYkf&-
zQ-spcUbkfEMTH`@d8T}+I=fhvxDd}uH$+ha4FYi~L{UX52)qkfa;JM5?NtImA$57^
z_i6wH1V!sUycOaSCyjZ_Ym;wp&H{0z;sR0?(d<Hxe~<RbL*ehMi}nQt-QIhy89@Ov
zGiO$K%p!wII44w*y`dWSDFvq?bS`yj^%4tiuAs)&WY#w{a(#}CM$(XEAgz69aXg0O
zUhNKF)Dj?AX^gVTB0@aQNBn8PDu8O7%wb*NaFjY(dRSt})!;DMz;CP)@<BMNy)D5k
z<#$}xS3-8yLlhR2S^|c?(HJk}Si|TX=7NBxc!+mWq8>x8xm3J~2mVa%Da<7LB688l
zxSDz$Fg_y;t7Y{)Rbn)#<vlG-8RoumylL6*gBhc5DVSQXcsV{aO6dx~e1%hbCiauO
zpI5L-pxj%HGurfkJ$H~IitBR$mb)1bl2JD`-nIq2IWSXkp(_a}&I3=IjO4@?cik?E
z;HG|T7l|xPz<6e*_)_1b#dTKxZ!(}o2jLK;&!EOhg{0)+MdgfOaY%9aK;jSR*yxbo
z$?U@dQw?YEH}OF#Do}cW22p7#C!Io-{dS{7@!ye}!Z3G0AvW|7gJ;4x1B>yr8e}d)
zmDO~|j(z$<>GP!+XIYm=D<Eu*@+4W6n_J;N=ENJF)2ZSDV@CL>RPk3D4eIniZ;O?)
z*Y7?ZZQfQcQxxjew}o1l82i<OE-jq_VNZ?imM`+cahxSvHn0zX^~U}`%#aW+TS41A
zUe;5kYxDJz1t?v*n>XQEF4_!=bru8H6O#C#zBXG^<3YT35545Q*MH1rAvy?maJwm6
z8$3Rc%B;;>I2>!)gi=|R)Yzg7x(~_>aCq*k)|ZI6@1|>N3gwyI(kxyII<<Z}s$%Zj
zXg}xjV@skSwKKp0GW5(@brLOAlifJRU}DE&Wsy&LG17vW7Ialk+Bi0w32EBKDc**K
z%#|-U<ce6oEJF#-OYUgM{%-Rm%-4Q(OqbSM_>`p2M--}#yXh-6rVYd7MJi6Ry0kW$
zvJrP0IhZ5nto<^=pYtSoZY|3~cAbUdK^DSVye@X5MiXrT{5iT@e!1x3uLjsU^*ey0
znmd0WZC0smY+e0b@#w91Vo?95np)0img>=h3c{2yT9f^@L`53X%&O2>PG{h+Fz>2M
zEWZsnYUVCbD@w6q6G``my1&D)Ooa7RL#^YSg@`PMWikjKR56e5oY1Sj&JYNws>yw*
z<yB)wu;Nh$e6tiCF15)gh1g&_cnTdh1i7{G?o{5Sf0V!%IyJM6+_0yZaP;t4H(qyC
zOJvhQ$W;I;mjR(gp;jiPlCSWV#km{TJ%iCxjelL((DXv<l#xumcjy2;TWr^#t5r*T
zMs|RX4)m^72-}u_s=fumGN7|yLBuA1*IqI$l=Ko{;Ob9mk_NIZ?$a(Dyk-Kt4k0EO
zc~w@+ceUE4wMp{q`x$9nVo8gMxD_@N5C<<>UAyI<GwBmQMa<~81g$9Mo{fo4&gD^z
z!06Y4fNd!xVg8sJSxKB02#R%!f|Ym!ZBa(5*S>l1-Rued`KiFn8hBXR^RF^GuaHD2
zz;#Px=Tv)h{i5DJMRxGv^is)EPYGhNu}z3VEeWx0nZE{V_<UW&T;vw+&47qBs#cm}
z&rovBPSS;WfF!xRhLoSrxpHQLnqx@43hMUmYFQEa^x8EeSkpc|s<@;7G*L?cRA0^n
z8tc*>n*vy9936Ym6l65J0%4pPSX;gT0L*zW#|}+|J4@0(1^hTE4xO8qb>2Gxmg$oI
ze9kng_BVh4zzsG*)+=Mq?Yrx=ZD423;U)J9;0|u?P6SuTa-UiZnioN0)vXkQLzrA9
z16<>%@7!3&p=4O!L;?@62vk^JHHS^XWZ2Sg^X#DaqvA?=?ygY52$I!Btg#>gLS*S7
z#^LB1ShGa2>Y9VQmqLwtg4IG}d_)R7X)7`M4Y=Lj%H4O`sy1vdrmn9oC}o(jW=sJs
zUWMcP0cu&}>+j0te;!L!f;d^hBf*5A!69|Hxqn+ie)BsUV&1AHH^H1RbJ+_AOiy?q
zcNqQR#KB6HYoHFm#=)|v-$)e#pn`Vcai_)wAZN;BBoE?goa=h}kMg2Sea0hUosmJS
zan|OWud5XBO*dd5)R`1zQPZUUG8LpV<W?VqOH9=DNm3)xf9-1Opnq98^FjgNH}FyS
z>&OsZ4qTk>jJ^Zh42Q8y%`IN#ml=*PXMB*mWmG@pxmvN`mk+7xC<*caK5$o0*txO?
z^8;w;Z#_4G+jYL6uAgsw-l<<9jDY7qjx0)Cg9jDx7oTvYyGBeO2sd)g2kozPKy{(~
z)0*W$w|Ns(c~!#BBcDs*4G^5?>-?0=s{bm;OWEKD)T0>XJ6Ab|Z>6hvbgU#{T<Uoz
zp?PS9d2A_Un}pp4pSx!R25`J7kc_vT^EC6Zm5sc{&l@L8-V;rJ$MD;U{nHR=;y*@Q
zDwUTA!bV6WPu!B?TspLghvUYNwQwZ+X$I^8!+*t^o$Ivf=H}CA{EnAds4veWw-3ty
zQVqiL@fta}BCz~Kg4PVzcr80d*pK*ZALg`_qCjgI@2n*gnk7>K#8Ie8c!rtkCx`H0
zMJNWX>jRNa(O*a?ik#?oR(u*IaMFceHv(Sg79R~&@q9Q>!3_9E@YT>!$qmy^yEzZX
zq3Gh}7@?=|&hyeP<WZNW;%U$v#cT+KjzcZ3LK`t=HuVK7jb3@E&n;ZBIC+_B#KN);
zQ`6XKFxsU?GqV7ILOvt&jSSM^IYF0&U{85ayoI5-WDA#=yeZ6Le7<SSG<0j?gROQ>
zZ`xyBIt8;S1|4smp0yvT4RiOGAPrSJj(3;=t4CfI*GPCenD+geC|5fyog!ub(m(im
z5X;!r<=dP$<UD-W?aIdyB<CbPqs6gdNmIO#%zMvK>Q?apoi3~hS4J$RkfGx4M(x)D
z8%Jz)<}rgZszabvFbLI3@IBt4yVS!Wy2<>(5tc5STKd{r&ZZ-ks{6I>Foy{wA(>Ve
zEOm6?Z<6e>E$37ibT<wS_;9jJN`kdGYozk5qX1HKlJ-d3;4u6dNn1xQE5v}RG(V0N
z#m#06_Ua*k8DaC*FM7VrU7&6Udz1iTD!Oia2Ljz9_q_yyrou8RTgWK`XRr3C=jr$7
z&&?9z#4C%+4Faos=t~;=YSnx}BDDM0VA~pJ-EE!&sAq?`f$%_r+7ft0h2~*0O=Qn*
z2XNK<E0I-(%BkRXb(D#+Y6pA-ouqAiD9$2obrxknHKCM|kn<C1%R58<O&UTTSZS!k
z?V%O3Ywa0cxXJ|*RCG$2PVV9ZjT|!?l<AD&7#A!g2PJ}uN?I<uygOxDzXy&%6XuCw
zi@6ww&o>QS>L{n{`v&dE<Ol>TY=Y__w@i-OS46#8TrFE!yOZvPV=li;IU{Q~n3jK8
zcGepp7vs4Y4D`fA-6_z{<SF-Udd!+(BWljQmFIZk0SUTk=vaS)muo)i$v7Nei(l>%
z@<T*+U~!m54`R*k5csdvoAjpLvE!pDdrm~a(F`(=WVcn_#i&`cR{FM;qsrcziB+^F
ze?y&c`B>)(#?rdXDRRl!pj8Z3%%8v<FhWGYRWk;6sK&IiW41wgG>n4Ud8H1OiG|z(
zbH<!zg($_lyo2ksbk0dpcpk>X*fc6}`Ywm74^)lPOuXbO=~xMj&`M_hu)7a4Y(#`d
z^adl-(cENXA_Qw*gcs;`+FJtJfN`&8Gj=o5yL-76&cbKL{y3Ra6(2-@vu_b+BaR0^
z^)SMnubHMt+@`t@slK+K6{M1Yk~L-A7-oAUdy25>n)zy_0y%+vvT&8Te$wA0H*Hq3
zRu$B>>T?LoHBQlU)5Ohzr!q5V{W<I;3>+m7vkPjfT33EVKy8$cilsU<mYJwE?cg{p
zi)6H~17krXGw~1ltG$iv1hawVT{9NoDm1`c&Ab~3Z^R?L|97ww=3KR}0bUE{vLqsf
zEF~(4Ayzs$k?tt)nRG3DyyW~288Rz{j<mChe~N9_ov{otOQh$F%TwT8nz5QioSEVm
z6DsetnZaLltB%Iz3$mNfGTpUtnn7={L}2@m(iyV2SqJ8vlOVIP_GiY<=>crOOmDjy
zC$9=$$D-atTkU9pd=gQ{HCEZC>cFCDD7fIQrutF20!$_$Wb%7FeTdQt4P=41r>0#J
z#mc8<ct(|rEdL9$@ZnRf(DB10l6z)vINXwTir92DmM^yGs1qTsFvCC~uDn?7BMl|a
zjO;w~tJBeL5a$GWFqdl-F-a?c@XjjlOTWUnZ2fHri^JjRSA=(Cy&qJLy+Qf`(+Xr0
z4(TNwGaIEr;%idW=5&e}T$OAcJ-vS%Y)DsR#Ds0t_BkFA1o)KrJj-3I2z^d`c|;IB
zHG}fCrbnI`kqUZB9-ol?TXT=e0||0UQ5HQr#6{QX2)Z_z+8g+W)nO~Z3L6fIvp53k
z1sp5)pz#-$2GSalqx34Bs6q3KBbU%iTi9NJh9XvW7W!D)8CpgIyXwR7Th(*g1$&_e
zwKm_j>|zBBguA-b3nf;KG!qCWy}RmC_n9FEiRUTXrviu24l0+#@ARvo2&*qn)$aR-
z@xyp#G@g$2y1)JR6cPG>vL!}fI7t2+6sdS~hkBt+a!bgr@IoJqX!O{`{n?iS1dzAR
zmt)4QtW(~|*Hp;S(x(I~K>FSRw`aOG`GOw=9ItO4M5=2qc=4l(?tWJRT^7A*_q)`g
zDCVBc3c^~yLSzT6jm?+IVHx4CP`9#&&*qXzZ*el96aoq+BzZi5Qdw*CkV?3jU!HeB
zYJfT>w2nA|e*_XXd6YKRd(&B<zwG96GOC>Agv3i>VNaj$yz5dYJw#;p)3G&!e(y{o
z&Z2o;#KJK2)%ULNKv9E7rt8fVzEjO7SE~ieu;~&hA=<fI3B~iEcXUJM3!Vv~x?_80
z0BecKO_FwRp-D18EzQ|^@wnNSYemX>QrZpwnN2xk0|(NhK{Cn}89&&v)I)55W^Jzn
z+?CdDRiMTZY1qPCo0-pEVM|8nf=|?6fg|pc1DhIgtZE-QK|r?rf{Zv96=HEK(%OEj
zA_~m44eIC@iX+)Q*GMu1;pD6a>T8=OhchE_sZ*7rwRJiG#l&`_lzQ&rdLqbhCTxYM
zrq$;AeB*f1#IdK9<z@2g*UvibvA83<3zx4z!EQrct6deI_lJpE(Cmk?vww+KQT^c-
za)JEpJo>9Y7_U>W#<u2wDN)jRic2(9o1;g{-9Ff{WIS`1@8iSc<)*bGMKxo`RDcr_
zO5J4ZJ$f79rfu}FU8zVF!bX!k$OCL>44!3E!8PTI?qL-sHjh;5D%&u6-O6krjYO2e
zxV=Pp@|4yNWdaJlTRlt5OdscIvKfOzB0^WI09=+n!}zeTZ*i>6)eT>tli}ek-xb=n
zPSLK0YFSrSvyz|8&D6U4ag{eE^V=kOU&^$td1VhUvF=kbG<~z^vxDQcM)0yrEZKp%
zQxnH4=Sz23>|H~Vyz!oAV$8`FiTxp3ymH0Umdy=B!h!Cw8iMuKTpi<g(DqiCml6P!
zh>ObC4}oQ0q$Ha2B);xejc^99G_*H;lz0;TIL?!>?&D%o?p!{S_r7!>H?|_~;a06j
zbY=i(^KdB)Il7V}<=bT6K|eES^N}hHS-W40?S>T9hEE$a8_~1!kn&$%Qs^N#D!VO3
z)~V$&MpZs(SYd-AT@V!NE@cM6J;GaEK8DdQ#s+OxX$MgwhHPH)fFwv47b}x8P83HR
z@8y=%F=*>v+ZK#4ff#y5Mq__tb*+uA$*lz>SY%^D%-><7p&UG1DdPVK8ko6X>f>|#
zF}OP}g?I4|!?@HB(Y-99eIg}nO@fHxy(2y;)1Yvd+5Y2?5JT;7Dl$B#5l2Se7u~6j
z719SRnC%wlSm!-Qau)F*D|LW|k%_=_*%y9$kHK|MT4CrHm+Rq-0&gOnd^z5t@DKlw
z^>=YA;WnK<G_hm=VX;}4RXJO(&21xHkXJn`^oGS0$&^pzd`sbXWi%o4B3Oyh#JD$U
zf!q*?ZqP2o;Yx)?oUo0lr?|Fv1eu}1F|>9TEtFl#n9v@Lu13%<xm3TozF@rAG5&~;
z2%Y%gF}YM<>49Qra*&+h16ic1D%k>nX}@Bxu^|^Z7+$Q;!a{J*gt??5E`KAlk(x6q
z3JsR9L%k^q%>cWITC9)8mbh<P<b(h`8f=||!gHh&=0>=XfP3hnUE2=2N%wv%Z`Zj!
zHx;*Ft6~LN4h^4tcd5e^S!hq;A-!MTGjOutE-q5RlAtQaT&m8!k>6j$>EZ%#DVB>Y
z_~)ELE=LyBn77$Jk_1$n+rBxe4MNS^wKa8Em6;Q61^Df$8EbbgKeTH+!h$z;a8HIm
zjxfibTAQtsx;o*oUn#00j4h6{$~X*52ToYDK^jC96}0aNgm-jM39=yEZ*T`$6cKcL
z15y@pg4mug@KmAyw?j7LD-9<AJ<>|DA;@f&3mp#41ccUWQlXXxi)y`fpUFkqQ59MV
zXR(SMxgxYEH&o)JF>+~GQ(PTI7k7dgnR0AP`)p}AFduhZ*V{?~D+d43+=PgQeh9ec
zb9~k8ZWy(}k&lAWZ$3tgIlMm@hp=<MNk^rak%JppTP}A+lkO`@v=A16(@w-j{#gzu
zXqf$mj``;|j%OnpN#OVG1^FD-y9J{tGO?&7L(jWlBFxJvYxKZtY#bcp!GHw5ZktQS
zz_T3*Xa!v&K0OPv-i3n{ZX2gd!O>t}QbbxrgBY+KGk<@Ih$`q+UGKHa4OZI09LN(f
ziKEx(kku<<H7WWESi>;D%eL4|R`iK1D<xoW#6z4!;}Dgb??Fk89OT#(`gLEWf6>&l
zINi#y>smNu(BMzyev=z`q2raSq3-Nka-t_>X$~+%+1Kw`7HxBjsNcH;?+GWT_!UER
zy%>5eK+4>@4qBx;4jW!fXVympjXSoooRVWj&lwoiL4yz7)%OH|iJ7`I^=|`gMvj6`
zk<Q`zdyIP=qX<Ho7HXe`2|fQcgdY6k1gHwQzbRarBwf2tLLPo2t(gw>IKaQ{-my1(
z`@%+ewR7>ey$o_T@ykn+lvRF&CLDQ`b=^Ibb)EAruY5jPq9AZc2fx70(Bdh=7?dlm
zQ%&jCLWvjh(z}lVS+%TgVNwta73vrvv#KV6weaW$>*f`;(US|mwag?yroeSfHpF|{
z>!C~vBc)ELXbP1oPY=2aGPt?B&7vv(fJ9=pbQsHXl|z<=3kSP|e*87X{W^z$Hc<zl
zJHR_FMdbSSlo+@)L#6FGKS9SUpN|&}@$}fPAg{$Ax?XDnaQdx!j3{TftPvWVhO2}+
zu@LnluyPPAZo9!)vcIRAlS9Kx00}Y!S+Wy+>?`5)K2v%|Bk%m%3uYtfJLhLCI#rAh
zk7*T?9Bv+osZV2B1XV*`IwfKn_B(TD3M$iLjvkGuAKsY+RmR>hBeO!2wR&%Vx`{{H
zyytk@)pRxiDX!YU1%&NaxJtfZAGyCgPKL4M3lKj(&eMdRP7OZR_Z-N(v$amt_Lpag
z(d=IvBuEIRhgT30LqN*)h(6oUziSX%dd4t;)#MNnZ(OI2?c3V7*k0tfOxxaNS`4~%
z1$F_>kR%k#A@1|EeHClxf3)=nx6gRJAZc>vT+guq^m2&#SaM<_z2`GCyA*rMvZ_yq
z1(0DWl!mNRVD*rx$!uS#&kgEt-orU(OR!T=5%wDVjQ4As?vb|aYQzeGw)76CBnI@I
z+J(P{k7rRxzOweL8!iZZwfVPge6(2w+EWq*hi3ZsA#5w!KGXpgKN5iR^2j>WwFlo$
zP2>SUIK4E(_;WSIi=6<qG*aDAm{&vNF6Kc-skD8lt<(qXS0H({$veKJ9P*)G-U(L7
zvuv6+j>W4@UWqZdSwy;?dKQ`p{zrJaUTxN862=7&{GW&>J-=6gMjc@Hs>~9yk@e-F
zy__}jF3GK#6}f7=`@T@>Av_$;#`Z3g2{sfEZ&H&v>Yz(9@p$xH-9gwj3Cg)r-U%c`
zn>pVwi>imszMNk2KG&~=_(n@X<2L53i}md?%YS;6EWMj8L8KMU*cQ9Ls^JTNwfoO>
zx-G7T$Af5hO`1t>9v>cpXjf41^_czoNvRhL56EI?=EqpFNPLD>J4HJv;m|EsJ8S_I
z;SszFi}ildbbH^-3w^`Pon@01!#~g@VO(b!Hx=Y{au)?XD2nTfUc)?;qk))3;4(5r
z4o32v&(T3-o@Bm>H_*&hC`fY(D2y8;pS;JZ>*TBTVA<u^!B#N9&$Qm8kBMO}ZFzZh
zd2*82vKq-Yr$!ZVLAyV?o003YX7B<4i~{A=JyhF8Ew6bRQQw<&?qg!w12B=8b}Zf%
z{=C_|pgmAoKa$%-d4ybQavZUY-?5_p4RAJgy1P;qes`q|ue_?q)K?xKV9p<Gj(^tq
z)NxX0*fydp1X`!HM|5g2LnTjK(m$U#18ceqRlDC4N{=c8!Zf>IyVo;jY`+1R|JjcC
zuVrd*bo(<X2p}MJOdueHf0n5oOdM^U9gIvI8U8_TOX^y-8|-L4H#M9K1J5W@E*ZLp
zs|>S^L*Z;!vtX8f28fN5tJ>6x<YlYdH9LF6<P$9vE(>{5KpQAA-Hu1D(VTAGRAifW
zMnS3rg()tmyEK3m)V$(>LWh+sv$2P{0Kd8QC;}ijpK~Xm9$*Gxo5rOT1b({@Xod%D
zMs@Z47y%FpUg?gC3^f*nB4ltDsnov|^rx0~ECzd;8U9?oda|GiiZgzG=pxiyUhQsL
zHK^ek;A4NZC{vg!V2XR~*bR)vloWp*h2tJ~0!z!}8k++m(;=*Rb2phtolFe+@jzSX
z+Q3aYr5pFDjGfrB;%?CyvMhs`9X5Y6q%~1VBE2e|_;d05wb==Jfu~e|`ZVcpCw!mF
zrWf~8aI0*ZZ1-TN#~=sf^aYFO13@FewHP3y(Y`YEUHn1YtPmHCX4F<)EIZv@H;iSI
zi*z9!bfN^1PEK9T2Q$Ra9nEv=7N%P3q~UEnxYyM1$Ie0v=f(VydE6|nVYYl8{BY>V
zZbQCS<s+0hCE`nr&E3cMd5)jk4IT@RDZTc>rWgE6hj0P6JW2#x5ul9;u2zj~gmeQ}
z?_m+^erwHlqWO10suV6*qVcK7z;RH{qVA4pTSgSXD1XM^iP?`{Dcs9_HxQUqgvO=f
z)_lr}zI#EvbkO5|Jzpo^Iy2AQ@Hu9IA`i{Q`D&(4G+BF67fH|IFL8(XExps#?!N*7
zpKAGl4RWgI?B*ZkdFh>C*)-$b(|q*h7fp|EHe4&@UGPbwkf=_Q$`9!44FJwV9$7@Q
zhr9tu=;^?yeN-6JDqr=aW582B8~lYXrx|XgosBIlI|74ScGu^J%QgD5bSVzSf8ED^
z$ZfFP8gkUoD+#3_a0&l3lZnJPAK=H?1$SR>0}C-fbm_}3Q>;iLipFAYT((5U<O+pX
zXI#6iYEmXMwV7S*pT?y?(-it;H6hJE0G|Ws7|;FV&lv+Iy(_-lQ>i>F`=nr{Qs+9u
zZM}{r!`VbgbvgfputZ0!ZE`0;7s+l)1%YdL(wgW3-XRmtG!ScOPSN@Jttr-DmzY<b
z(b>;QvooC--Pf;fZvy_rO2!#^rMzj^^lRoIP#*)mKY9#PpX+$=#kS4rDZ>?Kq7xJl
zG7rIKtlY5V^EG8{IE*Ew!J$XT;FM)VBf<TMJX)uQ8rf6q5yQh!T1&(%jCII7f}NX`
zx_<H9$3JLua{xA50tZ>Ax|+VJ7*}~U?<1p1NOKtJUy`DbPM5npfcI{*fGKGC`uEz_
zS7B<BDT<9gZW!yz<B@yWwnF1g&(j-l=KLOG`}i74XZz?Epp6lJS}yW~YpTZ18j2O-
zs6#Zdhtc($(71hAX{4leA+OBCfbxs;B@8-Ro70-oH=(V5fb9FUV3H|~OYOPAia)31
zL9C2@;nJXG;{nwetJiX`-(z?Ldb<?LN{#ta-|W0Vn^Jt}Swd7_>Q4GxD}WxLG3{z0
zY@%^<d8x51P9EFD)Oy%`vvffEhQj)^vzqeiJhsJTU%W4KP<%2=b7=-kxTYFVl$3_S
zRgb6DITJ_4OqGOlA!%Th;3Bn^M=%lAl&KxERaDz#^Ogd$(A3nbguJA~_b|J_YV$fL
zx}@rw@w+LvzNU;sq_r#(OHCb6Dwy;m?PYd9@RlN}@3>LqrnSVt<PpR9es(N#2n9A!
zbLaQxdBxJ4kIB;k4Z{e+h8kFa5zVNLw-}85OXObv`PD9Ha_jxEtL>Xq#i!8s#fRO%
zA@$J(%$m|CvjB1B_Lje8qxn7x-VO5yVcjpoH|E+%$;LnXoAblzsr~^VP`-MjCijAL
z{0iqhQ@nINy!IzFdhYV~iXLAG4Az~t$x52?!*-|r?}i_{a(D?y71v;<E1Gbq9Xk(n
zxnChA7ArqFz3${+uxIjj<Jc5(yDxtu8_sRL+=~Pp+3*Cs#|chiavrA%vhJ@N8bGCM
z5c{sJ-d7L@yGzcl9?HhmxvG4Q>I>f*2*t#>&6qiGkNlJx?pe5^cW$Jr8QK72dJ9T9
ziB=V@D6;oFr<_2k5Q;EITERD&J224-_hLssApfZ!Q4V2Bb$1%NhW{MnAScwY5CA@G
zH$+jsbpS*D;0}tp^JTbTE8A_p^kZQR(TAE20Rco<Xl?P$V)hmcXJP^0H!oAy@%vIf
zXd$SvsU)tZW+!h`@?v6E-RR*}BBN=H1&gS0hC+-_tG`8&UzE~n<!u6Y6kbV;2Tfb{
zSk>QB%nl5P1h}&bNS~c2NQ>RZ6#--OWCz~I;C@6njDzqqC(^=}X_vfHC%S>eTJ|nE
zp{(FVlW<4L4VFVs)eNNFn!lTpG_YnpItJEZ(MMdF4(axYU(j6F@HRrt2Yw@uh6ZSn
zG)yJCPrlURpN1aDyJd)%E5D9+#b)euG97GXTgozpcdCqrA?KJ{z?GSQ%ma$O=?jiq
z_PaOj!Jh}&<98-f-4%KhSBLgU2PGT8-V2|8A>#_Bw-#(|$~tDCR<WHr2)^fx(cQIu
zXbAU(E#y0v%rG>lP%Sn;)maj9PeiYKKqIbS9`D1H%b`CnOWM`A;r+>fGn(w62Q$K}
z*clFk@>qsPVT?BDamK(7@dIq{3vY+{rr_^;OnyoiIZ%Gje($;<)RK42=J@Ni3|yKG
zC-7VzQZFw_DSpS+<A*#jgtI+jOA2i4WttW^_6_Lo4yCU_JHla>{NRnn(h4Ahui=Sq
z^@owzLS9ri#g#C}m~Kja((?wlw#(ILxzAFrq*J1L8Oc)ZsSQ4z<N%^~x*S(?z@O?%
z7^i+X?Io|31gw(20?7gjJ<IUA9H52pnHZ8?Uo^?RpPw_bKJ&+fvN3QGb~RSz+=RJ2
zd|9a1-DAn2ZEkX0JU#g`P36(A-!;b>e-RPCNMSCWpaD(zl;j47OmXrqa~LKtE2qm(
z4vg)(miaQop{1%B8~~a_d8yPV;X)F^s|MS3ltboGHNNJR&UGpLgqmY$8Xq-SuMbNo
zDa=Y5?sAXu-%dPuE6d4t?AN-#?=7vp8P@9SIz2*^5cu4tXFl&3@vj~)E=}3LUpGEL
zM>_U#QH99E>Q*8Gy^E+4&WsOP-@efS`*AtE!_>dde9G24mH<?M&rY?ZXzQ|PRw;3O
z6Ds=EyEbQK23;dUw>c{p;C@2g+_RN?ub0B)49T*RQ(^h}GGkiyk0*bb5Hrw^#$(x>
zSPDV?d6g1twOPR78CEXng=R!|gPsG+QkhO(t*XdCe8xfyVT~xE+(|*k!^N0Bf3~ct
zzC=C!<H5txK7bX@a!*3;bVr|?D@WIxD+^B4B!5lc;%B}*C)##6;qCN%!klxM-!p*D
zGYVBfqp@T@NbV^%Lt|^IT_*HyMz3+<v2o?JzC3-H;pF8rfQp$;@fSf7w}UhhqgL>s
zX$A_XRFQFBiWSr+FeJIQ2{Djzp#<xFAI%hrAlC~L1HfiOR}WgxLR?(YlP>OMvLHhF
z5=x{z(GwVn%->5Eq?OaS5K2pT%ya3A&CMTJWwm)o6V`i}k8@LrUy*9dz;<=Y@cU+B
zZtC!H!hFq)qf3`%p~%6eym;%0H?D(rcZf`02c?9j&>X@ZHBKYh`(t!-;rV9i*Ln>m
zD7Gn&K0r?Jw6RxKOPyRevq-CyWshG>8{6xzbP?3p?+5O4htbXxh*)ixAuq&MVyiRY
zI@H5cmLuD@X_l3B!O5bUlnrv6?Pmw+JDe7_LYbbSwlgCAJRo1rJtD~^2z#0Z+un2j
z9iD>x1N(L|HQsS8<W0Ee>{+DS+!S^1)`!nYS-{yRA9wJ>^OcrZ$Z&%+L{M{P{rR(%
z$5mSoy;qgTw=J>N%STQKvv)R>$pQAvP`yg6BazM7L;LEI&m1e5w=Tv2J65^2RzxkI
zfqjoE*0gnI#Xmn=>#qM{Ho1z&o!GPC80BhW&*igw)j9eg#}}+ahsU+T<jpso<ipR~
z2LOu3_H+r#Q*&w?Q56s!NIY=}e;AcAalq-yx9p!@&OD+Jx>d7m2XdnQq#lJy?%xuM
z-ag;=^L4kXtWce_!)_Uc$5Elo?KM6$L49-^6Wbez^Dl-XPD0Dn=tYw^huFeh8c>4R
z6hK=QG7-rmjK{CRdR8?4n4t}^hfNyp9s!m}x6s3?U?aJ)Rb+5-zzTs5g&<L6J9+Bv
ztTMI?9j)BbZh81xb`dvc9u*g>poCqu3x@MSs9blFF_g&ort-?-vy_)ipkr&pmTIu&
z2(+A`v3*~tP)(Ts!U2_z2Qgji_o}G;IArx}sH%UE&CpDcj`!{(O16?;dyE>#IsqID
z+JwVK-u5;}XO!$TQ8z$6(;c)dd=06E4819Nt>vCVrMp;if$H|HCEYUk1LWmf^q5*3
zAK#*%=ufn&!(p_uF8kCBvD8N4<P-@iJXF_>qQ6ogE~^a>&!d`$l7d1ok`gShWJwzq
z>-Dc>Wk?sy6UpM!b1a1OihJ0a*a2?kLL%+3y7R?<9r>7nxi&|dUDQv^RkTtY&A#S=
zCnXO*Anr0s20b0sJ3YGdvCBomDc^%Ta>`vc2Cq{VGO34(@^wutD6(=`Q&lM#II-cw
z8Pa0y>bk9SLE-07yq7F-i!9<9wW$L!siXp7JzJE0CHpfhbdvN(mE-~^<^e=+^HMFR
z%IUoZmC}xUaduvXQ%r}-q9>okO9uuX#Iy7h%Vx4fZQ<Xdr`&=L;eK`02_R=-{sGGp
z`s>fSu)5T=Wit2sZJIuwFJ?Uw985yx`yc&<R^DA!Ye>)BkY?2)O?iSTxJV)%v094I
zQ5e+)fp&#MeoMYp(Dt9#t$=IBQ&dg14d2W6+u_&hIl&b{?bADl4XVM@#C2|(wxE6;
zmoh!SLszHm=_fs_)R~WT%Ehdu2ryjvc8UwjeXr>(Tf$Me%Wko}mmj0QAz2gyV&)_l
z_25r4@IT%InI<~381|CYhKBMz<-ZuFSwY~QmEN0)UH$Zadk)#M!~s@2!@&M>$4R*(
zx=#;#)RK9@A{_fl6@3PcBGA;SWc4n3*6t(~zhQp2zD0IV=c)?b*HX*}y*1}RFSSS6
zRz9K2f4e}cHe7x;O2p@injB8J+!`xcS|X0S#cU%%=@r5wx$RZCt!B0)@7MCP2u$|F
z4R5%49mj->A;4z|Dg!E+15QwGqPK|EU=}$t*E(&8rtMrzdXn>QT%+6J$sezj!9d7*
zJsc1Yp5Dj`XAaL@SHS>AAMaA@+(I@Dxqq@HA79Cgr!{)`MLd>1jt!jR_2?$TiK+Y<
zC}8=nQfatq6<YWyD?co1f9W6P(jq?uC0VvH)zeLQTTZbAr~p*P!G1GC5ng3b?-z^w
z#eF|E{fjjQw2TKWpScjw*|D}$-9NJl{mfX#P>7j2zvKKIq*x<Fp~?O*@sv7rTt#CL
zXNDs44bp5E%i^J;HoOb^`!Q+}KA1&h^625JflkIm7+k#v)e3W!0mWieK`%%9F)XBR
z!KgV@_xHpcW*Xr3LbzjtUB>9?VQ%j0s|%JDo7x&&jUt1TR<8ObPhP&0pSzx-{G`ez
z2E+rJSVP>Ky~{NCZ4%UkPO)xUUP<+Xrr~#mTPMqIiA;`B574@49mL}dvJ*n*C953l
z!E6g5|Kg(#r?-~N*IocFXrHRn4_V(`#|la(fV?keBp5)%!G?c6a<GC&b8@>+zti(9
zfAjM#>5q8xAaq15L4W|(vOzp3R42*%s>r{qn)R3L5Fdve_bb2Ktzyf+SB>PpQLi~v
zbg&5JiW)ZuhjPK~RvOh6K1TF|$s?571Z5%)pW~lb{*UR;-vi%X`HS2N3e)2~6N15V
zB6!yTSU{fkvCBBx(`RxHA$Ij*{7?%I<VKUT#qKP3Kug05$`}cy22SJh5cJA^p6$Cw
z*78#l7e*TTI2e1><b<kYzE}1hX3X+z(HlK@-WL4}$U8l>Z^y5PQ~G+1s}*woSo3j%
zZYP<Zh1vk{M#I6qT2UI3BkniG|F0tl|Mxz=fl;6f4D=svr{PA36Z~I5BT@6;U{f{>
z;$MlmN*(0C08hsa>R*szq6YIXxU&_9L-?PE_6cHMjD-L5nC73B{~x;OKM!U?k{6NI
z|BX`mj}8p||0bB^rGP=ufd2co|9^}V<Ul~^|1tar@h2d8lN0`v72@LpW*8U{(A__*
z754v7S>R7V_C`;z@J9WwJQ4ujI3Ni^|B7n8QUA-dRJ?t`6C4O=2J(NKPK*Dm_wxUm
z!u#NW_{#n(`jLg8`~OGzUm0FhYb1I9<D(b)fBS(``PV4O=f6Y9_{UGL_P-(lo&VF1
zIt!!<DGU&hF5Lh2!(;NV5h~!{xXZcz6ruj3^ZOr$?tiA7Wc#n4CIACs$Me5F#{UCH
C4;-2R

delta 16708
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
Zt{@Hmuk8i|1o!_N5E?TxFzD8RcmPr+LXZFe

