Class: AutoREST::DBAdapter Abstract

Inherits:
Object
  • Object
show all
Defined in:
lib/autorest/db/adapter.rb

Overview

This class is abstract.

Database Adapter class for AutoREST.

This abstract class serves as a base class for specific database adapters such as SQLite, MySQL, PostgreSQL, and Oracle. It defines the common interface that all adapters must implement. These include methods for preparing the database (e.g., fetching table and column metadata), executing SQL queries, and managing database connections.

Direct Known Subclasses

MySQLDB, OracleDB, PostgresDB, SQLiteDB

Instance Method Summary collapse

Constructor Details

#initialize(db_kind, db_name, db_conn) ⇒ DBAdapter

Initializes a new DBAdapter instance.

Parameters:

  • db_kind (Symbol)

    The type of database (e.g., :sqlite, :mysql, :pg, :orcl)

  • db_name (String)

    The database name or SID (for Oracle)

  • db_conn (Object)

    The database connection object



17
18
19
20
21
22
# File 'lib/autorest/db/adapter.rb', line 17

def initialize(db_kind, db_name, db_conn)
    @db_kind = db_kind
    @dbname = db_name
    @db_conn = db_conn
    @tables = nil
end

Instance Method Details

#closevoid

This method returns an undefined value.

Closes the database connection.



159
160
161
# File 'lib/autorest/db/adapter.rb', line 159

def close
    @db_conn.close
end

#columns(table_name) ⇒ Array<String>

Returns the list of column names for a given table.

Parameters:

  • table_name (String)

    The name of the table

Returns:

  • (Array<String>)

    A list of column names



71
72
73
74
# File 'lib/autorest/db/adapter.rb', line 71

def columns(table_name)
    prepare if @tables.nil?
    @tables[table_name].keys
end

#del_row(table_name, value) ⇒ Hash, String

Deletes a row from a table.

Parameters:

  • table_name (String)

    The name of the table

  • value (String, Integer)

    The value of the primary key of the row to delete

Returns:

  • (Hash, String)

    The deleted row as a hash, or an error message



146
147
148
149
150
151
152
153
154
# File 'lib/autorest/db/adapter.rb', line 146

def del_row(table_name, value)
    prepare if @tables.nil?
    return "404: Table #{table_name} does not exist" unless @tables.include?(table_name)
    return "403: Insufficient rights to delete Table #{table_name}" unless @access_tables.include?(table_name)
    result = row(table_name, value)
    return result if result.is_a?(String)
    exec_sql("delete from #{escape(table_name)} where #{pkey(table_name)} = #{value.inspect}")
    result
end

#escape(input) ⇒ String

This method is abstract.

Escapes input data to safely use in SQL queries.

Parameters:

  • input (String)

    The raw input data

Returns:

  • (String)

    The escaped input data

Raises:

  • (NotImplementedError)


47
48
49
# File 'lib/autorest/db/adapter.rb', line 47

def escape(input)
    raise NotImplementedError, "#{self.class} has not implemented method '#{__method__}'"
end

#exec_sql(sql) ⇒ Array<Hash>

This method is abstract.

Executes a raw SQL query.

Parameters:

  • sql (String)

    The SQL query to execute

Returns:

  • (Array<Hash>)

    The result of the query as an array of hashes

Raises:

  • (NotImplementedError)


38
39
40
# File 'lib/autorest/db/adapter.rb', line 38

def exec_sql(sql)
    raise NotImplementedError, "#{self.class} has not implemented method '#{__method__}'"
end

#insert(table_name, data) ⇒ Hash, String

Inserts a new row into a table.

Parameters:

  • table_name (String)

    The name of the table

  • data (Hash)

    The data to insert, where keys are column names and values are column values

Returns:

  • (Hash, String)

    The inserted row as a hash, or an error message



111
112
113
114
115
116
117
118
119
120
# File 'lib/autorest/db/adapter.rb', line 111

def insert(table_name, data)
    prepare if @tables.nil?
    return "404: Table #{table_name} does not exist" unless @tables.include?(table_name)
    return "403: Insufficient rights to access Table #{table_name}" unless @access_tables.include?(table_name)
    return "409: Row already exists" if has_row(table_name, data[pkey(table_name)])
    cols = data.keys.join(", ")
    values = data.values.map(&:inspect).join(", ")
    exec_sql("insert into #{escape(table_name)} (#{cols}) values (#{values})")
    row(table_name, data[pkey(table_name)])
end

#prepareObject

This method is abstract.

Prepares the database by fetching metadata, such as tables and columns. This method must be implemented by subclasses.

Raises:

  • (NotImplementedError)

    If the method is not implemented by a subclass.



29
30
31
# File 'lib/autorest/db/adapter.rb', line 29

def prepare
    raise NotImplementedError, "#{self.class} has not implemented method '#{__method__}'"
end

#row(table_name, value, cols = "*") ⇒ Hash, String

Returns a specific row in a table identified by its primary key value.

Parameters:

  • table_name (String)

    The name of the table

  • value (String, Integer)

    The value of the primary key

  • cols (String, Array<String>) (defaults to: "*")

    The columns to retrieve (defaults to “*”)

Returns:

  • (Hash, String)

    The row as a hash, or an error message



96
97
98
99
100
101
102
103
104
# File 'lib/autorest/db/adapter.rb', line 96

def row(table_name, value, cols = "*")
    prepare if @tables.nil?
    return "404: Table #{table_name} does not exist" unless @tables.include?(table_name)
    return "403: Insufficient rights to access Table #{table_name}" unless @access_tables.include?(table_name)
    return "502: Table does not have primary key" if pkey(table_name).nil?
    result = exec_sql("select #{escape(cols)} from #{table_name} where #{pkey(table_name)} = #{value.inspect}")
    return "404: Row not found" if result.empty?
    result
end

#rows(table_name, cols = "*") ⇒ Array<Hash>, String

Returns the rows of a table for the specified columns.

Parameters:

  • table_name (String)

    The name of the table

  • cols (String, Array<String>) (defaults to: "*")

    The columns to retrieve (defaults to “*”)

Returns:

  • (Array<Hash>, String)

    The rows of the table as an array of hashes, or an error message



81
82
83
84
85
86
87
88
# File 'lib/autorest/db/adapter.rb', line 81

def rows(table_name, cols = "*")
    prepare if @tables.nil?
    return "404: Table #{table_name} does not exist" unless @tables.include?(table_name)
    return "403: Insufficient rights to access Table #{table_name}" unless @access_tables.include?(table_name)
    result = exec_sql("select #{escape(cols)} from #{escape(table_name)}")
    return "404: Table #{table_name} is empty" if result.empty?
    result
end

#set_access_tables(access_tab) ⇒ void

This method returns an undefined value.

Sets the access tables for the database. If no tables are specified, all tables are accessible.

Parameters:

  • access_tab (Array<String>)

    A list of tables the user has access to



55
56
57
# File 'lib/autorest/db/adapter.rb', line 55

def set_access_tables(access_tab)
    @access_tables = access_tab.empty? ? @tables.keys : access_tab
end

#tablesArray<String>

Returns the list of table names in the database.

Returns:

  • (Array<String>)

    A list of table names



62
63
64
65
# File 'lib/autorest/db/adapter.rb', line 62

def tables
    prepare if @tables.nil?
    @tables.keys
end

#update(table_name, pk, value, patch = false) ⇒ Hash, String

Updates an existing row in a table.

Parameters:

  • table_name (String)

    The name of the table

  • pk (String, Integer)

    The primary key of the row to update

  • value (Hash)

    The new values for the row, where keys are column names and values are column values

  • patch (Boolean) (defaults to: false)

    If true, allows the partial changes, for PATCH requests (defaults to false)

Returns:

  • (Hash, String)

    The updated row as a hash, or an error message



129
130
131
132
133
134
135
136
137
138
139
# File 'lib/autorest/db/adapter.rb', line 129

def update(table_name, pk, value, patch = false)
    prepare if @tables.nil?
    return "404: Table #{table_name} does not exist" unless @tables.include?(table_name)
    return "403: Insufficient rights to update Table #{table_name}" unless @access_tables.include?(table_name)
    return "404: Row not found" unless has_row(table_name, pk)
    return "422: Primary key mismatch" if (pk != value[pkey(table_name)].to_s && !patch)
    return "422: Invalid data" if (value.keys & columns(table_name) != value.keys)
    kvpairs = value.map { |k, v| "#{k} = #{v.inspect}" }.join(", ")
    exec_sql("update #{escape(table_name)} set #{kvpairs} where #{pkey(table_name)} = #{pk.inspect}")
    row(table_name, pk)
end