Class: Webhookdb::DBAdapter

Inherits:
Object
  • Object
show all
Defined in:
lib/webhookdb/db_adapter.rb

Direct Known Subclasses

PG, Snowflake

Defined Under Namespace

Modules: ColumnTypes, DefaultSql Classes: Column, Connection, Index, InvalidIdentifier, PG, Partition, Partitioning, Schema, SequelConnection, Snowflake, Table, TableDescriptor, UnsupportedAdapter

Constant Summary collapse

VALID_IDENTIFIER =
/^[a-zA-Z][a-zA-Z\d_ ]*$/
INVALID_IDENTIFIER_PROMPT =
"Identifiers must start with a letter and contain only letters, numbers, spaces, and underscores.\n" \
"See https://docs.webhookdb.com/concepts/valid-identifiers/ for rules\n" \
"about identifiers like schema, table, and column names."
INVALID_IDENTIFIER_MESSAGE =
INVALID_IDENTIFIER_PROMPT.tr("\n", " ")

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#nameSymbol

Returns:

  • (Symbol)


# File 'lib/webhookdb/db_adapter.rb', line 78

#tableTable

Returns:



# File 'lib/webhookdb/db_adapter.rb', line 78

#targetsArray<Column>

Returns:



# File 'lib/webhookdb/db_adapter.rb', line 78

#uniqueBoolean

Returns:

  • (Boolean)


# File 'lib/webhookdb/db_adapter.rb', line 78

Class Method Details

.adapter(url) ⇒ Webhookdb::DBAdapter

Parameters:

  • url (String)

Returns:



217
218
219
220
221
222
223
224
225
226
# File 'lib/webhookdb/db_adapter.rb', line 217

def self.adapter(url)
  case url
    when /^postgres/
      return Webhookdb::DBAdapter::PG.new
    when /^snowflake/
      return Webhookdb::DBAdapter::Snowflake.new
    else
      raise UnsupportedAdapter, "no adapter available for #{url}"
  end
end

.supported_adapters_messageObject



228
229
230
# File 'lib/webhookdb/db_adapter.rb', line 228

def self.supported_adapters_message
  return "Postgres (postgres://), SnowflakeDB (snowflake://)"
end

.valid_identifier?(s) ⇒ Boolean

Returns:

  • (Boolean)


232
# File 'lib/webhookdb/db_adapter.rb', line 232

def self.valid_identifier?(s) = VALID_IDENTIFIER.match?(s)

.validate_identifier!(s, type:) ⇒ Object

Raise if the identifier s is invalid according to VALID_IDENTIFIER. type is used in the error message, like ‘Sorry, this is not a valid table name.’ If the user tries SQL injection, let them know we noticed!

Raises:



237
238
239
240
241
242
# File 'lib/webhookdb/db_adapter.rb', line 237

def self.validate_identifier!(s, type:)
  return if self.valid_identifier?(s)
  msg = "Sorry, this is not a valid #{type} name. #{INVALID_IDENTIFIER_MESSAGE}"
  msg += " And we see you what you did there ;)" if s.include?(";") && s.downcase.include?("drop")
  raise InvalidIdentifier, msg
end

Instance Method Details

#add_column_sql(table, column, if_not_exists: false) ⇒ String

Parameters:

  • table (Table)
  • column (Column)
  • if_not_exists (Boolean) (defaults to: false)

Returns:

  • (String)

Raises:

  • (NotImplementedError)


193
194
195
# File 'lib/webhookdb/db_adapter.rb', line 193

def add_column_sql(table, column, if_not_exists: false)
  raise NotImplementedError
end

#connection(url) ⇒ Connection

Return a new Connection for the adapter. By default, return a SequelConnection, but adapters not using Sequel will need their own type.

Returns:



143
144
145
# File 'lib/webhookdb/db_adapter.rb', line 143

def connection(url)
  return SequelConnection.new(url)
end

#create_column_sql(column) ⇒ Object

Parameters:

  • column (Column)

    The column to create SQL for.

Raises:

  • (NotImplementedError)


187
# File 'lib/webhookdb/db_adapter.rb', line 187

def create_column_sql(column) = raise NotImplementedError

#create_index_sql(index, concurrently:) ⇒ String

Parameters:

Returns:

  • (String)

Raises:

  • (NotImplementedError)


172
173
174
# File 'lib/webhookdb/db_adapter.rb', line 172

def create_index_sql(index, concurrently:)
  raise NotImplementedError
end

#create_index_sqls(index, concurrently:, partitions: []) ⇒ Array<String>

Create indices, including for partitions. By default, just call create_index_sql and return it in a single-item array. Override if creating indices while using partitions requires extra logic.

Parameters:

Returns:

  • (Array<String>)


181
182
183
184
# File 'lib/webhookdb/db_adapter.rb', line 181

def create_index_sqls(index, concurrently:, partitions: [])
  _ = partitions
  return [self.create_index_sql(index, concurrently:)]
end

#create_schema_sql(schema, if_not_exists: false) ⇒ String

Parameters:

  • schema (Schema)
  • if_not_exists (Boolean) (defaults to: false)

Returns:

  • (String)

Raises:

  • (NotImplementedError)


150
151
152
# File 'lib/webhookdb/db_adapter.rb', line 150

def create_schema_sql(schema, if_not_exists: false)
  raise NotImplementedError
end

#create_table_sql(table, columns, schema: nil, if_not_exists: false, partition: nil) ⇒ String

Return the CREATE TABLE sql to create table with columns.

Parameters:

  • table (Table)
  • columns (Array<Column>)
  • schema (Schema) (defaults to: nil)
  • if_not_exists (TrueClass, FalseClass) (defaults to: false)

    If true, use CREATE TABLE IF NOT EXISTS.

  • partition (Webhookdb::DBAdapter::Partitioning, nil) (defaults to: nil)

    If provided, adds a “PARTITION BY HASH (partition_column_name)” to the returned SQL.

Returns:

  • (String)

Raises:

  • (NotImplementedError)


162
163
164
# File 'lib/webhookdb/db_adapter.rb', line 162

def create_table_sql(table, columns, schema: nil, if_not_exists: false, partition: nil)
  raise NotImplementedError
end

#escape_identifier(s) ⇒ Object

We write our own escaper because we want to only escape what’s needed; otherwise we want to avoid quoting identifiers.

Raises:

  • (NotImplementedError)


168
# File 'lib/webhookdb/db_adapter.rb', line 168

def escape_identifier(s) = raise NotImplementedError

#merge_from_csv(connection, file, table, pk_col, copy_columns) ⇒ Object

Given a table and a (temporary) file with CSV data, import it into the table. Usually this is a COPY INTO command. For PG it would read from stdin, for Snowflake it would have to stage the file.

Parameters:

  • connection (Connection)
  • file (File)
  • table (Table)
  • pk_col (Column)

    Use this to identifier the same row between source and destination.

  • copy_columns (Array<Column>)

    All columns to copy. NOTE: This includes the pk column, since it should be copied, as we depend on it persisting.

Raises:

  • (NotImplementedError)


207
208
209
# File 'lib/webhookdb/db_adapter.rb', line 207

def merge_from_csv(connection, file, table, pk_col, copy_columns)
  raise NotImplementedError
end

#verify_connection(url, timeout: 2, statement: "SELECT 1") ⇒ Object



211
212
213
# File 'lib/webhookdb/db_adapter.rb', line 211

def verify_connection(url, timeout: 2, statement: "SELECT 1")
  return self._verify_connection(url, timeout:, statement:)
end