mirror of
git://git.sv.gnu.org/emacs.git
synced 2025-12-28 16:21:07 -08:00
* src/sqlite.c (sqlite3_db_config) [WINDOWSNT]: Load from the DLL. (Fsqlite_load_extension): Use 'sqlite3_db_config' to enable and disable loading of extensions. Add a few free extensions to the allow-list. Fix testing for the ".dll" extension. (Bug#63590) * test/src/sqlite-tests.el (sqlite-load-extension): Fix the test to require successful load if the extension does exist.
264 lines
8.9 KiB
EmacsLisp
264 lines
8.9 KiB
EmacsLisp
;;; sqlite-tests.el --- Tests for sqlite.el -*- lexical-binding: t; -*-
|
||
|
||
;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
|
||
|
||
;; This file is part of GNU Emacs.
|
||
|
||
;; GNU Emacs 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.
|
||
|
||
;; GNU Emacs 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 GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
|
||
|
||
;;; Commentary:
|
||
|
||
;;
|
||
|
||
;;; Code:
|
||
|
||
(require 'ert)
|
||
(require 'ert-x)
|
||
|
||
(declare-function sqlite-execute "sqlite.c")
|
||
(declare-function sqlite-close "sqlite.c")
|
||
(declare-function sqlitep "sqlite.c")
|
||
(declare-function sqlite-available-p "sqlite.c")
|
||
(declare-function sqlite-finalize "sqlite.c")
|
||
(declare-function sqlite-next "sqlite.c")
|
||
(declare-function sqlite-more-p "sqlite.c")
|
||
(declare-function sqlite-select "sqlite.c")
|
||
(declare-function sqlite-open "sqlite.c")
|
||
(declare-function sqlite-load-extension "sqlite.c")
|
||
(declare-function sqlite-version "sqlite.c")
|
||
|
||
(ert-deftest sqlite-select ()
|
||
(skip-unless (sqlite-available-p))
|
||
(let ((db (sqlite-open)))
|
||
(should (eq (type-of db) 'sqlite))
|
||
(should (sqlitep db))
|
||
(should-not (sqlitep 'foo))
|
||
|
||
(should
|
||
(zerop
|
||
(sqlite-execute
|
||
db "create table if not exists test1 (col1 text, col2 integer, col3 float, col4 blob)")))
|
||
|
||
(should-error
|
||
(sqlite-execute
|
||
db "insert into test1 (col1, col2, col3, col4) values ('foo', 2, 9.45, 'bar', 'zot')"))
|
||
|
||
(should
|
||
(=
|
||
(sqlite-execute
|
||
db "insert into test1 (col1, col2, col3, col4) values ('foo', 2, 9.45, 'bar')")
|
||
1))
|
||
|
||
(should
|
||
(equal
|
||
(sqlite-select db "select * from test1" nil 'full)
|
||
'(("col1" "col2" "col3" "col4") ("foo" 2 9.45 "bar"))))))
|
||
|
||
(ert-deftest sqlite-set ()
|
||
(skip-unless (sqlite-available-p))
|
||
(let ((db (sqlite-open))
|
||
set)
|
||
(should
|
||
(zerop
|
||
(sqlite-execute
|
||
db "create table if not exists test1 (col1 text, col2 integer)")))
|
||
|
||
(should
|
||
(=
|
||
(sqlite-execute db "insert into test1 (col1, col2) values ('foo', 1)")
|
||
1))
|
||
(should
|
||
(=
|
||
(sqlite-execute db "insert into test1 (col1, col2) values ('bar', 2)")
|
||
1))
|
||
|
||
(setq set (sqlite-select db "select * from test1" nil 'set))
|
||
(should (sqlitep set))
|
||
(should (sqlite-more-p set))
|
||
(should (equal (sqlite-next set)
|
||
'("foo" 1)))
|
||
(should (equal (sqlite-next set)
|
||
'("bar" 2)))
|
||
(should-not (sqlite-next set))
|
||
(should-not (sqlite-more-p set))
|
||
(sqlite-finalize set)
|
||
(should-error (sqlite-next set))))
|
||
|
||
(ert-deftest sqlite-chars ()
|
||
(skip-unless (sqlite-available-p))
|
||
(let (db)
|
||
(setq db (sqlite-open))
|
||
(sqlite-execute
|
||
db "create table if not exists test2 (col1 text, col2 integer)")
|
||
(sqlite-execute
|
||
db "insert into test2 (col1, col2) values ('fóo', 3)")
|
||
(sqlite-execute
|
||
db "insert into test2 (col1, col2) values ('fóo', 3)")
|
||
(sqlite-execute
|
||
db "insert into test2 (col1, col2) values ('fo', 4)")
|
||
(should
|
||
(equal (sqlite-select db "select * from test2" nil 'full)
|
||
'(("col1" "col2") ("fóo" 3) ("fóo" 3) ("fo" 4))))))
|
||
|
||
(ert-deftest sqlite-numbers ()
|
||
(skip-unless (sqlite-available-p))
|
||
(let (db)
|
||
(setq db (sqlite-open))
|
||
(sqlite-execute
|
||
db "create table if not exists test3 (col1 integer)")
|
||
(let ((big (expt 2 50))
|
||
(small (expt 2 10)))
|
||
(sqlite-execute db (format "insert into test3 values (%d)" small))
|
||
(sqlite-execute db (format "insert into test3 values (%d)" big))
|
||
(should
|
||
(equal
|
||
(sqlite-select db "select * from test3")
|
||
(list (list small) (list big)))))))
|
||
|
||
(ert-deftest sqlite-param ()
|
||
(skip-unless (sqlite-available-p))
|
||
(let (db)
|
||
(setq db (sqlite-open))
|
||
(sqlite-execute
|
||
db "create table if not exists test4 (col1 text, col2 number)")
|
||
(sqlite-execute db "insert into test4 values (?, ?)" (list "foo" 1))
|
||
(should
|
||
(equal
|
||
(sqlite-select db "select * from test4 where col2 = ?" '(1))
|
||
'(("foo" 1))))
|
||
(should
|
||
(equal
|
||
(sqlite-select db "select * from test4 where col2 = ?" [1])
|
||
'(("foo" 1))))))
|
||
|
||
(ert-deftest sqlite-binary ()
|
||
(skip-unless (sqlite-available-p))
|
||
(let (db)
|
||
(setq db (sqlite-open))
|
||
(sqlite-execute
|
||
db "create table if not exists test5 (col1 text, col2 number)")
|
||
(let ((string (with-temp-buffer
|
||
(set-buffer-multibyte nil)
|
||
(insert 0 1 2)
|
||
(buffer-string))))
|
||
(should-not (multibyte-string-p string))
|
||
(sqlite-execute
|
||
db "insert into test5 values (?, ?)" (list string 2))
|
||
(let ((out (caar
|
||
(sqlite-select db "select col1 from test5 where col2 = 2"))))
|
||
(should (equal out string))))))
|
||
|
||
(ert-deftest sqlite-different-dbs ()
|
||
(skip-unless (sqlite-available-p))
|
||
(let (db1 db2)
|
||
(setq db1 (sqlite-open))
|
||
(setq db2 (sqlite-open))
|
||
(sqlite-execute
|
||
db1 "create table if not exists test6 (col1 text, col2 number)")
|
||
(sqlite-execute
|
||
db2 "create table if not exists test6 (col1 text, col2 number)")
|
||
(sqlite-execute
|
||
db1 "insert into test6 values (?, ?)" '("foo" 2))
|
||
(should (sqlite-select db1 "select * from test6"))
|
||
(should-not (sqlite-select db2 "select * from test6"))))
|
||
|
||
(ert-deftest sqlite-close-dbs ()
|
||
(skip-unless (sqlite-available-p))
|
||
(let (db)
|
||
(setq db (sqlite-open))
|
||
(sqlite-execute
|
||
db "create table if not exists test6 (col1 text, col2 number)")
|
||
(sqlite-execute db "insert into test6 values (?, ?)" '("foo" 2))
|
||
(should (sqlite-select db "select * from test6"))
|
||
(sqlite-close db)
|
||
(should-error (sqlite-select db "select * from test6"))))
|
||
|
||
(ert-deftest sqlite-load-extension ()
|
||
(skip-unless (sqlite-available-p))
|
||
(skip-unless (fboundp 'sqlite-load-extension))
|
||
(let (db)
|
||
(setq db (sqlite-open))
|
||
(should-error
|
||
(sqlite-load-extension db "/usr/lib/sqlite3/notpcre.so"))
|
||
(should-error
|
||
(sqlite-load-extension db "/usr/lib/sqlite3/n"))
|
||
(should-error
|
||
(sqlite-load-extension db "/usr/lib/sqlite3/"))
|
||
(should-error
|
||
(sqlite-load-extension db "/usr/lib/sqlite3"))
|
||
(if (eq system-type 'windows-nt)
|
||
(should
|
||
(eq (sqlite-load-extension db "/usr/lib/sqlite3/pcre.dll")
|
||
(file-readable-p "/usr/lib/sqlite3/pcre.dll")))
|
||
(should
|
||
(eq (sqlite-load-extension db "/usr/lib/sqlite3/pcre.so")
|
||
(file-readable-p "/usr/lib/sqlite3/pcre.so"))))
|
||
|
||
(should-error
|
||
(sqlite-load-extension
|
||
db "/usr/lib/x86_64-linux-gnu/libsqlite3_mod_notcsvtable.so"))
|
||
(should-error
|
||
(sqlite-load-extension
|
||
db "/usr/lib/x86_64-linux-gnu/libsqlite3_mod_csvtablen.so"))
|
||
(should-error
|
||
(sqlite-load-extension
|
||
db "/usr/lib/x86_64-linux-gnu/libsqlite3_mod_csvtable"))
|
||
(if (eq system-type 'windows-nt)
|
||
(should
|
||
(eq (sqlite-load-extension db "/usr/lib/sqlite3/csvtable.dll")
|
||
(file-readable-p "/usr/lib/sqlite3/csvtable.dll")))
|
||
(should
|
||
(eq (sqlite-load-extension db "/usr/lib/x86_64-linux-gnu/libsqlite3_mod_csvtable.so")
|
||
(file-readable-p "/usr/lib/x86_64-linux-gnu/libsqlite3_mod_csvtable.so"))))))
|
||
|
||
(ert-deftest sqlite-blob ()
|
||
(skip-unless (sqlite-available-p))
|
||
(let (db)
|
||
(progn
|
||
(setq db (sqlite-open))
|
||
(sqlite-execute
|
||
db "create table if not exists test10 (col1 text, col2 blob, col3 numbre)")
|
||
(let ((string (with-temp-buffer
|
||
(set-buffer-multibyte nil)
|
||
(insert 0 1 2)
|
||
(buffer-string))))
|
||
(should-not (multibyte-string-p string))
|
||
(sqlite-execute
|
||
db "insert into test10 values (?, ?, 1)"
|
||
(list string
|
||
(propertize string
|
||
'coding-system 'binary)))
|
||
(cl-destructuring-bind
|
||
(c1 c2 _)
|
||
(car (sqlite-select db "select * from test10 where col3 = 1"))
|
||
(should (equal c1 string))
|
||
(should (equal c2 string))
|
||
(should (multibyte-string-p c1))
|
||
(should-not (multibyte-string-p c2)))))))
|
||
|
||
(ert-deftest sqlite-returning ()
|
||
(skip-unless (sqlite-available-p))
|
||
(skip-unless (version<= "3.35" (sqlite-version)))
|
||
(let (db)
|
||
(progn
|
||
(setq db (sqlite-open))
|
||
(sqlite-execute db "CREATE TABLE people1 (people_id INTEGER PRIMARY KEY, first TEXT, last TEXT)")
|
||
(should (null (sqlite-select db "select * from people1")))
|
||
(should
|
||
(equal
|
||
(sqlite-execute db "INSERT INTO people1 (first, last) values (?, ?) RETURNING people_id, first"
|
||
'("Joe" "Doe"))
|
||
'((1 "Joe")))))))
|
||
|
||
;;; sqlite-tests.el ends here
|