Skip to content

Commit

Permalink
Added preprocessor macros.
Browse files Browse the repository at this point in the history
  • Loading branch information
interkosmos committed Feb 26, 2024
1 parent 89e29d0 commit 0917e3c
Show file tree
Hide file tree
Showing 6 changed files with 133 additions and 89 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ jobs:
sudo apt-get install -y gcc-${GCC_V} gfortran-${GCC_V} make
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-${GCC_V} 100 \
--slave /usr/bin/gfortran gfortran /usr/bin/gfortran-${GCC_V}
sudo apt-get remove -y sqlite3 libsqlite3-0 libsqlite3-dev
sudo apt-get remove -y sqlite3 libsqlite3-dev
- name: Build and Install SQLite 3 (Linux)
if: contains(matrix.os, 'ubuntu')
Expand Down
10 changes: 7 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -11,22 +11,25 @@ RELEASE = -O2 -march=native

CFLAGS = $(RELEASE)
FFLAGS = $(RELEASE)
PPFLAGS = -DSQLITE_ENABLE_COLUMN_METADATA=0
LDFLAGS = -I$(PREFIX)/include -L$(PREFIX)/lib
LDLIBS = -lsqlite3
ARFLAGS = rcs
TARGET = libfortran-sqlite3.a
SRC = src/sqlite3_macro.c src/sqlite3.F90 src/sqlite3_util.f90
OBJ = sqlite3.o sqlite3_macro.o sqlite3_util.o

.PHONY: all clean test

all: $(TARGET)

test: test_sqlite3

$(TARGET): src/sqlite3_util.f90 src/sqlite3.f90
$(TARGET): $(SRC)
$(CC) $(CFLAGS) -c src/sqlite3_macro.c
$(FC) $(FFLAGS) -c src/sqlite3_util.f90
$(FC) $(FFLAGS) -c src/sqlite3.f90
$(AR) $(ARFLAGS) $(TARGET) sqlite3.o sqlite3_macro.o sqlite3_util.o
$(FC) $(FFLAGS) $(PPFLAGS) -c src/sqlite3.F90
$(AR) $(ARFLAGS) $(TARGET) $(OBJ)

test_sqlite3: $(TARGET) test/test_sqlite3.f90
$(FC) $(FFLAGS) $(LDFLAGS) -o test_sqlite3 test/test_sqlite3.f90 $(TARGET) $(LDLIBS)
Expand All @@ -36,3 +39,4 @@ clean:
if [ `ls -1 *.o 2>/dev/null | wc -l` -gt 0 ]; then rm *.o; fi
if [ -e $(TARGET) ]; then rm $(TARGET); fi
if [ -e test_sqlite3 ]; then rm test_sqlite3; fi
if [ -e test.sqlite ]; then rm test.sqlite; fi
24 changes: 24 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@ run:
# pkg install databases/sqlite3
```

On Linux:

```
# apt-get install sqlite3 libsqlite3-0 libsqlite3-dev
```

Then, clone the GitHub repository:

```
Expand Down Expand Up @@ -40,9 +46,27 @@ Execute the provided `Makefile`:
$ make
```

Pass the preprocessor flag `-DSQLITE_ENABLE_COLUMN_METADATA=1` to add interface
bindings to column meta data functions:

```
$ make PPFLAGS="-DSQLITE_ENABLE_COLUMN_METADATA=1"
```

You may want to override the default compilers by passing the arguments `CC` (C
compiler) and `FC` (Fortran compiler).

## Source-Code Documentation

Use [FORD](https://github.com/Fortran-FOSS-Programmers/ford) to generate the
source-code documentation:

```
$ ford ford.md
```

The output files are written to `doc/`.

## Example

The following SQL schema will be created by the example:
Expand Down
1 change: 1 addition & 0 deletions ford.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ project: fortran-sqlite3
summary: A collection of ISO C binding interfaces to SQLite 3.
author: Philipp Engel
project_github: https://github.com/interkosmos/fortran-sqlite3
macro: SQLITE_ENABLE_COLUMN_METADATA=1
143 changes: 76 additions & 67 deletions src/sqlite3.f90 → src/sqlite3.F90
Original file line number Diff line number Diff line change
Expand Up @@ -193,16 +193,10 @@ module sqlite3
public :: sqlite3_close
public :: sqlite3_close_
public :: sqlite3_column_count
public :: sqlite3_column_database_name
public :: sqlite3_column_database_name_
public :: sqlite3_column_double
public :: sqlite3_column_int
public :: sqlite3_column_int64
public :: sqlite3_column_name
public :: sqlite3_column_origin_name
public :: sqlite3_column_origin_name_
public :: sqlite3_column_table_name
public :: sqlite3_column_table_name_
public :: sqlite3_column_text
public :: sqlite3_column_type
public :: sqlite3_config
Expand Down Expand Up @@ -264,6 +258,21 @@ module sqlite3
public :: sqlite3_threadsafe
public :: sqlite3_update_hook

#if SQLITE_ENABLE_COLUMN_METADATA
public :: sqlite3_column_database_name
public :: sqlite3_column_database_name_
public :: sqlite3_column_table_name
public :: sqlite3_column_table_name_
public :: sqlite3_column_origin_name
public :: sqlite3_column_origin_name_
#endif

interface sqlite3_config
module procedure :: sqlite3_config_funptr_ptr
module procedure :: sqlite3_config_int
module procedure :: sqlite3_config_null
end interface

interface
! int sqlite3_backup_finish(sqlite3_backup *p)
function sqlite3_backup_finish(p) bind(c, name='sqlite3_backup_finish')
Expand Down Expand Up @@ -420,15 +429,6 @@ function sqlite3_column_count(stmt) bind(c, name='sqlite3_column_count')
integer(kind=c_int) :: sqlite3_column_count
end function sqlite3_column_count

! const char *sqlite3_column_database_name(sqlite3_stmt *stmt, int idx)
function sqlite3_column_database_name_(stmt, idx) bind(c, name='sqlite3_column_database_name')
import :: c_int, c_ptr
implicit none
type(c_ptr), intent(in), value :: stmt
integer(kind=c_int), intent(in), value :: idx
type(c_ptr) :: sqlite3_column_database_name_
end function sqlite3_column_database_name_

! double sqlite3_column_double(sqlite3_stmt *stmt, int idx)
function sqlite3_column_double(stmt, idx) bind(c, name='sqlite3_column_double')
import :: c_double, c_int, c_ptr
Expand Down Expand Up @@ -465,24 +465,6 @@ function sqlite3_column_name_(stmt, idx) bind(c, name='sqlite3_column_name')
type(c_ptr) :: sqlite3_column_name_
end function sqlite3_column_name_

! const char *sqlite3_column_origin_name(sqlite3_stmt *stmt, int idx)
function sqlite3_column_origin_name_(stmt, idx) bind(c, name='sqlite3_column_origin_name')
import :: c_int, c_ptr
implicit none
type(c_ptr), intent(in), value :: stmt
integer(kind=c_int), intent(in), value :: idx
type(c_ptr) :: sqlite3_column_origin_name_
end function sqlite3_column_origin_name_

! const char *sqlite3_column_table_name(sqlite3_stmt *stmt, int idx)
function sqlite3_column_table_name_(stmt, idx) bind(c, name='sqlite3_column_table_name')
import :: c_int, c_ptr
implicit none
type(c_ptr), intent(in), value :: stmt
integer(kind=c_int), intent(in), value :: idx
type(c_ptr) :: sqlite3_column_table_name_
end function sqlite3_column_table_name_

! const unsigned char *sqlite3_column_text(sqlite3_stmt *stmt, int idx)
function sqlite3_column_text_(stmt, idx) bind(c, name='sqlite3_column_text')
import :: c_int, c_ptr
Expand Down Expand Up @@ -898,11 +880,36 @@ subroutine sqlite3_str_reset(str) bind(c, name='slqite3_str_reset')
end subroutine sqlite3_str_reset
end interface

interface sqlite3_config
module procedure :: sqlite3_config_funptr_ptr
module procedure :: sqlite3_config_int
module procedure :: sqlite3_config_null
#if SQLITE_ENABLE_COLUMN_METADATA
interface
! const char *sqlite3_column_database_name(sqlite3_stmt *stmt, int idx)
function sqlite3_column_database_name_(stmt, idx) bind(c, name='sqlite3_column_database_name')
import :: c_int, c_ptr
implicit none
type(c_ptr), intent(in), value :: stmt
integer(kind=c_int), intent(in), value :: idx
type(c_ptr) :: sqlite3_column_database_name_
end function sqlite3_column_database_name_

! const char *sqlite3_column_origin_name(sqlite3_stmt *stmt, int idx)
function sqlite3_column_origin_name_(stmt, idx) bind(c, name='sqlite3_column_origin_name')
import :: c_int, c_ptr
implicit none
type(c_ptr), intent(in), value :: stmt
integer(kind=c_int), intent(in), value :: idx
type(c_ptr) :: sqlite3_column_origin_name_
end function sqlite3_column_origin_name_

! const char *sqlite3_column_table_name(sqlite3_stmt *stmt, int idx)
function sqlite3_column_table_name_(stmt, idx) bind(c, name='sqlite3_column_table_name')
import :: c_int, c_ptr
implicit none
type(c_ptr), intent(in), value :: stmt
integer(kind=c_int), intent(in), value :: idx
type(c_ptr) :: sqlite3_column_table_name_
end function sqlite3_column_table_name_
end interface
#endif
contains
function sqlite3_backup_init(dest, dest_name, source, source_name)
type(c_ptr), intent(in) :: dest
Expand Down Expand Up @@ -950,16 +957,6 @@ function sqlite3_close(db)
if (sqlite3_close == SQLITE_OK) db = c_null_ptr
end function sqlite3_close

function sqlite3_column_database_name(stmt, idx)
type(c_ptr), intent(inout) :: stmt
integer, intent(in) :: idx
character(len=:), allocatable :: sqlite3_column_database_name
type(c_ptr) :: ptr

ptr = sqlite3_column_database_name_(stmt, idx)
call c_f_str_ptr(ptr, sqlite3_column_database_name)
end function sqlite3_column_database_name

function sqlite3_column_name(stmt, idx)
type(c_ptr), intent(inout) :: stmt
integer, intent(in) :: idx
Expand All @@ -970,26 +967,6 @@ function sqlite3_column_name(stmt, idx)
call c_f_str_ptr(ptr, sqlite3_column_name)
end function sqlite3_column_name

function sqlite3_column_origin_name(stmt, idx)
type(c_ptr), intent(inout) :: stmt
integer, intent(in) :: idx
character(len=:), allocatable :: sqlite3_column_origin_name
type(c_ptr) :: ptr

ptr = sqlite3_column_origin_name_(stmt, idx)
call c_f_str_ptr(ptr, sqlite3_column_origin_name)
end function sqlite3_column_origin_name

function sqlite3_column_table_name(stmt, idx)
type(c_ptr), intent(inout) :: stmt
integer, intent(in) :: idx
character(len=:), allocatable :: sqlite3_column_table_name
type(c_ptr) :: ptr

ptr = sqlite3_column_table_name_(stmt, idx)
call c_f_str_ptr(ptr, sqlite3_column_table_name)
end function sqlite3_column_table_name

function sqlite3_column_text(stmt, idx)
type(c_ptr), intent(inout) :: stmt
integer, intent(in) :: idx
Expand Down Expand Up @@ -1173,4 +1150,36 @@ subroutine sqlite3_log(ierr_code, str)

call sqlite3_log_(ierr_code, str // c_null_char)
end subroutine sqlite3_log

#if SQLITE_ENABLE_COLUMN_METADATA
function sqlite3_column_database_name(stmt, idx)
type(c_ptr), intent(inout) :: stmt
integer, intent(in) :: idx
character(len=:), allocatable :: sqlite3_column_database_name
type(c_ptr) :: ptr

ptr = sqlite3_column_database_name_(stmt, idx)
call c_f_str_ptr(ptr, sqlite3_column_database_name)
end function sqlite3_column_database_name

function sqlite3_column_origin_name(stmt, idx)
type(c_ptr), intent(inout) :: stmt
integer, intent(in) :: idx
character(len=:), allocatable :: sqlite3_column_origin_name
type(c_ptr) :: ptr

ptr = sqlite3_column_origin_name_(stmt, idx)
call c_f_str_ptr(ptr, sqlite3_column_origin_name)
end function sqlite3_column_origin_name

function sqlite3_column_table_name(stmt, idx)
type(c_ptr), intent(inout) :: stmt
integer, intent(in) :: idx
character(len=:), allocatable :: sqlite3_column_table_name
type(c_ptr) :: ptr

ptr = sqlite3_column_table_name_(stmt, idx)
call c_f_str_ptr(ptr, sqlite3_column_table_name)
end function sqlite3_column_table_name
#endif
end module sqlite3
42 changes: 24 additions & 18 deletions test/test_sqlite3.f90
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@ integer(kind=c_int) function exec_callback(client_data, argc, argv, cols) bind(c
integer(kind=c_int), intent(in), value :: argc
type(c_ptr), intent(in) :: argv(*)
type(c_ptr), intent(in) :: cols(*)
character(len=:), allocatable :: buf
integer :: i

character(len=:), allocatable :: buf
integer :: i

exec_callback = 1 ! No more rows on error.

Expand All @@ -41,7 +42,8 @@ subroutine error_log_callback(udp, err_code, err_msg) bind(c)
type(c_ptr), intent(in), value :: udp
integer(kind=c_int), intent(in), value :: err_code
type(c_ptr), intent(in), value :: err_msg
character(len=:), allocatable :: msg

character(len=:), allocatable :: msg

call c_f_str_ptr(err_msg, msg)
print '(a)', repeat('-', 64)
Expand All @@ -60,7 +62,8 @@ subroutine update_callback(udp, type, db_name, tbl_name, rowid) bind(c)
type(c_ptr), intent(in), value :: db_name
type(c_ptr), intent(in), value :: tbl_name
integer(kind=c_int64_t), intent(in), value :: rowid
character(len=:), allocatable :: db_str, tbl_str

character(len=:), allocatable :: db_str, tbl_str

call c_f_str_ptr(db_name, db_str)
call c_f_str_ptr(tbl_name, tbl_str)
Expand Down Expand Up @@ -89,15 +92,16 @@ program test_sqlite3
use :: sqlite3
use :: callbacks
implicit none (type, external)
character(len=*), parameter :: DB_FILE = 'test.db'
character(len=*), parameter :: DB_FILE = 'test.sqlite'
character(len=*), parameter :: DB_TABLE = 'test_table'

character(len=:), allocatable :: db_name ! Database name.
character(len=:), allocatable :: errmsg ! Error message.
integer :: rc ! Return code.
type(c_ptr) :: db ! SQLite database.
type(c_ptr) :: stmt ! SQLite statement.
type(c_ptr) :: udp ! User-data pointer.

integer :: rc ! Return code.
type(c_ptr) :: db ! SQLite database.
type(c_ptr) :: stmt ! SQLite statement.
type(c_ptr) :: udp ! User-data pointer.

! Set configuration to single thread.
rc = sqlite3_config(SQLITE_CONFIG_SINGLETHREAD)
Expand Down Expand Up @@ -211,10 +215,11 @@ program test_sqlite3
contains
integer function journal_mode_wal(db) result(rc)
!! Enables WAL mode.
type(c_ptr), intent(inout) :: db
character(len=:), allocatable :: buf
integer :: err
type(c_ptr) :: stmt
type(c_ptr), intent(inout) :: db

character(len=:), allocatable :: buf
integer :: err
type(c_ptr) :: stmt

rc = -1

Expand Down Expand Up @@ -252,11 +257,12 @@ subroutine print_error(rc, func, errmsg)
end subroutine print_error

subroutine print_values(stmt, ncols)
type(c_ptr), intent(inout) :: stmt
integer, intent(in) :: ncols
integer :: col_type
integer :: i
character(len=:), allocatable :: buf
type(c_ptr), intent(inout) :: stmt
integer, intent(in) :: ncols

integer :: col_type
integer :: i
character(len=:), allocatable :: buf

do i = 0, ncols - 1
col_type = sqlite3_column_type(stmt, i)
Expand Down

0 comments on commit 0917e3c

Please sign in to comment.