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 string

Return a new string made by doubling each single-quote in string, and prefixing and suffixing with single-quote. The returned string will also have backslash characters #\\ replaced with \134 (i.e., the string of four characters: #\\, #\1, #\3, #\4). The returned string is marked by sql-pre. For example:

          (define bef "ab'c\\d")
          (define aft (sql-quote bef))
          (define (both proc)
            (map proc (list bef aft)))
          
          (display aft)        -| 'ab''c\134d'
          (both string-length) ⇒ (6 12)
          (both sql-pre?)      ⇒ (#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\134b'
          
          (with-fluids ((sql-quote-auto-E? #t))
            (e.g.))
          -| E'a\134b'

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.

9.6 string external representation

Guile 1.8 and later represent certain octets in the xrep, or external representation, of a string with \xXX, e.g., \x07 for #\bel. PostgreSQL 7.4 and 8.0 do not recognize \xXX as valid syntax in a literal string, which is a problem if you need to connect to them.

But even for PostgreSQL 8.1 and later, which accepts \xXX as an octet with hex value XX, a problem arises when there is a mix of contiguous raw and \x representations, intended to represent (for instance) a UTF-8 encoded character. It seems1 Guile

  - 1.4 DTRT by doing nothing (mu power!);
  - 1.6 likewise is blissfully unperturbing;
  - 1.8 fails by \x-escaping inconsistently;
  - 2.0 doesn't have this problem.

To avoid both problems, use string-xrep.

— Procedure: string-xrep string

Return the external representation of string, guaranteed to not have \x-escape sequences. Specifically, the first and last characters are double-quote #\", and internal #\\ and #\" are backslash-escaped. Characters that normally have an xrep with \x are instead passed straight through. For some Guile versions, this behavior is identical to object->string.


Footnotes

[1] The survey and its results are in the ‘guile-user’ archive:
http://lists.gnu.org/archive/html/guile-user/2012-01/msg00114.html.