Author: phd
Date: 2006-09-01 07:12:58 -0600 (Fri, 01 Sep 2006)
New Revision: 1894
Modified:
SQLObject/branches/0.7-bugfix/docs/News.txt
SQLObject/branches/0.7-bugfix/docs/SQLObject.txt
SQLObject/branches/0.7-bugfix/sqlobject/main.py
SQLObject/branches/0.7-bugfix/sqlobject/sqlbuilder.py
SQLObject/branches/0.7-bugfix/sqlobject/tests/test_unicode.py
Log:
Fixed a longstanding problem with UnicodeCol - at last you can use unicode
strings in .select() and .selectBy() queries (with some limitations).
Modified: SQLObject/branches/0.7-bugfix/docs/News.txt
===================================================================
--- SQLObject/branches/0.7-bugfix/docs/News.txt 2006-09-01 13:12:23 UTC (rev 1893)
+++ SQLObject/branches/0.7-bugfix/docs/News.txt 2006-09-01 13:12:58 UTC (rev 1894)
@@ -49,6 +49,25 @@
Bug Fixes
---------
+* Fixed a longstanding problem with UnicodeCol - at last you can use unicode
+ strings in .select() and .selectBy() queries. There are some limitations,
+ though:
+
+ - only simple q-magic fields are supported; no expressions;
+ - only == and <> operators are supported;
+
+ The following code works::
+
+ MyTable.select(u'value' == MyTable.q.name)
+ MyTable.select(MyTable.q.name <> u'value')
+ MyTable.select(OR(MyTable.q.col1 == u'value1', MyTable.q.col2 <> u'value2'))
+ MyTable.selectBy(name = u'value')
+ MyTable.selectBy(col1=u'value1', col2=u'value2')
+
+ The following still does not work::
+
+ MyTable.select((MyTable.q.name + MyTable.q.surname) == u'value')
+
* Cull patch (clear cache).
* .destroySelf() inside a transaction.
Modified: SQLObject/branches/0.7-bugfix/docs/SQLObject.txt
===================================================================
--- SQLObject/branches/0.7-bugfix/docs/SQLObject.txt 2006-09-01 13:12:23 UTC (rev 1893)
+++ SQLObject/branches/0.7-bugfix/docs/SQLObject.txt 2006-09-01 13:12:58 UTC (rev 1894)
@@ -1127,11 +1127,28 @@
A subclass of `StringCol`. Also accepts a dbEncoding keyword
argument, which defaults to ``"UTF-8"``. Values coming in and
out from the database will be encoded and decoded. **Note**:
- parameters in queries will not be automatically encoded, so if
- you do a query matching a UnicodeCol column you must apply the
- encoding yourself.
+ there are some limitations on using UnicodeCol in queries:
+ - only simple q-magic fields are supported; no expressions;
+ - only == and <> operators are supported;
+ The following code works::
+
+ MyTable.select(u'value' == MyTable.q.name)
+ MyTable.select(MyTable.q.name <> u'value')
+ MyTable.select(OR(MyTable.q.col1 == u'value1', MyTable.q.col2 <> u'value2'))
+ MyTable.selectBy(name = u'value')
+ MyTable.selectBy(col1=u'value1', col2=u'value2')
+
+ The following does not work::
+
+ MyTable.select((MyTable.q.name + MyTable.q.surname) == u'value')
+
+ In that case you must apply the encoding yourself::
+
+ MyTable.select((MyTable.q.name + MyTable.q.surname) == u'value'.encode(dbEncoding))
+
+
.. Relationships_:
Relationships Between Classes/Tables
Modified: SQLObject/branches/0.7-bugfix/sqlobject/main.py
===================================================================
--- SQLObject/branches/0.7-bugfix/sqlobject/main.py 2006-09-01 13:12:23 UTC (rev 1893)
+++ SQLObject/branches/0.7-bugfix/sqlobject/main.py 2006-09-01 13:12:58 UTC (rev 1894)
@@ -1297,6 +1297,11 @@
select = classmethod(select)
def selectBy(cls, connection=None, **kw):
+ for key, column in cls.sqlmeta.columns.items():
+ if (key in kw) and isinstance(column, col.SOUnicodeCol):
+ value = kw[key]
+ if isinstance(value, unicode):
+ kw[key] = value.encode(column.dbEncoding)
conn = connection or cls._connection
return cls.SelectResultsClass(cls,
conn._SO_columnClause(cls, kw),
Modified: SQLObject/branches/0.7-bugfix/sqlobject/sqlbuilder.py
===================================================================
--- SQLObject/branches/0.7-bugfix/sqlobject/sqlbuilder.py 2006-09-01 13:12:23 UTC (rev 1893)
+++ SQLObject/branches/0.7-bugfix/sqlobject/sqlbuilder.py 2006-09-01 13:12:58 UTC (rev 1894)
@@ -323,6 +323,23 @@
registerConverter(SQLObjectField, SQLExprConverter)
+
+class UnicodeField(SQLObjectField):
+ def __init__(self, tableName, fieldName, original, column):
+ SQLObjectField.__init__(self, tableName, fieldName, original)
+ self.column = column
+ def __eq__(self, other):
+ if isinstance(other, unicode):
+ other = other.encode(self.column.dbEncoding)
+ return SQLOp('=', self, other)
+ def __ne__(self, other):
+ if isinstance(other, unicode):
+ other = other.encode(self.column.dbEncoding)
+ return SQLOp('<>', self, other)
+
+registerConverter(UnicodeField, SQLExprConverter)
+
+
class Table(SQLExpression):
FieldClass = Field
@@ -339,6 +356,7 @@
class SQLObjectTable(Table):
FieldClass = SQLObjectField
+ UnicodeFieldClass = UnicodeField
def __init__(self, soClass):
self.soClass = soClass
@@ -355,9 +373,12 @@
elif attr not in self.soClass.sqlmeta.columns:
raise AttributeError("%s instance has no attribute '%s'" % (self.soClass.__name__, attr))
else:
- return self.FieldClass(self.tableName,
- self.soClass.sqlmeta.columns[attr].dbName,
- attr)
+ column = self.soClass.sqlmeta.columns[attr]
+ if hasattr(column, "dbEncoding"):
+ return self.UnicodeFieldClass(self.tableName, column.dbName,
+ attr, column)
+ else:
+ return self.FieldClass(self.tableName, column.dbName, attr)
class TableSpace:
TableClass = Table
Modified: SQLObject/branches/0.7-bugfix/sqlobject/tests/test_unicode.py
===================================================================
--- SQLObject/branches/0.7-bugfix/sqlobject/tests/test_unicode.py 2006-09-01 13:12:23 UTC (rev 1893)
+++ SQLObject/branches/0.7-bugfix/sqlobject/tests/test_unicode.py 2006-09-01 13:12:58 UTC (rev 1894)
@@ -5,7 +5,7 @@
## Unicode columns
########################################
-class Unicode1(SQLObject):
+class TestUnicode(SQLObject):
count = IntCol(alternateID=True)
col1 = UnicodeCol()
col2 = UnicodeCol(dbEncoding='latin-1')
@@ -16,24 +16,54 @@
def enumerate(lst):
return [(i, lst[i]) for i in range(len(lst))]
-def test_create():
- setupClass(Unicode1)
- data = [u'\u00f0', u'test', 'ascii test']
+data = [u'\u00f0', u'test', 'ascii test']
+items = []
+def setup():
+ global items
items = []
+ setupClass(TestUnicode)
for i, n in enumerate(data):
- items.append(Unicode1(count=i, col1=n, col2=n))
+ items.append(TestUnicode(count=i, col1=n, col2=n))
+
+def test_create():
+ setup()
for n, item in zip(data, items):
- item.col1 = item.col2 = n
- for n, item in zip(data, items):
assert item.col1 == item.col2
assert item.col1 == n
- conn = Unicode1._connection
+
+ conn = TestUnicode._connection
rows = conn.queryAll("""
SELECT count, col1, col2
- FROM unicode1
+ FROM test_unicode
ORDER BY count
""")
for count, col1, col2 in rows:
assert data[count].encode('utf-8') == col1
assert data[count].encode('latin1') == col2
+
+def test_select():
+ setup()
+ for value in data:
+ rows = list(TestUnicode.select(TestUnicode.q.col1 == value))
+ assert len(rows) == 1
+ rows = list(TestUnicode.select(TestUnicode.q.col2 == value))
+ assert len(rows) == 1
+ rows = list(TestUnicode.select(AND(
+ TestUnicode.q.col1 == value,
+ TestUnicode.q.col2 == value
+ )))
+ assert len(rows) == 1
+ rows = list(TestUnicode.selectBy(col1=value))
+ assert len(rows) == 1
+ rows = list(TestUnicode.selectBy(col2=value))
+ assert len(rows) == 1
+ rows = list(TestUnicode.selectBy(col1=value, col2=value))
+ assert len(rows) == 1
+ rows = list(TestUnicode.select(OR(
+ TestUnicode.q.col1 == u'\u00f0',
+ TestUnicode.q.col2 == u'test'
+ )))
+ assert len(rows) == 2
+ rows = list(TestUnicode.selectBy(col1=u'\u00f0', col2=u'test'))
+ assert len(rows) == 0
|