<commit_before># -*- coding: utf-8 -*-
"""Classes to read from and write to SQLite databases."""

from __future__ import unicode_literals

import re

import sqlite3

from esedbrc import py2to3


class Sqlite3DatabaseFile(object):
  """SQLite3 database file."""

  _HAS_TABLE_QUERY = (
      'SELECT name FROM sqlite_master '
      'WHERE type = "table" AND name = "{0:s}"')

  def __init__(self):
    """Initializes a database file."""
    super(Sqlite3DatabaseFile, self).__init__()
    self._connection = None
    self._cursor = None
    self.filename = None
    self.read_only = None

  def Close(self):
    """Closes the database file.

    Raises:
      RuntimeError: if the database is not opened.
    """
    if not self._connection:
      raise RuntimeError('Cannot close database not opened.')

    # We need to run commit or not all data is stored in the database.
    self._connection.commit()
    self._connection.close()

    self._connection = None
    self._cursor = None
    self.filename = None
    self.read_only = None

  def CreateTable(self, table_name, column_definitions):
    """Creates a table.

    Args:
      table_name (str): table name.
      column_definitions (list[str]): column definitions.

    Raises:
      RuntimeError: if the database is not opened or
          if the database is in read-only mode.
    """
    if not self._connection:
      raise RuntimeError('Cannot create table database not opened.')

    if self.read_only:
      raise RuntimeError('Cannot create table database in read-only mode.')

    sql_query = 'CREATE TABLE {0:s} ( {1:s} )'.format(
        table_name, ', '.join(column_definitions))

    self._cursor.execute(sql_query)

  def GetValues(self, table_names, column_names, condition):
    """Retrieves values from a table.

    Args:
      table_names (list[str]): table names.
      column_names (list[str]): column names.
      condition (str): condition.

    Yields:
      sqlite3.row: a row.

    Raises:
      RuntimeError: if the database is not opened.
    """
    if not self._connection:
      raise RuntimeError('Cannot retrieve values database not opened.')

    if condition:
      condition = ' WHERE {0:s}'.format(condition)

    sql_query = 'SELECT {1:s} FROM {0:s}{2:s}'.format(
        ', '.join(table_names), ', '.join(column_names), condition)

    self._cursor.execute(sql_query)

    for row in self._cursor:
      values = {}
      for column_index, column_name in enumerate(column_names):
        values[column_name] = row[column_index]
      yield values

  def HasTable(self, table_name):
    """Determines if a specific table exists.

    Args:
      table_name (str): table name.

    Returns:
      bool: True if the table exists, False otheriwse.

    Raises:
      RuntimeError: if the database is not opened.
    """
    if not self._connection:
      raise RuntimeError(
          'Cannot determine if table exists database not opened.')

    sql_query = self._HAS_TABLE_QUERY.format(table_name)

    self._cursor.execute(sql_query)

    return bool(self._cursor.fetchone())

  def InsertValues(self, table_name, column_names, values):
    """Inserts values into a table.

    Args:
      table_name (str): table name.
      column_names (list[str]): column names.
      values (list[str]): values formatted as a string.

    Raises:
      RuntimeError: if the database is not opened or
          if the database is in read-only mode or
          if an unsupported value type is encountered.
    """
    if not self._connection:
      raise RuntimeError('Cannot insert values database not opened.')

    if self.read_only:
      raise RuntimeError('Cannot insert values database in read-only mode.')

    if not values:
      return

    sql_values = []
    for value in values:
      if isinstance(value, py2to3.STRING_TYPES):
        # In sqlite3 the double quote is escaped with a second double quote.
        value = '"{0:s}"'.format(re.sub('"', '""', value))
      elif isinstance(value, py2to3.INTEGER_TYPES):
        value = '{0:d}'.format(value)
      elif isinstance(value, float):
        value = '{0:f}'.format(value)
      elif value is None:
        value = 'NULL'
      else:
        raise RuntimeError('Unsupported value type: {0:s}.'.format(
            type(value)))
      sql_values.append(value)

    sql_query = 'INSERT INTO {0:s} ( {1:s} ) VALUES ( {2:s} )'.format(
        table_name, ', '.join(column_names), ', '.join(sql_values))

    self._cursor.execute(sql_query)

  def Open(self, filename, read_only=False):
    """Opens the database file.

    Args:
      filename (str): filename of the database.
      read_only (Optional[bool]): True if the database should be opened in
          read-only mode. Since sqlite3 does not support a real read-only
          mode we fake it by only permitting SELECT queries.<commit_msg>Changes to formatting strings for type()<commit_after># -*- coding: utf-8 -*-
"""Classes to read from and write to SQLite databases."""

from __future__ import unicode_literals

import re

import sqlite3

from esedbrc import py2to3


class Sqlite3DatabaseFile(object):
  """SQLite3 database file."""

  _HAS_TABLE_QUERY = (
      'SELECT name FROM sqlite_master '
      'WHERE type = "table" AND name = "{0:s}"')

  def __init__(self):
    """Initializes a database file."""
    super(Sqlite3DatabaseFile, self).__init__()
    self._connection = None
    self._cursor = None
    self.filename = None
    self.read_only = None

  def Close(self):
    """Closes the database file.

    Raises:
      RuntimeError: if the database is not opened.
    """
    if not self._connection:
      raise RuntimeError('Cannot close database not opened.')

    # We need to run commit or not all data is stored in the database.
    self._connection.commit()
    self._connection.close()

    self._connection = None
    self._cursor = None
    self.filename = None
    self.read_only = None

  def CreateTable(self, table_name, column_definitions):
    """Creates a table.

    Args:
      table_name (str): table name.
      column_definitions (list[str]): column definitions.

    Raises:
      RuntimeError: if the database is not opened or
          if the database is in read-only mode.
    """
    if not self._connection:
      raise RuntimeError('Cannot create table database not opened.')

    if self.read_only:
      raise RuntimeError('Cannot create table database in read-only mode.')

    sql_query = 'CREATE TABLE {0:s} ( {1:s} )'.format(
        table_name, ', '.join(column_definitions))

    self._cursor.execute(sql_query)

  def GetValues(self, table_names, column_names, condition):
    """Retrieves values from a table.

    Args:
      table_names (list[str]): table names.
      column_names (list[str]): column names.
      condition (str): condition.

    Yields:
      sqlite3.row: a row.

    Raises:
      RuntimeError: if the database is not opened.
    """
    if not self._connection:
      raise RuntimeError('Cannot retrieve values database not opened.')

    if condition:
      condition = ' WHERE {0:s}'.format(condition)

    sql_query = 'SELECT {1:s} FROM {0:s}{2:s}'.format(
        ', '.join(table_names), ', '.join(column_names), condition)

    self._cursor.execute(sql_query)

    for row in self._cursor:
      values = {}
      for column_index, column_name in enumerate(column_names):
        values[column_name] = row[column_index]
      yield values

  def HasTable(self, table_name):
    """Determines if a specific table exists.

    Args:
      table_name (str): table name.

    Returns:
      bool: True if the table exists, False otheriwse.

    Raises:
      RuntimeError: if the database is not opened.
    """
    if not self._connection:
      raise RuntimeError(
          'Cannot determine if table exists database not opened.')

    sql_query = self._HAS_TABLE_QUERY.format(table_name)

    self._cursor.execute(sql_query)

    return bool(self._cursor.fetchone())

  def InsertValues(self, table_name, column_names, values):
    """Inserts values into a table.

    Args:
      table_name (str): table name.
      column_names (list[str]): column names.
      values (list[str]): values formatted as a string.

    Raises:
      RuntimeError: if the database is not opened or
          if the database is in read-only mode or
          if an unsupported value type is encountered.
    """
    if not self._connection:
      raise RuntimeError('Cannot insert values database not opened.')

    if self.read_only:
      raise RuntimeError('Cannot insert values database in read-only mode.')

    if not values:
      return

    sql_values = []
    for value in values:
      if isinstance(value, py2to3.STRING_TYPES):
        # In sqlite3 the double quote is escaped with a second double quote.
        value = '"{0:s}"'.format(re.sub('"', '""', value))
      elif isinstance(value, py2to3.INTEGER_TYPES):
        value = '{0:d}'.format(value)
      elif isinstance(value, float):
        value = '{0:f}'.format(value)
      elif value is None:
        value = 'NULL'
      else:
        raise RuntimeError('Unsupported value type: {0!s}.'.format(
            type(value)))
      sql_values.append(value)

    sql_query = 'INSERT INTO {0:s} ( {1:s} ) VALUES ( {2:s} )'.format(
        table_name, ', '.join(column_names), ', '.join(sql_values))

    self._cursor.execute(sql_query)

  def Open(self, filename, read_only=False):
    """Opens the database file.

    Args:
      filename (str): filename of the database.
      read_only (Optional[bool]): True if the database should be opened in
          read-only mode. Since sqlite3 does not support a real read-only
          mode we fake it by only permitting SELECT queries.
{'fraction_non_alphanumeric': 0.10591259640102828, 'fraction_numerical': 0.0057583547557840615, 'mean_word_length': 2.79921875, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4358978', 'n_tokens_mistral': 2917, 'n_tokens_neox': 2807, 'n_words': 930}