[Modeling-cvs] ProjectModeling/Modeling/DatabaseAdaptors/SQLiteAdaptorLayer SQLiteSQLExpression.py,1
Status: Abandoned
Brought to you by:
sbigaret
|
From: <sbi...@us...> - 2003-08-10 14:43:18
|
Update of /cvsroot/modeling/ProjectModeling/Modeling/DatabaseAdaptors/SQLiteAdaptorLayer
In directory sc8-pr-cvs1:/tmp/cvs-serv16799/Modeling/DatabaseAdaptors/SQLiteAdaptorLayer
Modified Files:
SQLiteSQLExpression.py
Log Message:
Fixed bug #785913: "LIKE qualifier w/ raw '%' and '_' characters does not
work w/ SQLite"
Fixed bug #786217: 'Qualifier LIKE can be case-insensitive' (bug was
observed for MySQL and SQLite)
Index: SQLiteSQLExpression.py
===================================================================
RCS file: /cvsroot/modeling/ProjectModeling/Modeling/DatabaseAdaptors/SQLiteAdaptorLayer/SQLiteSQLExpression.py,v
retrieving revision 1.1
retrieving revision 1.2
diff -C2 -d -r1.1 -r1.2
*** SQLiteSQLExpression.py 11 Jun 2003 11:10:17 -0000 1.1
--- SQLiteSQLExpression.py 10 Aug 2003 14:43:16 -0000 1.2
***************
*** 49,52 ****
--- 49,58 ----
import string
+ import re
+ sqlite_esc_star_mark_replct='[*]'
+ sqlite_escaped_star=re.compile(r'\\\*')
+ sqlite_esc_question_mark_replct='[?]'
+ sqlite_escaped_question_mark=re.compile(r'\\\?')
+
class SQLiteSQLExpression(SQLExpression):
"""
***************
*** 127,128 ****
--- 133,260 ----
return (str, aliases)
+
+
+ def globPatternForShellPattern(self, pattern):
+ """
+ Transforms a shell pattern of a like/ilike qualifier to a shell pattern
+ accepted by SQLite's GLOB statement.
+
+ There's little to be done, except that escaped characters '\*' and '\?'
+ become, respectively, '[*]' and '[?]'
+ """
+ pattern=sqlite_escaped_question_mark.sub(sqlite_esc_question_mark_replct,
+ pattern)
+ pattern=sqlite_escaped_star.sub(sqlite_esc_star_mark_replct, pattern)
+ return pattern
+
+ def sqlStringForCaseInsensitiveLike(self, keyString, valueString):
+ """
+ Overrides the default implementation and returns the SQL string, to be
+ inserted in a WHERE clause, for case-insensitive comparison between a
+ lvalue and a rvalue. Note that sqlite LIKE sql operator is
+ case-insensitive.
+
+ Returns the following string::
+
+ <keyString> LIKE <valueString>
+
+ Parameters:
+
+ keyString -- the left value
+
+ valueString -- the right value
+
+ See also: sqlStringForKeyValueQualifier(),
+ sqlStringForKeyComparisonQualifier()
+ """
+ return "%s LIKE %s"% ( keyString, valueString )
+
+ def sqlStringForKeyValueQualifier(self, aQualifier):
+ """
+ Overrides the default behaviour to handle 'like' and 'ilike' correctly
+ wrt the way sqlite works.
+
+ Returns:
+
+ - the inherited SQLExpression.sqlStringForKeyValueQualifier() if
+ aQualifier.operator() is not like or ilike,
+
+ - if aQualifier.operator() is QualifierOperatorLike:
+
+ <key> GLOB <globPatternForShellPattern(value)>
+
+ for example, the qualifier 'title like "*abc*"' is turned into:
+
+ title GLOB "*abc*"
+
+ - if it is QualifierOperatorCaseInsensitiveLike, returns
+ SQLExpression.sqlStringForKeyValueQualifier() with arguments
+ keyString=<key> and
+ valueString=self.sqlPatternFromShellPattern(<value>)
+
+ For example, the qualifier 'title like "*abc*"' is turned into:
+
+ title LIKE "%abc%"
+
+ Note: the LIKE operator is case-insensitive in sqlite, while GLOB is
+ case-sensitive
+
+ See also: SQLExpression.sqlStringForKeyValueQualifier()
+ globPatternForShellPattern()
+ """
+ from Modeling.Qualifier import \
+ QualifierOperatorCaseInsensitiveLike as op_ilike, \
+ QualifierOperatorLike as op_like
+
+ qualifier_operator=aQualifier.operator()
+ if qualifier_operator not in (op_like, op_ilike):
+ return SQLExpression.sqlStringForKeyValueQualifier(self, aQualifier)
+
+ # Now we handle like or ilike, exclusively
+ key=aQualifier.key()
+ value=aQualifier.value()
+
+ # do not transform the shell pattern to a sql pattern for LIKE, since
+ # we'll use the sql statement 'GLOB' for like, and 'GLOB' uses a shell
+ # pattern
+ if aQualifier.operator() is op_ilike:
+ value=self.sqlPatternFromShellPattern(value)
+ else: # like
+ operatorStr=self.sqlStringForSelector(aQualifier.operator(), value)
+ value=self.globPatternForShellPattern(value)
+
+
+ keyString=self.sqlStringForAttributeNamed(key)
+ valueString=self.sqlStringForValue(value, key)
+
+
+ if qualifier_operator is op_like:
+ return keyString+' '+operatorStr+' '+valueString
+ else:
+ return self.sqlStringForCaseInsensitiveLike(keyString, valueString)
+
+ def sqlStringForSelector(self, selector, value):
+ """
+ Overrides the default behaviour to ensure that Qualifier operator
+ 'LIKE' matches case-sensitively.
+
+ Note: this is because the SQL LIKE operator is case-insensitive by default
+ in mysql.
+
+ Returns:
+
+ - if selector is Modeling.Qualifier.QualifierOperatorLike,
+ returns "GLOB"
+
+ - otherwise returns SQLExpression.sqlStringForSelector()
+
+ See also: SQLExpression.sqlStringForSelector()
+ sqlStringForKeyValueQualifier()
+ globPatternForShellPattern()
+ """
+ from Modeling.Qualifier import QualifierOperatorLike
+ selectorIs=lambda s, selector=selector: s==selector
+ if selectorIs(QualifierOperatorLike):
+ return "GLOB"
+ else:
+ return SQLExpression.sqlStringForSelector(self, selector, value)
|