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 =

Default SQLite database path used by local Mammoth runs.

File.expand_path("../../.sqlite3/mammoth.db", __dir__.to_s)
MIGRATION_DIR =

Directory containing bundled SQLite schema migration files.

File.expand_path("sql", __dir__.to_s)
BOOTSTRAP_FILE =

Initial schema migration file applied to new SQLite stores.

"__bootstrap__.sql"
BOOTSTRAP_VERSION =

Synthetic schema version recorded after the bootstrap migration succeeds.

"__bootstrap__"
MIGRATIONS_TABLE =

Table that records applied SQLite schema migrations.

"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



36
37
38
39
# File 'lib/mammoth/sqlite_store.rb', line 36

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

Instance Attribute Details

#pathObject (readonly)

Returns the value of attribute path.



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

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:



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

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:



64
65
66
67
68
69
# File 'lib/mammoth/sqlite_store.rb', line 64

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



85
86
87
# File 'lib/mammoth/sqlite_store.rb', line 85

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

#connectMammoth::SQLiteStore

Open the SQLite database and configure conservative operational pragmas.

Returns:



44
45
46
47
48
49
50
51
52
53
54
# File 'lib/mammoth/sqlite_store.rb', line 44

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



57
58
59
# File 'lib/mammoth/sqlite_store.rb', line 57

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:



75
76
77
78
79
80
81
82
# File 'lib/mammoth/sqlite_store.rb', line 75

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



91
92
93
94
95
96
# File 'lib/mammoth/sqlite_store.rb', line 91

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



112
113
114
115
116
# File 'lib/mammoth/sqlite_store.rb', line 112

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



100
101
102
103
104
105
106
107
# File 'lib/mammoth/sqlite_store.rb', line 100

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