Ejemplo n.º 1
0
    def insert_list(self, table_name, records):
        if not records:
            return

        columns = set()
        for r in records:
            columns |= set(r.keys())
        columns = jx.sort(columns)

        try:
            self.execute(
                "DELETE FROM " + self.quote_column(table_name) + SQL_WHERE +
                "_id IN {{ids}}",
                {"ids": self.quote_column([r["_id"] for r in records])})

            command = (SQL_INSERT + self.quote_column(table_name) +
                       sql_iso(sql_list(self.quote_column(k)
                                        for k in columns)) + SQL_VALUES +
                       sql_iso(
                           sql_list(
                               self.quote_value(r.get(k, None))
                               for k in columns for r in records)))
            self.execute(command)
        except Exception as e:
            Log.error("problem with insert", e)
Ejemplo n.º 2
0
    def to_sql(self, schema, not_null=False, boolean=False):
        lhs = SQLang[self.lhs].partial_eval()
        rhs = SQLang[self.rhs].partial_eval()
        lhs_sql = lhs.to_sql(schema, not_null=True)
        rhs_sql = rhs.to_sql(schema, not_null=True)
        if is_literal(rhs) and lhs_sql[0].sql.b != None and rhs.value in ("T",
                                                                          "F"):
            rhs_sql = BooleanOp(rhs).to_sql(schema)
        if is_literal(lhs) and rhs_sql[0].sql.b != None and lhs.value in ("T",
                                                                          "F"):
            lhs_sql = BooleanOp(lhs).to_sql(schema)

        if len(lhs_sql) != len(rhs_sql):
            Log.error("lhs and rhs have different dimensionality!?")

        acc = []
        for l, r in zip(lhs_sql, rhs_sql):
            for t in "bsnj":
                if r.sql[t] == None:
                    if l.sql[t] == None:
                        pass
                    else:
                        acc.append(ConcatSQL(l.sql[t], SQL_IS_NULL))
                elif l.sql[t] == None:
                    acc.append(ConcatSQL(r.sql[t], SQL_IS_NULL))
                else:
                    acc.append(
                        ConcatSQL(sql_iso(l.sql[t]), SQL_EQ,
                                  sql_iso(r.sql[t])))
        if not acc:
            return FALSE.to_sql(schema)
        else:
            return wrap([{"name": ".", "sql": {"b": JoinSQL(SQL_OR, acc)}}])
Ejemplo n.º 3
0
    def to_sql(self, schema, not_null=False, boolean=False):
        value = SQLang[self.expr].partial_eval()
        missing_value = value.missing().partial_eval()

        if not is_op(missing_value, MissingOp):
            return missing_value.to_sql(schema)

        value_sql = value.to_sql(schema)

        if len(value_sql) > 1:
            return wrap([{"name": ".", "sql": {"b": SQL_FALSE}}])

        acc = []
        for c in value_sql:
            for t, v in c.sql.items():
                if t in "bn":
                    acc.append(ConcatSQL(sql_iso(v), SQL_IS_NULL))
                if t == "s":
                    acc.append(ConcatSQL(
                        sql_iso(sql_iso(v), SQL_IS_NULL),
                        SQL_OR,
                        sql_iso(sql_iso(v), SQL_EQ, SQL_EMPTY_STRING)
                    ))

        if not acc:
            return wrap([{"name": ".", "sql": {"b": SQL_TRUE}}])
        else:
            return wrap([{"name": ".", "sql": {"b": SQL_AND.join(acc)}}])
Ejemplo n.º 4
0
def sql_create(table, properties, primary_key=None, unique=None):
    """
    :param table:  NAME OF THE TABLE TO CREATE
    :param properties: DICT WITH {name: type} PAIRS (type can be plain text)
    :param primary_key: COLUMNS THAT MAKE UP THE PRIMARY KEY
    :param unique: COLUMNS THAT SHOULD BE UNIQUE
    :return:
    """
    acc = [
        SQL_CREATE,
        quote_column(table),
        SQL_OP,
        sql_list([quote_column(k) + SQL(v) for k, v in properties.items()]),
    ]

    if primary_key:
        acc.append(SQL_COMMA),
        acc.append(SQL(" PRIMARY KEY ")),
        acc.append(
            sql_iso(sql_list([quote_column(c)
                              for c in listwrap(primary_key)])))
    if unique:
        acc.append(SQL_COMMA),
        acc.append(SQL(" UNIQUE ")),
        acc.append(
            sql_iso(sql_list([quote_column(c) for c in listwrap(unique)])))

    acc.append(SQL_CP)
    return ConcatSQL(*acc)
Ejemplo n.º 5
0
    def to_bq(self, schema, not_null=False, boolean=False):
        lhs = BQLang[self.lhs].to_bq(schema)[0].sql.n
        rhs = BQLang[self.rhs].to_bq(schema)[0].sql.n
        d = BQLang[self.default].to_bq(schema)[0].sql.n

        if lhs and rhs:
            if d == None:
                return wrap(
                    [{"name": ".", "sql": {"n": sql_iso(lhs) + " / " + sql_iso(rhs)}}]
                )
            else:
                return wrap(
                    [
                        {
                            "name": ".",
                            "sql": {
                                "n": sql_coalesce(
                                    [sql_iso(lhs) + " / " + sql_iso(rhs), d]
                                )
                            },
                        }
                    ]
                )
        else:
            return Null
Ejemplo n.º 6
0
    def _insert(self, collection):
        for nested_path, details in collection.items():
            active_columns = wrap(list(details.active_columns))
            rows = details.rows
            num_rows = len(rows)
            table_name = concat_field(self.name, nested_path)

            if table_name == self.name:
                # DO NOT REQUIRE PARENT OR ORDER COLUMNS
                meta_columns = [GUID, UID]
            else:
                meta_columns = [UID, PARENT, ORDER]

            all_columns = meta_columns + active_columns.es_column  # ONLY THE PRIMITIVE VALUE COLUMNS
            command = ConcatSQL(
                SQL_INSERT,
                quote_column(table_name),
                sql_iso(sql_list(map(quote_column, all_columns))),
                SQL_VALUES,
                sql_list(
                    sql_iso(sql_list(quote_value(row.get(c)) for c in all_columns))
                    for row in unwrap(rows)
                )
            )

            with self.db.transaction() as t:
                t.execute(command)
Ejemplo n.º 7
0
    def _nest_column(self, column):
        new_path, type_ = untyped_column(column.es_column)
        if type_ != SQL_NESTED_TYPE:
            Log.error("only nested types can be nested")
        destination_table = concat_field(self.fact_name, new_path)
        existing_table = concat_field(self.fact_name, column.nested_path[0])

        # FIND THE INNER COLUMNS WE WILL BE MOVING
        moving_columns = []
        for c in self.columns:
            if destination_table != column.es_index and column.es_column == c.es_column:
                moving_columns.append(c)
                c.nested_path = new_path

        # TODO: IF THERE ARE CHILD TABLES, WE MUST UPDATE THEIR RELATIONS TOO?

        # LOAD THE COLUMNS
        data = self.namespace.db.about(destination_table)
        if not data:
            # DEFINE A NEW TABLE
            command = (
                SQL_CREATE + quote_column(destination_table) + sql_iso(sql_list([
                    quoted_UID + "INTEGER",
                    quoted_PARENT + "INTEGER",
                    quoted_ORDER + "INTEGER",
                    "PRIMARY KEY " + sql_iso(quoted_UID),
                    "FOREIGN KEY " + sql_iso(quoted_PARENT) + " REFERENCES " + quote_column(existing_table) + sql_iso(quoted_UID)
                ]))
            )
            with self.namespace.db.transaction() as t:
                t.execute(command)
                self.add_table([new_path]+column.nested_path)

        # TEST IF THERE IS ANY DATA IN THE NEW NESTED ARRAY
        if not moving_columns:
            return

        column.es_index = destination_table
        with self.namespace.db.transaction() as t:
            t.execute(
                "ALTER TABLE " + quote_column(destination_table) +
                " ADD COLUMN " + quote_column(column.es_column) + " " + column.es_type
            )

            # Deleting parent columns
            for col in moving_columns:
                column = col.es_column
                tmp_table = "tmp_" + existing_table
                columns = list(map(text, t.query(SQL_SELECT + SQL_STAR + SQL_FROM + quote_column(existing_table) + SQL_LIMIT + SQL_ZERO).header))
                t.execute(
                    "ALTER TABLE " + quote_column(existing_table) +
                    " RENAME TO " + quote_column(tmp_table)
                )
                t.execute(
                    SQL_CREATE + quote_column(existing_table) + SQL_AS +
                    SQL_SELECT + sql_list([quote_column(c) for c in columns if c != column]) +
                    SQL_FROM + quote_column(tmp_table)
                )
                t.execute("DROP TABLE " + quote_column(tmp_table))
Ejemplo n.º 8
0
 def to_bq(self, schema, not_null=False, boolean=False):
     value = self.value.to_bq(schema, not_null=True)[0].sql.s
     start = self.start.to_bq(schema, not_null=True)[0].sql.n
     if self.length is NULL:
         sql = "SUBSTR" + sql_iso(sql_list([value, start]))
     else:
         length = self.length.to_bq(schema, not_null=True)[0].sql.n
         sql = "SUBSTR" + sql_iso(sql_list([value, start, length]))
     return wrap([{"name": ".", "sql": sql}])
Ejemplo n.º 9
0
def sql_insert(table, records):
    records = listwrap(records)
    keys = list({k for r in records for k in r.keys()})
    return ConcatSQL(
        SQL_INSERT,
        quote_column(table),
        sql_iso(sql_list(map(quote_column, keys))),
        SQL_VALUES,
        sql_list(
            sql_iso(sql_list([quote_value(r[k]) for k in keys]))
            for r in records),
    )
Ejemplo n.º 10
0
    def insert(self, table_name, record):
        keys = list(record.keys())

        try:
            command = (
                SQL_INSERT + quote_column(table_name) +
                sql_iso(sql_list([quote_column(k) for k in keys])) +
                SQL_VALUES +
                sql_iso(sql_list([quote_value(record[k]) for k in keys]))
            )
            self.execute(command)
        except Exception as e:
            Log.error("problem with record: {{record}}", record=record, cause=e)
Ejemplo n.º 11
0
def _inequality_to_bq(self, schema, not_null=False, boolean=False, many=True):
    op, identity = _sql_operators[self.op]
    lhs = NumberOp(self.lhs).partial_eval().to_bq(schema, not_null=True)[0].sql.n
    rhs = NumberOp(self.rhs).partial_eval().to_bq(schema, not_null=True)[0].sql.n
    sql = sql_iso(lhs) + op + sql_iso(rhs)

    output = BQLScript(
        data_type=BOOLEAN,
        expr=sql,
        frum=self,
        miss=OrOp([self.lhs.missing(), self.rhs.missing()]),
        schema=schema,
    )
    return output
Ejemplo n.º 12
0
    def _load_functions(self):
        global _load_extension_warning_sent
        library_loc = File.new_instance(sys.modules[__name__].__file__,
                                        "../..")
        full_path = File.new_instance(
            library_loc, "vendor/sqlite/libsqlitefunctions.so").abspath
        try:
            trace = get_stacktrace(0)[0]
            if self.upgrade:
                if os.name == "nt":
                    file = File.new_instance(
                        trace["file"],
                        "../../vendor/sqlite/libsqlitefunctions.so")
                else:
                    file = File.new_instance(
                        trace["file"],
                        "../../vendor/sqlite/libsqlitefunctions")

                full_path = file.abspath
                self.db.enable_load_extension(True)
                self.db.execute(
                    text(SQL_SELECT + "load_extension" +
                         sql_iso(quote_value(full_path))))
        except Exception as e:
            if not _load_extension_warning_sent:
                _load_extension_warning_sent = True
                Log.warning(
                    "Could not load {{file}}, doing without. (no SQRT for you!)",
                    file=full_path,
                    cause=e,
                )
Ejemplo n.º 13
0
    def insert_new(self, table_name, candidate_key, new_record):
        candidate_key = listwrap(candidate_key)

        condition = sql_eq(**{k: new_record[k] for k in candidate_key})
        command = (
            SQL_INSERT + quote_column(table_name) +
            sql_iso(sql_list(quote_column(k) for k in new_record.keys())) +
            SQL_SELECT + "a.*" + SQL_FROM + sql_iso(SQL_SELECT + sql_list([
                quote_value(v) + " " + quote_column(k)
                for k, v in new_record.items()
            ]) + SQL_FROM + "DUAL") + " a" + SQL_LEFT_JOIN +
            sql_iso(SQL_SELECT + "'dummy' exist " + SQL_FROM +
                    quote_column(table_name) + SQL_WHERE + condition +
                    SQL_LIMIT + SQL_ONE) + " b ON " + SQL_TRUE + SQL_WHERE +
            " exist " + SQL_IS_NULL)
        self.execute(command, {})
Ejemplo n.º 14
0
    def to_bq(self, schema, not_null=False, boolean=False):
        value = self.value.to_bq(schema, not_null=True)[0].sql.s
        find = self.find.to_bq(schema, not_null=True)[0].sql.s

        return wrap(
            [{"name": ".", "sql": {"n": "INSTR" + sql_iso(sql_list([value, find]))}}]
        )
Ejemplo n.º 15
0
    def to_bq(self, schema, not_null=False, boolean=False):
        acc = []
        for term in self.terms:
            sqls = BQLang[term].to_bq(schema)
            if len(sqls) > 1:
                acc.append(SQL_TRUE)
            else:
                for t, v in sqls[0].sql.items():
                    if t in ["b", "s", "n"]:
                        acc.append(
                            ConcatSQL(
                                SQL_CASE,
                                SQL_WHEN,
                                sql_iso(v),
                                SQL_IS_NULL,
                                SQL_THEN,
                                SQL_ZERO,
                                SQL_ELSE,
                                SQL_ONE,
                                SQL_END,
                            ))
                    else:
                        acc.append(SQL_TRUE)

        if not acc:
            return wrap([{}])
        else:
            return wrap([{"nanme": ".", "sql": {"n": SQL("+").join(acc)}}])
Ejemplo n.º 16
0
    def get_sql(self, get_ids):
        sql = self._compose_sql(get_ids)

        # ORDERING
        sort = []
        ordering = []
        for ci, c in enumerate(self.columns):
            if c.sort:
                sort.append(quote_column(c.column_alias) + SQL_IS_NOT_NULL)
                sort.append(quote_column(c.column_alias))
                ordering.append(ci)

        union_all_sql = SQL_UNION_ALL.join(sql)
        union_all_sql = ConcatSQL(
            SQL_SELECT,
            SQL_STAR,
            SQL_FROM,
            sql_alias(sql_iso(union_all_sql), "a"),
            SQL_ORDERBY,
            sql_list(sort),
        )
        if DEBUG:
            Log.note("{{sql}}", sql=union_all_sql)

        return union_all_sql
Ejemplo n.º 17
0
    def to_bq(self, schema, not_null=False, boolean=False):
        default = self.default.to_bq(schema)
        if len(self.terms) == 0:
            return default
        default = coalesce(default[0].sql.s, SQL_NULL)
        sep = BQLang[self.separator].to_bq(schema)[0].sql.s

        acc = []
        for t in self.terms:
            t = BQLang[t]
            missing = t.missing().partial_eval()

            term = t.to_bq(schema, not_null=True)[0].sql
            if term.s:
                term_sql = term.s
            elif term.n:
                term_sql = "cast(" + term.n + " as text)"
            else:
                term_sql = (SQL_CASE + SQL_WHEN + term.b + SQL_THEN +
                            quote_value("true") + SQL_ELSE +
                            quote_value("false") + SQL_END)

            if isinstance(missing, TrueOp):
                acc.append(SQL_EMPTY_STRING)
            elif missing:
                acc.append(
                    SQL_CASE + SQL_WHEN +
                    sql_iso(missing.to_bq(schema, boolean=True)[0].sql.b) +
                    SQL_THEN + SQL_EMPTY_STRING + SQL_ELSE +
                    sql_iso(sql_concat_text([sep, term_sql])) + SQL_END)
            else:
                acc.append(sql_concat_text([sep, term_sql]))

        expr_ = "SUBSTR" + sql_iso(
            sql_list([
                sql_concat_text(acc),
                LengthOp(self.separator).to_bq(schema)[0].sql.n + SQL("+1"),
            ]))

        return BQLScript(
            expr=expr_,
            data_type=STRING,
            frum=self,
            miss=self.missing(),
            many=False,
            schema=schema,
        )
Ejemplo n.º 18
0
 def to_bq(self, schema, not_null=False, boolean=False):
     v = self.value.to_bq(schema)[0].sql
     return wrap([{
         "name": ".",
         "sql": {
             "n": "UNIX_TIMESTAMP" + sql_iso(v.n)
         }
     }])
Ejemplo n.º 19
0
    def _window_op(self, query, window):
        # http://www2.sqlite.org/cvstrac/wiki?p=UnsupportedSqlAnalyticalFunctions
        if window.value == "rownum":
            return ("ROW_NUMBER()-1 OVER (" + " PARTITION BY " +
                    sql_iso(sql_list(window.edges.values)) + SQL_ORDERBY +
                    sql_iso(sql_list(window.edges.sort)) + ") AS " +
                    quote_column(window.name))

        range_min = text(coalesce(window.range.min, "UNBOUNDED"))
        range_max = text(coalesce(window.range.max, "UNBOUNDED"))

        return (sql_aggs[window.aggregate] +
                sql_iso(window.value.to_sql(schema)) + " OVER (" +
                " PARTITION BY " + sql_iso(sql_list(window.edges.values)) +
                SQL_ORDERBY + sql_iso(sql_list(window.edges.sort)) +
                " ROWS BETWEEN " + range_min + " PRECEDING AND " + range_max +
                " FOLLOWING " + ") AS " + quote_column(window.name))
Ejemplo n.º 20
0
def basic_multiop_to_bq(self,
                        schema,
                        not_null=False,
                        boolean=False,
                        many=False):
    op, identity = _sql_operators[self.op.split("basic.")[1]]
    sql = op.join(
        sql_iso(BQLang[t].to_bq(schema)[0].sql.n) for t in self.terms)
    return wrap([{"name": ".", "sql": {"n": sql}}])
Ejemplo n.º 21
0
 def about(self, table_name):
     """
     :param table_name: TABLE IF INTEREST
     :return: SOME INFORMATION ABOUT THE TABLE
         (cid, name, dtype, notnull, dfft_value, pk) tuples
     """
     details = self.query("PRAGMA table_info" +
                          sql_iso(quote_column(table_name)))
     return details.data
Ejemplo n.º 22
0
 def to_bq(self, schema, not_null=False, boolean=False):
     value = BQLang[self.value].to_bq(schema, not_null=True)[0].sql.s
     start = (AddOp([self.start, Literal(1)
                     ]).partial_eval().to_bq(schema,
                                             not_null=True)[0].sql.n)
     length = (SubOp([self.end, self.start
                      ]).partial_eval().to_bq(schema,
                                              not_null=True)[0].sql.n)
     sql = "SUBSTR" + sql_iso(value + "," + start + ", " + length)
     return wrap([{"name": ".", "sql": {"s": sql}}])
Ejemplo n.º 23
0
 def to_bq(self, schema, not_null=False, boolean=False):
     terms = [
         BQLang[t].partial_eval().to_bq(schema)[0].sql.n for t in self.terms
     ]
     return wrap([{
         "name": ".",
         "sql": {
             "n": "min" + sql_iso((sql_list(terms)))
         }
     }])
Ejemplo n.º 24
0
def _binaryop_to_bq(self, schema, not_null=False, boolean=False, many=True):
    op, identity = _sql_operators[self.op]

    lhs = NumberOp(self.lhs).partial_eval().to_bq(schema,
                                                  not_null=True)[0].sql.n
    rhs = NumberOp(self.rhs).partial_eval().to_bq(schema,
                                                  not_null=True)[0].sql.n
    script = sql_iso(lhs) + op + sql_iso(rhs)
    if not_null:
        sql = script
    else:
        missing = OrOp([self.lhs.missing(), self.rhs.missing()]).partial_eval()
        if missing is FALSE:
            sql = script
        else:
            sql = ("CASE WHEN " +
                   missing.to_bq(schema, boolean=True)[0].sql.b +
                   " THEN NULL ELSE " + script + " END")
    return wrap([{"name": ".", "sql": {"n": sql}}])
Ejemplo n.º 25
0
    def insert_list(self, table_name, records):
        if not records:
            return

        keys = set()
        for r in records:
            keys |= set(r.keys())
        keys = jx.sort(keys)

        try:
            command = (SQL_INSERT + quote_column(table_name) +
                       sql_iso(sql_list([quote_column(k) for k in keys])) +
                       SQL_VALUES + sql_list(
                           sql_iso(sql_list([quote_value(r[k]) for k in keys]))
                           for r in records))
            self.execute(command)
        except Exception as e:
            Log.error("problem with record: {{record}}",
                      record=records,
                      cause=e)
Ejemplo n.º 26
0
    def to_sql(self, schema, not_null=False, boolean=False):
        field = self.field.to_sql(schema)[0].sql
        acc = []
        for t, v in field.items():
            if t in "bns":
                acc.append(sql_iso(v + SQL_IS_NOT_NULL))

        if not acc:
            return wrap([{"name": ".", "sql": {"b": SQL_FALSE}}])
        else:
            return wrap([{"name": ".", "sql": {"b": SQL_OR.join(acc)}}])
Ejemplo n.º 27
0
    def to_bq(self, schema, not_null=False, boolean=False):
        lhs = BQLang[self.lhs].to_bq(schema)
        rhs = BQLang[self.rhs].to_bq(schema)
        acc = []
        if len(lhs) != len(rhs):
            Log.error("lhs and rhs have different dimensionality!?")

        for l, r in zip(lhs, rhs):
            for t in "bsnj":
                if l.sql[t] == None:
                    if r.sql[t] == None:
                        pass
                    else:
                        acc.append(sql_iso(r.sql[t]) + SQL_IS_NULL)
                elif l.sql[t] is ZERO:
                    if r.sql[t] == None:
                        acc.append(SQL_FALSE)
                    elif r.sql[t] is ZERO:
                        Log.error(
                            "Expecting expression to have been simplified already"
                        )
                    else:
                        acc.append(r.sql[t])
                else:
                    if r.sql[t] == None:
                        acc.append(sql_iso(l.sql[t]) + SQL_IS_NULL)
                    elif r.sql[t] is ZERO:
                        acc.append(l.sql[t])
                    else:
                        acc.append(
                            sql_iso(l.sql[t]) + " = " + sql_iso(r.sql[t]))
        if not acc:
            return FALSE.to_bq(schema)
        else:
            return BQLScript(
                expr=SQL_OR.join(acc),
                frum=self,
                data_type=BOOLEAN,
                miss=FALSE,
                schema=schema,
            )
Ejemplo n.º 28
0
 def to_bq(self, schema, not_null=False, boolean=False):
     if not is_op(self.superset, Literal):
         Log.error("Not supported")
     j_value = json2value(self.superset.json)
     if j_value:
         var = BQLang[self.value].to_bq(schema)
         sql = SQL_OR.join(
             sql_iso(ConcatSQL(v, SQL_IN, quote_list(j_value)))
             for t, v in var[0].sql.items())
     else:
         sql = SQL_FALSE
     return wrap([{"name": ".", "sql": {"b": sql}}])
Ejemplo n.º 29
0
 def to_bq(self, schema, not_null=False, boolean=False):
     test = BQLang[self.term].missing().to_bq(schema, boolean=True)[0].sql.b
     value = BQLang[self.term].to_bq(schema, not_null=True)[0].sql
     acc = []
     for t, v in value.items():
         if t == "b":
             acc.append(SQL_CASE + SQL_WHEN + sql_iso(test) + SQL_THEN +
                        SQL_NULL + SQL_WHEN + sql_iso(v) + SQL_THEN +
                        "'true'" + SQL_ELSE + "'false'" + SQL_END)
         elif t == "s":
             acc.append(v)
         else:
             acc.append("RTRIM(RTRIM(CAST" +
                        sql_iso(v + " as TEXT), " + quote_value("0")) +
                        ", " + quote_value(".") + ")")
     if not acc:
         return wrap([{}])
     elif len(acc) == 1:
         return wrap([{"name": ".", "sql": {"s": acc[0]}}])
     else:
         return wrap([{"name": ".", "sql": {"s": sql_coalesce(acc)}}])
Ejemplo n.º 30
0
 def to_sql(self, schema, not_null=False, boolean=False):
     not_expr = NotOp(BooleanOp(self.term)).partial_eval()
     if is_op(not_expr, NotOp):
         return wrap([{
             "name": ".",
             "sql": {
                 "b":
                 "NOT " + sql_iso(not_expr.term.to_sql(schema)[0].sql.b)
             },
         }])
     else:
         return not_expr.to_sql(schema)