]> git.openstreetmap.org Git - rails.git/blobdiff - app/controllers/amf_controller.rb
fixing version problem for way_tags
[rails.git] / app / controllers / amf_controller.rb
index 093f863a71f7d07455e6b8062a0ffb8cab1399f8..9564a1bdf79ff974d2e7b073ea411d699b34309c 100644 (file)
@@ -35,10 +35,10 @@ class AmfController < ApplicationController
 
       case message
       when 'getpresets';       results[index]=putdata(index,getpresets)
-      when 'whichways';        results[index]=putdata(index,whichways(args))
+      when 'whichways';                results[index]=putdata(index,whichways(args))
       when 'getway';           results[index]=putdata(index,getway(args))
       when 'putway';           results[index]=putdata(index,putway(args))
-      when 'deleteway';        results[index]=putdata(index,deleteway(args))
+      when 'deleteway';                results[index]=putdata(index,deleteway(args))
       end
     end
 
@@ -195,8 +195,8 @@ EOF
   end
 
   # -----      getway (objectname, way, baselong, basey, masterscale)
-  #            returns objectname, array of co-ordinates, attributes,
-  #                            xmin,xmax,ymin,ymax
+  #                    returns objectname, array of co-ordinates, attributes,
+  #                                    xmin,xmax,ymin,ymax
 
   def getway(args)
     objname,wayid,baselong,basey,masterscale=args
@@ -226,15 +226,16 @@ EOF
   end
 
   # -----      putway (user token, way, array of co-ordinates, array of attributes,
-  #                            baselong, basey, masterscale)
-  #            returns current way ID, new way ID, hash of renumbered nodes,
-  #                            xmin,xmax,ymin,ymax
+  #                                    baselong, basey, masterscale)
+  #                    returns current way ID, new way ID, hash of renumbered nodes,
+  #                                    xmin,xmax,ymin,ymax
 
   def putway(args)
     usertoken,originalway,points,attributes,baselong,basey,masterscale=args
     uid=getuserid(usertoken)
     return if !uid
     db_uqs='uniq'+uid.to_s+originalway.to_i.abs.to_s+Time.new.to_i.to_s        # temp uniquesegments table name, typically 51 chars
+    db_uqn='unin'+uid.to_s+originalway.to_i.abs.to_s+Time.new.to_i.to_s        # temp uniquenodes table name, typically 51 chars
     db_now='@now'+uid.to_s+originalway.to_i.abs.to_s+Time.new.to_i.to_s        # 'now' variable name, typically 51 chars
     ActiveRecord::Base.connection.execute("SET #{db_now}=NOW()")
     originalway=originalway.to_i
@@ -249,6 +250,7 @@ EOF
         id2=row['id2'].to_i; xc[id2]=row['long2'].to_f; yc[id2]=row['lat2'].to_f; tagc[id2]=row['tags2']
         seg[row['segment_id'].to_i]=id1.to_s+'-'+id2.to_s
       }
+         ActiveRecord::Base.connection.update("UPDATE current_ways SET timestamp=#{db_now},user_id=#{uid},visible=1 WHERE id=#{way}")
     else
       way=ActiveRecord::Base.connection.insert("INSERT INTO current_ways (user_id,timestamp,visible) VALUES (#{uid},#{db_now},1)")
     end
@@ -261,7 +263,7 @@ EOF
 
     xmin = ymin = 999999
     xmax = ymax = -999999
-    insertsql = nodelist =  ''
+    insertsql = ''
     renumberednodes={}
 
     points.each_index do |i|
@@ -277,7 +279,7 @@ EOF
       if node<0
         # new node - create
         newnode=ActiveRecord::Base.connection.insert("INSERT INTO current_nodes (   latitude,longitude,timestamp,user_id,visible,tags) VALUES (           #{ys},#{xs},#{db_now},#{uid},1,#{tagsql})")
-        ActiveRecord::Base.connection.insert("INSERT INTO nodes         (id,latitude,longitude,timestamp,user_id,visible,tags) VALUES (#{newnode},#{ys},#{xs},#{db_now},#{uid},1,#{tagsql})")
+                       ActiveRecord::Base.connection.insert("INSERT INTO nodes         (id,latitude,longitude,timestamp,user_id,visible,tags) VALUES (#{newnode},#{ys},#{xs},#{db_now},#{uid},1,#{tagsql})")
         points[i][2]=newnode
         renumberednodes[node.to_s]=newnode.to_s
 
@@ -286,24 +288,18 @@ EOF
         if (xs!=xc[node] or (ys/0.0000001).round!=(yc[node]/0.0000001).round or tagstr!=tagc[node])
           ActiveRecord::Base.connection.insert("INSERT INTO nodes (id,latitude,longitude,timestamp,user_id,visible,tags) VALUES (#{node},#{ys},#{xs},#{db_now},#{uid},1,#{tagsql})")
           ActiveRecord::Base.connection.update("UPDATE current_nodes SET latitude=#{ys},longitude=#{xs},timestamp=#{db_now},user_id=#{uid},tags=#{tagsql},visible=1 WHERE id=#{node}")
-        else
-          if (nodelist!='') then nodelist+=',' end; nodelist+=node.to_s
         end
       else
         # old node, created in another way and now added to this way
-        if (nodelist!='') then nodelist+=',' end; nodelist+=node.to_s
       end
 
     end
 
-    if nodelist!='' then
-      ActiveRecord::Base.connection.update("UPDATE current_nodes SET timestamp=#{db_now},user_id=#{uid},visible=1 WHERE id IN (#{nodelist})")
-    end
 
     # -- 6.i compare segments
 
     numberedsegments={}
-    seglist=''
+    seglist=''                         # list of existing segments that we want to keep
     for i in (0..(points.length-2))
       if (points[i+1][3].to_i==0) then next end
       segid=points[i+1][5].to_i
@@ -316,72 +312,55 @@ EOF
         end
       end
       segid=ActiveRecord::Base.connection.insert("INSERT INTO current_segments (   node_a,node_b,timestamp,user_id,visible,tags) VALUES (         #{from},#{to},#{db_now},#{uid},1,'')")
-      ActiveRecord::Base.connection.insert("INSERT INTO segments         (id,node_a,node_b,timestamp,user_id,visible,tags) VALUES (#{segid},#{from},#{to},#{db_now},#{uid},1,'')")
+               ActiveRecord::Base.connection.insert("INSERT INTO segments         (id,node_a,node_b,timestamp,user_id,visible,tags) VALUES (#{segid},#{from},#{to},#{db_now},#{uid},1,'')")
       points[i+1][5]=segid
       numberedsegments[(i+1).to_s]=segid.to_s
     end
     # numberedsegments.each{|a,b| RAILS_DEFAULT_LOGGER.error("Sending back: seg no. #{a} -> id #{b}") }
 
-    if seglist!='' then
-      ActiveRecord::Base.connection.update("UPDATE current_segments SET timestamp=#{db_now},user_id=#{uid},visible=1 WHERE id IN (#{seglist})")
-    end
-
 
     # -- 6.ii insert new way segments
 
-    createuniquesegments(way,db_uqs)
+    createuniquesegments(way,db_uqs,seglist)   # segments which appear in this way but no other
 
-    # a=''
-    # ActiveRecord::Base.connection.select_values("SELECT segment_id FROM #{db_uqs}").each {|b| a+=b+',' }
-    # RAILS_DEFAULT_LOGGER.error("Unique segments are #{a}")
-    # a=ActiveRecord::Base.connection.select_value("SELECT #{db_now}")
-    # RAILS_DEFAULT_LOGGER.error("Timestamp of this edit is #{a}")
-    # RAILS_DEFAULT_LOGGER.error("Userid of this edit is #{uid}")
-
-    #          delete nodes from uniquesegments (and not in modified way)
+    #          delete segments from uniquesegments (and not in modified way)
 
     sql=<<-EOF
-      INSERT INTO nodes (id,latitude,longitude,timestamp,user_id,visible)  
-      SELECT DISTINCT cn.id,cn.latitude,cn.longitude,#{db_now},#{uid},0 
-        FROM current_nodes AS cn, 
-           current_segments AS cs,
-           #{db_uqs} AS us 
-       WHERE(cn.id=cs.node_a OR cn.id=cs.node_b) 
-         AND cs.id=us.segment_id AND cs.visible=1 
-         AND (cn.timestamp!=#{db_now} OR cn.user_id!=#{uid})
+      INSERT INTO segments (id,node_a,node_b,timestamp,user_id,visible) 
+      SELECT DISTINCT segment_id,node_a,node_b,#{db_now},#{uid},0
+        FROM current_segments AS cs, #{db_uqs} AS us
+       WHERE cs.id=us.segment_id AND cs.visible=1 
     EOF
     ActiveRecord::Base.connection.insert(sql)
 
     sql=<<-EOF
-      UPDATE current_nodes AS cn, 
-           current_segments AS cs, 
-           #{db_uqs} AS us 
-         SET cn.timestamp=#{db_now},cn.visible=0,cn.user_id=#{uid} 
-       WHERE (cn.id=cs.node_a OR cn.id=cs.node_b) 
-         AND cs.id=us.segment_id AND cs.visible=1 
-         AND (cn.timestamp!=#{db_now} OR cn.user_id!=#{uid})
+         UPDATE current_segments AS cs, #{db_uqs} AS us
+          SET cs.timestamp=#{db_now},cs.visible=0,cs.user_id=#{uid} 
+        WHERE cs.id=us.segment_id AND cs.visible=1 
     EOF
     ActiveRecord::Base.connection.update(sql)
 
-    #          delete segments from uniquesegments (and not in modified way)
+    #          delete nodes not in modified way or any other segments
+
+    createuniquenodes(db_uqs,db_uqn)   # nodes which appear in this way but no other
 
     sql=<<-EOF
-      INSERT INTO segments (id,node_a,node_b,timestamp,user_id,visible) 
-      SELECT DISTINCT segment_id,node_a,node_b,#{db_now},#{uid},0
-        FROM current_segments AS cs, #{db_uqs} AS us
-       WHERE cs.id=us.segment_id AND cs.visible=1 
-         AND (cs.timestamp!=#{db_now} OR cs.user_id!=#{uid})
+               INSERT INTO nodes (id,latitude,longitude,timestamp,user_id,visible)  
+               SELECT DISTINCT cn.id,cn.latitude,cn.longitude,#{db_now},#{uid},0 
+                 FROM current_nodes AS cn,#{db_uqn}
+                WHERE cn.id=node_id
     EOF
     ActiveRecord::Base.connection.insert(sql)
 
     sql=<<-EOF
-         UPDATE current_segments AS cs, #{db_uqs} AS us
-          SET cs.timestamp=#{db_now},cs.visible=0,cs.user_id=#{uid} 
-        WHERE cs.id=us.segment_id AND cs.visible=1 
-          AND (cs.timestamp!=#{db_now} OR cs.user_id!=#{uid})
+      UPDATE current_nodes AS cn, #{db_uqn}
+         SET cn.timestamp=#{db_now},cn.visible=0,cn.user_id=#{uid} 
+       WHERE cn.id=node_id
     EOF
     ActiveRecord::Base.connection.update(sql)
+
     ActiveRecord::Base.connection.execute("DROP TABLE #{db_uqs}")
+    ActiveRecord::Base.connection.execute("DROP TABLE #{db_uqn}")
 
     #          insert new version of route into way_segments
 
@@ -410,7 +389,7 @@ EOF
       if v[0,6]=='(type ' then next end
       if insertsql !='' then insertsql +=',' end
       if currentsql!='' then currentsql+=',' end
-      insertsql +="(#{way},'"+sqlescape(k)+"','"+sqlescape(v)+"',version)"
+      insertsql +="(#{way},'"+sqlescape(k)+"','"+sqlescape(v)+"',#{version})"
       currentsql+="(#{way},'"+sqlescape(k)+"','"+sqlescape(v)+"')"
     end
 
@@ -422,65 +401,66 @@ EOF
   end
 
   # -----      deleteway (user token, way)
-  #            returns way ID only
+  #                    returns way ID only
 
   def deleteway(args)
     usertoken,way=args
     uid=getuserid(usertoken); if !uid then return end
-  way=way.to_i
-
-  db_uqs='uniq'+uid.to_s+way.to_i.abs.to_s+Time.new.to_i.to_s  # temp uniquesegments table name, typically 51 chars
-  db_now='@now'+uid.to_s+way.to_i.abs.to_s+Time.new.to_i.to_s  # 'now' variable name, typically 51 chars
-  ActiveRecord::Base.connection.execute("SET #{db_now}=NOW()")
-  createuniquesegments(way,db_uqs)
-
-  sql=<<-EOF
-      INSERT INTO nodes (id,latitude,longitude,timestamp,user_id,visible) 
-      SELECT DISTINCT cn.id,cn.latitude,cn.longitude,#{db_now},#{uid},0 
-        FROM current_nodes AS cn, 
-           current_segments AS cs, 
-           #{db_uqs} AS us
-       WHERE (cn.id=cs.node_a OR cn.id=cs.node_b) 
-         AND cs.id=us.segment_id
-    EOF
-  ActiveRecord::Base.connection.insert(sql)
+       way=way.to_i
 
-  sql=<<-EOF
-      UPDATE current_nodes AS cn, 
-           current_segments AS cs, 
-           #{db_uqs} AS us
-         SET cn.timestamp=#{db_now},cn.visible=0,cn.user_id=#{uid} 
-       WHERE (cn.id=cs.node_a OR cn.id=cs.node_b) 
-         AND cs.id=us.segment_id
-    EOF
-  ActiveRecord::Base.connection.update(sql)
+       db_uqs='uniq'+uid.to_s+way.to_i.abs.to_s+Time.new.to_i.to_s     # temp uniquesegments table name, typically 51 chars
+       db_uqn='unin'+uid.to_s+way.to_i.abs.to_s+Time.new.to_i.to_s     # temp uniquenodes table name, typically 51 chars
+       db_now='@now'+uid.to_s+way.to_i.abs.to_s+Time.new.to_i.to_s     # 'now' variable name, typically 51 chars
+       ActiveRecord::Base.connection.execute("SET #{db_now}=NOW()")
+       createuniquesegments(way,db_uqs,'')
 
-  # -  delete any otherwise unused segments
+       # -     delete any otherwise unused segments
 
-  sql=<<-EOF
+       sql=<<-EOF
       INSERT INTO segments (id,node_a,node_b,timestamp,user_id,visible) 
       SELECT DISTINCT segment_id,node_a,node_b,#{db_now},#{uid},0 
         FROM current_segments AS cs, #{db_uqs} AS us
        WHERE cs.id=us.segment_id
     EOF
-  ActiveRecord::Base.connection.insert(sql)
+       ActiveRecord::Base.connection.insert(sql)
 
-  sql=<<-EOF
+       sql=<<-EOF
       UPDATE current_segments AS cs, #{db_uqs} AS us
          SET cs.timestamp=#{db_now},cs.visible=0,cs.user_id=#{uid} 
        WHERE cs.id=us.segment_id
     EOF
-  ActiveRecord::Base.connection.update(sql)
-  ActiveRecord::Base.connection.execute("DROP TABLE #{db_uqs}")
+       ActiveRecord::Base.connection.update(sql)
 
-  # - delete way
+       # - delete any unused nodes
+  
+    createuniquenodes(db_uqs,db_uqn)
 
-  ActiveRecord::Base.connection.insert("INSERT INTO ways (id,user_id,timestamp,visible) VALUES (#{way},#{uid},#{db_now},0)")
-  ActiveRecord::Base.connection.update("UPDATE current_ways SET user_id=#{uid},timestamp=#{db_now},visible=0 WHERE id=#{way}")
-  ActiveRecord::Base.connection.execute("DELETE FROM current_way_segments WHERE id=#{way}")
-  ActiveRecord::Base.connection.execute("DELETE FROM current_way_tags WHERE id=#{way}")
+       sql=<<-EOF
+               INSERT INTO nodes (id,latitude,longitude,timestamp,user_id,visible)  
+               SELECT DISTINCT cn.id,cn.latitude,cn.longitude,#{db_now},#{uid},0 
+                 FROM current_nodes AS cn,#{db_uqn}
+                WHERE cn.id=node_id
+    EOF
+       ActiveRecord::Base.connection.insert(sql)
 
-  way
+       sql=<<-EOF
+      UPDATE current_nodes AS cn, #{db_uqn}
+         SET cn.timestamp=#{db_now},cn.visible=0,cn.user_id=#{uid} 
+       WHERE cn.id=node_id
+    EOF
+       ActiveRecord::Base.connection.update(sql)
+       
+       ActiveRecord::Base.connection.execute("DROP TABLE #{db_uqs}")
+       ActiveRecord::Base.connection.execute("DROP TABLE #{db_uqn}")
+
+       # - delete way
+       
+       ActiveRecord::Base.connection.insert("INSERT INTO ways (id,user_id,timestamp,visible) VALUES (#{way},#{uid},#{db_now},0)")
+       ActiveRecord::Base.connection.update("UPDATE current_ways SET user_id=#{uid},timestamp=#{db_now},visible=0 WHERE id=#{way}")
+       ActiveRecord::Base.connection.execute("DELETE FROM current_way_segments WHERE id=#{way}")
+       ActiveRecord::Base.connection.execute("DELETE FROM current_way_tags WHERE id=#{way}")
+       
+       way
 end
 
 # ====================================================================
@@ -492,11 +472,14 @@ def readwayquery(id)
       "    FROM current_way_segments,current_segments,current_nodes AS n1,current_nodes AS n2 "+
       "   WHERE current_way_segments.id=#{id} "+
       "     AND segment_id=current_segments.id "+
+         "     AND current_segments.visible=1 "+
       "     AND n1.id=node_a and n2.id=node_b "+
+      "     AND n1.visible=1 AND n2.visible=1 "+
       "   ORDER BY sequence_id"
 end
 
-def createuniquesegments(way,uqs_name)
+def createuniquesegments(way,uqs_name,seglist)
+  # Finds segments which appear in (previous version of) this way and no other
   sql=<<-EOF
       CREATE TEMPORARY TABLE #{uqs_name}
               SELECT a.segment_id
@@ -507,9 +490,28 @@ def createuniquesegments(way,uqs_name)
                  AND b.id != #{way}
                WHERE b.segment_id IS NULL
     EOF
+  if (seglist!='') then sql+=" AND a.segment_id NOT IN (#{seglist})" end
   ActiveRecord::Base.connection.execute(sql)
 end
 
+def createuniquenodes(uqs_name,uqn_name)
+       # Finds nodes which appear in uniquesegments but no other segments
+       sql=<<-EOF
+               CREATE TEMPORARY TABLE #{uqn_name}
+                          SELECT DISTINCT node_id
+                             FROM (SELECT cn.id AS node_id
+                                                 FROM current_nodes AS cn,
+                                                      current_segments AS cs,
+                                                      #{uqs_name} AS us
+                                                WHERE cs.id=us.segment_id
+                                                  AND (cn.id=cs.node_a OR cn.id=cs.node_b)) AS n
+                                        LEFT JOIN current_segments AS cs2 ON node_id=cs2.node_a AND cs2.visible=1
+                                        LEFT JOIN current_segments AS cs3 ON node_id=cs3.node_b AND cs3.visible=1
+                                            WHERE cs2.node_a IS NULL
+                                              AND cs3.node_b IS NULL
+       EOF
+       ActiveRecord::Base.connection.execute(sql)
+end
 
 def sqlescape(a)
   a.gsub("'","''").gsub(92.chr,92.chr+92.chr)
@@ -542,9 +544,9 @@ end
 def getuserid(token)
   token=sqlescape(token)
   if (token=~/^(.+)\+(.+)$/) then
-    return ActiveRecord::Base.connection.select_value("SELECT id FROM users WHERE active=1 AND timeout>NOW() AND email='#{$1}' AND pass_crypt=MD5('#{$2}')")
+    return ActiveRecord::Base.connection.select_value("SELECT id FROM users WHERE active=1 AND email='#{$1}' AND pass_crypt=MD5('#{$2}')")
   else
-    return ActiveRecord::Base.connection.select_value("SELECT id FROM users WHERE active=1 AND timeout>NOW() AND token='#{token}'")
+    return ActiveRecord::Base.connection.select_value("SELECT id FROM users WHERE active=1 AND token='#{token}'")
   end
 end