Skip to content

Commit a335d31

Browse files
committed
Added macro wrappers.
1 parent b998eca commit a335d31

File tree

5 files changed

+100
-64
lines changed

5 files changed

+100
-64
lines changed

Makefile

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
.POSIX:
22
.SUFFIXES:
33

4+
CC = gcc
45
FC = gfortran
56
AR = ar
67
PREFIX = /usr/local
78

8-
DEBUG = -g -O0 -Wall -fmax-errors=1
9+
DEBUG = -g -O0 -Wall
910
RELEASE = -O2 -march=native
1011

12+
CFLAGS = $(RELEASE)
1113
FFLAGS = $(RELEASE)
1214
LDFLAGS = -I$(PREFIX)/include -L$(PREFIX)/lib
1315
LDLIBS = -lsqlite3
@@ -21,9 +23,10 @@ all: $(TARGET)
2123
test: test_sqlite3
2224

2325
$(TARGET): src/sqlite3_util.f90 src/sqlite3.f90
26+
$(CC) $(CFLAGS) -c src/sqlite3_macro.c
2427
$(FC) $(FFLAGS) -c src/sqlite3_util.f90
2528
$(FC) $(FFLAGS) -c src/sqlite3.f90
26-
$(AR) $(ARFLAGS) $(TARGET) sqlite3.o sqlite3_util.o
29+
$(AR) $(ARFLAGS) $(TARGET) sqlite3.o sqlite3_macro.o sqlite3_util.o
2730

2831
test_sqlite3: $(TARGET) test/test_sqlite3.f90
2932
$(FC) $(FFLAGS) $(LDFLAGS) -o test_sqlite3 test/test_sqlite3.f90 $(TARGET) $(LDLIBS)

README.md

Lines changed: 24 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
# fortran-sqlite3
2+
23
A work-in-progress collection of Fortran 2018 interface bindings to SQLite 3
34
(≥ 3.39.0). See [COVERAGE](COVERAGE.md) for an overview of bound functions.
45

56
## Build Instructions
7+
68
Make sure that `libsqlite3` is installed with development headers. On FreeBSD,
79
run:
810

@@ -13,60 +15,56 @@ run:
1315
Then, clone the GitHub repository:
1416

1517
```
16-
$ git clone https://github.com/interkosmos/fortran-sqlite3
18+
$ git clone --depth 1 https://github.com/interkosmos/fortran-sqlite3
1719
$ cd fortran-sqlite3/
1820
```
1921

2022
Either build the library with `fpm` or `make`. Once compiled, link your Fortran
2123
application against `libfortran-sqlite3.a` and `-lsqlite3`.
2224

2325
### fpm
26+
2427
Simply execute the Fortran Package Manager:
2528

2629
```
27-
$ fpm build --profile=release
30+
$ fpm build --profile release
2831
```
2932

3033
The output files are written to `build/`.
3134

3235
### make
33-
Execute the provided `Makefile` with `make`:
36+
37+
Execute the provided `Makefile`:
3438

3539
```
3640
$ make
3741
```
3842

39-
You may want to override the default Fortran compiler (GNU Fortran) by passing
40-
the `FC` argument, for instance:
41-
42-
```
43-
$ make FC=ifort
44-
```
43+
You may want to override the default compilers by passing the arguments `CC` (C
44+
compiler) and `FC` (Fortran compiler).
4545

4646
## Example
47+
4748
The following SQL schema will be created by the example:
4849

4950
```sql
50-
CREATE TABLE example_table (
51+
CREATE TABLE example (
5152
id INTEGER PRIMARY KEY,
5253
string TEXT,
5354
value INTEGER
5455
);
5556
```
5657

57-
The program opens a database `example.sqlite`, creates the table `example_table`,
58+
The program opens a database `example.sqlite`, creates the table `example`,
5859
inserts some values, then reads them back in, and prints them to console.
5960

60-
The module `sqlite3_util` contains C interoperability functions/interfaces to
61-
convert C char pointer to Fortran allocatable character.
62-
6361
```fortran
6462
! example.f90
6563
program example
6664
use, intrinsic :: iso_c_binding
6765
use :: sqlite3
68-
use :: sqlite3_util
6966
implicit none (type, external)
67+
7068
character(len=:), allocatable :: errmsg
7169
integer :: rc
7270
type(c_ptr) :: db
@@ -83,7 +81,7 @@ program example
8381
if (rc /= SQLITE_OK) print '("sqlite3_exec(): ", a)', errmsg
8482
8583
! Create a prepared statement.
86-
rc = sqlite3_prepare_v2(db, "INSERT INTO example_table(string, value) VALUES(?, ?)", stmt)
84+
rc = sqlite3_prepare_v2(db, "INSERT INTO example(string, value) VALUES (?, ?)", stmt)
8785
8886
! Bind the values to the statement.
8987
rc = sqlite3_bind_text(stmt, 1, 'one')
@@ -97,7 +95,7 @@ program example
9795
rc = sqlite3_finalize(stmt)
9896
9997
! Read values from database.
100-
rc = sqlite3_prepare_v2(db, "SELECT * FROM example_table", stmt)
98+
rc = sqlite3_prepare_v2(db, "SELECT * FROM example", stmt)
10199
102100
! Print rows line by line.
103101
do while (sqlite3_step(stmt) /= SQLITE_DONE)
@@ -148,6 +146,7 @@ $ ./example
148146
```
149147

150148
## fpm
149+
151150
You can add *fortran-sqlite3* as an [fpm](https://github.com/fortran-lang/fpm)
152151
dependency to your `fpm.toml`:
153152

@@ -157,13 +156,19 @@ fortran-sqlite3 = { git = "https://github.com/interkosmos/fortran-sqlite3.git" }
157156
```
158157

159158
## Compatibility
159+
160160
The Fortran interfaces to the SQLite functions `sqlite3_bind_text()` and
161-
`sqlite3_column_text()` support only 8-bit character strings. The Fortran
162-
wrapper function `sqlite3_bind_text()` selects destructor type
161+
`sqlite3_column_text()` support only 8-bit character strings.
162+
163+
The Fortran wrapper function `sqlite3_bind_text()` selects destructor type
163164
`SQLITE_TRANSIENT` if argument `destructor` is not passed, in contrast to the
164165
SQLite default `SQLITE_STATIC`. Therefore, SQLite will make a copy of the given
165166
value. Otherwise, the passed variable could go out of scope before SQLite was
166167
able to read the string completely, leading to possible data corruption.
167168

169+
The module `sqlite3_util` contains C interoperability functions/interfaces to
170+
convert C char pointer to Fortran allocatable character.
171+
168172
## Licence
173+
169174
ISC

src/sqlite3.f90

Lines changed: 33 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -358,53 +358,53 @@ function sqlite3_close_(db) bind(c, name='sqlite3_close')
358358
integer(kind=c_int) :: sqlite3_close_
359359
end function sqlite3_close_
360360

361-
! double sqlite3_column_double(sqlite3_stmt *stmt, int icol)
362-
function sqlite3_column_double(stmt, icol) bind(c, name='sqlite3_column_double')
361+
! double sqlite3_column_double(sqlite3_stmt *stmt, int idx)
362+
function sqlite3_column_double(stmt, idx) bind(c, name='sqlite3_column_double')
363363
import :: c_double, c_int, c_ptr
364364
implicit none
365365
type(c_ptr), intent(in), value :: stmt
366-
integer(kind=c_int), intent(in), value :: icol
366+
integer(kind=c_int), intent(in), value :: idx
367367
real(kind=c_double) :: sqlite3_column_double
368368
end function sqlite3_column_double
369369

370-
! int sqlite3_column_int(sqlite3_stmt *stmt, int icol)
371-
function sqlite3_column_int(stmt, icol) bind(c, name='sqlite3_column_int')
370+
! int sqlite3_column_int(sqlite3_stmt *stmt, int idx)
371+
function sqlite3_column_int(stmt, idx) bind(c, name='sqlite3_column_int')
372372
import :: c_int, c_ptr
373373
implicit none
374374
type(c_ptr), intent(in), value :: stmt
375-
integer(kind=c_int), intent(in), value :: icol
375+
integer(kind=c_int), intent(in), value :: idx
376376
integer(kind=c_int) :: sqlite3_column_int
377377
end function sqlite3_column_int
378378

379-
! sqlite3_int64 sqlite3_column_int64(sqlite3_stmt *stmt, int icol)
380-
function sqlite3_column_int64(stmt, icol) bind(c, name='sqlite3_column_int64')
379+
! sqlite3_int64 sqlite3_column_int64(sqlite3_stmt *stmt, int idx)
380+
function sqlite3_column_int64(stmt, idx) bind(c, name='sqlite3_column_int64')
381381
import :: c_int, c_int64_t, c_ptr
382382
implicit none
383383
type(c_ptr), intent(in), value :: stmt
384-
integer(kind=c_int), intent(in), value :: icol
384+
integer(kind=c_int), intent(in), value :: idx
385385
integer(kind=c_int) :: sqlite3_column_int64
386386
end function sqlite3_column_int64
387387

388-
! const unsigned char *sqlite3_column_text(sqlite3_stmt *stmt, int icol)
389-
function sqlite3_column_text_(stmt, icol) bind(c, name='sqlite3_column_text')
388+
! const unsigned char *sqlite3_column_text(sqlite3_stmt *stmt, int idx)
389+
function sqlite3_column_text_(stmt, idx) bind(c, name='sqlite3_column_text')
390390
import :: c_int, c_ptr
391391
implicit none
392392
type(c_ptr), intent(in), value :: stmt
393-
integer(kind=c_int), intent(in), value :: icol
393+
integer(kind=c_int), intent(in), value :: idx
394394
type(c_ptr) :: sqlite3_column_text_
395395
end function sqlite3_column_text_
396396

397-
! int sqlite3_column_type(sqlite3_stmt *stmt, int icol)
398-
function sqlite3_column_type(stmt, icol) bind(c, name='sqlite3_column_type')
397+
! int sqlite3_column_type(sqlite3_stmt *stmt, int idx)
398+
function sqlite3_column_type(stmt, idx) bind(c, name='sqlite3_column_type')
399399
import :: c_int, c_ptr
400400
implicit none
401401
type(c_ptr), intent(in), value :: stmt
402-
integer(kind=c_int), intent(in), value :: icol
402+
integer(kind=c_int), intent(in), value :: idx
403403
integer(kind=c_int) :: sqlite3_column_type
404404
end function sqlite3_column_type
405405

406-
! int sqlite3_config(int option, ...)
407-
function sqlite3_config_funptr_ptr_(option, funptr, ptr) bind(c, name='sqlite3_config')
406+
! int sqlite3_config_funptr_ptr_(int option, void *funptr, void *ptr)
407+
function sqlite3_config_funptr_ptr_(option, funptr, ptr) bind(c, name='sqlite3_config_funptr_ptr_')
408408
import :: c_funptr, c_int, c_ptr
409409
implicit none
410410
integer(kind=c_int), intent(in), value :: option
@@ -413,17 +413,17 @@ function sqlite3_config_funptr_ptr_(option, funptr, ptr) bind(c, name='sqlite3_c
413413
integer(kind=c_int) :: sqlite3_config_funptr_ptr_
414414
end function sqlite3_config_funptr_ptr_
415415

416-
! int sqlite3_config(int option, ...)
417-
function sqlite3_config_int_(option, arg) bind(c, name='sqlite3_config')
416+
! int sqlite3_config_int_(int option, int arg)
417+
function sqlite3_config_int_(option, arg) bind(c, name='sqlite3_config_int_')
418418
import :: c_int
419419
implicit none
420420
integer(kind=c_int), intent(in), value :: option
421421
integer(kind=c_int), intent(in), value :: arg
422422
integer(kind=c_int) :: sqlite3_config_int_
423423
end function sqlite3_config_int_
424424

425-
! int sqlite3_config(int option, ...)
426-
function sqlite3_config_null_(option) bind(c, name='sqlite3_config')
425+
! int sqlite3_config_null_(int option)
426+
function sqlite3_config_null_(option) bind(c, name='sqlite3_config_null_')
427427
import :: c_int
428428
implicit none
429429
integer(kind=c_int), intent(in), value :: option
@@ -703,12 +703,12 @@ subroutine sqlite3_free(ptr) bind(c, name='sqlite3_free')
703703
type(c_ptr), intent(in), value :: ptr
704704
end subroutine sqlite3_free
705705

706-
! void sqlite3_log(int iErrCode, const char *zFormat, ...)
707-
subroutine sqlite3_log_(ierr_code, zformat) bind(c, name='sqlite3_log')
706+
! void sqlite3_log_(int iErrCode, const char *str)
707+
subroutine sqlite3_log_(ierr_code, str) bind(c, name='sqlite3_log_')
708708
import :: c_char, c_int
709709
implicit none
710710
integer(kind=c_int), intent(in), value :: ierr_code
711-
character(kind=c_char), intent(in) :: zformat
711+
character(kind=c_char), intent(in) :: str
712712
end subroutine sqlite3_log_
713713

714714
! void sqlite3_str_append(sqlite3_str *str, const char *zIn, int N)
@@ -789,13 +789,13 @@ function sqlite3_close(db)
789789
if (sqlite3_close == SQLITE_OK) db = c_null_ptr
790790
end function sqlite3_close
791791

792-
function sqlite3_column_text(stmt, icol)
792+
function sqlite3_column_text(stmt, idx)
793793
type(c_ptr), intent(inout) :: stmt
794-
integer, intent(in) :: icol
795-
type(c_ptr) :: ptr
794+
integer, intent(in) :: idx
796795
character(len=:), allocatable :: sqlite3_column_text
796+
type(c_ptr) :: ptr
797797

798-
ptr = sqlite3_column_text_(stmt, icol)
798+
ptr = sqlite3_column_text_(stmt, idx)
799799
if (.not. c_associated(ptr)) return
800800
call c_f_str_ptr(ptr, sqlite3_column_text)
801801
end function sqlite3_column_text
@@ -831,7 +831,7 @@ function sqlite3_db_name(db, n)
831831
type(c_ptr) :: ptr
832832

833833
ptr = sqlite3_db_name_(db, n)
834-
if (c_associated(ptr)) call c_f_str_ptr(ptr, sqlite3_db_name)
834+
call c_f_str_ptr(ptr, sqlite3_db_name)
835835
end function sqlite3_db_name
836836

837837
function sqlite3_errmsg(db)
@@ -840,7 +840,7 @@ function sqlite3_errmsg(db)
840840
type(c_ptr) :: ptr
841841

842842
ptr = sqlite3_errmsg_(db)
843-
if (c_associated(ptr)) call c_f_str_ptr(ptr, sqlite3_errmsg)
843+
call c_f_str_ptr(ptr, sqlite3_errmsg)
844844
end function sqlite3_errmsg
845845

846846
function sqlite3_exec(db, sql, callback, client_data, errmsg)
@@ -853,7 +853,6 @@ function sqlite3_exec(db, sql, callback, client_data, errmsg)
853853
type(c_ptr) :: ptr
854854

855855
sqlite3_exec = sqlite3_exec_(db, sql // c_null_char, callback, client_data, ptr)
856-
if (.not. c_associated(ptr)) return
857856
if (present(errmsg)) call c_f_str_ptr(ptr, errmsg)
858857
end function sqlite3_exec
859858

@@ -870,7 +869,6 @@ function sqlite3_libversion()
870869
character(len=:), allocatable :: sqlite3_libversion
871870

872871
ptr = sqlite3_libversion_()
873-
if (.not. c_associated(ptr)) return
874872
call c_f_str_ptr(ptr, sqlite3_libversion)
875873
end function sqlite3_libversion
876874

@@ -920,7 +918,6 @@ function sqlite3_sourceid()
920918
character(len=:), allocatable :: sqlite3_sourceid
921919

922920
ptr = sqlite3_sourceid_()
923-
if (.not. c_associated(ptr)) return
924921
call c_f_str_ptr(ptr, sqlite3_sourceid)
925922
end function sqlite3_sourceid
926923

@@ -930,14 +927,13 @@ function sqlite3_str_value(str)
930927
character(len=:), allocatable :: sqlite3_str_value
931928

932929
ptr = sqlite3_str_value_(str)
933-
if (.not. c_associated(ptr)) return
934930
call c_f_str_ptr(ptr, sqlite3_str_value)
935931
end function sqlite3_str_value
936932

937-
subroutine sqlite3_log(ierr_code, zformat)
933+
subroutine sqlite3_log(ierr_code, str)
938934
integer, intent(in) :: ierr_code
939-
character(len=*), intent(in) :: zformat
935+
character(len=*), intent(in) :: str
940936

941-
call sqlite3_log_(ierr_code, zformat // c_null_char)
937+
call sqlite3_log_(ierr_code, str // c_null_char)
942938
end subroutine sqlite3_log
943939
end module sqlite3

src/sqlite3_macro.c

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/* sqlite3_macro.c */
2+
#include <sqlite3.h>
3+
4+
#ifdef __cplusplus
5+
extern "C" {
6+
#endif
7+
8+
int sqlite3_config_funptr_ptr_(int, void *, void *);
9+
int sqlite3_config_int_(int, int);
10+
int sqlite3_config_null_(int);
11+
void sqlite3_log_(int, const char *);
12+
13+
int sqlite3_config_funptr_ptr_(int option, void *funptr, void *ptr)
14+
{
15+
return sqlite3_config(option, funptr, ptr);
16+
}
17+
18+
int sqlite3_config_int_(int option, int arg)
19+
{
20+
return sqlite3_config(option, arg);
21+
}
22+
23+
int sqlite3_config_null_(int option)
24+
{
25+
return sqlite3_config(option);
26+
}
27+
28+
void sqlite3_log_(int iErrCode, const char *str)
29+
{
30+
sqlite3_log(iErrCode, "%s", str);
31+
}
32+
33+
#ifdef __cplusplus
34+
}
35+
#endif

0 commit comments

Comments
 (0)