branch: elpa/emacsql
commit 4db068920d2f2e0b0812e8789ae59f62c4207e97
Author: Christopher Wellons <[email protected]>
Commit: Christopher Wellons <[email protected]>
Provide MySQL front-end.
---
README.md | 2 +-
emacsql-mysql.el | 71 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 72 insertions(+), 1 deletion(-)
diff --git a/README.md b/README.md
index d9236aded4..da19b75656 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
# Emacsql
Emacsql is a high-level Emacs Lisp front-end for SQLite (primarily),
-PostgreSQL, and potentially other SQL databases.
+PostgreSQL, MySQL, and potentially other SQL databases.
It is currently a work-in-progress (around 90% complete).
diff --git a/emacsql-mysql.el b/emacsql-mysql.el
new file mode 100644
index 0000000000..6f228ba83f
--- /dev/null
+++ b/emacsql-mysql.el
@@ -0,0 +1,71 @@
+;;; emacsql-mysql.el --- front-end for MySQL -*- lexical-binding: t; -*-
+
+;;; Code:
+
+(require 'cl-lib)
+(require 'eieio)
+(require 'emacsql)
+
+(defvar emacsql-mysql-executable "mysql"
+ "Path to the mysql command line executable.")
+
+(defvar emacsql-mysql-sentinel "--------------\n\n--------------\n\n"
+ "What MySQL will print when it has completed its output.")
+
+(defclass emacsql-mysql-connection (emacsql-connection)
+ ((dbname :reader emacsql-psql-dbname :initarg :dbname)
+ (types :allocation :class
+ :reader emacsql-types
+ :initform '((integer "BIGINT")
+ (float "DOUBLE")
+ (object "LONGTEXT")
+ (nil "LONGTEXT")))))
+
+(defun emacsql-mysql (dbname)
+ (let* ((buffer (generate-new-buffer " *emacsql-mysql*"))
+ (mysql emacsql-mysql-executable)
+ (process (start-process "emacsql-mysql" buffer mysql
+ "-rfBNL" "--skip-pager" dbname))
+ (connection (make-instance 'emacsql-mysql-connection
+ :process process
+ :dbname dbname)))
+ (setf (process-sentinel process)
+ (lambda (proc _) (kill-buffer (process-buffer proc))))
+ (emacsql-register connection)))
+
+(defmethod emacsql-close ((connection emacsql-mysql-connection))
+ (let ((process (emacsql-process connection)))
+ (when (process-live-p process)
+ (process-send-eof process))))
+
+(defmethod emacsql-send-message ((connection emacsql-mysql-connection) message)
+ (let ((process (emacsql-process connection)))
+ (process-send-string process message)
+ (process-send-string process "\\c\\p\n")))
+
+(defmethod emacsql-waiting-p ((connection emacsql-mysql-connection))
+ (let ((length (length emacsql-mysql-sentinel)))
+ (with-current-buffer (emacsql-buffer connection)
+ (and (>= (buffer-size) length)
+ (progn (setf (point) (- (point-max) length))
+ (looking-at emacsql-mysql-sentinel))))))
+
+(defmethod emacsql-parse ((connection emacsql-mysql-connection))
+ (with-current-buffer (emacsql-buffer connection)
+ (let ((standard-input (current-buffer)))
+ (setf (point) (point-min))
+ (when (looking-at "ERROR")
+ (let ((beg (line-beginning-position))
+ (end (line-end-position)))
+ (signal 'emacsql-error (list (buffer-substring beg end)))))
+ (cl-loop until (looking-at emacsql-mysql-sentinel)
+ collect (read) into row
+ when (looking-at "\n")
+ collect row into rows
+ and do (setf row ())
+ and do (forward-char)
+ finally (cl-return rows)))))
+
+(provide 'emacsql-mysql)
+
+;;; emacsql-mysql.el ends here