Class: AceMQ::AMQP::Patterns::SQL::SQLite3Connection

Inherits:
Object
  • Object
show all
Defined in:
lib/acemq/amqp/patterns/sql.rb

Overview

A connection over the sqlite3 gem.

The one the specs run against, and the one to reach for in a test or a single-process service. A SQLite database is a file one process writes at a time, so it is not the shared store the outbox and the idempotency table exist to be — but it is a real database with real transactions, which is what those two need to be tested honestly.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(database) ⇒ SQLite3Connection

Returns a new instance of SQLite3Connection.

Parameters:

  • database (SQLite3::Database)


224
225
226
# File 'lib/acemq/amqp/patterns/sql.rb', line 224

def initialize(database)
  @database = database
end

Instance Attribute Details

#database ⇒ Object (readonly)

The wrapped SQLite3::Database.



229
230
231
# File 'lib/acemq/amqp/patterns/sql.rb', line 229

def database
  @database
end

Instance Method Details

#constraint_violation?(error) ⇒ Boolean

A duplicate key only. SQLite raises the same ConstraintException for NOT NULL, CHECK and a trigger's RAISE(ABORT), and reading those as "somebody else won" turns a write that never landed into a message acked unhandled. The extended code is not exposed by the gem, so the message is what tells them apart; a primary key and a unique index both read this way.

Returns:

  • (Boolean)


253
254
255
256
257
# File 'lib/acemq/amqp/patterns/sql.rb', line 253

def constraint_violation?(error)
  defined?(SQLite3::ConstraintException) &&
    error.is_a?(SQLite3::ConstraintException) &&
    error.message.start_with?("UNIQUE constraint failed")
end

#placeholder(_index) ⇒ Object

SQLite numbers its parameters for you.



245
# File 'lib/acemq/amqp/patterns/sql.rb', line 245

def placeholder(_index) = "?"

#run(sql, params = []) ⇒ Object



231
232
233
234
235
236
237
238
239
240
241
242
# File 'lib/acemq/amqp/patterns/sql.rb', line 231

def run(sql, params = [])
  rows = @database.execute(sql, params)
  # changes reports the last statement's row count, which is what a
  # conditional update needs and what a select has no use for.
  #
  # The shape of a row is the database's to choose, not this wrapper's:
  # +results_as_hash = true+ is a setting on the SQLite3::Database
  # handed over, ActiveRecord sets it on the connection it opens, and
  # nothing here may turn a caller's setting off behind their back.
  # Normalised on the way out instead.
  Result.new(SQL.positional(rows), @database.changes)
end

#transaction ⇒ Object

Runs a block inside a transaction, rolling back if it raises.



260
# File 'lib/acemq/amqp/patterns/sql.rb', line 260

def transaction(&) = @database.transaction(&)