0.4.0beta6
----------
-- Added full list of SQLite reserved keywords so that they get escaped
- properly.
+- the Session identity map is now *weak referencing* by default, use
+weak_identity_map=False to use a regular dict. The weak dict we are using
+is customized to detect instances which are "dirty" and maintain a temporary
+strong reference to those instances until changes are flushed.
- Mapper compilation has been reorganized such that most compilation occurs
upon mapper construction. This allows us to have fewer calls to
inheritance relationships need to be constructed in inheritance order
(which should be the normal case anyway).
+- Added full list of SQLite reserved keywords so that they get escaped
+properly.
+
- Removed "parameters" argument from clauseelement.compile(), replaced with
"column_keys". The parameters sent to execute() only interact with the
insert/update statement compilation process in terms of the column names
of foreign key attributes during a flush where the parent object is
deleted.
-- the Session identity map is now *weak referencing* by default, use
- weak_identity_map=False to use a regular dict. The weak dict we are using
- is customized to detect instances which are "dirty" and maintain a temporary
- strong reference to those instances until changes are flushed.
-
- Column defaults and onupdates, executing inline, will add parenthesis for
subqueries and other parenthesis-requiring expressions
+- the behavior of String/Unicode types regarding that they auto-convert
+ to TEXT/CLOB when no length is present now occurs *only* for an exact type
+ of String or Unicode with no arguments. If you use VARCHAR or NCHAR
+ (subclasses of String/Unicode) with no length, they will be interpreted
+ by the dialect as VARCHAR/NCHAR; no "magic" conversion happens there.
+ This is less surprising behavior and in particular this helps Oracle keep
+ string-based bind parameters as VARCHARs and not CLOBs [ticket:793].
+
- Fixes to ShardedSession to work with deferred columns [ticket:771].
- User-defined shard_chooser() function must accept "clause=None" argument;
self.type = type_
# TODO: move to types module, obviously
+ # using VARCHAR/NCHAR so that we dont get the genericized "String"
+ # type which usually resolves to TEXT/CLOB
type_map = {
- str : sqltypes.String,
- unicode : sqltypes.Unicode,
+ str : sqltypes.VARCHAR,
+ unicode : sqltypes.NCHAR,
int : sqltypes.Integer,
float : sqltypes.Numeric,
type(None):sqltypes.NullType
def get_search_list(self):
l = super(String, self).get_search_list()
- if self.length is None:
+ # if we are String or Unicode with no length,
+ # return TEXT as the highest-priority type
+ # to be adapted by the dialect
+ if self.length is None and l[0] in (String, Unicode):
return (TEXT,) + l
else:
return l
-
def get_dbapi_type(self, dbapi):
return dbapi.STRING
"ON addresses.address_type_id = address_types_1.id WHERE addresses.user_id = :addresses_user_id ORDER BY addresses.rowid, "
"address_types.rowid")
+class TypesTest(SQLCompileTest):
+ def test_no_clobs_for_string_params(self):
+ """test that simple string params get a DBAPI type of VARCHAR, not CLOB.
+ this is to prevent setinputsizes from setting up cx_oracle.CLOBs on
+ string-based bind params [ticket:793]."""
+
+ class FakeDBAPI(object):
+ def __getattr__(self, attr):
+ return attr
+
+ dialect = oracle.OracleDialect()
+ dbapi = FakeDBAPI()
+
+ b = bindparam("foo", "hello world!")
+ assert b.type.dialect_impl(dialect).get_dbapi_type(dbapi) == 'STRING'
+
+ b = bindparam("foo", u"hello world!")
+ assert b.type.dialect_impl(dialect).get_dbapi_type(dbapi) == 'STRING'
+
class SequenceTest(SQLCompileTest):
def test_basic(self):
seq = Sequence("my_seq_no_schema")
from sqlalchemy import *
from sqlalchemy import types
import sqlalchemy.engine.url as url
-from sqlalchemy.databases import mssql, oracle, mysql
+from sqlalchemy.databases import mssql, oracle, mysql, postgres
from testlib import *
t2 = mysql.MSVarBinary()
assert isinstance(dialect.type_descriptor(t1), mysql.MSVarBinary)
assert isinstance(dialect.type_descriptor(t2), mysql.MSVarBinary)
+
+ def teststringadapt(self):
+ """test that String with no size becomes TEXT, *all* others stay as varchar/String"""
+
+ oracle_dialect = oracle.OracleDialect()
+ mysql_dialect = mysql.MySQLDialect()
+ postgres_dialect = postgres.PGDialect()
+
+ for dialect, start, test in [
+ (oracle_dialect, String(), oracle.OracleText),
+ (oracle_dialect, VARCHAR(), oracle.OracleString),
+ (oracle_dialect, String(50), oracle.OracleString),
+ (oracle_dialect, Unicode(), oracle.OracleText),
+ (oracle_dialect, NCHAR(), oracle.OracleString),
+ (mysql_dialect, String(), mysql.MSText),
+ (mysql_dialect, VARCHAR(), mysql.MSString),
+ (mysql_dialect, String(50), mysql.MSString),
+ (mysql_dialect, Unicode(), mysql.MSText),
+ (mysql_dialect, NCHAR(), mysql.MSNChar),
+ (postgres_dialect, String(), postgres.PGText),
+ (postgres_dialect, VARCHAR(), postgres.PGString),
+ (postgres_dialect, String(50), postgres.PGString),
+ (postgres_dialect, Unicode(), postgres.PGText),
+ (postgres_dialect, NCHAR(), postgres.PGString),
+ ]:
+ assert isinstance(start.dialect_impl(dialect), test), "wanted %r got %r" % (test, start.dialect_impl(dialect))
+
class UserDefinedTest(PersistTest):