From 5bde0e2c6ebcb8accc1c2da558fdd6bf5ab831d8 Mon Sep 17 00:00:00 2001 From: Gabor Szarnyas Date: Thu, 18 Apr 2024 18:56:59 +0200 Subject: [PATCH 1/4] Fix linter warnings --- docs/api/odbc/linux.md | 4 ++++ docs/api/odbc/macos.md | 4 ++++ docs/api/odbc/windows.md | 4 ++++ 3 files changed, 12 insertions(+) diff --git a/docs/api/odbc/linux.md b/docs/api/odbc/linux.md index be69ad47c48..8e594c6631d 100644 --- a/docs/api/odbc/linux.md +++ b/docs/api/odbc/linux.md @@ -26,9 +26,13 @@ sudo yum install unixODBC 1. Download the ODBC Linux Asset corresponding to your architecture: + + * [x86_64 (AMD64)](https://github.com/duckdb/duckdb/releases/download/v{{ site.currentduckdbversion }}/duckdb_odbc-linux-amd64.zip) * [arm64](https://github.com/duckdb/duckdb/releases/download/v{{ site.currentduckdbversion }}/duckdb_odbc-linux-aarch64.zip) + + 2. The package contains the following files: * `libduckdb_odbc.so`: the DuckDB driver. diff --git a/docs/api/odbc/macos.md b/docs/api/odbc/macos.md index 47142928e8f..d916fb0b2e5 100644 --- a/docs/api/odbc/macos.md +++ b/docs/api/odbc/macos.md @@ -9,12 +9,16 @@ title: ODBC API on macOS brew install unixodbc ``` + + 2. DuckDB releases a universal [ODBC driver for macOS](https://github.com/duckdb/duckdb/releases/download/v{{ site.currentduckdbversion }}/duckdb_odbc-osx-universal.zip) (supporting both Intel and Apple Silicon CPUs). To download it, run: ```bash wget https://github.com/duckdb/duckdb/releases/download/v{{ site.currentduckdbversion }}/duckdb_odbc-osx-universal.zip ``` + + 3. The archive contains the `libduckdb_odbc.dylib` artifact. To extract it to a directory, run: ```bash diff --git a/docs/api/odbc/windows.md b/docs/api/odbc/windows.md index 4d20c97facc..38b0e21d664 100644 --- a/docs/api/odbc/windows.md +++ b/docs/api/odbc/windows.md @@ -9,8 +9,12 @@ Using the DuckDB ODBC API on Windows requires the following steps: The Driver Manager on Windows is provided in a DLL file `odbccp32.dll`, and other files and tools. For detailed information check out the [Common ODBC Component Files](https://docs.microsoft.com/en-us/previous-versions/windows/desktop/odbc/dn170563(v=vs.85)). + + 2. DuckDB releases the ODBC driver as an asset. For Windows, download it from the [Windows ODBC asset (x86_64/AMD64)](https://github.com/duckdb/duckdb/releases/download/v{{ site.currentduckdbversion }}/duckdb_odbc-windows-amd64.zip). + + 3. The archive contains the following artifacts: * `duckdb_odbc.dll`: the DuckDB driver compiled for Windows. From 94bbb85ce7b13d8a29f1c18fa75a6e95e833d7f1 Mon Sep 17 00:00:00 2001 From: Gabor Szarnyas Date: Thu, 18 Apr 2024 19:05:45 +0200 Subject: [PATCH 2/4] Remove ToCs --- docs/guides/odbc/general.md | 30 ------------------------------ 1 file changed, 30 deletions(-) diff --git a/docs/guides/odbc/general.md b/docs/guides/odbc/general.md index c153b69a26f..53c15e62023 100644 --- a/docs/guides/odbc/general.md +++ b/docs/guides/odbc/general.md @@ -3,11 +3,6 @@ layout: docu title: "ODBC 101: A Duck Themed Guide to ODBC" --- -* [What is ODBC?](#what-is-odbc) -* [General Concepts](#general-concepts) -* [Setting up an Application](#setting-up-an-application) -* [Sample Application](#sample-application) - ## What is ODBC? [ODBC](https://learn.microsoft.com/en-us/sql/odbc/microsoft-open-database-connectivity-odbc?view=sql-server-ver16) which stands for Open Database Connectivity, is a standard that allows different programs to talk to different databases including, of course, **DuckDB** 🦆. This makes it easier to build programs that work with many different databases, which saves time as developers don't have to write custom code to connect to each database. Instead, they can use the standardized ODBC interface, which reduces development time and costs, and programs are easier to maintain. However, ODBC can be slower than other methods of connecting to a database, such as using a native driver, as it adds an extra layer of abstraction between the application and the database. Furthermore, because DuckDB is column-based and ODBC is row-based, there can be some inefficiencies when using ODBC with DuckDB. @@ -103,31 +98,6 @@ The following is a step-by-step guide to setting up an application that uses ODB > To install the driver as well as anything else you will need follow these [instructions](../../api/odbc/overview). -- [What is ODBC?](#what-is-odbc) -- [General Concepts](#general-concepts) - - [Handles](#handles) - - [Environment](#environment) - - [Connection](#connection) - - [Statement](#statement) - - [Descriptor](#descriptor) - - [Connecting](#connecting) - - [Connection String](#connection-string) - - [DSN](#dsn) - - [Error Handling and Diagnostics](#error-handling-and-diagnostics) - - [Buffers and Binding](#buffers-and-binding) -- [Setting up an Application](#setting-up-an-application) - - [1. Include the SQL Header Files](#1-include-the-sql-header-files) - - [2. Define the ODBC Handles and Connect to the Database](#2-define-the-odbc-handles-and-connect-to-the-database) - - [2.a. Connecting with SQLConnect](#2a-connecting-with-sqlconnect) - - [2.b. Connecting with SQLDriverConnect](#2b-connecting-with-sqldriverconnect) - - [3. Adding a Query](#3-adding-a-query) - - [4. Fetching Results](#4-fetching-results) - - [5. Go Wild](#5-go-wild) - - [6. Free the Handles and Disconnecting](#6-free-the-handles-and-disconnecting) -- [Sample Application](#sample-application) - - [Sample `.cpp` file](#sample-cpp-file) - - [Sample `CMakelists.txt` file](#sample-cmakeliststxt-file) - ### 1. Include the SQL Header Files The first step is to include the SQL header files: From 21d76de2365df2a54cc9fb562377abc33e249c9f Mon Sep 17 00:00:00 2001 From: Gabor Szarnyas Date: Thu, 18 Apr 2024 19:35:23 +0200 Subject: [PATCH 3/4] Linter fixes --- docs/sql/functions/char.md | 30 +++++++++++++++--------------- docs/sql/functions/nested.md | 4 ++-- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/docs/sql/functions/char.md b/docs/sql/functions/char.md index 7691276a761..bed0da25345 100644 --- a/docs/sql/functions/char.md +++ b/docs/sql/functions/char.md @@ -28,9 +28,9 @@ This section describes functions and operators for examining and manipulating st | [`contains(string, search_string)`](#containsstring-search_string) | Return true if `search_string` is found within `string`. | | [`ends_with(string, search_string)`](#ends_withstring-search_string) | Return true if `string` ends with `search_string`. | | [`format_bytes(bytes)`](#format_bytesbytes) | Converts bytes to a human-readable representation using units based on powers of 2 (KiB, MiB, GiB, etc.). | -| [`format(format, parameters, ...)`](#formatformat-parameters) | Formats a string using the [fmt syntax](#fmt-syntax). | +| [`format(format, parameters, ...)`](#formatformat-parameters-) | Formats a string using the [fmt syntax](#fmt-syntax). | | [`from_base64(string)`](#from_base64string) | Convert a base64 encoded string to a character string. | -| [`greatest(x1, x2, ...)`](#greatestx1-x2) | Selects the largest value using lexicographical ordering. Note that lowercase characters are considered "larger" than uppercase characters and [collations](../expressions/collations) are not supported. | +| [`greatest(x1, x2, ...)`](#greatestx1-x2-) | Selects the largest value using lexicographical ordering. Note that lowercase characters are considered "larger" than uppercase characters and [collations](../expressions/collations) are not supported. | | [`hash(value)`](#hashvalue) | Returns a `UBIGINT` with the hash of the `value`. | | [`ilike_escape(string, like_specifier, escape_character)`](#ilike_escapestring-like_specifier-escape_character) | Returns true if the `string` matches the `like_specifier` (see [Pattern Matching](../../sql/functions/patternmatching)) using case-insensitive matching. `escape_character` is used to search for wildcard characters in the `string`. | | [`instr(string, search_string)`](#instrstring-search_string) | Return location of first occurrence of `search_string` in `string`, counting from 1. Returns 0 if no match found. | @@ -39,27 +39,27 @@ This section describes functions and operators for examining and manipulating st | [`left(string, count)`](#leftstring-count) | Extract the left-most count characters. | | [`length_grapheme(string)`](#length_graphemestring) | Number of grapheme clusters in `string`. | | [`length(string)`](#lengthstring) | Number of characters in `string`. | -| [`like_escape(string, like_specifier, escape_character)`](#like_escapestring-like_specifier-escape_character) | Returns true if the `string` matches the `like_specifier` (see [Pattern Matching](../../sql/functions/patternmatching)) using case-sensitive matching. `escape_character` is used to search for wildcard characters in the `string`. | +| [`like_escape(string, like_specifier, escape_character)`](#like_escapestring-like_specifier-escape_character) | Returns true if the `string` matches the `like_specifier` (see [Pattern Matching](../../sql/functions/patternmatching)) using case-sensitive matching. `escape_character` is used to search for wildcard characters in the `string`. | | [`lower(string)`](#lowerstring) | Convert `string` to lower case. | | [`lpad(string, count, character)`](#lpadstring-count-character) | Pads the `string` with the character from the left until it has count characters. | | [`ltrim(string, characters)`](#ltrimstring-characters) | Removes any occurrences of any of the `characters` from the left side of the `string`. | | [`ltrim(string)`](#ltrimstring) | Removes any spaces from the left side of the `string`. | | [`md5(value)`](#md5value) | Returns the [MD5 hash](https://en.wikipedia.org/wiki/MD5) of the `value`. | | [`nfc_normalize(string)`](#nfc_normalizestring) | Convert string to Unicode NFC normalized string. Useful for comparisons and ordering if text data is mixed between NFC normalized and not. | -| [`not_ilike_escape(string, like_specifier, escape_character)`](#not_ilike_escapestring-like_specifier-escape_character) | Returns false if the `string` matches the `like_specifier` (see [Pattern Matching](../../sql/functions/patternmatching)) using case-sensitive matching. `escape_character` is used to search for wildcard characters in the `string`. | -| [`not_like_escape(string, like_specifier, escape_character)`](#not_like_escapestring-like_specifier-escape_character) | Returns false if the `string` matches the `like_specifier` (see [Pattern Matching](../../sql/functions/patternmatching)) using case-insensitive matching. `escape_character` is used to search for wildcard characters in the `string`. | +| [`not_ilike_escape(string, like_specifier, escape_character)`](#not_ilike_escapestring-like_specifier-escape_character) | Returns false if the `string` matches the `like_specifier` (see [Pattern Matching](../../sql/functions/patternmatching)) using case-sensitive matching. `escape_character` is used to search for wildcard characters in the `string`. | +| [`not_like_escape(string, like_specifier, escape_character)`](#not_like_escapestring-like_specifier-escape_character) | Returns false if the `string` matches the `like_specifier` (see [Pattern Matching](../../sql/functions/patternmatching)) using case-insensitive matching. `escape_character` is used to search for wildcard characters in the `string`. | | [`ord(string)`](#ordstring) | Return ASCII character code of the leftmost character in a string. | | [`parse_dirname(path, separator)`](#parse_dirnamepath-separator) | Returns the top-level directory name from the given path. `separator` options: `system`, `both_slash` (default), `forward_slash`, `backslash`. | | [`parse_dirpath(path, separator)`](#parse_dirpathpath-separator) | Returns the head of the path (the pathname until the last slash) similarly to Python's [`os.path.dirname`](https://docs.python.org/3.7/library/os.path.html#os.path.dirname) function. `separator` options: `system`, `both_slash` (default), `forward_slash`, `backslash`. | | [`parse_filename(path, trim_extension, separator)`](#parse_filenamepath-trim_extension-separator) | Returns the last component of the path similarly to Python's [`os.path.basename`](https://docs.python.org/3.7/library/os.path.html#os.path.basename) function. If `trim_extension` is true, the file extension will be removed (defaults to `false`). `separator` options: `system`, `both_slash` (default), `forward_slash`, `backslash`. | | [`parse_path(path, separator)`](#parse_pathpath-separator) | Returns a list of the components (directories and filename) in the path similarly to Python's [`pathlib.parts`](https://docs.python.org/3/library/pathlib.html#pathlib.PurePath.parts) function. `separator` options: `system`, `both_slash` (default), `forward_slash`, `backslash`. | -| [`position(search_string in string)`](#positionsearch_stringinstring) | Return location of first occurrence of `search_string` in `string`, counting from 1. Returns 0 if no match found. | +| [`position(search_string IN string)`](#positionsearch_string-in-string) | Return location of first occurrence of `search_string` in `string`, counting from 1. Returns 0 if no match found. | | [`printf(format, parameters...)`](#printfformat-parameters) | Formats a `string` using [printf syntax](#printf-syntax). | | [`read_text(source)`](#read_textsource) | Returns the content from `source` (a filename, a list of filenames, or a glob pattern) as a `VARCHAR`. The file content is first validated to be valid UTF-8. If `read_text` attempts to read a file with invalid UTF-8 an error is thrown suggesting to use `read_blob` instead. See the [`read_text` guide](../../guides/import/read_file#read_text) for more details. | | [`regexp_escape(string)`](#regexp_escapestring) | Escapes special patterns to turn `string` into a regular expression similarly to Python's [`re.escape` function](https://docs.python.org/3/library/re.html#re.escape). | -| [`regexp_extract_all(string, regex[, group = 0])`](#regexp_extract_allstring-regex-group0) | Split the `string` along the `regex` and extract all occurrences of `group`. | -| [`regexp_extract(string, pattern , name_list)`](#regexp_extractstring-pattern-name_list) | If `string` contains the regexp `pattern`, returns the capturing groups as a struct with corresponding names from `name_list` (see [Pattern Matching](patternmatching#using-regexp_extract)). | -| [`regexp_extract(string, pattern [, idx])`](#regexp_extractstring-pattern-idx) | If `string` contains the regexp `pattern`, returns the capturing group specified by optional parameter `idx` (see [Pattern Matching](patternmatching#using-regexp_extract)). | +| [`regexp_extract_all(string, regex[, group = 0])`](#regexp_extract_allstring-regex-group--0) | Split the `string` along the `regex` and extract all occurrences of `group`. | +| [`regexp_extract(string, pattern, name_list)`](#regexp_extractstring-pattern--name_list) | If `string` contains the regexp `pattern`, returns the capturing groups as a struct with corresponding names from `name_list` (see [Pattern Matching](patternmatching#using-regexp_extract)). | +| [`regexp_extract(string, pattern[, idx])`](#regexp_extractstring-pattern--idx) | If `string` contains the regexp `pattern`, returns the capturing group specified by optional parameter `idx` (see [Pattern Matching](patternmatching#using-regexp_extract)). | | [`regexp_full_match(string, regex)`](#regexp_full_matchstring-regex) | Returns `true` if the entire `string` matches the `regex` (see [Pattern Matching](patternmatching)). | | [`regexp_matches(string, pattern)`](#regexp_matchesstring-pattern) | Returns `true` if `string` contains the regexp `pattern`, `false` otherwise (see [Pattern Matching](patternmatching#using-regexp_matches)). | | [`regexp_replace(string, pattern, replacement)`](#regexp_replacestring-pattern-replacement) | If `string` contains the regexp `pattern`, replaces the matching part with `replacement` (see [Pattern Matching](patternmatching#using-regexp_replace)). | @@ -286,7 +286,7 @@ This section describes functions and operators for examining and manipulating st | **Example** | `instr('test test', 'es')` | | **Result** | 2 | -### `least(x1, x2, ... )` +### `least(x1, x2, ...)`
@@ -326,7 +326,7 @@ This section describes functions and operators for examining and manipulating st | **Example** | `length('Hello🦆')` | | **Result** | `6` | -### `like_escape(string, like_specifier, escape_character)` +### `like_escape(string, like_specifier, escape_character)`
@@ -383,7 +383,7 @@ This section describes functions and operators for examining and manipulating st | **Example** | `nfc_normalize('ardèch')` | | **Result** | `ardèch` | -### `not_ilike_escape(string, like_specifier, escape_character)` +### `not_ilike_escape(string, like_specifier, escape_character)`
@@ -391,7 +391,7 @@ This section describes functions and operators for examining and manipulating st | **Example** | `not_ilike_escape('A%c', 'a$%C', '$')` | | **Result** | `false` | -### `not_like_escape(string, like_specifier, escape_character)` +### `not_like_escape(string, like_specifier, escape_character)`
@@ -439,12 +439,12 @@ This section describes functions and operators for examining and manipulating st | **Example** | `parse_path('/path/to/file.csv', 'system')` | | **Result** | `[/, path, to, file.csv]` | -### `position(search_string in string)` +### `position(search_string IN string)`
| **Description** | Return location of first occurrence of `search_string` in `string`, counting from 1. Returns 0 if no match found. | -| **Example** | `position('b' in 'abc')` | +| **Example** | `position('b' IN 'abc')` | | **Result** | `2` | ### `printf(format, parameters...)` diff --git a/docs/sql/functions/nested.md b/docs/sql/functions/nested.md index 4b1b606b604..96e9b82f6cb 100644 --- a/docs/sql/functions/nested.md +++ b/docs/sql/functions/nested.md @@ -433,8 +433,8 @@ FROM (VALUES (['Hello', '', 'World'])) t(strings); | [`row(any, ...)`](#rowany-) | Create an unnamed `STRUCT` (tuple) containing the argument values. | | [`struct_extract(struct, 'entry')`](#struct_extractstruct-entry) | Extract the named entry from the `STRUCT`. | | [`struct_extract(struct, idx)`](#struct_extractstruct-idx) | Extract the entry from an unnamed `STRUCT` (tuple) using an index (1-based). | -| [`struct_insert(struct, name := any, ...)`](#struct_insertstruct-name--any) | Add field(s)/value(s) to an existing `STRUCT` with the argument values. The entry name(s) will be the bound variable name(s). | -| [`struct_pack(name := any, ...)`](#struct_packname--any) | Create a `STRUCT` containing the argument values. The entry name will be the bound variable name. | +| [`struct_insert(struct, name := any, ...)`](#struct_insertstruct-name--any-) | Add field(s)/value(s) to an existing `STRUCT` with the argument values. The entry name(s) will be the bound variable name(s). | +| [`struct_pack(name := any, ...)`](#struct_packname--any-) | Create a `STRUCT` containing the argument values. The entry name will be the bound variable name. | ### `struct.entry`* From b56552a0815804462839110f96909a9b0260c443 Mon Sep 17 00:00:00 2001 From: Gabor Szarnyas Date: Thu, 18 Apr 2024 19:37:09 +0200 Subject: [PATCH 4/4] Reformat Python code --- scripts/generate_function_json.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/scripts/generate_function_json.py b/scripts/generate_function_json.py index b8e9f6efb9e..265aeb6f28c 100644 --- a/scripts/generate_function_json.py +++ b/scripts/generate_function_json.py @@ -55,9 +55,11 @@ def main(): else [] ), 'category': category, - 'result': get_result(function['example']) - if function.get('example') - else None, + 'result': ( + get_result(function['example']) + if function.get('example') + else None + ), } for function in json.load(fh) ]