def map_field_attr(table_name, field_identifier, column_type):
    assert(field_identifier != None)
    if not field_exists(table_name, field_identifier):
        # Create new Field
        new_column = Column(field_identifier, column_type)
        table = setobject_table_registry.lookup_by_table(table_name)
        new_column.create(table)

        # re-map setobject type
        map_tables(exclude_sys_tables=True)
 def map_computed_properties(cls):
     cls.sa_map_dispose()
     table_name = cls.get_table_name()
     table_type = setobject_table_registry.lookup_by_table(table_name)
     if not hasattr(cls, 'mapper_properties'):
         raise Exception("Can't map without mapping properties. Ensure that they are " \
             "created beforehand with compute_mapper_properties."
             )
     orm.mapper(cls,
               table_type,
               properties=cls.mapper_properties,
               )
 def __setattr__(self, name, value):
     super(Dropdown, self).__setattr__(name, value)
     if name == 'linkage':
         if self.plan_identifier != None and value != None:
             # Get the table identifier from our plan identifier and set it as the linkage's target class
             table = setobject_table_registry.lookup_by_table('p2_model')
             plan = getUtility(IDbUtility).engine.execute(table.select(table.c.plan_identifier == self.plan_identifier)).first()
             plan_type = plan['so_type']
             table_identifier = setobject_type_registry.lookup(plan_type).get_table_name()
             oldtargetclass = None
             try:
                 oldtargetclass = self.linkage.target_classname
             except AttributeError:
                 pass
             if oldtargetclass == None or oldtargetclass == "":
                 self.linkage.target_classname = table_identifier
def orm_mapping(event=None):
    # Register table type for grokked ModelBase classes
    registered = []
    for setobject_type in setobject_type_registry.values():
        class_name = setobject_type.__name__
        table_name = setobject_type.get_table_name()
        # Create SA table type
        if setobject_table_registry.get_by_table(table_name) == None:
            table_type = Table(table_name, metadata, autoload=True)
        else:
            table_type = setobject_table_registry.lookup_by_table(table_name)
        # And register it.
        setobject_table_registry.register_type(class_name, table_name, table_type)
        registered.append(class_name)

    # register all the non-grokked, remaining tables (e.g. user tables) 
    register_remaining_tables(registered)
    
    map_tables() 
    def compute_orm_properties(self, THIS_IS_A_DIRTY_HACK_PROPERTIES_DICT):
        mappedsotype = setobject_type_registry.lookup(self.target_model.klass)
        xref_table_class = None
        sourcetable = setobject_table_registry.lookup_by_class(self.source_model.klass)
        targettable = setobject_table_registry.lookup_by_class(self.target_model.klass)
        if self.cardinality.id == 'MANY_TO_ONE' or \
                self.cardinality.id == 'ONE(FK)_TO_ONE':
            # take primary key on our side
            primaryfk = getattr(sourcetable.c, self.relation.foreignkeycol)
            primaryidentifier = getattr(targettable.c, mappedsotype.get_primary_key_attr_name())
            primaryjoin = (primaryfk == primaryidentifier)
            secondaryjoin = None
        elif self.cardinality.id == 'ONE_TO_MANY' or \
                self.cardinality.id == 'ONE_TO_ONE(FK)':
            # take primary key on other side
            primaryfk = getattr(targettable.c, self.relation.foreignkeycol)
            primaryidentifier = getattr(
                sourcetable.c,
                setobject_type_registry.lookup(self.source_model.klass).get_primary_key_attr_name()
            )
            primaryjoin = (primaryfk == primaryidentifier)
            secondaryjoin = None
        elif self.cardinality.id == 'MANY_TO_MANY':
            # xref! we actually need two clauses here.
            
            # Obtain table class:
            xref_table_class = setobject_table_registry.get_by_table(self.relation.xref_table)
            if xref_table_class is None:
                # Class is not mapped (probably not having a primary key or something like that) -> autoload
                xref_table_class = Table(self.relation.xref_table, metadata, autoload=True, useexisting=True, autoload_with=getUtility(IDbUtility).engine)
            
            # Compose two join clauses
            primaryjoin = (cls.get_primary_key_column() == getattr(xref_table_class.c, self.relation.foreignkeycol))
            secondaryjoin = (mappedsotype.get_primary_key_column() == getattr(xref_table_class.c, self.relation.foreignkeycol2))
        
        # add the obtained setobject to our mapped properties
        if self.cardinality.id == 'MANY_TO_ONE':
            # This mapping should really not happen here and now.
            # Instead, the linkage MUST be persisted into
            # table p2_linkage at save time!

            THIS_IS_A_DIRTY_HACK_PROPERTIES_DICT[self.attr_name] = orm.relation(
                mappedsotype,
                uselist=False,
                cascade=self.cascade,
                back_populates=self.back_populates,
                primaryjoin=primaryjoin,
                post_update=self.post_update
            )
            relationarguments = {
                'uselist' : False,
                'cascade' : self.cascade,
                'back_populates' : self.back_populates,
                'primaryjoin' : primaryjoin,
                'post_update' : self.post_update
            }
        else:
            # the other side has the foreign key, store things as a collection
            
            order_by = None
            collection_class = None
            
            # This is a special case for the spans as they should not be mapped as ordinary
            # dictionary, but rather as an orderable dictionary. This is necessary to retain the insert order
            # as a ordinary dict isn't ordered. Consider this to be implemented in a more generic way if this
            # use case is occuring for user relations as well.
            if self.attr_name == 'spans' and self.source_model.klass == 'WidgetType':
                collection_class=SpanCollectionClass
                span_table = setobject_table_registry.lookup_by_table('p2_span')
                order_by=span_table.c.order
            
            # This is another special case to ensure the widgets being tab ordered
            if self.attr_name == 'widgets' and self.source_model.klass == 'FormType':
                collection_class = WidgetCollectionClass
                widget_table = setobject_table_registry.lookup_by_table('p2_widget')
                order_by=widget_table.c.tab_order
            
            # Get collection class
            if collection_class == None:
                if self.ref_key is None:
                    collection_class = column_mapped_collection(mappedsotype.get_primary_key_column())
                else:
                    mapped_column = mappedsotype.get_column(self.ref_key)
                    collection_class = column_mapped_collection(mapped_column)
            
            # Compute arguments:
            relationarguments = {
                'back_populates' : self.back_populates,
                'collection_class' : collection_class,
                'uselist' : True,
                'primaryjoin': primaryjoin,
                'cascade' : self.cascade,
                'post_update' : self.post_update
                }
            if order_by is not None:
                relationarguments['order_by'] = order_by
        
        # Set xref table if we got one
        if xref_table_class is not None:
            relationarguments['secondary'] = xref_table_class
            if secondaryjoin is not None:
                relationarguments['secondaryjoin'] = secondaryjoin
        
        return relationarguments
 def get_table_class(cls):
     return setobject_table_registry.lookup_by_table(cls.get_table_name())
    def do(self, plan, searchterm, group, page, resultsperpage, uservars=[]):
        """ Do a search on the plan based on a generic search term and return the results.
        The results will also be associated with information about which fields actually
        matched the search query and whether there is a next page to the current one. 
        Please note this implementation is most likely SLOW and could need optimization or
        replacement at some point. """

        dbutility = getUtility(IDbUtility)
        
        # change searchterm into LIKE compatible syntax
        searchterm = self.replaceoperators(searchterm)
        
        # list to hold the search values/columns we collect from the widgets
        searchvalues = []
            
        # collect all columns based on the widgets on the form and their mapping
        for form in plan.forms.itervalues():
            for widget in form.widgets.itervalues():
                if widget.widget_type == 'relation' or \
                        widget.widget_type == 'fileupload' or \
                        widget.widget_type == 'dropdown':
                    continue
                for span in widget.spans.itervalues():
                    if hasattr(span, 'attr_name') and span.attr_name != None:
                        # We got a new column to examine.
                        if span.attr_name != 'span_value' and len(span.attr_name) > 0:
                            self.addsearchvalue(searchvalues, span.attr_name, widget.widget_identifier, form.form_identifier)
        
        # do we have some columns to search through?
        #if len(searchvalues) <= 0:
        #    return {'resultset' : None, 'searchfields' : None, 'nextpage': False} # nothing to search for!
        
        # get the table class object
        tableclass = setobject_table_registry.lookup_by_table(plan.table_identifier)
        
        # lists for composing the conditions/columns used in our query
        conditions = []
        columns = []
        
        # we always want to have the primary key column in our results
        klass = setobject_type_registry.lookup(plan.klass)
        columns.append(getattr(tableclass.c, klass.get_primary_key_attr_name()))
        
        # compose the search conditions based on the avilable input fields
        for value in searchvalues:
            if searchterm != '%':
                condition = getattr(tableclass.c, value['field']).like(searchterm, escape='\\')
            else:
                condition1 = getattr(tableclass.c, value['field']).like(searchterm, escape='\\')
                condition2 = (getattr(tableclass.c, value['field']) == None)
                condition = or_(condition1, condition2)
            conditions.append(condition)
            columns.append(getattr(tableclass.c, value['field']))
            columns.append(condition.label("_field_matched_" + value['field']))
        
        # compose our query
        if len(conditions) > 0:
            queryobj = select(columns).where(or_(*conditions)).offset((int(page)-1) * resultsperpage).limit(resultsperpage+1)
        else:
            queryobj = select(columns).offset((int(page)-1) * resultsperpage).limit(resultsperpage+1)
        
        # See if there is a next page to this one
        gotnextpage = False
        resultarray = []
        results = queryobj.execute()
        for result in results:
            if len(resultarray) < resultsperpage:
                resultarray.append(result)
            else:
                gotnextpage = True
        
        return {'resultset' : resultarray, 'searchfields' : searchvalues, 'nextpage' : gotnextpage}