Skip to content

Commit 82fca57

Browse files
committed
First commit
0 parents  commit 82fca57

File tree

6 files changed

+199
-0
lines changed

6 files changed

+199
-0
lines changed

.github/workflows/build.yml

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
name: build
2+
on: [push, pull_request]
3+
jobs:
4+
build:
5+
runs-on: ubuntu-latest
6+
steps:
7+
- uses: actions/checkout@v4
8+
- uses: ankane/setup-postgres@v1
9+
with:
10+
database: pgvector_fortran_test
11+
dev-files: true
12+
- run: |
13+
cd /tmp
14+
git clone --branch v0.8.0 https://github.com/pgvector/pgvector.git
15+
cd pgvector
16+
make
17+
sudo make install
18+
- uses: fortran-lang/setup-fpm@v5
19+
with:
20+
fpm-version: 0.10.1
21+
- run: fpm run

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
build

LICENSE.txt

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
The MIT License (MIT)
2+
3+
Copyright (c) 2024 Andrew Kane
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in
13+
all copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21+
THE SOFTWARE.

README.md

+84
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
# pgvector-fortran
2+
3+
[pgvector](https://github.com/pgvector/pgvector) support for Fortran
4+
5+
Supports [Libpq-Fortran](https://github.com/ShinobuAmasaki/libpq-fortran)
6+
7+
[![Build Status](https://github.com/pgvector/pgvector-fortran/actions/workflows/build.yml/badge.svg)](https://github.com/pgvector/pgvector-fortran/actions)
8+
9+
## Getting Started
10+
11+
Follow the instructions for your database library:
12+
13+
- [Libpq-Fortran](#libpq-fortran)
14+
15+
## Libpq-Fortran
16+
17+
Enable the extension
18+
19+
```fortran
20+
type(c_ptr) :: res
21+
22+
res = PQexec(conn, "CREATE EXTENSION IF NOT EXISTS vector")
23+
```
24+
25+
Create a table
26+
27+
```fortran
28+
res = PQexec(conn, "CREATE TABLE items (id bigserial PRIMARY KEY, embedding vector(3))")
29+
```
30+
31+
Insert vectors
32+
33+
```fortran
34+
character(256) :: values(2)
35+
36+
values(1) = "[1,2,3]"
37+
values(2) = "[4,5,6]"
38+
res = PQexecParams(conn, "INSERT INTO items (embedding) VALUES ($1), ($2)", 2, [0, 0], values)
39+
```
40+
41+
Get the nearest neighbors
42+
43+
```fortran
44+
character(256) :: values(1)
45+
46+
values(1) = "[3,1,2]"
47+
res = PQexecParams(conn, "SELECT * FROM items ORDER BY embedding <-> $1 LIMIT 5", 1, [0], values)
48+
```
49+
50+
Add an approximate index
51+
52+
```fortran
53+
res = PQexec(conn, "CREATE INDEX ON items USING hnsw (embedding vector_l2_ops)")
54+
! or
55+
res = PQexec(conn, "CREATE INDEX ON items USING ivfflat (embedding vector_l2_ops) WITH (lists = 100)")
56+
```
57+
58+
Use `vector_ip_ops` for inner product and `vector_cosine_ops` for cosine distance
59+
60+
See a [full example](app/main.f90)
61+
62+
## Contributing
63+
64+
Everyone is encouraged to help improve this project. Here are a few ways you can help:
65+
66+
- [Report bugs](https://github.com/pgvector/pgvector-fortran/issues)
67+
- Fix bugs and [submit pull requests](https://github.com/pgvector/pgvector-fortran/pulls)
68+
- Write, clarify, or fix documentation
69+
- Suggest or add new features
70+
71+
To get started with development:
72+
73+
```sh
74+
git clone https://github.com/pgvector/pgvector-fortran.git
75+
cd pgvector-fortran
76+
createdb pgvector_fortran_test
77+
fpm run
78+
```
79+
80+
Specify the path to libpq if needed:
81+
82+
```sh
83+
FPM_CFLAGS="-I/opt/homebrew/opt/libpq/include" FPM_LDFLAGS="-L/opt/homebrew/opt/libpq/lib" fpm run
84+
```

app/main.f90

+62
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
program main
2+
use iso_c_binding
3+
use libpq
4+
implicit none
5+
6+
type(c_ptr) :: conn
7+
type(c_ptr) :: res
8+
character(256) :: values(3)
9+
integer :: ntuples
10+
integer :: i
11+
12+
conn = PQconnectdb("postgres://localhost/pgvector_fortran_test")
13+
if (PQstatus(conn) /= CONNECTION_OK) then
14+
stop 1
15+
endif
16+
17+
res = PQexec(conn, "CREATE EXTENSION IF NOT EXISTS vector")
18+
if (PQresultStatus(res) /= PGRES_COMMAND_OK) then
19+
stop 1
20+
endif
21+
call PQclear(res)
22+
23+
res = PQexec(conn, "DROP TABLE IF EXISTS items")
24+
if (PQresultStatus(res) /= PGRES_COMMAND_OK) then
25+
stop 1
26+
endif
27+
call PQclear(res)
28+
29+
res = PQexec(conn, "CREATE TABLE items (id bigserial PRIMARY KEY, embedding vector(3))")
30+
if (PQresultStatus(res) /= PGRES_COMMAND_OK) then
31+
stop 1
32+
endif
33+
call PQclear(res)
34+
35+
values(1) = "[1,1,1]"
36+
values(2) = "[2,2,2]"
37+
values(3) = "[1,1,2]"
38+
res = PQexecParams(conn, "INSERT INTO items (embedding) VALUES ($1), ($2), ($3)", 3, [0, 0, 0], values)
39+
if (PQresultStatus(res) /= PGRES_COMMAND_OK) then
40+
stop 1
41+
endif
42+
call PQclear(res)
43+
44+
values(1) = "[1,1,1]"
45+
res = PQexecParams(conn, "SELECT * FROM items ORDER BY embedding <-> $1 LIMIT 5", 1, [0], values)
46+
if (PQresultStatus(res) /= PGRES_TUPLES_OK) then
47+
stop 1
48+
endif
49+
ntuples = PQntuples(res)
50+
do i = 0, ntuples - 1
51+
print *, PQgetvalue(res, i, 0), ": ", PQgetvalue(res, i, 1)
52+
end do
53+
call PQclear(res)
54+
55+
res = PQexec(conn, "CREATE INDEX ON items USING hnsw (embedding vector_l2_ops)")
56+
if (PQresultStatus(res) /= PGRES_COMMAND_OK) then
57+
stop 1
58+
endif
59+
call PQclear(res)
60+
61+
call PQfinish(conn)
62+
end program main

fpm.toml

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
name = "pgvector"
2+
3+
[build]
4+
link = ["pq"]
5+
6+
[dependencies]
7+
libpq-fortran = { git = "https://github.com/ankane/libpq-fortran", branch = "fixes" }
8+
9+
[install]
10+
library = false

0 commit comments

Comments
 (0)