Support running an SQL file on init#252
Conversation
|
Hi @staticlibs, great PR, think it will add a lot of versatility. I wonder if it would be better to go back to your original idea of two files instead of one file with a marker. You could have the option to pass two separate files, eg: |
|
Thanks for your comments! I've experimented with 2 files, the problem with them is that you also need to pass 2 sha256 sums for them. All of this in connection string. In BI tools connectors the input field for these options (and, in general, a single input field for The So the proposal would be to leave a single file - rather keep the marker, or drop the marker logic completely along with per-connection init logic. Connection init is less useful than DB init, for example, in DuckLake only the |
|
Thanks for the explanation. In that case, I agree that the marker is the best of both worlds. Perhaps for now, the connection init is less useful, but this way we also future-proof it. |
This change adds support for `session_init_sql_file` connection option, that allows to speficy the path to an SQL file in local file system, that will be read by the driver and executed in a newly created connection before passing it to user. By default the file is initalized only once per database, on the first connection established to this DB. For `:memory:` connection-private DBs it effectively executed once per connection. In addition to the DB init, it supports executing a part of the SQL file for every connection. It looks for the specific marker: ``` /* DUCKDB_CONNECTION_INIT_BELOW_MARKER */ ``` in the SQL file. If this marker is present - everything before the marker is executed on DB init, and everything after this marker - on connection init. DB init is not re-run when the DB is closed and re-opened after the last connection to it was closed and then new one created. If such re-init is necessary - `jdbc_pin_db` option is supposed to be used instead. It is understood, that this feature can be security sensitive (it effectively implements an RCE entry) in contexts, where other applications/processes/users can control the appending to user-specified connection string or re-writing the specified file in local file system. The following security measures are taken to mitigate that: - `session_init_sql_file` option can only be specified in the connection string itself, it is not accepted as part of connection `Properties` - `session_init_sql_file` option must be specified as the first option in the connection string, for example: 'jdbc:duckdb:;session_init_sql_file=/path/to/init.sql' - `session_init_sql_file_sha256=<sha56sum_of_sql_file>` option can be specified, the file contents SHA-256 sum is checked againts this value - `session_init_sql_file_sha256` option can only be specified in the connection string itself - `session_init_sql_file` and `session_init_sql_file_sha256` options cannot be specified multiple times - content of the SQL file are available to the running code using `DuckDBConnection#getSessionInitSQL()` method Testing: new tests added in a separate file.
a870cdd to
ab885e2
Compare
This change is a counterpart of a similar functionality in DuckDB JDBC driver added in duckdb/duckdb-java#252. It adds support for `session_init_sql_file` connection option, that allows to speficy the path to an SQL file in local file system, that will be read by the driver and executed in a newly created connection before passing it to user. By default the file is initalized only once per database, on the first `SQLConnect` call to this DB. For `:memory:` connection-private DBs it effectively executed once per connection. In addition to the DB init, it supports executing a part of the SQL file for every connection. It looks for the specific marker: ``` /* DUCKDB_CONNECTION_INIT_BELOW_MARKER */ ``` in the SQL file. If this marker is present - everything before the marker is executed on DB init, and everything after this marker - on connection init. To minimize the security impact of this change in contexts, where other applications/processes/users can control the appending to user-specified connection string or re-writing the specified file in local file system, the following restrictions are added: - `session_init_sql_file` can only be specified in the DSN configuration in `.ini` file or in Windows Registry; unlike oridinary options, this options can NOT be used in the connection string to override DSN configuration - `session_init_sql_file_sha256=<sha56sum_of_sql_file>` option can be specified (also only in DSN), the file contents SHA-256 sum is checked againts this value - contents of the SQL file being executed are added to the diagnostic records for the `SQLConnect/SQLDriverConnect` call, when ODBC tracing is enabled in Driver Manager settings - the full SQL file is printed to the log like this: ``` <Client app name> 7cc-2300 EXIT SQLDriverConnectW with return code 1 (SQL_SUCCESS_WITH_INFO) [...] DIAG [01000] ODBC_DuckDB->SQLDriverConnect Session init SQL: <SQL file contents> ``` Testing: new tests added (in a separate file), they use `SQLWritePrivateProfileString` Driver Manager API to temporary set `session_init_sql_file` in user DSN settings. This call has some limitations (cannot set `database` on Windows) but is confirmed to work on CI for all platforms.
This is a backport of the PR duckdb#252 to `v1.3-ossivalis` stable branch. This change adds support for `session_init_sql_file` connection option, that allows to speficy the path to an SQL file in local file system, that will be read by the driver and executed in a newly created connection before passing it to user. By default the file is initalized only once per database, on the first connection established to this DB. For `:memory:` connection-private DBs it effectively executed once per connection. In addition to the DB init, it supports executing a part of the SQL file for every connection. It looks for the specific marker: ``` /* DUCKDB_CONNECTION_INIT_BELOW_MARKER */ ``` in the SQL file. If this marker is present - everything before the marker is executed on DB init, and everything after this marker - on connection init. DB init is not re-run when the DB is closed and re-opened after the last connection to it was closed and then new one created. If such re-init is necessary - `jdbc_pin_db` option is supposed to be used instead. It is understood, that this feature can be security sensitive (it effectively implements an RCE entry) in contexts, where other applications/processes/users can control the appending to user-specified connection string or re-writing the specified file in local file system. The following security measures are taken to mitigate that: - `session_init_sql_file` option can only be specified in the connection string itself, it is not accepted as part of connection `Properties` - `session_init_sql_file` option must be specified as the first option in the connection string, for example: 'jdbc:duckdb:;session_init_sql_file=/path/to/init.sql' - `session_init_sql_file_sha256=<sha56sum_of_sql_file>` option can be specified, the file contents SHA-256 sum is checked againts this value - `session_init_sql_file_sha256` option can only be specified in the connection string itself - `session_init_sql_file` and `session_init_sql_file_sha256` options cannot be specified multiple times - content of the SQL file are available to the running code using `DuckDBConnection#getSessionInitSQL()` method Testing: new tests added in a separate file.
This is a backport of the PR #252 to `v1.3-ossivalis` stable branch. This change adds support for `session_init_sql_file` connection option, that allows to speficy the path to an SQL file in local file system, that will be read by the driver and executed in a newly created connection before passing it to user. By default the file is initalized only once per database, on the first connection established to this DB. For `:memory:` connection-private DBs it effectively executed once per connection. In addition to the DB init, it supports executing a part of the SQL file for every connection. It looks for the specific marker: ``` /* DUCKDB_CONNECTION_INIT_BELOW_MARKER */ ``` in the SQL file. If this marker is present - everything before the marker is executed on DB init, and everything after this marker - on connection init. DB init is not re-run when the DB is closed and re-opened after the last connection to it was closed and then new one created. If such re-init is necessary - `jdbc_pin_db` option is supposed to be used instead. It is understood, that this feature can be security sensitive (it effectively implements an RCE entry) in contexts, where other applications/processes/users can control the appending to user-specified connection string or re-writing the specified file in local file system. The following security measures are taken to mitigate that: - `session_init_sql_file` option can only be specified in the connection string itself, it is not accepted as part of connection `Properties` - `session_init_sql_file` option must be specified as the first option in the connection string, for example: 'jdbc:duckdb:;session_init_sql_file=/path/to/init.sql' - `session_init_sql_file_sha256=<sha56sum_of_sql_file>` option can be specified, the file contents SHA-256 sum is checked againts this value - `session_init_sql_file_sha256` option can only be specified in the connection string itself - `session_init_sql_file` and `session_init_sql_file_sha256` options cannot be specified multiple times - content of the SQL file are available to the running code using `DuckDBConnection#getSessionInitSQL()` method Testing: new tests added in a separate file.
This is a backport of the PR duckdb#157 to `v1.3-ossivalis` stable branch. This change is a counterpart of a similar functionality in DuckDB JDBC driver added in duckdb/duckdb-java#252. It adds support for `session_init_sql_file` connection option, that allows to speficy the path to an SQL file in local file system, that will be read by the driver and executed in a newly created connection before passing it to user. By default the file is initalized only once per database, on the first `SQLConnect` call to this DB. For `:memory:` connection-private DBs it effectively executed once per connection. In addition to the DB init, it supports executing a part of the SQL file for every connection. It looks for the specific marker: ``` /* DUCKDB_CONNECTION_INIT_BELOW_MARKER */ ``` in the SQL file. If this marker is present - everything before the marker is executed on DB init, and everything after this marker - on connection init. To minimize the security impact of this change in contexts, where other applications/processes/users can control the appending to user-specified connection string or re-writing the specified file in local file system, the following restrictions are added: - `session_init_sql_file` can only be specified in the DSN configuration in `.ini` file or in Windows Registry; unlike oridinary options, this options can NOT be used in the connection string to override DSN configuration - `session_init_sql_file_sha256=<sha56sum_of_sql_file>` option can be specified (also only in DSN), the file contents SHA-256 sum is checked againts this value - contents of the SQL file being executed are added to the diagnostic records for the `SQLConnect/SQLDriverConnect` call, when ODBC tracing is enabled in Driver Manager settings - the full SQL file is printed to the log like this: ``` <Client app name> 7cc-2300 EXIT SQLDriverConnectW with return code 1 (SQL_SUCCESS_WITH_INFO) [...] DIAG [01000] ODBC_DuckDB->SQLDriverConnect Session init SQL: <SQL file contents> ``` Testing: new tests added (in a separate file), they use `SQLWritePrivateProfileString` Driver Manager API to temporary set `session_init_sql_file` in user DSN settings. This call has some limitations (cannot set `database` on Windows) but is confirmed to work on CI for all platforms.
This change is a counterpart of a similar functionality in DuckDB JDBC driver added in duckdb/duckdb-java#252. It adds support for `session_init_sql_file` connection option, that allows to speficy the path to an SQL file in local file system, that will be read by the driver and executed in a newly created connection before passing it to user. By default the file is initalized only once per database, on the first `SQLConnect` call to this DB. For `:memory:` connection-private DBs it effectively executed once per connection. In addition to the DB init, it supports executing a part of the SQL file for every connection. It looks for the specific marker: ``` /* DUCKDB_CONNECTION_INIT_BELOW_MARKER */ ``` in the SQL file. If this marker is present - everything before the marker is executed on DB init, and everything after this marker - on connection init. To minimize the security impact of this change in contexts, where other applications/processes/users can control the appending to user-specified connection string or re-writing the specified file in local file system, the following restrictions are added: - `session_init_sql_file` can only be specified in the DSN configuration in `.ini` file or in Windows Registry; unlike oridinary options, this options can NOT be used in the connection string to override DSN configuration - `session_init_sql_file_sha256=<sha56sum_of_sql_file>` option can be specified (also only in DSN), the file contents SHA-256 sum is checked againts this value - contents of the SQL file being executed are added to the diagnostic records for the `SQLConnect/SQLDriverConnect` call, when ODBC tracing is enabled in Driver Manager settings - the full SQL file is printed to the log like this: ``` <Client app name> 7cc-2300 EXIT SQLDriverConnectW with return code 1 (SQL_SUCCESS_WITH_INFO) [...] DIAG [01000] ODBC_DuckDB->SQLDriverConnect Session init SQL: <SQL file contents> ``` Testing: new tests added (in a separate file), they use `SQLWritePrivateProfileString` Driver Manager API to temporary set `session_init_sql_file` in user DSN settings. This call has some limitations (cannot set `database` on Windows) but is confirmed to work on CI for all platforms.
This is a backport of the PR duckdb#157 to `v1.3-ossivalis` stable branch. This change is a counterpart of a similar functionality in DuckDB JDBC driver added in duckdb/duckdb-java#252. It adds support for `session_init_sql_file` connection option, that allows to speficy the path to an SQL file in local file system, that will be read by the driver and executed in a newly created connection before passing it to user. By default the file is initalized only once per database, on the first `SQLConnect` call to this DB. For `:memory:` connection-private DBs it effectively executed once per connection. In addition to the DB init, it supports executing a part of the SQL file for every connection. It looks for the specific marker: ``` /* DUCKDB_CONNECTION_INIT_BELOW_MARKER */ ``` in the SQL file. If this marker is present - everything before the marker is executed on DB init, and everything after this marker - on connection init. To minimize the security impact of this change in contexts, where other applications/processes/users can control the appending to user-specified connection string or re-writing the specified file in local file system, the following restrictions are added: - `session_init_sql_file` can only be specified in the DSN configuration in `.ini` file or in Windows Registry; unlike oridinary options, this options can NOT be used in the connection string to override DSN configuration - `session_init_sql_file_sha256=<sha56sum_of_sql_file>` option can be specified (also only in DSN), the file contents SHA-256 sum is checked againts this value - contents of the SQL file being executed are added to the diagnostic records for the `SQLConnect/SQLDriverConnect` call, when ODBC tracing is enabled in Driver Manager settings - the full SQL file is printed to the log like this: ``` <Client app name> 7cc-2300 EXIT SQLDriverConnectW with return code 1 (SQL_SUCCESS_WITH_INFO) [...] DIAG [01000] ODBC_DuckDB->SQLDriverConnect Session init SQL: <SQL file contents> ``` Testing: new tests added (in a separate file), they use `SQLWritePrivateProfileString` Driver Manager API to temporary set `session_init_sql_file` in user DSN settings. This call has some limitations (cannot set `database` on Windows) but is confirmed to work on CI for all platforms.
This change is a counterpart of a similar functionality in DuckDB JDBC driver added in duckdb/duckdb-java#252. It adds support for `session_init_sql_file` connection option, that allows to speficy the path to an SQL file in local file system, that will be read by the driver and executed in a newly created connection before passing it to user. By default the file is initalized only once per database, on the first `SQLConnect` call to this DB. For `:memory:` connection-private DBs it effectively executed once per connection. In addition to the DB init, it supports executing a part of the SQL file for every connection. It looks for the specific marker: ``` /* DUCKDB_CONNECTION_INIT_BELOW_MARKER */ ``` in the SQL file. If this marker is present - everything before the marker is executed on DB init, and everything after this marker - on connection init. To minimize the security impact of this change in contexts, where other applications/processes/users can control the appending to user-specified connection string or re-writing the specified file in local file system, the following restrictions are added: - `session_init_sql_file` can only be specified in the DSN configuration in `.ini` file or in Windows Registry; unlike oridinary options, this options can NOT be used in the connection string to override DSN configuration - `session_init_sql_file_sha256=<sha56sum_of_sql_file>` option can be specified (also only in DSN), the file contents SHA-256 sum is checked againts this value - contents of the SQL file being executed are added to the diagnostic records for the `SQLConnect/SQLDriverConnect` call, when ODBC tracing is enabled in Driver Manager settings - the full SQL file is printed to the log like this: ``` <Client app name> 7cc-2300 EXIT SQLDriverConnectW with return code 1 (SQL_SUCCESS_WITH_INFO) [...] DIAG [01000] ODBC_DuckDB->SQLDriverConnect Session init SQL: <SQL file contents> ``` Testing: new tests added (in a separate file), they use `SQLWritePrivateProfileString` Driver Manager API to temporary set `session_init_sql_file` in user DSN settings. This call has some limitations (cannot set `database` on Windows) but is confirmed to work on CI for all platforms.
This is a backport of the PR duckdb#157 to `v1.3-ossivalis` stable branch. This change is a counterpart of a similar functionality in DuckDB JDBC driver added in duckdb/duckdb-java#252. It adds support for `session_init_sql_file` connection option, that allows to speficy the path to an SQL file in local file system, that will be read by the driver and executed in a newly created connection before passing it to user. By default the file is initalized only once per database, on the first `SQLConnect` call to this DB. For `:memory:` connection-private DBs it effectively executed once per connection. In addition to the DB init, it supports executing a part of the SQL file for every connection. It looks for the specific marker: ``` /* DUCKDB_CONNECTION_INIT_BELOW_MARKER */ ``` in the SQL file. If this marker is present - everything before the marker is executed on DB init, and everything after this marker - on connection init. To minimize the security impact of this change in contexts, where other applications/processes/users can control the appending to user-specified connection string or re-writing the specified file in local file system, the following restrictions are added: - `session_init_sql_file` can only be specified in the DSN configuration in `.ini` file or in Windows Registry; unlike oridinary options, this options can NOT be used in the connection string to override DSN configuration - `session_init_sql_file_sha256=<sha56sum_of_sql_file>` option can be specified (also only in DSN), the file contents SHA-256 sum is checked againts this value - contents of the SQL file being executed are added to the diagnostic records for the `SQLConnect/SQLDriverConnect` call, when ODBC tracing is enabled in Driver Manager settings - the full SQL file is printed to the log like this: ``` <Client app name> 7cc-2300 EXIT SQLDriverConnectW with return code 1 (SQL_SUCCESS_WITH_INFO) [...] DIAG [01000] ODBC_DuckDB->SQLDriverConnect Session init SQL: <SQL file contents> ``` Testing: new tests added (in a separate file), they use `SQLWritePrivateProfileString` Driver Manager API to temporary set `session_init_sql_file` in user DSN settings. This call has some limitations (cannot set `database` on Windows) but is confirmed to work on CI for all platforms.
This is a backport of the PR #157 to `v1.3-ossivalis` stable branch. This change is a counterpart of a similar functionality in DuckDB JDBC driver added in duckdb/duckdb-java#252. It adds support for `session_init_sql_file` connection option, that allows to speficy the path to an SQL file in local file system, that will be read by the driver and executed in a newly created connection before passing it to user. By default the file is initalized only once per database, on the first `SQLConnect` call to this DB. For `:memory:` connection-private DBs it effectively executed once per connection. In addition to the DB init, it supports executing a part of the SQL file for every connection. It looks for the specific marker: ``` /* DUCKDB_CONNECTION_INIT_BELOW_MARKER */ ``` in the SQL file. If this marker is present - everything before the marker is executed on DB init, and everything after this marker - on connection init. To minimize the security impact of this change in contexts, where other applications/processes/users can control the appending to user-specified connection string or re-writing the specified file in local file system, the following restrictions are added: - `session_init_sql_file` can only be specified in the DSN configuration in `.ini` file or in Windows Registry; unlike oridinary options, this options can NOT be used in the connection string to override DSN configuration - `session_init_sql_file_sha256=<sha56sum_of_sql_file>` option can be specified (also only in DSN), the file contents SHA-256 sum is checked againts this value - contents of the SQL file being executed are added to the diagnostic records for the `SQLConnect/SQLDriverConnect` call, when ODBC tracing is enabled in Driver Manager settings - the full SQL file is printed to the log like this: ``` <Client app name> 7cc-2300 EXIT SQLDriverConnectW with return code 1 (SQL_SUCCESS_WITH_INFO) [...] DIAG [01000] ODBC_DuckDB->SQLDriverConnect Session init SQL: <SQL file contents> ``` Testing: new tests added (in a separate file), they use `SQLWritePrivateProfileString` Driver Manager API to temporary set `session_init_sql_file` in user DSN settings. This call has some limitations (cannot set `database` on Windows) but is confirmed to work on CI for all platforms.
This change adds support for
session_init_sql_fileconnection option, that allows to speficy the path to an SQL file in local file system, that will be read by the driver and executed in a newly created connection before passing it to user.By default the file is initalized only once per database, on the first connection established to this DB.
For
:memory:connection-private DBs it effectively executed once per connection.In addition to the DB init, it supports executing a part of the SQL file for every connection. It looks for the specific marker:
in the SQL file. If this marker is present - everything before the marker is executed on DB init, and everything after this marker - on connection init.
DB init is not re-run when the DB is closed and re-opened after the last connection to it was closed and then new one created. If such re-init is necessary -
jdbc_pin_dboption is supposed to be used instead.It is understood, that this feature can be security sensitive (it effectively implements an RCE entry) in contexts, where other applications/processes/users can control the appending to user-specified connection string or re-writing the specified file in local file system. The following security measures are taken to mitigate that:
session_init_sql_fileoption can only be specified in the connection string itself, it is not accepted as part of connectionPropertiessession_init_sql_fileoption must be specified as the first option in the connection string, for example: 'jdbc:duckdb:;session_init_sql_file=/path/to/init.sql'session_init_sql_file_sha256=<sha56sum_of_sql_file>option can be specified, the file contents SHA-256 sum is checked againts this valuesession_init_sql_file_sha256option can only be specified in the connection string itselfsession_init_sql_fileandsession_init_sql_file_sha256options cannot be specified multiple timesDuckDBConnection#getSessionInitSQL()methodTesting: new tests added in a separate file.