Skip to content
Open
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
47 changes: 25 additions & 22 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -63,36 +63,39 @@ else
RENAME_WHEELS_ARGS=
endif

prefix=dist
$(prefix):
mkdir -p $(prefix)
ifndef PREFIX
PREFIX=dist
endif

$(PREFIX):
mkdir -p $(PREFIX)

TARGET_LOADABLE=$(prefix)/vec0.$(LOADABLE_EXTENSION)
TARGET_STATIC=$(prefix)/libsqlite_vec0.a
TARGET_STATIC_H=$(prefix)/sqlite-vec.h
TARGET_CLI=$(prefix)/sqlite3
TARGET_LOADABLE=$(PREFIX)/vec0.$(LOADABLE_EXTENSION)
TARGET_STATIC=$(PREFIX)/libsqlite_vec0.a
TARGET_STATIC_H=$(PREFIX)/sqlite-vec.h
TARGET_CLI=$(PREFIX)/sqlite3

loadable: $(TARGET_LOADABLE)
static: $(TARGET_STATIC)
cli: $(TARGET_CLI)

all: loadable static cli

OBJS_DIR=$(prefix)/.objs
LIBS_DIR=$(prefix)/.libs
BUILD_DIR=$(prefix)/.build
OBJS_DIR=$(PREFIX)/.objs
LIBS_DIR=$(PREFIX)/.libs
BUILD_DIR=$(PREFIX)/.build

$(OBJS_DIR): $(prefix)
$(OBJS_DIR): $(PREFIX)
mkdir -p $@

$(LIBS_DIR): $(prefix)
$(LIBS_DIR): $(PREFIX)
mkdir -p $@

$(BUILD_DIR): $(prefix)
$(BUILD_DIR): $(PREFIX)
mkdir -p $@


$(TARGET_LOADABLE): sqlite-vec.c sqlite-vec.h $(prefix)
$(TARGET_LOADABLE): sqlite-vec.c sqlite-vec.h $(PREFIX)
$(CC) \
-fPIC -shared \
-Wall -Wextra \
Expand All @@ -101,12 +104,12 @@ $(TARGET_LOADABLE): sqlite-vec.c sqlite-vec.h $(prefix)
$(CFLAGS) \
$< -o $@

$(TARGET_STATIC): sqlite-vec.c sqlite-vec.h $(prefix) $(OBJS_DIR)
$(TARGET_STATIC): sqlite-vec.c sqlite-vec.h $(PREFIX) $(OBJS_DIR)
$(CC) -Ivendor/ $(CFLAGS) -DSQLITE_CORE -DSQLITE_VEC_STATIC \
-O3 -c $< -o $(OBJS_DIR)/vec.o
$(AR) rcs $@ $(OBJS_DIR)/vec.o

$(TARGET_STATIC_H): sqlite-vec.h $(prefix)
$(TARGET_STATIC_H): sqlite-vec.h $(PREFIX)
cp $< $@


Expand Down Expand Up @@ -136,7 +139,7 @@ $(LIBS_DIR)/sqlite-vec.a: $(OBJS_DIR)/sqlite-vec.o $(LIBS_DIR)
$(AR) rcs $@ $<


$(TARGET_CLI): sqlite-vec.h $(LIBS_DIR)/sqlite-vec.a $(LIBS_DIR)/shell.a $(LIBS_DIR)/sqlite3.a examples/sqlite3-cli/core_init.c $(prefix)
$(TARGET_CLI): sqlite-vec.h $(LIBS_DIR)/sqlite-vec.a $(LIBS_DIR)/shell.a $(LIBS_DIR)/sqlite3.a examples/sqlite3-cli/core_init.c $(PREFIX)
$(CC) -g3 \
-Ivendor/ -I./ \
-DSQLITE_CORE \
Expand Down Expand Up @@ -197,13 +200,13 @@ test-loadable-watch:
watchexec --exts c,py,Makefile --clear -- make test-loadable

test-unit:
$(CC) tests/test-unit.c sqlite-vec.c -I./ -Ivendor -o $(prefix)/test-unit && $(prefix)/test-unit
$(CC) tests/test-unit.c sqlite-vec.c -I./ -Ivendor -o $(PREFIX)/test-unit && $(PREFIX)/test-unit

site-dev:
npm --prefix site run dev
npm --PREFIX site run dev

site-build:
npm --prefix site run build
npm --PREFIX site run build

install:
install -d $(INSTALL_LIB_DIR)
Expand All @@ -229,9 +232,9 @@ uninstall:

# ███████████████████████████████ WASM SECTION ███████████████████████████████

WASM_DIR=$(prefix)/.wasm
WASM_DIR=$(PREFIX)/.wasm

$(WASM_DIR): $(prefix)
$(WASM_DIR): $(PREFIX)
mkdir -p $@

SQLITE_WASM_VERSION=3450300
Expand Down
4 changes: 4 additions & 0 deletions bindings/elixir/.formatter.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Used by "mix format"
[
inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"]
]
75 changes: 75 additions & 0 deletions bindings/elixir/.github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
name: CI

on:
pull_request:
push:
branches:
- "main"

jobs:
lint:
runs-on: ${{ matrix.os }}
env:
MIX_ENV: dev
name: Lint
strategy:
matrix:
os: ["ubuntu-latest"]
elixir: ["1.17"]
otp: ["27"]
steps:
- uses: actions/checkout@v4
- name: Install Erlang & Elixir
uses: erlef/setup-beam@v1
with:
otp-version: ${{ matrix.otp }}
elixir-version: ${{ matrix.elixir }}
- uses: actions/cache@v3
with:
path: deps
key: ${{ matrix.os }}-otp_${{ matrix.otp }}-elixir_${{ matrix.elixir }}-mix_${{ hashFiles('**/mix.lock') }}
restore-keys: ${{ matrix.os }}-otp_${{ matrix.otp }}-elixir_${{ matrix.elixir }}-mix_
- name: Install mix dependencies
run: mix deps.get
- name: Compile mix dependencies
run: mix deps.compile
- name: Check formatting
run: mix format --check-formatted
- name: Check unused deps
run: mix deps.unlock --check-unused
- name: Credo check
run: mix credo --all

test:
runs-on: ${{ matrix.os }}
env:
MIX_ENV: test

name: Test Elixir ${{ matrix.elixir }}, OTP ${{ matrix.otp }}, OS ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: ["ubuntu-latest"]
elixir: ["1.17"]
otp: ["27"]

steps:
- uses: actions/checkout@v4
- uses: erlef/setup-beam@v1
with:
otp-version: ${{ matrix.otp }}
elixir-version: ${{ matrix.elixir }}

- uses: actions/cache@v3
with:
path: deps
key: ${{ matrix.os }}-otp_${{ matrix.otp }}-elixir_${{ matrix.elixir }}-mix_${{ hashFiles('**/mix.lock') }}
restore-keys: ${{ matrix.os }}-otp_${{ matrix.otp }}-elixir_${{ matrix.elixir }}-mix_
- name: Install mix dependencies
run: mix deps.get --only test
- name: Compile mix dependencies
run: mix deps.compile
- name: Compile project
run: mix compile
- name: Test project
run: mix test --include slow
35 changes: 35 additions & 0 deletions bindings/elixir/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# The directory Mix will write compiled artifacts to.
/_build/

# If you run "mix test --cover", coverage assets end up here.
/cover/

# The directory Mix downloads your dependencies sources to.
/deps/

# Where third-party dependencies like ExDoc output generated docs.
/doc/

# Ignore .fetch files in case you like to edit your project deps locally.
/.fetch

# If the VM crashes, it generates a dump, let's ignore it too.
erl_crash.dump

# Also ignore archive artifacts (built via "mix archive.build").
*.ez

# Ignore package tarball (built via "mix hex.build").
sqlite_vec-*.tar

# Temporary files, for example, from tests.
/tmp/

# downloaded libraries
/priv/**/vec0.*

/notebooks/*.db
/notebooks/*.db-*

# test database
/test/*.db*
21 changes: 21 additions & 0 deletions bindings/elixir/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2024 Joel Koch

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
1 change: 1 addition & 0 deletions bindings/elixir/Makefile
59 changes: 59 additions & 0 deletions bindings/elixir/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# SqliteVec

[![Hex Package](https://img.shields.io/hexpm/v/sqlite_vec.svg?style=for-the-badge)](https://hex.pm/packages/sqlite_vec)
[![Hex Docs](https://img.shields.io/badge/hex-docs-blue.svg?style=for-the-badge)](https://hexdocs.pm/sqlite_vec)
[![Build Status](https://img.shields.io/github/actions/workflow/status/joelpaulkoch/sqlite_vec/ci.yml?label=Build%20Status&style=for-the-badge&branch=main)](https://github.com/joelpaulkoch/sqlite_vec/actions)

A wrapper to use [sqlite-vec](https://github.com/asg017/sqlite-vec), a SQLite extension for working with vectors, in Elixir.
Builds the loadable library using `elixir_make`.
Moreover, this package provides structs and custom Ecto types for working with Float32, Int8, and Bit vectors.

## Limitations
- it's currently not possible to create int8 and bit vectors using `Ecto`. You must directly use SQL to do so
- not implemented operations: `vec_each`, `vec_quantize_i8`

## Installation

The package can be installed by adding `sqlite_vec` to your list of dependencies in `mix.exs`:

```elixir
def deps do
[
{:sqlite_vec, "~> 0.1.0"}
]
end
```

## Getting Started

`SqliteVec.path/0` returns the path of the loadable library.
Therefore, you can load the extension using this path.

For instance with `Exqlite`:
```elixir
{:ok, conn} = Basic.open(":memory:")
:ok = Basic.enable_load_extension(conn)

Basic.load_extension(conn, SqliteVec.path())
```

Or, with an `Ecto.Repo` and `ecto_sqlite3`:

```elixir
defmodule MyApp.Repo do
use Ecto.Repo,
otp_app: :my_app,
adapter: Ecto.Adapters.SQLite3
end

config :my_app, MyApp.Repo, load_extensions: [SqliteVec.path()]
```

You can check out the [Getting Started](notebooks/getting_started.livemd) and [Usage with Ecto](notebooks/usage_with_ecto.livemd) notebooks.

## Attribution

Special thanks to these projects that helped to make this package:

- [sqlite-vec](https://github.com/asg017/sqlite-vec), of course, which provides all of the functionality
- [pgvector](https://hexdocs.pm/pgvector/readme.html) provides something similar for postgres and quite some code could be reused
1 change: 1 addition & 0 deletions bindings/elixir/VERSION
12 changes: 12 additions & 0 deletions bindings/elixir/lib/sqlite_vec.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
defmodule SqliteVec do
@moduledoc false

@target System.get_env("MIX_TARGET", "")

@doc """
Provides the path to the loadable library.
"""
def path() do
Path.join([:code.priv_dir(:sqlite_vec), @target, "vec0"])
end
end
Loading