branch: elpa/emacsql commit 4db068920d2f2e0b0812e8789ae59f62c4207e97 Author: Christopher Wellons <well...@nullprogram.com> Commit: Christopher Wellons <well...@nullprogram.com>
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