def validate(self, context): if self.view is not None and context.views.raw_def(self.view) is None: raise ValidationError('view {} is not defined'.format(self.view), self) if not self.force and os.path.isfile(self.filename): raise ValidationError('file {} already exists; to overwrite use {} after {}'\ .format(self.filename, literal(sym.FORCE), literal(sym.SAVE)), self)
def __str__(self): s = literal(sym.RENAME) + literal(sym.ARG_L) if self.relname is not None: s += self.relname + literal(sym.COLON) + ' ' if self.attrnames is None: s += literal(sym.STAR) else: s += ', '.join(name for name in self.attrnames) s += literal(sym.ARG_R) + ' ' + str(paren(self.inputs[0])) return s
def validate(self, context): if self.view is not None: if context.views.raw_def(self.view) is None: raise ValidationError('view {} is not defined'.format(self.view), self) if not self.force: dependents = context.views.find_dependents(self.view) if len(dependents) > 0: raise ValidationError('view {} is used in defining others ({});' ' to clear them all, use {} after {}'\ .format(self.view, ', '.join(dependents), literal(sym.FORCE), literal(sym.CLEAR)), self)
def info(self): views = self.definition.find_views() yield 'VIEW {} depends on '.format(self.view) +\ ('no other views' if len(views) == 0 else ', '.join(views)) yield literal(sym.GETS) for line in self.definition.info(): yield line
def execute_from_file(filename, context, echo=False): for ast in statements_from_file(filename): if echo: print(str(ast) + literal(sym.TERMINATOR)) ast.validate(context) logger.info('statement validated:') for line in ast.info(): logger.info(line) ast.execute(context)
def execute(self, context): views = context.views.topo(self.view) try: with open(self.filename, 'w') as f: for v in views: print('{} {} {};'.format(v, literal(sym.GETS), context.views.raw_def(v)), file=f) print('wrote file {}'.format(self.filename)) except Exception as e: raise ExecutionError('writing to {} failed'.format(self.filename), self) from e
def execute(self, context): if self.cmd == sym.LIST: print('database relations:') for table in context.db.list(): attrs = ['{}:{}'.format(attr, type.value)\ for attr, type in context.db.describe(table)] print(' {}({})'.format(table, ', '.join(attrs))) if len(context.views.list()) > 0: print('views defined:') for view in context.views.list(): raw_def = context.views.raw_def(view) ast = RelExpr.from_view_def(raw_def) logging.disable(logging.WARNING) ast.validate(context) logging.disable(logging.NOTSET) print(' {}({}) {} {}'.format( view, ', '.join(ast.type.str_attr_names_and_types()), literal(sym.GETS), raw_def)) elif self.cmd == sym.QUIT: sys.exit(0)
def __str__(self): return ('{}' if self.can_omit_paren() else\ literal(sym.PAREN_L) + '{}' + literal(sym.PAREN_R))\ .format(self.expr)
def info(self): return self.func + literal(sym.PAREN_L) +\ ', '.join(arg.info() for arg in self.args) +\ literal(sym.PAREN_R)
def __str__(self): return '{} {} {}'.format(self.view, literal(sym.GETS), self.definition)
def __str__(self): return '{} {} {}'.format(paren(self.inputs[0]), literal(self.op()), paren(self.inputs[1]))
def __str__(self): cond = '' if self.cond is None else\ literal(sym.ARG_L) + str(self.cond) + literal(sym.ARG_R) return '{} {}{} {}'.format(paren(self.inputs[0]), literal(sym.JOIN), cond, paren(self.inputs[1]))
def __str__(self): return literal(sym.SELECT) + literal(sym.ARG_L) + str(self.cond) + literal(sym.ARG_R) +\ ' ' + str(paren(self.inputs[0]))
def __str__(self): if self.rel is None: return self.name else: return self.rel + literal(sym.DOT) + self.name
def __str__(self): return literal(sym.SAVE) +\ (literal(sym.FORCE) if self.force else '') + ' ' +\ (literal(sym.STAR) if self.view is None else self.view) + ' ' +\ str_to_sqlstr(self.filename)
def __str__(self): return literal(sym.CLEAR) +\ (literal(sym.FORCE) if self.force else '') + ' ' +\ (literal(sym.STAR) if self.view is None else self.view)
def from_view_def(view_def): return one_statement_from_string(view_def + literal(sym.TERMINATOR))
def sql(self, relexpr): fmt = '{input} {op}' if self.op in ( sym.IS_NULL, sym.IS_NOT_NULL) else '{op} {input}' return fmt.format(op=literal(self.op), input=paren(self.inputs[0]).sql(relexpr))
def info(self): fmt = '{input} {op}' if self.op in ( sym.IS_NULL, sym.IS_NOT_NULL) else '{op} {input}' return fmt.format(op=literal(self.op), input=paren(self.inputs[0]).info())
def sql(self, relexpr): return '{} {} {}'.format( paren(self.inputs[0]).sql(relexpr), literal(self.op), paren(self.inputs[1]).sql(relexpr))
def info(self): return '{} {} {}'.format( paren(self.inputs[0]).info(), literal(self.op), paren(self.inputs[1]).info())
def __str__(self): return literal(self.cmd)
def __str__(self): return self.func + literal(sym.PAREN_L) +\ ', '.join(str(arg) for arg in self.args) +\ literal(sym.PAREN_R)
def sql(self, relexpr): return self.func + literal(sym.PAREN_L) +\ ', '.join(arg.sql(relexpr) for arg in self.args) +\ literal(sym.PAREN_R)
def info(self): yield lreplace(str(self), literal(sym.CLEAR), symbolic(sym.CLEAR))
def info(self): yield lreplace(str(self), literal(sym.SOURCE), symbolic(sym.SOURCE))
def __str__(self): return literal(sym.SOURCE) + ' ' + str_to_sqlstr(self.filename)
def execute(self, context): if self.cmd == sym.LIST: print('database relations:') for table in context.db.list(): attrs = ['{}:{}'.format(attr, type.value)\ for attr, type in context.db.describe(table)] print(' {}({})'.format(table, ', '.join(attrs))) if len(context.views.list()) > 0: print('views defined:') for view in context.views.list(): raw_def = context.views.raw_def(view) ast = RelExpr.from_view_def(raw_def) logging.disable(logging.WARNING) ast.validate(context) logging.disable(logging.NOTSET) print(' {}({}) {} {}'.format( view, ', '.join(ast.type.str_attr_names_and_types()), literal(sym.GETS), raw_def)) elif self.cmd == sym.HELP: print(r''' Relational Operators: Selection: \select{ CONDITION } INPUT_REL Projection: \project{ ATTR_1, ATTR_2, ... } INPUT_REL (Theta-)Join: INPUT_REL_1 \join_{ CONDITION } INPUT_REL_2 Natural Join: INPUT_REL_1 \join INPUT_REL_2 Cross Product: INPUT_REL_1 \cross INPUT_REL_2 Set Union: INPUT_REL_1 \union INPUT_REL_2 Set Difference: INPUT_REL_1 \diff INPUT_REL_2 Set Intersection: INPUT_REL_1 \intersect INPUT_REL_2 Rename: \rename_{ NEW_ATTR_NAME_1, NEW_ATTR_NAME_2, ... } INPUT_REL \rename_{ NEW_REL_NAME: * } INPUT_REL \rename_{ NEW_REL_NAME: NEW_ATTR_NAME_1, NEW_ATTR_NAME_2, ... } INPUT_REL Aggregation: \aggr_{ AGGR_EXP_1, AGGR_EXP_2, ... } INPUT_REL \aggr_{ GROUP_BY_ATTR_1, GROUP_BY_ATTR_2, ...: AGGR_EXP_1, AGGR_EXP_2, ... } INPUT_REL Writing Relational Algebra Queries: * End every query with a semicolon (;). * The simplest query is one that returns a database relation, i.e.: REL_NAME; * Build a complex query by nesting: you can feed a subquery as an input relation to another relational operator (using parentheses to enclose the subquery as necessary to avoid ambiguity) , e.g.: \select_{CONDITION} (\project_{ATTR1, ATTR2} REL_1 ) \join REL_2; Commands: \help; \quit; \list; List database relatoions and user-defined views \clear *; Clear all user view definitions \clear! V; Clear definition for view V those dependant on it \save 'FILE'; Save all view defintions to FILE \save V 'FILE'; Save definition for view V to FILE, along with any definitions it depends on \source 'FILE'; Execute RA statements from FILE \sqlexec_{ SQL }; Execute SQL (a single statement) in the underlying database For more details, see ''' + context.configured['setup.docbaseurl'] + ''' ''') elif self.cmd == sym.QUIT: sys.exit(0)
def __str__(self): return literal(sym.SQLEXEC) +\ literal(sym.ARG_L) + self.sql + literal(sym.ARG_R)
def __str__(self): return literal(sym.PROJECT) + literal(sym.ARG_L) +\ ', '.join(str(attr) for attr in self.attrs) +\ literal(sym.ARG_R) + ' ' + str(paren(self.inputs[0]))