1. You are missing such operators like || and && (former is string concatenation, latter is tests overlapping geometric objects).
There are also a. math: !, !!, #, >>, <<.
b. geometric: ##, @@, @-@, ~=, <->, &<, &>, <<|, |>>, &<|, |&>, <^, >^, ?#, ?|, ?-|, ?||, @>, <@.
c. network: <<=, >>=.
?| is both binary and unary operator, ! is postfix (but is equivalent to prefix !!, so you may define :! that expands to prefix !! or just :!! that expands to !!).
There are also another operators like @, but they have functions-substitutions (@ x <=> abs(x)).
psql's command \do (describe operators) also lists other operators.
2. As PSQL allows defining own operators, I think it worth exporting s-sql::def-infix-ops or creating some more flexible user macro (one might prefer to use :concat instead of :||).
With such facility you don't need to define such rare-used operators like @-@ and ?-|, allowing user to define them.
Hey Ivan,
- You are missing such operators like || and && (former is string concatenation, latter is tests overlapping geometric objects).
You've probably noticed how easy it is to add operators to S-SQL. Patches defining additional operators that are commonly used are welcome -- || would be a good candidate.
- As PSQL allows defining own operators, I think it worth exporting s-sql::def-infix-ops or creating some more flexible user macro (one might prefer to use :concat instead of :||).
I very much agree. Wanna write a patch? ;)
Cheers, Marijn
On 10077 day of my life Marijn Haverbeke wrote:
... a patch?
Comment string may require full rewriting.
diff -rN -u old-postmodern/postmodern/package.lisp new-postmodern/postmodern/package.lisp --- old-postmodern/postmodern/package.lisp 2008-01-07 20:38:27.000000000 +0600 +++ new-postmodern/postmodern/package.lisp 2008-01-07 20:38:27.000000000 +0600 @@ -25,6 +25,7 @@ #:smallint #:bigint #:numeric #:real #:double-precision #:bytea #:text #:varchar #:*escape-sql-names-p* #:sql-escape-string + #:def-infix-ops
;; Condition type from cl-postgres #:database-error #:database-error-message #:database-error-code diff -rN -u old-postmodern/s-sql/s-sql.lisp new-postmodern/s-sql/s-sql.lisp --- old-postmodern/s-sql/s-sql.lisp 2008-01-07 20:38:27.000000000 +0600 +++ new-postmodern/s-sql/s-sql.lisp 2008-01-07 20:38:27.000000000 +0600 @@ -16,6 +16,7 @@ #:to-sql-name #:sql-ize #:*escape-sql-names-p* + #:def-infix-ops #:sql #:sql-compile #:enable-s-sql-syntax)) @@ -373,21 +374,58 @@ (destructuring-bind ,arglist ,args-name ,@body))))
-(defun expand-infix-op (operator allow-unary args) - (if (cdr args) - `("(" ,@(sql-expand-list args (strcat " " operator " ")) ")") - (if allow-unary - (sql-expand (first args)) - (error "SQL operator ~A takes at least two arguments." operator)))) - -(defmacro def-infix-ops (allow-unary &rest ops) +(defun expand-infix-op (operator class args) + (declare (type (member t :both nil) class)) + (cond + ((cdr args) + `("(" ,@(sql-expand-list args (strcat " " operator " ")) ")")) + ((eq class t) + (sql-expand (first args))) + ((eq class :both) + `(,operator "(" ,@(sql-expand (first args)) ")")) + (t + (error "SQL operator ~A takes at least two arguments." operator)))) + +(defmacro def-infix-ops (class &rest ops) + (declare (type (member t :both nil) class)) + "Define infix operators. +CLASS may be either T, :BOTH or NIL. + + 1. T. S-SQL operators may be both binary and unary, but unary form + is equivalent to the only argument itself (e.g. + (:AND condition) => "condition"). + + 2. :BOTH. S-SQL operators may be both binary and unary, but unlike + T, operator is kept before the argument in unary form. Example + is PosgreSQL's ?| operator: + (def-infix-ops :both :?\|) + (:?\| a) => "?|(a)" + (:?\| a b) => "a ?| b". + + 3. NIL. Operator is binary only. + +OPS is a list of operator designators. There are two kinds of +operator designators: + + 1. A keyword. Downcased symbol value of the keword is used as SQL + name of operator. + + 2. Two-element list: (KEYWORD STRING). String is used as SQL name + of operator, and KEYWORD is S-SQL name of operator. + Example: (:concat "||")." `(progn ,@(mapcar (lambda (op) - `(defmethod expand-sql-op ((op (eql ,op)) args) - (expand-infix-op ,(string-downcase (symbol-name op)) ,allow-unary args))) + (when (keywordp op) + (setf op (list op (string-downcase (symbol-name op))))) + (let ((kwd (first op)) + (txt (second op))) + `(defmethod expand-sql-op ((op (eql ,kwd)) args) + (expand-infix-op ,txt ,class args)))) ops))) -(def-infix-ops t :+ :* :& :||| :and :or :union) -(def-infix-ops nil := :/ :!= :< :> :<= :>= :^ :intersect :except :~* :!~ :!~* :like :ilike) + +(def-infix-ops t :+ :* :& :||| :and :or :union :|| (:concat "||")) +(def-infix-ops nil := :/ :!= :< :> :<= :>= :^ :intersect :except :~* :!~ :!~* + :like :ilike :&& :% :# :<< :>>)
(def-sql-op :- (first &rest rest) (if rest
On 10077 day of my life Ivan Boldyrev wrote:
On 10077 day of my life Marijn Haverbeke wrote:
... a patch?
+(defmacro def-infix-ops (class &rest ops)
BTW: names of definition macros with minus in their names are traditionally started with define, not def (define-modify-macro, define-method-combination, but defvar, defun, defmacro). So proper name for public macro should be define-infix-ops.
Ivan,
I pushed patches making a register-sql-operators macro available and changing the way strings are passed to strcat. Take a look.
Cheers, Marijn
On 10079 day of my life Marijn Haverbeke wrote:
I pushed patches making a register-sql-operators macro available and changing the way strings are passed to strcat. Take a look.
Excellent, but you forgot to insert comma at symbol NAME in a :unary branch of MAKE-EXPANDER.
====================================================================== I tried to send appropriate one-line patch with darcs mail, but darcs doesn't allow sending only this particular patch. This is not a first time I stuck into such darcs' behaviour, and this is one of reasons I dislike this VCS.
$ darcs send -u -i -o comma.patch ../postmodern Creating patch to "../postmodern"...
Tue Jan 8 15:21:32 NOVT 2008 Ivan Boldyrev lispnik@gmail.com * Enchance infix operators definition macro. def-infix-ops is renamed to define-infix-ops, and its first argument now accepts :both. expand-infix-op is changed accordingly. Some new infix operators are added. Shall I send this patch? (1/4) [ynWvpxqadjk], or ? for help: n
Tue Jan 8 15:22:01 NOVT 2008 Ivan Boldyrev lispnik@gmail.com * Make SQL generation faster. Shall I send this patch? (2/4) [ynWvpxqadjk], or ? for help: n You don't want to send any patches, and that's fine with me!
======================================================================
Hey Ivan,
That's what I get for making 'trivial' changes just before committing something. I pushed a fix. The reason darcs doesn't prompt you to send that patch is (I think) that you have a bunch of other patches in your repository that are not in mine, and this change depends on one of those.
Cheers, Marijn
postmodern-devel@common-lisp.net