'''`TissueMAPS` database models.'''

from base import Model, DateMixIn, File

import logging
import inspect
import collections
from sqlalchemy import create_engine
from sqlalchemy.sql.schema import Table

from utils import DATABASE_URI
from utils import Session

_postgresxl_register = collections.defaultdict(dict)

logger = logging.getLogger(__name__)


def distribute_by(column_name):
    '''Register a database model class for use with
    `PostgresXL <http://www.postgres-xl.org/>`_.

    Parameters
    ----------
    column_name: str
        name of the column that should be used for distribution of the table

    Raises
    ------
    TypeError
        when decorated class is not derived from
        :py:class:`tmlib.models.Model`
    '''
    def decorator(cls):
        if Model not in inspect.getmro(cls):
            raise TypeError(
                'Registered class must be derived from tmlib.models.Model'
            )
        _postgresxl_register[cls.__tablename__] = column_name
        return cls
    return decorator


class PostgresXl(object):

    '''Destribution of SQL tables declared via SQLAlchemy for use with
    PostgresXL database cluster.
    '''

    def __init__(self):
        # TODO: this approach is quite a hack, this should be implemented in
        # SQLAlchemy at some point (see http://docs.sqlalchemy.org/en/latest/core/ddl.html)
        self._engine = create_engine(
            DATABASE_URI, strategy='mock', executor=self._dump
        )
        self._sql = str()

    def generate_create_table_statements(self):
        '''Generates SQL `CREATE TABLE` statements for all model classes
        derived from :py:class:`tmlib.models.Model`.

        Returns
        -------
        str
            SQL statement
        '''
        Model.metadata.create_all(self._engine, checkfirst=False)
        return self._sql

    def create_tables(self):
        '''Creates all tables declared by model classes derived from
        :py:class:`tmlib.models.Model`.
        '''
        sql = self.generate_create_table_statements()
        Session._engine.execute(sql)

    def _dump(self, sql, *multiparams, **params):
        if isinstance(sql, basestring):
            self._sql += sql + ';'
            return
        table_name = sql.element.name
        logger.info('create sql statement for table "%s"', table_name)
        create_table = str(sql.compile(dialect=self._engine.dialect)).rstrip()
        column_name = _postgresxl_register.get(table_name, None)
        if column_name is not None and isinstance(sql.element, Table):
            logger.info('distribute table "%s"', table_name)
            create_table += ' DISTRIBUTE BY HASH(' + column_name + ')'
        self._sql += create_table + ';' + '\n'


from user import User
from experiment import Experiment
from well import Well
from channel import Channel
from layer import ChannelLayer
from mapobject import MapobjectType, Mapobject, MapobjectOutline, MapobjectSegmentation, MapobjectType
from feature import Feature, FeatureValue
from plate import Plate
from acquisition import Acquisition, ImageFileMapping
from cycle import Cycle
from submission import Submission, Task
from site import Site
from alignment import SiteShift, SiteIntersection
from file import MicroscopeImageFile, MicroscopeMetadataFile, ChannelImageFile, ProbabilityImageFile, IllumstatsFile, PyramidTileFile



@@ -2067,17 +2067,56 @@
         
-S
+with Session() as session:%0A            s
 ession._

Fix another bug in PostgresXl class