summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--python/skytools/quoting.py44
1 files changed, 43 insertions, 1 deletions
diff --git a/python/skytools/quoting.py b/python/skytools/quoting.py
index 96b0b022..0ce50080 100644
--- a/python/skytools/quoting.py
+++ b/python/skytools/quoting.py
@@ -4,6 +4,13 @@
import psycopg, urllib, re
+__all__ = [
+ "quote_literal", "quote_copy", "quote_bytea_raw",
+ "quote_bytea_literal", "quote_bytea_copy", "quote_statement",
+ "quote_ident", "quote_fqident", "quote_json",
+ "db_urlencode", "db_urldecode", "unescape", "unescape_copy"
+]
+
#
# SQL quoting
#
@@ -49,7 +56,7 @@ def quote_bytea_copy(s):
return quote_copy(quote_bytea_raw(s))
def quote_statement(sql, dict):
- """Quote whose statement.
+ """Quote whole statement.
Data values are taken from dict.
"""
@@ -58,6 +65,41 @@ def quote_statement(sql, dict):
xdict[k] = quote_literal(v)
return sql % xdict
+# reserved keywords
+_ident_kwmap = {
+"all":1, "analyse":1, "analyze":1, "and":1, "any":1, "array":1, "as":1,
+"asc":1, "asymmetric":1, "both":1, "case":1, "cast":1, "check":1, "collate":1,
+"column":1, "constraint":1, "create":1, "current_date":1, "current_role":1,
+"current_time":1, "current_timestamp":1, "current_user":1, "default":1,
+"deferrable":1, "desc":1, "distinct":1, "do":1, "else":1, "end":1, "except":1,
+"false":1, "for":1, "foreign":1, "from":1, "grant":1, "group":1, "having":1,
+"in":1, "initially":1, "intersect":1, "into":1, "leading":1, "limit":1,
+"localtime":1, "localtimestamp":1, "new":1, "not":1, "null":1, "off":1,
+"offset":1, "old":1, "on":1, "only":1, "or":1, "order":1, "placing":1,
+"primary":1, "references":1, "returning":1, "select":1, "session_user":1,
+"some":1, "symmetric":1, "table":1, "then":1, "to":1, "trailing":1, "true":1,
+"union":1, "unique":1, "user":1, "using":1, "when":1, "where":1,
+}
+
+_ident_bad = re.compile(r"[^a-z0-9_]")
+def quote_ident(s):
+ """Quote SQL identifier.
+
+ If is checked against weird symbols and keywords.
+ """
+
+ if _ident_bad.search(s) or s in _ident_kwmap:
+ s = '"%s"' % s.replace('"', '""')
+ return s
+
+def quote_fqident(s):
+ """Quote fully qualified SQL identifier.
+
+ The '.' is taken as namespace separator and
+ all parts are quoted separately
+ """
+ return '.'.join(map(quote_ident, s.split('.')))
+
#
# quoting for JSON strings
#