emacs-elpa-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[nongnu] elpa/emacsql 3e6a24e22a 303/427: Escape identifiers that collid


From: ELPA Syncer
Subject: [nongnu] elpa/emacsql 3e6a24e22a 303/427: Escape identifiers that collide with keywords.
Date: Tue, 13 Dec 2022 02:59:53 -0500 (EST)

branch: elpa/emacsql
commit 3e6a24e22af95460a05bfab5c258c1ffd34ffc2a
Author: Christopher Wellons <wellons@nullprogram.com>
Commit: Christopher Wellons <wellons@nullprogram.com>

    Escape identifiers that collide with keywords.
---
 README.md           |  1 +
 emacsql-compiler.el | 16 +++++++++++++++-
 emacsql-mysql.el    | 35 +++++++++++++++++++++++++++++++++++
 emacsql-psql.el     | 15 +++++++++++++++
 emacsql-sqlite.el   | 19 +++++++++++++++++++
 5 files changed, 85 insertions(+), 1 deletion(-)

diff --git a/README.md b/README.md
index 0714831c59..d0c55b7923 100644
--- a/README.md
+++ b/README.md
@@ -373,6 +373,7 @@ inherits from `emacsql-connection`.
  * Provide `emacsql-types` if needed (hint: use a class-allocated slot).
  * Ensure that you properly read NULL as nil (hint: ask your back-end
    to print it that way).
+ * Register all reserved words with `emacsql-register-reserved`.
  * Preferably provide `emacsql-reconnect` if possible.
  * If available, ensure foreign key constraints are enabled by
    default.
diff --git a/emacsql-compiler.el b/emacsql-compiler.el
index baa45bba2e..8879c97748 100644
--- a/emacsql-compiler.el
+++ b/emacsql-compiler.el
@@ -32,6 +32,19 @@
 
 ;; Escaping functions:
 
+(defvar emacsql-reserved (make-hash-table :test 'equal)
+  "Collection of all known reserved words, used for escaping.")
+
+(defun emacsql-register-reserved (seq)
+  "Register sequence of keywords as reserved words, returning SEQ."
+  (cl-loop for word being the elements of seq
+           do (setf (gethash (upcase (format "%s" word)) emacsql-reserved) t)
+           finally (cl-return seq)))
+
+(defun emacsql-reserved-p (name)
+  "Returns non-nil if string NAME is a SQL keyword."
+  (gethash (upcase name) emacsql-reserved))
+
 (defun emacsql-quote-scalar (string)
   "Single-quote (scalar) STRING for use in a SQL expression."
   (format "'%s'" (replace-regexp-in-string "'" "''" string)))
@@ -53,7 +66,8 @@
       (let ((print (replace-regexp-in-string "-" "_" (format "%S" identifier)))
             (special "[]-\000-\040!\"#%&'()*+,./:;<=>?@[\\^`{|}~\177]"))
         (if (or (string-match-p special print)
-                (string-match-p "^[0-9$]" print))
+                (string-match-p "^[0-9$]" print)
+                (emacsql-reserved-p print))
             (emacsql-quote-identifier print)
           print)))))
 
diff --git a/emacsql-mysql.el b/emacsql-mysql.el
index 4930497b07..32d1248a21 100644
--- a/emacsql-mysql.el
+++ b/emacsql-mysql.el
@@ -12,6 +12,41 @@
 (defvar emacsql-mysql-sentinel "--------------\n\n--------------\n\n"
   "What MySQL will print when it has completed its output.")
 
+(defvar emacsql-mysql-reserved
+  (emacsql-register-reserved
+   '(ACCESSIBLE ADD ALL ALTER ANALYZE AND AS ASC ASENSITIVE BEFORE
+     BETWEEN BIGINT BINARY BLOB BOTH BY CALL CASCADE CASE CHANGE CHAR
+     CHARACTER CHECK COLLATE COLUMN CONDITION CONSTRAINT CONTINUE
+     CONVERT CREATE CROSS CURRENT_DATE CURRENT_TIME CURRENT_TIMESTAMP
+     CURRENT_USER CURSOR DATABASE DATABASES DAY_HOUR DAY_MICROSECOND
+     DAY_MINUTE DAY_SECOND DEC DECIMAL DECLARE DEFAULT DELAYED DELETE
+     DESC DESCRIBE DETERMINISTIC DISTINCT DISTINCTROW DIV DOUBLE DROP
+     DUAL EACH ELSE ELSEIF ENCLOSED ESCAPED EXISTS EXIT EXPLAIN FALSE
+     FETCH FLOAT FLOAT4 FLOAT8 FOR FORCE FOREIGN FROM FULLTEXT GENERAL
+     GRANT GROUP HAVING HIGH_PRIORITY HOUR_MICROSECOND HOUR_MINUTE
+     HOUR_SECOND IF IGNORE IGNORE_SERVER_IDS IN INDEX INFILE INNER
+     INOUT INSENSITIVE INSERT INT INT1 INT2 INT3 INT4 INT8 INTEGER
+     INTERVAL INTO IS ITERATE JOIN KEY KEYS KILL LEADING LEAVE LEFT
+     LIKE LIMIT LINEAR LINES LOAD LOCALTIME LOCALTIMESTAMP LOCK LONG
+     LONGBLOB LONGTEXT LOOP LOW_PRIORITY MASTER_HEARTBEAT_PERIOD
+     MASTER_SSL_VERIFY_SERVER_CERT MATCH MAXVALUE MAXVALUE MEDIUMBLOB
+     MEDIUMINT MEDIUMTEXT MIDDLEINT MINUTE_MICROSECOND MINUTE_SECOND
+     MOD MODIFIES NATURAL NOT NO_WRITE_TO_BINLOG NULL NUMERIC ON
+     OPTIMIZE OPTION OPTIONALLY OR ORDER OUT OUTER OUTFILE PRECISION
+     PRIMARY PROCEDURE PURGE RANGE READ READS READ_WRITE REAL
+     REFERENCES REGEXP RELEASE RENAME REPEAT REPLACE REQUIRE RESIGNAL
+     RESIGNAL RESTRICT RETURN REVOKE RIGHT RLIKE SCHEMA SCHEMAS
+     SECOND_MICROSECOND SELECT SENSITIVE SEPARATOR SET SHOW SIGNAL
+     SIGNAL SLOW SMALLINT SPATIAL SPECIFIC SQL SQL_BIG_RESULT
+     SQL_CALC_FOUND_ROWS SQLEXCEPTION SQL_SMALL_RESULT SQLSTATE
+     SQLWARNING SSL STARTING STRAIGHT_JOIN TABLE TERMINATED THEN
+     TINYBLOB TINYINT TINYTEXT TO TRAILING TRIGGER TRUE UNDO UNION
+     UNIQUE UNLOCK UNSIGNED UPDATE USAGE USE USING UTC_DATE UTC_TIME
+     UTC_TIMESTAMP VALUES VARBINARY VARCHAR VARCHARACTER VARYING WHEN
+     WHERE WHILE WITH WRITE XOR YEAR_MONTH ZEROFILL))
+  "List of all of MySQL's reserved words.
+http://dev.mysql.com/doc/refman/5.5/en/reserved-words.html";)
+
 (defclass emacsql-mysql-connection (emacsql-connection)
   ((dbname :reader emacsql-psql-dbname :initarg :dbname)
    (types :allocation :class
diff --git a/emacsql-psql.el b/emacsql-psql.el
index ab1fc44040..a2bbc99f02 100644
--- a/emacsql-psql.el
+++ b/emacsql-psql.el
@@ -26,6 +26,21 @@
                 nil)))
         (error :cannot-execute)))))
 
+(defvar emacsql-psql-reserved
+  (emacsql-register-reserved
+   '(ALL ANALYSE ANALYZE AND ANY AS ASC AUTHORIZATION BETWEEN BINARY
+     BOTH CASE CAST CHECK COLLATE COLUMN CONSTRAINT CREATE CROSS
+     CURRENT_DATE CURRENT_TIME CURRENT_TIMESTAMP CURRENT_USER DEFAULT
+     DEFERRABLE DESC DISTINCT DO ELSE END EXCEPT FALSE FOR FOREIGN
+     FREEZE FROM FULL GRANT GROUP HAVING ILIKE IN INITIALLY INNER
+     INTERSECT INTO IS ISNULL JOIN LEADING LEFT LIKE LIMIT LOCALTIME
+     LOCALTIMESTAMP NATURAL NEW NOT NOTNULL NULL OFF OFFSET OLD ON
+     ONLY OR ORDER OUTER OVERLAPS PLACING PRIMARY REFERENCES RIGHT
+     SELECT SESSION_USER SIMILAR SOME TABLE THEN TO TRAILING TRUE
+     UNION UNIQUE USER USING VERBOSE WHEN WHERE))
+  "List of all of PostgreSQL's reserved words.
+http://www.postgresql.org/docs/7.3/static/sql-keywords-appendix.html";)
+
 (defclass emacsql-psql-connection (emacsql-connection)
   ((dbname :reader emacsql-psql-dbname :initarg :dbname)
    (types :allocation :class
diff --git a/emacsql-sqlite.el b/emacsql-sqlite.el
index a62f35fcab..ff8e3c307d 100644
--- a/emacsql-sqlite.el
+++ b/emacsql-sqlite.el
@@ -34,6 +34,25 @@ version."
                     emacsql-data-root)
   "Path to the EmacSQL backend (this is not the sqlite3 shell).")
 
+(defvar emacsql-sqlite-reserved
+  (emacsql-register-reserved
+   '(ABORT ACTION ADD AFTER ALL ALTER ANALYZE AND AS ASC ATTACH
+     AUTOINCREMENT BEFORE BEGIN BETWEEN BY CASCADE CASE CAST CHECK
+     COLLATE COLUMN COMMIT CONFLICT CONSTRAINT CREATE CROSS
+     CURRENT_DATE CURRENT_TIME CURRENT_TIMESTAMP DATABASE DEFAULT
+     DEFERRABLE DEFERRED DELETE DESC DETACH DISTINCT DROP EACH ELSE END
+     ESCAPE EXCEPT EXCLUSIVE EXISTS EXPLAIN FAIL FOR FOREIGN FROM FULL
+     GLOB GROUP HAVING IF IGNORE IMMEDIATE IN INDEX INDEXED INITIALLY
+     INNER INSERT INSTEAD INTERSECT INTO IS ISNULL JOIN KEY LEFT LIKE
+     LIMIT MATCH NATURAL NO NOT NOTNULL NULL OF OFFSET ON OR ORDER
+     OUTER PLAN PRAGMA PRIMARY QUERY RAISE RECURSIVE REFERENCES REGEXP
+     REINDEX RELEASE RENAME REPLACE RESTRICT RIGHT ROLLBACK ROW
+     SAVEPOINT SELECT SET TABLE TEMP TEMPORARY THEN TO TRANSACTION
+     TRIGGER UNION UNIQUE UPDATE USING VACUUM VALUES VIEW VIRTUAL WHEN
+     WHERE WITH WITHOUT))
+  "List of all of SQLite's reserved words.
+http://www.sqlite.org/lang_keywords.html";)
+
 (defclass emacsql-sqlite-connection (emacsql-connection emacsql-protocol-mixin)
   ((file :initarg :file
          :type (or null string)



reply via email to

[Prev in Thread] Current Thread [Next in Thread]