Next: , Previous: qcons extension, Up: Query Construction


9.4 Quoting

Ideally, the tree construction procedures in the following section would be powerful enough to do the right thing given a well-formed prefix-style expression. However, sometimes reality intrudes and you need to craft SQL directly. In these cases, it still may be a good idea to use the tree construction procedures for most of the work and tweak only the small parts that need it. This selective use of varying expression construction approaches is known prosaically as quoting.

— Procedure: sql-pre string

Return string marked as preformatted. This inhibits certain types of processing when passed through the other procedures defined in this module. Repeated calls do not nest.

— Procedure: sql-pre? string

Return #t if string is marked as preformatted.

— Procedure: sql-unpre string

Return string, undoing the effect of sql-pre.

— Procedure: sql-quote s

Return a new string made by doubling each single-quote in string s, and prefixing and suffixing with single-quote. The returned string is marked by sql-pre. For example:

          (define bef "ab'cd")
          (define aft (sql-quote bef))
          aft ⇒ "'ab''cd'"
          (map string-length (list bef aft)) ⇒ (5 8)
          (map sql-pre? (list bef aft)) ⇒ (#f #t)

Note that this procedure used to return internal single-quote characters prefixed with a backslash, which is acceptable by PostgreSQL (given certain runtime parameter settings), but not standards conforming. The current (as of Guile-PG 0.38) behavior is standards-conforming, upward compatible, and avoids futzing with the runtime parameters.

— Procedure: idquote id

Return the quoted identifier form of id, a string or symbol. The returned string is marked by sql-pre. For example:

          (define (try x)
            (display (idquote x))
            (newline))
          
          (try 'abcd)       -| "abcd"
          (try 'ab.cd)      -| "ab"."cd"
          (try 'abcd[xyz])  -| "abcd"[xyz]
          (try 'ab.cd[xyz]) -| "ab"."cd"[xyz]
          
          ;; Special case: only * after dot.
          (try 'ab.*)       -| "ab".*

Note that PostgreSQL case-folding for non-quoted identifiers is nonstandard. The PostgreSQL documentation says:

If you want to write portable applications you are advised to always quote a particular name or never quote it. Section 4.1.1, Identifiers and Keywords

The qcons module (see Query Construction) uses idquote internally extensively.

9.5 Standard Conforming Strings

Starting with PostgreSQL 8.2, there is a configuration file and runtime parameter standard_conforming_strings that controls how strictly the server parses SQL string syntax. When its value is on, strings that include the ‘\’ (backslash) character must be prefixed with ‘E’. Even when it is off, the server may emit a warning, anyway. To avoid such unpleasantness, Guile-PG provides sql-quote-auto-E?.

— Fluid: sql-quote-auto-E?

When non-#f, sql-quote will prefix a ‘E’ if it detects any ‘\’ (backslash) characters in its arg. For example:

          (define (e.g.)
            (display (sql-quote "a\\b")))
          
          (fluid-ref sql-quote-auto-E?)
          ⇒ #f
          
          (e.g.)
          -| 'a\b'
          
          (with-fluids ((sql-quote-auto-E? #t))
            (e.g.))
          -| E'a\b'

If there are no backslash characters, this has no effect.

The typical way to use this is to set the fluid soon after you make the connection and forget about it:

     (and (pg-parameter-status CONN 'standard_conforming_strings)
          ;; Don't bother checking the parameter value;
          ;; enable functionality unconditionally.
          (fluid-set! sql-quote-auto-E? #t))

This can get hairy if you maintain more than one connection at a time to servers with mixed support for standard_conforming_strings, however (i.e., pre-8.2 and 8.2+ together). In that case, it is better to use with-fluids to enable the functionality completely dynamically.