예제 #1
0
    def get_query(self):
        """
        Returns a  string representing an SQL query. The string will point
        to the database cache of this query if it exists.

        Returns
        -------
        str
            SQL query string.

        """
        try:
            table_name = self.fully_qualified_table_name
            schema, name = table_name.split(".")
            with rlock(self.redis, self.md5):
                if self.connection.has_table(schema=schema, name=name):
                    try:
                        touch_cache(self.connection, self.md5)
                    except ValueError:
                        pass  # Cache record not written yet, which can happen for Models
                        # which will call through to this method from their `_make_query` method while writing metadata.
                    # In that scenario, the table _is_ written, but won't be visible from the connection touch_cache uses
                    # as the cache metadata transaction isn't complete!
                    return "SELECT * FROM {}".format(table_name)
        except NotImplementedError:
            pass
        return self._make_query()
예제 #2
0
 def do_query() -> ModelResult:
     logger.debug("Getting storage lock.")
     with rlock(self.redis, self.md5):
         logger.debug("Obtained storage lock.")
         con = self.connection.engine
         if force:
             self.invalidate_db_cache(name, schema=schema)
         try:
             with con.begin():
                 logger.debug("Using pandas to store.")
                 self._df.to_sql(name, con, schema=schema, index=False)
                 if schema == "cache":
                     self._db_store_cache_metadata(
                         compute_time=self._runtime)
         except AttributeError:
             logger.debug(
                 "No dataframe to store, presumably because this"
                 " was retrieved from the db.")
     logger.debug("Released storage lock.")
     return self
예제 #3
0
 def do_query() -> Query:
     logger.debug("Getting storage lock.")
     with rlock(self.redis, self.md5):
         logger.debug("Obtained storage lock.")
         query_ddl_ops = self._make_sql(name,
                                        schema=schema,
                                        force=force)
         logger.debug("Made SQL.")
         con = self.connection.engine
         if force:
             self.invalidate_db_cache(name, schema=schema)
         plan_time = 0
         with con.begin():
             ddl_op_results = []
             for ddl_op in query_ddl_ops:
                 try:
                     ddl_op_result = con.execute(ddl_op)
                 except Exception as e:
                     logger.error(
                         f"Error executing SQL: '{ddl_op}'. Error was {e}"
                     )
                     raise e
                 try:
                     ddl_op_results.append(ddl_op_result.fetchall())
                 except ResourceClosedError:
                     pass  # Nothing to do here
                 for ddl_op_result in ddl_op_results:
                     try:
                         plan = ddl_op_result[0][0][
                             0]  # Should be a query plan
                         plan_time += plan["Execution Time"]
                     except (IndexError, KeyError):
                         pass  # Not an explain result
             logger.debug("Executed queries.")
             if schema == "cache":
                 self._db_store_cache_metadata(compute_time=plan_time)
     logger.debug("Released storage lock.")
     return self
예제 #4
0
    def invalidate_db_cache(self,
                            name=None,
                            schema=None,
                            cascade=True,
                            drop=True):
        """
        Helper function for store, drops this table, and (by default) any
        that depend on it, as well as removing them from
        the cache metadata table.

        Parameters
        ----------
        name : str
            Name of the table
        schema : str
            Schema of the table
        cascade : bool
            Set to false to remove only this table from cache
        drop : bool
            Set to false to remove the cache record without dropping the table
        """
        with rlock(self.redis, self.md5):
            con = self.connection.engine
            try:
                table_reference_to_this_query = self.get_table()
                if table_reference_to_this_query is not self:
                    table_reference_to_this_query.invalidate_db_cache(
                        cascade=cascade,
                        drop=drop)  # Remove any Table pointing as this query
            except (ValueError, NotImplementedError) as e:
                pass  # This cache record isn't actually stored
            try:
                deps = self.connection.fetch(
                    """SELECT obj FROM cache.cached LEFT JOIN cache.dependencies
                    ON cache.cached.query_id=cache.dependencies.query_id
                    WHERE depends_on='{}'""".format(self.md5))
                with con.begin():
                    con.execute("DELETE FROM cache.cached WHERE query_id=%s",
                                (self.md5, ))
                    logger.debug("Deleted cache record for {}.".format(
                        self.fully_qualified_table_name))
                    if drop:
                        con.execute("DROP TABLE IF EXISTS {}".format(
                            self.fully_qualified_table_name))
                        logger.debug("Dropped cache for for {}.".format(
                            self.fully_qualified_table_name))

                if cascade:
                    for rec in deps:
                        dep = pickle.loads(rec[0])
                        logger.debug(
                            "Cascading to {} from cache record for {}.".format(
                                dep.fully_qualified_table_name,
                                self.fully_qualified_table_name,
                            ))
                        dep.invalidate_db_cache()
                else:
                    logger.debug("Not cascading to dependents.")
            except NotImplementedError:
                logger.info("Table has no standard name.")
            if schema is not None:
                full_name = "{}.{}".format(schema, name)
            else:
                full_name = name
            logger.debug("Dropping {}".format(full_name))
            with con.begin():
                con.execute("DROP TABLE IF EXISTS {}".format(full_name))
예제 #5
0
 def unlock(timer):
     with rlock(dl.redis, dl.md5):
         for i in range(101):
             timer.append(i)