This patch will make compose_query.cgi considerably faster.  It also has the
beginnings of a library for parsing a simple language (for expressing
conditionals) into SQL.  Right now, the language only understands &'s, |'s, and
most operators sql understands.  In the future, it'll understand ()'s, !'s, and
maybe others...but, given that the original compose_query.cgi only knew &'s and
='s, I didn't want to gate this patch for such support.  In addition, high on
my todo list is the ability to drill down into results by clicking on rows,
columns, and cells.


Signed-off-by: Jeremy Orlow <jorlow@google.com>

NB. mbligh changed the set calls to use the builtin class. If that doesn't
work, it's my fault ;-)



git-svn-id: http://test.kernel.org/svn/autotest/trunk@1100 592f7852-d20e-0410-864c-8624ca9c26a4
diff --git a/tko/query_lib.py b/tko/query_lib.py
index 402142b..e20a667 100644
--- a/tko/query_lib.py
+++ b/tko/query_lib.py
@@ -14,6 +14,85 @@
 
 db = db.db()
 
+def dprint(str):
+	pass
+	#print "! %s<br>" % str
+
+def parse_scrub_and_gen_condition(condition, valid_field_dict):
+	me = parse_scrub_and_gen_condition   # shorten the name
+	compare_ops = {'=':'=', '<>':'<>', '==':'=', '!=':'<>', '>':'>',
+	               '<':'<', '>=':'>=', '<=':'<=', '~':'LIKE', '#':'REGEXP'}
+
+	# strip white space
+	condition = condition.strip()
+
+	# ()'s
+	#match = re.match(r'^[(](.+)[)]$', condition)
+	#if match:
+	#	dprint("Matched () on %s" % condition)
+	#	depth = 0
+	#	for c in match.group(1):
+	#		if c == '(':	depth += 1
+	#		if c == ')':	depth -= 1
+	#		if depth < 0:	break
+	#	dprint("Depth is %d" % depth)
+	#	if depth == 0:
+	#		dprint("Match...stripping ()'s")
+	#		return me(match.group(1), valid_field_dict)
+
+	# OR
+	match = re.match(r'^(.+)[|](.+)$', condition)
+	if match:
+		dprint("Matched | on %s" % condition)
+		(a_sql, a_values) = me(match.group(1), valid_field_dict)
+		(b_sql, b_values) = me(match.group(2), valid_field_dict)
+		return (" (%s) OR (%s) " % (a_sql, b_sql),
+		        a_values + b_values)
+
+	# AND
+	match = re.match(r'^(.+)[&](.+)$', condition)
+	if match:
+		dprint("Matched & on %s" % condition)
+		(a_sql, a_values) = me(match.group(1), valid_field_dict)
+		(b_sql, b_values) = me(match.group(2), valid_field_dict)
+		return (" (%s) AND (%s) " % (a_sql, b_sql),
+		        a_values + b_values)
+
+	# NOT
+	#match = re.match(r'^[!](.+)$', condition)
+	#if match:
+	#	dprint("Matched ! on %s" % condition)
+	#	(sql, values) = me(match.group(1), valid_field_dict)
+	#	return (" NOT (%s) " % (sql,), values)
+
+	# '<field> <op> <value>' where value can be quoted
+	# double quotes are escaped....i.e.  '''' is the same as "'"
+	regex = r'^(%s)[ \t]*(%s)[ \t]*' + \
+	        r'(\'((\'\'|[^\'])*)\'|"((""|[^"])*)"|([^\'"].*))$'
+	regex = regex % ('|'.join(valid_field_dict.keys()),
+	                 '|'.join(compare_ops.keys()))
+	match = re.match(regex, condition)
+	if match:
+		field = valid_field_dict[match.group(1)]
+		op = compare_ops[match.group(2)]
+		if match.group(5):
+			val = match.group(4).replace("''", "'")
+		elif match.group(7):
+			val = match.group(6).replace('""', '"')
+		elif match.group(8):
+			val = match.group(8)
+		else:
+			raise "Internal error"
+		return ("%s %s %%s" % (field, op), [val])
+		
+
+	raise "Could not parse '%s' (%s)" % (condition, regex)
+
+
+###
+### Everything past here is depricated.
+###
+
 def generate_sql_condition(condition_list):
 	""" generate the sql for the condition list."""
 	sql = ''