summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLukáš Lalinský2011-10-16 11:20:31 +0000
committerLukáš Lalinský2011-10-16 11:24:21 +0000
commit081613f9001277579efb31617706b3898eec2f2a (patch)
tree8d725db116bc4b353068e5d3ec8f73bd60d2bbd6
parent21c478d2eb241e049452f13e4f8191dce4cea5a9 (diff)
Add an option to split the key and value fields
-rw-r--r--python/skytools/parsing.py67
1 files changed, 46 insertions, 21 deletions
diff --git a/python/skytools/parsing.py b/python/skytools/parsing.py
index cf491417..5f6ab9ad 100644
--- a/python/skytools/parsing.py
+++ b/python/skytools/parsing.py
@@ -69,7 +69,7 @@ class _logtriga_parser:
for typ, tok in sql_tokenizer(sql, ignore_whitespace = True):
yield tok
- def parse_insert(self, tk, fields, values):
+ def parse_insert(self, tk, fields, values, key_fields, key_values):
"""Handler for inserts."""
# (col1, col2) values ('data', null)
if tk.next() != "(":
@@ -96,7 +96,7 @@ class _logtriga_parser:
t = tk.next()
raise Exception("expected EOF, got " + repr(t))
- def parse_update(self, tk, fields, values):
+ def parse_update(self, tk, fields, values, key_fields, key_values):
"""Handler for updates."""
# col1 = 'data1', col2 = null where pk1 = 'pk1' and pk2 = 'pk2'
while 1:
@@ -104,7 +104,6 @@ class _logtriga_parser:
if tk.next() != "=":
raise Exception("syntax error")
values.append(tk.next())
-
t = tk.next()
if t == ",":
continue
@@ -114,30 +113,35 @@ class _logtriga_parser:
raise Exception("syntax error, expected WHERE or , got "+repr(t))
while 1:
fld = tk.next()
- fields.append(fld)
+ key_fields.append(fld)
self.pklist.append(fld)
if tk.next() != "=":
raise Exception("syntax error")
- values.append(tk.next())
+ key_values.append(tk.next())
t = tk.next()
if t.lower() != "and":
raise Exception("syntax error, expected AND got "+repr(t))
- def parse_delete(self, tk, fields, values):
+ def parse_delete(self, tk, fields, values, key_fields, key_values):
"""Handler for deletes."""
# pk1 = 'pk1' and pk2 = 'pk2'
while 1:
fld = tk.next()
- fields.append(fld)
+ key_fields.append(fld)
self.pklist.append(fld)
if tk.next() != "=":
raise Exception("syntax error")
- values.append(tk.next())
+ key_values.append(tk.next())
t = tk.next()
if t.lower() != "and":
raise Exception("syntax error, expected AND, got "+repr(t))
- def parse_sql(self, op, sql, pklist=None):
+ def _create_dbdict(self, fields, values):
+ fields = [skytools.unquote_ident(f) for f in fields]
+ values = [skytools.unquote_literal(f) for f in values]
+ return skytools.dbdict(zip(fields, values))
+
+ def parse_sql(self, op, sql, pklist=None, splitkeys=False):
"""Main entry point."""
if pklist is None:
self.pklist = []
@@ -146,26 +150,31 @@ class _logtriga_parser:
tk = self.tokenizer(sql)
fields = []
values = []
+ key_fields = []
+ key_values = []
try:
if op == "I":
- self.parse_insert(tk, fields, values)
+ self.parse_insert(tk, fields, values, key_fields, key_values)
elif op == "U":
- self.parse_update(tk, fields, values)
+ self.parse_update(tk, fields, values, key_fields, key_values)
elif op == "D":
- self.parse_delete(tk, fields, values)
+ self.parse_delete(tk, fields, values, key_fields, key_values)
raise Exception("syntax error")
except StopIteration:
# last sanity check
- if len(fields) == 0 or len(fields) != len(values):
+ if (len(fields) + len(key_fields) == 0 or
+ len(fields) != len(values) or
+ len(key_fields) != len(key_values)):
raise Exception("syntax error, fields do not match values")
- fields = [skytools.unquote_ident(f) for f in fields]
- values = [skytools.unquote_literal(f) for f in values]
- return skytools.dbdict(zip(fields, values))
+ if splitkeys:
+ return (self._create_dbdict(key_fields, key_values),
+ self._create_dbdict(fields, values))
+ return self._create_dbdict(fields + key_fields, values + key_values)
-def parse_logtriga_sql(op, sql):
- return parse_sqltriga_sql(op, sql)
+def parse_logtriga_sql(op, sql, splitkeys=False):
+ return parse_sqltriga_sql(op, sql, splitkeys=splitkeys)
-def parse_sqltriga_sql(op, sql, pklist=None):
+def parse_sqltriga_sql(op, sql, pklist=None, splitkeys=False):
"""Parse partial SQL used by pgq.sqltriga() back to data values.
Parser has following limitations:
@@ -173,7 +182,7 @@ def parse_sqltriga_sql(op, sql, pklist=None):
- Does not support dollar quoting.
- Does not support complex expressions anywhere. (hashtext(col1) = hashtext(val1))
- WHERE expression must not contain IS (NOT) NULL
- - Does not support updating pk value.
+ - Does not support updating pk value, unless you use the splitkeys parameter.
Returns dict of col->data pairs.
@@ -188,8 +197,24 @@ def parse_sqltriga_sql(op, sql, pklist=None):
Delete event:
>>> parse_logtriga_sql('D', "id = 1 and id2 = 'str''val'")
{'id2': "str'val", 'id': '1'}
+
+ If you set the splitkeys parameter, it will return two dicts, one for key
+ fields and one for data fields.
+
+ Insert event:
+ >>> parse_logtriga_sql('I', '(id, data) values (1, null)', splitkeys=True)
+ ({}, {'data': None, 'id': '1'})
+
+ Update event:
+ >>> parse_logtriga_sql('U', "data='foo' where id = 1", splitkeys=True)
+ ({'id': '1'}, {'data': 'foo'})
+
+ Delete event:
+ >>> parse_logtriga_sql('D', "id = 1 and id2 = 'str''val'", splitkeys=True)
+ ({'id2': "str'val", 'id': '1'}, {})
+
"""
- return _logtriga_parser().parse_sql(op, sql, pklist)
+ return _logtriga_parser().parse_sql(op, sql, pklist, splitkeys=splitkeys)
def parse_tabbed_table(txt):