(self)
Request handler for POST operations.
Request handler for POST operations.
Request handler for POST operations .
def post(self):
    """Request handler for POST operations."""
    try:
      start_time = time.time()
      urlfetch.set_default_fetch_deadline(URLFETCH_TIMEOUT)

      config = explorer_config.ExplorerConfigModel.Get()

      request_data = json.loads(self.request.body)

      datasource = request_data.get('datasource')
      if not datasource:
        raise KeyError('The datasource is required to run a query')

      query = datasource.get('query_exec') or datasource.get('query')

      if not query:
        raise KeyError('datasource.query must be provided.')

      if (not config.grant_query_to_public and
          not users.is_current_user_admin()):
        dashboard_id = request_data.get('dashboard_id')
        if not dashboard_id:
          raise KeyError('The dashboard id is required to run a query')

        widget_id = request_data.get('id')
        if not widget_id:
          raise KeyError('The widget id is required to run a query')

        if dashboard.Dashboard.IsQueryCustom(query, dashboard_id, widget_id):
          raise SecurityError('The user is not authorized to run custom queries')
        else:
          logging.error('Query is identical.')

      cache_duration = config.cache_duration or None

      logging.debug('Query datasource: %s', datasource)
      query_config = datasource['config']

      if datasource.get('type', 'BigQuery') == 'Cloud SQL':
        logging.debug('Using Cloud SQL backend')
        cloudsql_client_config = query_config.get('cloudsql')
        if not cloudsql_client_config:
          cloudsql_client_config = {}

        cloudsql_server_config = cloudsql_config.CloudsqlConfigModel.Get()

        client = gae_cloud_sql_client.GaeCloudSqlClient(
          instance=cloudsql_client_config.get('instance'),
          db_name=cloudsql_client_config.get('database_name'),
          db_user=cloudsql_server_config.username,
          db_password=cloudsql_server_config.password)
      else:
        logging.debug('Using BigQuery backend')
        client = DataHandlerUtil.GetDataClient(self.env)

      client.project_id = config.default_project
      response = client.Query(query, cache_duration=cache_duration)

      if query_config['results'].get('pivot'):
        pivot_config = query_config['results']['pivot_config']

        transformer = big_query_result_pivot.BigQueryPivotTransformer(
            reply=response,
            rows_name=pivot_config['row_field'],
            columns_name=pivot_config['column_field'],
            values_name=pivot_config['value_field'])
        transformer.Transform()

      response['results'] = (
          result_util.ReplyFormatter.RowsToDataTableFormat(response))

      elapsed_time = time.time() - start_time
      response['elapsedTime'] = elapsed_time
      self.RenderJson(response)

    # If 'expected' errors occur (specifically dealing with SQL problems),
    # return JSON with descriptive text so that we can give the user a
    # constructive error message.
    # TODO: Formalize error reporting/handling across the application.
    except (big_query_client.BigQueryError, big_query_result_pivot.DuplicateValueError,
            ValueError, KeyError, SecurityError) as err:
      logging.error(str(err))
      self.RenderJson({'error': str(err)})
    except MySQLdb.OperationalError as err:
      self.RenderJson({'error': 'MySQLdb error %s' % str(err)})
    except (google.appengine.runtime.DeadlineExceededError,
            apiproxy_errors.DeadlineExceededError,
            urlfetch_errors.DeadlineExceededError):
      self.RenderText(text=ERROR_TIMEOUT, status=408)
def post ( self ) : try : start_time = time . time ( ) urlfetch . set_default_fetch_deadline ( URLFETCH_TIMEOUT ) config = explorer_config . ExplorerConfigModel . Get ( ) request_data = json . loads ( self . request . body ) datasource = request_data . get ( 'datasource' ) if not datasource : raise KeyError ( 'The datasource is required to run a query' ) query = datasource . get ( 'query_exec' ) or datasource . get ( 'query' ) if not query : raise KeyError ( 'datasource.query must be provided.' ) if ( not config . grant_query_to_public and not users . is_current_user_admin ( ) ) : dashboard_id = request_data . get ( 'dashboard_id' ) if not dashboard_id : raise KeyError ( 'The dashboard id is required to run a query' ) widget_id = request_data . get ( 'id' ) if not widget_id : raise KeyError ( 'The widget id is required to run a query' ) if dashboard . Dashboard . IsQueryCustom ( query , dashboard_id , widget_id ) : raise SecurityError ( 'The user is not authorized to run custom queries' ) else : logging . error ( 'Query is identical.' ) cache_duration = config . cache_duration or None logging . debug ( 'Query datasource: %s' , datasource ) query_config = datasource [ 'config' ] if datasource . get ( 'type' , 'BigQuery' ) == 'Cloud SQL' : logging . debug ( 'Using Cloud SQL backend' ) cloudsql_client_config = query_config . get ( 'cloudsql' ) if not cloudsql_client_config : cloudsql_client_config = { } cloudsql_server_config = cloudsql_config . CloudsqlConfigModel . Get ( ) client = gae_cloud_sql_client . GaeCloudSqlClient ( instance = cloudsql_client_config . get ( 'instance' ) , db_name = cloudsql_client_config . get ( 'database_name' ) , db_user = cloudsql_server_config . username , db_password = cloudsql_server_config . password ) else : logging . debug ( 'Using BigQuery backend' ) client = DataHandlerUtil . GetDataClient ( self . env ) client . project_id = config . default_project response = client . Query ( query , cache_duration = cache_duration ) if query_config [ 'results' ] . get ( 'pivot' ) : pivot_config = query_config [ 'results' ] [ 'pivot_config' ] transformer = big_query_result_pivot . BigQueryPivotTransformer ( reply = response , rows_name = pivot_config [ 'row_field' ] , columns_name = pivot_config [ 'column_field' ] , values_name = pivot_config [ 'value_field' ] ) transformer . Transform ( ) response [ 'results' ] = ( result_util . ReplyFormatter . RowsToDataTableFormat ( response ) ) elapsed_time = time . time ( ) - start_time response [ 'elapsedTime' ] = elapsed_time self . RenderJson ( response ) # If 'expected' errors occur (specifically dealing with SQL problems), # return JSON with descriptive text so that we can give the user a # constructive error message. # TODO: Formalize error reporting/handling across the application. except ( big_query_client . BigQueryError , big_query_result_pivot . DuplicateValueError , ValueError , KeyError , SecurityError ) as err : logging . error ( str ( err ) ) self . RenderJson ( { 'error' : str ( err ) } ) except MySQLdb . OperationalError as err : self . RenderJson ( { 'error' : 'MySQLdb error %s' % str ( err ) } ) except ( google . appengine . runtime . DeadlineExceededError , apiproxy_errors . DeadlineExceededError , urlfetch_errors . DeadlineExceededError ) : self . RenderText ( text = ERROR_TIMEOUT , status = 408 )