~ubuntu-branches/debian/jessie/sqlalchemy/jessie

« back to all changes in this revision

Viewing changes to doc/_sources/core/types.txt

  • Committer: Package Import Robot
  • Author(s): Piotr Ożarowski, Jakub Wilk, Piotr Ożarowski
  • Date: 2013-07-06 20:53:52 UTC
  • mfrom: (1.4.23) (16.1.17 experimental)
  • Revision ID: package-import@ubuntu.com-20130706205352-ryppl1eto3illd79
Tags: 0.8.2-1
[ Jakub Wilk ]
* Use canonical URIs for Vcs-* fields.

[ Piotr Ożarowski ]
* New upstream release
* Upload to unstable
* Build depend on python3-all instead of -dev, extensions are not built for
  Python 3.X 

Show diffs side-by-side

added added

removed removed

Lines of Context:
197
197
database's dialect module. See the :ref:`sqlalchemy.dialects_toplevel`
198
198
reference for the database you're interested in.
199
199
 
200
 
For example, MySQL has a ``BIGINTEGER`` type and PostgreSQL has an
 
200
For example, MySQL has a ``BIGINT`` type and PostgreSQL has an
201
201
``INET`` type.  To use these, import them from the module explicitly::
202
202
 
203
203
    from sqlalchemy.dialects import mysql
204
204
 
205
 
    table = Table('foo', meta,
206
 
        Column('id', mysql.BIGINTEGER),
 
205
    table = Table('foo', metadata,
 
206
        Column('id', mysql.BIGINT),
207
207
        Column('enumerates', mysql.ENUM('a', 'b', 'c'))
208
208
    )
209
209
 
211
211
 
212
212
    from sqlalchemy.dialects import postgresql
213
213
 
214
 
    table = Table('foo', meta,
 
214
    table = Table('foo', metadata,
215
215
        Column('ipaddress', postgresql.INET),
216
 
        Column('elements', postgresql.ARRAY(str))
217
 
        )
 
216
        Column('elements', postgresql.ARRAY(String))
 
217
    )
218
218
 
219
219
Each dialect provides the full set of typenames supported by
220
220
that backend within its `__all__` collection, so that a simple
279
279
See the section :ref:`type_compilation_extension`, a subsection of
280
280
:ref:`sqlalchemy.ext.compiler_toplevel`, for additional examples.
281
281
 
 
282
.. _types_typedecorator:
 
283
 
282
284
Augmenting Existing Types
283
285
~~~~~~~~~~~~~~~~~~~~~~~~~
284
286
 
287
289
type object.  It is used when additional in-Python marshaling of data
288
290
to and from the database is required.
289
291
 
 
292
.. note::
 
293
 
 
294
  The bind- and result-processing of :class:`.TypeDecorator`
 
295
  is *in addition* to the processing already performed by the hosted
 
296
  type, which is customized by SQLAlchemy on a per-DBAPI basis to perform
 
297
  processing specific to that DBAPI.  To change the DBAPI-level processing
 
298
  for an existing type, see the section :ref:`replacing_processors`.
 
299
 
290
300
.. autoclass:: TypeDecorator
291
301
   :members:
292
 
   :undoc-members:
293
302
   :inherited-members:
294
303
   :show-inheritance:
295
304
 
437
446
support for mutability is best applied using the ``sqlalchemy.ext.mutable``
438
447
extension - see the example in :ref:`mutable_toplevel`.
439
448
 
 
449
.. _replacing_processors:
 
450
 
 
451
Replacing the Bind/Result Processing of Existing Types
 
452
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
453
 
 
454
Most augmentation of type behavior at the bind/result level
 
455
is achieved using :class:`.TypeDecorator`.   For the rare scenario
 
456
where the specific processing applied by SQLAlchemy at the DBAPI
 
457
level needs to be replaced, the SQLAlchemy type can be subclassed
 
458
directly, and the ``bind_processor()`` or ``result_processor()``
 
459
methods can be overridden.   Doing so requires that the
 
460
``adapt()`` method also be overridden.  This method is the mechanism
 
461
by which SQLAlchemy produces DBAPI-specific type behavior during
 
462
statement execution.  Overriding it allows a copy of the custom
 
463
type to be used in lieu of a DBAPI-specific type.  Below we subclass
 
464
the :class:`.types.TIME` type to have custom result processing behavior.
 
465
The ``process()`` function will receive ``value`` from the DBAPI
 
466
cursor directly::
 
467
 
 
468
  class MySpecialTime(TIME):
 
469
      def __init__(self, special_argument):
 
470
          super(MySpecialTime, self).__init__()
 
471
          self.special_argument = special_argument
 
472
 
 
473
      def result_processor(self, dialect, coltype):
 
474
          import datetime
 
475
          time = datetime.time
 
476
          def process(value):
 
477
              if value is not None:
 
478
                  microseconds = value.microseconds
 
479
                  seconds = value.seconds
 
480
                  minutes = seconds / 60
 
481
                  return time(
 
482
                            minutes / 60,
 
483
                            minutes % 60,
 
484
                            seconds - minutes * 60,
 
485
                            microseconds)
 
486
              else:
 
487
                  return None
 
488
          return process
 
489
 
 
490
      def adapt(self, impltype):
 
491
          return MySpecialTime(self.special_argument)
 
492
 
 
493
.. _types_sql_value_processing:
 
494
 
 
495
Applying SQL-level Bind/Result Processing
 
496
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
497
 
 
498
As seen in the sections :ref:`types_typedecorator` and :ref:`replacing_processors`,
 
499
SQLAlchemy allows Python functions to be invoked both when parameters are sent
 
500
to a statement, as well as when result rows are loaded from the database, to apply
 
501
transformations to the values as they are sent to or from the database.   It is also
 
502
possible to define SQL-level transformations as well.  The rationale here is when
 
503
only the relational database contains a particular series of functions that are necessary
 
504
to coerce incoming and outgoing data between an application and persistence format.
 
505
Examples include using database-defined encryption/decryption functions, as well
 
506
as stored procedures that handle geographic data.  The Postgis extension to Postgresql
 
507
includes an extensive array of SQL functions that are necessary for coercing
 
508
data into particular formats.
 
509
 
 
510
Any :class:`.TypeEngine`, :class:`.UserDefinedType` or :class:`.TypeDecorator` subclass
 
511
can include implementations of
 
512
:meth:`.TypeEngine.bind_expression` and/or :meth:`.TypeEngine.column_expression`, which
 
513
when defined to return a non-``None`` value should return a :class:`.ColumnElement`
 
514
expression to be injected into the SQL statement, either surrounding
 
515
bound parameters or a column expression.  For example, to build a ``Geometry``
 
516
type which will apply the Postgis function ``ST_GeomFromText`` to all outgoing
 
517
values and the function ``ST_AsText`` to all incoming data, we can create
 
518
our own subclass of :class:`.UserDefinedType` which provides these methods
 
519
in conjunction with :data:`~.sqlalchemy.sql.expression.func`::
 
520
 
 
521
    from sqlalchemy import func
 
522
    from sqlalchemy.types import UserDefinedType
 
523
 
 
524
    class Geometry(UserDefinedType):
 
525
        def get_col_spec(self):
 
526
            return "GEOMETRY"
 
527
 
 
528
        def bind_expression(self, bindvalue):
 
529
            return func.ST_GeomFromText(bindvalue, type_=self)
 
530
 
 
531
        def column_expression(self, col):
 
532
            return func.ST_AsText(col, type_=self)
 
533
 
 
534
We can apply the ``Geometry`` type into :class:`.Table` metadata
 
535
and use it in a :func:`.select` construct::
 
536
 
 
537
    geometry = Table('geometry', metadata,
 
538
                  Column('geom_id', Integer, primary_key=True),
 
539
                  Column('geom_data', Geometry)
 
540
                )
 
541
 
 
542
    print select([geometry]).where(
 
543
      geometry.c.geom_data == 'LINESTRING(189412 252431,189631 259122)')
 
544
 
 
545
The resulting SQL embeds both functions as appropriate.   ``ST_AsText``
 
546
is applied to the columns clause so that the return value is run through
 
547
the function before passing into a result set, and ``ST_GeomFromText``
 
548
is run on the bound parameter so that the passed-in value is converted::
 
549
 
 
550
    SELECT geometry.geom_id, ST_AsText(geometry.geom_data) AS geom_data_1
 
551
    FROM geometry
 
552
    WHERE geometry.geom_data = ST_GeomFromText(:geom_data_2)
 
553
 
 
554
The :meth:`.TypeEngine.column_expression` method interacts with the
 
555
mechanics of the compiler such that the SQL expression does not interfere
 
556
with the labeling of the wrapped expression.   Such as, if we rendered
 
557
a :func:`.select` against a :func:`.label` of our expression, the string
 
558
label is moved to the outside of the wrapped expression::
 
559
 
 
560
    print select([geometry.c.geom_data.label('my_data')])
 
561
 
 
562
Output::
 
563
 
 
564
    SELECT ST_AsText(geometry.geom_data) AS my_data
 
565
    FROM geometry
 
566
 
 
567
For an example of subclassing a built in type directly, we subclass
 
568
:class:`.postgresql.BYTEA` to provide a ``PGPString``, which will make use of the
 
569
Postgresql ``pgcrypto`` extension to encrpyt/decrypt values
 
570
transparently::
 
571
 
 
572
    from sqlalchemy import create_engine, String, select, func, \
 
573
            MetaData, Table, Column, type_coerce
 
574
 
 
575
    from sqlalchemy.dialects.postgresql import BYTEA
 
576
 
 
577
    class PGPString(BYTEA):
 
578
        def __init__(self, passphrase, length=None):
 
579
            super(PGPString, self).__init__(length)
 
580
            self.passphrase = passphrase
 
581
 
 
582
        def bind_expression(self, bindvalue):
 
583
            # convert the bind's type from PGPString to
 
584
            # String, so that it's passed to psycopg2 as is without
 
585
            # a dbapi.Binary wrapper
 
586
            bindvalue = type_coerce(bindvalue, String)
 
587
            return func.pgp_sym_encrypt(bindvalue, self.passphrase)
 
588
 
 
589
        def column_expression(self, col):
 
590
            return func.pgp_sym_decrypt(col, self.passphrase)
 
591
 
 
592
    metadata = MetaData()
 
593
    message = Table('message', metadata,
 
594
                    Column('username', String(50)),
 
595
                    Column('message',
 
596
                        PGPString("this is my passphrase", length=1000)),
 
597
                )
 
598
 
 
599
    engine = create_engine("postgresql://scott:tiger@localhost/test", echo=True)
 
600
    with engine.begin() as conn:
 
601
        metadata.create_all(conn)
 
602
 
 
603
        conn.execute(message.insert(), username="some user",
 
604
                                    message="this is my message")
 
605
 
 
606
        print conn.scalar(
 
607
                select([message.c.message]).\
 
608
                    where(message.c.username == "some user")
 
609
            )
 
610
 
 
611
The ``pgp_sym_encrypt`` and ``pgp_sym_decrypt`` functions are applied
 
612
to the INSERT and SELECT statements::
 
613
 
 
614
  INSERT INTO message (username, message)
 
615
    VALUES (%(username)s, pgp_sym_encrypt(%(message)s, %(pgp_sym_encrypt_1)s))
 
616
    {'username': 'some user', 'message': 'this is my message',
 
617
      'pgp_sym_encrypt_1': 'this is my passphrase'}
 
618
 
 
619
  SELECT pgp_sym_decrypt(message.message, %(pgp_sym_decrypt_1)s) AS message_1
 
620
    FROM message
 
621
    WHERE message.username = %(username_1)s
 
622
    {'pgp_sym_decrypt_1': 'this is my passphrase', 'username_1': 'some user'}
 
623
 
 
624
 
 
625
.. versionadded:: 0.8  Added the :meth:`.TypeEngine.bind_expression` and
 
626
   :meth:`.TypeEngine.column_expression` methods.
 
627
 
 
628
See also:
 
629
 
 
630
:ref:`examples_postgis`
 
631
 
 
632
.. _types_operators:
 
633
 
 
634
Redefining and Creating New Operators
 
635
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
636
 
 
637
SQLAlchemy Core defines a fixed set of expression operators available to all column expressions.
 
638
Some of these operations have the effect of overloading Python's built in operators;
 
639
examples of such operators include
 
640
:meth:`.ColumnOperators.__eq__` (``table.c.somecolumn == 'foo'``),
 
641
:meth:`.ColumnOperators.__invert__` (``~table.c.flag``),
 
642
and :meth:`.ColumnOperators.__add__` (``table.c.x + table.c.y``).  Other operators are exposed as
 
643
explicit methods on column expressions, such as
 
644
:meth:`.ColumnOperators.in_` (``table.c.value.in_(['x', 'y'])``) and :meth:`.ColumnOperators.like`
 
645
(``table.c.value.like('%ed%')``).
 
646
 
 
647
The Core expression constructs in all cases consult the type of the expression in order to determine
 
648
the behavior of existing operators, as well as to locate additional operators that aren't part of
 
649
the built in set.   The :class:`.TypeEngine` base class defines a root "comparison" implementation
 
650
:class:`.TypeEngine.Comparator`, and many specific types provide their own sub-implementations of this
 
651
class.   User-defined :class:`.TypeEngine.Comparator` implementations can be built directly into a
 
652
simple subclass of a particular type in order to override or define new operations.  Below,
 
653
we create a :class:`.Integer` subclass which overrides the :meth:`.ColumnOperators.__add__` operator::
 
654
 
 
655
    from sqlalchemy import Integer
 
656
 
 
657
    class MyInt(Integer):
 
658
        class comparator_factory(Integer.Comparator):
 
659
            def __add__(self, other):
 
660
                return self.op("goofy")(other)
 
661
 
 
662
The above configuration creates a new class ``MyInt``, which
 
663
establishes the :attr:`.TypeEngine.comparator_factory` attribute as
 
664
referring to a new class, subclassing the :class:`.TypeEngine.Comparator` class
 
665
associated with the :class:`.Integer` type.
 
666
 
 
667
Usage::
 
668
 
 
669
    >>> sometable = Table("sometable", metadata, Column("data", MyInt))
 
670
    >>> print sometable.c.data + 5
 
671
    sometable.data goofy :data_1
 
672
 
 
673
The implementation for :meth:`.ColumnOperators.__add__` is consulted
 
674
by an owning SQL expression, by instantiating the :class:`.TypeEngine.Comparator` with
 
675
itself as the ``expr`` attribute.   The mechanics of the expression
 
676
system are such that operations continue recursively until an
 
677
expression object produces a new SQL expression construct. Above, we
 
678
could just as well have said ``self.expr.op("goofy")(other)`` instead
 
679
of ``self.op("goofy")(other)``.
 
680
 
 
681
New methods added to a :class:`.TypeEngine.Comparator` are exposed on an
 
682
owning SQL expression
 
683
using a ``__getattr__`` scheme, which exposes methods added to
 
684
:class:`.TypeEngine.Comparator` onto the owning :class:`.ColumnElement`.
 
685
For example, to add a ``log()`` function
 
686
to integers::
 
687
 
 
688
    from sqlalchemy import Integer, func
 
689
 
 
690
    class MyInt(Integer):
 
691
        class comparator_factory(Integer.Comparator):
 
692
            def log(self, other):
 
693
                return func.log(self, other)
 
694
 
 
695
Using the above type::
 
696
 
 
697
    >>> print sometable.c.data.log(5)
 
698
    log(:log_1, :log_2)
 
699
 
 
700
 
 
701
Unary operations
 
702
are also possible.  For example, to add an implementation of the
 
703
Postgresql factorial operator, we combine the :class:`.UnaryExpression` construct
 
704
along with a :class:`.custom_op` to produce the factorial expression::
 
705
 
 
706
    from sqlalchemy import Integer
 
707
    from sqlalchemy.sql.expression import UnaryExpression
 
708
    from sqlalchemy.sql import operators
 
709
 
 
710
    class MyInteger(Integer):
 
711
        class comparator_factory(Integer.Comparator):
 
712
            def factorial(self):
 
713
                return UnaryExpression(self.expr,
 
714
                            modifier=operators.custom_op("!"),
 
715
                            type_=MyInteger)
 
716
 
 
717
Using the above type::
 
718
 
 
719
    >>> from sqlalchemy.sql import column
 
720
    >>> print column('x', MyInteger).factorial()
 
721
    x !
 
722
 
 
723
See also:
 
724
 
 
725
:attr:`.TypeEngine.comparator_factory`
 
726
 
 
727
.. versionadded:: 0.8  The expression system was enhanced to support
 
728
  customization of operators on a per-type level.
 
729
 
 
730
 
440
731
Creating New Types
441
732
~~~~~~~~~~~~~~~~~~
442
733
 
447
738
 
448
739
.. autoclass:: UserDefinedType
449
740
   :members:
450
 
   :undoc-members:
451
 
   :inherited-members:
452
741
   :show-inheritance:
453
742
 
454
743
.. _types_api:
458
747
 
459
748
.. autoclass:: AbstractType
460
749
   :members:
461
 
   :undoc-members:
462
 
   :inherited-members:
463
750
   :show-inheritance:
464
751
 
465
752
.. autoclass:: TypeEngine
466
753
   :members:
467
 
   :undoc-members:
468
 
   :inherited-members:
469
 
   :show-inheritance:
470
 
 
471
 
.. autoclass:: MutableType
472
 
   :members:
473
 
   :undoc-members:
474
 
   :inherited-members:
475
754
   :show-inheritance:
476
755
 
477
756
.. autoclass:: Concatenable
478
757
   :members:
479
 
   :undoc-members:
480
758
   :inherited-members:
481
759
   :show-inheritance:
482
760