Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
162 changes: 0 additions & 162 deletions .github/workflows/ExtensionTemplate.yml

This file was deleted.

16 changes: 8 additions & 8 deletions .github/workflows/MainDistributionPipeline.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,17 @@ concurrency:
jobs:
duckdb-stable-build:
name: Build extension binaries
uses: duckdb/extension-ci-tools/.github/workflows/_extension_distribution.yml@v1.5.1
uses: duckdb/extension-ci-tools/.github/workflows/_extension_distribution.yml@v1.5-variegata
with:
duckdb_version: v1.5.1
ci_tools_version: v1.5.1
extension_name: quack
duckdb_version: v1.5.2
ci_tools_version: v1.5-variegata
extension_name: cozip

code-quality-check:
name: Code Quality Check
uses: duckdb/extension-ci-tools/.github/workflows/_extension_code_quality.yml@v1.5.1
uses: duckdb/extension-ci-tools/.github/workflows/_extension_code_quality.yml@v1.5-variegata
with:
duckdb_version: v1.5.1
ci_tools_version: v1.5.1
extension_name: quack
duckdb_version: v1.5.2
ci_tools_version: v1.5-variegata
extension_name: cozip
format_checks: 'format;tidy'
22 changes: 18 additions & 4 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,8 +1,22 @@
build
.idea
cmake-build-debug
build/
out/
.vs/
.idea/
cmake-build-debug/
duckdb_unittest_tempdir/
.DS_Store
testext

.DS_Store
*.user
CMakeUserPresets.json

__pycache__/
test/python/__pycache__/
.ipynb_checkpoints/
.Rhistory
tmp/
notebooks/cozip_validation_artifacts/
notebooks/

src/cozip_extension_old.cpp
test/sql/cozip_old.test
14 changes: 4 additions & 10 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
cmake_minimum_required(VERSION 3.5)

# Set extension name here
set(TARGET_NAME quack)
set(TARGET_NAME cozip)

# DuckDB's extension distribution supports vcpkg. As such, dependencies can be added in ./vcpkg.json and then
# used in cmake with find_package. Feel free to remove or replace with other dependencies.
# Note that it should also be removed from vcpkg.json to prevent needlessly installing it..
find_package(OpenSSL REQUIRED)
# DuckDB's extension distribution supports vcpkg. cozip currently has no
# third-party dependencies.

set(EXTENSION_NAME ${TARGET_NAME}_extension)
set(LOADABLE_EXTENSION_NAME ${TARGET_NAME}_loadable_extension)
Expand All @@ -18,15 +16,11 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)

include_directories(src/include)

set(EXTENSION_SOURCES src/quack_extension.cpp)
set(EXTENSION_SOURCES src/cozip_extension.cpp)

build_static_extension(${TARGET_NAME} ${EXTENSION_SOURCES})
build_loadable_extension(${TARGET_NAME} " " ${EXTENSION_SOURCES})

# Link OpenSSL in both the static library as the loadable extension
target_link_libraries(${EXTENSION_NAME} OpenSSL::SSL OpenSSL::Crypto)
target_link_libraries(${LOADABLE_EXTENSION_NAME} OpenSSL::SSL OpenSSL::Crypto)

install(
TARGETS ${EXTENSION_NAME}
EXPORT "${DUCKDB_EXPORT_SET}"
Expand Down
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
PROJ_DIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))

# Configuration of extension
EXT_NAME=quack
EXT_NAME=cozip
EXT_CONFIG=${PROJ_DIR}extension_config.cmake

# Include the Makefile from extension-ci-tools
include extension-ci-tools/makefiles/duckdb_extension.Makefile
include extension-ci-tools/makefiles/duckdb_extension.Makefile
133 changes: 133 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
# cozip DuckDB Extension

`cozip` is a small DuckDB extension for inspecting ZIP-compatible `cozip`
archives. A `cozip` file is still a valid ZIP file, but its first entry is a
special `__cozip__` member containing a compact binary index with priority file
names, absolute payload offsets, and payload sizes.

This extension currently focuses on local-file inspection. It validates the
core cozip 1.0 layout and exposes the priority index through DuckDB SQL. It
does not create archives or decompress payloads.

## SQL API

```sql
LOAD cozip;

SELECT cozip_priority_count('test/data/flat_store_6files.cozip');
SELECT cozip_profile('test/data/flat_store_6files.cozip');
SELECT cozip_integrity_hash_ok('test/data/flat_store_6files.cozip');
SELECT cozip_metadata_offset('test/data/flat_store_6files.cozip');
SELECT cozip_index_json('test/data/flat_store_6files.cozip');

SELECT *
FROM cozip_index('test/data/flat_store_6files.cozip')
ORDER BY ordinal;
```

`cozip_index(path)` returns:

| column | type | meaning |
| --- | --- | --- |
| `ordinal` | `UBIGINT` | priority-entry order in the `__cozip__` index |
| `name` | `VARCHAR` | priority-entry name |
| `offset_bytes` | `UBIGINT` | absolute payload offset from byte 0 |
| `size_bytes` | `UBIGINT` | payload size in bytes |

Scalar functions:

| function | returns |
| --- | --- |
| `cozip_priority_count(path)` | number of entries listed in the `__cozip__` priority index |
| `cozip_profile(path)` | profile byte from the cozip index header |
| `cozip_metadata_offset(path)` | absolute payload offset for `__metadata__` |
| `cozip_integrity_hash_ok(path)` | whether the stored FNV-1a integrity hash matches |
| `cozip_tail_hash_ok(path)` | compatibility alias for `cozip_integrity_hash_ok` |
| `cozip_index_json(path)` | compact JSON representation of the parsed index |

## Format Notes

The reader expects the current cozip core format:

1. The first ZIP Local File Header starts at byte `0`.
2. The first entry name is exactly `__cozip__`.
3. The `__cozip__` Local File Header has a single 12-byte extra field with
header id `0xCA0C`.
4. The cozip index payload starts at byte `51`.
5. The index payload begins with `CZIP`, followed by `version`, `profile`, and
`n_entries`.
6. The integrity hash is FNV-1a 64 over the index payload and the final
`32768` bytes of the archive, counting overlapping bytes once.
7. The stored hash lives in archive bytes `43..50`.

## Build On Windows

Configure with CMake and the DuckDB submodule:

```powershell
cmake -S .\duckdb -B .\build\release -G "Visual Studio 18 2026" -A x64 -T v143 `
-DDUCKDB_EXTENSION_CONFIGS="${PWD}\extension_config.cmake" `
-DEXTENSION_STATIC_BUILD=1 `
-DUNITTEST_ROOT_DIRECTORY="${PWD}" `
-DBENCHMARK_ROOT_DIRECTORY="${PWD}" `
-DENABLE_UNITTEST_CPP_TESTS=FALSE `
-DENABLE_EXTENSION_AUTOLOADING=0 `
-DENABLE_EXTENSION_AUTOINSTALL=0
```

If `cmake` is not on your `PATH`, use the Visual Studio bundled executable,
for example:

```powershell
& "C:\Program Files\Microsoft Visual Studio\18\Community\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin\cmake.exe" --version
```

Build the extension and test runner:

```powershell
cmake --build .\build\release --config Release --target cozip_loadable_extension
cmake --build .\build\release --config Release --target unittest
```

Run the extension tests:

```powershell
.\build\release\test\Release\unittest.exe --test-dir . "test/sql/cozip.test"
```

If Windows refuses to overwrite `cozip.duckdb_extension`, close any Python, R,
or DuckDB process that previously loaded it.

## Local Manual Test

```powershell
.\build\release\Release\duckdb.exe -unsigned -c "LOAD './build/release/extension/cozip/cozip.duckdb_extension'; SELECT * FROM cozip_index('test/data/flat_store_6files.cozip');"
```

## GitHub Actions

`.github/workflows/MainDistributionPipeline.yml` calls DuckDB's official
`extension-ci-tools` reusable pipeline. That pipeline builds and tests the
extension on Linux, Windows, and macOS using the same SQLLogicTest file under
`test/sql/` that we run locally.

## Notebooks

- `notebooks/cozip_architecture.ipynb` explains the binary layout, formulas,
integrity hash, and generation steps.
- `notebooks/cozip_python_testing.ipynb` loads the compiled extension from
Python and cross-checks the fixture with the pure-Python parser in
`notebooks/cozip.py`.

## Generating A `.cozip`

A `.cozip` is not produced by renaming an arbitrary `.zip`. It is generated as a
ZIP file with extra rules:

1. Write `__cozip__` as the first local file entry.
2. Use ZIP method STORE for `__cozip__`.
3. Put a 12-byte extra field in the `__cozip__` local header.
4. Store a `CZIP` payload listing priority names, offsets, and sizes.
5. Write regular ZIP entries, Central Directory, and EOCD.
6. Compute FNV-1a over the index payload and the final 32768 bytes.
7. Store that hash in the `__cozip__` extra field.
Loading
Loading