diff --git a/.github/workflows/MainDistributionPipeline.yml b/.github/workflows/MainDistributionPipeline.yml
index 5935195..301b0b6 100644
--- a/.github/workflows/MainDistributionPipeline.yml
+++ b/.github/workflows/MainDistributionPipeline.yml
@@ -3,7 +3,6 @@
#
name: Main Extension Distribution Pipeline
on:
- push:
pull_request:
workflow_dispatch:
diff --git a/.github/workflows/SQLTests.yml b/.github/workflows/SQLTests.yml
index ca6e69d..1ae4874 100644
--- a/.github/workflows/SQLTests.yml
+++ b/.github/workflows/SQLTests.yml
@@ -6,9 +6,6 @@ on:
GSHEETS_KEY_FILE_JSON:
required: false
- # For fork PRs: runs with base repo secrets after environment approval
- pull_request_target:
-
# Manual trigger: maintainers can run SQL tests for any ref
workflow_dispatch:
inputs:
diff --git a/.gitignore b/.gitignore
index c4a7041..1c8d250 100644
--- a/.gitignore
+++ b/.gitignore
@@ -31,3 +31,9 @@ _site/
token.txt
credentials.json
service-account-credentials.json
+
+# Local Temp Files
+tmp/
+
+# Proxy Configs
+tinyproxy.conf
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 6581756..da939ef 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -31,10 +31,12 @@ set(EXTENSION_SOURCES
src/sheets/transport/httplib_client.cpp
src/sheets/transport/duckdb_http_client.cpp
src/sheets/transport/mock_http_client.cpp
+ src/sheets/transport/client_factory.cpp
src/sheets/util/encoding.cpp
src/sheets/range.cpp
src/sheets/auth_factory.cpp
src/utils/secret.cpp
+ src/utils/proxy.cpp
src/utils/version.cpp)
# Warn on unused/dead code (GCC/Clang only; MSVC uses different flag syntax)
diff --git a/docs/pages/index.md b/docs/pages/index.md
index a1b381b..990b66e 100644
--- a/docs/pages/index.md
+++ b/docs/pages/index.md
@@ -9,9 +9,8 @@ hide_title: true
**🚧 Experimental 🚧** Here be dragons
-
-
+
A DuckDB extension for reading and writing Google Sheets with SQL.
@@ -26,7 +25,7 @@ LOAD gsheets;
The latest version of [DuckDB](https://duckdb.org/docs/installation) (currently 1.4.0) is supported.
-## Usage
+## Usage
### Authenticate
@@ -37,22 +36,45 @@ CREATE SECRET (TYPE gsheet);
-- OR create a secret with your Google API access token (boring, see below guide)
CREATE SECRET (
- TYPE gsheet,
- PROVIDER access_token,
+ TYPE gsheet,
+ PROVIDER access_token,
TOKEN ''
);
--- OR create a non-expiring JSON secret with your Google API private key
+-- OR create a non-expiring JSON secret with your Google API private key
-- (This enables use in non-interactive workflows like data pipelines)
-- (see "Getting a Google API Access Private Key" below)
CREATE SECRET (
- TYPE gsheet,
- PROVIDER key_file,
+ TYPE gsheet,
+ PROVIDER key_file,
FILEPATH ''
);
```
+### HTTP Proxy
+
+See [HTTP Proxy documentation](https://duckdb.org/docs/stable/core_extensions/httpfs/https#http-proxy).
+
+You can add an HTTP proxy using the Secrets Manager:
+
+```sql
+CREATE SECRET http_proxy (
+ TYPE http,
+ HTTP_PROXY 'http_proxy_url',
+ HTTP_PROXY_USERNAME 'username',
+ HTTP_PROXY_PASSWORD 'password'
+);
+```
+
+Alternatively, you can add it via configuration options:
+
+```sql
+SET http_proxy = 'http_proxy_url';
+SET http_proxy_username = 'username';
+SET http_proxy_password = 'password';
+```
+
### Read
```sql
@@ -102,40 +124,40 @@ copy to 'https://docs.google.com/spreadsheets/d/11QdEasMWbETbFVxry-
-- Write a spreadsheet to a specific sheet with the sheet parameter
-- NOTE: A sheet parameter will take precedence over the query string
-copy
-to 'https://docs.google.com/spreadsheets/d/11QdEasMWbETbFVxry-SsD8jVcdYIT1zBQszcF84MdE8/edit'
+copy
+to 'https://docs.google.com/spreadsheets/d/11QdEasMWbETbFVxry-SsD8jVcdYIT1zBQszcF84MdE8/edit'
(format gsheet, sheet 'Woot');
-- Write a spreadsheet to a specific range with the range parameter
-- NOTE: A range parameter will take precedence over the query string
-copy
-to 'https://docs.google.com/spreadsheets/d/11QdEasMWbETbFVxry-SsD8jVcdYIT1zBQszcF84MdE8/edit'
+copy
+to 'https://docs.google.com/spreadsheets/d/11QdEasMWbETbFVxry-SsD8jVcdYIT1zBQszcF84MdE8/edit'
(format gsheet, sheet 'Woot', range 'B2:C10000');
-- Only overwrite the range that is being written to
-copy
-to 'https://docs.google.com/spreadsheets/d/11QdEasMWbETbFVxry-SsD8jVcdYIT1zBQszcF84MdE8/edit'
+copy
+to 'https://docs.google.com/spreadsheets/d/11QdEasMWbETbFVxry-SsD8jVcdYIT1zBQszcF84MdE8/edit'
(format gsheet, sheet 'Woot', range 'B2:C10000', overwrite_range TRUE);
-- Overwrite the entire sheet (this is the default)
-copy
-to 'https://docs.google.com/spreadsheets/d/11QdEasMWbETbFVxry-SsD8jVcdYIT1zBQszcF84MdE8/edit'
+copy
+to 'https://docs.google.com/spreadsheets/d/11QdEasMWbETbFVxry-SsD8jVcdYIT1zBQszcF84MdE8/edit'
(format gsheet, sheet 'Woot', range 'B2:C10000', overwrite_sheet TRUE);
-- Append below existing data
-- (by default, no header will be included)
-copy
-to 'https://docs.google.com/spreadsheets/d/11QdEasMWbETbFVxry-SsD8jVcdYIT1zBQszcF84MdE8/edit'
+copy
+to 'https://docs.google.com/spreadsheets/d/11QdEasMWbETbFVxry-SsD8jVcdYIT1zBQszcF84MdE8/edit'
(format gsheet, sheet 'Woot', range 'B2:C10000', overwrite_sheet FALSE, overwrite_range FALSE);
-- Append below existing data, but force the output of a header
-copy
-to 'https://docs.google.com/spreadsheets/d/11QdEasMWbETbFVxry-SsD8jVcdYIT1zBQszcF84MdE8/edit'
+copy
+to 'https://docs.google.com/spreadsheets/d/11QdEasMWbETbFVxry-SsD8jVcdYIT1zBQszcF84MdE8/edit'
(format gsheet, sheet 'Woot', range 'B2:C10000', overwrite_sheet FALSE, overwrite_range FALSE, header TRUE);
-- Write with no header
-copy
-to 'https://docs.google.com/spreadsheets/d/11QdEasMWbETbFVxry-SsD8jVcdYIT1zBQszcF84MdE8/edit'
+copy
+to 'https://docs.google.com/spreadsheets/d/11QdEasMWbETbFVxry-SsD8jVcdYIT1zBQszcF84MdE8/edit'
(format gsheet, header FALSE);
```
@@ -178,7 +200,7 @@ The contents of the JSON file will be stored in the secret, as will the temporar
Follow steps 13 and 14.
-This private key by default will not expire. Use caution with it.
+This private key by default will not expire. Use caution with it.
This will also require an additional API request approximately every 30 minutes.
@@ -188,6 +210,6 @@ This will also require an additional API request approximately every 30 minutes.
- Google Sheets has a limit of 10,000,000 cells per spreadsheet.
- Sheets must already exist to COPY TO them.
-## Support
+## Support
If you are having problems, find a bug, or have an idea for an improvement, please [file an issue on GitHub](https://github.com/evidence-dev/duckdb_gsheets).
diff --git a/src/gsheets_copy.cpp b/src/gsheets_copy.cpp
index 33f6b52..7b3472f 100644
--- a/src/gsheets_copy.cpp
+++ b/src/gsheets_copy.cpp
@@ -10,7 +10,7 @@
#include "sheets/auth_factory.hpp"
#include "sheets/client.hpp"
#include "sheets/range.hpp"
-#include "sheets/transport/httplib_client.hpp"
+#include "sheets/transport/client_factory.hpp"
#include "sheets/types.hpp"
namespace duckdb {
@@ -139,7 +139,7 @@ unique_ptr GSheetCopyFunction::GSheetWriteInitializeGlobal(C
std::string sheet_range;
// Initialize client
- auto http = make_uniq();
+ auto http = sheets::CreateHttpClient(context);
auto auth = sheets::CreateAuthFromSecret(context, *http);
if (!auth) {
throw InvalidInputException("No 'gsheet' secret found...");
diff --git a/src/gsheets_read.cpp b/src/gsheets_read.cpp
index 52d8c57..1d946af 100644
--- a/src/gsheets_read.cpp
+++ b/src/gsheets_read.cpp
@@ -7,7 +7,7 @@
#include "sheets/client.hpp"
#include "sheets/auth_factory.hpp"
-#include "sheets/transport/httplib_client.hpp"
+#include "sheets/transport/client_factory.hpp"
namespace duckdb {
@@ -103,12 +103,12 @@ unique_ptr ReadSheetBind(ClientContext &context, TableFunctionBind
std::string sheet_range = extract_sheet_range(sheet_input);
// Initialize client
- sheets::HttpLibClient http;
- auto auth = sheets::CreateAuthFromSecret(context, http);
+ auto http = sheets::CreateHttpClient(context);
+ auto auth = sheets::CreateAuthFromSecret(context, *http);
if (!auth) {
throw InvalidInputException("No 'gsheet' secret found...");
}
- sheets::GoogleSheetsClient client(http, *auth);
+ sheets::GoogleSheetsClient client(*http, *auth);
// Parse named parameters
for (auto &kv : input.named_parameters) {
diff --git a/src/include/sheets/auth_factory.hpp b/src/include/sheets/auth_factory.hpp
index 622bfa9..5b1c0ab 100644
--- a/src/include/sheets/auth_factory.hpp
+++ b/src/include/sheets/auth_factory.hpp
@@ -8,8 +8,7 @@
namespace duckdb {
namespace sheets {
-std::unique_ptr CreateAuthFromSecret(ClientContext &ctx, IHttpClient &http,
- const std::string &secretName = "");
+std::unique_ptr CreateAuthFromSecret(ClientContext &ctx, IHttpClient &http);
} // namespace sheets
} // namespace duckdb
diff --git a/src/include/sheets/transport/client_factory.hpp b/src/include/sheets/transport/client_factory.hpp
new file mode 100644
index 0000000..6e06718
--- /dev/null
+++ b/src/include/sheets/transport/client_factory.hpp
@@ -0,0 +1,15 @@
+#pragma once
+
+#include
+
+#include "duckdb/main/client_context.hpp"
+
+#include "sheets/transport/http_client.hpp"
+
+namespace duckdb {
+namespace sheets {
+
+std::unique_ptr CreateHttpClient(ClientContext &ctx);
+
+} // namespace sheets
+} // namespace duckdb
diff --git a/src/include/sheets/transport/http_type.hpp b/src/include/sheets/transport/http_type.hpp
index 09f2f21..bbf9452 100644
--- a/src/include/sheets/transport/http_type.hpp
+++ b/src/include/sheets/transport/http_type.hpp
@@ -1,5 +1,6 @@
#pragma once
+#include
#include
#include