def add_property(self, key, prop):
     if sql.is_column(prop):
         self.columns[key] = prop
         prop = ColumnProperty(prop)
     self.props[key] = prop
     if isinstance(prop, ColumnProperty):
         for col in prop.columns:
             proplist = self.columntoproperty.setdefault(col.original, [])
             proplist.append(prop)
     prop.init(key, self)
Beispiel #2
0
 def add_property(self, key, prop):
     """adds an additional property to this mapper.  this is the same as if it were 
     specified within the 'properties' argument to the constructor.  if the named
     property already exists, this will replace it.  Useful for
     circular relationships, or overriding the parameters of auto-generated properties
     such as backreferences."""
     if sql.is_column(prop):
         self.columns[key] = prop
         prop = ColumnProperty(prop)
     self.props[key] = prop
     if isinstance(prop, ColumnProperty):
         for col in prop.columns:
             proplist = self.columntoproperty.setdefault(col.original, [])
             proplist.append(prop)
     prop.init(key, self)
Beispiel #3
0
    def visit_select(self, select):
        # the actual list of columns to print in the SELECT column list.
        inner_columns = util.OrderedDict()

        self.select_stack.append(select)
        for c in select._raw_columns:
            if isinstance(c, sql.Select) and c.is_scalar:
                self.traverse(c)
                inner_columns[self.get_str(c)] = c
                continue
            if hasattr(c, '_selectable'):
                s = c._selectable()
            else:
                self.traverse(c)
                inner_columns[self.get_str(c)] = c
                continue
            for co in s.columns:
                if select.use_labels:
                    labelname = co._label
                    if labelname is not None:
                        l = co.label(labelname)
                        self.traverse(l)
                        inner_columns[labelname] = l
                    else:
                        self.traverse(co)
                        inner_columns[self.get_str(co)] = co
                # TODO: figure this out, a ColumnClause with a select as a parent
                # is different from any other kind of parent
                elif select.is_subquery and isinstance(
                        co, sql._ColumnClause
                ) and not co.is_literal and co.table is not None and not isinstance(
                        co.table, sql.Select):
                    # SQLite doesnt like selecting from a subquery where the column
                    # names look like table.colname, so add a label synonomous with
                    # the column name
                    l = co.label(co.name)
                    self.traverse(l)
                    inner_columns[self.get_str(l.obj)] = l
                else:
                    self.traverse(co)
                    inner_columns[self.get_str(co)] = co
        self.select_stack.pop(-1)

        collist = string.join(
            [self.get_str(v) for v in inner_columns.values()], ', ')

        text = "SELECT "
        text += self.visit_select_precolumns(select)
        text += collist

        whereclause = select.whereclause

        froms = []
        for f in select.froms:

            if self.parameters is not None:
                # look at our own parameters, see if they
                # are all present in the form of BindParamClauses.  if
                # not, then append to the above whereclause column conditions
                # matching those keys
                for c in f.columns:
                    if sql.is_column(c) and self.parameters.has_key(
                            c.key) and not self.binds.has_key(c.key):
                        value = self.parameters[c.key]
                    else:
                        continue
                    clause = c == value
                    self.traverse(clause)
                    whereclause = sql.and_(clause, whereclause)
                    self.visit_compound(whereclause)

            # special thingy used by oracle to redefine a join
            w = self.get_whereclause(f)
            if w is not None:
                # TODO: move this more into the oracle module
                whereclause = sql.and_(w, whereclause)
                self.visit_compound(whereclause)

            t = self.get_from_text(f)
            if t is not None:
                froms.append(t)

        if len(froms):
            text += " \nFROM "
            text += string.join(froms, ', ')
        else:
            text += self.default_from()

        if whereclause is not None:
            t = self.get_str(whereclause)
            if t:
                text += " \nWHERE " + t

        group_by = self.get_str(select.group_by_clause)
        if group_by:
            text += " GROUP BY " + group_by

        if select.having is not None:
            t = self.get_str(select.having)
            if t:
                text += " \nHAVING " + t

        order_by = self.get_str(select.order_by_clause)
        if order_by:
            text += " ORDER BY " + order_by

        text += self.visit_select_postclauses(select)

        text += self.for_update_clause(select)

        if getattr(select, 'parens', False):
            self.strings[select] = "(" + text + ")"
        else:
            self.strings[select] = text
        self.froms[select] = "(" + text + ")"
    def visit_select(self, select):
        # the actual list of columns to print in the SELECT column list.
        inner_columns = util.OrderedDict()

        self.select_stack.append(select)
        for c in select._raw_columns:
            if hasattr(c, '_selectable'):
                s = c._selectable()
            else:
                self.traverse(c)
                inner_columns[self.get_str(c)] = c
                continue
            for co in s.columns:
                if select.use_labels:
                    labelname = co._label
                    if labelname is not None:
                        l = co.label(labelname)
                        self.traverse(l)
                        inner_columns[labelname] = l
                    else:
                        self.traverse(co)
                        inner_columns[self.get_str(co)] = co
                # TODO: figure this out, a ColumnClause with a select as a parent
                # is different from any other kind of parent
                elif select.is_selected_from and isinstance(co, sql._ColumnClause) and not co.is_literal and co.table is not None and not isinstance(co.table, sql.Select):
                    # SQLite doesnt like selecting from a subquery where the column
                    # names look like table.colname, so add a label synonomous with
                    # the column name
                    l = co.label(co.name)
                    self.traverse(l)
                    inner_columns[self.get_str(l.obj)] = l
                else:
                    self.traverse(co)
                    inner_columns[self.get_str(co)] = co
        self.select_stack.pop(-1)

        collist = string.join([self.get_str(v) for v in inner_columns.values()], ', ')

        text = "SELECT "
        text += self.visit_select_precolumns(select)
        text += collist

        whereclause = select.whereclause

        froms = []
        for f in select.froms:

            if self.parameters is not None:
                # TODO: whack this feature in 0.4
                # look at our own parameters, see if they
                # are all present in the form of BindParamClauses.  if
                # not, then append to the above whereclause column conditions
                # matching those keys
                for c in f.columns:
                    if sql.is_column(c) and self.parameters.has_key(c.key) and not self.binds.has_key(c.key):
                        value = self.parameters[c.key]
                    else:
                        continue
                    clause = c==value
                    if whereclause is not None:
                        whereclause = self.traverse(sql.and_(clause, whereclause), stop_on=util.Set([whereclause]))
                    else:
                        whereclause = clause
                        self.traverse(whereclause)

            # special thingy used by oracle to redefine a join
            w = self.get_whereclause(f)
            if w is not None:
                # TODO: move this more into the oracle module
                if whereclause is not None:
                    whereclause = self.traverse(sql.and_(w, whereclause), stop_on=util.Set([whereclause, w]))
                else:
                    whereclause = w

            t = self.get_from_text(f)
            if t is not None:
                froms.append(t)

        if len(froms):
            text += " \nFROM "
            text += string.join(froms, ', ')
        else:
            text += self.default_from()

        if whereclause is not None:
            t = self.get_str(whereclause)
            if t:
                text += " \nWHERE " + t

        group_by = self.get_str(select.group_by_clause)
        if group_by:
            text += " GROUP BY " + group_by

        if select.having is not None:
            t = self.get_str(select.having)
            if t:
                text += " \nHAVING " + t

        text += self.order_by_clause(select)
        text += self.visit_select_postclauses(select)
        text += self.for_update_clause(select)

        self.strings[select] = text
        self.froms[select] = "(" + text + ")"
    def __init__(self,
                 class_,
                 table,
                 primarytable=None,
                 properties=None,
                 primary_key=None,
                 is_primary=False,
                 inherits=None,
                 inherit_condition=None,
                 extension=None,
                 order_by=False,
                 allow_column_override=False,
                 **kwargs):

        if primarytable is not None:
            sys.stderr.write(
                "'primarytable' argument to mapper is deprecated\n")

        if extension is None:
            self.extension = MapperExtension()
        else:
            self.extension = extension
        self.class_ = class_
        self.is_primary = is_primary
        self.order_by = order_by
        self._options = {}

        if not issubclass(class_, object):
            raise TypeError("Class '%s' is not a new-style class" %
                            class_.__name__)

        if isinstance(table, sql.Select):
            # some db's, noteably postgres, dont want to select from a select
            # without an alias.  also if we make our own alias internally, then
            # the configured properties on the mapper are not matched against the alias
            # we make, theres workarounds but it starts to get really crazy (its crazy enough
            # the SQL that gets generated) so just require an alias
            raise TypeError(
                "Mapping against a Select object requires that it has a name.  Use an alias to give it a name, i.e. s = select(...).alias('myselect')"
            )
        else:
            self.table = table

        if inherits is not None:
            self.primarytable = inherits.primarytable
            # inherit_condition is optional since the join can figure it out
            self.table = sql.join(inherits.table, table, inherit_condition)
        else:
            self.primarytable = self.table

        # locate all tables contained within the "table" passed in, which
        # may be a join or other construct
        tf = TableFinder()
        self.table.accept_visitor(tf)
        self.tables = tf.tables

        # determine primary key columns, either passed in, or get them from our set of tables
        self.pks_by_table = {}
        if primary_key is not None:
            for k in primary_key:
                self.pks_by_table.setdefault(
                    k.table, util.HashSet(ordered=True)).append(k)
                if k.table != self.table:
                    # associate pk cols from subtables to the "main" table
                    self.pks_by_table.setdefault(
                        self.table, util.HashSet(ordered=True)).append(k)
        else:
            for t in self.tables + [self.table]:
                try:
                    l = self.pks_by_table[t]
                except KeyError:
                    l = self.pks_by_table.setdefault(
                        t, util.HashSet(ordered=True))
                if not len(t.primary_key):
                    raise ValueError(
                        "Table " + t.name +
                        " has no primary key columns. Specify primary_key argument to mapper."
                    )
                for k in t.primary_key:
                    l.append(k)

        # make table columns addressable via the mapper
        self.columns = util.OrderedProperties()
        self.c = self.columns

        # object attribute names mapped to MapperProperty objects
        self.props = {}

        # table columns mapped to lists of MapperProperty objects
        # using a list allows a single column to be defined as
        # populating multiple object attributes
        self.columntoproperty = {}

        # load custom properties
        if properties is not None:
            for key, prop in properties.iteritems():
                if sql.is_column(prop):
                    try:
                        prop = self.table._get_col_by_original(prop)
                    except KeyError:
                        raise ValueError(
                            "Column '%s' is not represented in mapper's table"
                            % prop._label)
                    self.columns[key] = prop
                    prop = ColumnProperty(prop)
                elif isinstance(prop, list) and sql.is_column(prop[0]):
                    try:
                        prop = [
                            self.table._get_col_by_original(p) for p in prop
                        ]
                    except KeyError, e:
                        raise ValueError(
                            "Column '%s' is not represented in mapper's table"
                            % e.args[0])
                    self.columns[key] = prop[0]
                    prop = ColumnProperty(*prop)
                self.props[key] = prop
                if isinstance(prop, ColumnProperty):
                    for col in prop.columns:
                        proplist = self.columntoproperty.setdefault(
                            col.original, [])
                        proplist.append(prop)
    def visit_select(self, select):

        # the actual list of columns to print in the SELECT column list.
        # its an ordered dictionary to insure that the actual labeled column name
        # is unique.
        inner_columns = OrderedDict()

        self.select_stack.append(select)
        for c in select._raw_columns:
            if c.is_selectable():
                for co in c.columns:
                    if select.use_labels:
                        l = co.label(co._label)
                        l.accept_visitor(self)
                        inner_columns[co._label] = l
                    elif select.issubquery and isinstance(co, Column):
                        # SQLite doesnt like selecting from a subquery where the column
                        # names look like table.colname, so add a label synonomous with
                        # the column name
                        l = co.label(co.key)
                        l.accept_visitor(self)
                        inner_columns[self.get_str(l.obj)] = l
                    else:
                        co.accept_visitor(self)
                        inner_columns[self.get_str(co)] = co
            else:
                c.accept_visitor(self)
                inner_columns[self.get_str(c)] = c
        self.select_stack.pop(-1)

        collist = string.join(
            [self.get_str(v) for v in inner_columns.values()], ', ')

        text = "SELECT "
        if select.distinct:
            text += "DISTINCT "
        text += collist

        whereclause = select.whereclause

        froms = []
        for f in select.froms:

            if self.parameters is not None:
                # look at our own parameters, see if they
                # are all present in the form of BindParamClauses.  if
                # not, then append to the above whereclause column conditions
                # matching those keys
                for c in f.columns:
                    if sql.is_column(c) and self.parameters.has_key(
                            c.key) and not self.binds.has_key(c.key):
                        value = self.parameters[c.key]
                    else:
                        continue
                    clause = c == value
                    clause.accept_visitor(self)
                    whereclause = sql.and_(clause, whereclause)
                    self.visit_compound(whereclause)

            # special thingy used by oracle to redefine a join
            w = self.get_whereclause(f)
            if w is not None:
                # TODO: move this more into the oracle module
                whereclause = sql.and_(w, whereclause)
                self.visit_compound(whereclause)

            t = self.get_from_text(f)
            if t is not None:
                froms.append(t)

        if len(froms):
            text += " \nFROM "
            text += string.join(froms, ', ')

        if whereclause is not None:
            t = self.get_str(whereclause)
            if t:
                text += " \nWHERE " + t

        for tup in select.clauses:
            ss = self.get_str(tup[1])
            if ss:
                text += " " + tup[0] + " " + ss

        if select.having is not None:
            t = self.get_str(select.having)
            if t:
                text += " \nHAVING " + t

        if select.limit is not None or select.offset is not None:
            # TODO: ok, so this is a simple limit/offset thing.
            # need to make this DB neutral for mysql, oracle
            text += self.limit_clause(select)

        if getattr(select, 'issubquery', False):
            self.strings[select] = "(" + text + ")"
        else:
            self.strings[select] = text
        self.froms[select] = "(" + text + ")"
Beispiel #7
0
    def __init__(self,
                 class_,
                 table,
                 primarytable=None,
                 properties=None,
                 primary_key=None,
                 is_primary=False,
                 inherits=None,
                 inherit_condition=None,
                 extension=None,
                 order_by=False,
                 allow_column_override=False,
                 entity_name=None,
                 always_refresh=False,
                 version_id_col=None,
                 construct_new=False,
                 **kwargs):

        if primarytable is not None:
            sys.stderr.write(
                "'primarytable' argument to mapper is deprecated\n")

        ext = MapperExtension()

        for ext_class in global_extensions:
            ext = ext_class().chain(ext)

        if extension is not None:
            for ext_obj in util.to_list(extension):
                ext = ext_obj.chain(ext)

        self.extension = ext

        self.class_ = class_
        self.entity_name = entity_name
        self.class_key = ClassKey(class_, entity_name)
        self.is_primary = is_primary
        self.order_by = order_by
        self._options = {}
        self.always_refresh = always_refresh
        self.version_id_col = version_id_col
        self.construct_new = construct_new

        if not issubclass(class_, object):
            raise ArgumentError("Class '%s' is not a new-style class" %
                                class_.__name__)

        if isinstance(table, sql.Select):
            # some db's, noteably postgres, dont want to select from a select
            # without an alias.  also if we make our own alias internally, then
            # the configured properties on the mapper are not matched against the alias
            # we make, theres workarounds but it starts to get really crazy (its crazy enough
            # the SQL that gets generated) so just require an alias
            raise ArgumentError(
                "Mapping against a Select object requires that it has a name.  Use an alias to give it a name, i.e. s = select(...).alias('myselect')"
            )
        else:
            self.table = table

        if inherits is not None:
            if self.class_.__mro__[1] != inherits.class_:
                raise ArgumentError(
                    "Class '%s' does not inherit from '%s'" %
                    (self.class_.__name__, inherits.class_.__name__))
            self.primarytable = inherits.primarytable
            # inherit_condition is optional.
            if not table is inherits.noninherited_table:
                if inherit_condition is None:
                    # figure out inherit condition from our table to the immediate table
                    # of the inherited mapper, not its full table which could pull in other
                    # stuff we dont want (allows test/inheritance.InheritTest4 to pass)
                    inherit_condition = sql.join(inherits.noninherited_table,
                                                 table).onclause
                self.table = sql.join(inherits.table, table, inherit_condition)
                #print "inherit condition", str(self.table.onclause)

                # generate sync rules.  similarly to creating the on clause, specify a
                # stricter set of tables to create "sync rules" by,based on the immediate
                # inherited table, rather than all inherited tables
                self._synchronizer = sync.ClauseSynchronizer(
                    self, self, sync.ONETOMANY)
                self._synchronizer.compile(
                    self.table.onclause,
                    util.HashSet([inherits.noninherited_table]),
                    mapperutil.TableFinder(table))
                # the old rule
                #self._synchronizer.compile(self.table.onclause, inherits.tables, TableFinder(table))
            else:
                self._synchronizer = None
            self.inherits = inherits
            self.noninherited_table = table
            if self.order_by is False:
                self.order_by = inherits.order_by
        else:
            self.primarytable = self.table
            self.noninherited_table = self.table
            self._synchronizer = None
            self.inherits = None

        # locate all tables contained within the "table" passed in, which
        # may be a join or other construct
        self.tables = mapperutil.TableFinder(self.table)

        # determine primary key columns, either passed in, or get them from our set of tables
        self.pks_by_table = {}
        if primary_key is not None:
            for k in primary_key:
                self.pks_by_table.setdefault(
                    k.table, util.HashSet(ordered=True)).append(k)
                if k.table != self.table:
                    # associate pk cols from subtables to the "main" table
                    self.pks_by_table.setdefault(
                        self.table, util.HashSet(ordered=True)).append(k)
        else:
            for t in self.tables + [self.table]:
                try:
                    l = self.pks_by_table[t]
                except KeyError:
                    l = self.pks_by_table.setdefault(
                        t, util.HashSet(ordered=True))
                if not len(t.primary_key):
                    raise ArgumentError(
                        "Table " + t.name +
                        " has no primary key columns. Specify primary_key argument to mapper."
                    )
                for k in t.primary_key:
                    l.append(k)

        # make table columns addressable via the mapper
        self.columns = util.OrderedProperties()
        self.c = self.columns

        # object attribute names mapped to MapperProperty objects
        self.props = {}

        # table columns mapped to lists of MapperProperty objects
        # using a list allows a single column to be defined as
        # populating multiple object attributes
        self.columntoproperty = {}

        # load custom properties
        if properties is not None:
            for key, prop in properties.iteritems():
                if sql.is_column(prop):
                    try:
                        prop = self.table._get_col_by_original(prop)
                    except KeyError:
                        raise ArgumentError(
                            "Column '%s' is not represented in mapper's table"
                            % prop._label)
                    self.columns[key] = prop
                    prop = ColumnProperty(prop)
                elif isinstance(prop, list) and sql.is_column(prop[0]):
                    try:
                        prop = [
                            self.table._get_col_by_original(p) for p in prop
                        ]
                    except KeyError, e:
                        raise ArgumentError(
                            "Column '%s' is not represented in mapper's table"
                            % e.args[0])
                    self.columns[key] = prop[0]
                    prop = ColumnProperty(*prop)
                self.props[key] = prop
                if isinstance(prop, ColumnProperty):
                    for col in prop.columns:
                        proplist = self.columntoproperty.setdefault(
                            col.original, [])
                        proplist.append(prop)