--- /dev/null
+.. change::
+ :tags: mssql
+ :tickets: 7243
+
+ Added support for ``FILESTREAM`` when using ``VARBINARY(max)``
+ in MSSQL.
+
+ .. seealso::
+
+ :paramref:`_mssql.VARBINARY.filestream`
:members: __init__
+.. autoclass:: VARBINARY
+ :members: __init__
+
.. autoclass:: VARCHAR
:members: __init__
class VARBINARY(sqltypes.VARBINARY, sqltypes.LargeBinary):
"""The MSSQL VARBINARY type.
- This type is present to support "deprecate_large_types" mode where
- either ``VARBINARY(max)`` or IMAGE is rendered. Otherwise, this type
- object is redundant vs. :class:`_types.VARBINARY`.
+ This type adds additional features to the core :class:`_types.VARBINARY`
+ type, including "deprecate_large_types" mode where
+ either ``VARBINARY(max)`` or IMAGE is rendered, as well as the SQL
+ Server ``FILESTREAM`` option.
.. versionadded:: 1.0.0
:ref:`mssql_large_type_deprecation`
-
-
"""
__visit_name__ = "VARBINARY"
+ def __init__(self, length=None, filestream=False):
+ """
+ Construct a VARBINARY type.
+
+ :param length: optional, a length for the column for use in
+ DDL statements, for those binary types that accept a length,
+ such as the MySQL BLOB type.
+
+ :param filestream=False: if True, renders the ``FILESTREAM`` keyword
+ in the table definition. In this case ``length`` must be ``None``
+ or ``'max'``.
+
+ .. versionadded:: 1.4.31
+
+ """
+
+ self.filestream = filestream
+ if self.filestream and length not in (None, "max"):
+ raise ValueError(
+ "length must be None or 'max' when setting filestream"
+ )
+ super(VARBINARY, self).__init__(length=length)
+
class IMAGE(sqltypes.LargeBinary):
__visit_name__ = "IMAGE"
return "XML"
def visit_VARBINARY(self, type_, **kw):
- return self._extend("VARBINARY", type_, length=type_.length or "max")
+ text = self._extend("VARBINARY", type_, length=type_.length or "max")
+ if getattr(type_, "filestream", False):
+ text += " FILESTREAM"
+ return text
def visit_boolean(self, type_, **kw):
return self.visit_BIT(type_)
from sqlalchemy.testing import ComparesTables
from sqlalchemy.testing import engines
from sqlalchemy.testing import eq_
+from sqlalchemy.testing import expect_raises_message
from sqlalchemy.testing import fixtures
from sqlalchemy.testing import is_
from sqlalchemy.testing import is_not
(mssql.MSVarBinary, [10], {}, "VARBINARY(10)"),
(types.VARBINARY, [10], {}, "VARBINARY(10)"),
(types.VARBINARY, [], {}, "VARBINARY(max)"),
+ (
+ mssql.MSVarBinary,
+ [],
+ {"filestream": True},
+ "VARBINARY(max) FILESTREAM",
+ ),
(mssql.MSImage, [], {}, "IMAGE"),
(mssql.IMAGE, [], {}, "IMAGE"),
(types.LargeBinary, [], {}, "IMAGE"),
)
self.assert_(repr(col))
+ def test_VARBINARY_init(self):
+ d = mssql.dialect()
+ t = mssql.MSVarBinary(length=None, filestream=True)
+ eq_(str(t.compile(dialect=d)), "VARBINARY(max) FILESTREAM")
+ t = mssql.MSVarBinary(length="max", filestream=True)
+ eq_(str(t.compile(dialect=d)), "VARBINARY(max) FILESTREAM")
+ with expect_raises_message(
+ ValueError, "length must be None or 'max' when setting filestream"
+ ):
+ mssql.MSVarBinary(length=1000, filestream=True)
+
class TypeRoundTripTest(
fixtures.TestBase, AssertsExecutionResults, ComparesTables
),
]
+ if testing.requires.mssql_filestream.enabled:
+ columns.append(
+ (
+ mssql.MSVarBinary,
+ [],
+ {"filestream": True},
+ "VARBINARY(max) FILESTREAM",
+ )
+ )
engine = engines.testing_engine(
options={"deprecate_large_types": deprecate_large_types}
)
None,
False,
),
+ (
+ mssql.VARBINARY(filestream=True),
+ "binary_data_one.dat",
+ None,
+ True,
+ None,
+ False,
+ testing.requires.mssql_filestream,
+ ),
(
sqltypes.LargeBinary,
"binary_data_one.dat",
def json_deserializer_binary(self):
"indicates if the json_deserializer function is called with bytes"
return only_on(["postgresql+psycopg"])
+
+ @property
+ def mssql_filestream(self):
+ "returns if mssql supports filestream"
+
+ def check(config):
+ with config.db.connect() as conn:
+ res = conn.exec_driver_sql(
+ "SELECT [type] FROM sys.master_files WHERE "
+ "database_id = DB_ID() AND [type] = 2"
+ ).scalar()
+ return res is not None
+
+ return only_on(["mssql"]) + only_if(check)