def create_table(self, bq_table, project_id, dataset_id, table_id):
        """
    Create a table with the given schema in BigQuery.
    :param bq_table: BQTable object
    :param project_id: project id
    :param dataset_id: dataset id
    :param table_id: table id
    :return: True if successful otherwise False
    """
        bq_schema = bq_table.get_schema()
        tf = tempfile.NamedTemporaryFile(delete=False)
        tf.write(bq_schema.to_json())
        tf.close()

        # bq mk --table --expiration [INTEGER] --description [DESCRIPTION]
        #             --label [KEY:VALUE, KEY:VALUE] [PROJECT_ID]:[DATASET].[TABLE] [SCHEMA]
        args = '{0}:{1}.{2} {3}'.format(project_id, dataset_id, table_id,
                                        tf.name)
        cflags = '--table --label organization:rdr'
        pcode, so, se = gcp_bq_command('mk', args=args, command_flags=cflags)  # pylint: disable=unused-variable

        os.unlink(tf.name)

        if pcode != 0:
            if 'parsing error in row starting at position' in so:
                raise BQInvalidSchemaException(so)
            else:
                raise BQException(se if se else so)
        _logger.info('  {0}: {1}'.format(
            '{0}.{1}.{2}'.format(project_id, dataset_id,
                                 table_id).ljust(LJUST_WIDTH, '.'), 'created'))

        return True
    def get_table_schema(self, project_id, dataset_id, table_id):
        """
    Retrieve the table schema from BigQuery
    :param project_id: project id
    :param dataset_id: dataset id
    :param table_id: table id
    :return: string
    """
        # bq show --schema --format=prettyjson [PROJECT_ID]:[DATASET].[TABLE]
        args = '{0}:{1}.{2}'.format(project_id, dataset_id, table_id)
        pcode, so, se = gcp_bq_command(
            'show', args=args, command_flags='--schema --format=prettyjson')  # pylint: disable=unused-variable

        if pcode != 0:
            if 'Not found' in so:
                return None
            if 'Authorization error' in so:
                _logger.error(
                    '** BigQuery returned an authorization error, please check the following: **'
                )
                _logger.error('   * Service account has correct permissions.')
                _logger.error(
                    '   * Timezone and time on computer match PMI account settings.'
                )
                # for more suggestions look at:
                #    https://blog.timekit.io/google-oauth-invalid-grant-nightmare-and-how-to-fix-it-9f4efaf1da35
            raise BQException(se if se else so)

        return so
    def delete_view(self, bq_view, project_id, dataset_id, view_id):
        """
    Delete the view from BigQuery
    :param bq_view: BQView object
    :param project_id: project id
    :param dataset_id: dataset id
    :param view_id: table id
    :return: string
    """
        bq_table = bq_view.get_table()
        if not bq_table:
            raise ValueError(
                'BQView {0} does not have a BQTable object configured.')

        # bq rm --force --table [PROJECT_ID]:[DATASET].[TABLE]
        args = '{0}:{1}.{2}'.format(project_id, dataset_id, view_id)
        pcode, so, se = gcp_bq_command('rm',
                                       args=args,
                                       command_flags='--force --table')  # pylint: disable=unused-variable

        if pcode != 0:
            raise BQException(se if se else so)
        _logger.info('  {0}: {1}'.format(
            '{0}.{1}.{2}'.format(project_id, dataset_id,
                                 view_id).ljust(75, '.'), 'deleted'))

        return so
    def create_view(self, bq_view, project_id, dataset_id, view_id):
        """
    Create a view
    :param bq_view: BQView object
    :param project_id: project id
    :param dataset_id: dataset id
    :param view_id: table id
    :return: True if successful otherwise False
    """
        view_desc = bq_view.get_descr()
        view_sql = bq_view.get_sql()
        bq_table = bq_view.get_table()
        if not bq_table:
            raise ValueError(
                'BQView {0} does not have a BQTable object configured.')

        tmp_sql = view_sql.format(project=project_id, dataset=dataset_id)
        args = '{0}:{1}.{2}'.format(project_id, dataset_id, view_id)

        # Try to update
        cflags = "--description '{0}' --view '{1}'".format(view_desc, tmp_sql)
        pcode, so, se = gcp_bq_command('update',
                                       args=args,
                                       command_flags=cflags)  # pylint: disable=unused-variable

        if pcode == 0:
            _logger.info('  {0}: {1}'.format(
                '{0}.{1}.{2}'.format(project_id, dataset_id,
                                     view_id).ljust(LJUST_WIDTH, '.'),
                'updated'))
        else:
            cflags = "--use_legacy_sql=false --label organization:rdr --description '{0}' --view '{1}'".\
                          format(view_desc, tmp_sql)
            pcode, so, se = gcp_bq_command('mk',
                                           args=args,
                                           command_flags=cflags)  # pylint: disable=unused-variable
            if pcode != 0:
                raise BQException(se if se else so)
            _logger.info('  {0}: {1}'.format(
                '{0}.{1}.{2}'.format(project_id, dataset_id,
                                     view_id).ljust(LJUST_WIDTH, '.'),
                'created'))

        return True
    def delete_table(self, project_id, dataset_id, table_id):
        """
    Delete the table from BigQuery
    :param project_id: project id
    :param dataset_id: dataset id
    :param table_id: table id
    :return: String
    """
        # bq rm --force --table [PROJECT_ID]:[DATASET].[TABLE]
        args = '{0}:{1}.{2}'.format(project_id, dataset_id, table_id)
        pcode, so, se = gcp_bq_command('rm',
                                       args=args,
                                       command_flags='--force --table')  # pylint: disable=unused-variable

        if pcode != 0:
            raise BQException(se if se else so)
        _logger.info('  {0}: {1}'.format(
            '{0}.{1}.{2}'.format(project_id, dataset_id,
                                 table_id).ljust(LJUST_WIDTH, '.'), 'deleted'))

        return so
    def modify_table(self, bq_table, project_id, dataset_id, table_id):
        """
    Modify the schema of a table in BigQuery.
    :param bq_table: BQTable object
    :param project_id: project id
    :param dataset_id: dataset id
    :param table_id: table id
    :return: True if successful otherwise False
    """
        bq_schema = bq_table.get_schema()
        tf = tempfile.NamedTemporaryFile(delete=False)
        tf.write(bq_schema.to_json())
        tf.close()

        # bq update [PROJECT_ID]:[DATASET].[TABLE] [SCHEMA]
        args = '{0}:{1}.{2} {3}'.format(project_id, dataset_id, table_id,
                                        tf.name)
        pcode, so, se = gcp_bq_command('update', args=args)  # pylint: disable=unused-variable

        os.unlink(tf.name)

        if pcode == 0:
            _logger.info('  {0}: {1}'.format(
                '{0}.{1}.{2}'.format(project_id, dataset_id,
                                     table_id).ljust(LJUST_WIDTH, '.'),
                'updated'))
        else:
            if 'already exists in schema' in so:
                raise BQDuplicateFieldException(so)
            elif 'parsing error in row starting at position' in so:
                raise BQInvalidSchemaException(so)
            elif 'add required columns to an existing schema' in so:
                raise BQInvalidModeException(so)
            elif 'Precondition Failed' in so:
                raise BQSchemaStructureException(so)
            else:
                raise BQException(so)

        return True