activerecord-postgis-adapter 5.2.2 → 7.1.0

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: a6467b540dc2494cfe0add8a78d7d04258c6ae7a64b32ef397d7b58703b961d8
4
- data.tar.gz: 508f828273255798e15451a683d331c7488fb2d0840f92ba5dccb7c7d97f2f9b
3
+ metadata.gz: fcaaf2a57395c122e6541b1e40bd416f5f31fd1e512c250e5222ec5bb3feb650
4
+ data.tar.gz: 2772452b3ea880ecab759cb5add73d2ed22a89a78e12eae087aff60a061a8f20
5
5
  SHA512:
6
- metadata.gz: 198647715bc7f7ed32b996e1dc5be24019d27c65b3cf3085b1b09d0544052b0f302aff527e58de2e75fd43964365af79044f512ee10575102284f82a489222d0
7
- data.tar.gz: dbe312d6930f13c271a0ee82312e05966e645c7d77edb2dd31643e5277b3de755b35f0d55e7e5704ba56ea47a9d10efbb0e57b7b67e9019bb19366fadd2fd579
6
+ metadata.gz: 743b335ad32f5d872eebd7c512d7557102ed137664e4336a8c26154fe5f3b2bc3ded2b8e0ebe73195e05e8bb9affb538f7dde93e2aa095b142078e464c2fed98
7
+ data.tar.gz: 8cfc035141871044857863337a94f4c854423afc784f305853cd1a838dde14ec729a941c50a14edc5841829e8c21ce8c4f04c1826611ecb853d8239fb95401f4
@@ -1,5 +1,23 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ module RGeo
4
+ module ActiveRecord
5
+ ##
6
+ # Extend rgeo-activerecord visitors to use PostGIS specific functionality
7
+ module SpatialToPostGISSql
8
+ def visit_in_spatial_context(node, collector)
9
+ # Use ST_GeomFromEWKT for EWKT geometries
10
+ if node.is_a?(String) && node =~ /SRID=[\d+]{0,};/
11
+ collector << "#{st_func('ST_GeomFromEWKT')}(#{quote(node)})"
12
+ else
13
+ super(node, collector)
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+ RGeo::ActiveRecord::SpatialToSql.prepend RGeo::ActiveRecord::SpatialToPostGISSql
20
+
3
21
  module Arel # :nodoc:
4
22
  module Visitors # :nodoc:
5
23
  # Different super-class under JRuby JDBC adapter.
@@ -11,22 +29,6 @@ module Arel # :nodoc:
11
29
 
12
30
  class PostGIS < PostGISSuperclass # :nodoc:
13
31
  include RGeo::ActiveRecord::SpatialToSql
14
-
15
- FUNC_MAP = {
16
- "st_wkttosql" => "ST_GeomFromEWKT",
17
- }
18
-
19
- def st_func(standard_name)
20
- FUNC_MAP[standard_name.downcase] || standard_name
21
- end
22
-
23
- def visit_String(node, collector)
24
- collector << "#{st_func('ST_WKTToSQL')}(#{quote(node)})"
25
- end
26
-
27
- def visit_RGeo_ActiveRecord_SpatialNamedFunction(node, collector)
28
- aggregate(st_func(node.name), node, collector)
29
- end
30
32
  end
31
33
  end
32
34
  end
@@ -6,43 +6,43 @@ module ActiveRecord
6
6
  module ColumnMethods
7
7
  def spatial(name, options = {})
8
8
  raise "You must set a type. For example: 't.spatial type: :st_point'" unless options[:type]
9
- column(name, options[:type], options)
9
+ column(name, options[:type], **options)
10
10
  end
11
11
 
12
12
  def geography(name, options = {})
13
- column(name, :geography, options)
13
+ column(name, :geography, **options)
14
14
  end
15
15
 
16
16
  def geometry(name, options = {})
17
- column(name, :geometry, options)
17
+ column(name, :geometry, **options)
18
18
  end
19
19
 
20
20
  def geometry_collection(name, options = {})
21
- column(name, :geometry_collection, options)
21
+ column(name, :geometry_collection, **options)
22
22
  end
23
23
 
24
24
  def line_string(name, options = {})
25
- column(name, :line_string, options)
25
+ column(name, :line_string, **options)
26
26
  end
27
27
 
28
28
  def multi_line_string(name, options = {})
29
- column(name, :multi_line_string, options)
29
+ column(name, :multi_line_string, **options)
30
30
  end
31
31
 
32
32
  def multi_point(name, options = {})
33
- column(name, :multi_point, options)
33
+ column(name, :multi_point, **options)
34
34
  end
35
35
 
36
36
  def multi_polygon(name, options = {})
37
- column(name, :multi_polygon, options)
37
+ column(name, :multi_polygon, **options)
38
38
  end
39
39
 
40
40
  def st_point(name, options = {})
41
- column(name, :st_point, options)
41
+ column(name, :st_point, **options)
42
42
  end
43
43
 
44
44
  def st_polygon(name, options = {})
45
- column(name, :st_polygon, options)
45
+ column(name, :st_polygon, **options)
46
46
  end
47
47
  end
48
48
  end
@@ -10,7 +10,11 @@ module ActiveRecord # :nodoc:
10
10
  module ConnectionHandling # :nodoc:
11
11
  if RUBY_ENGINE == "jruby"
12
12
 
13
+ # modified from https://github.com/jruby/activerecord-jdbc-adapter/blob/master/lib/arjdbc/postgresql/connection_methods.rb#L3
13
14
  def postgis_connection(config)
15
+ config = config.deep_dup
16
+ config = symbolize_keys_if_necessary(config)
17
+
14
18
  config[:adapter_class] = ConnectionAdapters::PostGISAdapter
15
19
  postgresql_connection(config)
16
20
  end
@@ -23,21 +27,22 @@ module ActiveRecord # :nodoc:
23
27
  # https://github.com/rails/rails/blob/master/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
24
28
  # FULL REPLACEMENT because we need to create a different class.
25
29
  def postgis_connection(config)
26
- conn_params = config.symbolize_keys
27
-
28
- conn_params.delete_if { |_, v| v.nil? }
30
+ conn_params = config.symbolize_keys.compact
29
31
 
30
32
  # Map ActiveRecords param names to PGs.
31
33
  conn_params[:user] = conn_params.delete(:username) if conn_params[:username]
32
34
  conn_params[:dbname] = conn_params.delete(:database) if conn_params[:database]
33
35
 
34
- # Forward only valid config params to PGconn.connect.
36
+ # Forward only valid config params to PG.connect
35
37
  valid_conn_param_keys = PG::Connection.conndefaults_hash.keys + [:requiressl]
36
38
  conn_params.slice!(*valid_conn_param_keys)
37
39
 
38
- # The postgres drivers don't allow the creation of an unconnected PGconn object,
39
- # so just pass a nil connection object for the time being.
40
- ConnectionAdapters::PostGISAdapter.new(nil, logger, conn_params, config)
40
+ ConnectionAdapters::PostGISAdapter.new(
41
+ ConnectionAdapters::PostGISAdapter.new_client(conn_params),
42
+ logger,
43
+ conn_params,
44
+ config
45
+ )
41
46
  end
42
47
 
43
48
  end
@@ -2,17 +2,18 @@
2
2
 
3
3
  namespace :db do
4
4
  namespace :gis do
5
- desc "Setup PostGIS data in the database"
5
+ desc 'Setup PostGIS data in the database'
6
6
  task setup: [:load_config] do
7
7
  environments = [Rails.env]
8
- environments << "test" if Rails.env.development?
9
- ActiveRecord::Base.configurations
10
- .values_at(*environments)
11
- .compact
12
- .reject { |config| config["database"].blank? }
13
- .each do |config|
14
- ActiveRecord::ConnectionAdapters::PostGIS::PostGISDatabaseTasks.new(config).setup_gis
8
+ environments << 'test' if Rails.env.development?
9
+ environments.each do |environment|
10
+ ActiveRecord::Base.configurations
11
+ .configs_for(env_name: environment)
12
+ .reject { |env| env.configuration_hash[:database].blank? }
13
+ .each do |env|
14
+ ActiveRecord::ConnectionAdapters::PostGIS::PostGISDatabaseTasks.new(env).setup_gis
15
15
  end
16
+ end
16
17
  end
17
18
  end
18
19
  end
@@ -4,16 +4,17 @@ module ActiveRecord
4
4
  module ConnectionAdapters
5
5
  module PostGIS
6
6
  module OID
7
+ # OID used to represent geometry/geography database types and attributes.
8
+ #
9
+ # Accepts `geo_type`, `srid`, `has_z`, `has_m`, and `geographic` as parameters.
10
+ # Responsible for parsing sql_types returned from the database and WKT features.
7
11
  class Spatial < Type::Value
8
- # sql_type is a string that comes from the database definition
9
- # examples:
10
- # "geometry(Point,4326)"
11
- # "geography(Point,4326)"
12
- # "geometry(Polygon,4326) NOT NULL"
13
- # "geometry(Geography,4326)"
14
- def initialize(oid, sql_type)
15
- @sql_type = sql_type
16
- @geo_type, @srid, @has_z, @has_m = self.class.parse_sql_type(sql_type)
12
+ def initialize(geo_type: 'geometry', srid: 0, has_z: false, has_m: false, geographic: false)
13
+ @geo_type = geo_type
14
+ @srid = srid
15
+ @has_z = has_z
16
+ @has_m = has_m
17
+ @geographic = geographic
17
18
  end
18
19
 
19
20
  # sql_type: geometry, geometry(Point), geometry(Point,4326), ...
@@ -43,30 +44,24 @@ module ActiveRecord
43
44
  # otherType(a,b)
44
45
  geo_type = sql_type
45
46
  end
46
- [geo_type, srid, has_z, has_m]
47
+ geographic = sql_type.match?(/geography/)
48
+
49
+ [geo_type, srid, has_z, has_m, geographic]
47
50
  end
48
51
 
49
52
  def spatial_factory
50
53
  @spatial_factory ||=
51
54
  RGeo::ActiveRecord::SpatialFactoryStore.instance.factory(
52
- geo_type: @geo_type,
53
- has_m: @has_m,
54
- has_z: @has_z,
55
- sql_type: @sql_type,
56
- srid: @srid
55
+ factory_attrs
57
56
  )
58
57
  end
59
58
 
60
- def geographic?
61
- @sql_type =~ /geography/
62
- end
63
-
64
59
  def spatial?
65
60
  true
66
61
  end
67
62
 
68
63
  def type
69
- geographic? ? :geography : :geometry
64
+ @geographic ? :geography : :geometry
70
65
  end
71
66
 
72
67
  # support setting an RGeo object or a WKT string
@@ -107,6 +102,16 @@ module ActiveRecord
107
102
  RGeo::WKRep::WKTParser.new(spatial_factory, support_ewkt: true, default_srid: @srid)
108
103
  end
109
104
  end
105
+
106
+ def factory_attrs
107
+ {
108
+ geo_type: @geo_type.underscore,
109
+ has_m: @has_m,
110
+ has_z: @has_z,
111
+ srid: @srid,
112
+ sql_type: type.to_s
113
+ }
114
+ end
110
115
  end
111
116
  end
112
117
  end
@@ -4,7 +4,7 @@ module ActiveRecord # :nodoc:
4
4
  module ConnectionAdapters # :nodoc:
5
5
  module PostGIS # :nodoc:
6
6
  class PostGISDatabaseTasks < ::ActiveRecord::Tasks::PostgreSQLDatabaseTasks # :nodoc:
7
- def initialize(config)
7
+ def initialize(db_config)
8
8
  super
9
9
  ensure_installation_configs
10
10
  end
@@ -14,19 +14,19 @@ module ActiveRecord # :nodoc:
14
14
  if extension_names
15
15
  setup_gis_from_extension
16
16
  end
17
- establish_connection(configuration)
17
+ establish_connection(db_config)
18
18
  end
19
19
 
20
20
  # Override to set the database owner and call setup_gis
21
21
  def create(master_established = false)
22
22
  establish_master_connection unless master_established
23
- extra_configs = { "encoding" => encoding }
24
- extra_configs["owner"] = username if has_su?
25
- connection.create_database(configuration["database"], configuration.merge(extra_configs))
23
+ extra_configs = { encoding: encoding }
24
+ extra_configs[:owner] = username if has_su?
25
+ connection.create_database(db_config.database, configuration_hash.merge(extra_configs))
26
26
  setup_gis
27
27
  rescue ::ActiveRecord::StatementInvalid => error
28
28
  if /database .* already exists/ === error.message
29
- raise ::ActiveRecord::Tasks::DatabaseAlreadyExists
29
+ raise ::ActiveRecord::DatabaseAlreadyExists
30
30
  else
31
31
  raise
32
32
  end
@@ -36,24 +36,24 @@ module ActiveRecord # :nodoc:
36
36
 
37
37
  # Override to use su_username and su_password
38
38
  def establish_master_connection
39
- establish_connection(configuration.merge(
40
- "database" => "postgres",
41
- "password" => su_password,
42
- "schema_search_path" => "public",
43
- "username" => su_username
39
+ establish_connection(configuration_hash.merge(
40
+ database: "postgres",
41
+ password: su_password,
42
+ schema_search_path: "public",
43
+ username: su_username
44
44
  ))
45
45
  end
46
46
 
47
47
  def establish_su_connection
48
- establish_connection(configuration.merge(
49
- "password" => su_password,
50
- "schema_search_path" => "public",
51
- "username" => su_username
48
+ establish_connection(configuration_hash.merge(
49
+ password: su_password,
50
+ schema_search_path: "public",
51
+ username: su_username
52
52
  ))
53
53
  end
54
54
 
55
55
  def username
56
- @username ||= configuration["username"]
56
+ @username ||= configuration_hash[:username]
57
57
  end
58
58
 
59
59
  def quoted_username
@@ -61,29 +61,30 @@ module ActiveRecord # :nodoc:
61
61
  end
62
62
 
63
63
  def password
64
- @password ||= configuration["password"]
64
+ @password ||= configuration_hash[:password]
65
65
  end
66
66
 
67
67
  def su_username
68
- @su_username ||= configuration["su_username"] || username
68
+ @su_username ||= configuration_hash.fetch(:su_username, username)
69
69
  end
70
70
 
71
71
  def su_password
72
- @su_password ||= configuration["su_password"] || password
72
+ @su_password ||= configuration_hash.fetch(:su_password, password)
73
73
  end
74
74
 
75
75
  def has_su?
76
- @has_su = configuration.include?("su_username") unless defined?(@has_su)
77
- @has_su
76
+ return @has_su if defined?(@has_su)
77
+
78
+ @has_su = configuration_hash.include?(:su_username)
78
79
  end
79
80
 
80
81
  def search_path
81
- @search_path ||= configuration["schema_search_path"].to_s.strip.split(",").map(&:strip)
82
+ @search_path ||= configuration_hash[:schema_search_path].to_s.strip.split(",").map(&:strip)
82
83
  end
83
84
 
84
85
  def extension_names
85
86
  @extension_names ||= begin
86
- extensions = configuration["postgis_extension"]
87
+ extensions = configuration_hash[:postgis_extension]
87
88
  case extensions
88
89
  when ::String
89
90
  extensions.split(",")
@@ -96,11 +97,11 @@ module ActiveRecord # :nodoc:
96
97
  end
97
98
 
98
99
  def ensure_installation_configs
99
- if configuration["setup"] == "default" && !configuration["postgis_extension"]
100
+ if configuration_hash[:setup] == "default" && !configuration_hash[:postgis_extension]
100
101
  share_dir = `pg_config --sharedir`.strip rescue "/usr/share"
101
102
  control_file = ::File.expand_path("extension/postgis.control", share_dir)
102
103
  if ::File.readable?(control_file)
103
- configuration["postgis_extension"] = "postgis"
104
+ @configuration_hash = configuration_hash.merge(postgis_extension: "postgis").freeze
104
105
  end
105
106
  end
106
107
  end
@@ -113,7 +114,7 @@ module ActiveRecord # :nodoc:
113
114
  end
114
115
  connection.execute("CREATE EXTENSION IF NOT EXISTS #{extname} SCHEMA topology")
115
116
  else
116
- if (postgis_schema = configuration["postgis_schema"])
117
+ if (postgis_schema = configuration_hash[:postgis_schema])
117
118
  schema_clause = "WITH SCHEMA #{postgis_schema}"
118
119
  unless schema_exists?(postgis_schema)
119
120
  connection.execute("CREATE SCHEMA #{postgis_schema}")
@@ -5,46 +5,37 @@ module ActiveRecord
5
5
  module PostGIS
6
6
  module SchemaStatements
7
7
  # override
8
- # pass table_name to #new_column
9
- def columns(table_name)
10
- # Limit, precision, and scale are all handled by the superclass.
11
- column_definitions(table_name).map do |column_name, type, default, notnull, oid, fmod, collation, comment|
12
- oid = oid.to_i
13
- fmod = fmod.to_i
14
- type_metadata = fetch_type_metadata(column_name, type, oid, fmod)
15
- cast_type = get_oid_type(oid.to_i, fmod.to_i, column_name, type)
16
- default_value = extract_value_from_default(default)
8
+ # https://github.com/rails/rails/blob/6-0-stable/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb#L624
9
+ # Create a SpatialColumn instead of a PostgreSQL::Column
10
+ def new_column_from_field(table_name, field)
11
+ column_name, type, default, notnull, oid, fmod, collation, comment = field
12
+ type_metadata = fetch_type_metadata(column_name, type, oid.to_i, fmod.to_i)
13
+ default_value = extract_value_from_default(default)
14
+ default_function = extract_default_function(default_value, default)
17
15
 
18
- default_function = extract_default_function(default_value, default)
19
- new_column(table_name, column_name, default_value, cast_type, type_metadata, !notnull,
20
- default_function, collation, comment)
21
- end
22
- end
23
-
24
- # override
25
- def new_column(table_name, column_name, default, cast_type, sql_type_metadata = nil,
26
- null = true, default_function = nil, collation = nil, comment = nil)
27
- # JDBC gets true/false in Rails 4, where other platforms get 't'/'f' strings.
28
- if null.is_a?(String)
29
- null = (null == "t")
30
- end
16
+ serial =
17
+ if (match = default_function&.match(/\Anextval\('"?(?<sequence_name>.+_(?<suffix>seq\d*))"?'::regclass\)\z/))
18
+ sequence_name_from_parts(table_name, column_name, match[:suffix]) == match[:sequence_name]
19
+ end
31
20
 
32
- column_info = spatial_column_info(table_name).get(column_name, sql_type_metadata.sql_type)
21
+ # {:dimension=>2, :has_m=>false, :has_z=>false, :name=>"latlon", :srid=>0, :type=>"GEOMETRY"}
22
+ spatial = spatial_column_info(table_name).get(column_name, type_metadata.sql_type)
33
23
 
34
- SpatialColumn.new(column_name,
35
- default,
36
- sql_type_metadata,
37
- null,
38
- table_name,
39
- default_function,
40
- collation,
41
- comment,
42
- cast_type,
43
- column_info)
24
+ SpatialColumn.new(
25
+ column_name,
26
+ default_value,
27
+ type_metadata,
28
+ !notnull,
29
+ default_function,
30
+ collation: collation,
31
+ comment: comment.presence,
32
+ serial: serial,
33
+ spatial: spatial
34
+ )
44
35
  end
45
36
 
46
37
  # override
47
- # https://github.com/rails/rails/blob/master/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb#L583
38
+ # https://github.com/rails/rails/blob/master/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb#L544
48
39
  #
49
40
  # returns Postgresql sql type string
50
41
  # examples:
@@ -54,12 +45,12 @@ module ActiveRecord
54
45
  # note: type alone is not enough to detect the sql type,
55
46
  # so `limit` is used to pass the additional information. :(
56
47
  #
57
- # type_to_sql(:geography, "Point,4326")
48
+ # type_to_sql(:geography, limit: "Point,4326")
58
49
  # => "geography(Point,4326)"
59
- def type_to_sql(type, options = {})
60
- case type
61
- when :geometry, :geography
62
- "#{type}(#{options[:limit]})"
50
+ def type_to_sql(type, limit: nil, precision: nil, scale: nil, array: nil, **)
51
+ case type.to_s
52
+ when "geometry", "geography"
53
+ "#{type}(#{limit})"
63
54
  else
64
55
  super
65
56
  end
@@ -83,8 +74,8 @@ module ActiveRecord
83
74
  end
84
75
 
85
76
  # override
86
- def create_table_definition(*args)
87
- PostGIS::TableDefinition.new(*args)
77
+ def create_table_definition(*args, **kwargs)
78
+ PostGIS::TableDefinition.new(self, *args, **kwargs)
88
79
  end
89
80
 
90
81
  # memoize hash of column infos for tables
@@ -94,8 +85,6 @@ module ActiveRecord
94
85
  end
95
86
 
96
87
  def initialize_type_map(map = type_map)
97
- super
98
-
99
88
  %w(
100
89
  geography
101
90
  geometry
@@ -107,10 +96,19 @@ module ActiveRecord
107
96
  st_point
108
97
  st_polygon
109
98
  ).each do |geo_type|
110
- map.register_type(geo_type) do |oid, _, sql_type|
111
- OID::Spatial.new(oid, sql_type)
99
+ map.register_type(geo_type) do |_, _, sql_type|
100
+ # sql_type is a string that comes from the database definition
101
+ # examples:
102
+ # "geometry(Point,4326)"
103
+ # "geography(Point,4326)"
104
+ # "geometry(Polygon,4326) NOT NULL"
105
+ # "geometry(Geography,4326)"
106
+ geo_type, srid, has_z, has_m, geographic = OID::Spatial.parse_sql_type(sql_type)
107
+ OID::Spatial.new(geo_type: geo_type, srid: srid, has_z: has_z, has_m: has_m, geographic: geographic)
112
108
  end
113
109
  end
110
+
111
+ super
114
112
  end
115
113
  end
116
114
  end
@@ -7,19 +7,17 @@ module ActiveRecord # :nodoc:
7
7
  # sql_type examples:
8
8
  # "Geometry(Point,4326)"
9
9
  # "Geography(Point,4326)"
10
- # cast_type example classes:
11
- # OID::Spatial
12
- # OID::Integer
13
- def initialize(name, default, sql_type_metadata = nil, null = true, table_name = nil,
14
- default_function = nil, collation = nil, comment = nil, cast_type = nil, opts = nil)
15
- @cast_type = cast_type
10
+ def initialize(name, default, sql_type_metadata = nil, null = true,
11
+ default_function = nil, collation: nil, comment: nil,
12
+ serial: nil, spatial: nil)
13
+ @sql_type_metadata = sql_type_metadata
16
14
  @geographic = !!(sql_type_metadata.sql_type =~ /geography\(/i)
17
- if opts
15
+ if spatial
18
16
  # This case comes from an entry in the geometry_columns table
19
- set_geometric_type_from_name(opts[:type])
20
- @srid = opts[:srid].to_i
21
- @has_z = !!opts[:has_z]
22
- @has_m = !!opts[:has_m]
17
+ set_geometric_type_from_name(spatial[:type])
18
+ @srid = spatial[:srid].to_i
19
+ @has_z = !!spatial[:has_z]
20
+ @has_m = !!spatial[:has_m]
23
21
  elsif @geographic
24
22
  # Geographic type information is embedded in the SQL type
25
23
  @srid = 4326
@@ -32,7 +30,8 @@ module ActiveRecord # :nodoc:
32
30
  # @geometric_type = geo_type_from_sql_type(sql_type)
33
31
  build_from_sql_type(sql_type_metadata.sql_type)
34
32
  end
35
- super(name, default, sql_type_metadata, null, table_name, default_function, collation, comment: comment)
33
+ super(name, default, sql_type_metadata, null, default_function,
34
+ collation: collation, comment: comment, serial: serial)
36
35
  if spatial?
37
36
  if @srid
38
37
  @limit = { srid: @srid, type: to_type_name(geometric_type) }
@@ -54,15 +53,11 @@ module ActiveRecord # :nodoc:
54
53
  alias :has_m? :has_m
55
54
 
56
55
  def limit
57
- if spatial?
58
- @limit
59
- else
60
- super
61
- end
56
+ spatial? ? @limit : super
62
57
  end
63
58
 
64
59
  def spatial?
65
- @cast_type.respond_to?(:spatial?) && @cast_type.spatial?
60
+ %i[geometry geography].include?(@sql_type_metadata.type)
66
61
  end
67
62
 
68
63
  private
@@ -72,7 +67,7 @@ module ActiveRecord # :nodoc:
72
67
  end
73
68
 
74
69
  def build_from_sql_type(sql_type)
75
- geo_type, @srid, @has_z, @has_m = OID::Spatial.parse_sql_type(sql_type)
70
+ geo_type, @srid, @has_z, @has_m, @geographic = OID::Spatial.parse_sql_type(sql_type)
76
71
  set_geometric_type_from_name(geo_type)
77
72
  end
78
73
 
@@ -7,7 +7,7 @@ module ActiveRecord # :nodoc:
7
7
  include ColumnMethods
8
8
 
9
9
  # super: https://github.com/rails/rails/blob/master/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb
10
- def new_column_definition(name, type, options)
10
+ def new_column_definition(name, type, **options)
11
11
  if (info = PostGISAdapter.spatial_column_options(type.to_sym))
12
12
  if (limit = options.delete(:limit))
13
13
  options.merge!(limit) if limit.is_a?(::Hash)
@@ -18,9 +18,9 @@ module ActiveRecord # :nodoc:
18
18
 
19
19
  options[:limit] = ColumnDefinitionUtils.limit_from_options(geo_type, options)
20
20
  options[:spatial_type] = geo_type
21
- column = super(name, base_type, options)
21
+ column = super(name, base_type, **options)
22
22
  else
23
- column = super(name, type, options)
23
+ column = super(name, type, **options)
24
24
  end
25
25
 
26
26
  column
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ module ConnectionAdapters
5
+ module PostGIS
6
+ module Type
7
+ # Look for :postgis types first, then check for :postgresql
8
+ # types to simulate a kind of Type inheritance.
9
+ def lookup(*args, adapter: current_adapter_name, **kwargs)
10
+ super(*args, adapter: adapter, **kwargs)
11
+ rescue ArgumentError => e
12
+ raise e unless current_adapter_name == :postgis
13
+
14
+ super(*args, adapter: :postgresql, **kwargs)
15
+ end
16
+ end
17
+ end
18
+ end
19
+
20
+ # Type uses `class << self` syntax so we have to prepend to the singleton_class
21
+ Type.singleton_class.prepend(ActiveRecord::ConnectionAdapters::PostGIS::Type)
22
+ end
@@ -3,7 +3,7 @@
3
3
  module ActiveRecord
4
4
  module ConnectionAdapters
5
5
  module PostGIS
6
- VERSION = "5.2.2"
6
+ VERSION = "7.1.0"
7
7
  end
8
8
  end
9
9
  end
@@ -7,13 +7,7 @@
7
7
 
8
8
  require "rgeo/active_record"
9
9
 
10
- # autoload AbstractAdapter to avoid circular require and void context warnings
11
- module ActiveRecord
12
- module ConnectionAdapters
13
- AbstractAdapter
14
- end
15
- end
16
-
10
+ require "active_record/connection_adapters"
17
11
  require "active_record/connection_adapters/postgresql_adapter"
18
12
  require "active_record/connection_adapters/postgis/version"
19
13
  require "active_record/connection_adapters/postgis/column_methods"
@@ -24,6 +18,7 @@ require "active_record/connection_adapters/postgis/spatial_column"
24
18
  require "active_record/connection_adapters/postgis/arel_tosql"
25
19
  require "active_record/connection_adapters/postgis/setup"
26
20
  require "active_record/connection_adapters/postgis/oid/spatial"
21
+ require "active_record/connection_adapters/postgis/type" # has to be after oid/*
27
22
  require "active_record/connection_adapters/postgis/create_connection"
28
23
  require "active_record/connection_adapters/postgis/postgis_database_tasks"
29
24
 
@@ -38,7 +33,7 @@ end
38
33
  module ActiveRecord
39
34
  module ConnectionAdapters
40
35
  class PostGISAdapter < PostgreSQLAdapter
41
- include PostGIS::SchemaStatements
36
+ ADAPTER_NAME = 'PostGIS'
42
37
 
43
38
  SPATIAL_COLUMN_OPTIONS =
44
39
  {
@@ -57,22 +52,10 @@ module ActiveRecord
57
52
  # http://postgis.17.x6.nabble.com/Default-SRID-td5001115.html
58
53
  DEFAULT_SRID = 0
59
54
 
60
- # def initialize(*args)
61
- def initialize(connection, logger, connection_parameters, config)
62
- super
63
-
64
- @visitor = Arel::Visitors::PostGIS.new(self)
65
- # copy from https://github.com/rails/rails/blob/6ece7df8d80c6d93db43878fa4c0278a0204072c/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb#L199
66
- if self.class.type_cast_config_to_boolean(config.fetch(:prepared_statements) { true })
67
- @prepared_statements = true
68
- @visitor.extend(DetermineIfPreparableVisitor)
69
- else
70
- @prepared_statements = false
71
- end
72
- end
55
+ include PostGIS::SchemaStatements
73
56
 
74
- def adapter_name
75
- "PostGIS"
57
+ def arel_visitor # :nodoc:
58
+ Arel::Visitors::PostGIS.new(self)
76
59
  end
77
60
 
78
61
  def self.spatial_column_options(key)
@@ -105,6 +88,39 @@ module ActiveRecord
105
88
  super
106
89
  end
107
90
  end
91
+
92
+ # PostGIS specific types
93
+ [
94
+ :geography,
95
+ :geometry,
96
+ :geometry_collection,
97
+ :line_string,
98
+ :multi_line_string,
99
+ :multi_point,
100
+ :multi_polygon,
101
+ :st_point,
102
+ :st_polygon,
103
+ ].each do |geo_type|
104
+ ActiveRecord::Type.register(geo_type, PostGIS::OID::Spatial, adapter: :postgis)
105
+ end
108
106
  end
109
107
  end
110
108
  end
109
+
110
+ # if using JRUBY, create ArJdbc::PostGIS module
111
+ # and prepend it to the PostgreSQL adapter since
112
+ # it is the default adapter_spec.
113
+ # see: https://github.com/jruby/activerecord-jdbc-adapter/blob/master/lib/arjdbc/postgresql/adapter.rb#27
114
+ if RUBY_ENGINE == "jruby"
115
+ module ArJdbc
116
+ module PostGIS
117
+ ADAPTER_NAME = 'PostGIS'
118
+
119
+ def adapter_name
120
+ ADAPTER_NAME
121
+ end
122
+ end
123
+ end
124
+
125
+ ArJdbc::PostgreSQL.prepend(ArJdbc::PostGIS)
126
+ end
metadata CHANGED
@@ -1,14 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activerecord-postgis-adapter
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.2.2
4
+ version: 7.1.0
5
5
  platform: ruby
6
6
  authors:
7
- - Daniel Azuma, Tee Parham
7
+ - Daniel Azuma
8
+ - Tee Parham
8
9
  autorequire:
9
10
  bindir: bin
10
11
  cert_chain: []
11
- date: 2018-12-02 00:00:00.000000000 Z
12
+ date: 2021-03-28 00:00:00.000000000 Z
12
13
  dependencies:
13
14
  - !ruby/object:Gem::Dependency
14
15
  name: activerecord
@@ -16,28 +17,28 @@ dependencies:
16
17
  requirements:
17
18
  - - "~>"
18
19
  - !ruby/object:Gem::Version
19
- version: '5.1'
20
+ version: '6.1'
20
21
  type: :runtime
21
22
  prerelease: false
22
23
  version_requirements: !ruby/object:Gem::Requirement
23
24
  requirements:
24
25
  - - "~>"
25
26
  - !ruby/object:Gem::Version
26
- version: '5.1'
27
+ version: '6.1'
27
28
  - !ruby/object:Gem::Dependency
28
29
  name: rgeo-activerecord
29
30
  requirement: !ruby/object:Gem::Requirement
30
31
  requirements:
31
32
  - - "~>"
32
33
  - !ruby/object:Gem::Version
33
- version: '6.0'
34
+ version: 7.0.0
34
35
  type: :runtime
35
36
  prerelease: false
36
37
  version_requirements: !ruby/object:Gem::Requirement
37
38
  requirements:
38
39
  - - "~>"
39
40
  - !ruby/object:Gem::Version
40
- version: '6.0'
41
+ version: 7.0.0
41
42
  - !ruby/object:Gem::Dependency
42
43
  name: rake
43
44
  requirement: !ruby/object:Gem::Requirement
@@ -97,7 +98,10 @@ dependencies:
97
98
  description: ActiveRecord connection adapter for PostGIS. It is based on the stock
98
99
  PostgreSQL adapter, and adds built-in support for the spatial extensions provided
99
100
  by PostGIS. It uses the RGeo library to represent spatial data in Ruby.
100
- email: dazuma@gmail.com, parhameter@gmail.com
101
+ email:
102
+ - dazuma@gmail.com
103
+ - parhameter@gmail.com
104
+ - kfdoggett@gmail.com
101
105
  executables: []
102
106
  extensions: []
103
107
  extra_rdoc_files: []
@@ -115,12 +119,13 @@ files:
115
119
  - lib/active_record/connection_adapters/postgis/spatial_column.rb
116
120
  - lib/active_record/connection_adapters/postgis/spatial_column_info.rb
117
121
  - lib/active_record/connection_adapters/postgis/spatial_table_definition.rb
122
+ - lib/active_record/connection_adapters/postgis/type.rb
118
123
  - lib/active_record/connection_adapters/postgis/version.rb
119
124
  - lib/active_record/connection_adapters/postgis_adapter.rb
120
125
  - lib/activerecord-postgis-adapter.rb
121
126
  homepage: http://github.com/rgeo/activerecord-postgis-adapter
122
127
  licenses:
123
- - BSD
128
+ - BSD-3-Clause
124
129
  metadata: {}
125
130
  post_install_message:
126
131
  rdoc_options: []
@@ -130,15 +135,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
130
135
  requirements:
131
136
  - - ">="
132
137
  - !ruby/object:Gem::Version
133
- version: 2.2.2
138
+ version: 2.5.0
134
139
  required_rubygems_version: !ruby/object:Gem::Requirement
135
140
  requirements:
136
141
  - - ">="
137
142
  - !ruby/object:Gem::Version
138
143
  version: '0'
139
144
  requirements: []
140
- rubyforge_project:
141
- rubygems_version: 2.7.8
145
+ rubygems_version: 3.0.8
142
146
  signing_key:
143
147
  specification_version: 4
144
148
  summary: ActiveRecord adapter for PostGIS, based on RGeo.