Class: Mammoth::SQLiteStore

Inherits:
Object
  • Object
show all
Defined in:
lib/mammoth/sqlite_store.rb

Overview

Owns Mammoth’s local SQLite operational database.

The SQLite database is Mammoth’s operational memory. It stores only boring, inspectable state required for reliability: schema versions, checkpoints, and dead letters.

Constant Summary collapse

DEFAULT_DB_PATH =
File.expand_path("../../.sqlite3/mammoth.db", __dir__)
MIGRATION_DIR =
File.expand_path("sql", __dir__)
BOOTSTRAP_FILE =
"__bootstrap__.sql"
BOOTSTRAP_VERSION =
"__bootstrap__"
MIGRATIONS_TABLE =
"schema_migrations"

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(path = DEFAULT_DB_PATH) ⇒ SQLiteStore

Returns a new instance of SQLiteStore.

Parameters:

  • path (String) (defaults to: DEFAULT_DB_PATH)

    SQLite database path



31
32
33
34
# File 'lib/mammoth/sqlite_store.rb', line 31

def initialize(path = DEFAULT_DB_PATH)
  @path = path
  @database = nil
end

Instance Attribute Details

#pathObject (readonly)

Returns the value of attribute path.



20
21
22
# File 'lib/mammoth/sqlite_store.rb', line 20

def path
  @path
end

Class Method Details

.connect(path = DEFAULT_DB_PATH) ⇒ Mammoth::SQLiteStore

Open and return a connected store.

Parameters:

  • path (String) (defaults to: DEFAULT_DB_PATH)

    SQLite database path

Returns:



26
27
28
# File 'lib/mammoth/sqlite_store.rb', line 26

def self.connect(path = DEFAULT_DB_PATH)
  new(path).connect
end

Instance Method Details

#bootstrap!Mammoth::SQLiteStore

Apply the initial schema if it has not yet been applied.

Returns:



59
60
61
62
63
64
# File 'lib/mammoth/sqlite_store.rb', line 59

def bootstrap!
  return self if bootstrapped?

  apply_migration!(BOOTSTRAP_FILE, BOOTSTRAP_VERSION)
  self
end

#bootstrapped?Boolean

Returns true when the initial schema is already applied.

Returns:

  • (Boolean)

    true when the initial schema is already applied



80
81
82
# File 'lib/mammoth/sqlite_store.rb', line 80

def bootstrapped?
  table_exists?(MIGRATIONS_TABLE) && version_exists?(BOOTSTRAP_VERSION)
end

#connectMammoth::SQLiteStore

Open the SQLite database and configure conservative operational pragmas.

Returns:



39
40
41
42
43
44
45
46
47
48
49
# File 'lib/mammoth/sqlite_store.rb', line 39

def connect
  FileUtils.mkdir_p(File.dirname(path))
  @database = SQLite3::Database.new(path)
  @database.results_as_hash = true
  execute_pragma("journal_mode", "WAL")
  execute_pragma("foreign_keys", "ON")
  execute_pragma("busy_timeout", 5000)
  self
rescue SQLite3::Exception => e
  raise StoreError, "failed to open SQLite database #{path}: #{e.message}"
end

#databaseSQLite3::Database

Returns connected database.

Returns:

  • (SQLite3::Database)

    connected database



52
53
54
# File 'lib/mammoth/sqlite_store.rb', line 52

def database
  @database || connect.database
end

#migrate!(sql_file) ⇒ Mammoth::SQLiteStore

Apply a migration file unless its version already exists.

Parameters:

  • sql_file (String)

    SQL file name under lib/mammoth/sql

Returns:



70
71
72
73
74
75
76
77
# File 'lib/mammoth/sqlite_store.rb', line 70

def migrate!(sql_file)
  bootstrap!
  version_name = File.basename(sql_file, ".sql")
  return self if version_exists?(version_name)

  apply_migration!(sql_file, version_name)
  self
end

#table_exists?(table_name) ⇒ Boolean

Returns true when a table exists.

Parameters:

  • table_name (String)

    table name

Returns:

  • (Boolean)

    true when a table exists



86
87
88
89
90
91
# File 'lib/mammoth/sqlite_store.rb', line 86

def table_exists?(table_name)
  !database.execute(
    "SELECT 1 FROM sqlite_schema WHERE type = ? AND name = ? LIMIT 1",
    ["table", table_name]
  ).empty?
end

#tablesArray<String>

Return table names in the operational database.

Returns:

  • (Array<String>)

    table names



107
108
109
110
111
# File 'lib/mammoth/sqlite_store.rb', line 107

def tables
  database.execute(
    "SELECT name FROM sqlite_schema WHERE type = 'table' ORDER BY name"
  ).map { |row| row.fetch("name") }
end

#version_exists?(version_name) ⇒ Boolean

Returns true when a migration version exists.

Parameters:

  • version_name (String)

    migration version

Returns:

  • (Boolean)

    true when a migration version exists



95
96
97
98
99
100
101
102
# File 'lib/mammoth/sqlite_store.rb', line 95

def version_exists?(version_name)
  return false unless table_exists?(MIGRATIONS_TABLE)

  !database.execute(
    "SELECT 1 FROM schema_migrations WHERE version = ? LIMIT 1",
    [version_name]
  ).empty?
end