def migration25(tdset): """ Add _grist_Filters table and populate based on existing filters stored in _grist_Views_section_field. From this version on, filter in _grist_Views_section_field is deprecated. """ doc_actions = [ actions.AddTable('_grist_Filters', [ schema.make_column("viewSectionRef", "Ref:_grist_Views_section"), schema.make_column("colRef", "Ref:_grist_Tables_column"), schema.make_column("filter", "Text"), ]) ] # Move existing field filters to _grist_Filters. fields = list( actions.transpose_bulk_action( tdset.all_tables['_grist_Views_section_field'])) col_info = {'filter': [], 'colRef': [], 'viewSectionRef': []} for f in fields: if not f.filter: continue col_info['filter'].append(f.filter) col_info['colRef'].append(f.colRef) col_info['viewSectionRef'].append(f.parentId) num_filters = len(col_info['filter']) if num_filters > 0: doc_actions.append( actions.BulkAddRecord('_grist_Filters', [None] * num_filters, col_info)) return tdset.apply_doc_actions(doc_actions)
def migration2(tdset): """ Add TableViews table, and populate based on existing sections. Add TabBar table, and populate based on existing views. Add PrimaryViewId to Tables and populated using relatedViews """ # Maps tableRef to viewRef primary_views = {} # Associate each view with a single table; this dict includes primary views. views_to_table = {} # For each table, find a view to serve as the primary view. view_sections = actions.transpose_bulk_action( tdset.all_tables['_grist_Views_section']) for s in view_sections: if s.tableRef not in primary_views and s.parentKey == "record": # The view containing this section is a good candidate for primary view. primary_views[s.tableRef] = s.parentId if s.parentId not in views_to_table: # The first time we see a (view, table) combination, associate the view with that table. views_to_table[s.parentId] = s.tableRef def create_primary_views_action(primary_views): row_ids = sorted(primary_views.keys()) values = {'primaryViewId': [primary_views[r] for r in row_ids]} return actions.BulkUpdateRecord('_grist_Tables', row_ids, values) def create_tab_bar_action(views_to_table): row_ids = list(xrange(1, len(views_to_table) + 1)) return actions.ReplaceTableData( '_grist_TabBar', row_ids, {'viewRef': sorted(views_to_table.keys())}) def create_table_views_action(views_to_table, primary_views): related_views = sorted( set(views_to_table.keys()) - set(primary_views.values())) row_ids = list(xrange(1, len(related_views) + 1)) return actions.ReplaceTableData( '_grist_TableViews', row_ids, { 'tableRef': [views_to_table[v] for v in related_views], 'viewRef': related_views, }) return tdset.apply_doc_actions([ actions.AddTable('_grist_TabBar', [ schema.make_column('viewRef', 'Ref:_grist_Views'), ]), actions.AddTable('_grist_TableViews', [ schema.make_column('tableRef', 'Ref:_grist_Tables'), schema.make_column('viewRef', 'Ref:_grist_Views'), ]), add_column('_grist_Tables', 'primaryViewId', 'Ref:_grist_Views'), create_primary_views_action(primary_views), create_tab_bar_action(views_to_table), create_table_views_action(views_to_table, primary_views) ])
def migration24(tdset): return tdset.apply_doc_actions([ actions.AddTable( '_grist_Triggers', [ schema.make_column("tableRef", "Ref:_grist_Tables"), schema.make_column("eventTypes", "ChoiceList"), schema.make_column("isReadyColRef", "Ref:_grist_Tables_column"), schema.make_column("actions", "Text"), # JSON ]), ])
def migration20(tdset): """ Add _grist_Pages table and populate based on existing TableViews entries, ie: tables are sorted alphabetically by their `tableId` and views are gathered within their corresponding table and sorted by their id. """ tables = list( actions.transpose_bulk_action(tdset.all_tables['_grist_Tables'])) table_map = {t.id: t for t in tables} table_views = list( actions.transpose_bulk_action(tdset.all_tables['_grist_TableViews'])) # Old docs may include "Other views", not associated with any table. Don't include those in # table_views_map: they'll get included but not sorted or grouped by tableId. table_views_map = { tv.viewRef: table_map[tv.tableRef].tableId for tv in table_views if tv.tableRef in table_map } views = list( actions.transpose_bulk_action(tdset.all_tables['_grist_Views'])) def view_key(view): """ Returns ("Table1", 2) where "Table1" is the view's tableId and 2 the view id. For primary view (ie: not referenced in _grist_TableViews) returns ("Table1", -1). Useful to get the list of views sorted in the same way as in the Table side pane. We use -1 for primary view to make sure they come first among all the views of the same table. """ if view.id in table_views_map: return (table_views_map[view.id], view.id) # the name of primary view's is the same as the tableId return (view.name, -1) views.sort(key=view_key) row_ids = list(xrange(1, len(views) + 1)) return tdset.apply_doc_actions([ actions.AddTable('_grist_Pages', [ schema.make_column('viewRef', 'Ref:_grist_Views'), schema.make_column('pagePos', 'PositionNumber'), schema.make_column('indentation', 'Int'), ]), actions.ReplaceTableData( '_grist_Pages', row_ids, { 'viewRef': [v.id for v in views], 'pagePos': row_ids, 'indentation': [1 if v.id in table_views_map else 0 for v in views] }) ])
def migration1(tdset): """ Add TabItems table, and populate based on existing sections. """ doc_actions = [] # The very first migration is extra-lax, and creates some tables that are missing in some test # docs. That's only because we did not distinguish schema version before migrations were # implemented. Other migrations should not need such conditionals. if '_grist_Attachments' not in tdset.all_tables: doc_actions.append( actions.AddTable("_grist_Attachments", [ schema.make_column("fileIdent", "Text"), schema.make_column("fileName", "Text"), schema.make_column("fileType", "Text"), schema.make_column("fileSize", "Int"), schema.make_column("timeUploaded", "DateTime") ])) if '_grist_TabItems' not in tdset.all_tables: doc_actions.append( actions.AddTable("_grist_TabItems", [ schema.make_column("tableRef", "Ref:_grist_Tables"), schema.make_column("viewRef", "Ref:_grist_Views"), ])) if 'schemaVersion' not in tdset.all_tables['_grist_DocInfo'].columns: doc_actions.append(add_column('_grist_DocInfo', 'schemaVersion', 'Int')) doc_actions.extend([ add_column('_grist_Attachments', 'imageHeight', 'Int'), add_column('_grist_Attachments', 'imageWidth', 'Int'), ]) view_sections = actions.transpose_bulk_action( tdset.all_tables['_grist_Views_section']) rows = sorted({(s.tableRef, s.parentId) for s in view_sections}) if rows: values = { 'tableRef': [r[0] for r in rows], 'viewRef': [r[1] for r in rows] } row_ids = list(xrange(1, len(rows) + 1)) doc_actions.append( actions.ReplaceTableData('_grist_TabItems', row_ids, values)) return tdset.apply_doc_actions(doc_actions)
def migration14(tdset): # Create the ACL table AND also the default ACL groups, default resource, and the default rule. # These match the actions applied to new document by 'InitNewDoc' useraction (as of v14). return tdset.apply_doc_actions([ actions.AddTable('_grist_ACLMemberships', [ schema.make_column('parent', 'Ref:_grist_ACLPrincipals'), schema.make_column('child', 'Ref:_grist_ACLPrincipals'), ]), actions.AddTable('_grist_ACLPrincipals', [ schema.make_column('userName', 'Text'), schema.make_column('groupName', 'Text'), schema.make_column('userEmail', 'Text'), schema.make_column('instanceId', 'Text'), schema.make_column('type', 'Text'), ]), actions.AddTable('_grist_ACLResources', [ schema.make_column('colIds', 'Text'), schema.make_column('tableId', 'Text'), ]), actions.AddTable('_grist_ACLRules', [ schema.make_column('aclFormula', 'Text'), schema.make_column('principals', 'Text'), schema.make_column('resource', 'Ref:_grist_ACLResources'), schema.make_column('aclColumn', 'Ref:_grist_Tables_column'), schema.make_column('permissions', 'Int'), ]), # Set up initial ACL data. actions.BulkAddRecord( '_grist_ACLPrincipals', [1, 2, 3, 4], { 'type': ['group', 'group', 'group', 'group'], 'groupName': ['Owners', 'Admins', 'Editors', 'Viewers'], }), actions.AddRecord('_grist_ACLResources', 1, { 'tableId': '', 'colIds': '' }), actions.AddRecord('_grist_ACLRules', 1, { 'resource': 1, 'permissions': 0x3F, 'principals': '[1]' }), ])
def add_column(table_id, col_id, col_type, *args, **kwargs): return actions.AddColumn( table_id, col_id, schema.make_column(col_id, col_type, *args, **kwargs))