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 +4 -4
- data/lib/pg_types/railtie.rb +2 -4
- data/lib/pg_types/schema_dumper.rb +58 -25
- data/lib/pg_types/schema_statements.rb +24 -0
- data/lib/pg_types/version.rb +1 -1
- data/lib/pg_types.rb +13 -4
- metadata +3 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1cd243d89a6bc0e672b5cd07d3aa1d2fe3d4227351cb0ee64720cf0126ed9538
|
4
|
+
data.tar.gz: b19af58bb2ba7b308dc7597d487d6914e5cdb044d762da86191103ae4a4512e0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9d14da9a0eafad1dded2f282521cb814b36581de7e2f0d3ae620bffddb3cd8c738fc8441d176ab745fb32965b92a28c55dfa97a4a4409698fcca0a2d9dbfed15
|
7
|
+
data.tar.gz: 06771fa123bd0bc8999ebe2e986f967c0361ff22f8f066eb068f6e353d68a3f6d7c2bb36acea28d7604188755c5ad23c8ae1d447aa5cbe66ee2d14bc1fccc5b8
|
data/lib/pg_types/railtie.rb
CHANGED
@@ -2,11 +2,9 @@
|
|
2
2
|
|
3
3
|
module PgTypes
|
4
4
|
class Railtie < Rails::Railtie
|
5
|
-
initializer "
|
5
|
+
initializer "pg_types.load", after: "pg_aggregates.load" do
|
6
6
|
ActiveSupport.on_load(:active_record) do
|
7
|
-
|
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
|
-
#
|
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
|
-
|
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
|
23
|
+
return if types.empty?
|
24
24
|
|
25
25
|
stream.puts " # These are custom PostgreSQL types that were defined"
|
26
26
|
|
27
|
-
|
28
|
-
|
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
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
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
|
-
|
40
|
-
|
41
|
-
#{sql_def}
|
42
|
-
SQL
|
70
|
+
# Get the appropriate connection
|
71
|
+
connection = ActiveRecord::Base.connection
|
43
72
|
|
44
|
-
|
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
|
data/lib/pg_types/version.rb
CHANGED
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
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
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.
|
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:
|
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.
|
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: []
|