[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[nongnu] elpa/emacsql 8945af0dd8 129/427: Add :check and allow schemas t
From: |
ELPA Syncer |
Subject: |
[nongnu] elpa/emacsql 8945af0dd8 129/427: Add :check and allow schemas to have variables. |
Date: |
Tue, 13 Dec 2022 02:59:35 -0500 (EST) |
branch: elpa/emacsql
commit 8945af0dd8ba6b6dbe901bee356f1bbe207778fd
Author: Christopher Wellons <wellons@nullprogram.com>
Commit: Christopher Wellons <wellons@nullprogram.com>
Add :check and allow schemas to have variables.
---
README.md | 3 +--
emacsql-tests.el | 19 +++++++++-----
emacsql.el | 77 +++++++++++++++++++++++++++++++-------------------------
3 files changed, 57 insertions(+), 42 deletions(-)
diff --git a/README.md b/README.md
index af7699f187..c3f7a0267b 100644
--- a/README.md
+++ b/README.md
@@ -59,8 +59,7 @@ Because Emacsql stores entire lisp objects as values, the only
relevant types are `integer`, `float`, and `object` (default).
Additional columns constraints include `:primary` (aka `PRIMARY KEY`),
-`:unique` (aka `UNIQUE`), `:non-nil` (aka `NOT NULL`), `:default` (aka
-`DEFAULT`).
+`:unique`, `:non-nil` (aka `NOT NULL`), `:default`, and `:check`.
```el
;; Example schema:
diff --git a/emacsql-tests.el b/emacsql-tests.el
index dac5793f89..fd514fe205 100644
--- a/emacsql-tests.el
+++ b/emacsql-tests.el
@@ -30,14 +30,15 @@
"(1, 2, 3), (4, 5, 6)")))
(ert-deftest emacsql-schema ()
- (should (string= (emacsql--schema-to-string [a]) "a"))
- (should (string= (emacsql--schema-to-string [a b c]) "a, b, c"))
- (should (string= (emacsql--schema-to-string [a (b)]) "a, b"))
- (should (string= (emacsql--schema-to-string [a (b float)])
+ (should (string= (car (emacsql--schema-to-string [a])) "a"))
+ (should (string= (car (emacsql--schema-to-string [a b c])) "a, b, c"))
+ (should (string= (car (emacsql--schema-to-string [a (b)])) "a, b"))
+ (should (string= (car (emacsql--schema-to-string [a (b float)]))
"a, b REAL"))
- (should (string= (emacsql--schema-to-string [a (b :primary float :unique)])
+ (should (string= (car (emacsql--schema-to-string
+ [a (b :primary float :unique)]))
"a, b REAL PRIMARY KEY UNIQUE"))
- (should (string= (emacsql--schema-to-string [(a integer) (b float)])
+ (should (string= (car (emacsql--schema-to-string [(a integer) (b float)]))
"a INTEGER, b REAL")))
(ert-deftest emacsql-var ()
@@ -80,6 +81,12 @@
"CREATE TABLE foo (a DEFAULT 10);")
([:create-table foo [(a :primary :non-nil) b]] '()
"CREATE TABLE foo (a PRIMARY KEY NOT NULL, b);")
+ ([:create-table foo [a (b :check (< b 10))]] '()
+ "CREATE TABLE foo (a, b CHECK (b < 10));")
+ ([:create-table foo $1] '([a b (c :primary)])
+ "CREATE TABLE foo (a, b, c PRIMARY KEY);")
+ ([:create-table foo [a b (c :default $1)]] '("FOO")
+ "CREATE TABLE foo (a, b, c DEFAULT '\"FOO\"');")
([:drop-table $1] '(foo)
"DROP TABLE foo;")))
diff --git a/emacsql.el b/emacsql.el
index 8861f25ec7..0683b37fee 100644
--- a/emacsql.el
+++ b/emacsql.el
@@ -264,39 +264,6 @@ CONN-SPEC is a connection specification like the call to
(not (emacsql--complete-p conn)))
(accept-process-output (emacsql-process conn) timeout))))
-(defun emacsql--column-to-string (column)
- "Convert COLUMN schema into a SQL string."
- (let ((name (emacsql-escape-identifier (pop column)))
- (output ())
- (type nil))
- (while column
- (let ((next (pop column)))
- (cl-case next
- (:primary (push "PRIMARY KEY" output))
- (:non-nil (push "NOT NULL" output))
- (:unique (push "UNIQUE" output))
- (:default (push "DEFAULT" output)
- (push (emacsql-escape-value (pop column)) output))
- (integer (setf type "INTEGER"))
- (float (setf type "REAL"))
- (object (setf type "TEXT"))
- (otherwise
- (if (keywordp next)
- (error "Unknown schema contraint %s" next)
- (error "Invalid type %s: %s" next
- "must be 'integer', 'float', or 'object'"))))))
- (mapconcat #'identity
- (nconc (if type (list name type) (list name)) (nreverse output))
- " ")))
-
-(defun emacsql--schema-to-string (schema)
- "Convert SCHEMA into a SQL-consumable string."
- (cl-loop for column being the elements of schema
- when (symbolp column)
- collect (emacsql-escape-identifier column) into parts
- else collect (emacsql--column-to-string column) into parts
- finally (cl-return (mapconcat #'identity parts ", "))))
-
(defun emacsql-escape-value (value)
"Escape VALUE for sending to SQLite."
(let ((print-escape-newlines t))
@@ -365,6 +332,7 @@ a list of (<string> [arg-pos] ...)."
(:identifier (emacsql-escape-identifier thing))
(:value (emacsql-escape-value thing))
(:vector (emacsql-escape-vector thing))
+ (:schema (car (emacsql--schema-to-string thing)))
(:auto (if (symbolp thing)
(emacsql-escape-identifier thing)
(emacsql-escape-value thing)))))))))
@@ -430,6 +398,45 @@ definitions for return from a `emacsql-defexpander'."
(idents (thing) (combine (emacsql--idents thing))))
(cons (concat ,prefix (progn ,@body)) emacsql--vars))))
+(defun emacsql--column-to-string (column)
+ "Convert COLUMN schema into a SQL string."
+ (emacsql-with-vars ""
+ (let ((name (var (pop column) :identifier))
+ (output ())
+ (type nil))
+ (while column
+ (let ((next (pop column)))
+ (cl-case next
+ (:primary (push "PRIMARY KEY" output))
+ (:non-nil (push "NOT NULL" output))
+ (:unique (push "UNIQUE" output))
+ (:default (push "DEFAULT" output)
+ (push (var (pop column) :value) output))
+ (:check (push "CHECK" output)
+ (push (format "(%s)" (expr (pop column))) output))
+ (integer (setf type "INTEGER"))
+ (float (setf type "REAL"))
+ (object (setf type "TEXT"))
+ (otherwise
+ (if (keywordp next)
+ (error "Unknown schema contraint %s" next)
+ (error "Invalid type %s: %s" next
+ "must be 'integer', 'float', or 'object'"))))))
+ (setf output (nreverse output))
+ (when type (push type output))
+ (push name output)
+ (mapconcat #'identity output " "))))
+
+(defun emacsql--schema-to-string (schema)
+ "Convert SCHEMA into a SQL-consumable string."
+ (emacsql-with-vars ""
+ (cl-loop for column across schema
+ when (symbolp column)
+ collect (var column :identifier) into parts
+ else
+ collect (combine (emacsql--column-to-string column)) into parts
+ finally (cl-return (mapconcat #'identity parts ", ")))))
+
(defun emacsql--vector (vector)
"Expand VECTOR, making variables as needed."
(emacsql-with-vars ""
@@ -570,7 +577,9 @@ definitions for return from a `emacsql-defexpander'."
(let* ((items (list temporary "TABLE" if-not-exists name))
(spec (cl-remove-if-not #'identity items)))
(format "%s (%s)" (mapconcat #'identity spec " ")
- (emacsql--schema-to-string schema))))))
+ (if (symbolp schema)
+ (var schema :schema)
+ (combine (emacsql--schema-to-string schema))))))))
(emacsql-defexpander :drop-table (table)
(emacsql-with-vars "DROP TABLE "
- [nongnu] elpa/emacsql 0ba12b89d5 084/427: Drop "work in progress.", (continued)
- [nongnu] elpa/emacsql 0ba12b89d5 084/427: Drop "work in progress.", ELPA Syncer, 2022/12/13
- [nongnu] elpa/emacsql 364bf466ea 086/427: Linkify the issue in the README., ELPA Syncer, 2022/12/13
- [nongnu] elpa/emacsql dd3f153406 089/427: Drop old with-errors macro., ELPA Syncer, 2022/12/13
- [nongnu] elpa/emacsql 72c1954517 096/427: Block on connection until the output has flushed., ELPA Syncer, 2022/12/13
- [nongnu] elpa/emacsql 1e9857ccc4 103/427: Allow variables inside vectors., ELPA Syncer, 2022/12/13
- [nongnu] elpa/emacsql 8a66563af6 105/427: Combine :insert and :into., ELPA Syncer, 2022/12/13
- [nongnu] elpa/emacsql d04ef64ce0 109/427: Add IF NOT EXISTS and TEMPORARY to CREATE TABLE., ELPA Syncer, 2022/12/13
- [nongnu] elpa/emacsql 58641b9827 115/427: Fill out keywords in README., ELPA Syncer, 2022/12/13
- [nongnu] elpa/emacsql fc941d7c75 118/427: Capture a common identifier vector pattern., ELPA Syncer, 2022/12/13
- [nongnu] elpa/emacsql a09911a205 125/427: Add LIMIT and OFFSET expanders., ELPA Syncer, 2022/12/13
- [nongnu] elpa/emacsql 8945af0dd8 129/427: Add :check and allow schemas to have variables.,
ELPA Syncer <=
- [nongnu] elpa/emacsql 4206b17f39 134/427: Add support for AS with CREATE TABLE., ELPA Syncer, 2022/12/13
- [nongnu] elpa/emacsql 6c32f02139 137/427: Add emacsql-thread macro., ELPA Syncer, 2022/12/13
- [nongnu] elpa/emacsql 54c180017e 138/427: Add :pragma and note in README., ELPA Syncer, 2022/12/13
- [nongnu] elpa/emacsql 5e2ab842f7 139/427: Add foreign key test., ELPA Syncer, 2022/12/13
- [nongnu] elpa/emacsql 42c2fd7569 145/427: Tweak limitation wording., ELPA Syncer, 2022/12/13
- [nongnu] elpa/emacsql fe0c7004fc 146/427: Add :begin, :commit, and :rollback., ELPA Syncer, 2022/12/13
- [nongnu] elpa/emacsql 2550196816 162/427: Drop SQLite version requirements., ELPA Syncer, 2022/12/13
- [nongnu] elpa/emacsql 9a1b4209ba 164/427: Add PostgreSQL front-end., ELPA Syncer, 2022/12/13
- [nongnu] elpa/emacsql 5f4c2ed5a7 166/427: Add emacsql-psql-unavailable-p., ELPA Syncer, 2022/12/13
- [nongnu] elpa/emacsql 1d0ef4011c 167/427: Make emacsql-connection abstract., ELPA Syncer, 2022/12/13