Skip to content

Commit

Permalink
Support :generated_always_as column option on PostgreSQL 12+
Browse files Browse the repository at this point in the history
This option was already supported on recent versions of MariaDB
and MySQL.  PostgreSQL 12+ doesn't support virtual columns, so
currently the :generated_type option is not supported.
  • Loading branch information
jeremyevans committed Aug 2, 2019
1 parent 198c5cf commit dd29c6c
Show file tree
Hide file tree
Showing 4 changed files with 25 additions and 6 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
=== master

* Support :generated_always_as column option on PostgreSQL 12+ (jeremyevans)

=== 5.23.0 (2019-08-01)

* Work around a bug on jdbc-sqlite3 3.27.2.1 when parsing schema for tables with columns with default values (jeremyevans)
Expand Down
12 changes: 8 additions & 4 deletions lib/sequel/adapters/shared/postgres.rb
Original file line number Diff line number Diff line change
Expand Up @@ -836,10 +836,14 @@ def column_definition_collate_sql(sql, column)
# default value is given.
def column_definition_default_sql(sql, column)
super
if !column[:serial] && !['serial', 'bigserial'].include?(column[:type].to_s) && !column[:default] && (identity = column[:identity])
sql << " GENERATED "
sql << (identity == :always ? "ALWAYS" : "BY DEFAULT")
sql << " AS IDENTITY"
if !column[:serial] && !['serial', 'bigserial'].include?(column[:type].to_s) && !column[:default]
if (identity = column[:identity])
sql << " GENERATED "
sql << (identity == :always ? "ALWAYS" : "BY DEFAULT")
sql << " AS IDENTITY"
elsif (generated = column[:generated_always_as])
sql << " GENERATED ALWAYS AS (#{literal(generated)}) STORED"
end
end
end

Expand Down
9 changes: 7 additions & 2 deletions lib/sequel/database/schema_generator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,9 @@ def check(*args, &block)
# yet exist on referenced table (but will exist before the transaction commits).
# Basically it adds DEFERRABLE INITIALLY DEFERRED on key creation.
# If you use :immediate as the value, uses DEFERRABLE INITIALLY IMMEDIATE.
# :generated_always_as :: Specify a GENERATED ALWAYS AS column expression,
# if generated columns are supported (PostgreSQL 12+, MariaDB 5.2.0+,
# and MySQL 5.7.6+).
# :index :: Create an index on this column. If given a hash, use the hash as the
# options for the index.
# :key :: For foreign key columns, the column in the associated table
Expand All @@ -132,9 +135,11 @@ def check(*args, &block)
# creating a unique index on the column.
# :unique_constraint_name :: The name to give the unique key constraint
#
# PostgreSQL specific options:
#
# :identity :: Create an identity column.
#
# MySQL specific options:
# :generated_always_as :: Specify a GENERATED ALWAYS AS column expression,
# if generated columns are supported.
# :generated_type :: Set the type of column when using :generated_always_as,
# should be :virtual or :stored to force a type.
def column(name, type, opts = OPTS)
Expand Down
6 changes: 6 additions & 0 deletions spec/adapters/postgres_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,12 @@
@db.convert_serial_to_identity(:tmp_dolls, :column=>:id)
end if DB.server_version >= 100002 && DB.get{current_setting('is_superuser')} == 'on'

it "should support creating generated columns" do
@db.create_table(:tmp_dolls){Integer :a; Integer :b; Integer :c, :generated_always_as=>Sequel[:a] * 2 + :b + 1}
@db[:tmp_dolls].insert(:a=>100, :b=>10)
@db[:tmp_dolls].select_order_map([:a, :b, :c]).must_equal [[100, 10, 211]]
end if DB.server_version >= 120000

it "should support pg_loose_count extension" do
@db.extension :pg_loose_count
@db.create_table(:tmp_dolls){text :name}
Expand Down

0 comments on commit dd29c6c

Please sign in to comment.