Skip to content

Commit 293b8d0

Browse files
authoredJul 21, 2016
Merge pull request #9013 from CartoDB/8958-arcgis-oids
Fix incorrect querying of object ids in ArcGIS connector
2 parents 921358b + 3eb11dc commit 293b8d0

File tree

3 files changed

+29
-7
lines changed

3 files changed

+29
-7
lines changed
 

‎services/datasources/lib/datasources/url/arcgis.rb

+25-4
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@ class ArcGIS < BaseDirectStream
4444
# Used to display more data only (for local debugging purposes)
4545
DEBUG = false
4646

47+
VECTOR_LAYER_TYPE = 'Feature Layer'.freeze
48+
OID_FIELD_TYPE = 'esriFieldTypeOID'.freeze
49+
4750
attr_reader :metadata
4851

4952
# Constructor
@@ -249,8 +252,15 @@ def get_subresource_metadata(id, subresource_id)
249252
# non-rails symbolize keys
250253
data = ::JSON.parse(response.body).inject({}){|memo,(k,v)| memo[k.to_sym] = v; memo}
251254

255+
raise ResponseError.new("Invalid layer type: '#{data[:type]}'") if data[:type] != VECTOR_LAYER_TYPE
252256
raise ResponseError.new("Missing data: 'fields'") if data[:fields].nil?
253257

258+
if data[:supportedQueryFormats].present?
259+
supported_formats = data.fetch(:supportedQueryFormats).gsub(' ', '').split(',')
260+
else
261+
supported_formats = []
262+
end
263+
254264
begin
255265
@metadata = {
256266
arcgis_version: data.fetch(:currentVersion),
@@ -259,14 +269,14 @@ def get_subresource_metadata(id, subresource_id)
259269
type: data.fetch(:type),
260270
geometry_type: data.fetch(:geometryType),
261271
copyright: data.fetch(:copyrightText, ''),
262-
fields: data.fetch(:fields).map{ |field|
272+
fields: data.fetch(:fields).try(:map) { |field|
263273
{
264274
name: field['name'],
265275
type: field['type']
266276
}
267277
},
268278
max_records_per_query: data.fetch(:maxRecordCount, 500),
269-
supported_formats: data.fetch(:supportedQueryFormats).gsub(' ', '').split(','),
279+
supported_formats: supported_formats,
270280
advanced_queries_supported: data.fetch(:supportsAdvancedQueries, false)
271281
}
272282
rescue => exception
@@ -337,6 +347,9 @@ def get_layers_list(url)
337347
raise ResponseError.new("Missing data: #{exception.to_s} #{request_url} #{exception.backtrace}")
338348
end
339349

350+
# We only support vector layers (not raster layers)
351+
data = data.reject { |layer| layer['type'] != VECTOR_LAYER_TYPE }
352+
340353
raise ResponseError.new("Empty layers list #{request_url}") if data.length == 0
341354

342355
begin
@@ -388,10 +401,18 @@ def get_by_ids(url, ids, fields)
388401
raise InvalidInputDataError.new("'ids' empty or invalid") if (ids.nil? || ids.length == 0)
389402
raise InvalidInputDataError.new("'fields' empty or invalid") if (fields.nil? || fields.length == 0)
390403

404+
oid_field = fields.find { |field| field[:type] == OID_FIELD_TYPE }
405+
391406
if ids.length == 1
392-
ids_field = {objectIds: ids.first}
407+
ids_field = { objectIds: ids.first }
393408
else
394-
ids_field = {where: "OBJECTID >=#{ids.first} AND OBJECTID <=#{ids.last}"}
409+
if oid_field
410+
# Note that ids is sorted
411+
ids_field = { where: "#{oid_field[:name]} >=#{ids.first} AND #{oid_field[:name]} <=#{ids.last}" }
412+
else
413+
# This could be innefficient with large number of ids, but it is limited to MAX_BLOCK_SIZE
414+
ids_field = { objectIds: ids.join(',') }
415+
end
395416
end
396417

397418
prepared_fields = Addressable::URI.encode(fields.map { |field| "#{field[:name]}" }.join(','))
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
{"layers":[
2-
{"id":0, "name":"first layer"}
3-
]}
2+
{"id":0, "name":"first layer", "type":"Feature Layer"}
3+
]}

‎services/datasources/spec/unit/arcgis_spec.rb

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# encoding: utf-8
22

3+
require 'active_support/core_ext'
4+
35
require_relative '../../lib/datasources'
46
require_relative '../doubles/user'
57

@@ -519,4 +521,3 @@
519521
end
520522
end
521523
end
522-

0 commit comments

Comments
 (0)