X-Git-Url: http://git.kpe.io/?a=blobdiff_plain;f=sql%2Fexpressions.lisp;h=45d4631b5eaccf70b878b49a6b79907b9d4930c4;hb=ef93cbe09e01bb540651e6719eb4e8fe7ebeefd0;hp=746ed001ee608232be7f24e6f78d9591b62ac4bc;hpb=2a0e0fdaa59c9b431bad7ef35cab891f831a9d3b;p=clsql.git diff --git a/sql/expressions.lisp b/sql/expressions.lisp index 746ed00..45d4631 100644 --- a/sql/expressions.lisp +++ b/sql/expressions.lisp @@ -1,8 +1,6 @@ ;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; -;;;; $Id$ -;;;; ;;;; Classes defining SQL expressions and methods for formatting the ;;;; appropriate SQL commands. ;;;; @@ -194,15 +192,25 @@ sql `(make-instance 'sql-ident-table :name ',name :table-alias ',alias))) +(defun special-char-p (s) + "Check if a string has any special characters" + (loop for char across s + thereis (find char '(#\space #\, #\. #\! #\@ #\# #\$ #\% + #\^ #\& #\* #\| #\( #\) #\- #\+)))) + (defmethod output-sql ((expr sql-ident-table) database) (with-slots (name alias) expr - (etypecase name - (string - (format *sql-stream* "~s" (sql-escape name))) - (symbol - (write-string (sql-escape name) *sql-stream*))) - (when alias - (format *sql-stream* " ~s" alias))) + (flet ((p (s) ;; the etypecase is in sql-escape too + (let ((sym? (symbolp s)) + (s (sql-escape s))) + (format *sql-stream* + (if (and sym? (not (special-char-p s))) + "~a" "~s") + s)))) + (p name) + (when alias + (princ #\space *sql-stream*) + (p alias)))) t) (defmethod output-sql-hash-key ((expr sql-ident-table) database) @@ -242,19 +250,34 @@ ;; should do arity checking of subexpressions (defmethod output-sql ((expr sql-relational-exp) database) - (with-slots (operator sub-expressions) - expr - (let ((subs (if (consp (car sub-expressions)) - (car sub-expressions) - sub-expressions))) - (write-char #\( *sql-stream*) - (do ((sub subs (cdr sub))) - ((null (cdr sub)) (output-sql (car sub) database)) - (output-sql (car sub) database) - (write-char #\Space *sql-stream*) - (output-sql operator database) - (write-char #\Space *sql-stream*)) - (write-char #\) *sql-stream*))) + (with-slots (operator sub-expressions) expr + ;; we do this as two runs so as not to emit confusing superflous parentheses + ;; The first loop renders all the child outputs so that we can skip anding with + ;; empty output (which causes sql errors) + ;; the next loop simply emits each sub-expression with the appropriate number of + ;; parens and operators + (flet ((trim (sub) + (string-trim +whitespace-chars+ + (with-output-to-string (*sql-stream*) + (output-sql sub database))))) + (let ((str-subs (loop for sub in sub-expressions + for str-sub = (trim sub) + when (and str-sub (> (length str-sub) 0)) + collect str-sub))) + (case (length str-subs) + (0 nil) + (1 (write-string (first str-subs) *sql-stream*)) + (t + (write-char #\( *sql-stream*) + (write-string (first str-subs) *sql-stream*) + (loop for str-sub in (rest str-subs) + do + (write-char #\Space *sql-stream*) + (output-sql operator database) + (write-char #\Space *sql-stream*) + (write-string str-sub *sql-stream*)) + (write-char #\) *sql-stream*)) + )))) t) (defclass sql-upcase-like (sql-relational-exp) @@ -967,6 +990,7 @@ uninclusive, and the args from that keyword to the end." (cons (symbol-name-default-case "UNSIGNED") "UNSIGNED") (cons (symbol-name-default-case "ZEROFILL") "ZEROFILL") (cons (symbol-name-default-case "AUTO-INCREMENT") "AUTO_INCREMENT") + (cons (symbol-name-default-case "DEFAULT") "DEFAULT") (cons (symbol-name-default-case "UNIQUE") "UNIQUE"))) (defmethod database-constraint-statement (constraint-list database) @@ -986,6 +1010,9 @@ uninclusive, and the args from that keyword to the end." :message (format nil "unsupported column constraint '~A'" constraint)) (setq string (concatenate 'string string (cdr output)))) + (when (equal (symbol-name (car constraint)) "DEFAULT") + (setq constraint (cdr constraint)) + (setq string (concatenate 'string string " " (car constraint)))) (if (< 1 (length constraint)) (setq string (concatenate 'string string " "))))))))