﻿<?xml version="1.0" encoding="utf-8"?>

<!-- EngineVersion = Java version -->
<ApiConfig Name="DuckDB (Parquet)"
           Slug="duckdb-connector"
           Type="JDBC"
           Category="file"
           Id="18D1AA28-2A7E-47F1-AE2E-03856EA07EEA"
           Version="3"
           EngineVersion="8"
           Desc="Query Parquet and DuckDB files from Power BI, SQL Server Linked Server via ZappySys Data Gateway, Crystal Reports, SSRS, Azure Data Factory, and other ODBC tools -- almost no coding required."
           HelpLink="https://community.zappysys.com/search?q=parquet"
           Logo="https://cdn.zappysys.com/wp-content/uploads/2025/11/duckdb-connector.png"
           Provider="DuckDB"
           >

    <VersionHistory>
        <Change Ver="3" Date="2026-09-15" Type="Modified">Numbered Auth Notes, Finish/Test Connection wording, optional file Auth.</Change>
        <Change Ver="2" Date="2026-09-14" Type="Fix">Wizard downloads DuckDB JDBC 1.4.5.0 (LTS) from Maven and the Titanic Parquet sample from GitHub. In-memory URL plus SELECT from the sample file.</Change>
        <Change Ver="1" Date="2025-10-02" Type="New">Initial version.</Change>
    </VersionHistory>

    <!-- Global parameters -->
    <Template>
        <Param Name="DriverDownloadPageLink"
               Value="https://duckdb.org/docs/stable/clients/java.html" />

        <Param Name="MvnRepositoryDriverDownloadLink"
               Value="https://mvnrepository.com/artifact/org.duckdb/duckdb_jdbc" />
        <!-- filename=url;filename=url — first '=' split so query strings stay intact. {DownloadFolder} is replaced after download. -->
        <Param Name="DriverDownloadLinks"
               Hidden="True"
               Value="duckdb_jdbc-1.4.5.0.jar=https://repo1.maven.org/maven2/org/duckdb/duckdb_jdbc/1.4.5.0/duckdb_jdbc-1.4.5.0.jar" />
        <Param Name="SampleDownloadLinks"
               Hidden="True"
               Value="titanic.parquet=https://raw.githubusercontent.com/fhdsl/data_snacks/d3c03fde8d4d8e6d1ce9d7e3463df9da2f867a4d/docs/data/titanic.parquet" />
    </Template>

    <!-- Authentications -->
    <Auths>
        <Auth Name="InMemory"
              Label="In-Memory Connection"
              ConnStr="jdbc:duckdb:memory:">
            <Params>
                <Param Name="DriverClass"
                       Label="Driver class"
                       Required="False"
                       Desc="Optional. Leave blank to auto-detect from the JAR (e.g. org.duckdb.DuckDBDriver)."
                       Value="org.duckdb.DuckDBDriver" />
                <Param Name="DriverFilePaths" Editor="FileOpen"
                       Label="JDBC driver file(s)"
                       Required="True"
                       Desc="Path to the DuckDB JDBC JAR on disk. Separate multiple JARs with a semicolon (e.g. C:\ZappySys\Jdbc\MyConnector\driver.jar)."
                       Value="{DownloadFolder}\duckdb_jdbc-1.4.5.0.jar" />
            </Params>
            <Notes>
                <![CDATA[<p>Query Parquet with DuckDB JDBC from Power BI, SQL Server Linked Server via ZappySys Data Gateway, Crystal Reports, SSRS, Azure Data Factory, and other ODBC tools.</p>
<ol>
  <li>The wizard downloads DuckDB JDBC 1.4.5.0 (LTS) and the Titanic sample Parquet into <code>{DownloadFolder}</code>.</li>
  <li>This Auth is in-memory (<code>jdbc:duckdb:memory:</code>). After Finish, query the sample with <code>SELECT * FROM "{DownloadFolder}\titanic.parquet"</code>.</li>
  <li>Use the File Auth if you want a persistent <code>.duckdb</code> database instead of memory.</li>
  <li>Finish the wizard. Then click <strong>Test Connection</strong> on the DSN Main UI (the wizard does not run Test Connection).</li>
  <li>Done. You can query from C#, Python, PowerShell, and ODBC apps.</li>
</ol>]]>
            </Notes>
        </Auth>
        <Auth Name="File"
              Label="Local DuckDB file"
              ConnStr="jdbc:duckdb:{DownloadFolder}\mydb.duckdb"
              HelpLink="https://duckdb.org/docs/stable/clients/java.html">
            <Params>
                <Param Name="DriverClass"
                       Label="Driver class"
                       Required="False"
                       Desc="Optional. Leave blank to auto-detect from the JAR (e.g. org.duckdb.DuckDBDriver)."
                       Value="org.duckdb.DuckDBDriver" />
                <Param Name="DriverFilePaths" Editor="FileOpen"
                       Label="JDBC driver file(s)"
                       Required="True"
                       Desc="Path to the DuckDB JDBC JAR on disk. Separate multiple JARs with a semicolon (e.g. C:\ZappySys\Jdbc\MyConnector\driver.jar)."
                       Value="{DownloadFolder}\duckdb_jdbc-1.4.5.0.jar" />
            </Params>
            <Notes>
                <![CDATA[<p>Persistent DuckDB file from Power BI, SQL Server Linked Server via ZappySys Data Gateway, Crystal Reports, SSRS, Azure Data Factory, and other ODBC tools.</p>
<ol>
  <li>The wizard still downloads the JDBC JAR (and Titanic sample) into <code>{DownloadFolder}</code>.</li>
  <li>After Finish, point the JDBC URL at your <code>.duckdb</code> file if you do not want <code>mydb.duckdb</code>.</li>
  <li>You can still query Parquet with <code>SELECT * FROM '{DownloadFolder}\titanic.parquet'</code>.</li>
  <li>Finish the wizard. Then click <strong>Test Connection</strong> on the DSN Main UI (the wizard does not run Test Connection).</li>
  <li>Done. You can query from C#, Python, PowerShell, and ODBC apps.</li>
</ol>]]>
            </Notes>
        </Auth>
    </Auths>

    <Examples>
        <Example Slug="read-titanic-sample-parquet" Default="True" Group="ODBC" Label="Read Titanic sample Parquet"
                 HelpLink="https://duckdb.org/docs/stable/data/parquet/overview">
            <Desc><![CDATA[
<p>Reads the Titanic sample Parquet the wizard downloads next to the JDBC JAR (<code>{DownloadFolder}\titanic.parquet</code>). Connection is in-memory; the path is the data source.</p>
            ]]></Desc>
            <Code>
                <![CDATA[SELECT *
FROM "{DownloadFolder}\titanic.parquet"]]>
            </Code>
        </Example>

        <Example Slug="read-parquet-file-over-https" Group="ODBC" Label="Read Parquet file over HTTPS"
                 HelpLink="https://duckdb.org/docs/stable/data/parquet/overview">
            <Desc><![CDATA[
<p>Reads a remote Parquet file directly over HTTPS. Use <code>read_parquet()</code> with a URL; DuckDB fetches and queries the file without a local copy. Returns all rows and columns from the file.</p>
            ]]></Desc>
            <Code>
                <![CDATA[SELECT *
FROM read_parquet('https://hrbrmstr.github.io/large-parquet-test/sample.parquet');]]>
            </Code>
        </Example>

        <Example Group="ODBC" Slug="read-local-parquet-file-implicit-path" Label="Read local Parquet file (implicit path)"
                 HelpLink="https://duckdb.org/docs/stable/data/parquet/overview">
            <Desc><![CDATA[
<p>Reads a local Parquet file by specifying its path in the <code>FROM</code> clause. DuckDB automatically uses the optimized Parquet engine. Replace the path with your file location.</p>
            ]]></Desc>
            <Code>
                <![CDATA[SELECT * FROM 'D:\ParquetFiles\titanic.parquet';]]>
            </Code>
        </Example>

        <Example Group="ODBC" Slug="read-parquet-files-with-options" Label="Read Parquet files with options"
                 HelpLink="https://duckdb.org/docs/stable/data/parquet/overview">
            <Desc><![CDATA[
<p>Reads one or more Parquet files using <code>read_parquet()</code> with a path and optional arguments such as <code>filename=TRUE</code> (add a source filename column) and <code>binary_as_string=TRUE</code>. Wildcards in the path match multiple files.</p>
            ]]></Desc>
            <Code>
                <![CDATA[SELECT * 
FROM read_parquet('D:\ParquetFiles\flights-*.parq',filename=TRUE, binary_as_string=TRUE);]]>
            </Code>
        </Example>

        <Example Group="ODBC" Slug="inspect-parquet-file-schema" Label="Inspect Parquet file schema"
                 HelpLink="https://duckdb.org/docs/stable/data/parquet/overview">
            <Desc><![CDATA[
<p>Shows the schema of a Parquet file: column names and data types. Use <code>DESCRIBE</code> with a <code>SELECT</code> from the file path. Useful before writing queries or mapping columns.</p>
            ]]></Desc>
            <Code>
                <![CDATA[DESCRIBE SELECT * FROM 'D:\ParquetFiles\titanic.parquet';]]>
            </Code>
        </Example>

        <Example Group="ODBC" Slug="read-multiple-parquet-files-list" Label="Read multiple Parquet files (list)"
                 HelpLink="https://duckdb.org/docs/stable/data/parquet/overview">
            <Desc><![CDATA[
<p>Reads multiple Parquet files with the same schema by passing a list of paths to <code>read_parquet()</code>. Returns a single result set. Use when you have a fixed set of files rather than a wildcard pattern.</p>
            ]]></Desc>
            <Code>
                <![CDATA[SELECT * 
FROM read_parquet(['D:\ParquetFiles\file1.parquet', 'D:\ParquetFiles\file2.parquet', 'D:\ParquetFiles\file3.parquet']);]]>
            </Code>
        </Example>

        <Example Group="ODBC" Slug="read-parquet-files-with-wildcard-in-from" Label="Read Parquet files with wildcard in FROM"
                 HelpLink="https://duckdb.org/docs/stable/data/parquet/overview">
            <Desc><![CDATA[
<p>Reads all Parquet files matching a wildcard pattern (e.g. <code>*.parquet</code>) by putting the pattern in the <code>FROM</code> clause. DuckDB treats them as one logical table. Simpler than <code>read_parquet()</code> when you only need a path pattern.</p>
            ]]></Desc>
            <Code>
                <![CDATA[SELECT * 
FROM 'D:\ParquetFiles\*.parquet';]]>
            </Code>
        </Example>

        <Example Group="ODBC" Slug="read-parquet-files-with-filename-column" Label="Read Parquet files with filename column"
                 HelpLink="https://duckdb.org/docs/stable/data/parquet/overview">
            <Desc><![CDATA[
<p>Reads multiple Parquet files via a wildcard and adds a <code>filename</code> column indicating the source file for each row. In DuckDB 1.3.0 and later this is the default when using <code>read_parquet()</code> with multiple files.</p>
            ]]></Desc>
            <Code>
                <![CDATA[SELECT filename, *
FROM read_parquet('D:\ParquetFiles\flights-*.parquet');]]>
            </Code>
        </Example>

        <Example Group="ODBC" Slug="read-parquet-files-from-multiple-folders" Label="Read Parquet files from multiple folders"
                 HelpLink="https://duckdb.org/docs/stable/data/parquet/overview">
            <Desc><![CDATA[
<p>Reads all matching Parquet files from several folders by passing a list of wildcard paths to <code>read_parquet()</code>. Results are merged into one dataset. Use when data is split across directories.</p>
            ]]></Desc>
            <Code>
                <![CDATA[SELECT filename, *
FROM read_parquet(['D:\folder1\*.parquet', 'D:\folder2\*.parquet']);]]>
            </Code>
        </Example>

        <Example Group="ODBC" Slug="query-parquet-metadata-detailed" Label="Query Parquet metadata (detailed)"
                 HelpLink="https://duckdb.org/docs/stable/data/parquet/metadata.html#parquet-metadata">
            <Desc><![CDATA[
<p>Returns detailed Parquet metadata: schema, row groups, and column statistics. Use <code>parquet_metadata()</code> with a file path or URL. Helpful for tuning or understanding file layout.</p>
            ]]></Desc>
            <Code>
                <![CDATA[SELECT *
FROM parquet_metadata('https://hrbrmstr.github.io/large-parquet-test/sample.parquet');]]>
            </Code>
        </Example>

        <Example Group="ODBC" Slug="query-parquet-file-metadata-lowlevel" Label="Query Parquet file metadata (low-level)"
                 HelpLink="https://duckdb.org/docs/stable/data/parquet/metadata.html#parquet-file-metadata">
            <Desc><![CDATA[
<p>Returns low-level Parquet file metadata: row group details, encodings, and column-level statistics. Use <code>parquet_file_metadata()</code> when you need implementation-level details for debugging or optimization.</p>
            ]]></Desc>
            <Code>
                <![CDATA[SELECT *
FROM parquet_file_metadata('D:\ParquetFiles\titanic.parquet');]]>
            </Code>
        </Example>

        <Example Group="ODBC" Slug="query-parquet-keyvalue-metadata" Label="Query Parquet key-value metadata"
                HelpLink="https://duckdb.org/docs/stable/data/parquet/metadata.html#parquet-key-value-metadata">
            <Desc><![CDATA[
<p>Reads user-defined key-value metadata from the Parquet file footer. Use <code>parquet_kv_metadata()</code> with the file path when the file stores custom metadata (e.g. from a writer that writes key-value pairs).</p>
            ]]></Desc>
            <Code>
                <![CDATA[SELECT *
FROM parquet_kv_metadata('D:\ParquetFiles\titanic.parquet');]]>
            </Code>
        </Example>

        <Example Group="ODBC" Slug="query-parquet-file-schema" Label="Query Parquet file schema"
                 HelpLink="https://duckdb.org/docs/stable/data/parquet/metadata.html#parquet-schema">
            <Desc><![CDATA[
<p>Returns the Parquet file schema: column names, types, and nested structure. Use <code>parquet_schema()</code> when you need the schema definition without reading data. Complements <code>DESCRIBE SELECT</code> for programmatic use.</p>
            ]]></Desc>
            <Code>
                <![CDATA[SELECT *
FROM parquet_schema('D:\ParquetFiles\titanic.parquet');]]>
            </Code>
        </Example>

        <Example Group="ODBC" Slug="write-table-to-parquet-file" Label="Write table to Parquet file"
              HelpLink="https://duckdb.org/docs/stable/data/parquet/overview">
            <Desc><![CDATA[
<p>Writes the result of a query or table to a Parquet file. Use <code>COPY</code> with a <code>SELECT</code> (or table name) and a path; specify <code>FORMAT parquet</code>. The target path must be writable.</p>
            ]]></Desc>
            <Code>
                <![CDATA[COPY 
    (Select * from tblTitanic) 
    TO 'D:\ParquetFiles\titanic.parquet' (FORMAT parquet);]]>
            </Code>
        </Example>

        <Example Group="ODBC" Slug="write-parquet-file-with-custom-options" Label="Write Parquet file with custom options"
              HelpLink="https://duckdb.org/docs/stable/data/parquet/overview">
            <Desc><![CDATA[
<p>Writes data to a Parquet file with options such as <code>STRING_DICTIONARY_PAGE_SIZE_LIMIT</code> to control dictionary page size (default 1 MB). Use when you need to tune file size or compatibility.</p>
            ]]></Desc>
            <Code>
                <![CDATA[COPY
    lineitem
    TO 'D:\ParquetFiles\lineitem-with-custom-dictionary-size.parquet'
    (FORMAT parquet, STRING_DICTIONARY_PAGE_SIZE_LIMIT 100_000);]]>
            </Code>
        </Example>

        <Example Group="ODBC" Slug="write-zstdcompressed-parquet-file" Label="Write ZSTD-compressed Parquet file"
              HelpLink="https://duckdb.org/docs/stable/data/parquet/overview">
            <Desc><![CDATA[
<p>Writes a Parquet file using Zstandard (zstd) compression. Set <code>COMPRESSION zstd</code> and optionally <code>COMPRESSION_LEVEL</code> (1 is fastest). Use when you want smaller files and can trade write speed for size.</p>
            ]]></Desc>
            <Code>
                <![CDATA[COPY tbl
    TO 'D:\ParquetFiles\result-zstd.parquet'
    (FORMAT parquet, COMPRESSION zstd, COMPRESSION_LEVEL 1);]]>
            </Code>
        </Example>

        <Example Group="ODBC" Slug="convert-csv-to-parquet-file" Label="Convert CSV to Parquet file"
              HelpLink="https://duckdb.org/docs/stable/data/parquet/overview">
            <Desc><![CDATA[
<p>Reads data from a CSV file with <code>read_csv()</code> and writes it to a Parquet file using <code>COPY ... TO ... (FORMAT parquet)</code>. Use for one-off conversion or ETL; DuckDB handles type inference from CSV.</p>
            ]]></Desc>
            <Code>
                <![CDATA[COPY 
	(Select * from read_csv('D:\CsvFiles\Countries.csv')) 
	TO 'D:\ParquetFiles\Countries.parquet' (FORMAT parquet);]]>
            </Code>
        </Example>

    </Examples>
</ApiConfig>