Search Shortcut cmd + k | ctrl + k
gdrive

Query files in Google Drive directly with a gdrive:// filesystem

Maintainer(s): jrosskopf

Installing and Loading

INSTALL gdrive FROM community;
LOAD gdrive;

Example

-- Unattended: a service account. To WRITE you need a Shared Drive --
-- service accounts have no personal Drive storage quota and get
-- 403 storageQuotaExceeded anywhere else. Reading a shared folder is fine.
--
-- DRIVE_ID is a SHARED DRIVE id; ROOT_FOLDER_ID is a FOLDER id. They are
-- not interchangeable: passing a folder id as DRIVE_ID fails with
-- "Shared drive not found". Use whichever matches what was shared.
CREATE SECRET gdrive (
    TYPE gdrive,
    PROVIDER service_account,
    KEY_FILE '/etc/creds/sa.json',
    DRIVE_ID '0ABcDeFgHiJkLmNoPQ',       -- or ROOT_FOLDER_ID '1a2b3c...'
    DRIVE_SCOPE 'https://www.googleapis.com/auth/drive.readonly'
);

-- Query a file by path. Drive has no path addressing, so each segment
-- costs a lookup; results are cached per secret.
SELECT count(*) FROM 'gdrive://Finance/2026/actuals.parquet';

-- Address a file by id instead: zero resolution calls. Prefer this in
-- generated or stored queries.
SELECT * FROM read_csv('gdrive://id:1a2b3cDeFgHiJkLmNoPQrStUvWxYz');

-- Glob a folder.
SELECT * FROM read_parquet('gdrive://exports/parts/*.parquet');

-- A native Google Sheet is queryable with no manual export: it has no
-- byte stream, so it is served through Drive's CSV export.
SELECT * FROM read_csv('gdrive://Finance/Budget');

-- Write a whole file. Writes are sequential; Drive cannot write at a
-- byte offset, so positional writes raise an error rather than corrupt.
COPY (SELECT * FROM t) TO 'gdrive://reports/out.parquet' (FORMAT parquet);

-- Inspect API calls and cache hits for the session.
SELECT * FROM gdrive_stats();

About gdrive

Registers a gdrive:// filesystem, so any DuckDB path expression can address a file in Google Drive with no download or copy step. Because DuckDB dispatches file access through its virtual filesystem, everything layered on it inherits the scheme: read_parquet, read_csv, COPY, glob, and table formats such as DuckLake — attaching a DuckLake whose DATA_PATH is on Drive works and is tested live.

ATTACH of a DuckDB database file on gdrive:// is NOT supported. DuckDB opens database files through a different path that does not consult the virtual filesystem, so the attempt fails immediately rather than half-working.

This is Google Drive, not Google Cloud Storage — a different product with a different API and access model. For gs:// buckets use the gcs extension.

Reads are ranged, so a Parquet scan fetches footers and column chunks rather than whole files. Path resolution is cached per secret and per drive, because Drive has no path addressing and each segment otherwise costs an API call.

Two behaviours are deliberately strict. Drive permits two files with the same name in one folder, so a path is not a unique identifier: rather than pick one and make results depend on Drive's internal ordering, ambiguity is an error naming both file ids. And Drive cannot write at a byte offset, so positional writes raise an error instead of silently corrupting a file.

Drive is slower than object storage by a wide margin, and enforces per-user API quotas that object storage does not. A ranged read costs ~1.3 s regardless of how few bytes it requests, against ~1 ms for S3/GCS. Use this when Drive is the system of record for data you want to query and you would rather not maintain a second copy — not as a substitute for object storage under a hot workload. On a workstation, Google Drive for desktop plus ordinary local paths is simpler and faster.

Added Functions

function_name function_type description comment examples
gdrive_reset_stats table Zero the process-wide Drive API call counters reported by gdrive_stats(). Use it to measure exactly what ONE operation costs: reset, run the query, then read gdrive_stats(). Affects the whole process, so it will disturb a concurrent measurement in another connection. NULL [CALL gdrive_reset_stats()]
gdrive_stats table Drive API call counters, one row per metric: files_get, files_list, files_media, files_export, files_create, files_update, files_delete (calls by kind), cache_hits/cache_misses (the path-resolution cache that mitigates R-1 amplification), retries (retried HTTP attempts across all kinds), and total (sum of the files_* kind counters), and path_cache_entries (a GAUGE: the live size of the path->id cache, bounded by gdrive_path_cache_entries). Process-wide, not reset between queries – call it before and after an operation and diff the two snapshots to measure that operation's amplification. NULL [SELECT * FROM gdrive_stats()]
gdrive_version scalar NULL NULL  

Overloaded Functions

This extension does not add any function overloads.

Added Types

This extension does not add any types.

Added Settings

name description input_type scope aliases
gdrive_adc_file Path to an Application Default Credentials JSON file, overriding normal discovery for PROVIDER credential_chain. Empty (default) resolves GOOGLE_APPLICATION_CREDENTIALS, then CLOUDSDK_CONFIG, then the well-known gcloud location. VARCHAR GLOBAL []
gdrive_block_cache_bytes Total memory the shared block cache may hold (default 256 MiB). Least-recently-used blocks are evicted above this. Shared by all files and all threads. UBIGINT GLOBAL []
gdrive_block_size_bytes Block size for cached reads (default 16 MiB, 0 to disable and read exact ranges). Drive charges roughly the same for a 1 KB and a 16 MB request, so larger blocks trade bandwidth for far fewer round trips. UBIGINT GLOBAL []
gdrive_docs_export_mime MIME type to export application/vnd.google-apps.document files as: 'text/plain' (default) or 'text/markdown'. Sheets always export to text/csv. VARCHAR GLOBAL []
gdrive_immutable_prefixes Comma-separated gdrive:// path prefixes whose files are never overwritten in place (e.g. a DuckLake DATA_PATH). Skips the per-open metadata refresh for them. Matching is on whole path segments. Empty (the default) disables it. Declaring a prefix whose files ARE rewritten in place causes stale reads that cannot be detected. VARCHAR GLOBAL []
gdrive_path_cache_entries Maximum path->file-id mappings to cache (default 4096, 0 for unbounded). Least-recently-used entries are dropped above this; a dropped mapping just costs one files.list per segment to rebuild. UBIGINT GLOBAL []
gdrive_permanent_delete RemoveFile permanently deletes instead of moving to trash (default: false, trash). BOOLEAN GLOBAL []