Class: WOWSQL::WOWSQLSchema

Inherits:
Object
  • Object
show all
Defined in:
lib/wowsql/schema.rb

Overview

Schema management client for PostgreSQL.

Requires a SERVICE ROLE key (wowsql_service_…), not an anonymous key.

Examples:

schema = WOWSQL::WOWSQLSchema.new(
  "myproject",
  "wowsql_service_..."
)
schema.create_table("users", [
  { "name" => "id", "type" => "UUID", "auto_increment" => true },
  { "name" => "email", "type" => "VARCHAR(255)", "unique" => true, "nullable" => false },
  { "name" => "name", "type" => "VARCHAR(255)" },
  { "name" => "metadata", "type" => "JSONB", "default" => "'{}'" },
  { "name" => "created_at", "type" => "TIMESTAMPTZ", "default" => "CURRENT_TIMESTAMP" },
], primary_key: "id", indexes: ["email"])

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(project_url, service_key, base_domain: 'wowsqlconnect.com', secure: true, timeout: 30, verify_ssl: true) ⇒ WOWSQLSchema

Returns a new instance of WOWSQLSchema.

Parameters:

  • project_url (String)

    Project subdomain or full URL

  • service_key (String)

    Service role key (wowsql_service_…)

  • base_domain (String) (defaults to: 'wowsqlconnect.com')

    Base domain (default: “wowsqlconnect.com”)

  • secure (Boolean) (defaults to: true)

    Use HTTPS (default: true)

  • timeout (Integer) (defaults to: 30)

    Request timeout in seconds (default: 30)

  • verify_ssl (Boolean) (defaults to: true)

    Verify SSL certificates (default: true)



31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/wowsql/schema.rb', line 31

def initialize(project_url, service_key, base_domain: 'wowsqlconnect.com', secure: true,
               timeout: 30, verify_ssl: true)
  if project_url.start_with?('http://') || project_url.start_with?('https://')
    base = project_url.chomp('/')
    base = base.split('/api').first if base.include?('/api')
    @base_url = base
  else
    protocol = secure ? 'https' : 'http'
    if project_url.include?(".#{base_domain}") || project_url.end_with?(base_domain)
      @base_url = "#{protocol}://#{project_url}"
    else
      @base_url = "#{protocol}://#{project_url}.#{base_domain}"
    end
  end

  @timeout = timeout

  ssl_options = verify_ssl ? {} : { verify: false }

  @conn = Faraday.new(url: @base_url, ssl: ssl_options) do |f|
    f.request :json
    f.response :json
    f.adapter Faraday.default_adapter
    f.options.timeout = timeout
  end

  @conn.headers['Authorization'] = "Bearer #{service_key}"
  @conn.headers['Content-Type'] = 'application/json'
end

Instance Attribute Details

#base_urlObject (readonly)

Returns the value of attribute base_url.



23
24
25
# File 'lib/wowsql/schema.rb', line 23

def base_url
  @base_url
end

Instance Method Details

#add_column(table_name, column_name, column_type, nullable: true, default: nil) ⇒ Hash

Add a column to an existing table.

Parameters:

  • table_name (String)

    Table name

  • column_name (String)

    Column name

  • column_type (String)

    Column type

  • nullable (Boolean) (defaults to: true)

    Whether column is nullable

  • default (String, nil) (defaults to: nil)

    Default value

Returns:

  • (Hash)


151
152
153
154
155
156
157
158
159
# File 'lib/wowsql/schema.rb', line 151

def add_column(table_name, column_name, column_type, nullable: true, default: nil)
  alter_table(
    table_name, 'add_column',
    column_name: column_name,
    column_type: column_type,
    nullable: nullable,
    default: default
  )
end

#alter_table(table_name, operation, column_name: nil, column_type: nil, new_column_name: nil, nullable: true, default: nil) ⇒ Hash

Alter an existing table.

Operations: add_column, drop_column, modify_column, rename_column

Parameters:

  • table_name (String)

    Table name

  • operation (String)

    Operation type

  • column_name (String, nil) (defaults to: nil)

    Column name

  • column_type (String, nil) (defaults to: nil)

    Column type

  • new_column_name (String, nil) (defaults to: nil)

    New column name (for rename)

  • nullable (Boolean) (defaults to: true)

    Whether column is nullable

  • default (String, nil) (defaults to: nil)

    Default value

Returns:

  • (Hash)


108
109
110
111
112
113
114
115
116
117
118
119
# File 'lib/wowsql/schema.rb', line 108

def alter_table(table_name, operation, column_name: nil, column_type: nil,
                new_column_name: nil, nullable: true, default: nil)
  request('PATCH', "/api/v2/schema/tables/#{table_name}", nil, {
    table_name: table_name,
    operation: operation,
    column_name: column_name,
    column_type: column_type,
    new_column_name: new_column_name,
    nullable: nullable,
    default: default
  })
end

#closeObject

Close the HTTP connection.



235
236
237
# File 'lib/wowsql/schema.rb', line 235

def close
  @conn.close if @conn.respond_to?(:close)
end

#create_index(table_name, columns, unique: false, name: nil, using: nil) ⇒ Hash

Create an index.

Parameters:

  • table_name (String)

    Table to index

  • columns (String, Array<String>)

    Column(s)

  • unique (Boolean) (defaults to: false)

    Create a UNIQUE index

  • name (String, nil) (defaults to: nil)

    Custom index name

  • using (String, nil) (defaults to: nil)

    Index method (btree, hash, gin, gist)

Returns:

  • (Hash)


208
209
210
211
212
213
214
215
216
# File 'lib/wowsql/schema.rb', line 208

def create_index(table_name, columns, unique: false, name: nil, using: nil)
  cols = columns.is_a?(Array) ? columns : [columns]
  idx_name = name || "idx_#{table_name}_#{cols.join('_')}"
  unique_kw = unique ? 'UNIQUE ' : ''
  using_kw = using ? " USING #{using}" : ''
  col_list = cols.map { |c| "\"#{c}\"" }.join(', ')
  sql = "CREATE #{unique_kw}INDEX IF NOT EXISTS \"#{idx_name}\" ON \"#{table_name}\"#{using_kw} (#{col_list})"
  execute_sql(sql)
end

#create_table(table_name, columns, primary_key:, indexes: nil) ⇒ Hash

Create a new table.

Parameters:

  • table_name (String)

    Name of the table

  • columns (Array<Hash>)

    Column definitions (name, type, auto_increment, unique, nullable, default)

  • primary_key (String)

    Primary key column name (must be the UUID column)

  • indexes (Array<String>, nil) (defaults to: nil)

    Columns to create indexes on

Returns:

  • (Hash)

Raises:

  • (ArgumentError)


70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/wowsql/schema.rb', line 70

def create_table(table_name, columns, primary_key:, indexes: nil)
  raise ArgumentError, 'primary_key is required; primary key must be UUID type.' if primary_key.nil? || primary_key.to_s.strip.empty?

  assert_uuid_primary_key!(primary_key, columns)

  request('POST', '/api/v2/schema/tables', nil, {
    table_name: table_name,
    columns: columns,
    primary_key: primary_key,
    indexes: indexes
  })
end

#drop_column(table_name, column_name) ⇒ Hash

Drop a column from a table.

Parameters:

  • table_name (String)

    Table name

  • column_name (String)

    Column name

Returns:

  • (Hash)


166
167
168
# File 'lib/wowsql/schema.rb', line 166

def drop_column(table_name, column_name)
  alter_table(table_name, 'drop_column', column_name: column_name)
end

#drop_table(table_name, cascade: false) ⇒ Hash

Drop a table. WARNING: This cannot be undone!

Parameters:

  • table_name (String)

    Table to drop

  • cascade (Boolean) (defaults to: false)

    Also drop dependent objects

Returns:

  • (Hash)


126
127
128
# File 'lib/wowsql/schema.rb', line 126

def drop_table(table_name, cascade: false)
  request('DELETE', "/api/v2/schema/tables/#{table_name}", { 'cascade' => cascade }, nil)
end

#execute_sql(sql) ⇒ Hash

Execute raw DDL SQL.

Only schema statements are allowed: CREATE TABLE, ALTER TABLE, DROP TABLE, CREATE INDEX, DROP INDEX, etc.

Parameters:

  • sql (String)

    DDL SQL statement

Returns:

  • (Hash)


137
138
139
# File 'lib/wowsql/schema.rb', line 137

def execute_sql(sql)
  request('POST', '/api/v2/schema/execute', nil, { sql: sql })
end

#get_table_schema(table_name) ⇒ Hash

Get column-level schema information for a table.

Parameters:

  • table_name (String)

    Table name

Returns:

  • (Hash)


230
231
232
# File 'lib/wowsql/schema.rb', line 230

def get_table_schema(table_name)
  request('GET', "/api/v2/tables/#{table_name}/schema", nil, nil)
end

#list_tablesArray<String>

List all tables via the v2 REST API.

Returns:

  • (Array<String>)


221
222
223
224
# File 'lib/wowsql/schema.rb', line 221

def list_tables
  resp = request('GET', '/api/v2/tables', nil, nil)
  resp['tables'] || []
end

#modify_column(table_name, column_name, column_type: nil, nullable: nil, default: nil) ⇒ Hash

Change column type, nullability, or default value.

Parameters:

  • table_name (String)

    Table name

  • column_name (String)

    Column name

  • column_type (String, nil) (defaults to: nil)

    New column type

  • nullable (Boolean, nil) (defaults to: nil)

    New nullability

  • default (String, nil) (defaults to: nil)

    New default value

Returns:

  • (Hash)


192
193
194
195
196
197
198
# File 'lib/wowsql/schema.rb', line 192

def modify_column(table_name, column_name, column_type: nil, nullable: nil, default: nil)
  kwargs = { column_name: column_name }
  kwargs[:column_type] = column_type unless column_type.nil?
  kwargs[:nullable] = nullable unless nullable.nil?
  kwargs[:default] = default unless default.nil?
  alter_table(table_name, 'modify_column', **kwargs)
end

#rename_column(table_name, old_name, new_name) ⇒ Hash

Rename a column.

Parameters:

  • table_name (String)

    Table name

  • old_name (String)

    Current column name

  • new_name (String)

    New column name

Returns:

  • (Hash)


176
177
178
179
180
181
182
# File 'lib/wowsql/schema.rb', line 176

def rename_column(table_name, old_name, new_name)
  alter_table(
    table_name, 'rename_column',
    column_name: old_name,
    new_column_name: new_name
  )
end