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)
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)
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 + ")"
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)