[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[nongnu] elpa/sqlite3 a51467b031 04/62: added test for Emacs 25.1
From: |
ELPA Syncer |
Subject: |
[nongnu] elpa/sqlite3 a51467b031 04/62: added test for Emacs 25.1 |
Date: |
Tue, 14 Mar 2023 11:01:44 -0400 (EDT) |
branch: elpa/sqlite3
commit a51467b0318359bd56ad925fa327b959f912acee
Author: Y. N. Lo <gordonynlo@yahoo.com>
Commit: Y. N. Lo <gordonynlo@yahoo.com>
added test for Emacs 25.1
---
.gitignore | 8 +
Makefile | 20 ++-
README.md => README-in.md | 159 ++++++++++--------
README.md | 198 ++++++++++++++---------
regression.el | 17 +-
sqlite3-napi.el => sqlite3-api-constants.el | 16 +-
sqlite3-napi-module.c => sqlite3-api-module.c | 223 ++++++++++++--------------
sqlite3-api.el | 20 +++
sqlite3-napi-module.so | Bin 31944 -> 0 bytes
tools/gen-consts.py | 3 +-
tools/run.sh | 26 ++-
11 files changed, 418 insertions(+), 272 deletions(-)
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000000..b800ee7c50
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,8 @@
+*.o
+*.so
+**/.DS_Store
+sqlite3-napi-module-with-create-function.c
+README-in.md
+xxx.el
+tools/def.c
+tools/def
\ No newline at end of file
diff --git a/Makefile b/Makefile
index 6583693de4..d3c714837f 100644
--- a/Makefile
+++ b/Makefile
@@ -1,11 +1,16 @@
CC = gcc
CFLAGS = -g3 -Wall -std=c99
-EMACS=$(HOME)/test-emacs/bin/emacs
+EMACS252=$(HOME)/test-emacs/bin/emacs
+EMACS251=$(HOME)/test-emacs-251/bin/emacs
+MODULE=sqlite3-api-module.so
-all: sqlite3-napi-module.so
+all: $(MODULE) misc
clean:
- rm -f *.so
+ rm -f *.so *.o
+
+misc:
+ (cd tools; ./run.sh)
%.so: %.o
$(CC) -shared -o $@ $< -lsqlite3
@@ -13,5 +18,10 @@ clean:
%.o: %.c
$(CC) $(CFLAGS) -fPIC -c $<
-test:
- $(EMACS) -batch -Q -l regression.el
+# Emacs 25.2
+test: $(MODULE)
+ $(EMACS252) -batch -Q -l regression.el
+
+# Emacs 25.1
+test251: $(MODULE)
+ $(EMACS251) -batch -Q -l regression.el
diff --git a/README.md b/README-in.md
similarity index 50%
copy from README.md
copy to README-in.md
index 61458c10be..f66f5a1de4 100644
--- a/README.md
+++ b/README-in.md
@@ -1,63 +1,79 @@
-# SQLite3 Native API for Emacs 25+
-sqlite-napi is a dynamic module for GNU Emacs that provides
-direct access to the SQLite3 C API.
-## Usage
-~~~el
-(require 'sqlite3-napi)
-
-(let ((dbh)
- (stmt))
- (unwind-protect
- (progn
- (setq dbh (sqlite3-open "/path/to/db"
- (logior sqlite-open-readwrite
- sqlite-open-create)))
- (setq stmt (sqlite3-prepare dbh "select * from some_table"))
- (while (= sqlite-row (sqlite3-step stmt))
- (cl-loop for i from 0 to (1- (sqlite3-column-count stmt)) do
- (message "Column #%d: %s => %s" i
- (sqlite3-column-name stmt i)
- (sqlite3-column-text stmt i)))))
- ;; Clean up
- (sqlite3-finalize stmt)
- (sqlite3-close dbh)))
-~~~
-This is alpha software and might crash your Emacs. Save your work before
-trying it out.
+# SQLite3 API for Emacs 25+
+`sqlite3-api` is a dynamic module for GNU Emacs 25+ that provides
+direct access to the core SQLite3 C API from Emacs Lisp.
+~~~el
+(require 'sqlite3-api)
+
+(setq dbh (sqlite3-open "person.sqlite3" sqlite-open-readwrite
sqlite-open-create))
+(sqlite3-exec dbh "create table temp (name text, age integer)")
+(sqlite3-exec dbh "begin") ;; begin transaction
+(setq stmt (sqlite3-prepare dbh "insert into temp values (?,?)"))
+(cl-loop for i from 1 to 10 do
+ (sqlite3-bind-multi stmt (format "name%d" i) i)
+ ;; execute the SQL
+ (sqlite3-step stmt)
+ ;; call reset if you want to bind the SQL to a new set of variables
+ (sqlite3-reset stmt) )
+(sqlite3-exec dbh "commit")
+(sqlite3-finalize stmt)
+
+(setq stmt (sqlite3-prepare dbh "select * from temp"))
+(while (= sqlite-row (sqlite3-step stmt))
+ (cl-destructuring-bind (name age) (sqlite3-fetch stmt)
+ (message "name: %s, age: %d" name age)))
+(sqlite3-finalize stmt)
+(sqlite3-close dbh)
+~~~
+While this module provides only 14 functions (vs 200+ in the C API), it should
satisfy most
+users' needs.
+This is an alpha release and it might crash your Emacs. Save your work before
you try it out!
+
+<<TOC>>
## Requirements
-- Emacs 25.1 or above, compiled with module support (`--with-modules`)
+- Emacs 25.1 or above, compiled with module support (`./configure
--with-modules`)
- sqlite3 library and header file
-- C compiler
+- A C99 compiler
+
+It's been tested on macOS Sierra) and CentOS 7.
## Installation
~~~sh
-$ git co https://github.com/pekingduck/sqlite3-napi
-$ cd sqlite3-napi
+$ git co https://github.com/pekingduck/emacs-sqlite3-api
+$ cd emacs-sqlite3-api
$ make
-$ cp sqlite3-napi.el sqlite3-napi-module.so /your/elisp/load-path/
+$ cp sqlite3-api.el sqlite3-api-constants.el sqlite3-api-module.so
/your/elisp/load-path/
~~~
-Once the code stabilizes I will make it available on melpa.
-## Constants
-These constants (defined in sqlite3.h) are things such as numeric result codes
from various interfaces (ex: `SQLITE_OK`) or flags passed into functions to
control behavior (ex: `SQLITE_OPEN_READONLY`).
+A copy of `emacs-module.h` is included in this repo so Emacs source tree
+is not needed to build the module.
+
+## API
+An application will typically use sqlite3_open() to create a single database
connection during initialization.
+
+To run an SQL statement, the application follows these steps:
+
+1. Create a prepared statement using sqlite3_prepare().
+1. Evaluate the prepared statement by calling sqlite3_step() one or more times.
+1. For queries, extract results by calling sqlite3_column() in between two
calls to sqlite3_step().
+1. Destroy the prepared statement using sqlite3_finalize().
+1. Close the database using sqlite3_close().
+
+[SQlite3 constants](https://www.sqlite.org/rescode.html), defined in
sqlite3.h, are things such as numeric result codes from various interfaces (ex:
`SQLITE_OK`) or flags passed into functions to control behavior (ex:
`SQLITE_OPEN_READONLY`).
In elisp they are in lowercase and words are separated by "-" instead of
"_". For example, `SQLITE_OK` would be `sqlite-ok`.
-Refer to the [offical site](https://www.sqlite.org/rescode.html)
-for a full list of constants.
-## Functions
-Here I will briefly describe functions available in this module.
+[www.sqlite.org](https://www.sqlite.org) is always a good source of
information, especially
+[An Introduction to the SQLite C/C++
Interface](https://www.sqlite.org/cintro.html) and [C/C++ API
Reference](https://www.sqlite.org/c3ref/intro.html).
-Consult the [offical API
documentation](https://www.sqlite.org/c3ref/funclist.html) for details.
### sqlite3-open
~~~el
-(sqlite3-open "/path/to/data-file" flags)
+(sqlite3-open "/path/to/data-file" flag1 flag2 ...)
~~~
Open the database file and return a database handle.
-In case of error, the function raises `'db-error` along with a
-corresponding error message.
+This function calls
[`sqlite3_open_v2()`](https://www.sqlite.org/c3ref/open.html) internally and
raises `'db-error` in case of error.
+*flag1*, *flag2*.... will be ORed together.
### sqlite3-close
~~~el
(sqlite3-close database-handle)
@@ -68,6 +84,8 @@ Close the database file.
(sqlite3-prepare database-handle sql-statement)
~~~
Compile the supplied SQL statement and return a statement handle.
+
+This function calls
[`sqlite3_prepare_v2()`](https://www.sqlite.org/c3ref/prepare.html) internally
and raises 'sql-error (such as invalid SQL statement).
### sqlite3-finalize
~~~el
(sqlite3-finalize statement-handle)
@@ -117,11 +135,11 @@ The Swiss Army Knife of the API, you can execute multiple
SQL statements
The callback function, if supplied, is invoked for *each row* and should
accept 3
parameters:
1. the first parameter is the number of columns in the current row;
- 2. the second parameter is the actual data (as a list strings);
+ 2. the second parameter is the actual data (as a list strings or nil in case
of NULL);
3. the third one is a list of column names.
To signal an error condition inside the callback, return `nil`.
-`sqlite3_exec()` will stop the execution and return `sqlite-abort`.
+`sqlite3_exec()` will stop the execution and raise 'db-error.
An example of a callback:
~~~el
@@ -137,9 +155,9 @@ An example of a callback:
More examples:
~~~el
;; Update/delete/insert
-(sqlite3-exec dbh "delete from table")
+(sqlite3-exec dbh "delete from table") ;; delete returns no rows
-;; Retrieve the metadata of all columns of a table
+;; Retrieve the metadata of columns in a table
(sqlite3-exec dbh "pragma table_info(table)" #'print-row)
;; Transaction support
@@ -164,19 +182,22 @@ Please note that column number starts from 1, not 0!
~~~
The above functions returns the number of SQL parameters of a prepared
statement.
+### sqlite3-bind-multi
~~~el
(sqlite3-bind-multi statement-handle &rest params)
~~~
-`sqlite3-bind-multi` is not part of the official API but is provided for
+`sqlite3-bind-multi` binds multiple parameters to a prepared SQL
+statement. It is not part of the official API but is provided for
convenience.
Example:
~~~el
-(sqlite3-bind-multi stmt 1 "a" 1.555 nil) ;; nil for NULL
+(sqlite3-bind-multi stmt 1234 "a" 1.555 nil) ;; nil for NULL
~~~
### sqlite3-column-*
-These column functions retrieve data from the current row of a
-result set.
+These column functions are used to retrieve the current row
+of the result set.
+
~~~el
(sqlite3-column-count statement-handle)
~~~
@@ -198,30 +219,36 @@ The above functions retrieve data of the specified column.
Note: You can call `sqlite3-column-xxx` on a column even
if `sqlite3-column-type` returns `sqlite-yyy`: the SQLite3 engine will
perform the necessary type conversion.
+
+Example:
~~~el
-(sqlite3-fetch statement-handle)
+(setq stmt (sqlite3-prepare dbh "select * from temp"))
+(while (= sqlite-row (sqlite3-step stmt))
+ (let ((name (sqlite3-column-text stmt 0))
+ (age (sqlite3-column-int64 stmt 1)))
+ (message "name: %s, age: %d" name age)))
+~~~
+### sqlite3-fetch
+~~~el
+(sqlite3-fetch statement-handle) ;; returns a list such as (123 56 "Peter
Smith" nil)
~~~
`sqlite3-fetch` is not part of the official API but provided for
-convenience. It returns the current row as a list of values.
+convenience. It retrieves the current row as a
+list without having to deal with sqlite3-column-* explicitly.
+
## A Note on Garbage Collection
Since Emacs's garbage collection is non-deterministic, it would be
a good idea
to manually free database/statement handles once they are not needed.
-~~~el
-(unwind-protect
- (progn
- (setq dbh (sqlite3-open "..."))
- (setq stmt (sqlite3-prepare dbh "select ..."))
- (.....))
- (sqlite3-finalize stmt)
- (sqlite3-close dbh))
-~~~
-## Missing features
-- BLOB support
-- Custom functions written in elisp
-
## Known Problems
- SQLite3 supports 64 bit integers but Emacs integers are only 61 bits.
For integers > 61 bits you can retrieve them as text as a workaround.
-- TEXT fields with embedded NULLs are not supported.
+- BLOB/TEXT columns with embedded NULLs are not supported.
+
+## License
+The code is licensed under the [GNU GPL
v3](https://www.gnu.org/licenses/gpl-3.0.html).
+
+## Useful Links for Writing Dynamic Modules
+- https://phst.github.io/emacs-modules
+- http://nullprogram.com/blog/2016/11/05/
diff --git a/README.md b/README.md
index 61458c10be..98dc45b3c8 100644
--- a/README.md
+++ b/README.md
@@ -1,79 +1,120 @@
# SQLite3 Native API for Emacs 25+
-sqlite-napi is a dynamic module for GNU Emacs that provides
-direct access to the SQLite3 C API.
-## Usage
+`sqlite-napi` is a dynamic module for GNU Emacs that provides
+direct access to the core SQLite3 C API.
~~~el
(require 'sqlite3-napi)
-(let ((dbh)
- (stmt))
- (unwind-protect
- (progn
- (setq dbh (sqlite3-open "/path/to/db"
- (logior sqlite-open-readwrite
- sqlite-open-create)))
- (setq stmt (sqlite3-prepare dbh "select * from some_table"))
- (while (= sqlite-row (sqlite3-step stmt))
- (cl-loop for i from 0 to (1- (sqlite3-column-count stmt)) do
- (message "Column #%d: %s => %s" i
- (sqlite3-column-name stmt i)
- (sqlite3-column-text stmt i)))))
- ;; Clean up
- (sqlite3-finalize stmt)
- (sqlite3-close dbh)))
+(setq dbh (sqlite3-open "person.sqlite3" sqlite-open-readwrite
sqlite-open-create))
+(sqlite3-exec dbh "create table temp (name text, age integer)")
+(sqlite3-exec dbh "begin") ;; begin transaction
+(setq stmt (sqlite3-prepare dbh "insert into temp values (?,?)"))
+(cl-loop for i from 1 to 10 do
+ (sqlite3-bind-multi stmt (format "name%d" i) i)
+ ;; execute the SQL
+ (sqlite3-step stmt)
+ ;; call reset if you want to bind the SQL to a new set of variables
+ (sqlite3-reset stmt) )
+(sqlite3-exec dbh "commit")
+(sqlite3-finalize stmt)
+
+(setq stmt (sqlite3-prepare dbh "select * from temp"))
+(while (= sqlite-row (sqlite3-step stmt))
+ (cl-destructuring-bind (name age) (sqlite3-fetch stmt)
+ (message "name: %s, age: %d" name age)))
+(sqlite3-finalize stmt)
+(sqlite3-close dbh)
~~~
+While this module provides only 14 functions (vs 200+ in the C API), it should
satisfy most
+users' needs.
+
This is alpha software and might crash your Emacs. Save your work before
trying it out.
-## Requirements
+## Table of Contents
+* [Requirements](#1)
+* [Installation](#2)
+* [API](#3)
+ * [sqlite3-open](#3-1)
+ * [sqlite3-close](#3-2)
+ * [sqlite3-prepare](#3-3)
+ * [sqlite3-finalize](#3-4)
+ * [sqlite3-step](#3-5)
+ * [sqlite3-changes](#3-6)
+ * [sqlite3-reset](#3-7)
+ * [sqlite3-last-insert-rowid](#3-8)
+ * [sqlite3-get-autocommit](#3-9)
+ * [sqlite3-exec](#3-10)
+ * [sqlite3-bind-*](#3-11)
+ * [sqlite3-bind-multi](#3-12)
+ * [sqlite3-column-*](#3-13)
+ * [sqlite3-fetch](#3-14)
+* [A Note on Garbage Collection](#4)
+* [Known Problems](#5)
+* [License](#6)
+* [Useful Links for Writing Dynamic Modules](#7)
+
+## <a name="1"/> Requirements
- Emacs 25.1 or above, compiled with module support (`--with-modules`)
- sqlite3 library and header file
-- C compiler
-## Installation
+- A C compiler
+
+It's been tested on macOS and Linux (CentOS).
+## <a name="2"/> Installation
~~~sh
-$ git co https://github.com/pekingduck/sqlite3-napi
-$ cd sqlite3-napi
+$ git co https://github.com/pekingduck/emacs-sqlite3-napi
+$ cd emacs-sqlite3-napi
$ make
-$ cp sqlite3-napi.el sqlite3-napi-module.so /your/elisp/load-path/
+$ cp sqlite3-napi.el sqlite3-napi-constants.el sqlite3-napi-module.so
/your/elisp/load-path/
~~~
-Once the code stabilizes I will make it available on melpa.
-## Constants
-These constants (defined in sqlite3.h) are things such as numeric result codes
from various interfaces (ex: `SQLITE_OK`) or flags passed into functions to
control behavior (ex: `SQLITE_OPEN_READONLY`).
+A copy of `emacs-module.h` is included in this repo so Emacs source tree
+is not needed to build the module.
+
+## <A NAME="3"/> API
+An application will typically use sqlite3_open() to create a single database
connection during initialization.
+
+To run an SQL statement, the application follows these steps:
+
+1. Create a prepared statement using sqlite3_prepare().
+1. Evaluate the prepared statement by calling sqlite3_step() one or more times.
+1. For queries, extract results by calling sqlite3_column() in between two
calls to sqlite3_step().
+1. Destroy the prepared statement using sqlite3_finalize().
+1. Close the database using sqlite3_close().
+
+[SQlite3 constants](https://www.sqlite.org/rescode.html), defined in
sqlite3.h, are things such as numeric result codes from various interfaces (ex:
`SQLITE_OK`) or flags passed into functions to control behavior (ex:
`SQLITE_OPEN_READONLY`).
In elisp they are in lowercase and words are separated by "-" instead of
"_". For example, `SQLITE_OK` would be `sqlite-ok`.
-Refer to the [offical site](https://www.sqlite.org/rescode.html)
-for a full list of constants.
-## Functions
-Here I will briefly describe functions available in this module.
+[www.sqlite.org](https://www.sqlite.org) is always a good source of
information, especially
+[An Introduction to the SQLite C/C++
Interface](https://www.sqlite.org/cintro.html) and [C/C++ API
Reference](https://www.sqlite.org/c3ref/intro.html).
-Consult the [offical API
documentation](https://www.sqlite.org/c3ref/funclist.html) for details.
-### sqlite3-open
+### <a name="3-1"/> sqlite3-open
~~~el
-(sqlite3-open "/path/to/data-file" flags)
+(sqlite3-open "/path/to/data-file" flag1 flag2 ...)
~~~
Open the database file and return a database handle.
-In case of error, the function raises `'db-error` along with a
-corresponding error message.
+This function calls
[`sqlite3_open_v2()`](https://www.sqlite.org/c3ref/open.html) internally and
raises `'db-error` in case of error.
-### sqlite3-close
+*flag1*, *flag2*.... will be ORed together.
+### <a name="3-2"/> sqlite3-close
~~~el
(sqlite3-close database-handle)
~~~
Close the database file.
-### sqlite3-prepare
+### <a name="3-3"/> sqlite3-prepare
~~~el
(sqlite3-prepare database-handle sql-statement)
~~~
Compile the supplied SQL statement and return a statement handle.
-### sqlite3-finalize
+
+This function calls
[`sqlite3_prepare_v2()`](https://www.sqlite.org/c3ref/prepare.html) internally
and raises 'sql-error (such as invalid SQL statement).
+### <a name="3-4"/> sqlite3-finalize
~~~el
(sqlite3-finalize statement-handle)
~~~
Destroy a prepared statement.
-### sqlite3-step
+### <a name="3-5"/> sqlite3-step
~~~el
(sqlite3-step statement-handle)
~~~
@@ -83,31 +124,31 @@ Execute a prepared SQL statement. Some of the return codes
are:
`sqlite-row` - if the SQL statement being executed returns any data, then
`sqlite-row` is returned each time a new row of data is ready for processing by
the caller.
-### sqlite3-changes
+### <a name="3-6"/> sqlite3-changes
~~~el
(sqlite3-changes database-handle)
~~~
Return the number of rows modified (for update/delete/insert statements)
-### sqlite3-reset
+### <a name="3-7"/> sqlite3-reset
~~~el
(sqlite3-reset statement-handle)
~~~
Reset a prepared statement. Call this function if you want to re-bind
the statement to new variables.
-### sqlite3-last-insert-rowid
+### <a name="3-8"/> sqlite3-last-insert-rowid
~~~el
(sqlite3-last-insert-rowid database-handle)
~~~
Retrieve the last inserted rowid (64 bit).
Notes: Beware that Emacs only supports integers up to 61 bits.
-### sqlite3-get-autocommit
+### <a name="3-9"/> sqlite3-get-autocommit
~~~el
(sqlite3-get-autocommit database-handle)
~~~
Return 1 / 0 if auto-commit mode is ON / OFF.
-### sqlite3-exec
+### <a name="3-10"/> sqlite3-exec
~~~el
(sqlite3-exec database-handle sql-statements &optional callback)
~~~
@@ -117,11 +158,11 @@ The Swiss Army Knife of the API, you can execute multiple
SQL statements
The callback function, if supplied, is invoked for *each row* and should
accept 3
parameters:
1. the first parameter is the number of columns in the current row;
- 2. the second parameter is the actual data (as a list strings);
+ 2. the second parameter is the actual data (as a list strings or nil in case
of NULL);
3. the third one is a list of column names.
To signal an error condition inside the callback, return `nil`.
-`sqlite3_exec()` will stop the execution and return `sqlite-abort`.
+`sqlite3_exec()` will stop the execution and raise 'db-error.
An example of a callback:
~~~el
@@ -137,9 +178,9 @@ An example of a callback:
More examples:
~~~el
;; Update/delete/insert
-(sqlite3-exec dbh "delete from table")
+(sqlite3-exec dbh "delete from table") ;; delete returns no rows
-;; Retrieve the metadata of all columns of a table
+;; Retrieve the metadata of columns in a table
(sqlite3-exec dbh "pragma table_info(table)" #'print-row)
;; Transaction support
@@ -149,7 +190,7 @@ More examples:
...
(sqlite3-exec dbh "rollback")
~~~
-### sqlite3-bind-*
+### <a name="3-11"/> sqlite3-bind-*
~~~el
(sqlite3-bind-text statement-handle column-no value)
(sqlite3-bind-int64 statement-handle column-no value)
@@ -164,19 +205,22 @@ Please note that column number starts from 1, not 0!
~~~
The above functions returns the number of SQL parameters of a prepared
statement.
+### <a name="3-12"/> sqlite3-bind-multi
~~~el
(sqlite3-bind-multi statement-handle &rest params)
~~~
-`sqlite3-bind-multi` is not part of the official API but is provided for
+`sqlite3-bind-multi` binds multiple parameters to a prepared SQL
+statement. It is not part of the official API but is provided for
convenience.
Example:
~~~el
-(sqlite3-bind-multi stmt 1 "a" 1.555 nil) ;; nil for NULL
+(sqlite3-bind-multi stmt 1234 "a" 1.555 nil) ;; nil for NULL
~~~
-### sqlite3-column-*
-These column functions retrieve data from the current row of a
-result set.
+### <a name="3-13"/> sqlite3-column-*
+These column functions are used to retrieve the current row
+of the result set.
+
~~~el
(sqlite3-column-count statement-handle)
~~~
@@ -198,30 +242,36 @@ The above functions retrieve data of the specified column.
Note: You can call `sqlite3-column-xxx` on a column even
if `sqlite3-column-type` returns `sqlite-yyy`: the SQLite3 engine will
perform the necessary type conversion.
+
+Example:
~~~el
-(sqlite3-fetch statement-handle)
+(setq stmt (sqlite3-prepare dbh "select * from temp"))
+(while (= sqlite-row (sqlite3-step stmt))
+ (let ((name (sqlite3-column-text stmt 0))
+ (age (sqlite3-column-int64 stmt 1)))
+ (message "name: %s, age: %d" name age)))
+~~~
+### <a name="3-14"/> sqlite3-fetch
+~~~el
+(sqlite3-fetch statement-handle) ;; returns a list such as (123 56 "Peter
Smith" nil)
~~~
`sqlite3-fetch` is not part of the official API but provided for
-convenience. It returns the current row as a list of values.
-## A Note on Garbage Collection
+convenience. It retrieves the current row as a
+list without having to deal with sqlite3-column-* explicitly.
+
+## <a name="4"/> A Note on Garbage Collection
Since Emacs's garbage collection is non-deterministic, it would be
a good idea
to manually free database/statement handles once they are not needed.
-~~~el
-(unwind-protect
- (progn
- (setq dbh (sqlite3-open "..."))
- (setq stmt (sqlite3-prepare dbh "select ..."))
- (.....))
- (sqlite3-finalize stmt)
- (sqlite3-close dbh))
-~~~
-## Missing features
-- BLOB support
-- Custom functions written in elisp
-
-## Known Problems
+## <a name="5"/> Known Problems
- SQLite3 supports 64 bit integers but Emacs integers are only 61 bits.
For integers > 61 bits you can retrieve them as text as a workaround.
-- TEXT fields with embedded NULLs are not supported.
+- BLOB/ TEXT fields with embedded NULLs are not supported.
+
+## <a name="6"/> License
+The code is licensed under the [GNU GPL
v3](https://www.gnu.org/licenses/gpl-3.0.html).
+
+## <a name="7"/> Useful Links for Writing Dynamic Modules
+- https://phst.github.io/emacs-modules
+- http://nullprogram.com/blog/2016/11/05/
diff --git a/regression.el b/regression.el
index e43b1b973e..2721ceea9d 100644
--- a/regression.el
+++ b/regression.el
@@ -1,8 +1,22 @@
;; -*- lexical-binding: t -*-
+;; This program is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <http://www.gnu.org/licenses/>.
+;;
+
(setq lexical-binding t)
(add-to-list 'load-path ".")
-(require 'sqlite3-napi)
+(require 'sqlite3-api)
(require 'cl)
@@ -17,7 +31,6 @@
(unwind-protect
(progn
(should (= sqlite-ok (sqlite3-exec dbh "create table temp ( id
integer primary key autoincrement )")))
- (should-not (= sqlite-ok (sqlite3-exec dbh "create table temp ( id
integer primary key autoincrement )")))
(should (= sqlite-ok (sqlite3-exec dbh "insert into temp values
(NULL)")))
(setq stmt (sqlite3-prepare dbh "select count(*) from temp"))
(should (= sqlite-row (sqlite3-step stmt)))
diff --git a/sqlite3-napi.el b/sqlite3-api-constants.el
similarity index 95%
rename from sqlite3-napi.el
rename to sqlite3-api-constants.el
index b41139a767..10f9bb931b 100644
--- a/sqlite3-napi.el
+++ b/sqlite3-api-constants.el
@@ -1,4 +1,16 @@
-(require 'sqlite3-napi-module)
+;; This program is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <http://www.gnu.org/licenses/>.
+;;
(defconst sqlite-version "3.16.0")
(defconst sqlite-version-number 3016000)
(defconst sqlite-source-id "2016-11-04 19:09:39
0e5ffd9123d6d2d2b8f3701e8a73cc98a3a7ff5f")
@@ -365,4 +377,4 @@
(defconst sqlite-scanstat-name 3)
(defconst sqlite-scanstat-explain 4)
(defconst sqlite-scanstat-selectid 5)
-(provide 'sqlite3-napi)
\ No newline at end of file
+(provide 'sqlite3-api-constants)
\ No newline at end of file
diff --git a/sqlite3-napi-module.c b/sqlite3-api-module.c
similarity index 80%
rename from sqlite3-napi-module.c
rename to sqlite3-api-module.c
index 91f6b113d7..546e5965b1 100644
--- a/sqlite3-napi-module.c
+++ b/sqlite3-api-module.c
@@ -1,3 +1,18 @@
+/*
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
@@ -31,7 +46,7 @@ static int SQLITE3_LOG_LEVEL_DEBUG = 0;
static int SQLITE3_LOG_LEVEL_INFO = 1;
static int SQLITE3_LOG_LEVEL_WARN = 2;
static int SQLITE3_LOG_LEVEL_ERROR = 3;
-static int sqlite3_napi_log_level;
+static int sqlite3_api_log_level;
int symbol_value_as_int(emacs_env *env,
emacs_value sym,
@@ -42,9 +57,17 @@ int symbol_value_as_int(emacs_env *env,
return defaul;
}
+/* Equivalent to (list a b c) in elisp
+ n is the number of arguments
+ elts, an array of emacs_valuem, are elements of the list
+ */
+emacs_value make_list(emacs_env *env, int n, emacs_value *elts) {
+ return env->funcall(env, SYM(env, "list"), n, elts);
+}
+
#if 0
static void message(emacs_env *env, int log_level, const char *fmt, ...) {
- if (log_level < sqlite3_napi_log_level)
+ if (log_level < sqlite3_api_log_level)
return;
va_list args;
@@ -71,10 +94,11 @@ static void message(emacs_env *env, int log_level, const
char *fmt, ...) {
}
#endif
+/* Logging function */
static void message(emacs_env *env, int log_level, const char *fmt, ...) {
(void)env;
- if (log_level < sqlite3_napi_log_level)
+ if (log_level < sqlite3_api_log_level)
return;
static const char *LOG_LEVEL_DESC[] = {
@@ -93,10 +117,11 @@ static void message(emacs_env *env, int log_level, const
char *fmt, ...) {
fprintf(stderr, "\n");
}
+/* Equivalent to (signal error data) in elisp */
void signal_error(emacs_env *env, const char *symbol, const char *msg) {
emacs_value signal = SYM(env, symbol);
emacs_value errmsg = env->make_string(env, msg, strlen(msg));
- env->non_local_exit_signal(env, signal, errmsg);
+ env->non_local_exit_signal(env, signal, make_list(env, 1, &errmsg));
}
/* Extract and copy string contents from function parameters */
@@ -114,7 +139,7 @@ int extract_string_arg(emacs_env *env, emacs_value arg,
char **str) {
return 0;
}
-/* Create a LISP function callable from within Emacs */
+/* Bind the supplied function to a symbol by calling (fset ....) */
void bind_func(emacs_env *env, const char *name, ptrdiff_t min,
ptrdiff_t max,
emacs_value (*function) (emacs_env *env,
@@ -130,7 +155,8 @@ void bind_func(emacs_env *env, const char *name, ptrdiff_t
min,
env->funcall(env, fset, 2, args);
}
-static void sqlite3_db_gc(void *ptr) {
+/* finalizer for database handle (sqlite3 *) */
+static void sqlite3_dbh_gc(void *ptr) {
INFO(0, "%s: entered", __func__);
if (ptr) {
@@ -139,6 +165,7 @@ static void sqlite3_db_gc(void *ptr) {
}
}
+/* finalizer for statement handle (sqlite3_stmt *) */
static void sqlite3_stmt_gc(void *ptr) {
INFO(0, "%s: entered", __func__);
@@ -151,7 +178,7 @@ static void sqlite3_stmt_gc(void *ptr) {
/* bind_*() functions:
Bind SQL parameters after the SQL is prepared (compiled).
*/
-static emacs_value sqlite3_napi_bind_null(
+static emacs_value sqlite3_api_bind_null(
emacs_env *env,
ptrdiff_t n,
emacs_value *args,
@@ -159,10 +186,6 @@ static emacs_value sqlite3_napi_bind_null(
(void)ptr;
(void)n;
- // TODO:
- // should signal an error instead of return SYM(env, "nil")??
- // Exrtract sqlite3 db struct
- /* User passed a nil stmt */
if (!env->is_not_nil(env, args[0])) {
WARN(env, "%s: statement handle is nil", __func__);
return SYM(env, "nil");
@@ -170,20 +193,15 @@ static emacs_value sqlite3_napi_bind_null(
sqlite3_stmt *stmt = (sqlite3_stmt *)env->get_user_ptr(env, args[0]);
NON_LOCAL_EXIT_CHECK(env);
- /* if (env->non_local_exit_check(env) != emacs_funcall_exit_return) */
- /* return SYM(env, "nil"); */
// The column no.
int col = env->extract_integer(env, args[1]);
NON_LOCAL_EXIT_CHECK(env);
- /* if (env->non_local_exit_check(env) != emacs_funcall_exit_return) { */
- /* return SYM(env, "nil"); */
- /* } */
return env->make_integer(env, sqlite3_bind_null(stmt, col));
}
-static emacs_value sqlite3_napi_bind_double(
+static emacs_value sqlite3_api_bind_double(
emacs_env *env,
ptrdiff_t n,
emacs_value *args,
@@ -191,9 +209,6 @@ static emacs_value sqlite3_napi_bind_double(
(void)ptr;
(void)n;
- // TODO:
- // should signal an error instead of return SYM(env, "nil")??
- // Exrtract sqlite3 db struct
if (!env->is_not_nil(env, args[0])) {
WARN(env, "%s: statement handle is nil", __func__);
return SYM(env, "nil");
@@ -212,7 +227,7 @@ static emacs_value sqlite3_napi_bind_double(
return env->make_integer(env, sqlite3_bind_double(stmt, col, val));
}
-static emacs_value sqlite3_napi_bind_parameter_count(
+static emacs_value sqlite3_api_bind_parameter_count(
emacs_env *env,
ptrdiff_t n,
emacs_value *args,
@@ -231,7 +246,7 @@ static emacs_value sqlite3_napi_bind_parameter_count(
return env->make_integer(env, sqlite3_bind_parameter_count(stmt));
}
-static emacs_value sqlite3_napi_bind_int64(
+static emacs_value sqlite3_api_bind_int64(
emacs_env *env,
ptrdiff_t n,
emacs_value *args,
@@ -239,9 +254,6 @@ static emacs_value sqlite3_napi_bind_int64(
(void)ptr;
(void)n;
- // TODO:
- // should signal an error instead of return SYM(env, "nil")??
- // Exrtract sqlite3 db struct
if (!env->is_not_nil(env, args[0])) {
WARN(env, "%s: statement handle is nil", __func__);
return SYM(env, "nil");
@@ -258,11 +270,10 @@ static emacs_value sqlite3_napi_bind_int64(
intmax_t val = env->extract_integer(env, args[2]);
NON_LOCAL_EXIT_CHECK(env);
- /* DEBUG(env, "%s: col %d, val %d", __func__, col, val); */
return env->make_integer(env, sqlite3_bind_int64(stmt, col, val));
}
-static emacs_value sqlite3_napi_bind_text(
+static emacs_value sqlite3_api_bind_text(
emacs_env *env,
ptrdiff_t n,
emacs_value *args,
@@ -270,9 +281,6 @@ static emacs_value sqlite3_napi_bind_text(
(void)ptr;
(void)n;
- // TODO:
- // should signal an error instead of return SYM(env, "nil")??
- // Exrtract sqlite3 db struct
if (!env->is_not_nil(env, args[0])) {
WARN(env, "%s: statement handle is nil", __func__);
return SYM(env, "nil");
@@ -296,7 +304,7 @@ static emacs_value sqlite3_napi_bind_text(
return env->make_integer(env, rv);
}
-static emacs_value sqlite3_napi_bind_multi(
+static emacs_value sqlite3_api_bind_multi(
emacs_env *env,
ptrdiff_t n,
emacs_value *args,
@@ -304,9 +312,6 @@ static emacs_value sqlite3_napi_bind_multi(
(void)ptr;
(void)n;
- // TODO:
- // should signal an error instead of return SYM(env, "nil")??
- // Exrtract sqlite3 db struct
if (!env->is_not_nil(env, args[0])) {
WARN(env, "%s: statement handle is nil", __func__);
return SYM(env, "nil");
@@ -345,12 +350,10 @@ static emacs_value sqlite3_napi_bind_multi(
}
}
- /* message(env, "bind_text [%s] to col %d", txt, col); */
-
return env->make_integer(env, rv);
}
-static emacs_value sqlite3_napi_column_name(
+static emacs_value sqlite3_api_column_name(
emacs_env *env,
ptrdiff_t n,
emacs_value *args,
@@ -358,9 +361,6 @@ static emacs_value sqlite3_napi_column_name(
(void)ptr;
(void)n;
- // TODO:
- // should signal an error instead of return SYM(env, "nil")??
- // Exrtract sqlite3 db struct
if (!env->is_not_nil(env, args[0])) {
WARN(env, "%s: statement handle is nil", __func__);
return SYM(env, "nil");
@@ -377,7 +377,7 @@ static emacs_value sqlite3_napi_column_name(
return env->make_string(env, name, strlen(name));
}
-static emacs_value sqlite3_napi_column_text(
+static emacs_value sqlite3_api_column_text(
emacs_env *env,
ptrdiff_t n,
emacs_value *args,
@@ -385,9 +385,6 @@ static emacs_value sqlite3_napi_column_text(
(void)ptr;
(void)n;
- // TODO:
- // should signal an error instead of return SYM(env, "nil")??
- // Exrtract sqlite3 db struct
if (!env->is_not_nil(env, args[0])) {
WARN(env, "%s: statement handle is nil", __func__);
return SYM(env, "nil");
@@ -406,7 +403,7 @@ static emacs_value sqlite3_napi_column_text(
size);
}
-static emacs_value sqlite3_napi_column_int64(
+static emacs_value sqlite3_api_column_int64(
emacs_env *env,
ptrdiff_t n,
emacs_value *args,
@@ -414,9 +411,6 @@ static emacs_value sqlite3_napi_column_int64(
(void)ptr;
(void)n;
- // TODO:
- // should signal an error instead of return SYM(env, "nil")??
- // Exrtract sqlite3 db struct
if (!env->is_not_nil(env, args[0])) {
WARN(env, "%s: statement handle is nil", __func__);
return SYM(env, "nil");
@@ -432,7 +426,7 @@ static emacs_value sqlite3_napi_column_int64(
return env->make_integer(env, (intmax_t)sqlite3_column_int64(stmt, col));
}
-static emacs_value sqlite3_napi_column_double(
+static emacs_value sqlite3_api_column_double(
emacs_env *env,
ptrdiff_t n,
emacs_value *args,
@@ -440,9 +434,6 @@ static emacs_value sqlite3_napi_column_double(
(void)ptr;
(void)n;
- // TODO:
- // should signal an error instead of return SYM(env, "nil")??
- // Exrtract sqlite3 db struct
if (!env->is_not_nil(env, args[0])) {
WARN(env, "%s: statement handle is nil", __func__);
return SYM(env, "nil");
@@ -458,7 +449,7 @@ static emacs_value sqlite3_napi_column_double(
return env->make_float(env, sqlite3_column_double(stmt, col));
}
-static emacs_value sqlite3_napi_column_type(
+static emacs_value sqlite3_api_column_type(
emacs_env *env,
ptrdiff_t n,
emacs_value *args,
@@ -466,9 +457,6 @@ static emacs_value sqlite3_napi_column_type(
(void)ptr;
(void)n;
- // TODO:
- // should signal an error instead of return SYM(env, "nil")??
- // Exrtract sqlite3 db struct
if (!env->is_not_nil(env, args[0])) {
WARN(env, "%s: statement handle is nil", __func__);
return SYM(env, "nil");
@@ -484,7 +472,7 @@ static emacs_value sqlite3_napi_column_type(
return env->make_integer(env, sqlite3_column_type(stmt, col));
}
-static emacs_value sqlite3_napi_changes(
+static emacs_value sqlite3_api_changes(
emacs_env *env,
ptrdiff_t n,
emacs_value *args,
@@ -492,7 +480,6 @@ static emacs_value sqlite3_napi_changes(
(void)ptr;
(void)n;
- // Exrtract sqlite3 db struct
if (!env->is_not_nil(env, args[0])) {
WARN(env, "%s: database handle is nil", __func__);
return SYM(env, "nil");
@@ -504,7 +491,7 @@ static emacs_value sqlite3_napi_changes(
return env->make_integer(env, sqlite3_changes(dbh));
}
-static emacs_value sqlite3_napi_step(
+static emacs_value sqlite3_api_step(
emacs_env *env,
ptrdiff_t n,
emacs_value *args,
@@ -512,7 +499,6 @@ static emacs_value sqlite3_napi_step(
(void)ptr;
(void)n;
- // Exrtract sqlite3 db struct
if (!env->is_not_nil(env, args[0])) {
WARN(env, "%s: statement handle is nil", __func__);
return SYM(env, "nil");
@@ -524,7 +510,7 @@ static emacs_value sqlite3_napi_step(
return env->make_integer(env, sqlite3_step(stmt));
}
-static emacs_value sqlite3_napi_reset(
+static emacs_value sqlite3_api_reset(
emacs_env *env,
ptrdiff_t n,
emacs_value *args,
@@ -544,7 +530,7 @@ static emacs_value sqlite3_napi_reset(
return env->make_integer(env, sqlite3_reset(stmt));
}
-static emacs_value sqlite3_napi_column_count(
+static emacs_value sqlite3_api_column_count(
emacs_env *env,
ptrdiff_t n,
emacs_value *args,
@@ -552,7 +538,6 @@ static emacs_value sqlite3_napi_column_count(
(void)ptr;
(void)n;
- // Exrtract sqlite3 db struct
if (!env->is_not_nil(env, args[0])) {
WARN(env, "%s: statement handle is nil", __func__);
return SYM(env, "nil");
@@ -564,7 +549,7 @@ static emacs_value sqlite3_napi_column_count(
return env->make_integer(env, sqlite3_column_count(stmt));
}
-static emacs_value sqlite3_napi_fetch(
+static emacs_value sqlite3_api_fetch(
emacs_env *env,
ptrdiff_t n,
emacs_value *args,
@@ -572,7 +557,6 @@ static emacs_value sqlite3_napi_fetch(
(void)ptr;
(void)n;
- // Exrtract sqlite3 db struct
if (!env->is_not_nil(env, args[0])) {
WARN(env, "%s: statement handle is nil", __func__);
return SYM(env, "nil");
@@ -602,13 +586,13 @@ static emacs_value sqlite3_napi_fetch(
elts[i] = SYM(env, "nil");
}
}
- emacs_value list = SYM(env, "list");
- emacs_value res = env->funcall(env, list, ncols, elts);
+
+ emacs_value res = make_list(env, ncols, elts);
free(elts);
return res;
}
-static emacs_value sqlite3_napi_prepare(
+static emacs_value sqlite3_api_prepare(
emacs_env *env,
ptrdiff_t n,
emacs_value *args,
@@ -616,7 +600,6 @@ static emacs_value sqlite3_napi_prepare(
(void)ptr;
(void)n;
- // Exrtract sqlite3 db struct
if (!env->is_not_nil(env, args[0])) {
WARN(env, "%s: database handle is nil", __func__);
return SYM(env, "nil");
@@ -642,13 +625,13 @@ static emacs_value sqlite3_napi_prepare(
char buf[SQLITE3_MAX_LOG_BUF];
snprintf(buf, SQLITE3_MAX_LOG_BUF,
"prepare(): sqlite3_prepare_v2() returned %d", rv);
- signal_error(env, "db-error", buf);
+ signal_error(env, "sql-error", buf);
return SYM(env, "nil");
}
return env->make_user_ptr(env, sqlite3_stmt_gc, stmt);
}
-static emacs_value sqlite3_napi_get_autocommit(
+static emacs_value sqlite3_api_get_autocommit(
emacs_env *env,
ptrdiff_t n,
emacs_value *args,
@@ -708,9 +691,9 @@ static int exec_callback(void *data, int ncols,
emacs_value args[3];
args[0] = env->make_integer(env, ncols);
NON_LOCAL_EXIT_CHECK_AND_CLEANUP;
- args[1] = env->funcall(env, SYM(env, "list"), ncols, data_args);
+ args[1] = make_list(env, ncols, data_args);
NON_LOCAL_EXIT_CHECK_AND_CLEANUP;
- args[2] = env->funcall(env, SYM(env, "list"), ncols, col_args);
+ args[2] = make_list(env, ncols, col_args);
NON_LOCAL_EXIT_CHECK_AND_CLEANUP;
emacs_value v = env->funcall(env, fe->callback, 3, args);
@@ -722,7 +705,7 @@ static int exec_callback(void *data, int ncols,
return 1;
}
-static emacs_value sqlite3_napi_exec(
+static emacs_value sqlite3_api_exec(
emacs_env *env,
ptrdiff_t n,
emacs_value *args,
@@ -741,7 +724,7 @@ static emacs_value sqlite3_napi_exec(
return SYM(env, "nil");
}
- char *errmsg;
+ char *errmsg = 0;
int rv;
if (n == 3) {
struct func_env fe = { env, args[2] };
@@ -751,15 +734,17 @@ static emacs_value sqlite3_napi_exec(
}
if (rv != SQLITE_OK) {
- ERROR(env, "%s returned %d [%s]", __func__, rv, errmsg);
+ signal_error(env, "db-error", errmsg);
+ if (errmsg)
+ sqlite3_free(errmsg);
+ return SYM(env, "nil");
}
- if (errmsg)
- sqlite3_free(errmsg);
return env->make_integer(env, rv);
}
-static emacs_value sqlite3_napi_finalize(
+
+static emacs_value sqlite3_api_finalize(
emacs_env *env,
ptrdiff_t n,
emacs_value *args,
@@ -781,7 +766,7 @@ static emacs_value sqlite3_napi_finalize(
}
-static emacs_value sqlite3_napi_close(
+static emacs_value sqlite3_api_close(
emacs_env *env,
ptrdiff_t n,
emacs_value *args,
@@ -802,7 +787,7 @@ static emacs_value sqlite3_napi_close(
return SYM(env, "nil");
}
-static emacs_value sqlite3_napi_last_insert_rowid(
+static emacs_value sqlite3_api_last_insert_rowid(
emacs_env *env,
ptrdiff_t n,
emacs_value *args,
@@ -821,7 +806,7 @@ static emacs_value sqlite3_napi_last_insert_rowid(
return env->make_integer(env, (intmax_t)sqlite3_last_insert_rowid(dbh));
}
-static emacs_value sqlite3_napi_set_log_level(
+static emacs_value sqlite3_api_set_log_level(
emacs_env *env,
ptrdiff_t n,
emacs_value *args,
@@ -831,12 +816,12 @@ static emacs_value sqlite3_napi_set_log_level(
int log_level = env->extract_integer(env, args[0]);
NON_LOCAL_EXIT_CHECK(env);
- sqlite3_napi_log_level = log_level;
+ sqlite3_api_log_level = log_level;
return SYM(env, "nil");
}
#if 0
-static emacs_value sqlite3_napi_test(
+static emacs_value sqlite3_api_test(
emacs_env *env,
ptrdiff_t n,
emacs_value *args,
@@ -844,7 +829,6 @@ static emacs_value sqlite3_napi_test(
(void)ptr;
(void)n;
- //return SYM(env, "nil");
emacs_value *fargs = malloc(sizeof(emacs_value)*2);
fargs[0] = env->make_integer(env, 1);
fargs[1] = env->make_integer(env, 99);
@@ -852,7 +836,7 @@ static emacs_value sqlite3_napi_test(
}
#endif
-static emacs_value sqlite3_napi_open(
+static emacs_value sqlite3_api_open(
emacs_env *env,
ptrdiff_t n,
emacs_value *args,
@@ -863,26 +847,29 @@ static emacs_value sqlite3_napi_open(
// Filename
char *db_file = 0;
if (extract_string_arg(env, args[0], &db_file)) {
- WARN(env, "%s: extract_string_arg return non-zero", __func__);
return SYM(env, "nil");
}
// FLAGS
- int flags = env->extract_integer(env, args[1]);
- NON_LOCAL_EXIT_CHECK(env);
+ int flags = 0;
+ for (int i = 1; i < n; i++) {
+ flags |= env->extract_integer(env, args[i]);
+ NON_LOCAL_EXIT_CHECK(env);
+ }
- sqlite3 *dbh;
+ sqlite3 *dbh = 0;
int rv = sqlite3_open_v2(db_file, &dbh, flags, 0);
INFO(env, "%s: file=%s, flags=%d, rv=%d", __func__, db_file, flags, rv);
free(db_file);
if (rv != SQLITE_OK) {
- // TODO: more descriptive error message (with error code)
+ if (dbh)
+ sqlite3_free(dbh);
signal_error(env, "db-error", "failed to open DB file");
return SYM(env, "nil");
}
- return env->make_user_ptr(env, sqlite3_db_gc, dbh);
+ return env->make_user_ptr(env, sqlite3_dbh_gc, dbh);
}
int emacs_module_init(struct emacs_runtime *ert) {
@@ -900,58 +887,58 @@ int emacs_module_init(struct emacs_runtime *ert) {
};
struct lisp_func all_funcs[] = {
- { "sqlite3-open", 1, 2, sqlite3_napi_open,
+ { "sqlite3-open", 1, 10, sqlite3_api_open,
"Open a SQLite3 database." },
- { "sqlite3-close", 1, 1, sqlite3_napi_close,
+ { "sqlite3-close", 1, 1, sqlite3_api_close,
"Close a SQLite3 database." },
- { "sqlite3-prepare", 2, 2, sqlite3_napi_prepare,
+ { "sqlite3-prepare", 2, 2, sqlite3_api_prepare,
"Prepare (compile) a SQL statement." },
- { "sqlite3-finalize", 1, 1, sqlite3_napi_finalize,
+ { "sqlite3-finalize", 1, 1, sqlite3_api_finalize,
"Destroy a prepared statement." },
- { "sqlite3-changes", 1, 1, sqlite3_napi_changes,
+ { "sqlite3-changes", 1, 1, sqlite3_api_changes,
"Count the number of rows modified." },
- { "sqlite3-step", 1, 1, sqlite3_napi_step,
+ { "sqlite3-step", 1, 1, sqlite3_api_step,
"Evaluate a SQL statement." },
- { "sqlite3-reset", 1, 1, sqlite3_napi_reset,
+ { "sqlite3-reset", 1, 1, sqlite3_api_reset,
"Reset a prepared SQL statement." },
- { "sqlite3-last-insert-rowid", 1, 1, sqlite3_napi_last_insert_rowid,
+ { "sqlite3-last-insert-rowid", 1, 1, sqlite3_api_last_insert_rowid,
"Return last insert rowid." },
- { "sqlite3-get-autocommit", 1, 1, sqlite3_napi_get_autocommit,
+ { "sqlite3-get-autocommit", 1, 1, sqlite3_api_get_autocommit,
"Test for auto-commit mode." },
- { "sqlite3-exec", 2, 3, sqlite3_napi_exec,
+ { "sqlite3-exec", 2, 3, sqlite3_api_exec,
"One-step query execution interface." },
- { "sqlite3-set-log-level", 1, 1, sqlite3_napi_set_log_level,
+ { "sqlite3-set-log-level", 1, 1, sqlite3_api_set_log_level,
"Set log level (DEBUG 0, INFO 1, WARN 2, ERROR 3, NOLOG 100)." },
/* bind interface */
- { "sqlite3-bind-text", 3, 3, sqlite3_napi_bind_text,
+ { "sqlite3-bind-text", 3, 3, sqlite3_api_bind_text,
"Bind text to a prepared SQL statement." },
- { "sqlite3-bind-int64", 3, 3, sqlite3_napi_bind_int64,
+ { "sqlite3-bind-int64", 3, 3, sqlite3_api_bind_int64,
"Bind int64 to a prepared SQL statement." },
- { "sqlite3-bind-double", 3, 3, sqlite3_napi_bind_double,
+ { "sqlite3-bind-double", 3, 3, sqlite3_api_bind_double,
"Bind double to a prepared SQL statement." },
- { "sqlite3-bind-null", 2, 2, sqlite3_napi_bind_null,
+ { "sqlite3-bind-null", 2, 2, sqlite3_api_bind_null,
"Bind NULL to a prepared SQL statement." },
{ "sqlite3-bind-parameter-count", 1, 1,
- sqlite3_napi_bind_parameter_count,
+ sqlite3_api_bind_parameter_count,
"Return the number of SQL parameters." },
- { "sqlite3-bind-multi", 1, 127, sqlite3_napi_bind_multi,
+ { "sqlite3-bind-multi", 1, 127, sqlite3_api_bind_multi,
"Bind multiple parameters to a prepared SQL statement." },
/* Result */
- { "sqlite3-column-count", 1, 1, sqlite3_napi_column_count,
+ { "sqlite3-column-count", 1, 1, sqlite3_api_column_count,
"Return the number of rows in a result set." },
- { "sqlite3-column-name", 2, 2, sqlite3_napi_column_name,
+ { "sqlite3-column-name", 2, 2, sqlite3_api_column_name,
"Return the name of a column." },
- { "sqlite3-column-type", 2, 2, sqlite3_napi_column_type,
+ { "sqlite3-column-type", 2, 2, sqlite3_api_column_type,
"Return the datatype of a column." },
- { "sqlite3-column-text", 2, 2, sqlite3_napi_column_text,
+ { "sqlite3-column-text", 2, 2, sqlite3_api_column_text,
"Return text data of a column." },
- { "sqlite3-column-int64", 2, 2, sqlite3_napi_column_int64,
+ { "sqlite3-column-int64", 2, 2, sqlite3_api_column_int64,
"Return int64 data of a column." },
- { "sqlite3-column-double", 2, 2, sqlite3_napi_column_double,
+ { "sqlite3-column-double", 2, 2, sqlite3_api_column_double,
"Return double data of a column." },
- { "sqlite3-fetch", 1, 1, sqlite3_napi_fetch,
+ { "sqlite3-fetch", 1, 1, sqlite3_api_fetch,
"Return a row as a list." },
{ NULL, 0, 0, NULL, NULL }
@@ -965,11 +952,11 @@ int emacs_module_init(struct emacs_runtime *ert) {
all_funcs[i].function,
all_funcs[i].documentation);
}
- sqlite3_napi_log_level = SQLITE3_LOG_LEVEL_ERROR;
+ sqlite3_api_log_level = SQLITE3_LOG_LEVEL_ERROR;
/* (provide 'sqlite3-module ) */
emacs_value provide = SYM(env, "provide");
- emacs_value mod = SYM(env, "sqlite3-napi-module");
+ emacs_value mod = SYM(env, "sqlite3-api-module");
env->funcall(env, provide, 1, &mod);
return 0;
}
diff --git a/sqlite3-api.el b/sqlite3-api.el
new file mode 100644
index 0000000000..948a19971d
--- /dev/null
+++ b/sqlite3-api.el
@@ -0,0 +1,20 @@
+;; This program is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+(require 'sqlite3-api-constants)
+(require 'sqlite3-api-module)
+
+(define-error 'db-error "Database Error")
+(define-error 'sql-error "SQL Error")
+
+(provide 'sqlite3-api)
diff --git a/sqlite3-napi-module.so b/sqlite3-napi-module.so
deleted file mode 100755
index 1a341eb5af..0000000000
Binary files a/sqlite3-napi-module.so and /dev/null differ
diff --git a/tools/gen-consts.py b/tools/gen-consts.py
index 752f606ff6..f2d21606e4 100755
--- a/tools/gen-consts.py
+++ b/tools/gen-consts.py
@@ -9,7 +9,6 @@ c_src="""
#include <sqlite3.h>
int main(int argc, char *argv[]) {
- printf(\"(require 'sqlite3-napi-module)\\n");
"""
print(c_src)
for line in sys.stdin.readlines():
@@ -22,5 +21,5 @@ for line in sys.stdin.readlines():
print(' printf("(defconst {1} \\"%s\\")\\n", {0});'.format(fields[1],
name))
else:
print(' printf("(defconst {1} %d)\\n", {0});'.format(fields[1], name))
-print(' printf("(provide \'sqlite3-napi)");')
+print(' printf("(provide \'sqlite3-api-constants)");')
print("}")
diff --git a/tools/run.sh b/tools/run.sh
index 4f052f7044..2c0a918483 100755
--- a/tools/run.sh
+++ b/tools/run.sh
@@ -1,5 +1,25 @@
#!/bin/bash
-grep "^#define SQLITE" /usr/include/sqlite3.h | ./gen-consts.py > def.c
-gcc -o def def.c -lsqlite3
-./def > ../sqlite3-napi.el
+DEST=../sqlite3-api-constants.el
+cat <<EOF > $DEST
+;; This program is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <http://www.gnu.org/licenses/>.
+;;
+EOF
+
+EXE=./def
+
+rm -f $EXE ${EXE}.c
+grep "^#define SQLITE" /usr/include/sqlite3.h | ./gen-consts.py > ${EXE}.c
+gcc -o $EXE ${EXE}.c -lsqlite3
+${EXE} >> $DEST
- [nongnu] elpa/sqlite3 ce41ac18bc 02/62: first commit, (continued)
- [nongnu] elpa/sqlite3 ce41ac18bc 02/62: first commit, ELPA Syncer, 2023/03/14
- [nongnu] elpa/sqlite3 8ad45baacf 05/62: fixed memory leak; used sqlite3_close_v2, ELPA Syncer, 2023/03/14
- [nongnu] elpa/sqlite3 ed7ea9c919 18/62: removed sqlite3-api-constants.el from repo, ELPA Syncer, 2023/03/14
- [nongnu] elpa/sqlite3 0bae137c63 26/62: LIB and INC added to Makefile, ELPA Syncer, 2023/03/14
- [nongnu] elpa/sqlite3 9e6dbe5d37 15/62: fixed typo, ELPA Syncer, 2023/03/14
- [nongnu] elpa/sqlite3 0131cc617d 19/62: python3 -> python, ELPA Syncer, 2023/03/14
- [nongnu] elpa/sqlite3 7abb3c6f70 28/62: fixed callback example; added Homebrew linkage, ELPA Syncer, 2023/03/14
- [nongnu] elpa/sqlite3 71d35506ec 07/62: minor adjustment to Makefile, ELPA Syncer, 2023/03/14
- [nongnu] elpa/sqlite3 a2d5e39133 43/62: Removed unused codes from consts.c, ELPA Syncer, 2023/03/14
- [nongnu] elpa/sqlite3 b72c2c40d9 44/62: Better handling of SQLite codes in consts.c, ELPA Syncer, 2023/03/14
- [nongnu] elpa/sqlite3 a51467b031 04/62: added test for Emacs 25.1,
ELPA Syncer <=
- [nongnu] elpa/sqlite3 1f1f7ab2db 09/62: added package creation section, ELPA Syncer, 2023/03/14
- [nongnu] elpa/sqlite3 1b7b1fc03f 10/62: fixed module installation bug, ELPA Syncer, 2023/03/14
- [nongnu] elpa/sqlite3 a69ff5a456 11/62: github installation function added, ELPA Syncer, 2023/03/14
- [nongnu] elpa/sqlite3 47391311a9 12/62: edited sqlite3-api.el to adhere to melpa guidelines, ELPA Syncer, 2023/03/14
- [nongnu] elpa/sqlite3 723787e6d9 21/62: added 'make install', ELPA Syncer, 2023/03/14
- [nongnu] elpa/sqlite3 77e719fb88 24/62: better comments, ELPA Syncer, 2023/03/14
- [nongnu] elpa/sqlite3 0dfe8e07df 30/62: 26.1 test added, ELPA Syncer, 2023/03/14
- [nongnu] elpa/sqlite3 b8fc4e2fae 35/62: TOC, ELPA Syncer, 2023/03/14
- [nongnu] elpa/sqlite3 15697800f8 37/62: Fixed changelog, ELPA Syncer, 2023/03/14
- [nongnu] elpa/sqlite3 9a2dbb9dc2 38/62: fixed typo, ELPA Syncer, 2023/03/14