rgeo 0.1.22 → 0.2.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.
- data/History.rdoc +31 -0
- data/README.rdoc +53 -59
- data/Spatial_Programming_With_RGeo.rdoc +120 -67
- data/Version +1 -1
- data/ext/proj4_c_impl/extconf.rb +1 -1
- data/lib/rgeo.rb +80 -87
- data/lib/rgeo/cartesian.rb +0 -10
- data/lib/rgeo/coord_sys.rb +0 -7
- data/lib/rgeo/coord_sys/proj4.rb +2 -2
- data/lib/rgeo/error.rb +2 -6
- data/lib/rgeo/feature.rb +0 -7
- data/lib/rgeo/feature/curve.rb +5 -5
- data/lib/rgeo/feature/factory.rb +45 -5
- data/lib/rgeo/feature/factory_generator.rb +2 -4
- data/lib/rgeo/feature/geometry.rb +97 -27
- data/lib/rgeo/feature/geometry_collection.rb +3 -3
- data/lib/rgeo/feature/line_string.rb +3 -3
- data/lib/rgeo/feature/multi_curve.rb +2 -2
- data/lib/rgeo/feature/multi_surface.rb +3 -3
- data/lib/rgeo/feature/point.rb +6 -6
- data/lib/rgeo/feature/polygon.rb +4 -4
- data/lib/rgeo/feature/surface.rb +3 -3
- data/lib/rgeo/geographic.rb +0 -11
- data/lib/rgeo/geographic/factory.rb +5 -2
- data/lib/rgeo/geographic/interface.rb +1 -1
- data/lib/rgeo/geos.rb +0 -7
- data/lib/rgeo/geos/factory.rb +1 -1
- data/lib/rgeo/impl_helper.rb +0 -7
- data/lib/rgeo/wkrep.rb +0 -7
- data/lib/rgeo/wkrep/wkb_parser.rb +2 -2
- data/test/tc_oneoff.rb +0 -1
- metadata +7 -155
- data/lib/active_record/connection_adapters/mysql2spatial_adapter.rb +0 -124
- data/lib/active_record/connection_adapters/mysqlspatial_adapter.rb +0 -136
- data/lib/active_record/connection_adapters/postgis_adapter.rb +0 -426
- data/lib/active_record/connection_adapters/spatialite_adapter.rb +0 -488
- data/lib/rgeo/active_record/arel_modifications.rb +0 -78
- data/lib/rgeo/active_record/base_modifications.rb +0 -124
- data/lib/rgeo/active_record/common.rb +0 -166
- data/lib/rgeo/active_record/mysql_common.rb +0 -150
- data/lib/rgeo/all.rb +0 -49
- data/lib/rgeo/geo_json.rb +0 -60
- data/lib/rgeo/geo_json/coder.rb +0 -401
- data/lib/rgeo/geo_json/entities.rb +0 -285
- data/lib/rgeo/geo_json/interface.rb +0 -129
- data/lib/rgeo/shapefile.rb +0 -60
- data/lib/rgeo/shapefile/reader.rb +0 -898
- data/test/active_record/common_setup_methods.rb +0 -129
- data/test/active_record/readme.txt +0 -43
- data/test/active_record/tc_mysqlspatial.rb +0 -170
- data/test/active_record/tc_postgis.rb +0 -282
- data/test/active_record/tc_spatialite.rb +0 -198
- data/test/shapefile/shapelib_testcases/readme.txt +0 -11
- data/test/shapefile/shapelib_testcases/test.dbf +0 -0
- data/test/shapefile/shapelib_testcases/test.shp +0 -0
- data/test/shapefile/shapelib_testcases/test.shx +0 -0
- data/test/shapefile/shapelib_testcases/test0.shp +0 -0
- data/test/shapefile/shapelib_testcases/test0.shx +0 -0
- data/test/shapefile/shapelib_testcases/test1.shp +0 -0
- data/test/shapefile/shapelib_testcases/test1.shx +0 -0
- data/test/shapefile/shapelib_testcases/test10.shp +0 -0
- data/test/shapefile/shapelib_testcases/test10.shx +0 -0
- data/test/shapefile/shapelib_testcases/test11.shp +0 -0
- data/test/shapefile/shapelib_testcases/test11.shx +0 -0
- data/test/shapefile/shapelib_testcases/test12.shp +0 -0
- data/test/shapefile/shapelib_testcases/test12.shx +0 -0
- data/test/shapefile/shapelib_testcases/test13.shp +0 -0
- data/test/shapefile/shapelib_testcases/test13.shx +0 -0
- data/test/shapefile/shapelib_testcases/test2.shp +0 -0
- data/test/shapefile/shapelib_testcases/test2.shx +0 -0
- data/test/shapefile/shapelib_testcases/test3.shp +0 -0
- data/test/shapefile/shapelib_testcases/test3.shx +0 -0
- data/test/shapefile/shapelib_testcases/test4.shp +0 -0
- data/test/shapefile/shapelib_testcases/test4.shx +0 -0
- data/test/shapefile/shapelib_testcases/test5.shp +0 -0
- data/test/shapefile/shapelib_testcases/test5.shx +0 -0
- data/test/shapefile/shapelib_testcases/test6.shp +0 -0
- data/test/shapefile/shapelib_testcases/test6.shx +0 -0
- data/test/shapefile/shapelib_testcases/test7.shp +0 -0
- data/test/shapefile/shapelib_testcases/test7.shx +0 -0
- data/test/shapefile/shapelib_testcases/test8.shp +0 -0
- data/test/shapefile/shapelib_testcases/test8.shx +0 -0
- data/test/shapefile/shapelib_testcases/test9.shp +0 -0
- data/test/shapefile/shapelib_testcases/test9.shx +0 -0
- data/test/shapefile/tc_shapelib_tests.rb +0 -527
- data/test/tc_geojson.rb +0 -279
@@ -1,124 +0,0 @@
|
|
1
|
-
# -----------------------------------------------------------------------------
|
2
|
-
#
|
3
|
-
# MysqlSpatial adapter for ActiveRecord
|
4
|
-
#
|
5
|
-
# -----------------------------------------------------------------------------
|
6
|
-
# Copyright 2010 Daniel Azuma
|
7
|
-
#
|
8
|
-
# All rights reserved.
|
9
|
-
#
|
10
|
-
# Redistribution and use in source and binary forms, with or without
|
11
|
-
# modification, are permitted provided that the following conditions are met:
|
12
|
-
#
|
13
|
-
# * Redistributions of source code must retain the above copyright notice,
|
14
|
-
# this list of conditions and the following disclaimer.
|
15
|
-
# * Redistributions in binary form must reproduce the above copyright notice,
|
16
|
-
# this list of conditions and the following disclaimer in the documentation
|
17
|
-
# and/or other materials provided with the distribution.
|
18
|
-
# * Neither the name of the copyright holder, nor the names of any other
|
19
|
-
# contributors to this software, may be used to endorse or promote products
|
20
|
-
# derived from this software without specific prior written permission.
|
21
|
-
#
|
22
|
-
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
23
|
-
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
24
|
-
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
25
|
-
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
26
|
-
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
27
|
-
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
28
|
-
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
29
|
-
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
30
|
-
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
31
|
-
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
32
|
-
# POSSIBILITY OF SUCH DAMAGE.
|
33
|
-
# -----------------------------------------------------------------------------
|
34
|
-
;
|
35
|
-
|
36
|
-
|
37
|
-
require 'rgeo/active_record/mysql_common'
|
38
|
-
require 'active_record/connection_adapters/mysql2_adapter'
|
39
|
-
|
40
|
-
|
41
|
-
module ActiveRecord
|
42
|
-
|
43
|
-
class Base
|
44
|
-
|
45
|
-
|
46
|
-
# Create a mysql2spatial connection adapter
|
47
|
-
|
48
|
-
def self.mysql2spatial_connection(config_)
|
49
|
-
config_[:username] = 'root' if config_[:username].nil?
|
50
|
-
if ::Mysql2::Client.const_defined?(:FOUND_ROWS)
|
51
|
-
config_[:flags] = ::Mysql2::Client::FOUND_ROWS
|
52
|
-
end
|
53
|
-
client_ = ::Mysql2::Client.new(config_.symbolize_keys)
|
54
|
-
options_ = [config_[:host], config_[:username], config_[:password], config_[:database], config_[:port], config_[:socket], 0]
|
55
|
-
ConnectionAdapters::Mysql2SpatialAdapter.new(client_, logger, options_, config_)
|
56
|
-
end
|
57
|
-
|
58
|
-
|
59
|
-
end
|
60
|
-
|
61
|
-
|
62
|
-
module ConnectionAdapters # :nodoc:
|
63
|
-
|
64
|
-
class Mysql2SpatialAdapter < Mysql2Adapter # :nodoc:
|
65
|
-
|
66
|
-
|
67
|
-
class SpatialColumn < ConnectionAdapters::Mysql2Column # :nodoc:
|
68
|
-
|
69
|
-
include ::RGeo::ActiveRecord::MysqlCommon::ColumnMethods
|
70
|
-
|
71
|
-
end
|
72
|
-
|
73
|
-
|
74
|
-
include ::RGeo::ActiveRecord::MysqlCommon::AdapterMethods
|
75
|
-
|
76
|
-
|
77
|
-
ADAPTER_NAME = 'Mysql2Spatial'.freeze
|
78
|
-
|
79
|
-
NATIVE_DATABASE_TYPES = Mysql2Adapter::NATIVE_DATABASE_TYPES.merge(:geometry => {:name => "geometry"}, :point => {:name => "point"}, :line_string => {:name => "linestring"}, :polygon => {:name => "polygon"}, :geometry_collection => {:name => "geometrycollection"}, :multi_point => {:name => "multipoint"}, :multi_line_string => {:name => "multilinestring"}, :multi_polygon => {:name => "multipolygon"})
|
80
|
-
|
81
|
-
|
82
|
-
def native_database_types
|
83
|
-
NATIVE_DATABASE_TYPES
|
84
|
-
end
|
85
|
-
|
86
|
-
|
87
|
-
def adapter_name
|
88
|
-
ADAPTER_NAME
|
89
|
-
end
|
90
|
-
|
91
|
-
|
92
|
-
def columns(table_name_, name_=nil)
|
93
|
-
result_ = execute("SHOW FIELDS FROM #{quote_table_name(table_name_)}", :skip_logging)
|
94
|
-
columns_ = []
|
95
|
-
result_.each(:symbolize_keys => true, :as => :hash) do |field_|
|
96
|
-
columns_ << SpatialColumn.new(field_[:Field], field_[:Default], field_[:Type], field_[:Null] == "YES")
|
97
|
-
end
|
98
|
-
columns_
|
99
|
-
end
|
100
|
-
|
101
|
-
|
102
|
-
def indexes(table_name_, name_=nil)
|
103
|
-
indexes_ = []
|
104
|
-
current_index_ = nil
|
105
|
-
result_ = execute("SHOW KEYS FROM #{quote_table_name(table_name_)}", name_)
|
106
|
-
result_.each(:symbolize_keys => true, :as => :hash) do |row_|
|
107
|
-
if current_index_ != row_[:Key_name]
|
108
|
-
next if row_[:Key_name] == 'PRIMARY' # skip the primary key
|
109
|
-
current_index_ = row_[:Key_name]
|
110
|
-
indexes_ << ::RGeo::ActiveRecord::Common::IndexDefinition.new(row_[:Table], row_[:Key_name], row_[:Non_unique] == 0, [], [], row_[:Index_type] == 'SPATIAL')
|
111
|
-
end
|
112
|
-
indexes_.last.columns << row_[:Column_name]
|
113
|
-
indexes_.last.lengths << row_[:Sub_part]
|
114
|
-
end
|
115
|
-
indexes_
|
116
|
-
end
|
117
|
-
|
118
|
-
|
119
|
-
end
|
120
|
-
|
121
|
-
end
|
122
|
-
|
123
|
-
|
124
|
-
end
|
@@ -1,136 +0,0 @@
|
|
1
|
-
# -----------------------------------------------------------------------------
|
2
|
-
#
|
3
|
-
# MysqlSpatial adapter for ActiveRecord
|
4
|
-
#
|
5
|
-
# -----------------------------------------------------------------------------
|
6
|
-
# Copyright 2010 Daniel Azuma
|
7
|
-
#
|
8
|
-
# All rights reserved.
|
9
|
-
#
|
10
|
-
# Redistribution and use in source and binary forms, with or without
|
11
|
-
# modification, are permitted provided that the following conditions are met:
|
12
|
-
#
|
13
|
-
# * Redistributions of source code must retain the above copyright notice,
|
14
|
-
# this list of conditions and the following disclaimer.
|
15
|
-
# * Redistributions in binary form must reproduce the above copyright notice,
|
16
|
-
# this list of conditions and the following disclaimer in the documentation
|
17
|
-
# and/or other materials provided with the distribution.
|
18
|
-
# * Neither the name of the copyright holder, nor the names of any other
|
19
|
-
# contributors to this software, may be used to endorse or promote products
|
20
|
-
# derived from this software without specific prior written permission.
|
21
|
-
#
|
22
|
-
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
23
|
-
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
24
|
-
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
25
|
-
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
26
|
-
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
27
|
-
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
28
|
-
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
29
|
-
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
30
|
-
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
31
|
-
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
32
|
-
# POSSIBILITY OF SUCH DAMAGE.
|
33
|
-
# -----------------------------------------------------------------------------
|
34
|
-
;
|
35
|
-
|
36
|
-
|
37
|
-
require 'rgeo/active_record/mysql_common'
|
38
|
-
require 'active_record/connection_adapters/mysql_adapter'
|
39
|
-
|
40
|
-
|
41
|
-
module ActiveRecord
|
42
|
-
|
43
|
-
class Base
|
44
|
-
|
45
|
-
|
46
|
-
# Create a mysqlspatial connection adapter
|
47
|
-
|
48
|
-
def self.mysqlspatial_connection(config_)
|
49
|
-
unless defined?(::Mysql)
|
50
|
-
begin
|
51
|
-
require 'mysql'
|
52
|
-
rescue ::LoadError
|
53
|
-
raise "!!! Missing the mysql gem. Add it to your Gemfile: gem 'mysql'"
|
54
|
-
end
|
55
|
-
unless defined?(::Mysql::Result) && ::Mysql::Result.method_defined?(:each_hash)
|
56
|
-
raise "!!! Outdated mysql gem. Upgrade to 2.8.1 or later. In your Gemfile: gem 'mysql', '2.8.1'. Or use gem 'mysql2'"
|
57
|
-
end
|
58
|
-
end
|
59
|
-
config_ = config_.symbolize_keys
|
60
|
-
mysql_ = ::Mysql.init
|
61
|
-
mysql_.ssl_set(config_[:sslkey], config_[:sslcert], config_[:sslca], config_[:sslcapath], config_[:sslcipher]) if config_[:sslca] || config_[:sslkey]
|
62
|
-
default_flags_ = ::Mysql.const_defined?(:CLIENT_MULTI_RESULTS) ? ::Mysql::CLIENT_MULTI_RESULTS : 0
|
63
|
-
default_flags_ |= ::Mysql::CLIENT_FOUND_ROWS if ::Mysql.const_defined?(:CLIENT_FOUND_ROWS)
|
64
|
-
options_ = [config_[:host], config_[:username] ? config_[:username].to_s : 'root', config_[:password].to_s, config_[:database], config_[:port], config_[:socket], default_flags_]
|
65
|
-
ConnectionAdapters::MysqlSpatialAdapter.new(mysql_, logger, options_, config_)
|
66
|
-
end
|
67
|
-
|
68
|
-
|
69
|
-
end
|
70
|
-
|
71
|
-
|
72
|
-
module ConnectionAdapters # :nodoc:
|
73
|
-
|
74
|
-
class MysqlSpatialAdapter < MysqlAdapter # :nodoc:
|
75
|
-
|
76
|
-
|
77
|
-
class SpatialColumn < ConnectionAdapters::MysqlColumn # :nodoc:
|
78
|
-
|
79
|
-
include ::RGeo::ActiveRecord::MysqlCommon::ColumnMethods
|
80
|
-
|
81
|
-
end
|
82
|
-
|
83
|
-
|
84
|
-
include ::RGeo::ActiveRecord::MysqlCommon::AdapterMethods
|
85
|
-
|
86
|
-
|
87
|
-
ADAPTER_NAME = 'MysqlSpatial'.freeze
|
88
|
-
|
89
|
-
NATIVE_DATABASE_TYPES = MysqlAdapter::NATIVE_DATABASE_TYPES.merge(:geometry => {:name => "geometry"}, :point => {:name => "point"}, :line_string => {:name => "linestring"}, :polygon => {:name => "polygon"}, :geometry_collection => {:name => "geometrycollection"}, :multi_point => {:name => "multipoint"}, :multi_line_string => {:name => "multilinestring"}, :multi_polygon => {:name => "multipolygon"})
|
90
|
-
|
91
|
-
|
92
|
-
def native_database_types
|
93
|
-
NATIVE_DATABASE_TYPES
|
94
|
-
end
|
95
|
-
|
96
|
-
|
97
|
-
def adapter_name
|
98
|
-
ADAPTER_NAME
|
99
|
-
end
|
100
|
-
|
101
|
-
|
102
|
-
def columns(table_name_, name_=nil)
|
103
|
-
result_ = execute("SHOW FIELDS FROM #{quote_table_name(table_name_)}", :skip_logging)
|
104
|
-
columns_ = []
|
105
|
-
result_.each do |field_|
|
106
|
-
columns_ << SpatialColumn.new(field_[0], field_[4], field_[1], field_[2] == "YES")
|
107
|
-
end
|
108
|
-
result_.free
|
109
|
-
columns_
|
110
|
-
end
|
111
|
-
|
112
|
-
|
113
|
-
def indexes(table_name_, name_=nil)
|
114
|
-
indexes_ = []
|
115
|
-
current_index_ = nil
|
116
|
-
result_ = execute("SHOW KEYS FROM #{quote_table_name(table_name_)}", name_)
|
117
|
-
result_.each do |row_|
|
118
|
-
if current_index_ != row_[2]
|
119
|
-
next if row_[2] == "PRIMARY" # skip the primary key
|
120
|
-
current_index_ = row_[2]
|
121
|
-
indexes_ << ::RGeo::ActiveRecord::Common::IndexDefinition.new(row_[0], row_[2], row_[1] == "0", [], [], row_[10] == 'SPATIAL')
|
122
|
-
end
|
123
|
-
indexes_.last.columns << row_[4]
|
124
|
-
indexes_.last.lengths << row_[7]
|
125
|
-
end
|
126
|
-
result_.free
|
127
|
-
indexes_
|
128
|
-
end
|
129
|
-
|
130
|
-
|
131
|
-
end
|
132
|
-
|
133
|
-
end
|
134
|
-
|
135
|
-
|
136
|
-
end
|
@@ -1,426 +0,0 @@
|
|
1
|
-
# -----------------------------------------------------------------------------
|
2
|
-
#
|
3
|
-
# PostGIS adapter for ActiveRecord
|
4
|
-
#
|
5
|
-
# -----------------------------------------------------------------------------
|
6
|
-
# Copyright 2010 Daniel Azuma
|
7
|
-
#
|
8
|
-
# All rights reserved.
|
9
|
-
#
|
10
|
-
# Redistribution and use in source and binary forms, with or without
|
11
|
-
# modification, are permitted provided that the following conditions are met:
|
12
|
-
#
|
13
|
-
# * Redistributions of source code must retain the above copyright notice,
|
14
|
-
# this list of conditions and the following disclaimer.
|
15
|
-
# * Redistributions in binary form must reproduce the above copyright notice,
|
16
|
-
# this list of conditions and the following disclaimer in the documentation
|
17
|
-
# and/or other materials provided with the distribution.
|
18
|
-
# * Neither the name of the copyright holder, nor the names of any other
|
19
|
-
# contributors to this software, may be used to endorse or promote products
|
20
|
-
# derived from this software without specific prior written permission.
|
21
|
-
#
|
22
|
-
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
23
|
-
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
24
|
-
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
25
|
-
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
26
|
-
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
27
|
-
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
28
|
-
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
29
|
-
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
30
|
-
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
31
|
-
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
32
|
-
# POSSIBILITY OF SUCH DAMAGE.
|
33
|
-
# -----------------------------------------------------------------------------
|
34
|
-
;
|
35
|
-
|
36
|
-
|
37
|
-
require 'rgeo/active_record/common'
|
38
|
-
require 'active_record/connection_adapters/postgresql_adapter'
|
39
|
-
|
40
|
-
|
41
|
-
module ActiveRecord
|
42
|
-
|
43
|
-
class Base
|
44
|
-
|
45
|
-
|
46
|
-
# Create a postgis connection adapter.
|
47
|
-
|
48
|
-
|
49
|
-
def self.postgis_connection(config_)
|
50
|
-
require 'pg'
|
51
|
-
|
52
|
-
config_ = config_.symbolize_keys
|
53
|
-
host_ = config_[:host]
|
54
|
-
port_ = config_[:port] || 5432
|
55
|
-
username_ = config_[:username].to_s if config_[:username]
|
56
|
-
password_ = config_[:password].to_s if config_[:password]
|
57
|
-
if config_.has_key?(:database)
|
58
|
-
database_ = config_[:database]
|
59
|
-
else
|
60
|
-
raise ::ArgumentError, "No database specified. Missing argument: database."
|
61
|
-
end
|
62
|
-
|
63
|
-
# The postgres drivers don't allow the creation of an unconnected PGconn object,
|
64
|
-
# so just pass a nil connection object for the time being.
|
65
|
-
ConnectionAdapters::PostGisAdapter.new(nil, logger, [host_, port_, nil, nil, database_, username_, password_], config_)
|
66
|
-
end
|
67
|
-
|
68
|
-
|
69
|
-
end
|
70
|
-
|
71
|
-
|
72
|
-
module ConnectionAdapters # :nodoc:
|
73
|
-
|
74
|
-
|
75
|
-
class PostGisAdapter < PostgreSQLAdapter # :nodoc:
|
76
|
-
|
77
|
-
|
78
|
-
ADAPTER_NAME = 'PostGIS'.freeze
|
79
|
-
|
80
|
-
@@native_database_types = nil
|
81
|
-
|
82
|
-
|
83
|
-
def native_database_types
|
84
|
-
@@native_database_types ||= super.merge(:geometry => {:name => "geometry"}, :point => {:name => "point"}, :line_string => {:name => "linestring"}, :polygon => {:name => "polygon"}, :geometry_collection => {:name => "geometrycollection"}, :multi_point => {:name => "multipoint"}, :multi_line_string => {:name => "multilinestring"}, :multi_polygon => {:name => "multipolygon"})
|
85
|
-
end
|
86
|
-
|
87
|
-
|
88
|
-
def adapter_name
|
89
|
-
ADAPTER_NAME
|
90
|
-
end
|
91
|
-
|
92
|
-
|
93
|
-
def postgis_lib_version
|
94
|
-
unless defined?(@postgis_lib_version)
|
95
|
-
@postgis_lib_version = select_value("SELECT PostGIS_Lib_Version()") rescue nil
|
96
|
-
end
|
97
|
-
@postgis_lib_version
|
98
|
-
end
|
99
|
-
|
100
|
-
|
101
|
-
def quote(value_, column_=nil)
|
102
|
-
if ::RGeo::Feature::Geometry.check_type(value_)
|
103
|
-
"'#{::RGeo::WKRep::WKBGenerator.new(:hex_format => true, :type_format => :ewkb, :emit_ewkb_srid => true).generate(value_)}'"
|
104
|
-
else
|
105
|
-
super
|
106
|
-
end
|
107
|
-
end
|
108
|
-
|
109
|
-
|
110
|
-
def columns(table_name_, name_=nil) #:nodoc:
|
111
|
-
table_name_ = table_name_.to_s
|
112
|
-
spatial_info_ = spatial_column_info(table_name_)
|
113
|
-
column_definitions(table_name_).collect do |name_, type_, default_, notnull_|
|
114
|
-
SpatialColumn.new(name_, default_, type_, notnull_ == 'f', type_ =~ /geometry/i ? spatial_info_[name_] : nil)
|
115
|
-
end
|
116
|
-
end
|
117
|
-
|
118
|
-
|
119
|
-
def create_table(table_name_, options_={})
|
120
|
-
table_name_ = table_name_.to_s
|
121
|
-
table_definition_ = SpatialTableDefinition.new(self)
|
122
|
-
table_definition_.primary_key(options_[:primary_key] || ::ActiveRecord::Base.get_primary_key(table_name_.singularize)) unless options_[:id] == false
|
123
|
-
yield table_definition_ if block_given?
|
124
|
-
if options_[:force] && table_exists?(table_name_)
|
125
|
-
drop_table(table_name_, options_)
|
126
|
-
end
|
127
|
-
|
128
|
-
create_sql_ = "CREATE#{' TEMPORARY' if options_[:temporary]} TABLE "
|
129
|
-
create_sql_ << "#{quote_table_name(table_name_)} ("
|
130
|
-
create_sql_ << table_definition_.to_sql
|
131
|
-
create_sql_ << ") #{options_[:options]}"
|
132
|
-
execute create_sql_
|
133
|
-
|
134
|
-
table_definition_.non_geographic_spatial_columns.each do |col_|
|
135
|
-
type_ = col_.type.to_s.gsub('_', '').upcase
|
136
|
-
has_z_ = col_.has_z?
|
137
|
-
has_m_ = col_.has_m?
|
138
|
-
type_ = "#{type_}M" if has_m_ && !has_z_
|
139
|
-
dimensions_ = 2
|
140
|
-
dimensions_ += 1 if has_z_
|
141
|
-
dimensions_ += 1 if has_m_
|
142
|
-
execute("SELECT AddGeometryColumn('#{quote_string(table_name_)}', '#{quote_string(col_.name)}', #{col_.srid}, '#{quote_string(type_)}', #{dimensions_})")
|
143
|
-
end
|
144
|
-
end
|
145
|
-
|
146
|
-
|
147
|
-
def drop_table(table_name_, options_={})
|
148
|
-
execute("DELETE from geometry_columns where f_table_name='#{quote_string(table_name_.to_s)}'")
|
149
|
-
super
|
150
|
-
end
|
151
|
-
|
152
|
-
|
153
|
-
def add_column(table_name_, column_name_, type_, options_={})
|
154
|
-
table_name_ = table_name_.to_s
|
155
|
-
if ::RGeo::ActiveRecord::GEOMETRY_TYPES.include?(type_.to_sym)
|
156
|
-
type_ = type_.to_s.gsub('_', '').upcase
|
157
|
-
has_z_ = options_[:has_z]
|
158
|
-
has_m_ = options_[:has_m]
|
159
|
-
srid_ = (options_[:srid] || 4326).to_i
|
160
|
-
if options_[:geographic]
|
161
|
-
type_ << 'Z' if has_z_
|
162
|
-
type_ << 'M' if has_m_
|
163
|
-
execute("ALTER TABLE #{quote_table_name(table_name_)} ADD COLUMN #{quote_column_name(column_name_)} GEOGRAPHY(#{type_},#{srid_})")
|
164
|
-
change_column_default(table_name_, column_name_, options_[:default]) if options_include_default?(options_)
|
165
|
-
change_column_null(table_name_, column_name_, false, options_[:default]) if options_[:null] == false
|
166
|
-
else
|
167
|
-
type_ = "#{type_}M" if has_m_ && !has_z_
|
168
|
-
dimensions_ = 2
|
169
|
-
dimensions_ += 1 if has_z_
|
170
|
-
dimensions_ += 1 if has_m_
|
171
|
-
execute("SELECT AddGeometryColumn('#{quote_string(table_name_)}', '#{quote_string(column_name_.to_s)}', #{srid_}, '#{quote_string(type_)}', #{dimensions_})")
|
172
|
-
end
|
173
|
-
else
|
174
|
-
super
|
175
|
-
end
|
176
|
-
end
|
177
|
-
|
178
|
-
|
179
|
-
def remove_column(table_name_, *column_names_)
|
180
|
-
column_names_ = column_names_.flatten.map{ |n_| n_.to_s }
|
181
|
-
spatial_info_ = spatial_column_info(table_name_)
|
182
|
-
remaining_column_names_ = []
|
183
|
-
column_names_.each do |name_|
|
184
|
-
if spatial_info_.include?(name_)
|
185
|
-
execute("SELECT DropGeometryColumn('#{quote_string(table_name_.to_s)}','#{quote_string(name_)}')")
|
186
|
-
else
|
187
|
-
remaining_column_names_ << name_.to_sym
|
188
|
-
end
|
189
|
-
end
|
190
|
-
if remaining_column_names_.size > 0
|
191
|
-
super(table_name_, *remaining_column_names_)
|
192
|
-
end
|
193
|
-
end
|
194
|
-
|
195
|
-
|
196
|
-
def add_index(table_name_, column_name_, options_={})
|
197
|
-
table_name_ = table_name_.to_s
|
198
|
-
column_names_ = ::Array.wrap(column_name_)
|
199
|
-
index_name_ = index_name(table_name_, :column => column_names_)
|
200
|
-
gist_clause_ = ''
|
201
|
-
index_type_ = ''
|
202
|
-
if ::Hash === options_ # legacy support, since this param was a string
|
203
|
-
index_type_ = 'UNIQUE' if options_[:unique]
|
204
|
-
index_name_ = options_[:name].to_s if options_.key?(:name)
|
205
|
-
gist_clause_ = 'USING GIST' if options_[:spatial]
|
206
|
-
else
|
207
|
-
index_type_ = options_
|
208
|
-
end
|
209
|
-
if index_name_.length > index_name_length
|
210
|
-
raise ::ArgumentError, "Index name '#{index_name_}' on table '#{table_name_}' is too long; the limit is #{index_name_length} characters"
|
211
|
-
end
|
212
|
-
if index_name_exists?(table_name_, index_name_, false)
|
213
|
-
raise ::ArgumentError, "Index name '#{index_name_}' on table '#{table_name_}' already exists"
|
214
|
-
end
|
215
|
-
quoted_column_names_ = quoted_columns_for_index(column_names_, options_).join(", ")
|
216
|
-
execute "CREATE #{index_type_} INDEX #{quote_column_name(index_name_)} ON #{quote_table_name(table_name_)} #{gist_clause_} (#{quoted_column_names_})"
|
217
|
-
end
|
218
|
-
|
219
|
-
|
220
|
-
def spatial_column_info(table_name_)
|
221
|
-
info_ = query("SELECT * FROM geometry_columns WHERE f_table_name='#{quote_string(table_name_.to_s)}'")
|
222
|
-
result_ = {}
|
223
|
-
info_.each do |row_|
|
224
|
-
name_ = row_[3]
|
225
|
-
type_ = row_[6]
|
226
|
-
dimension_ = row_[4].to_i
|
227
|
-
has_m_ = type_ =~ /m$/i ? true : false
|
228
|
-
type_.sub!(/m$/, '')
|
229
|
-
has_z_ = dimension_ > 3 || dimension_ == 3 && !has_m_
|
230
|
-
result_[name_] = {
|
231
|
-
:name => name_,
|
232
|
-
:type => type_,
|
233
|
-
:dimension => dimension_,
|
234
|
-
:srid => row_[5].to_i,
|
235
|
-
:has_z => has_z_,
|
236
|
-
:has_m => has_m_,
|
237
|
-
}
|
238
|
-
end
|
239
|
-
result_
|
240
|
-
end
|
241
|
-
|
242
|
-
|
243
|
-
class SpatialTableDefinition < ConnectionAdapters::TableDefinition # :nodoc:
|
244
|
-
|
245
|
-
attr_reader :spatial_columns
|
246
|
-
|
247
|
-
def initialize(base_)
|
248
|
-
super
|
249
|
-
end
|
250
|
-
|
251
|
-
def column(name_, type_, options_={})
|
252
|
-
super
|
253
|
-
col_ = self[name_]
|
254
|
-
if ::RGeo::ActiveRecord::GEOMETRY_TYPES.include?(col_.type.to_sym)
|
255
|
-
col_.extend(GeometricColumnDefinitionMethods) unless col_.respond_to?(:geographic?)
|
256
|
-
col_.set_geographic(options_[:geographic])
|
257
|
-
col_.set_srid((options_[:srid] || 4326).to_i)
|
258
|
-
col_.set_has_z(options_[:has_z])
|
259
|
-
col_.set_has_m(options_[:has_m])
|
260
|
-
end
|
261
|
-
self
|
262
|
-
end
|
263
|
-
|
264
|
-
def to_sql
|
265
|
-
@columns.find_all{ |c_| !c_.respond_to?(:geographic?) || c_.geographic? }.map{ |c_| c_.to_sql } * ', '
|
266
|
-
end
|
267
|
-
|
268
|
-
def non_geographic_spatial_columns
|
269
|
-
@columns.find_all{ |c_| c_.respond_to?(:geographic?) && !c_.geographic? }
|
270
|
-
end
|
271
|
-
|
272
|
-
end
|
273
|
-
|
274
|
-
|
275
|
-
module GeometricColumnDefinitionMethods # :nodoc:
|
276
|
-
|
277
|
-
def geographic?
|
278
|
-
defined?(@geographic) && @geographic
|
279
|
-
end
|
280
|
-
|
281
|
-
def srid
|
282
|
-
defined?(@srid) ? @srid : 4326
|
283
|
-
end
|
284
|
-
|
285
|
-
def has_z?
|
286
|
-
defined?(@has_z) && @has_z
|
287
|
-
end
|
288
|
-
|
289
|
-
def has_m?
|
290
|
-
defined?(@has_m) && @has_m
|
291
|
-
end
|
292
|
-
|
293
|
-
def set_geographic(value_)
|
294
|
-
@geographic = value_ ? true : false
|
295
|
-
end
|
296
|
-
|
297
|
-
def set_srid(value_)
|
298
|
-
@srid = value_
|
299
|
-
end
|
300
|
-
|
301
|
-
def set_has_z(value_)
|
302
|
-
@has_z = value_ ? true : false
|
303
|
-
end
|
304
|
-
|
305
|
-
def set_has_m(value_)
|
306
|
-
@has_m = value_ ? true : false
|
307
|
-
end
|
308
|
-
|
309
|
-
def sql_type
|
310
|
-
type_ = type.to_s.upcase.gsub('_', '')
|
311
|
-
type_ << 'Z' if has_z?
|
312
|
-
type_ << 'M' if has_m?
|
313
|
-
"GEOGRAPHY(#{type_},#{srid})"
|
314
|
-
end
|
315
|
-
|
316
|
-
end
|
317
|
-
|
318
|
-
|
319
|
-
class SpatialColumn < ConnectionAdapters::PostgreSQLColumn # :nodoc:
|
320
|
-
|
321
|
-
|
322
|
-
def initialize(name_, default_, sql_type_=nil, null_=true, opts_=nil)
|
323
|
-
super(name_, default_, sql_type_, null_)
|
324
|
-
@geographic = sql_type_ =~ /^geography/ ? true : false
|
325
|
-
if opts_
|
326
|
-
@geometric_type = ::RGeo::ActiveRecord::Common.geometric_type_from_name(opts_[:type])
|
327
|
-
@srid = opts_[:srid].to_i
|
328
|
-
@has_z = opts_[:has_z]
|
329
|
-
@has_m = opts_[:has_m]
|
330
|
-
elsif @geographic
|
331
|
-
if sql_type_ =~ /geography\((\w+[^,zm])(z?)(m?),(\d+)\)/i
|
332
|
-
@has_z = $2.length > 0
|
333
|
-
@has_m = $3.length > 0
|
334
|
-
@srid = $4.to_i
|
335
|
-
@geometric_type = ::RGeo::ActiveRecord::Common.geometric_type_from_name($1)
|
336
|
-
else
|
337
|
-
@geometric_type = ::RGeo::Feature::Geometry
|
338
|
-
@srid = 4326
|
339
|
-
@has_z = @has_m = false
|
340
|
-
end
|
341
|
-
else
|
342
|
-
@geometric_type = @has_z = @has_m = nil
|
343
|
-
@srid = 0
|
344
|
-
end
|
345
|
-
@ar_class = ::ActiveRecord::Base
|
346
|
-
end
|
347
|
-
|
348
|
-
|
349
|
-
def set_ar_class(val_)
|
350
|
-
@ar_class = val_
|
351
|
-
end
|
352
|
-
|
353
|
-
|
354
|
-
attr_reader :srid
|
355
|
-
attr_reader :geometric_type
|
356
|
-
attr_reader :has_z
|
357
|
-
attr_reader :has_m
|
358
|
-
|
359
|
-
|
360
|
-
def spatial?
|
361
|
-
type == :geometry
|
362
|
-
end
|
363
|
-
|
364
|
-
|
365
|
-
def geographic?
|
366
|
-
@geographic
|
367
|
-
end
|
368
|
-
|
369
|
-
|
370
|
-
def klass
|
371
|
-
type == :geometry ? ::RGeo::Feature::Geometry : super
|
372
|
-
end
|
373
|
-
|
374
|
-
|
375
|
-
def type_cast(value_)
|
376
|
-
type == :geometry ? SpatialColumn.string_to_geometry(value_, @ar_class, @geographic, @srid, @has_z, @has_m) : super
|
377
|
-
end
|
378
|
-
|
379
|
-
|
380
|
-
def type_cast_code(var_name_)
|
381
|
-
type == :geometry ? "::ActiveRecord::ConnectionAdapters::PostGisAdapter::SpatialColumn.string_to_geometry(#{var_name_}, self.class, #{@geographic ? 'true' : 'false'}, #{@srid.inspect}, #{@has_z ? 'true' : 'false'}, #{@has_m ? 'true' : 'false'})" : super
|
382
|
-
end
|
383
|
-
|
384
|
-
|
385
|
-
private
|
386
|
-
|
387
|
-
|
388
|
-
def simplified_type(sql_type_)
|
389
|
-
sql_type_ =~ /geography|geometry|point|linestring|polygon/i ? :geometry : super
|
390
|
-
end
|
391
|
-
|
392
|
-
|
393
|
-
def self.string_to_geometry(str_, ar_class_, geographic_, srid_, has_z_, has_m_)
|
394
|
-
case str_
|
395
|
-
when ::RGeo::Feature::Geometry
|
396
|
-
str_
|
397
|
-
when ::String
|
398
|
-
if str_.length == 0
|
399
|
-
nil
|
400
|
-
else
|
401
|
-
factory_ = ar_class_.rgeo_factory_generator.call(:srid => srid_, :has_z_coordinate => has_z_, :has_m_coordinate => has_m_, :geographic => geographic_)
|
402
|
-
marker_ = str_[0,1]
|
403
|
-
if marker_ == "\x00" || marker_ == "\x01"
|
404
|
-
::RGeo::WKRep::WKBParser.new(factory_, :support_ewkb => true).parse(str_) rescue nil
|
405
|
-
elsif str_[0,4] =~ /[0-9a-fA-F]{4}/
|
406
|
-
::RGeo::WKRep::WKBParser.new(factory_, :support_ewkb => true).parse_hex(str_) rescue nil
|
407
|
-
else
|
408
|
-
::RGeo::WKRep::WKTParser.new(factory_, :support_ewkt => true).parse(str_) rescue nil
|
409
|
-
end
|
410
|
-
end
|
411
|
-
else
|
412
|
-
nil
|
413
|
-
end
|
414
|
-
end
|
415
|
-
|
416
|
-
|
417
|
-
end
|
418
|
-
|
419
|
-
|
420
|
-
end
|
421
|
-
|
422
|
-
|
423
|
-
end
|
424
|
-
|
425
|
-
|
426
|
-
end
|