Cope with empty areas better.
[rails.git] / app / controllers / search_controller.rb
1 class SearchController < ApplicationController
2   # Support searching for nodes, ways, or all
3   # Can search by tag k, v, or both (type->k,value->v)
4   # Can search by name (k=name,v=....)
5
6   after_filter :compress_output
7
8   def search_all
9     do_search(true,true,true)
10   end
11
12   def search_ways
13     do_search(true,false,false)
14   end
15   def search_nodes
16     do_search(false,true,false)
17   end
18   def search_relations
19     do_search(false,false,true)
20   end
21
22   def do_search(do_ways,do_nodes,do_relations)
23     type = params['type']
24     value = params['value']
25     unless type or value
26       name = params['name']
27       if name
28         type = 'name'
29         value = name
30       end
31     end
32
33     way_ids = Array.new
34     ways = Array.new
35     nodes = Array.new
36     relations = Array.new
37
38     # Matching for tags table
39     cond_way = Array.new
40     sql = 'id IN (SELECT id FROM current_way_tags WHERE 1=1'
41     if type
42       sql += ' AND k=?'
43       cond_way += [type]
44     end
45     if value
46       sql += ' AND v=?'
47       cond_way += [value]
48     end
49     sql += ')'
50     cond_way = [sql] + cond_way
51
52     # Matching for tags table
53     cond_rel = Array.new
54     sql = 'id IN (SELECT id FROM current_relation_tags WHERE 1=1'
55     if type
56       sql += ' AND k=?'
57       cond_rel += [type]
58     end
59     if value
60       sql += ' AND v=?'
61       cond_rel += [value]
62     end
63     sql += ')'
64     cond_rel = [sql] + cond_rel
65
66     # Matching for tags column
67     if type and value
68       cond_tags = ['tags LIKE ? OR tags LIKE ? OR tags LIKE ? OR tags LIKE ?', 
69       ''+type+'='+value+'',
70       ''+type+'='+value+';%',
71       '%;'+type+'='+value+';%',
72       '%;'+type+'='+value+'' ]
73     elsif type
74       cond_tags = ['tags LIKE ? OR tags LIKE ?',
75       ''+type+'=%',
76       '%;'+type+'=%' ]
77     elsif value
78       cond_tags = ['tags LIKE ? OR tags LIKE ?',
79       '%='+value+';%',
80       '%='+value+'' ]
81     else
82       cond_tags = ['1=1']
83     end
84
85     # First up, look for the relations we want
86     if do_relations
87       relations = Relation.find(:all, :conditions => cond_rel, :limit => 100)
88     end
89
90     # then ways
91     if do_ways
92       ways = Way.find(:all, :conditions => cond_way, :limit => 100)
93     end
94
95     # Now, nodes
96     if do_nodes
97       nodes = Node.find(:all, :conditions => cond_tags, :limit => 2000)
98     end
99
100     # Fetch any node needed for our ways (only have matching nodes so far)
101     nodes += Node.find(ways.collect { |w| w.nds }.uniq)
102
103     # Print
104     user_display_name_cache = {}
105     doc = OSM::API.new.get_xml_doc
106     nodes.each do |node|
107       doc.root << node.to_xml_node(user_display_name_cache)
108     end
109
110     ways.each do |way|
111       doc.root << way.to_xml_node(user_display_name_cache)
112     end 
113
114     relations.each do |rel|
115       doc.root << rel.to_xml_node(user_display_name_cache)
116     end 
117     render :text => doc.to_s, :content_type => "text/xml"
118   end
119 end