def select(self, name, columns, where): results = ResultsTable(name, columns) for row in self.rows: match = True if where: ctx = RqlContext() ctx.variables.update(row) match = ctx.evaluate(where.predicate) if match: results.insert([row[field] for field in columns]) return results
def Select(self, stmt): alias_map = {} alias_rmap = {} # Extract the tables to scan source_tables = set() tables = {} for source in stmt.get_data_sources(): if source.query: name = source.alias or str(source.query) tables[name] = Select(source.query) else: name = source.name.name source_tables.add(name) tables[name] = self.tables[name] if source.alias: alias_map[source.alias] = name alias_rmap[name] = source.aliases # Map where-clauses result-fields to tables expr_fields = [] table_results_map = defaultdict(list) for index, result in enumerate(stmt.results): if isinstance(result, SqlColumnWild): for source in source_tables: table_results_map[source].extend(alias_map.get(k, k) for k in self.tables[source].columns) elif isinstance(result, SqlTableWild): table_results_map[result.table].extend(alias_map.get(k, k) for k in self.tables[source].columns) elif isinstance(result.expr, RqlIdentifier): field_name = result.expr.name index = field_name.rfind('.') if index > 0: source = field_name[:index] field_name = field_name[1+index:] table_results_map[source].append(field_name) else: for source in source_tables: table = self.tables[source] if field_name in table.columns: table_results_map[source].append(field_name) break # TODO: Extract where clause for the field else: # TODO: Expr may contains references to a table expr_fields.append((index, result)) if result.alias: name = str(result.expr) alias_map[result.alias] = name alias_rmap[name] = result.alias # Scan each source results = [] for source, fields in table_results_map.iteritems(): result = self.tables[source].select(source, fields, stmt.where) results.append(result) # Join and apply where-clauses if len(results) > 1: results = list(reversed(results)) # TODO: Apply the proper join... while len(results) >= 2: res_a = results.pop() res_b = results.pop() join_result = cross_join(res_a, res_b) results.append(join_result) results = results[0] if expr_fields: for row in results.rows: new_values = [] for index, field in expr_fields: ctx = RqlContext() ctx.variables.update(dict(zip(results.columns, row))) ctx.variables.update({alias_map.get(k, k): v for k, v in zip(results.columns, row)}) value = ctx.evaluate(field.expr) new_values.append((index, value)) for index, value in new_values: row.insert(index, value) for index, field in expr_fields: results.columns.insert(index, str(field.expr)) # Replace column names with the alias # blah.. move up to the result_table.aliases results.columns = [alias_map.get(name, name) for name in results.columns] if stmt.group_by: key = stmt.group_by.groups[0].name results = group_by(results, key) if stmt.order_by: results.sort([(o.column, -1 if o.order_type == 'DESC' else 1) for o in stmt.order_by]) return results
def Insert(self, stmt): table = self.tables[stmt.destination.name] ctx = RqlContext() table.insert({name: ctx.evaluate(expr) for name, expr in zip(stmt.columns, stmt.values)})