From: Shaun McDonald Date: Sat, 8 Nov 2008 11:52:58 +0000 (+0000) Subject: Resyncing from head 10895:11795 X-Git-Tag: live~7687^2~205 X-Git-Url: https://git.openstreetmap.org/rails.git/commitdiff_plain/bf29550db840c97cafffbe1e836750bef6c7942d?hp=-c Resyncing from head 10895:11795 --- bf29550db840c97cafffbe1e836750bef6c7942d diff --combined app/controllers/diary_entry_controller.rb index a965af2ff,e0d6e44cd..d9f5e4253 --- a/app/controllers/diary_entry_controller.rb +++ b/app/controllers/diary_entry_controller.rb @@@ -54,7 -54,7 +54,7 @@@ class DiaryEntryController < Applicatio def list if params[:display_name] - @this_user = User.find_by_display_name(params[:display_name], :conditions => "visible = 1") + @this_user = User.find_by_display_name(params[:display_name], :conditions => {:visible => true}) if @this_user @title = @this_user.display_name + "'s diary" @@@ -69,7 -69,8 +69,8 @@@ end else @title = "Users' diaries" - @entry_pages, @entries = paginate(:diary_entries, + @entry_pages, @entries = paginate(:diary_entries, :include => :user, + :conditions => "users.visible = 1", :order => 'created_at DESC', :per_page => 20) end @@@ -77,7 -78,7 +78,7 @@@ def rss if params[:display_name] - user = User.find_by_display_name(params[:display_name], :conditions => "visible = 1") + user = User.find_by_display_name(params[:display_name], :conditions => {:visible => true}) if user @entries = DiaryEntry.find(:all, :conditions => ['user_id = ?', user.id], :order => 'created_at DESC', :limit => 20) @@@ -90,7 -91,9 +91,9 @@@ render :nothing => true, :status => :not_found end else - @entries = DiaryEntry.find(:all, :order => 'created_at DESC', :limit => 20) + @entries = DiaryEntry.find(:all, :include => :user, + :conditions => "users.visible = 1", + :order => 'created_at DESC', :limit => 20) @title = "OpenStreetMap diary entries" @description = "Recent diary entries from users of OpenStreetMap" @link = "http://www.openstreetmap.org/diary" @@@ -100,7 -103,7 +103,7 @@@ end def view - user = User.find_by_display_name(params[:display_name], :conditions => "visible = 1") + user = User.find_by_display_name(params[:display_name], :conditions => {:visible => true}) if user @entry = DiaryEntry.find(:first, :conditions => ['user_id = ? AND id = ?', user.id, params[:id]]) diff --combined app/controllers/user_controller.rb index 196d5cea6,c658b2014..b9ed54096 --- a/app/controllers/user_controller.rb +++ b/app/controllers/user_controller.rb @@@ -16,6 -16,7 +16,7 @@@ class UserController < ApplicationContr @user.visible = true @user.data_public = true @user.description = "" if @user.description.nil? + @user.creation_ip = request.remote_ip if @user.save flash[:notice] = "User was successfully created. Check your email for a confirmation note, and you\'ll be mapping in no time :-)
Please note that you won't be able to login until you've received and confirmed your email address." @@@ -76,7 -77,7 +77,7 @@@ def lost_password @title = 'lost password' if params[:user] and params[:user][:email] - user = User.find_by_email(params[:user][:email], :conditions => "visible = 1") + user = User.find_by_email(params[:user][:email], :conditions => {:visible => true}) if user token = user.tokens.create @@@ -216,7 -217,7 +217,7 @@@ end def view - @this_user = User.find_by_display_name(params[:display_name], :conditions => "visible = 1") + @this_user = User.find_by_display_name(params[:display_name], :conditions => {:visible => true}) if @this_user @title = @this_user.display_name @@@ -229,7 -230,7 +230,7 @@@ def make_friend if params[:display_name] name = params[:display_name] - new_friend = User.find_by_display_name(name, :conditions => "visible = 1") + new_friend = User.find_by_display_name(name, :conditions => {:visible => true}) friend = Friend.new friend.user_id = @user.id friend.friend_user_id = new_friend.id @@@ -251,7 -252,7 +252,7 @@@ def remove_friend if params[:display_name] name = params[:display_name] - friend = User.find_by_display_name(name, :conditions => "visible = 1") + friend = User.find_by_display_name(name, :conditions => {:visible => true}) if @user.is_friends_with?(friend) Friend.delete_all "user_id = #{@user.id} AND friend_user_id = #{friend.id}" flash[:notice] = "#{friend.display_name} was removed from your friends." diff --combined app/models/diary_entry.rb index fe48ee8dc,dd1f9882a..c20788fbb --- a/app/models/diary_entry.rb +++ b/app/models/diary_entry.rb @@@ -1,10 -1,10 +1,12 @@@ class DiaryEntry < ActiveRecord::Base belongs_to :user - has_many :diary_comments, :order => "id" + has_many :diary_comments, :include => :user, + :conditions => "users.visible = 1", + :order => "diary_comments.id" validates_presence_of :title, :body + validates_length_of :title, :within => 1..255 + validates_length_of :language, :within => 2..3 validates_numericality_of :latitude, :allow_nil => true validates_numericality_of :longitude, :allow_nil => true validates_associated :user diff --combined app/views/browse/start.rjs index e257005a3,c17325ad1..f38b1dc80 --- a/app/views/browse/start.rjs +++ b/app/views/browse/start.rjs @@@ -15,6 -15,8 +15,8 @@@ page << < 0.25) { setStatus("Unable to load: Bounding box size of " + size + " is too large (must be smaller than 0.25)"); } else { - loadGML("/api/0.5/map?bbox=" + projected.toBBOX()); + loadGML("/api/#{API_VERSION}/map?bbox=" + projected.toBBOX()); } } @@@ -223,8 -223,8 +223,8 @@@ map.addLayer(browseDataLayer); browseSelectControl = new OpenLayers.Control.SelectFeature(browseDataLayer, { onSelect: onFeatureSelect }); - browseSelectControl.handler.stopDown = false; - browseSelectControl.handler.stopUp = false; + browseSelectControl.handlers.feature.stopDown = false; + browseSelectControl.handlers.feature.stopUp = false; map.addControl(browseSelectControl); browseSelectControl.activate(); } else { @@@ -393,7 -393,7 +393,7 @@@ this.link.href = ""; this.link.innerHTML = "Wait..."; - new Ajax.Request("/api/0.5/" + this.type + "/" + this.feature.osm_id + "/history", { + new Ajax.Request("/api/#{API_VERSION}/" + this.type + "/" + this.feature.osm_id + "/history", { onComplete: OpenLayers.Function.bind(displayHistory, this) }); diff --combined config/routes.rb index 139611bc6,b7d570980..91130b9b0 --- a/config/routes.rb +++ b/config/routes.rb @@@ -1,19 -1,10 +1,19 @@@ ActionController::Routing::Routes.draw do |map| # API + map.connect "api/capabilities", :controller => 'api', :action => 'capabilities' + + map.connect "api/#{API_VERSION}/changeset/create", :controller => 'changeset', :action => 'create' + map.connect "api/#{API_VERSION}/changeset/:id/upload", :controller => 'changeset', :action => 'upload', :id => /\d+/ + map.connect "api/#{API_VERSION}/changeset/:id/download", :controller => 'changeset', :action => 'download', :id => /\d+/ + map.connect "api/#{API_VERSION}/changeset/:id", :controller => 'changeset', :action => 'read', :id => /\d+/ + map.connect "api/#{API_VERSION}/changeset/:id/close", :controller => 'changeset', :action => 'close', :id =>/\d+/ + map.connect "api/#{API_VERSION}/node/create", :controller => 'node', :action => 'create' map.connect "api/#{API_VERSION}/node/:id/ways", :controller => 'way', :action => 'ways_for_node', :id => /\d+/ map.connect "api/#{API_VERSION}/node/:id/relations", :controller => 'relation', :action => 'relations_for_node', :id => /\d+/ map.connect "api/#{API_VERSION}/node/:id/history", :controller => 'old_node', :action => 'history', :id => /\d+/ + map.connect "api/#{API_VERSION}/node/:id/:version", :controller => 'old_node', :action => 'version', :id => /\d+/, :version => /\d+/ map.connect "api/#{API_VERSION}/node/:id", :controller => 'node', :action => 'read', :id => /\d+/, :conditions => { :method => :get } map.connect "api/#{API_VERSION}/node/:id", :controller => 'node', :action => 'update', :id => /\d+/, :conditions => { :method => :put } map.connect "api/#{API_VERSION}/node/:id", :controller => 'node', :action => 'delete', :id => /\d+/, :conditions => { :method => :delete } @@@ -23,12 -14,12 +23,12 @@@ map.connect "api/#{API_VERSION}/way/:id/history", :controller => 'old_way', :action => 'history', :id => /\d+/ map.connect "api/#{API_VERSION}/way/:id/full", :controller => 'way', :action => 'full', :id => /\d+/ map.connect "api/#{API_VERSION}/way/:id/relations", :controller => 'relation', :action => 'relations_for_way', :id => /\d+/ + map.connect "api/#{API_VERSION}/way/:id/:version", :controller => 'old_way', :action => 'version', :id => /\d+/, :version => /\d+/ map.connect "api/#{API_VERSION}/way/:id", :controller => 'way', :action => 'read', :id => /\d+/, :conditions => { :method => :get } map.connect "api/#{API_VERSION}/way/:id", :controller => 'way', :action => 'update', :id => /\d+/, :conditions => { :method => :put } map.connect "api/#{API_VERSION}/way/:id", :controller => 'way', :action => 'delete', :id => /\d+/, :conditions => { :method => :delete } map.connect "api/#{API_VERSION}/ways", :controller => 'way', :action => 'ways', :id => nil - map.connect "api/#{API_VERSION}/capabilities", :controller => 'api', :action => 'capabilities' map.connect "api/#{API_VERSION}/relation/create", :controller => 'relation', :action => 'create' map.connect "api/#{API_VERSION}/relation/:id/relations", :controller => 'relation', :action => 'relations_for_relation', :id => /\d+/ map.connect "api/#{API_VERSION}/relation/:id/history", :controller => 'old_relation', :action => 'history', :id => /\d+/ @@@ -63,8 -54,8 +63,9 @@@ # Potlatch API - map.connect "api/#{API_VERSION}/amf", :controller =>'amf', :action =>'talk' + map.connect "api/#{API_VERSION}/amf/read", :controller =>'amf', :action =>'amf_read' + map.connect "api/#{API_VERSION}/amf/write", :controller =>'amf', :action =>'amf_write' + map.connect "api/#{API_VERSION}/amf", :controller =>'amf', :action =>'talk' map.connect "api/#{API_VERSION}/swf/trackpoints", :controller =>'swf', :action =>'trackpoints' # Data browsing @@@ -76,7 -67,6 +77,7 @@@ map.connect '/browse/node/:id/history', :controller => 'browse', :action => 'node_history', :id => /\d+/ map.connect '/browse/relation/:id', :controller => 'browse', :action => 'relation', :id => /\d+/ map.connect '/browse/relation/:id/history', :controller => 'browse', :action => 'relation_history', :id => /\d+/ + map.connect '/browse/changeset/:id', :controller => 'browse', :action => 'changeset', :id => /\d+/ # web site diff --combined db/migrate/017_add_timestamp_indexes.rb index c6b3bc7c2,000000000..c6b3bc7c2 mode 100644,000000..100644 --- a/db/migrate/017_add_timestamp_indexes.rb +++ b/db/migrate/017_add_timestamp_indexes.rb @@@ -1,11 -1,0 +1,11 @@@ +class AddTimestampIndexes < ActiveRecord::Migration + def self.up + add_index :current_ways, :timestamp, :name => :current_ways_timestamp_idx + add_index :current_relations, :timestamp, :name => :current_relations_timestamp_idx + end + + def self.down + remove_index :current_ways, :name => :current_ways_timestamp_idx + remove_index :current_relations, :name => :current_relations_timestamp_idx + end +end diff --combined db/migrate/018_populate_node_tags_and_remove.rb index f10bf16d2,000000000..f10bf16d2 mode 100644,000000..100644 --- a/db/migrate/018_populate_node_tags_and_remove.rb +++ b/db/migrate/018_populate_node_tags_and_remove.rb @@@ -1,60 -1,0 +1,60 @@@ +class PopulateNodeTagsAndRemove < ActiveRecord::Migration + def self.up + have_nodes = select_value("SELECT count(*) FROM current_nodes").to_i != 0 + + if have_nodes + prefix = File.join Dir.tmpdir, "017_populate_node_tags_and_remove.#{$$}." + + cmd = "db/migrate/017_populate_node_tags_and_remove_helper" + src = "#{cmd}.c" + if not File.exists? cmd or File.mtime(cmd) < File.mtime(src) then + system 'cc -O3 -Wall `mysql_config --cflags --libs` ' + + "#{src} -o #{cmd}" or fail + end + + conn_opts = ActiveRecord::Base.connection.instance_eval { @connection_options } + args = conn_opts.map { |arg| arg.to_s } + [prefix] + fail "#{cmd} failed" unless system cmd, *args + + tempfiles = ['nodes', 'node_tags', 'current_nodes', 'current_node_tags']. + map { |base| prefix + base } + nodes, node_tags, current_nodes, current_node_tags = tempfiles + end + + execute "TRUNCATE nodes" + remove_column :nodes, :tags + remove_column :current_nodes, :tags + + add_column :nodes, :version, :bigint, :limit => 20, :null => false + + create_table :current_node_tags, innodb_table do |t| + t.column :id, :bigint, :limit => 64, :null => false + t.column :k, :string, :default => "", :null => false + t.column :v, :string, :default => "", :null => false + end + + create_table :node_tags, innodb_table do |t| + t.column :id, :bigint, :limit => 64, :null => false + t.column :version, :bigint, :limit => 20, :null => false + t.column :k, :string, :default => "", :null => false + t.column :v, :string, :default => "", :null => false + end + + # now get the data back + csvopts = "FIELDS TERMINATED BY ',' ENCLOSED BY '\"' ESCAPED BY '\"' LINES TERMINATED BY '\\n'" + + if have_nodes + execute "LOAD DATA INFILE '#{nodes}' INTO TABLE nodes #{csvopts} (id, latitude, longitude, user_id, visible, timestamp, tile, version)"; + execute "LOAD DATA INFILE '#{node_tags}' INTO TABLE node_tags #{csvopts} (id, version, k, v)" + execute "LOAD DATA INFILE '#{current_node_tags}' INTO TABLE current_node_tags #{csvopts} (id, k, v)" + end + + tempfiles.each { |fn| File.unlink fn } if have_nodes + end + + def self.down + raise IrreversibleMigration.new +# add_column :nodes, "tags", :text, :default => "", :null => false +# add_column :current_nodes, "tags", :text, :default => "", :null => false + end +end diff --combined db/migrate/018_populate_node_tags_and_remove_helper.c index 697b8fcd3,000000000..83c1b1743 mode 100644,000000..100644 --- a/db/migrate/018_populate_node_tags_and_remove_helper.c +++ b/db/migrate/018_populate_node_tags_and_remove_helper.c @@@ -1,241 -1,0 +1,241 @@@ +#include +#include +#include +#include +#include + +static void exit_mysql_err(MYSQL *mysql) { + const char *err = mysql_error(mysql); + if (err) { - fprintf(stderr, "017_populate_node_tags_and_remove_helper: MySQL error: %s\n", err); ++ fprintf(stderr, "018_populate_node_tags_and_remove_helper: MySQL error: %s\n", err); + } else { - fprintf(stderr, "017_populate_node_tags_and_remove_helper: MySQL error\n"); ++ fprintf(stderr, "018_populate_node_tags_and_remove_helper: MySQL error\n"); + } + abort(); + exit(EXIT_FAILURE); +} + +static void write_csv_col(FILE *f, const char *str, char end) { + char *out = (char *) malloc(2 * strlen(str) + 4); + char *o = out; + size_t len; + + *(o++) = '\"'; + for (; *str; str++) { + if (*str == '\0') { + break; + } else if (*str == '\"') { + *(o++) = '\"'; + *(o++) = '\"'; + } else { + *(o++) = *str; + } + } + *(o++) = '\"'; + *(o++) = end; + *(o++) = '\0'; + + len = strlen(out); + if (fwrite(out, len, 1, f) != 1) { + perror("fwrite"); + exit(EXIT_FAILURE); + } + + free(out); +} + +static void unescape(char *str) { + char *i = str, *o = str, tmp; + + while (*i) { + if (*i == '\\') { + i++; + switch (tmp = *i++) { + case 's': *o++ = ';'; break; + case 'e': *o++ = '='; break; + case '\\': *o++ = '\\'; break; + default: *o++ = tmp; break; + } + } else { + *o++ = *i++; + } + } +} + +static int read_node_tags(char **tags, char **k, char **v) { + if (!**tags) return 0; + char *i = strchr(*tags, ';'); + if (!i) i = *tags + strlen(*tags); + char *j = strchr(*tags, '='); + *k = *tags; + if (j && j < i) { + *v = j + 1; + } else { + *v = i; + } + *tags = *i ? i + 1 : i; + *i = '\0'; + if (j) *j = '\0'; + + unescape(*k); + unescape(*v); + + return 1; +} + +struct data { + MYSQL *mysql; + size_t version_size; + uint16_t *version; +}; + +static void proc_nodes(struct data *d, const char *tbl, FILE *out, FILE *out_tags, int hist) { + MYSQL_RES *res; + MYSQL_ROW row; + char query[256]; + + snprintf(query, sizeof(query), "SELECT id, latitude, longitude, " + "user_id, visible, tags, timestamp, tile FROM %s", tbl); + if (mysql_query(d->mysql, query)) + exit_mysql_err(d->mysql); + + res = mysql_use_result(d->mysql); + if (!res) exit_mysql_err(d->mysql); + + while ((row = mysql_fetch_row(res))) { + unsigned long id = strtoul(row[0], NULL, 10); + uint32_t version; + + if (id >= d->version_size) { + fprintf(stderr, "preallocated nodes size exceeded"); + abort(); + } + + if (hist) { + version = ++(d->version[id]); + + fprintf(out, "\"%s\",\"%s\",\"%s\",\"%s\",\"%s\",\"%s\",\"%s\",\"%u\"\n", + row[0], row[1], row[2], row[3], row[4], row[6], row[7], version); + } else { + /*fprintf(out, "\"%s\",\"%s\",\"%s\",\"%s\",\"%s\",\"%s\",\"%s\"\n", + row[0], row[1], row[2], row[3], row[4], row[6], row[7]);*/ + } + + char *tags_it = row[5], *k, *v; + while (read_node_tags(&tags_it, &k, &v)) { + if (hist) { + fprintf(out_tags, "\"%s\",\"%u\",", row[0], version); + } else { + fprintf(out_tags, "\"%s\",", row[0]); + } + + write_csv_col(out_tags, k, ','); + write_csv_col(out_tags, v, '\n'); + } + } + if (mysql_errno(d->mysql)) exit_mysql_err(d->mysql); + + mysql_free_result(res); +} + +static size_t select_size(MYSQL *mysql, const char *q) { + MYSQL_RES *res; + MYSQL_ROW row; + size_t ret; + + if (mysql_query(mysql, q)) + exit_mysql_err(mysql); + + res = mysql_store_result(mysql); + if (!res) exit_mysql_err(mysql); + + row = mysql_fetch_row(res); + if (!row) exit_mysql_err(mysql); + + if (row[0]) { + ret = strtoul(row[0], NULL, 10); + } else { + ret = 0; + } + + mysql_free_result(res); + + return ret; +} + +static MYSQL *connect_to_mysql(char **argv) { + MYSQL *mysql = mysql_init(NULL); + if (!mysql) exit_mysql_err(mysql); + + if (!mysql_real_connect(mysql, argv[1], argv[2], argv[3], argv[4], + argv[5][0] ? atoi(argv[5]) : 0, argv[6][0] ? argv[6] : NULL, 0)) + exit_mysql_err(mysql); + + if (mysql_set_character_set(mysql, "utf8")) + exit_mysql_err(mysql); + + return mysql; +} + +static void open_file(FILE **f, char *fn) { + *f = fopen(fn, "w+"); + if (!*f) { + perror("fopen"); + exit(EXIT_FAILURE); + } +} + +int main(int argc, char **argv) { + size_t prefix_len; + FILE *current_nodes, *current_node_tags, *nodes, *node_tags; + char *tempfn; + struct data data, *d = &data; + + if (argc != 8) { - printf("Usage: 017_populate_node_tags_and_remove_helper host user passwd database port socket prefix\n"); ++ printf("Usage: 018_populate_node_tags_and_remove_helper host user passwd database port socket prefix\n"); + exit(EXIT_FAILURE); + } + + d->mysql = connect_to_mysql(argv); + + d->version_size = 1 + select_size(d->mysql, "SELECT max(id) FROM current_nodes"); + d->version = (uint16_t *) malloc(sizeof(uint16_t) * d->version_size); + if (!d->version) { + perror("malloc"); + abort(); + exit(EXIT_FAILURE); + } + memset(d->version, 0, sizeof(uint16_t) * d->version_size); + + prefix_len = strlen(argv[7]); + tempfn = (char *) malloc(prefix_len + 32); + strcpy(tempfn, argv[7]); + + strcpy(tempfn + prefix_len, "current_nodes"); + open_file(¤t_nodes, tempfn); + + strcpy(tempfn + prefix_len, "current_node_tags"); + open_file(¤t_node_tags, tempfn); + + strcpy(tempfn + prefix_len, "nodes"); + open_file(&nodes, tempfn); + + strcpy(tempfn + prefix_len, "node_tags"); + open_file(&node_tags, tempfn); + + free(tempfn); + + proc_nodes(d, "nodes", nodes, node_tags, 1); + proc_nodes(d, "current_nodes", current_nodes, current_node_tags, 0); + + free(d->version); + + mysql_close(d->mysql); + + fclose(current_nodes); + fclose(current_node_tags); + fclose(nodes); + fclose(node_tags); + + exit(EXIT_SUCCESS); +} diff --combined db/migrate/019_move_to_innodb.rb index d17da8fd5,000000000..d17da8fd5 mode 100644,000000..100644 --- a/db/migrate/019_move_to_innodb.rb +++ b/db/migrate/019_move_to_innodb.rb @@@ -1,45 -1,0 +1,45 @@@ +class MoveToInnodb < ActiveRecord::Migration + @@conv_tables = ['nodes', 'ways', 'way_tags', 'way_nodes', + 'current_way_tags', 'relation_members', + 'relations', 'relation_tags', 'current_relation_tags'] + + @@ver_tbl = ['nodes', 'ways', 'relations'] + + def self.up + execute 'DROP INDEX current_way_tags_v_idx ON current_way_tags' + execute 'DROP INDEX current_relation_tags_v_idx ON current_relation_tags' + + @@ver_tbl.each { |tbl| + change_column tbl, "version", :bigint, :limit => 20, :null => false + } + + @@conv_tables.each { |tbl| + execute "ALTER TABLE #{tbl} ENGINE = InnoDB" + } + + @@ver_tbl.each { |tbl| + add_column "current_#{tbl}", "version", :bigint, :limit => 20, :null => false + # As the initial version of all nodes, ways and relations is 0, we set the + # current version to something less so that we can update the version in + # batches of 10000 + tbl.classify.constantize.update_all("version=-1") + while tbl.classify.constantize.count(:conditions => {:version => -1}) > 0 + tbl.classify.constantize.update_all("version=(SELECT max(version) FROM #{tbl} WHERE #{tbl}.id = current_#{tbl}.id)", {:version => -1}, :limit => 10000) + end + # execute "UPDATE current_#{tbl} SET version = " + + # "(SELECT max(version) FROM #{tbl} WHERE #{tbl}.id = current_#{tbl}.id)" + # The above update causes a MySQL error: + # -- add_column("current_nodes", "version", :bigint, {:null=>false, :limit=>20}) + # -> 1410.9152s + # -- execute("UPDATE current_nodes SET version = (SELECT max(version) FROM nodes WHERE nodes.id = current_nodes.id)") + # rake aborted! + # Mysql::Error: The total number of locks exceeds the lock table size: UPDATE current_nodes SET version = (SELECT max(version) FROM nodes WHERE nodes.id = current_nodes.id) + + # The above rails version will take longer, however will no run out of locks + } + end + + def self.down + raise IrreversibleMigration.new + end +end diff --combined db/migrate/020_key_constraints.rb index 40f98be02,000000000..40f98be02 mode 100644,000000..100644 --- a/db/migrate/020_key_constraints.rb +++ b/db/migrate/020_key_constraints.rb @@@ -1,50 -1,0 +1,50 @@@ +class KeyConstraints < ActiveRecord::Migration + def self.up + # Primary keys + add_primary_key :current_node_tags, [:id, :k] + add_primary_key :current_way_tags, [:id, :k] + add_primary_key :current_relation_tags, [:id, :k] + + add_primary_key :node_tags, [:id, :version, :k] + add_primary_key :way_tags, [:id, :version, :k] + add_primary_key :relation_tags, [:id, :version, :k] + + add_primary_key :nodes, [:id, :version] + + # Remove indexes superseded by primary keys + remove_index :current_way_tags, :name => :current_way_tags_id_idx + remove_index :current_relation_tags, :name => :current_relation_tags_id_idx + + remove_index :way_tags, :name => :way_tags_id_version_idx + remove_index :relation_tags, :name => :relation_tags_id_version_idx + + remove_index :nodes, :name => :nodes_uid_idx + + # Foreign keys (between ways, way_tags, way_nodes, etc.) + add_foreign_key :current_node_tags, [:id], :current_nodes + add_foreign_key :node_tags, [:id, :version], :nodes + + add_foreign_key :current_way_tags, [:id], :current_ways + add_foreign_key :current_way_nodes, [:id], :current_ways + add_foreign_key :way_tags, [:id, :version], :ways + add_foreign_key :way_nodes, [:id, :version], :ways + + add_foreign_key :current_relation_tags, [:id], :current_relations + add_foreign_key :current_relation_members, [:id], :current_relations + add_foreign_key :relation_tags, [:id, :version], :relations + add_foreign_key :relation_members, [:id, :version], :relations + + # Foreign keys (between different types of primitives) + add_foreign_key :current_way_nodes, [:node_id], :current_nodes, [:id] + + # FIXME: We don't have foreign keys for relation members since the id + # might point to a different table depending on the `type' column. + # We'd probably need different current_relation_member_nodes, + # current_relation_member_ways and current_relation_member_relations + # tables for this to work cleanly. + end + + def self.down + raise IrreversibleMigration.new + end +end diff --combined db/migrate/021_add_changesets.rb index 772a5f20d,000000000..772a5f20d mode 100644,000000..100644 --- a/db/migrate/021_add_changesets.rb +++ b/db/migrate/021_add_changesets.rb @@@ -1,46 -1,0 +1,46 @@@ +class AddChangesets < ActiveRecord::Migration + @@conv_user_tables = ['current_nodes', + 'current_relations', 'current_ways', 'nodes', 'relations', 'ways' ] + + def self.up + create_table "changesets", innodb_table do |t| + t.column "user_id", :bigint, :limit => 20, :null => false + t.column "created_at", :datetime, :null => false + t.column "open", :boolean, :null => false, :default => true + t.column "min_lat", :integer, :null => true + t.column "max_lat", :integer, :null => true + t.column "min_lon", :integer, :null => true + t.column "max_lon", :integer, :null => true + end + add_column :changesets, :id, :bigint_pk + + create_table "changeset_tags", innodb_table do |t| + t.column "id", :bigint, :limit => 64, :null => false + t.column "k", :string, :default => "", :null => false + t.column "v", :string, :default => "", :null => false + end + + add_index "changeset_tags", ["id"], :name => "changeset_tags_id_idx" + + # + # Initially we will have one changeset for every user containing + # all edits up to the API change, + # all the changesets will have the id of the user that made them. + # We need to generate a changeset for each user in the database + execute "INSERT INTO changesets (id, user_id, created_at, open)" + + "SELECT id, id, creation_time, 0 from users;" + + @@conv_user_tables.each { |tbl| + rename_column tbl, :user_id, :changeset_id + #foreign keys too + add_foreign_key tbl, [:changeset_id], :changesets, [:id] + } + end + + def self.down + # It's not easy to generate the user ids from the changesets + raise IrreversibleMigration.new + #drop_table "changesets" + #drop_table "changeset_tags" + end +end diff --combined public/javascripts/map.js index c2ddf9c39,c80ed2242..fcf34336f --- a/public/javascripts/map.js +++ b/public/javascripts/map.js @@@ -13,8 -13,6 +13,8 @@@ var nonamekeys = }; OpenLayers._getScriptLocation = function () { + // Should really have this file as an erb, so that this can return + // the real rails root return "/openlayers/"; } @@@ -32,7 -30,8 +32,8 @@@ function createMap(divName, options) ], units: "m", maxResolution: 156543.0339, - numZoomLevels: 20 + numZoomLevels: 20, + displayProjection: new OpenLayers.Projection("EPSG:4326") }); var mapnik = new OpenLayers.Layer.OSM.Mapnik("Mapnik", { @@@ -133,6 -132,8 +134,8 @@@ function getMapCenter(center, zoom) } function setMapCenter(center, zoom) { + var numzoom = map.getNumZoomLevels(); + if (zoom >= numzoom) zoom = numzoom - 1; map.setCenter(center.clone().transform(epsg4326, map.getProjectionObject()), zoom); }