known-vendor-issues.rst 6.56 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14
Known Vendor Issues
===================

This section describes known compatability issues with all the
supported database vendors:

PostgreSQL
----------

DateTime, DateTimeTz and Time Types
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Postgres has a variable return format for the datatype TIMESTAMP(n)
and TIME(n) if microseconds are allowed (n > 0). Whenever you save
Phil Davis's avatar
Phil Davis committed
15
a value with microseconds = 0, PostgreSQL will return this value in
16 17 18 19 20 21 22 23 24 25 26 27 28
the format:

::

    2010-10-10 10:10:10 (Y-m-d H:i:s)

However if you save a value with microseconds it will return the
full representation:

::

    2010-10-10 10:10:10.123456 (Y-m-d H:i:s.u)

29
Using the DateTime, DateTimeTz or Time type (and immutable variants) with microseconds
30 31
enabled columns can lead to errors because internally types expect
the exact format 'Y-m-d H:i:s' in combination with
高成功's avatar
高成功 committed
32
``DateTime::createFromFormat()``. This method is twice as fast as
33 34 35 36 37 38 39 40 41 42 43
passing the date to the constructor of ``DateTime``.

This is why Doctrine always wants to create the time related types
without microseconds:

-  DateTime to ``TIMESTAMP(0) WITHOUT TIME ZONE``
-  DateTimeTz to ``TIMESTAMP(0) WITH TIME ZONE``
-  Time to ``TIME(0) WITHOUT TIME ZONE``

If you do not let Doctrine create the date column types and rather
use types with microseconds you have replace the "DateTime",
44 45
"DateTimeTz" and "Time" types (and immutable variants) with a more
liberal DateTime parser that detects the format automatically:
46 47 48 49

::

    use Doctrine\DBAL\Types\Type;
50

51 52 53
    Type::overrideType('datetime', 'Doctrine\DBAL\Types\VarDateTimeType');
    Type::overrideType('datetimetz', 'Doctrine\DBAL\Types\VarDateTimeType');
    Type::overrideType('time', 'Doctrine\DBAL\Types\VarDateTimeType');
54

55 56 57 58
    Type::overrideType('datetime_immutable', 'Doctrine\DBAL\Types\VarDateTimeImmutableType');
    Type::overrideType('datetimetz_immutable', 'Doctrine\DBAL\Types\VarDateTimeImmutableType');
    Type::overrideType('time_immutable', 'Doctrine\DBAL\Types\VarDateTimeImmutableType');

59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
Timezones and DateTimeTz
~~~~~~~~~~~~~~~~~~~~~~~~

Postgres does not save the actual Timezone Name but UTC-Offsets.
The difference is subtle but can be potentially very nasty. Derick
Rethans explains it very well
`in a blog post of his <http://derickrethans.nl/storing-date-time-in-database.html>`_.

MySQL
-----

DateTimeTz
~~~~~~~~~~

MySQL does not support saving timezones or offsets. The DateTimeTz
Phil Davis's avatar
Phil Davis committed
74
type therefore behaves like the DateTime type.
75 76 77 78

Sqlite
------

79 80 81
Buffered Queries and Isolation
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Phil Davis's avatar
Phil Davis committed
82
Be careful if you execute a ``SELECT`` query and do not iterate over the
Benjamin Eberlei's avatar
Benjamin Eberlei committed
83
statements results immediately. ``UPDATE`` statements executed before iteration
84
affect only the rows that have not been buffered into PHP memory yet. This
Benjamin Eberlei's avatar
Benjamin Eberlei committed
85
breaks the SERIALIZABLE transaction isolation property that SQLite supposedly
86 87
has.

88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
DateTime
~~~~~~~~~~

Unlike most database management systems, Sqlite does not convert supplied
datetime strings to an internal storage format before storage. Instead, Sqlite
stores them as verbatim strings (i.e. as they are entered) and expects the user
to use the ``DATETIME()`` function when reading data which then converts the
stored values to datetime strings.
Because Doctrine is not using the ``DATETIME()`` function, you may end up with
"Could not convert database value ... to Doctrine Type datetime." exceptions
when trying to convert database values to ``\DateTime`` objects using

.. code-block:: php

    \Doctrine\DBAL\Types\Type::getType('datetime')->convertToPhpValue(...)

104 105 106 107
DateTimeTz
~~~~~~~~~~

Sqlite does not support saving timezones or offsets. The DateTimeTz
Phil Davis's avatar
Phil Davis committed
108
type therefore behaves like the DateTime type.
109

110 111 112 113 114 115 116 117
Reverse engineering primary key order
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
SQLite versions < 3.7.16 only return that a column is part of the primary key,
but not the order. This is only a problem with tables where the order of the
columns in the table is not the same as the order in the primary key. Tables
created with Doctrine use the order of the columns as defined in the primary
key.

118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
IBM DB2
-------

DateTimeTz
~~~~~~~~~~

DB2 does not save the actual Timezone Name but UTC-Offsets. The
difference is subtle but can be potentially very nasty. Derick
Rethans explains it very well
`in a blog post of his <http://derickrethans.nl/storing-date-time-in-database.html>`_.

Oracle
------

DateTimeTz
~~~~~~~~~~

Oracle does not save the actual Timezone Name but UTC-Offsets. The
difference is subtle but can be potentially very nasty. Derick
Rethans explains it very well
`in a blog post of his <http://derickrethans.nl/storing-date-time-in-database.html>`_.

OCI-LOB instances
~~~~~~~~~~~~~~~~~

Doctrine 2 always requests CLOB columns as strings, so that you as
a developer never get access to the ``OCI-LOB`` instance. Since we
are using prepared statements for all write operations inside the
ORM, using strings instead of the ``OCI-LOB`` does not cause any
problems.

Microsoft SQL Server
--------------------

Unique and NULL
~~~~~~~~~~~~~~~

Microsoft SQL Server takes Unique very seriously. There is only
ever one NULL allowed contrary to the standard where you can have
multiple NULLs in a unique column.

159 160 161 162 163 164 165 166 167
DateTime, DateTimeTz and Time Types
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

SQL Server has a variable return format for the datatype DATETIME(n)
if microseconds are allowed (n > 0). Whenever you save
a value with microseconds = 0.

If you do not let Doctrine create the date column types and rather
use types with microseconds you have replace the "DateTime",
168 169
"DateTimeTz" and "Time" types (and immutable variants) with a more
liberal DateTime parser that detects the format automatically:
170

171 172 173
::

    use Doctrine\DBAL\Types\Type;
174

175 176 177
    Type::overrideType('datetime', 'Doctrine\DBAL\Types\VarDateTime');
    Type::overrideType('datetimetz', 'Doctrine\DBAL\Types\VarDateTime');
    Type::overrideType('time', 'Doctrine\DBAL\Types\VarDateTime');
178

179 180 181 182
    Type::overrideType('datetime_immutable', 'Doctrine\DBAL\Types\VarDateTimeImmutableType');
    Type::overrideType('datetimetz_immutable', 'Doctrine\DBAL\Types\VarDateTimeImmutableType');
    Type::overrideType('time_immutable', 'Doctrine\DBAL\Types\VarDateTimeImmutableType');

183 184 185 186 187 188 189
PDO_SQLSRV: VARBINARY/BLOB columns
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The ``PDO_SQLSRV`` driver currently has a bug when binding values to
VARBINARY/BLOB columns with ``bindValue`` in prepared statements.
This raises an implicit conversion from data type error as it tries
to convert a character type value to a binary type value even if
190
you explicitly define the value as ``ParameterType::LARGE_OBJECT`` type.
191 192
Therefore it is highly encouraged to use the native ``sqlsrv``
driver instead which does not have this limitation.