summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES4
-rw-r--r--lib/sqlalchemy/dialects/firebird/base.py41
-rw-r--r--test/dialect/test_firebird.py16
-rw-r--r--test/sql/test_query.py1
4 files changed, 60 insertions, 2 deletions
diff --git a/CHANGES b/CHANGES
index 7eb7b2adb..e8bea81ce 100644
--- a/CHANGES
+++ b/CHANGES
@@ -92,6 +92,10 @@ CHANGES
- Fixed incorrect signature in do_execute(), error
introduced in 0.6.1. [ticket:1823]
+ - Firebird dialect adds CHAR, VARCHAR types which
+ accept a "charset" flag, to support Firebird
+ "CHARACTER SET" clause. [ticket:1813]
+
- declarative
- a mixin class can now define a column that matches
one which is present on a __table__ defined on a
diff --git a/lib/sqlalchemy/dialects/firebird/base.py b/lib/sqlalchemy/dialects/firebird/base.py
index 0d3143b3b..d6e0f95bd 100644
--- a/lib/sqlalchemy/dialects/firebird/base.py
+++ b/lib/sqlalchemy/dialects/firebird/base.py
@@ -78,9 +78,9 @@ from sqlalchemy.engine import base, default, reflection
from sqlalchemy.sql import compiler
-from sqlalchemy.types import (BIGINT, BLOB, BOOLEAN, CHAR, DATE,
+from sqlalchemy.types import (BIGINT, BLOB, BOOLEAN, DATE,
FLOAT, INTEGER, NUMERIC, SMALLINT,
- TEXT, TIME, TIMESTAMP, VARCHAR)
+ TEXT, TIME, TIMESTAMP)
RESERVED_WORDS = set([
@@ -123,6 +123,27 @@ RESERVED_WORDS = set([
])
+class _StringType(sqltypes.String):
+ """Base for Firebird string types."""
+
+ def __init__(self, charset = None, **kw):
+ self.charset = charset
+ super(_StringType, self).__init__(**kw)
+
+class VARCHAR(_StringType, sqltypes.VARCHAR):
+ """Firebird VARCHAR type"""
+ __visit_name__ = 'VARCHAR'
+
+ def __init__(self, length = None, **kwargs):
+ super(VARCHAR, self).__init__(length=length, **kwargs)
+
+class CHAR(_StringType, sqltypes.CHAR):
+ """Firebird CHAR type"""
+ __visit_name__ = 'CHAR'
+
+ def __init__(self, length = None, **kwargs):
+ super(CHAR, self).__init__(length=length, **kwargs)
+
colspecs = {
}
@@ -159,6 +180,22 @@ class FBTypeCompiler(compiler.GenericTypeCompiler):
def visit_BLOB(self, type_):
return "BLOB SUB_TYPE 0"
+ def _extend_string(self, type_, basic):
+ charset = getattr(type_, 'charset', None)
+ if charset is None:
+ return basic
+ else:
+ return '%s CHARACTER SET %s' % (basic, charset)
+
+ def visit_CHAR(self, type_):
+ basic = super(FBTypeCompiler, self).visit_CHAR(type_)
+ return self._extend_string(type_, basic)
+
+ def visit_VARCHAR(self, type_):
+ basic = super(FBTypeCompiler, self).visit_VARCHAR(type_)
+ return self._extend_string(type_, basic)
+
+
class FBCompiler(sql.compiler.SQLCompiler):
"""Firebird specific idiosincrasies"""
diff --git a/test/dialect/test_firebird.py b/test/dialect/test_firebird.py
index 9bdce8ff7..944d5bc2f 100644
--- a/test/dialect/test_firebird.py
+++ b/test/dialect/test_firebird.py
@@ -259,6 +259,22 @@ class CompileTest(TestBase, AssertsCompiledSQL):
i = insert(table1, values=dict(name='foo')).returning(func.length(table1.c.name))
self.assert_compile(i, "INSERT INTO mytable (name) VALUES (:name) RETURNING char_length(mytable.name) AS length_1")
+ def test_charset(self):
+ """Exercise CHARACTER SET options on string types."""
+
+ columns = [
+ (firebird.CHAR, [1], {},
+ 'CHAR(1)'),
+ (firebird.CHAR, [1], {'charset' : 'OCTETS'},
+ 'CHAR(1) CHARACTER SET OCTETS'),
+ (firebird.VARCHAR, [1], {},
+ 'VARCHAR(1)'),
+ (firebird.VARCHAR, [1], {'charset' : 'OCTETS'},
+ 'VARCHAR(1) CHARACTER SET OCTETS'),
+ ]
+
+ for type_, args, kw, res in columns:
+ self.assert_compile(type_(*args, **kw), res)
diff --git a/test/sql/test_query.py b/test/sql/test_query.py
index 5a4f03311..2b51d68a2 100644
--- a/test/sql/test_query.py
+++ b/test/sql/test_query.py
@@ -809,6 +809,7 @@ class QueryTest(TestBase):
assert len(r) == 0
@testing.emits_warning('.*empty sequence.*')
+ @testing.fails_on('firebird', 'uses sql-92 bind rules')
def test_literal_in(self):
"""similar to test_bind_in but use a bind with a value."""