pg_types 0.2.1 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e20908d841705a0d9aff62529d44d0b12d0490d51b254c49424601ddd01aa6ce
4
- data.tar.gz: 0aef0b9dd97da00bd122395c039c3e82a6ad25606abaf76fe903c13dade199d5
3
+ metadata.gz: 1cd243d89a6bc0e672b5cd07d3aa1d2fe3d4227351cb0ee64720cf0126ed9538
4
+ data.tar.gz: b19af58bb2ba7b308dc7597d487d6914e5cdb044d762da86191103ae4a4512e0
5
5
  SHA512:
6
- metadata.gz: b19210b13c1c77c22daf9a321be40e41ebbde543958d4c0cef1f8cebc1c109712744c26dae3b03de383a9945c2ffd5da7cdf4efcecec0573a6ede338d29aa2d0
7
- data.tar.gz: a95652c5c2c07a3fb70314ad9dddd0d62f08716382fd403937daac15b71c242f8eee06cedcd481d66e7d74935272eb33a5dbebfc752b064eb5350686b8a9387e
6
+ metadata.gz: 9d14da9a0eafad1dded2f282521cb814b36581de7e2f0d3ae620bffddb3cd8c738fc8441d176ab745fb32965b92a28c55dfa97a4a4409698fcca0a2d9dbfed15
7
+ data.tar.gz: 06771fa123bd0bc8999ebe2e986f967c0361ff22f8f066eb068f6e353d68a3f6d7c2bb36acea28d7604188755c5ad23c8ae1d447aa5cbe66ee2d14bc1fccc5b8
@@ -2,11 +2,9 @@
2
2
 
3
3
  module PgTypes
4
4
  class Railtie < Rails::Railtie
5
- initializer "postgres_aggregates.load" do
5
+ initializer "pg_types.load", after: "pg_aggregates.load" do
6
6
  ActiveSupport.on_load(:active_record) do
7
- ActiveRecord::ConnectionAdapters::AbstractAdapter.include PgTypes::SchemaStatements
8
- ActiveRecord::Migration::CommandRecorder.include PgTypes::CommandRecorder
9
- ActiveRecord::SchemaDumper.prepend PgTypes::SchemaDumper
7
+ PgTypes.load
10
8
  end
11
9
  end
12
10
  end
@@ -2,49 +2,82 @@
2
2
 
3
3
  module PgTypes
4
4
  module SchemaDumper
5
+ # Define a Struct for type information
6
+ TypeDefinition = Struct.new(:name, :definition)
7
+
8
+ # Override the types method from ActiveRecord's PostgreSQL schema dumper
9
+ # This will run at the right time in the schema dump process (after extensions, before tables)
5
10
  def tables(stream)
6
- # First dump types
11
+ # Then add our custom composite types
7
12
  dump_custom_types(stream)
8
- stream.puts
9
13
 
14
+ # Call the original types method first (for enum types)
10
15
  super
11
16
  end
12
17
 
13
18
  private
14
19
 
15
20
  def dump_custom_types(stream)
16
- type_versions = {}
17
- Dir.glob(File.join(Dir.pwd, "db/types/*_v*.sql")).each do |file|
18
- file_version = FileVersion.new(file)
19
- type_versions[file_version.name] ||= []
20
- type_versions[file_version.name] << file_version
21
- end
21
+ types = dumpable_types_in_database
22
22
 
23
- return if type_versions.empty?
23
+ return if types.empty?
24
24
 
25
25
  stream.puts " # These are custom PostgreSQL types that were defined"
26
26
 
27
- latest_versions = type_versions.transform_values do |versions|
28
- versions.max_by(&:version)
27
+ # Sort by name to ensure consistent ordering
28
+ types.sort_by(&:name).each do |type|
29
+ stream.puts <<-TYPE
30
+ create_type "#{type.name}", sql_definition: <<-SQL
31
+ #{type.definition}
32
+ SQL
33
+ TYPE
29
34
  end
35
+ end
30
36
 
31
- latest_versions.keys.sort.each do |type_name|
32
- file_version = latest_versions[type_name]
33
- all_versions = type_versions[type_name].map(&:version).sort
34
- version_comment = all_versions.size > 1 ? " -- versions: #{all_versions.join(", ")}" : ""
35
-
36
- # Remove any leading/trailing whitespace from SQL definition
37
- sql_def = file_version.sql_definition.strip
37
+ # Fetches all custom types from the database
38
+ def dumpable_types_in_database
39
+ @dumpable_types_in_database ||= begin
40
+ # SQL query to fetch custom types from PostgreSQL
41
+ sql = <<~SQL
42
+ SELECT#{" "}
43
+ t.typname AS name,
44
+ format(
45
+ 'CREATE TYPE %s AS (%s);',
46
+ t.typname,
47
+ array_to_string(
48
+ array_agg(
49
+ format(
50
+ '%s %s',
51
+ a.attname,
52
+ pg_catalog.format_type(a.atttypid, a.atttypmod)
53
+ ) ORDER BY a.attnum
54
+ ),
55
+ E',\n '
56
+ )
57
+ ) AS definition
58
+ FROM pg_type t
59
+ JOIN pg_class c ON (c.relname = t.typname)
60
+ JOIN pg_attribute a ON (a.attrelid = c.oid)
61
+ JOIN pg_namespace n ON (n.oid = t.typnamespace)
62
+ WHERE n.nspname = 'public'
63
+ AND c.relkind = 'c'
64
+ AND a.attnum > 0
65
+ AND NOT a.attisdropped
66
+ GROUP BY t.typname, n.nspname
67
+ ORDER BY t.typname;
68
+ SQL
38
69
 
39
- stream.puts <<-TYPE
40
- create_type "#{type_name}", sql_definition: <<-SQL#{version_comment}
41
- #{sql_def}
42
- SQL
70
+ # Get the appropriate connection
71
+ connection = ActiveRecord::Base.connection
43
72
 
44
- TYPE
73
+ # Execute the query and transform results into type objects
74
+ connection.execute(sql).map do |result|
75
+ TypeDefinition.new(
76
+ result["name"],
77
+ result["definition"].strip
78
+ )
79
+ end
45
80
  end
46
-
47
- stream.puts
48
81
  end
49
82
  end
50
83
  end
@@ -5,6 +5,9 @@ module PgTypes
5
5
  def create_type(name, version: nil, sql_definition: nil)
6
6
  raise ArgumentError, "Must provide either sql_definition or version" if sql_definition.nil? && version.nil?
7
7
 
8
+ # First, check if the type already exists to avoid duplicate creation attempts
9
+ return if type_exists?(name)
10
+
8
11
  if sql_definition
9
12
  execute sql_definition
10
13
  else
@@ -21,6 +24,10 @@ module PgTypes
21
24
 
22
25
  execute File.read(sql_file)
23
26
  end
27
+ rescue ActiveRecord::StatementInvalid => e
28
+ puts "WARNING: Failed to create type #{name}."
29
+ puts " Error: #{e.message}"
30
+ raise
24
31
  end
25
32
 
26
33
  def drop_type(name, force: false)
@@ -39,5 +46,22 @@ module PgTypes
39
46
  $$;
40
47
  SQL
41
48
  end
49
+
50
+ private
51
+
52
+ def type_exists?(name)
53
+ sql = <<-SQL
54
+ SELECT 1
55
+ FROM pg_catalog.pg_type t
56
+ JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace
57
+ WHERE t.typname = '#{name}'
58
+ AND n.nspname = 'public'
59
+ SQL
60
+
61
+ result = execute(sql)
62
+ result.any?
63
+ rescue StandardError
64
+ false
65
+ end
42
66
  end
43
67
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module PgTypes
4
- VERSION = "0.2.1"
4
+ VERSION = "0.2.2"
5
5
  end
data/lib/pg_types.rb CHANGED
@@ -10,11 +10,20 @@ require_relative "pg_types/schema_dumper"
10
10
  require_relative "pg_types/railtie"
11
11
 
12
12
  module PgTypes
13
+ module_function
14
+
13
15
  class Error < StandardError; end
14
16
 
15
- class << self
16
- def database
17
- ActiveRecord::Base.connection
18
- end
17
+ def load
18
+ # Add schema statements and command recorder
19
+ ActiveRecord::ConnectionAdapters::AbstractAdapter.include PgTypes::SchemaStatements
20
+ ActiveRecord::Migration::CommandRecorder.include PgTypes::CommandRecorder
21
+
22
+ # Hook into the schema dumper
23
+ ActiveRecord::SchemaDumper.prepend PgTypes::SchemaDumper
24
+ end
25
+
26
+ def database
27
+ ActiveRecord::Base.connection
19
28
  end
20
29
  end
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pg_types
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - mhenrixon
8
- autorequire:
9
8
  bindir: exe
10
9
  cert_chain: []
11
- date: 2024-11-05 00:00:00.000000000 Z
10
+ date: 2025-04-17 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: activerecord
@@ -97,7 +96,6 @@ metadata:
97
96
  rubygems_mfa_required: 'true'
98
97
  github_repo: ssh://github.com/mhenrixon/pg_types
99
98
  funding_uri: https://github.com/sponsors/mhenrixon
100
- post_install_message:
101
99
  rdoc_options: []
102
100
  require_paths:
103
101
  - lib
@@ -112,8 +110,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
112
110
  - !ruby/object:Gem::Version
113
111
  version: '0'
114
112
  requirements: []
115
- rubygems_version: 3.5.22
116
- signing_key:
113
+ rubygems_version: 3.6.2
117
114
  specification_version: 4
118
115
  summary: Rails integration for PostgreSQL custom types
119
116
  test_files: []