Coverage for /home/martinb/.local/share/virtualenvs/camcops/lib/python3.6/site-packages/sqlalchemy/dialects/mysql/types.py : 61%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1# mysql/types.py
2# Copyright (C) 2005-2020 the SQLAlchemy authors and contributors
3# <see AUTHORS file>
4#
5# This module is part of SQLAlchemy and is released under
6# the MIT License: http://www.opensource.org/licenses/mit-license.php
8import datetime
10from ... import exc
11from ... import types as sqltypes
12from ... import util
15class _NumericType(object):
16 """Base for MySQL numeric types.
18 This is the base both for NUMERIC as well as INTEGER, hence
19 it's a mixin.
21 """
23 def __init__(self, unsigned=False, zerofill=False, **kw):
24 self.unsigned = unsigned
25 self.zerofill = zerofill
26 super(_NumericType, self).__init__(**kw)
28 def __repr__(self):
29 return util.generic_repr(
30 self, to_inspect=[_NumericType, sqltypes.Numeric]
31 )
34class _FloatType(_NumericType, sqltypes.Float):
35 def __init__(self, precision=None, scale=None, asdecimal=True, **kw):
36 if isinstance(self, (REAL, DOUBLE)) and (
37 (precision is None and scale is not None)
38 or (precision is not None and scale is None)
39 ):
40 raise exc.ArgumentError(
41 "You must specify both precision and scale or omit "
42 "both altogether."
43 )
44 super(_FloatType, self).__init__(
45 precision=precision, asdecimal=asdecimal, **kw
46 )
47 self.scale = scale
49 def __repr__(self):
50 return util.generic_repr(
51 self, to_inspect=[_FloatType, _NumericType, sqltypes.Float]
52 )
55class _IntegerType(_NumericType, sqltypes.Integer):
56 def __init__(self, display_width=None, **kw):
57 self.display_width = display_width
58 super(_IntegerType, self).__init__(**kw)
60 def __repr__(self):
61 return util.generic_repr(
62 self, to_inspect=[_IntegerType, _NumericType, sqltypes.Integer]
63 )
66class _StringType(sqltypes.String):
67 """Base for MySQL string types."""
69 def __init__(
70 self,
71 charset=None,
72 collation=None,
73 ascii=False, # noqa
74 binary=False,
75 unicode=False,
76 national=False,
77 **kw
78 ):
79 self.charset = charset
81 # allow collate= or collation=
82 kw.setdefault("collation", kw.pop("collate", collation))
84 self.ascii = ascii
85 self.unicode = unicode
86 self.binary = binary
87 self.national = national
88 super(_StringType, self).__init__(**kw)
90 def __repr__(self):
91 return util.generic_repr(
92 self, to_inspect=[_StringType, sqltypes.String]
93 )
96class _MatchType(sqltypes.Float, sqltypes.MatchType):
97 def __init__(self, **kw):
98 # TODO: float arguments?
99 sqltypes.Float.__init__(self)
100 sqltypes.MatchType.__init__(self)
103class NUMERIC(_NumericType, sqltypes.NUMERIC):
104 """MySQL NUMERIC type."""
106 __visit_name__ = "NUMERIC"
108 def __init__(self, precision=None, scale=None, asdecimal=True, **kw):
109 """Construct a NUMERIC.
111 :param precision: Total digits in this number. If scale and precision
112 are both None, values are stored to limits allowed by the server.
114 :param scale: The number of digits after the decimal point.
116 :param unsigned: a boolean, optional.
118 :param zerofill: Optional. If true, values will be stored as strings
119 left-padded with zeros. Note that this does not effect the values
120 returned by the underlying database API, which continue to be
121 numeric.
123 """
124 super(NUMERIC, self).__init__(
125 precision=precision, scale=scale, asdecimal=asdecimal, **kw
126 )
129class DECIMAL(_NumericType, sqltypes.DECIMAL):
130 """MySQL DECIMAL type."""
132 __visit_name__ = "DECIMAL"
134 def __init__(self, precision=None, scale=None, asdecimal=True, **kw):
135 """Construct a DECIMAL.
137 :param precision: Total digits in this number. If scale and precision
138 are both None, values are stored to limits allowed by the server.
140 :param scale: The number of digits after the decimal point.
142 :param unsigned: a boolean, optional.
144 :param zerofill: Optional. If true, values will be stored as strings
145 left-padded with zeros. Note that this does not effect the values
146 returned by the underlying database API, which continue to be
147 numeric.
149 """
150 super(DECIMAL, self).__init__(
151 precision=precision, scale=scale, asdecimal=asdecimal, **kw
152 )
155class DOUBLE(_FloatType):
156 """MySQL DOUBLE type."""
158 __visit_name__ = "DOUBLE"
160 def __init__(self, precision=None, scale=None, asdecimal=True, **kw):
161 """Construct a DOUBLE.
163 .. note::
165 The :class:`.DOUBLE` type by default converts from float
166 to Decimal, using a truncation that defaults to 10 digits.
167 Specify either ``scale=n`` or ``decimal_return_scale=n`` in order
168 to change this scale, or ``asdecimal=False`` to return values
169 directly as Python floating points.
171 :param precision: Total digits in this number. If scale and precision
172 are both None, values are stored to limits allowed by the server.
174 :param scale: The number of digits after the decimal point.
176 :param unsigned: a boolean, optional.
178 :param zerofill: Optional. If true, values will be stored as strings
179 left-padded with zeros. Note that this does not effect the values
180 returned by the underlying database API, which continue to be
181 numeric.
183 """
184 super(DOUBLE, self).__init__(
185 precision=precision, scale=scale, asdecimal=asdecimal, **kw
186 )
189class REAL(_FloatType, sqltypes.REAL):
190 """MySQL REAL type."""
192 __visit_name__ = "REAL"
194 def __init__(self, precision=None, scale=None, asdecimal=True, **kw):
195 """Construct a REAL.
197 .. note::
199 The :class:`.REAL` type by default converts from float
200 to Decimal, using a truncation that defaults to 10 digits.
201 Specify either ``scale=n`` or ``decimal_return_scale=n`` in order
202 to change this scale, or ``asdecimal=False`` to return values
203 directly as Python floating points.
205 :param precision: Total digits in this number. If scale and precision
206 are both None, values are stored to limits allowed by the server.
208 :param scale: The number of digits after the decimal point.
210 :param unsigned: a boolean, optional.
212 :param zerofill: Optional. If true, values will be stored as strings
213 left-padded with zeros. Note that this does not effect the values
214 returned by the underlying database API, which continue to be
215 numeric.
217 """
218 super(REAL, self).__init__(
219 precision=precision, scale=scale, asdecimal=asdecimal, **kw
220 )
223class FLOAT(_FloatType, sqltypes.FLOAT):
224 """MySQL FLOAT type."""
226 __visit_name__ = "FLOAT"
228 def __init__(self, precision=None, scale=None, asdecimal=False, **kw):
229 """Construct a FLOAT.
231 :param precision: Total digits in this number. If scale and precision
232 are both None, values are stored to limits allowed by the server.
234 :param scale: The number of digits after the decimal point.
236 :param unsigned: a boolean, optional.
238 :param zerofill: Optional. If true, values will be stored as strings
239 left-padded with zeros. Note that this does not effect the values
240 returned by the underlying database API, which continue to be
241 numeric.
243 """
244 super(FLOAT, self).__init__(
245 precision=precision, scale=scale, asdecimal=asdecimal, **kw
246 )
248 def bind_processor(self, dialect):
249 return None
252class INTEGER(_IntegerType, sqltypes.INTEGER):
253 """MySQL INTEGER type."""
255 __visit_name__ = "INTEGER"
257 def __init__(self, display_width=None, **kw):
258 """Construct an INTEGER.
260 :param display_width: Optional, maximum display width for this number.
262 :param unsigned: a boolean, optional.
264 :param zerofill: Optional. If true, values will be stored as strings
265 left-padded with zeros. Note that this does not effect the values
266 returned by the underlying database API, which continue to be
267 numeric.
269 """
270 super(INTEGER, self).__init__(display_width=display_width, **kw)
273class BIGINT(_IntegerType, sqltypes.BIGINT):
274 """MySQL BIGINTEGER type."""
276 __visit_name__ = "BIGINT"
278 def __init__(self, display_width=None, **kw):
279 """Construct a BIGINTEGER.
281 :param display_width: Optional, maximum display width for this number.
283 :param unsigned: a boolean, optional.
285 :param zerofill: Optional. If true, values will be stored as strings
286 left-padded with zeros. Note that this does not effect the values
287 returned by the underlying database API, which continue to be
288 numeric.
290 """
291 super(BIGINT, self).__init__(display_width=display_width, **kw)
294class MEDIUMINT(_IntegerType):
295 """MySQL MEDIUMINTEGER type."""
297 __visit_name__ = "MEDIUMINT"
299 def __init__(self, display_width=None, **kw):
300 """Construct a MEDIUMINTEGER
302 :param display_width: Optional, maximum display width for this number.
304 :param unsigned: a boolean, optional.
306 :param zerofill: Optional. If true, values will be stored as strings
307 left-padded with zeros. Note that this does not effect the values
308 returned by the underlying database API, which continue to be
309 numeric.
311 """
312 super(MEDIUMINT, self).__init__(display_width=display_width, **kw)
315class TINYINT(_IntegerType):
316 """MySQL TINYINT type."""
318 __visit_name__ = "TINYINT"
320 def __init__(self, display_width=None, **kw):
321 """Construct a TINYINT.
323 :param display_width: Optional, maximum display width for this number.
325 :param unsigned: a boolean, optional.
327 :param zerofill: Optional. If true, values will be stored as strings
328 left-padded with zeros. Note that this does not effect the values
329 returned by the underlying database API, which continue to be
330 numeric.
332 """
333 super(TINYINT, self).__init__(display_width=display_width, **kw)
336class SMALLINT(_IntegerType, sqltypes.SMALLINT):
337 """MySQL SMALLINTEGER type."""
339 __visit_name__ = "SMALLINT"
341 def __init__(self, display_width=None, **kw):
342 """Construct a SMALLINTEGER.
344 :param display_width: Optional, maximum display width for this number.
346 :param unsigned: a boolean, optional.
348 :param zerofill: Optional. If true, values will be stored as strings
349 left-padded with zeros. Note that this does not effect the values
350 returned by the underlying database API, which continue to be
351 numeric.
353 """
354 super(SMALLINT, self).__init__(display_width=display_width, **kw)
357class BIT(sqltypes.TypeEngine):
358 """MySQL BIT type.
360 This type is for MySQL 5.0.3 or greater for MyISAM, and 5.0.5 or greater
361 for MyISAM, MEMORY, InnoDB and BDB. For older versions, use a
362 MSTinyInteger() type.
364 """
366 __visit_name__ = "BIT"
368 def __init__(self, length=None):
369 """Construct a BIT.
371 :param length: Optional, number of bits.
373 """
374 self.length = length
376 def result_processor(self, dialect, coltype):
377 """Convert a MySQL's 64 bit, variable length binary string to a long.
379 TODO: this is MySQL-db, pyodbc specific. OurSQL and mysqlconnector
380 already do this, so this logic should be moved to those dialects.
382 """
384 def process(value):
385 if value is not None:
386 v = 0
387 for i in value:
388 if not isinstance(i, int):
389 i = ord(i) # convert byte to int on Python 2
390 v = v << 8 | i
391 return v
392 return value
394 return process
397class TIME(sqltypes.TIME):
398 """MySQL TIME type. """
400 __visit_name__ = "TIME"
402 def __init__(self, timezone=False, fsp=None):
403 """Construct a MySQL TIME type.
405 :param timezone: not used by the MySQL dialect.
406 :param fsp: fractional seconds precision value.
407 MySQL 5.6 supports storage of fractional seconds;
408 this parameter will be used when emitting DDL
409 for the TIME type.
411 .. note::
413 DBAPI driver support for fractional seconds may
414 be limited; current support includes
415 MySQL Connector/Python.
417 """
418 super(TIME, self).__init__(timezone=timezone)
419 self.fsp = fsp
421 def result_processor(self, dialect, coltype):
422 time = datetime.time
424 def process(value):
425 # convert from a timedelta value
426 if value is not None:
427 microseconds = value.microseconds
428 seconds = value.seconds
429 minutes = seconds // 60
430 return time(
431 minutes // 60,
432 minutes % 60,
433 seconds - minutes * 60,
434 microsecond=microseconds,
435 )
436 else:
437 return None
439 return process
442class TIMESTAMP(sqltypes.TIMESTAMP):
443 """MySQL TIMESTAMP type.
445 """
447 __visit_name__ = "TIMESTAMP"
449 def __init__(self, timezone=False, fsp=None):
450 """Construct a MySQL TIMESTAMP type.
452 :param timezone: not used by the MySQL dialect.
453 :param fsp: fractional seconds precision value.
454 MySQL 5.6.4 supports storage of fractional seconds;
455 this parameter will be used when emitting DDL
456 for the TIMESTAMP type.
458 .. note::
460 DBAPI driver support for fractional seconds may
461 be limited; current support includes
462 MySQL Connector/Python.
464 """
465 super(TIMESTAMP, self).__init__(timezone=timezone)
466 self.fsp = fsp
469class DATETIME(sqltypes.DATETIME):
470 """MySQL DATETIME type.
472 """
474 __visit_name__ = "DATETIME"
476 def __init__(self, timezone=False, fsp=None):
477 """Construct a MySQL DATETIME type.
479 :param timezone: not used by the MySQL dialect.
480 :param fsp: fractional seconds precision value.
481 MySQL 5.6.4 supports storage of fractional seconds;
482 this parameter will be used when emitting DDL
483 for the DATETIME type.
485 .. note::
487 DBAPI driver support for fractional seconds may
488 be limited; current support includes
489 MySQL Connector/Python.
491 """
492 super(DATETIME, self).__init__(timezone=timezone)
493 self.fsp = fsp
496class YEAR(sqltypes.TypeEngine):
497 """MySQL YEAR type, for single byte storage of years 1901-2155."""
499 __visit_name__ = "YEAR"
501 def __init__(self, display_width=None):
502 self.display_width = display_width
505class TEXT(_StringType, sqltypes.TEXT):
506 """MySQL TEXT type, for text up to 2^16 characters."""
508 __visit_name__ = "TEXT"
510 def __init__(self, length=None, **kw):
511 """Construct a TEXT.
513 :param length: Optional, if provided the server may optimize storage
514 by substituting the smallest TEXT type sufficient to store
515 ``length`` characters.
517 :param charset: Optional, a column-level character set for this string
518 value. Takes precedence to 'ascii' or 'unicode' short-hand.
520 :param collation: Optional, a column-level collation for this string
521 value. Takes precedence to 'binary' short-hand.
523 :param ascii: Defaults to False: short-hand for the ``latin1``
524 character set, generates ASCII in schema.
526 :param unicode: Defaults to False: short-hand for the ``ucs2``
527 character set, generates UNICODE in schema.
529 :param national: Optional. If true, use the server's configured
530 national character set.
532 :param binary: Defaults to False: short-hand, pick the binary
533 collation type that matches the column's character set. Generates
534 BINARY in schema. This does not affect the type of data stored,
535 only the collation of character data.
537 """
538 super(TEXT, self).__init__(length=length, **kw)
541class TINYTEXT(_StringType):
542 """MySQL TINYTEXT type, for text up to 2^8 characters."""
544 __visit_name__ = "TINYTEXT"
546 def __init__(self, **kwargs):
547 """Construct a TINYTEXT.
549 :param charset: Optional, a column-level character set for this string
550 value. Takes precedence to 'ascii' or 'unicode' short-hand.
552 :param collation: Optional, a column-level collation for this string
553 value. Takes precedence to 'binary' short-hand.
555 :param ascii: Defaults to False: short-hand for the ``latin1``
556 character set, generates ASCII in schema.
558 :param unicode: Defaults to False: short-hand for the ``ucs2``
559 character set, generates UNICODE in schema.
561 :param national: Optional. If true, use the server's configured
562 national character set.
564 :param binary: Defaults to False: short-hand, pick the binary
565 collation type that matches the column's character set. Generates
566 BINARY in schema. This does not affect the type of data stored,
567 only the collation of character data.
569 """
570 super(TINYTEXT, self).__init__(**kwargs)
573class MEDIUMTEXT(_StringType):
574 """MySQL MEDIUMTEXT type, for text up to 2^24 characters."""
576 __visit_name__ = "MEDIUMTEXT"
578 def __init__(self, **kwargs):
579 """Construct a MEDIUMTEXT.
581 :param charset: Optional, a column-level character set for this string
582 value. Takes precedence to 'ascii' or 'unicode' short-hand.
584 :param collation: Optional, a column-level collation for this string
585 value. Takes precedence to 'binary' short-hand.
587 :param ascii: Defaults to False: short-hand for the ``latin1``
588 character set, generates ASCII in schema.
590 :param unicode: Defaults to False: short-hand for the ``ucs2``
591 character set, generates UNICODE in schema.
593 :param national: Optional. If true, use the server's configured
594 national character set.
596 :param binary: Defaults to False: short-hand, pick the binary
597 collation type that matches the column's character set. Generates
598 BINARY in schema. This does not affect the type of data stored,
599 only the collation of character data.
601 """
602 super(MEDIUMTEXT, self).__init__(**kwargs)
605class LONGTEXT(_StringType):
606 """MySQL LONGTEXT type, for text up to 2^32 characters."""
608 __visit_name__ = "LONGTEXT"
610 def __init__(self, **kwargs):
611 """Construct a LONGTEXT.
613 :param charset: Optional, a column-level character set for this string
614 value. Takes precedence to 'ascii' or 'unicode' short-hand.
616 :param collation: Optional, a column-level collation for this string
617 value. Takes precedence to 'binary' short-hand.
619 :param ascii: Defaults to False: short-hand for the ``latin1``
620 character set, generates ASCII in schema.
622 :param unicode: Defaults to False: short-hand for the ``ucs2``
623 character set, generates UNICODE in schema.
625 :param national: Optional. If true, use the server's configured
626 national character set.
628 :param binary: Defaults to False: short-hand, pick the binary
629 collation type that matches the column's character set. Generates
630 BINARY in schema. This does not affect the type of data stored,
631 only the collation of character data.
633 """
634 super(LONGTEXT, self).__init__(**kwargs)
637class VARCHAR(_StringType, sqltypes.VARCHAR):
638 """MySQL VARCHAR type, for variable-length character data."""
640 __visit_name__ = "VARCHAR"
642 def __init__(self, length=None, **kwargs):
643 """Construct a VARCHAR.
645 :param charset: Optional, a column-level character set for this string
646 value. Takes precedence to 'ascii' or 'unicode' short-hand.
648 :param collation: Optional, a column-level collation for this string
649 value. Takes precedence to 'binary' short-hand.
651 :param ascii: Defaults to False: short-hand for the ``latin1``
652 character set, generates ASCII in schema.
654 :param unicode: Defaults to False: short-hand for the ``ucs2``
655 character set, generates UNICODE in schema.
657 :param national: Optional. If true, use the server's configured
658 national character set.
660 :param binary: Defaults to False: short-hand, pick the binary
661 collation type that matches the column's character set. Generates
662 BINARY in schema. This does not affect the type of data stored,
663 only the collation of character data.
665 """
666 super(VARCHAR, self).__init__(length=length, **kwargs)
669class CHAR(_StringType, sqltypes.CHAR):
670 """MySQL CHAR type, for fixed-length character data."""
672 __visit_name__ = "CHAR"
674 def __init__(self, length=None, **kwargs):
675 """Construct a CHAR.
677 :param length: Maximum data length, in characters.
679 :param binary: Optional, use the default binary collation for the
680 national character set. This does not affect the type of data
681 stored, use a BINARY type for binary data.
683 :param collation: Optional, request a particular collation. Must be
684 compatible with the national character set.
686 """
687 super(CHAR, self).__init__(length=length, **kwargs)
689 @classmethod
690 def _adapt_string_for_cast(self, type_):
691 # copy the given string type into a CHAR
692 # for the purposes of rendering a CAST expression
693 type_ = sqltypes.to_instance(type_)
694 if isinstance(type_, sqltypes.CHAR):
695 return type_
696 elif isinstance(type_, _StringType):
697 return CHAR(
698 length=type_.length,
699 charset=type_.charset,
700 collation=type_.collation,
701 ascii=type_.ascii,
702 binary=type_.binary,
703 unicode=type_.unicode,
704 national=False, # not supported in CAST
705 )
706 else:
707 return CHAR(length=type_.length)
710class NVARCHAR(_StringType, sqltypes.NVARCHAR):
711 """MySQL NVARCHAR type.
713 For variable-length character data in the server's configured national
714 character set.
715 """
717 __visit_name__ = "NVARCHAR"
719 def __init__(self, length=None, **kwargs):
720 """Construct an NVARCHAR.
722 :param length: Maximum data length, in characters.
724 :param binary: Optional, use the default binary collation for the
725 national character set. This does not affect the type of data
726 stored, use a BINARY type for binary data.
728 :param collation: Optional, request a particular collation. Must be
729 compatible with the national character set.
731 """
732 kwargs["national"] = True
733 super(NVARCHAR, self).__init__(length=length, **kwargs)
736class NCHAR(_StringType, sqltypes.NCHAR):
737 """MySQL NCHAR type.
739 For fixed-length character data in the server's configured national
740 character set.
741 """
743 __visit_name__ = "NCHAR"
745 def __init__(self, length=None, **kwargs):
746 """Construct an NCHAR.
748 :param length: Maximum data length, in characters.
750 :param binary: Optional, use the default binary collation for the
751 national character set. This does not affect the type of data
752 stored, use a BINARY type for binary data.
754 :param collation: Optional, request a particular collation. Must be
755 compatible with the national character set.
757 """
758 kwargs["national"] = True
759 super(NCHAR, self).__init__(length=length, **kwargs)
762class TINYBLOB(sqltypes._Binary):
763 """MySQL TINYBLOB type, for binary data up to 2^8 bytes."""
765 __visit_name__ = "TINYBLOB"
768class MEDIUMBLOB(sqltypes._Binary):
769 """MySQL MEDIUMBLOB type, for binary data up to 2^24 bytes."""
771 __visit_name__ = "MEDIUMBLOB"
774class LONGBLOB(sqltypes._Binary):
775 """MySQL LONGBLOB type, for binary data up to 2^32 bytes."""
777 __visit_name__ = "LONGBLOB"