code: def expression_type(con, topx, ex):
    "take a BaseX descendant from sqparse2, return a type class from above"
    if isinstance(ex,sqparse2.Literal):
      if isinstance(ex.val,basestring): return STRING
      else: raise NotImplementedError('literal', type(ex.val))
    elif isinstance(ex,sqparse2.AttrX):
      if ex.parent.name in con.db: # warning: what if it's not a table? what if it's aliased?
        return expression_type(con, topx, con.db[ex.parent.name].get_column(ex.attr.name).coltp)
      else:
        raise NotImplementedError(ex.parent)
    elif isinstance(ex,sqparse2.TypeX):
      return dict(
        integer=NUMBER,
        text=STRING,
      )[ex.type.lower()]
    else:
      raise NotImplementedError('unk type', type(ex)f expression_type(con, topx, ex):
    "take a BaseX descendant from sqparse2, return a type class from above"
    if isinstance(ex,sqparse2.Literal):
      if isinstance(ex.val,basestring): return STRING
      else: raise NotImplementedError('literal', type(ex.val))
    elif isinstance(ex,sqparse2.AttrX):
      if ex.parent.name in con.db: # warning: what if it's not a table? what if it's aliased?
        return expression_type(con, topx, con.db[ex.parent.name].get_column(ex.attr.name).coltp)
      else:
        raise NotImplementedError(ex.parent)
    elif isinstance(ex,sqparse2.TypeX):
      return dict(
        integer=NUMBER,
        text=STRING,
      )[ex.type.lower()]
    else:
      raise NotImplementedError('unk type', type(ex))
docs: take a BaseX descendant from sqparse2, return a type class from above