text:
"""
.. dialect:: postgresql
    :name: PostgreSQL

Sequences/SERIAL
----------------

PostgreSQL supports sequences, and SQLAlchemy uses these as the default means
of creating new primary key values for integer-based primary key columns. When
creating tables, SQLAlchemy will issue the ``SERIAL`` datatype for
integer-based primary key columns, which generates a sequence and server side
default corresponding to the column.

To specify a specific named sequence to be used for primary key generation,
use the :func:`~sqlalchemy.schema.Sequence` construct::

    Table('sometable', metadata,
            Column('id', Integer, Sequence('some_id_seq'), primary_key=True)
        )

When SQLAlchemy issues a single INSERT statement, to fulfill the contract of
having the "last insert identifier" available, a RETURNING clause is added to
the INSERT statement which specifies the primary key columns should be
returned after the statement completes. The RETURNING functionality only takes
place if Postgresql 8.2 or later is in use. As a fallback approach, the
sequence, whether specified explicitly or implicitly via ``SERIAL``, is
executed independently beforehand, the returned value to be used in the
subsequent insert. Note that when an
:func:`~sqlalchemy.sql.expression.insert()` construct is executed using
"executemany" semantics, the "last inserted identifier" functionality does not
apply; no RETURNING clause is emitted nor is the sequence pre-executed in this
case.

To force the usage of RETURNING by default off, specify the flag
``implicit_returning=False`` to :func:`.create_engine`.

.. _postgresql_isolation_level:

Transaction Isolation Level
---------------------------

All Postgresql dialects support setting of transaction isolation level
both via a dialect-specific parameter ``isolation_level``
accepted by :func:`.create_engine`,
as well as the ``isolation_level`` argument as passed to :meth:`.Connection.execution_options`.
When using a non-psycopg2 dialect, this feature works by issuing the
command ``SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL
<level>`` for each new connection.

To set isolation level using :func:`.create_engine`::

    engine = create_engine(
                    "postgresql+pg8000://scott:tiger@localhost/test",
                    isolation_level="READ UNCOMMITTED"
                )

To set using per-connection execution options::

    connection = engine.connect()
    connection = connection.execution_options(isolation_level="READ COMMITTED")

Valid values for ``isolation_level`` include:

* ``READ COMMITTED``
* ``READ UNCOMMITTED``
* ``REPEATABLE READ``
* ``SERIALIZABLE``

The :mod:`~sqlalchemy.dialects.postgresql.psycopg2` dialect also offers the special level ``AUTOCOMMIT``.  See
:ref:`psycopg2_isolation_level` for details.

Remote / Cross-Schema Table Introspection
-----------------------------------------

Tables can be introspected from any accessible schema, including
inter-schema foreign key relationships.   However, care must be taken
when specifying the "schema" argument for a given :class:`.Table`, when
the given schema is also present in PostgreSQL's ``search_path`` variable
for the current connection.

If a FOREIGN KEY constraint reports that the remote table's schema is within
the current ``search_path``, the "schema" attribute of the resulting
:class:`.Table` will be set to ``None``, unless the actual schema of the
remote table matches that of the referencing table, and the "schema" argument
was explicitly stated on the referencing table.

The best practice here is to not use the ``schema`` argument
on :class:`.Table` for any schemas that are present in ``search_path``.
``search_path`` defaults to "public", but care should be taken
to inspect the actual value using::

    SHOW search_path;

.. versionchanged:: 0.7.3
    Prior to this version, cross-schema foreign keys when the schemas
    were also in the ``search_path`` could make an incorrect assumption
    if the schemas were explicitly stated on each :class:`.Table`.

Background on PG's ``search_path`` is at:
http://www.postgresql.org/docs/9.0/static/ddl-schemas.html#DDL-SCHEMAS-PATH

INSERT/UPDATE...RETURNING
-------------------------

The dialect supports PG 8.2's ``INSERT..RETURNING``, ``UPDATE..RETURNING`` and
``DELETE..RETURNING`` syntaxes.   ``INSERT..RETURNING`` is used by default
for single-row INSERT statements in order to fetch newly generated
primary key identifiers.   To specify an explicit ``RETURNING`` clause,
use the :meth:`._UpdateBase.returning` method on a per-statement basis::

    # INSERT..RETURNING
    result = table.insert().returning(table.c.col1, table.c.col2).\\
        values(name='foo')
    print result.fetchall()

    # UPDATE..RETURNING
    result = table.update().returning(table.c.col1, table.c.col2).\\
        where(table.c.name=='foo').values(name='bar')
    print result.fetchall()

    # DELETE..RETURNING
    result = table.delete().returning(table.c.col1, table.c.col2).\\
        where(table.c.name=='foo')
    print result.fetchall()

FROM ONLY ...
------------------------

The dialect supports PostgreSQL's ONLY keyword for targeting only a particular
table in an inheritance hierarchy. This can be used to produce the
``SELECT ... FROM ONLY``, ``UPDATE ONLY ...``, and ``DELETE FROM ONLY ...``
syntaxes. It uses SQLAlchemy's hints mechanism::

    # SELECT ... FROM ONLY ...
    result = table.select().with_hint(table, 'ONLY', 'postgresql')
    print result.fetchall()

    # UPDATE ONLY ...
    table.update(values=dict(foo='bar')).with_hint('ONLY',
                                                   dialect_name='postgresql')

    # DELETE FROM ONLY ...
    table.delete().with_hint('ONLY', dialect_name='postgresql')

.. _postgresql_indexes:

Postgresql-Specific Index Options
---------------------------------

Several extensions to the :class:`.Index` construct are available, specific
to the PostgreSQL dialect.

Partial Indexes
^^^^^^^^^^^^^^^^

Partial indexes add criterion to the index definition so that the index is
applied to a subset of rows.   These can be specified on :class:`.Index`
using the ``postgresql_where`` keyword argument::

  Index('my_index', my_table.c.id, postgresql_where=tbl.c.value > 10)

Operator Classes
^^^^^^^^^^^^^^^^^

PostgreSQL allows the specification of an *operator class* for each column of
an index (see
http://www.postgresql.org/docs/8.3/interactive/indexes-opclass.html).
The :class:`.Index` construct allows these to be specified via the
``postgresql_ops`` keyword argument::

    Index('my_index', my_table.c.id, my_table.c.data,
                            postgresql_ops={
                                'data': 'text_pattern_ops',
                                'id': 'int4_ops'
                            })

.. versionadded:: 0.7.2
    ``postgresql_ops`` keyword argument to :class:`.Index` construct.

Note that the keys in the ``postgresql_ops`` dictionary are the "key" name of
the :class:`.Column`, i.e. the name used to access it from the ``.c``
collection of :class:`.Table`, which can be configured to be different than
the actual name of the column as expressed in the database.

Index Types
^^^^^^^^^^^^

PostgreSQL provides several index types: B-Tree, Hash, GiST, and GIN, as well
as the ability for users to create their own (see
http://www.postgresql.org/docs/8.3/static/indexes-types.html). These can be
specified on :class:`.Index` using the ``postgresql_using`` keyword argument::

    Index('my_index', my_table.c.data, postgresql_using='gin')

The value passed to the keyword argument will be simply passed through to the
underlying CREATE INDEX command, so it *must* be a valid index type for your
version of PostgreSQL.

"""

from collections import defaultdict
import re

from ... import sql, schema, exc, util
from ...engine import default, reflection
from ...sql import compiler, expression, util as sql_util, operators
from ... import types as sqltypes

try:
    from uuid import UUID as _python_UUID
except ImportError:
    _python_UUID = None

from sqlalchemy.types import INTEGER, BIGINT, SMALLINT, VARCHAR, \
        CHAR, TEXT, FLOAT, NUMERIC, \
        DATE, BOOLEAN, REAL

RESERVED_WORDS = set(
    ["all", "analyse", "analyze", "and", "any", "array", "as", "asc",
    "asymmetric", "both", "case", "cast", "check", "collate", "column",
    "constraint", "create", "current_catalog", "current_date",
    "current_role", "current_time", "current_timestamp", "current_user",
    "default", "deferrable", "desc", "distinct", "do", "else", "end",
    "except", "false", "fetch", "for", "foreign", "from", "grant", "group",
    "having", "in", "initially", "intersect", "into", "leading", "limit",
    "localtime", "localtimestamp", "new", "not", "null", "off", "offset",
    "old", "on", "only", "or", "order", "placing", "primary", "references",
    "returning", "select", "session_user", "some", "symmetric", "table",
    "then", "to", "trailing", "true", "union", "unique", "user", "using",
    "variadic", "when", "where", "window", "with", "authorization",
    "between", "binary", "cross", "current_schema", "freeze", "full",
    "ilike", "inner", "is", "isnull", "join", "left", "like", "natural",
    "notnull", "outer", "over", "overlaps", "right", "similar", "verbose"
    ])

_DECIMAL_TYPES = (1231, 1700)
_FLOAT_TYPES = (700, 701, 1021, 1022)
_INT_TYPES = (20, 21, 23, 26, 1005, 1007, 1016)

class BYTEA(sqltypes.LargeBinary):
    __visit_name__ = 'BYTEA'

class DOUBLE_PRECISION(sqltypes.Float):
    __visit_name__ = 'DOUBLE_PRECISION'

class INET(sqltypes.TypeEngine):
    __visit_name__ = "INET"
PGInet = INET

class CIDR(sqltypes.TypeEngine):
    __visit_name__ = "CIDR"
PGCidr = CIDR

class MACADDR(sqltypes.TypeEngine):
    __visit_name__ = "MACADDR"
PGMacAddr = MACADDR

class TIMESTAMP(sqltypes.TIMESTAMP):
    def __init__(self, timezone=False, precision=None):
        super(TIMESTAMP, self).__init__(timezone=timezone)
        self.precision = precision

class TIME(sqltypes.TIME):
    def __init__(self, timezone=False, precision=None):
        super(TIME, self).__init__(timezone=timezone)
        self.precision = precision

class INTERVAL(sqltypes.TypeEngine):
    """Postgresql INTERVAL type.

    The INTERVAL type may not be supported on all DBAPIs.
    It is known to work on psycopg2 and not pg8000 or zxjdbc.

    """
    __visit_name__ = 'INTERVAL'

    def __init__(self, precision=None):
        self.precision = precision

    @classmethod
    def _adapt_from_generic_interval(cls, interval):
        return INTERVAL(precision=interval.second_precision)

    @property
    def _type_affinity(self):
        return sqltypes.Interval

PGInterval = INTERVAL

class BIT(sqltypes.TypeEngine):
    __visit_name__ = 'BIT'

    def __init__(self, length=None, varying=False):
        if not varying:
            # BIT without VARYING defaults to length 1
            self.length = length or 1
        else:
            # but BIT VARYING can be unlimited-length, so no default
            self.length = length
        self.varying = varying

PGBit = BIT

class UUID(sqltypes.TypeEngine):
    """Postgresql UUID type.

    Represents the UUID column type, interpreting
    data either as natively returned by the DBAPI
    or as Python uuid objects.

    The UUID type may not be supported on all DBAPIs.
    It is known to work on psycopg2 and not pg8000.

    """
    __visit_name__ = 'UUID'

    def __init__(self, as_uuid=False):
        """Construct a UUID type.

        :param as_uuid=False: if True, values will be interpreted
         as Python uuid objects, converting to/from string via the
         DBAPI.

         """
        if as_uuid and _python_UUID is None:
            raise NotImplementedError(
                "This version of Python does not support the native UUID type."
            )
        self.as_uuid = as_uuid

    def bind_processor(self, dialect):
        if self.as_uuid:
            def process(value):
                if value is not None:
                    value = str(value)
                return value
            return process
        else:
            return None

    def result_processor(self, dialect, coltype):
        if self.as_uuid:
            def process(value):
                if value is not None:
                    value = _python_UUID(value)
                return value
            return process
        else:
            return None

PGUuid = UUID

class _Slice(expression.ColumnElement):
    __visit_name__ = 'slice'
    type = sqltypes.NULLTYPE

    def __init__(self, slice_, source_comparator):
        self.start = source_comparator._check_literal(
                            source_comparator.expr,
                            operators.getitem, slice_.start)
        self.stop = source_comparator._check_literal(
                            source_comparator.expr,
                            operators.getitem, slice_.stop)

class Any(expression.ColumnElement):
    """Represent the clause ``left operator ANY (right)``.  ``right`` must be
    an array expression.

    .. seealso::

        :class:`.postgresql.ARRAY`

        :meth:`.postgresql.ARRAY.Comparator.any` - ARRAY-bound method

    """
    __visit_name__ = 'any'

    def __init__(self, left, right, operator=operators.eq):
        self.type = sqltypes.Boolean()
        self.left = expression._literal_as_binds(left)
        self.right = right
        self.operator = operator

class All(expression.ColumnElement):
    """Represent the clause ``left operator ALL (right)``.  ``right`` must be
    an array expression.

    .. seealso::

        :class:`.postgresql.ARRAY`

        :meth:`.postgresql.ARRAY.Comparator.all` - ARRAY-bound method

    """
    __visit_name__ = 'all'

    def __init__(self, left, right, operator=operators.eq):
        self.type = sqltypes.Boolean()
        self.left = expression._literal_as_binds(left)
        self.right = right
        self.operator = operator

class array(expression.Tuple):
    """A Postgresql ARRAY literal.

    This is used to produce ARRAY literals in SQL expressions, e.g.::

        from sqlalchemy.dialects.postgresql import array
        from sqlalchemy.dialects import postgresql
        from sqlalchemy import select, func

        stmt = select([
                        array([1,2]) + array([3,4,5])
                    ])

        print stmt.compile(dialect=postgresql.dialect())

    Produces the SQL::

        SELECT ARRAY[%(param_1)s, %(param_2)s] ||
            ARRAY[%(param_3)s, %(param_4)s, %(param_5)s]) AS anon_1

    An instance of :class:`.array` will always have the datatype
    :class:`.ARRAY`.  The "inner" type of the array is inferred from
    the values present, unless the ``type_`` keyword argument is passed::

        array(['foo', 'bar'], type_=CHAR)

    .. versionadded:: 0.8 Added the :class:`~.postgresql.array` literal type.

    See also:

    :class:`.postgresql.ARRAY`

    """
    __visit_name__ = 'array'

    def __init__(self, clauses, **kw):
        super(array, self).__init__(*clauses, **kw)
        self.type = ARRAY(self.type)

    def _bind_param(self, operator, obj):
        return array(*[
            expression.BindParameter(None, o, _compared_to_operator=operator,
                             _compared_to_type=self.type, unique=True)
            for o in obj
        ])

    def self_group(self, against=None):
        return self

class ARRAY(sqltypes.Concatenable, sqltypes.TypeEngine):
    """Postgresql ARRAY type.

    Represents values as Python lists.

    An :class:`.ARRAY` type is constructed given the "type"
    of element::

        mytable = Table("mytable", metadata,
                Column("data", ARRAY(Integer))
            )

    The above type represents an N-dimensional array,
    meaning Postgresql will interpret values with any number
    of dimensions automatically.   To produce an INSERT
    construct that passes in a 1-dimensional array of integers::

        connection.execute(
                mytable.insert(),
                data=[1,2,3]
        )

    The :class:`.ARRAY` type can be constructed given a fixed number
    of dimensions::

        mytable = Table("mytable", metadata,
                Column("data", ARRAY(Integer, dimensions=2))
            )

    This has the effect of the :class:`.ARRAY` type
    specifying that number of bracketed blocks when a :class:`.Table`
    is used in a CREATE TABLE statement, or when the type is used
    within a :func:`.expression.cast` construct; it also causes
    the bind parameter and result set processing of the type
    to optimize itself to expect exactly that number of dimensions.
    Note that Postgresql itself still allows N dimensions with such a type.

    SQL expressions of type :class:`.ARRAY` have support for "index" and
    "slice" behavior.  The Python ``[]`` operator works normally here, given
    integer indexes or slices.  Note that Postgresql arrays default
    to 1-based indexing.  The operator produces binary expression
    constructs which will produce the appropriate SQL, both for
    SELECT statements::

        select([mytable.c.data[5], mytable.c.data[2:7]])

    as well as UPDATE statements when the :meth:`.Update.values` method
    is used::

        mytable.update().values({
            mytable.c.data[5]: 7,
            mytable.c.data[2:7]: [1, 2, 3]
        })

    :class:`.ARRAY` provides special methods for containment operations,
    e.g.::

        mytable.c.data.contains([1, 2])

    For a full list of special methods see :class:`.ARRAY.Comparator`.

    .. versionadded:: 0.8 Added support for index and slice operations
       to the :class:`.ARRAY` type, including support for UPDATE
       statements, and special array containment operations.

    The :class:`.ARRAY` type may not be supported on all DBAPIs.
    It is known to work on psycopg2 and not pg8000.

    See also:

    :class:`.postgresql.array` - produce a literal array value.

    """
    __visit_name__ = 'ARRAY'

    class Comparator(sqltypes.Concatenable.Comparator):
        """Define comparison operations for :class:`.ARRAY`."""

        def __getitem__(self, index):
            if isinstance(index, slice):
                index = _Slice(index, self)
                return_type = self.type
            else:
                return_type = self.type.item_type
            return self._binary_operate(self.expr, operators.getitem, index,
                            result_type=return_type)

        def any(self, other, operator=operators.eq):
            """Return ``other operator ANY (array)`` clause.

            Argument places are switched, because ANY requires array
            expression to be on the right hand-side.

            E.g.::

                from sqlalchemy.sql import operators

                conn.execute(
                    select([table.c.data]).where(
                            table.c.data.any(7, operator=operators.lt)
                        )
                )

            :param other: expression to be compared
            :param operator: an operator object from the
             :mod:`sqlalchemy.sql.operators`
             package, defaults to :func:`.operators.eq`.

            .. seealso::

                :class:`.postgresql.Any`

                :meth:`.postgresql.ARRAY.Comparator.all`

            """
            return Any(other, self.expr, operator=operator)

        def all(self, other, operator=operators.eq):
            """Return ``other operator ALL (array)`` clause.

            Argument places are switched, because ALL requires array
            expression to be on the right hand-side.

            E.g.::

                from sqlalchemy.sql import operators

                conn.execute(
                    select([table.c.data]).where(
                            table.c.data.all(7, operator=operators.lt)
                        )
                )

            :param other: expression to be compared
            :param operator: an operator object from the
             :mod:`sqlalchemy.sql.operators`
             package, defaults to :func:`.operators.eq`.

            .. seealso::

                :class:`.postgresql.All`

                :meth:`.postgresql.ARRAY.Comparator.any`

            """
            return All(other, self.expr, operator=operator)

        def contains(self, other, **kwargs):
            """Boolean expression.  Test if elements are a superset of the
            elements of the argument array expression.
            """
            return self.expr.op('@>')(other)

        def contained_by(self, other):
            """Boolean expression.  Test if elements are a proper subset of the
            elements of the argument array expression.
            """
            return self.expr.op('<@')(other)

        def overlap(self, other):
            """Boolean expression.  Test if array has elements in common with
            an argument array expression.
            """
            return self.expr.op('&&')(other)

        def _adapt_expression(self, op, other_comparator):
            if isinstance(op, operators.custom_op):
                if op.opstring in ['@>', '<@', '&&']:
                    return op, sqltypes.Boolean
            return sqltypes.Concatenable.Comparator.\
                _adapt_expression(self, op, other_comparator)

    comparator_factory = Comparator

    def __init__(self, item_type, as_tuple=False, dimensions=None):
        """Construct an ARRAY.

        E.g.::

          Column('myarray', ARRAY(Integer))

        Arguments are:

        :param item_type: The data type of items of this array. Note that
          dimensionality is irrelevant here, so multi-dimensional arrays like
          ``INTEGER[][]``, are constructed as ``ARRAY(Integer)``, not as
          ``ARRAY(ARRAY(Integer))`` or such.

        :param as_tuple=False: Specify whether return results
          should be converted to tuples from lists. DBAPIs such
          as psycopg2 return lists by default. When tuples are
          returned, the results are hashable.

        :param dimensions: if non-None, the ARRAY will assume a fixed
         number of dimensions.  This will cause the DDL emitted for this
         ARRAY to include the exact number of bracket clauses ``[]``,
         and will also optimize the performance of the type overall.
         Note that PG arrays are always implicitly "non-dimensioned",
         meaning they can store any number of dimensions no matter how
         they were declared.

        """
        if isinstance(item_type, ARRAY):
            raise ValueError("Do not nest ARRAY types; ARRAY(basetype) "
                            "handles multi-dimensional arrays of basetype")
        if isinstance(item_type, type):
            item_type = item_type()
        self.item_type = item_type
        self.as_tuple = as_tuple
        self.dimensions = dimensions

    def compare_values(self, x, y):
        return x == y

    def _proc_array(self, arr, itemproc, dim, collection):
        if dim is None:
            arr = list(arr)
        if dim == 1 or dim is None and (
                        # this has to be (list, tuple), or at least
                        # not hasattr('__iter__'), since Py3K strings
                        # etc. have __iter__
                        not arr or not isinstance(arr[0], (list, tuple))):
            if itemproc:
                return collection(itemproc(x) for x in arr)
            else:
                return collection(arr)
        else:
            return collection(
                    self._proc_array(
                            x, itemproc,
                            dim - 1 if dim is not None else None,
                            collection)
                    for x in arr
                )

    def bind_processor(self, dialect):
        item_proc = self.item_type.\
                        dialect_impl(dialect).\
                        bind_processor(dialect)

        def process(value):
            if value is None:
                return value
            else:
                return self._proc_array(
                            value,
                            item_proc,
                            self.dimensions,
                            list)
        return process

    def result_processor(self, dialect, coltype):
        item_proc = self.item_type.\
                        dialect_impl(dialect).\
                        result_processor(dialect, coltype)

        def process(value):
            if value is None:
                return value
            else:
                return self._proc_array(
                            value,
                            item_proc,
                            self.dimensions,
                            tuple if self.as_tuple else list)
        return process

PGArray = ARRAY

class ENUM(sqltypes.Enum):
    """Postgresql ENUM type.

    This is a subclass of :class:`.types.Enum` which includes
    support for PG's ``CREATE TYPE``.

    :class:`~.postgresql.ENUM` is used automatically when
    using the :class:`.types.Enum` type on PG assuming
    the ``native_enum`` is left as ``True``.   However, the
    :class:`~.postgresql.ENUM` class can also be instantiated
    directly in order to access some additional Postgresql-specific
    options, namely finer control over whether or not
    ``CREATE TYPE`` should be emitted.

    Note that both :class:`.types.Enum` as well as
    :class:`~.postgresql.ENUM` feature create/drop
    methods; the base :class:`.types.Enum` type ultimately
    delegates to the :meth:`~.postgresql.ENUM.create` and
    :meth:`~.postgresql.ENUM.drop` methods present here.

    """

    def __init__(self, *enums, **kw):
        """Construct an :class:`~.postgresql.ENUM`.

        Arguments are the same as that of
        :class:`.types.Enum`, but also including
        the following parameters.

        :param create_type: Defaults to True.
         Indicates that ``CREATE TYPE`` should be
         emitted, after optionally checking for the
         presence of the type, when the parent
         table is being created; and additionally
         that ``DROP TYPE`` is called when the table
         is dropped.    When ``False``, no check
         will be performed and no ``CREATE TYPE``
         or ``DROP TYPE`` is emitted, unless
         :meth:`~.postgresql.ENUM.create`
         or :meth:`~.postgresql.ENUM.drop`
         are called directly.
         Setting to ``False`` is helpful
         when invoking a creation scheme to a SQL file
         without access to the actual database -
         the :meth:`~.postgresql.ENUM.create` and
         :meth:`~.postgresql.ENUM.drop` methods can
         be used to emit SQL to a target bind.

         .. versionadded:: 0.7.4

        """
        self.create_type = kw.pop("create_type", True)
        super(ENUM, self).__init__(*enums, **kw)

    def create(self, bind=None, checkfirst=True):
        """Emit ``CREATE TYPE`` for this
        :class:`~.postgresql.ENUM`.

        If the underlying dialect does not support
        Postgresql CREATE TYPE, no action is taken.

        :param bind: a connectable :class:`.Engine`,
         :class:`.Connection`, or similar object to emit
         SQL.
        :param checkfirst: if ``True``, a query against
         the PG catalog will be first performed to see
         if the type does not exist already before
         creating.

        """
        if not bind.dialect.supports_native_enum:
            return

        if not checkfirst or \
            not bind.dialect.has_type(bind, self.name, schema=self.schema):
            bind.execute(CreateEnumType(self))

    def drop(self, bind=None, checkfirst=True):
        """Emit ``DROP TYPE`` for this
        :class:`~.postgresql.ENUM`.

        If the underlying dialect does not support
        Postgresql DROP TYPE, no action is taken.

        :param bind: a connectable :class:`.Engine`,
         :class:`.Connection`, or similar object to emit
         SQL.
        :param checkfirst: if ``True``, a query against
         the PG catalog will be first performed to see
         if the type actually exists before dropping.

        """
        if not bind.dialect.supports_native_enum:
            return

        if not checkfirst or \
            bind.dialect.has_type(bind, self.name, schema=self.schema):
            bind.execute(DropEnumType(self))

    def _check_for_name_in_memos(self, checkfirst, kw):
        """Look in the 'ddl runner' for 'memos', then
        note our name in that collection.

        This to ensure a particular named enum is operated
        upon only once within any kind of create/drop
        sequence without relying upon "checkfirst".

        """
        if not self.create_type:
            return True
        if '_ddl_runner' in kw:
            ddl_runner = kw['_ddl_runner']
            if '_pg_enums' in ddl_runner.memo:
                pg_enums = ddl_runner.memo['_pg_enums']
            else:
                pg_enums = ddl_runner.memo['_pg_enums'] = set()
            present = self.name in pg_enums
            pg_enums.add(self.name)
            return present
        else:
            return False

    def _on_table_create(self, target, bind, checkfirst, **kw):
        if not self._check_for_name_in_memos(checkfirst, kw):
            self.create(bind=bind, checkfirst=checkfirst)

    def _on_metadata_create(self, target, bind, checkfirst, **kw):
        if self.metadata is not None and \
            not self._check_for_name_in_memos(checkfirst, kw):
            self.create(bind=bind, checkfirst=checkfirst)

    def _on_metadata_drop(self, target, bind, checkfirst, **kw):
        if not self._check_for_name_in_memos(checkfirst, kw):
            self.drop(bind=bind, checkfirst=checkfirst)

colspecs = {
    sqltypes.Interval: INTERVAL,
    sqltypes.Enum: ENUM,
}

ischema_names = {
    'integer': INTEGER,
    'bigint': BIGINT,
    'smallint': SMALLINT,
    'character varying': VARCHAR,
    'character': CHAR,
    '"char"': sqltypes.String,
    'name': sqltypes.String,
    'text': TEXT,
    'numeric': NUMERIC,
    'float': FLOAT,
    'real': REAL,
    'inet': INET,
    'cidr': CIDR,
    'uuid': UUID,
    'bit': BIT,
    'bit varying': BIT,
    'macaddr': MACADDR,
    'double precision': DOUBLE_PRECISION,
    'timestamp': TIMESTAMP,
    'timestamp with time zone': TIMESTAMP,
    'timestamp without time zone': TIMESTAMP,
    'time with time zone': TIME,
    'time without time zone': TIME,
    'date': DATE,
    'time': TIME,
    'bytea': BYTEA,
    'boolean': BOOLEAN,
    'interval': INTERVAL,
    'interval year to month': INTERVAL,
    'interval day to second': INTERVAL,
}

class PGCompiler(compiler.SQLCompiler):

    def visit_array(self, element, **kw):
        return "ARRAY[%s]" % self.visit_clauselist(element, **kw)

    def visit_slice(self, element, **kw):
        return "%s:%s" % (
                    self.process(element.start, **kw),
                    self.process(element.stop, **kw),
                )

    def visit_any(self, element, **kw):
        return "%s%sANY (%s)" % (
            self.process(element.left, **kw),
            compiler.OPERATORS[element.operator],
            self.process(element.right, **kw)
        )

    def visit_all(self, element, **kw):
        return "%s%sALL (%s)" % (
            self.process(element.left, **kw),
            compiler.OPERATORS[element.operator],
            self.process(element.right, **kw)
        )

    def visit_getitem_binary(self, binary, operator, **kw):
        return "%s[%s]" % (
                self.process(binary.left, **kw),
                self.process(binary.right, **kw)
            )

    def visit_match_op_binary(self, binary, operator, **kw):
        return "%s @@ to_tsquery(%s)" % (
                        self.process(binary.left, **kw),
                        self.process(binary.right, **kw))

    def visit_ilike_op_binary(self, binary, operator, **kw):
        escape = binary.modifiers.get("escape", None)
        return '%s ILIKE %s' % \
                (self.process(binary.left, **kw),
                    self.process(binary.right, **kw)) \
                + (escape and
                        (' ESCAPE ' + self.render_literal_value(escape, None))
                        or '')

    def visit_notilike_op_binary(self, binary, operator, **kw):
        escape = binary.modifiers.get("escape", None)
        return '%s NOT ILIKE %s' % \
                (self.process(binary.left, **kw),
                    self.process(binary.right, **kw)) \
                + (escape and
                        (' ESCAPE ' + self.render_literal_value(escape, None))
                        or '')

    def render_literal_value(self, value, type_):
        value = super(PGCompiler, self).render_literal_value(value, type_)
        # TODO: need to inspect "standard_conforming_strings"
        if self.dialect._backslash_escapes:
            value = value.replace('\\', '\\\\')
        return value

    def visit_sequence(self, seq):
        return "nextval('%s')" % self.preparer.format_sequence(seq)

    def limit_clause(self, select):
        text = ""
        if select._limit is not None:
            text += " \n LIMIT " + self.process(sql.literal(select._limit))
        if select._offset is not None:
            if select._limit is None:
                text += " \n LIMIT ALL"
            text += " OFFSET " + self.process(sql.literal(select._offset))
        return text

    def format_from_hint_text(self, sqltext, table, hint, iscrud):
        if hint.upper() != 'ONLY':
            raise exc.CompileError("Unrecognized hint: %r" % hint)
        return "ONLY " + sqltext

    def get_select_precolumns(self, select):
        if select._distinct is not False:
            if select._distinct is True:
                return "DISTINCT "
            elif isinstance(select._distinct, (list, tuple)):
                return "DISTINCT ON (" + ', '.join(
                    [self.process(col) for col in select._distinct]
                ) + ") "
            else:
                return "DISTINCT ON (" + self.process(select._distinct) + ") "
        else:
            return ""

    def for_update_clause(self, select):
        if select.for_update == 'nowait':
            return " FOR UPDATE NOWAIT"
        elif select.for_update == 'read':
            return " FOR SHARE"
        elif select.for_update == 'read_nowait':
            return " FOR SHARE NOWAIT"
        else:
            return super(PGCompiler, self).for_update_clause(select)

    def returning_clause(self, stmt, returning_cols):

        columns = [
                self._label_select_column(None, c, True, False, {})
                for c in expression._select_iterables(returning_cols)
            ]

        return 'RETURNING ' + ', '.join(columns)

    def visit_substring_func(self, func, **kw):
        s = self.process(func.clauses.clauses[0], **kw)
        start = self.process(func.clauses.clauses[1], **kw)
        if len(func.clauses.clauses) > 2:
            length = self.process(func.clauses.clauses[2], **kw)
            return "SUBSTRING(%s FROM %s FOR %s)" % (s, start, length)
        else:
            return "SUBSTRING(%s FROM %s)" % (s, start)

class PGDDLCompiler(compiler.DDLCompiler):
    def get_column_specification(self, column, **kwargs):
        colspec = self.preparer.format_column(column)
        impl_type = column.type.dialect_impl(self.dialect)
        if column.primary_key and \
            column is column.table._autoincrement_column and \
            not isinstance(impl_type, sqltypes.SmallInteger) and \
            (
                column.default is None or
                (
                    isinstance(column.default, schema.Sequence) and
                    column.default.optional
                )):
            if isinstance(impl_type, sqltypes.BigInteger):
                colspec += " BIGSERIAL"
            else:
                colspec += " SERIAL"
        else:
            colspec += " " + self.dialect.type_compiler.process(column.type)
            default = self.get_column_default_string(column)
            if default is not None:
                colspec += " DEFAULT " + default

        if not column.nullable:
            colspec += " NOT NULL"
        return colspec

    def visit_create_enum_type(self, create):
        type_ = create.element

        return "CREATE TYPE %s AS ENUM (%s)" % (
            self.preparer.format_type(type_),
            ",".join("'%s'" % e for e in type_.enums)
        )

    def visit_drop_enum_type(self, drop):
        type_ = drop.element

        return "DROP TYPE %s" % (
            self.preparer.format_type(type_)
        )

    def visit_create_index(self, create):
        preparer = self.preparer
        index = create.element
        self._verify_index_table(index)
        text = "CREATE "
        if index.unique:
            text += "UNIQUE "
        text += "INDEX %s ON %s " % (
                        self._prepared_index_name(index,
                                include_schema=False),
                    preparer.format_table(index.table)
                )

        if 'postgresql_using' in index.kwargs:
            using = index.kwargs['postgresql_using']
            text += "USING %s " % preparer.quote(using, index.quote)

        ops = index.kwargs.get('postgresql_ops', {})
        text += "(%s)" \
                % (
                    ', '.join([
                        self.sql_compiler.process(expr, include_table=False) +

                        (c.key in ops and (' ' + ops[c.key]) or '')

                        for expr, c in zip(index.expressions, index.columns)])
                    )

        if 'postgresql_where' in index.kwargs:
            whereclause = index.kwargs['postgresql_where']
        else:
            whereclause = None

        if whereclause is not None:
            whereclause = sql_util.expression_as_ddl(whereclause)
            where_compiled = self.sql_compiler.process(whereclause)
            text += " WHERE " + where_compiled
        return text

    def visit_exclude_constraint(self, constraint):
        text = ""
        if constraint.name is not None:
            text += "CONSTRAINT %s " % \
                    self.preparer.format_constraint(constraint)
        elements = []
        for c in constraint.columns:
            op = constraint.operators[c.name]
            elements.append(self.preparer.quote(c.name, c.quote)+' WITH '+op)
        text += "EXCLUDE USING %s (%s)" % (constraint.using, ', '.join(elements))
        if constraint.where is not None:
            sqltext = sql_util.expression_as_ddl(constraint.where)
            text += ' WHERE (%s)' % self.sql_compiler.process(sqltext)
        text += self.define_constraint_deferrability(constraint)
        return text

class PGTypeCompiler(compiler.GenericTypeCompiler):
    def visit_INET(self, type_):
        return "INET"

    def visit_CIDR(self, type_):
        return "CIDR"

    def visit_MACADDR(self, type_):
        return "MACADDR"

    def visit_FLOAT(self, type_):
        if not type_.precision:
            return "FLOAT"
        else:
            return "FLOAT(%(precision)s)" % {'precision': type_.precision}

    def visit_DOUBLE_PRECISION(self, type_):
        return "DOUBLE PRECISION"

    def visit_BIGINT(self, type_):
        return "BIGINT"

    def visit_HSTORE(self, type_):
        return "HSTORE"

    def visit_INT4RANGE(self, type_):
        return "INT4RANGE"

    def visit_INT8RANGE(self, type_):
        return "INT8RANGE"

    def visit_NUMRANGE(self, type_):
        return "NUMRANGE"

    def visit_DATERANGE(self, type_):
        return "DATERANGE"

    def visit_TSRANGE(self, type_):
        return "TSRANGE"

    def visit_TSTZRANGE(self, type_):
        return "TSTZRANGE"

    def visit_datetime(self, type_):
        return self.visit_TIMESTAMP(type_)

    def visit_enum(self, type_):
        if not type_.native_enum or not self.dialect.supports_native_enum:
            return super(PGTypeCompiler, self).visit_enum(type_)
        else:
            return self.visit_ENUM(type_)

    def visit_ENUM(self, type_):
        return self.dialect.identifier_preparer.format_type(type_)

    def visit_TIMESTAMP(self, type_):
        return "TIMESTAMP%s %s" % (
            getattr(type_, 'precision', None) and "(%d)" %
            type_.precision or "",
            (type_.timezone and "WITH" or "WITHOUT") + " TIME ZONE"
        )

    def visit_TIME(self, type_):
        return "TIME%s %s" % (
            getattr(type_, 'precision', None) and "(%d)" %
            type_.precision or "",
            (type_.timezone and "WITH" or "WITHOUT") + " TIME ZONE"
        )

    def visit_INTERVAL(self, type_):
        if type_.precision is not None:
            return "INTERVAL(%d)" % type_.precision
        else:
            return "INTERVAL"

    def visit_BIT(self, type_):
        if type_.varying:
            compiled = "BIT VARYING"
            if type_.length is not None:
                compiled += "(%d)" % type_.length
        else:
            compiled = "BIT(%d)" % type_.length
        return compiled

    def visit_UUID(self, type_):
        return "UUID"

    def visit_large_binary(self, type_):
        return self.visit_BYTEA(type_)

    def visit_BYTEA(self, type_):
        return "BYTEA"

    def visit_ARRAY(self, type_):
        return self.process(type_.item_type) + ('[]' * (type_.dimensions
                                                if type_.dimensions
                                                is not None else 1))

class PGIdentifierPreparer(compiler.IdentifierPreparer):

    reserved_words = RESERVED_WORDS

    def _unquote_identifier(self, value):
        if value[0] == self.initial_quote:
            value = value[1:-1].\
                        replace(self.escape_to_quote, self.escape_quote)
        return value

    def format_type(self, type_, use_schema=True):
        if not type_.name:
            raise exc.CompileError("Postgresql ENUM type requires a name.")

        name = self.quote(type_.name, type_.quote)
        if not self.omit_schema and use_schema and type_.schema is not None:
            name = self.quote_schema(type_.schema, type_.quote) + "." + name
        return name

class PGInspector(reflection.Inspector):

    def __init__(self, conn):
        reflection.Inspector.__init__(self, conn)

    def get_table_oid(self, table_name, schema=None):
        """Return the oid from `table_name` and `schema`."""

        return self.dialect.get_table_oid(self.bind, table_name, schema,
                                          info_cache=self.info_cache)

class CreateEnumType(schema._CreateDropBase):
    __visit_name__ = "create_enum_type"

class DropEnumType(schema._CreateDropBase):
    __visit_name__ = "drop_enum_type"

class PGExecutionContext(default.DefaultExecutionContext):
    def fire_sequence(self, seq, type_):
        return self._execute_scalar(("select nextval('%s')" % \
                self.dialect.identifier_preparer.format_sequence(seq)), type_)

    def get_insert_default(self, column):
        if column.primary_key and column is column.table._autoincrement_column:
            if column.server_default and column.server_default.has_argument:

                # pre-execute passive defaults on primary key columns
                return self._execute_scalar("select %s" %
                                    column.server_default.arg, column.type)

            elif (column.default is None or
                        (column.default.is_sequence and
                        column.default.optional)):

                # execute the sequence associated with a SERIAL primary
                # key column. for non-primary-key SERIAL, the ID just
                # generates server side.

                try:
                    seq_name = column._postgresql_seq_name
                except AttributeError:
                    tab = column.table.name
                    col = column.name
                    tab = tab[0:29 + max(0, (29 - len(col)))]
                    col = col[0:29 + max(0, (29 - len(tab)))]
                    name = "%s_%s_seq" % (tab, col)
                    column._postgresql_seq_name = seq_name = name

                sch = column.table.schema
                if sch is not None:
                    exc = "select nextval('\"%s\".\"%s\"')" % \
                            (sch, seq_name)
                else:
                    exc = "select nextval('\"%s\"')" % \
                            (seq_name, )

                return self._execute_scalar(exc, column.type)

        return super(PGExecutionContext, self).get_insert_default(column)

class PGDialect(default.DefaultDialect):
    name = 'postgresql'
    supports_alter = True
    max_identifier_length = 63
    supports_sane_rowcount = True

    supports_native_enum = True
    supports_native_boolean = True

    supports_sequences = True
    sequences_optional = True
    preexecute_autoincrement_sequences = True
    postfetch_lastrowid = False

    supports_default_values = True
    supports_empty_insert = False
    supports_multivalues_insert = True
    default_paramstyle = 'pyformat'
    ischema_names = ischema_names
    colspecs = colspecs

    statement_compiler = PGCompiler
    ddl_compiler = PGDDLCompiler
    type_compiler = PGTypeCompiler
    preparer = PGIdentifierPreparer
    execution_ctx_cls = PGExecutionContext
    inspector = PGInspector
    isolation_level = None

    # TODO: need to inspect "standard_conforming_strings"
    _backslash_escapes = True

    def __init__(self, isolation_level=None, **kwargs):
        default.DefaultDialect.__init__(self, **kwargs)
        self.isolation_level = isolation_level

    def initialize(self, connection):
        super(PGDialect, self).initialize(connection)
        self.implicit_returning = self.server_version_info > (8, 2) and \
                            self.__dict__.get('implicit_returning', True)
        self.supports_native_enum = self.server_version_info >= (8, 3)
        if not self.supports_native_enum:
            self.colspecs = self.colspecs.copy()
            # pop base Enum type
            self.colspecs.pop(sqltypes.Enum, None)
            # psycopg2, others may have placed ENUM here as well
            self.colspecs.pop(ENUM, None)

    def on_connect(self):
        if self.isolation_level is not None:
            def connect(conn):
                self.set_isolation_level(conn, self.isolation_level)
            return connect
        else:
            return None

    _isolation_lookup = set(['SERIALIZABLE',
                'READ UNCOMMITTED', 'READ COMMITTED', 'REPEATABLE READ'])

    def set_isolation_level(self, connection, level):
        level = level.replace('_', ' ')
        if level not in self._isolation_lookup:
            raise exc.ArgumentError(
                "Invalid value '%s' for isolation_level. "
                "Valid isolation levels for %s are %s" %
                (level, self.name, ", ".join(self._isolation_lookup))
                )
        cursor = connection.cursor()
        cursor.execute(
            "SET SESSION CHARACTERISTICS AS TRANSACTION "
            "ISOLATION LEVEL %s" % level)
        cursor.execute("COMMIT")
        cursor.close()

    def get_isolation_level(self, connection):
        cursor = connection.cursor()
        cursor.execute('show transaction isolation level')
        val = cursor.fetchone()[0]
        cursor.close()
        return val.upper()

    def do_begin_twophase(self, connection, xid):
        self.do_begin(connection.connection)

    def do_prepare_twophase(self, connection, xid):
        connection.execute("PREPARE TRANSACTION '%s'" % xid)

    def do_rollback_twophase(self, connection, xid,
                                is_prepared=True, recover=False):
        if is_prepared:
            if recover:
                #FIXME: ugly hack to get out of transaction
                # context when committing recoverable transactions
                # Must find out a way how to make the dbapi not
                # open a transaction.
                connection.execute("ROLLBACK")
            connection.execute("ROLLBACK PREPARED '%s'" % xid)
            connection.execute("BEGIN")
            self.do_rollback(connection.connection)
        else:
            self.do_rollback(connection.connection)

    def do_commit_twophase(self, connection, xid,
                                is_prepared=True, recover=False):
        if is_prepared:
            if recover:
                connection.execute("ROLLBACK")
            connection.execute("COMMIT PREPARED '%s'" % xid)
            connection.execute("BEGIN")
            self.do_rollback(connection.connection)
        else:
            self.do_commit(connection.connection)

    def do_recover_twophase(self, connection):
        resultset = connection.execute(
                    sql.text("SELECT gid FROM pg_prepared_xacts"))
        return [row[0] for row in resultset]

    def _get_default_schema_name(self, connection):
        return connection.scalar("select current_schema()")

    def has_schema(self, connection, schema):
        query = "select nspname from pg_namespace where lower(nspname)=:schema"
        cursor = connection.execute(
            sql.text(
                query,
                bindparams=[
                    sql.bindparam(
                        'schema', unicode(schema.lower()),
                        type_=sqltypes.Unicode)]
            )
        )

        return bool(cursor.first())

    def has_table(self, connection, table_name, schema=None):
        # seems like case gets folded in pg_class...
        if schema is None:
            cursor = connection.execute(
                sql.text(
                "select relname from pg_class c join pg_namespace n on "
                "n.oid=c.relnamespace where n.nspname=current_schema() and "
                "relname=:name",
                bindparams=[
                        sql.bindparam('name', unicode(table_name),
                        type_=sqltypes.Unicode)]
                )
            )
        else:
            cursor = connection.execute(
                sql.text(
                "select relname from pg_class c join pg_namespace n on "
                "n.oid=c.relnamespace where n.nspname=:schema and "
                "relname=:name",
                    bindparams=[
                        sql.bindparam('name',
                        unicode(table_name), type_=sqltypes.Unicode),
                        sql.bindparam('schema',
                        unicode(schema), type_=sqltypes.Unicode)]
                )
            )
        return bool(cursor.first())

    def has_sequence(self, connection, sequence_name, schema=None):
        if schema is None:
            cursor = connection.execute(
                sql.text(
                    "SELECT relname FROM pg_class c join pg_namespace n on "
                    "n.oid=c.relnamespace where relkind='S' and "
                    "n.nspname=current_schema() "
                    "and relname=:name",
                    bindparams=[
                        sql.bindparam('name', unicode(sequence_name),
                        type_=sqltypes.Unicode)
                    ]
                )
            )
        else:
            cursor = connection.execute(
                sql.text(
                "SELECT relname FROM pg_class c join pg_namespace n on "
                "n.oid=c.relnamespace where relkind='S' and "
                "n.nspname=:schema and relname=:name",
                bindparams=[
                    sql.bindparam('name', unicode(sequence_name),
                     type_=sqltypes.Unicode),
                    sql.bindparam('schema',
                                unicode(schema), type_=sqltypes.Unicode)
                ]
            )
            )

        return bool(cursor.first())

    def has_type(self, connection, type_name, schema=None):
        bindparams = [
            sql.bindparam('typname',
                unicode(type_name), type_=sqltypes.Unicode),
            sql.bindparam('nspname',
                unicode(schema), type_=sqltypes.Unicode),
            ]
        if schema is not None:
            query = """
            SELECT EXISTS (
                SELECT * FROM pg_catalog.pg_type t, pg_catalog.pg_namespace n
                WHERE t.typnamespace = n.oid
                AND t.typname = :typname
                AND n.nspname = :nspname
                )
                """
        else:
            query = """
            SELECT EXISTS (
                SELECT * FROM pg_catalog.pg_type t
                WHERE t.typname = :typname
                AND pg_type_is_visible(t.oid)
                )
                """
        cursor = connection.execute(sql.text(query, bindparams=bindparams))
        return bool(cursor.scalar())

    def _get_server_version_info(self, connection):
        v = connection.execute("select version()").scalar()
        m = re.match(
            '(?:PostgreSQL|EnterpriseDB) '
            '(\d+)\.(\d+)(?:\.(\d+))?(?:\.\d+)?(?:devel)?',
            v)
        if not m:
            raise AssertionError(
                    "Could not determine version from string '%s'" % v)
        return tuple([int(x) for x in m.group(1, 2, 3) if x is not None])

    @reflection.cache
    def get_table_oid(self, connection, table_name, schema=None, **kw):
        """Fetch the oid for schema.table_name.

        Several reflection methods require the table oid.  The idea for using
        this method is that it can be fetched one time and cached for
        subsequent calls.

        """
        table_oid = None
        if schema is not None:
            schema_where_clause = "n.nspname = :schema"
        else:
            schema_where_clause = "pg_catalog.pg_table_is_visible(c.oid)"
        query = """
            SELECT c.oid
            FROM pg_catalog.pg_class c
            LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
            WHERE (%s)
            AND c.relname = :table_name AND c.relkind in ('r','v')
        """ % schema_where_clause
        # Since we're binding to unicode, table_name and schema_name must be
        # unicode.
        table_name = unicode(table_name)
        if schema is not None:
            schema = unicode(schema)
        s = sql.text(query, bindparams=[
            sql.bindparam('table_name', type_=sqltypes.Unicode),
            sql.bindparam('schema', type_=sqltypes.Unicode)
            ],
            typemap={'oid': sqltypes.Integer}
        )
        c = connection.execute(s, table_name=table_name, schema=schema)
        table_oid = c.scalar()
        if table_oid is None:
            raise exc.NoSuchTableError(table_name)
        return table_oid

    @reflection.cache
    def get_schema_names(self, connection, **kw):
        s = """
        SELECT nspname
        FROM pg_namespace
        ORDER BY nspname
        """
        rp = connection.execute(s)
        # what about system tables?
        # Py3K
        #schema_names = [row[0] for row in rp \
        #                if not row[0].startswith('pg_')]
        # Py2K
        schema_names = [row[0].decode(self.encoding) for row in rp \
                        if not row[0].startswith('pg_')]
        # end Py2K
        return schema_names

    @reflection.cache
    def get_table_names(self, connection, schema=None, **kw):
        if schema is not None:
            current_schema = schema
        else:
            current_schema = self.default_schema_name

        result = connection.execute(
            sql.text(u"SELECT relname FROM pg_class c "
                "WHERE relkind = 'r' "
                "AND '%s' = (select nspname from pg_namespace n "
                "where n.oid = c.relnamespace) " %
                current_schema,
                typemap={'relname': sqltypes.Unicode}
            )
        )
        return [row[0] for row in result]

    @reflection.cache
    def get_view_names(self, connection, schema=None, **kw):
        if schema is not None:
            current_schema = schema
        else:
            current_schema = self.default_schema_name
        s = """
        SELECT relname
        FROM pg_class c
        WHERE relkind = 'v'
          AND '%(schema)s' = (select nspname from pg_namespace n
          where n.oid = c.relnamespace)
        """ % dict(schema=current_schema)
        # Py3K
        #view_names = [row[0] for row in connection.execute(s)]
        # Py2K
        view_names = [row[0].decode(self.encoding)
                            for row in connection.execute(s)]
        # end Py2K
        return view_names

    @reflection.cache
    def get_view_definition(self, connection, view_name, schema=None, **kw):
        if schema is not None:
            current_schema = schema
        else:
            current_schema = self.default_schema_name
        s = """
        SELECT definition FROM pg_views
        WHERE schemaname = :schema
        AND viewname = :view_name
        """
        rp = connection.execute(sql.text(s),
                                view_name=view_name, schema=current_schema)
        if rp:
            # Py3K
            #view_def = rp.scalar()
            # Py2K
            view_def = rp.scalar().decode(self.encoding)
            # end Py2K
            return view_def

    @reflection.cache
    def get_columns(self, connection, table_name, schema=None, **kw):

        table_oid = self.get_table_oid(connection, table_name, schema,
                                       info_cache=kw.get('info_cache'))
        SQL_COLS = """
            SELECT a.attname,
              pg_catalog.format_type(a.atttypid, a.atttypmod),
              (SELECT substring(pg_catalog.pg_get_expr(d.adbin, d.adrelid)
                for 128)
                FROM pg_catalog.pg_attrdef d
               WHERE d.adrelid = a.attrelid AND d.adnum = a.attnum
               AND a.atthasdef)
              AS DEFAULT,
              a.attnotnull, a.attnum, a.attrelid as table_oid
            FROM pg_catalog.pg_attribute a
            WHERE a.attrelid = :table_oid
            AND a.attnum > 0 AND NOT a.attisdropped
            ORDER BY a.attnum
        """
        s = sql.text(SQL_COLS,
            bindparams=[sql.bindparam('table_oid', type_=sqltypes.Integer)],
            typemap={'attname': sqltypes.Unicode, 'default': sqltypes.Unicode}
        )
        c = connection.execute(s, table_oid=table_oid)
        rows = c.fetchall()
        domains = self._load_domains(connection)
        enums = self._load_enums(connection)

        # format columns
        columns = []
        for name, format_type, default, notnull, attnum, table_oid in rows:
            column_info = self._get_column_info(
                name, format_type, default, notnull, domains, enums, schema)
            columns.append(column_info)
        return columns

    def _get_column_info(self, name, format_type, default,
                         notnull, domains, enums, schema):
        ## strip (*) from character varying(5), timestamp(5)
        # with time zone, geometry(POLYGON), etc.
        attype = re.sub(r'\(.*\)', '', format_type)

        # strip '[]' from integer[], etc.
        attype = re.sub(r'\[\]', '', attype)

        nullable = not notnull
        is_array = format_type.endswith('[]')
        charlen = re.search('\(([\d,]+)\)', format_type)
        if charlen:
            charlen = charlen.group(1)
        args = re.search('\((.*)\)', format_type)
        if args and args.group(1):
            args = tuple(re.split('\s*,\s*', args.group(1)))
        else:
            args = ()
        kwargs = {}

        if attype == 'numeric':
            if charlen:
                prec, scale = charlen.split(',')
                args = (int(prec), int(scale))
            else:
                args = ()
        elif attype == 'double precision':
            args = (53, )
        elif attype == 'integer':
            args = ()
        elif attype in ('timestamp with time zone',
                        'time with time zone'):
            kwargs['timezone'] = True
            if charlen:
                kwargs['precision'] = int(charlen)
            args = ()
        elif attype in ('timestamp without time zone',
                        'time without time zone', 'time'):
            kwargs['timezone'] = False
            if charlen:
                kwargs['precision'] = int(charlen)
            args = ()
        elif attype == 'bit varying':
            kwargs['varying'] = True
            if charlen:
                args = (int(charlen),)
            else:
                args = ()
        elif attype in ('interval', 'interval year to month',
                            'interval day to second'):
            if charlen:
                kwargs['precision'] = int(charlen)
            args = ()
        elif charlen:
            args = (int(charlen),)

        while True:
            if attype in self.ischema_names:
                coltype = self.ischema_names[attype]
                break
            elif attype in enums:
                enum = enums[attype]
                coltype = ENUM
                if "." in attype:
                    kwargs['schema'], kwargs['name'] = attype.split('.')
                else:
                    kwargs['name'] = attype
                args = tuple(enum['labels'])
                break
            elif attype in domains:
                domain = domains[attype]
                attype = domain['attype']
                # A table can't override whether the domain is nullable.
                nullable = domain['nullable']
                if domain['default'] and not default:
                    # It can, however, override the default
                    # value, but can't set it to null.
                    default = domain['default']
                continue
            else:
                coltype = None
                break

        if coltype:
            coltype = coltype(*args, **kwargs)
            if is_array:
                coltype = ARRAY(coltype)
        else:
            util.warn("Did not recognize type '%s' of column '%s'" %
                      (attype, name))
            coltype = sqltypes.NULLTYPE
        # adjust the default value
        autoincrement = False
        if default is not None:
            match = re.search(r"""(nextval\(')([^']+)('.*$)""", default)
            if match is not None:
                autoincrement = True
                # the default is related to a Sequence
                sch = schema
                if '.' not in match.group(2) and sch is not None:
                    # unconditionally quote the schema name.  this could
                    # later be enhanced to obey quoting rules /
                    # "quote schema"
                    default = match.group(1) + \
                                ('"%s"' % sch) + '.' + \
                                match.group(2) + match.group(3)

        column_info = dict(name=name, type=coltype, nullable=nullable,
                           default=default, autoincrement=autoincrement)
        return column_info

    @reflection.cache
    def get_pk_constraint(self, connection, table_name, schema=None, **kw):
        table_oid = self.get_table_oid(connection, table_name, schema,
                                       info_cache=kw.get('info_cache'))

        if self.server_version_info < (8, 4):
            # unnest() and generate_subscripts() both introduced in
            # version 8.4
            PK_SQL = """
                SELECT a.attname
                FROM
                    pg_class t
                    join pg_index ix on t.oid = ix.indrelid
                    join pg_attribute a
                        on t.oid=a.attrelid and a.attnum=ANY(ix.indkey)
                 WHERE
                  t.oid = :table_oid and ix.indisprimary = 't'
                ORDER BY a.attnum
            """
        else:
            PK_SQL = """
                SELECT a.attname
                FROM pg_attribute a JOIN (
                    SELECT unnest(ix.indkey) attnum,
                           generate_subscripts(ix.indkey, 1) ord
                    FROM pg_index ix
                    WHERE ix.indrelid = :table_oid AND ix.indisprimary
                    ) k ON a.attnum=k.attnum
                WHERE a.attrelid = :table_oid
                ORDER BY k.ord
            """
        t = sql.text(PK_SQL, typemap={'attname': sqltypes.Unicode})
        c = connection.execute(t, table_oid=table_oid)
        cols = [r[0] for r in c.fetchall()]

        PK_CONS_SQL = """
        SELECT conname
           FROM  pg_catalog.pg_constraint r
           WHERE r.conrelid = :table_oid AND r.contype = 'p'
           ORDER BY 1
        """
        t = sql.text(PK_CONS_SQL, typemap={'conname': sqltypes.Unicode})
        c = connection.execute(t, table_oid=table_oid)
        name = c.scalar()

        return {'constrained_columns': cols, 'name': name}

    @reflection.cache
    def get_foreign_keys(self, connection, table_name, schema=None, **kw):
        preparer = self.identifier_preparer
        table_oid = self.get_table_oid(connection, table_name, schema,
                                       info_cache=kw.get('info_cache'))

        FK_SQL = """
          SELECT r.conname,
                pg_catalog.pg_get_constraintdef(r.oid, true) as condef,
                n.nspname as conschema
          FROM  pg_catalog.pg_constraint r,
                pg_namespace n,
                pg_class c

          WHERE r.conrelid = :table AND
                r.contype = 'f' AND
                c.oid = confrelid AND
                n.oid = c.relnamespace
          ORDER BY 1
        """

        t = sql.text(FK_SQL, typemap={
                                'conname': sqltypes.Unicode,
                                'condef': sqltypes.Unicode})
        c = connection.execute(t, table=table_oid)
        fkeys = []
        for conname, condef, conschema in c.fetchall():
            m = re.search('FOREIGN KEY \((.*?)\) REFERENCES '
                            '(?:(.*?)\.)?(.*?)\((.*?)\)', condef).groups()
            constrained_columns, referred_schema, \
                    referred_table, referred_columns = m
            constrained_columns = [preparer._unquote_identifier(x)
                        for x in re.split(r'\s*,\s*', constrained_columns)]

            if referred_schema:
                referred_schema =\
                                preparer._unquote_identifier(referred_schema)
            elif schema is not None and schema == conschema:
                # no schema was returned by pg_get_constraintdef().  This
                # means the schema is in the search path.   We will leave
                # it as None, unless the actual schema, which we pull out
                # from pg_namespace even though pg_get_constraintdef() doesn't
                # want to give it to us, matches that of the referencing table,
                # and an explicit schema was given for the referencing table.
                referred_schema = schema
            referred_table = preparer._unquote_identifier(referred_table)
            referred_columns = [preparer._unquote_identifier(x)
                        for x in re.split(r'\s*,\s', referred_columns)]
            fkey_d = {
                'name': conname,
                'constrained_columns': constrained_columns,
                'referred_schema': referred_schema,
                'referred_table': referred_table,
                'referred_columns': referred_columns
            }
            fkeys.append(fkey_d)
        return fkeys

    @reflection.cache
    def get_indexes(self, connection, table_name, schema, **kw):
        table_oid = self.get_table_oid(connection, table_name, schema,
                                       info_cache=kw.get('info_cache'))

        IDX_SQL = """
          SELECT
              i.relname as relname,
              ix.indisunique, ix.indexprs, ix.indpred,
              a.attname, a.attnum, ix.indkey
          FROM
              pg_class t
                    join pg_index ix on t.oid = ix.indrelid
                    join pg_class i on i.oid=ix.indexrelid
                    left outer join
                        pg_attribute a
                        on t.oid=a.attrelid and a.attnum=ANY(ix.indkey)
          WHERE
              t.relkind = 'r'
              and t.oid = :table_oid
              and ix.indisprimary = 'f'
          ORDER BY
              t.relname,
              i.relname
        """

        t = sql.text(IDX_SQL, typemap={'attname': sqltypes.Unicode})
        c = connection.execute(t, table_oid=table_oid)

        indexes = defaultdict(lambda: defaultdict(dict))

        sv_idx_name = None
        for row in c.fetchall():
            idx_name, unique, expr, prd, col, col_num, idx_key = row

            if expr:
                if idx_name != sv_idx_name:
                    util.warn(
                      "Skipped unsupported reflection of "
                      "expression-based index %s"
                      % idx_name)
                sv_idx_name = idx_name
                continue

            if prd and not idx_name == sv_idx_name:
                util.warn(
                   "Predicate of partial index %s ignored during reflection"
                   % idx_name)
                sv_idx_name = idx_name

            index = indexes[idx_name]
            if col is not None:
                index['cols'][col_num] = col
            index['key'] = [int(k.strip()) for k in idx_key.split()]
            index['unique'] = unique

        return [
            {'name': name,
             'unique': idx['unique'],
             'column_names': [idx['cols'][i] for i in idx['key']]}
            for name, idx in indexes.items()
        ]

    def _load_enums(self, connection):
        if not self.supports_native_enum:
            return {}

        ## Load data types for enums:
        SQL_ENUMS = """
            SELECT t.typname as "name",
               -- no enum defaults in 8.4 at least
               -- t.typdefault as "default",
               pg_catalog.pg_type_is_visible(t.oid) as "visible",
               n.nspname as "schema",
               e.enumlabel as "label"
            FROM pg_catalog.pg_type t
                 LEFT JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace
                 LEFT JOIN pg_catalog.pg_enum e ON t.oid = e.enumtypid
            WHERE t.typtype = 'e'
            ORDER BY "name", e.oid -- e.oid gives us label order
        """

        s = sql.text(SQL_ENUMS, typemap={
                                'attname': sqltypes.Unicode,
                                'label': sqltypes.Unicode})
        c = connection.execute(s)

        enums = {}
        for enum in c.fetchall():
            if enum['visible']:
                # 'visible' just means whether or not the enum is in a
                # schema that's on the search path -- or not overridden by
                # a schema with higher precedence. If it's not visible,
                # it will be prefixed with the schema-name when it's used.
                name = enum['name']
            else:
                name = "%s.%s" % (enum['schema'], enum['name'])

            if name in enums:
                enums[name]['labels'].append(enum['label'])
            else:
                enums[name] = {
                        'labels': [enum['label']],
                        }

        return enums

    def _load_domains(self, connection):
        ## Load data types for domains:
        SQL_DOMAINS = """
            SELECT t.typname as "name",
               pg_catalog.format_type(t.typbasetype, t.typtypmod) as "attype",
               not t.typnotnull as "nullable",
               t.typdefault as "default",
               pg_catalog.pg_type_is_visible(t.oid) as "visible",
               n.nspname as "schema"
            FROM pg_catalog.pg_type t
               LEFT JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace
            WHERE t.typtype = 'd'
        """

        s = sql.text(SQL_DOMAINS, typemap={'attname': sqltypes.Unicode})
        c = connection.execute(s)

        domains = {}
        for domain in c.fetchall():
            ## strip (30) from character varying(30)
            attype = re.search('([^\(]+)', domain['attype']).group(1)
            if domain['visible']:
                # 'visible' just means whether or not the domain is in a
                # schema that's on the search path -- or not overridden by
                # a schema with higher precedence. If it's not visible,
                # it will be prefixed with the schema-name when it's used.
                name = domain['name']
            else:
                name = "%s.%s" % (domain['schema'], domain['name'])

            domains[name] = {
                    'attype': attype,
                    'nullable': domain['nullable'],
                    'default': domain['default']
                }

        return domains


text:
Photojournalism with Olympus M43
Arnold Jerocki INSPIRATION	1 Comment
About Arnold Jerocki
"I am a photojournalist, I work for the French and European press. I am part of the collective Divergence Images, I work for newspapers and companies. I started photography at the end of the 90s by photographing Theater and Dance during the festival of Avignon. I'm an Olympus Visionary and passionate about photojournalism."
Photojournalism with Olympus M43 - June 29, 2018
Hello Arnold! Could you present yourself to the readers?
Hello. I am 37 years old, I am French-Polish and I currently live in the south of France.
How did you get interested in photography and how long have you been shooting professionally?
I was initiated to photography by my cousin when I was a teenager, I started my career in 2000 as a theater photographer, then I made a break from 2005 to 2009 and I started again professionally in 2010 as a photojournalist in my area, since I work for daily newspapers like Le Monde, Liberation, Le Journal du Dimanche, Bild and magazines like VSD, Le Pelerin, Paris Match, L'Obs.
I am currently member of the collective Divergence-Images.
A high school student leaves school at the end of the day after an attempt at mass shooting by a 17-year-old earlier in the day
English supporters throw glass bottles as they clash with riot police at the Old Port of Marseille, France, 11 June 2016, before the UEFA EURO 2016 group B preliminary round match between England and Russia.
People take part in a nationwide day of protest against deeply unpopular labour reforms (Law El Khomri) that have divided the Socialist government and raised hackles in a country accustomed to ironclad job security, on March 9, 2016 in Marseille, France.
France's government has faced massive blowback — including from within its ranks — to measures that would give bosses more flexibility in hiring and firing.
Who were your early influences, if any?
I always liked the work of Raymond Depardon, I also like the work of photographer like Gueorgui Pinkhassov, Alex Webb, David Alan Harvey, I also like the work of Martin Parr that I had the chance to meet last week at the Grand Prix of Monaco.
The painters also have a great influence, I like to go to the Louvre Museum to see how they play with the light.
Emmanuel Macron travels to Marseilles, the day after his declaration of candidacy for the presidential election. 1r meeting at the Tino Rossi space at Les Pennes Mirabeau
He was elected French president
©Arnold Jerocki/Divergence
Emmanuel Macron on stage during his speech at the Palais des Sport where the candidate for the French president election give political meeting in Lyon, France the 02/04/2017
Are you formally trained or self-taught?
I passed a technical diploma of photography in 1999 but it has really not served me a lot because I learned the methods of work in film while the digital made its arrival in the professional world.
When did you start using Olympus and why? Do you use the Olympus system exclusively or, for some particular assignments, do you use another system?
In July 2013 I had an exhibition in Arles during 'Les Rencontres d'Arles', which allowed me to meet people of Olympus, they lent me a camera to make tests (OMD-EM5), for being honest I did not think it was great on the first day!! I then learned to use it and finally I bought one in September!
For 2 years I used my Olympus in complement of my Canon 5D3 and my Leica M9 and in 2015 I became ambassador for Olympus France and since then I work exclusively with material Olympus.
Pilot Max Verstappen from Redbull Team during Monaco GP 2017
Pilot Kimi RŠikkšnen from Ferrari team during Monaco GP 2017
Which do you prefer to photograph, portraits or events?
I do not really have preference, what makes the richness of my profession is precisely to change subject all the time.
We noticed you use both the Pen-F and the E-M1 mkII. Does each have a specific function within the genre of photography you make? If you had to choose only one, Pen-F or E-M1 mkII, which would it be?
I use the Pen-F as a main camera with the short focal lengths and I keep the E-M1 mark II as the second camera for the 40-150 f2.8 but sometimes it's the opposite! It is necessary not to take habits but to adapt the material to its needs.
If I had to choose only one it will be the Pen-F with the 25mm f1.8, small, light discreet and terribly effective.
Avignon, France le 06/07/2016
Piece of theater during the festival of Avignon
2666 d'aprs Roberto Bolano a la FabricA
Mise en scne JULIEN GOSSELIN
Avec NoŽmie Gantier
LEILA SE MEURT
ChorŽgraphie ALI CHAHROUR
Avec Ali Chahrour, Leila Chahrour
et les musiciens Ali Hout, Abed Kobeissi
Does Olympus current lens lineup fit all your needs, or do you use lenses from other manufacturers?
The current range of lens suits me very well. I do an infidelity to Olympus using the Panasonic 15mm f1.7 because I had bought it before being ambassador. I hope they have good surprises for the future, sports or wildlife photographers would be pleased with an optics such as the 150mm f2 or 200 f2.8 (equivalent 300mm f2 or 400mm f2.8 in full frame).
Portrait of AurŽlie Filippetti, Minister of Culture from May 2012 to August 2014, at the Cloitre St Louis Hotel in Avignon
France-02/02/2016
French farmers attend a demonstration and block the highway next to Arles, Southern France, 02 February 2016. Farmers staged a protest against falling prices of rice and meat
Oyster farmers of the ' Thau ' lagoon leave the harbor to get to their place of production
If you could make some suggestions of characteristics for a hypothetical Pen-F mkII, what would they be?
I would like a Pen-F a little bigger (I measure 1.93m and I have big hands!!) a little less gadgets and less touch to concentrate on the essentials, because in the end what we need to manage its speed, F-stop and a good viewfinder to stay focused on the subject.
Thank you for your time and availability!
Thank you to give me a place on your website.
SUBSCRIBE TODAY THE OLYMPUS PASSION VIRTUAL MAGAZINE

redpajama_set_name: RedPajamaCommonCrawl


text:
Love & Lifestyle
Magic Event Videos
Magic Event Photos
Tom Joyner
Divine Martino
Al B Sure!
Nia Noelle
3 Ways Trump's Obamacare Slash Can Affect People…
People of color will be affected the most with President Trump weakening Obamacare. It wasn't surprising to see President Donald Trump…
Senate Shockingly Didn't Pass #SkinnyBill Obamacare Repeal
While you were sleeping, the Senate voted to take away Obamacare with no replacement and still failed. While President Donald…
Paul Ryan 'Excited' Millions Will Lose Healthcare With…
To all who voted Republican in last year's election, be careful what you wish for! The Republicans lead by House…
Obamacare Replacement Clears First Hurdle With House Committee…
House Ways and Means Committee members OK'd the new bill after a grueling 18-hour session, with Republicans voting 23-16. …
Trump's Plan For 'The Blacks' Even More Elusive…
On the last day of Black History Month, President Donald Trump delivered his first State of Union Address, where he…
GOP Congressmen Dodge Town Hall Meetings Due To…
GOP congressmen and women want to repeal the Affordable Care Act but are scare to look in the face of…
President Obama Is Just Like Us: He Practices…
Ever wonder what President Obama does in his spare time? Well a new video from Buzzfeed.com suggests that he's just…
Affordable Health Care (Obamacare) Know Your Options
Originally posted on Majic 102.3 - 92.7: February 15th is the last day to sign up for health coverage or…
Get Well Wednesday: Your Questions About The Affordable…
Mark Stahl from Health Markets is here to help you navigate the requirement to have health insurance. If your…
Money Mondays: Affordable Care Act Enrollment Period
Mellody is President of Ariel investments, a Chicago-based money management firm that serves individual investors and retirement plans through…
White House Boasts Positive Affordable Care Act Numbers
Photo: CBO, Joint Committee of Taxation On Thursday, the White House released a series of numbers pointing to the…
Obamacare Sign-up: 5 Fast Facts You Need To…
Today, March 31, 2014, is the deadline to sign up for Obamacare. If you haven't already signed up yet, but…
Gun Violence, Mental Health & #GetCovered: What You…
1. Playing Games With Our Lives: New York Pastor Raffles Off Assault Rifle You have got to be kidding…
Obama Administration Begins Affordable Care Act Push During…
The Obama administration continues its push toward uninsured Americans to sign up for health insurance via the Affordable Care Act.…
These Celebs Know Their Way Around Some Edge…
SIGN UP FOR THE MAGIC 95.5 FM NEWSLETTER


text:
is a railway station in Sumida, Tokyo, Japan, operated by East Japan Railway Company (JR East) and Tokyo Metro. The surrounding area is the largest shopping district in Sumida Ward, featuring several large department stores, numerous small shops and restaurants.

Lines
Kinshichō Station is served by the JR East Sōbu Line (Rapid) and Chūō-Sōbu Line, as well as the Tokyo Metro Hanzōmon Line (Station number Z-13).

Station layout

JR East platforms

Tokyo Metro platforms

History
The station first opened on 9 December 1894. The Hanzōmon Line station opened on 19 March 2003.

The station facilities of the Hanzōmon Line were inherited by Tokyo Metro after the privatization of the Teito Rapid Transit Authority (TRTA) in 2004.

Passenger statistics
In fiscal 2013, the JR East station was used by 103,522 passengers daily (boarding passengers only), making it the 36th-busiest station operated by JR East. In fiscal 2013, the Tokyo Metro station was used by an average of 92,658 passengers per day (exiting and entering passengers), making it the 41st-busiest station operated by Tokyo Metro. The daily passenger figures for each operator in previous years are as shown below.

 Note that JR East figures are for boarding passengers only.

Surrounding area
 Kinshi Park
 Sumida Triphony Hall (concert hall)

See also

 List of railway stations in Japan

References

External links

 JR East station information
 Tokyo Metro station information

Railway stations in Japan opened in 1894
Sōbu Main Line
Chūō-Sōbu Line
Tokyo Metro Hanzomon Line
Stations of East Japan Railway Company
Stations of Tokyo Metro
Railway stations in Tokyo

redpajama_set_name: RedPajamaWikipedia


text:
Alex Robinson Proves Elite Status
By Alec Kinsky, D1 Circuit, 08/26/13, 3:30PM EDT
Texas Titans Point Guard Flies Under The Radar
In the sports world, everything is ranked. Whether it be teams, players, conferences, colleges, fantasy players - it doesn't matter - it's probably ranked.
In the high school basketball world, recruitment rankings reign supreme. Rivals, ESPN, Scout, & 24/7 are the four dominant sources in today's recruiting world, all giving different opinions on the nation's top talent. While these rankings can be somewhat subjective, the combination of the four different rankings give the fans a general feel of what scouts and coaches think of a certain player.
As the rankings are updated, just like anyone else, I find myself with slight disagreements as I scroll through. We have made our grievances known about the snub of Bonzie Colson, whom we firmly believe to be a top 100 player in the country. This year, there is one more player that is ranked who we feel is underrated across the recruitment board.
That player is Texas Titans' point guard Alex Robinson. Here is where he checks in on the recruiting boards:
Scout - No. 41
Rivals - No. 71
24/7 - No. 73
ESPN - No. 89
Taking the combined average, Robinson checks in at 68.5/100. While it's evident his game has garnered attention, most highly by Evan Daniels and Scout.com, his ranking doesn't scream "elite point guard." After his performances at the Peach Jam, it's almost impossible to consider him anything but elite.
During the most important tournament of the summer circuit, Robinson absolutely exploded on the court. In five Peach Jam games, the 6-foot-1 lefty floor-general averaged 14.0 points, 5.6 rebounds, 6.1 assists and 3.2 steals. Simply put, he looked like a completely different player.
Calm, cool and collected, Robinson was the Titans leader the entire season. He operated without backcourt teammate and top-recruit King McClure for the entire EYBL regular season. For 18 games, he shouldered all of the heavy lifting in the backcourt. His fatigue began to show during session four in Minneapolis, the last session of the EYBL regular season. When asked the difference between the EYBL and high school, Robinson sounded matter-of-fact.
"It's a lot faster. Every player is good. You gotta play both ends of the floor. You need to limit your mistakes and execute on offense."
After a month break and the return of his talented backcourt partner, Robinson was able to give us a glimpse of his potential. He pierced the lane at will and attacked the basket with a ferocity only matched by McClure.
Against Malik Newman and the Jackson Tigers, Robinson had a career game; 23 points, 9 rebounds, 8 assists and 5 steals. The most impressive aspect of that game was the five steals. His pressure defense was on display literally every time a Tigers' guard crossed half court, turning the heads of countless fans watching on. His individual performances are tough to ignore, but Robinson is all about his team.
"It's harder because it's 17 and under this year. But, we have such a great bond. No matter how far we get down, we feel we can come back and win."
Robinson will look to take that mentality to one of his six final schools; Memphis, Texas A&M, Texas Christian, Pittsburgh, Vanderbilt and Florida State. He plans to take time with his final decision, hoping to continue his rise up the 2014 class during his senior year at Timberview High School.
Let's hope the recruiting services take notice.
147 Nike EYBL alumni currently on NBA rosters
By Alec Kinsky, D1 Circuit 10/30/2019, 5:45pm EDT
Hunter Dickinson breaks down his final four schools - Duke, Florida State, Notre Dame & Michigan
By Pat Lawless 10/14/2019, 12:45pm EDT
Hunter Dickinson is looking at four schools
'The Academy' High School & College Official Rosters
By D1 Circuit Staff 08/07/2019, 4:30pm EDT
EJ Bates' Son Is a Basketball Prodigy. Coaching Him Is More Relatable Than You'd Think
By Alec Kinsky, SportsEngine 08/06/2019, 3:15pm EDT
VIDEO: 2019 'One Peachy Moment'
By Jon Lopez, Nike 07/17/2019, 2:45pm EDT
NIKE EYBL Announces 2019 Schedule & League Updates
By D1 Circuit Staff 02/26/2019, 12:00pm EST
All-EYBL: First Team
NOW LIVE: 2019 17U NIKE EYBL Team List
Tag(s): News
©2020 SportsEngine, Inc. This website is powered by the SportsEngine platform, but is owned by and subject to the D1 Circuit privacy policy.


text:
Biografia
Lavorò presso la polizia segreta irachena fin dagli anni settanta ma è a partire dal 1995 che cominciò la sua scalata al potere: divenuto intimo amico e collaboratore di Saddam, il dittatore iracheno lo pose in quell'anno a capo del Mukhabarat ed in questa veste Barzan divenne uno degli esponenti del regime più spietati nel reprimere le opposizioni interne.

Dal 1989 al 2000 fu il rappresentante dell'Iraq presso le Nazioni Unite a Ginevra: fece anche parte della commissione per i diritti umani e difese a spada tratta il suo governo dalle accuse di crimini contro l'umanità. Tuttavia gli Stati Uniti e non credettero alle sue parole e gli ufficiali americani stilarono un elenco, denominato la "sporca dozzina di Saddam", in cui Barzan era incluso.

Nel marzo del 2003, quando scoppiò la guerra in Iraq, le truppe statunitensi si misero alla caccia di Barzan e nel famoso mazzo di carte stilato dal governo di George W. Bush egli era il re di picche (in pratica il numero 5 del regime). Nell'aprile del 2003 la sua casa fu bombardata e distrutta ed il 17 dello stesso mese fu catturato dagli alleati a Tikrit.

Contro Barzan, Awad Hamed al-Bandar e Saddam Hussein partì un processo per crimini contro l'umanità, genocidio ed altri reati politici. Barzan fu condannato a morte il 3 dicembre 2006 per complicità nel massacro di Dujail, durante il quale era responsabile dei servizi segreti che coordinarono la repressione.

Scrisse una lettera a Bush ed al nuovo capo di Stato iracheno Jalal Talabani chiedendo di essere rilasciato per via di un cancro che lo affliggeva, ma la sentenza fu comunque confermata il 26 dicembre.

La condanna a morte per impiccagione fu eseguita il 15 gennaio del 2007 ad Al-Kazimiyya, un sobborgo di Baghdad.

Barzan Ibrahim al-Tikriti lascia un figlio, Omar al-Tikriti, che in questo momento si trova in esilio in Yemen.

Polemiche
Tra le pene capitali, la cui esecuzione destò riprovazione nella comunità internazionale, vi fu proprio l'impiccagione del fratellastro di Saddam Hussein, Barzan Ibrahim al-Tikriti. La sua esecuzione, con quella dell'ex-presidente del tribunale rivoluzionario iracheno, Awad al-Bandar, coimputati nello stesso processo, era originariamente prevista nella stessa notte nella quale fu eseguita quella di Saddam; fu poi rinviata alle 03:00 (ora locale) del 15 gennaio 2007.

La pressione sul collo fu così forte (nonostante l'uso del metodo del long drop) che la testa si staccò dal resto del corpo, non si sa se prima o dopo il suo decesso.
La notizia che la corda aveva tranciato di netto il collo del condannato, facendone schiantare il corpo al suolo e rotolare la testa a diversi metri di distanza (come riferito dai giornalisti che avevano potuto visionare il video dell'esecuzione, rimasto questa volta riservato, dopo le polemiche per la pubblicità di quello della morte di Saddam), fu accolta con orrore.

Note

Voci correlate
 Casa Saddam

Servizi segreti
Terrorismo islamista
Persone condannate per crimini contro l'umanità
Barzan


Here are a sample of the many responses to that question from the Home > TV Repair link under Browse Projects, at lower left.
Certainly you can contact a TV Repair shop (your Search the List category) but be sure to ask if that cost includes in-home repair or pickup and return by them or if you have to deliver it yourself(which with a large TV can not only be a problem if you have a sedan rather than SUV or pickup but also risks breakage in transit (especially if you do not have the original packaging).
And always first check the new TV replacement cost, because with TV prices constantly plummeting at box stores, replacement of the entire TV is commonly around the same cost as a screen repair, plus you get a new warranty (typically 1 year plus option of buying-up to a longer term) for the price.
Remember to also check the web for recalls on your model number, and also for comments on a lot of breakage problems - many models across multiple manufacturers are having spontaneous screen breakage problems and are providing (even if no formal recall) free replacement screens or even in some cases, for the squeekiest wheels, total new TV to keep the faillure rate out of the press.
I want to find out what the Average screen repair cost for 60 inch flatscreen Smart TV.
How much would it cost to fix a samsung 55 inch plasma tv screen that is broken?