code: def apply_sql(self, ex, values, lockref):
      
      sqex.depth_first_sub(ex,values)
      with self.lock_db(lockref, isinstance(ex,sqparse2.StartX)):
        sqex.replace_subqueries(ex,self,table.Table)
        if isinstance(ex,sqparse2.SelectX): return sqex.run_select(ex,self,table.Table)
        elif isinstance(ex,sqparse2.InsertX): return self[ex.table].insert(ex.cols,ex.values,ex.ret,self)
        elif isinstance(ex,sqparse2.UpdateX):
          if len(ex.tables)!=1: raise NotImplementedError('multi-table update')
          return self[ex.tables[0]].update(ex.assigns,ex.where,ex.ret,self)
        elif isinstance(ex,sqparse2.CreateX): self.create(ex)
        elif isinstance(ex,sqparse2.IndexX): pass
        elif isinstance(ex,sqparse2.DeleteX): return self[ex.table].delete(ex.where,self)
        elif isinstance(ex,sqparse2.StartX): self.trans_start(lockref)
        elif isinstance(ex,sqparse2.CommitX): self.trans_commit()
        elif isinstance(ex,sqparse2.RollbackX): self.trans_rollback()
        elif isinstance(ex,sqparse2.DropX): self.drop(ex)
        else: raise TypeError(type(ex))
docs: call the stmt in tree with values subbed on the tables in t_d.
      ex is a parsed statement returned by parse_expression.
      values is the tuple of %s replacements.
      lockref can be anything as long as it stays the same; it's used for assigning tranaction ownership.
        (safest is to make it a pgmock_dbapi2.Connection, because that will rollback on close)