def generate_sql(field_map, input_data, macro_map={}): """ This is method to be call for transpiling SQL query. e.g. generate_sql({1 : 'name'}, ['!=', ['field', 1], None])) shoud return SELECT * FROM data WHERE name IS NOT NULL. For bonus point, you may pass in a macro map as well. If that is the case, please specify macro id in the input data, do it like ['macro' : 'is_joe']. :type field_map: dict :type input_data: list :type macro_map: dict :rtype: str """ if input_data == []: return SQL_HEADER entity = Entity(input_data) where_clause = '' if entity.is_simple_clause(): where_clause = transpile_simple_clause(field_map, entity, macro_map) elif entity.is_compound_clause(): where_clause = transpile_compound_clause(field_map, entity, macro_map) elif entity.is_macro(): where_clause = transpile_macro(field_map, entity, macro_map) else: raise TranspilerError("Input (%s) not recognized." % (input_data)) return SQL_HEADER + ' WHERE '+ where_clause
def transpile_field(field_map, field_entity): """ Map field id to column name in the field_map """ field_id = field_entity.get_field_id() if field_id not in field_map: raise TranspilerError("Field id (%s) does not exist." % (field_id)) return field_map.get(field_id)
def transpile_compound_clause(field_map, clause_entity, macro_map={}, subclause=False): """ Transpile compound clause. subclause parameter indicates whether this compound clause is a sub clause of another compound clause. """ if not clause_entity.is_compound_clause(): raise TranspilerError("Clause (%s) is not a compound clause." % (clause)) operator = clause_entity.get_operator() entities = clause_entity.get_arguments() transpiled_entities = [] # Each sub entity can either be a simple clause, compound clause or macro. # If it is a compound clause, then it needs to be wrapped in a pair of # parenthesis. for sub_entity in entities: if sub_entity.is_simple_clause(): transpiled_entities.append( transpile_simple_clause(field_map, sub_entity)) elif sub_entity.is_compound_clause(): transpiled_entities.append( transpile_compound_clause(field_map, sub_entity, subclause=True)) elif sub_entity.is_macro(): transpiled_entities.append( transpile_macro(field_map, sub_entity, macro_map, subclause=True)) else: raise TranspilerError( 'Entity (%s) should be a clause but it is not.' % (sub_entity)) transpiled_compound_clause = join_tokens(transpiled_entities, operator) # If the input compound clause is a subclause of another compound clause, then we wrap it up # with '()'. return '(' + transpiled_compound_clause + ')' if subclause else transpiled_compound_clause
def transpile_macro(field_map, macro_entity, macro_map={}, subclause=False): """ Transpile macro entity. """ macro_id = macro_entity.get_macro_id() if macro_id not in macro_map: raise TranspilerError("Macro id: (%s) does not exist." % (macro_id)) entity = Entity(macro_map[macro_id]) if entity.is_macro(): # This takes care of one macro point to another macro, which # is weird, but possible. return transpile_macro(field_map, entity, macro_map) elif entity.is_simple_clause(): return transpile_simple_clause(field_map, entity, macro_map) elif entity.is_compound_clause(): return transpile_compound_clause(field_map, entity, macro_map, subclause=subclause) else: raise TranspilerError('Macro entity (%s) not recognized.' % (entity))
def transpile_simple_clause(field_map, clause_entity, macro_map={}): """ Transpile the whole simple clause. """ if not clause_entity.is_simple_clause(): raise TranspilerError("Clause (%s) is not a simple clause." % (clause_entity)) else: operator = clause_entity.get_operator() arguments = clause_entity.get_arguments() if operator in ['is_empty', 'not_empty']: field_entity = arguments[0] return { 'is_empty': lambda m, f: transpile_is_empty(m, f), 'not_empty': lambda m, f: transpile_not_empty(m, f) }[operator](field_map, field_entity) else: # It is simple clause with one operator and two arguments, follows # [<operator>, <field>, <literal>] format. field_entity, literal_entity = arguments return transpile_comparison(field_map, operator, field_entity, literal_entity)
def __validate_macro(self): if not self.is_macro(): raise TranspilerError("Not a macro: %s" % (self.i__item))
def __validate_field_value(self): if not self.is_field_value(): raise TranspilerError("Not a field value entity: %s!" % (self.__item))
def __validate_literal_value(self): if not self.is_literal_value(): raise TranspilerError("Not a literal value entity: %s!" % (self.__item))
def __validate_clause(self): if not self.is_clause(): raise TranspilerError("Not a clause entity: %s!" % (self.__item))