From: Shaun McDonald Date: Fri, 12 Dec 2008 19:29:27 +0000 (+0000) Subject: resync from rails_port 11795:12304 X-Git-Tag: live~7616^2~97 X-Git-Url: https://git.openstreetmap.org/rails.git/commitdiff_plain/721dd9c27d299455b9159457a095716f797389f1 resync from rails_port 11795:12304 --- 721dd9c27d299455b9159457a095716f797389f1 diff --cc app/controllers/trace_controller.rb index 06ae5dc3b,bcac11844..022c304fb --- a/app/controllers/trace_controller.rb +++ b/app/controllers/trace_controller.rb @@@ -47,12 -48,12 +48,13 @@@ class TraceController < ApplicationCont if params[:tag] @tag = params[:tag] - conditions[0] += " AND EXISTS (SELECT * FROM gpx_file_tags AS gft WHERE gft.gpx_id = gpx_files.id AND gft.tag = ?)" - conditions << @tag + + files = Tracetag.find_all_by_tag(params[:tag]).collect { |tt| tt.gpx_id } + conditions[0] += " AND gpx_files.id IN (#{files.join(',')})" end - conditions[0] += " AND gpx_files.visible = 1" + conditions[0] += " AND gpx_files.visible = ?" + conditions << true @trace_pages, @traces = paginate(:traces, :include => [:user, :tags], diff --cc app/models/user.rb index 0eddb259d,fae037110..ce244fe02 --- a/app/models/user.rb +++ b/app/models/user.rb @@@ -106,8 -104,17 +106,21 @@@ class User < ActiveRecord::Bas return false end + def trace_public_default + return self.preferences.find(:first, :conditions => {:k => "gps.trace.public", :v => "default"}) + end + + def delete + self.active = false + self.display_name = "user_#{self.id}" + self.description = nil + self.home_lat = nil + self.home_lon = nil + self.image = nil + self.email_valid = false + self.new_email = nil + self.visible = false + self.save + end + end diff --cc db/migrate/018_add_timestamp_indexes.rb index c6b3bc7c2,000000000..c6b3bc7c2 mode 100644,000000..100644 --- a/db/migrate/018_add_timestamp_indexes.rb +++ b/db/migrate/018_add_timestamp_indexes.rb diff --cc db/migrate/019_populate_node_tags_and_remove.rb index 2a3f3c988,000000000..860358646 mode 100644,000000..100644 --- a/db/migrate/019_populate_node_tags_and_remove.rb +++ b/db/migrate/019_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.#{$$}." ++ prefix = File.join Dir.tmpdir, "019_populate_node_tags_and_remove.#{$$}." + - cmd = "db/migrate/018_populate_node_tags_and_remove_helper" ++ cmd = "db/migrate/019_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 --cc db/migrate/019_populate_node_tags_and_remove_helper.c index 83c1b1743,000000000..c41ea33da mode 100644,000000..100644 --- a/db/migrate/019_populate_node_tags_and_remove_helper.c +++ b/db/migrate/019_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, "018_populate_node_tags_and_remove_helper: MySQL error: %s\n", err); ++ fprintf(stderr, "019_populate_node_tags_and_remove_helper: MySQL error: %s\n", err); + } else { - fprintf(stderr, "018_populate_node_tags_and_remove_helper: MySQL error\n"); ++ fprintf(stderr, "019_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: 018_populate_node_tags_and_remove_helper host user passwd database port socket prefix\n"); ++ printf("Usage: 019_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 --cc db/migrate/020_move_to_innodb.rb index da0488ca5,000000000..da0488ca5 mode 100644,000000..100644 --- a/db/migrate/020_move_to_innodb.rb +++ b/db/migrate/020_move_to_innodb.rb diff --cc db/migrate/021_key_constraints.rb index 40f98be02,000000000..40f98be02 mode 100644,000000..100644 --- a/db/migrate/021_key_constraints.rb +++ b/db/migrate/021_key_constraints.rb diff --cc db/migrate/022_add_changesets.rb index e0cf3904a,000000000..e0cf3904a mode 100644,000000..100644 --- a/db/migrate/022_add_changesets.rb +++ b/db/migrate/022_add_changesets.rb diff --cc db/migrate/023_order_relation_members.rb index 5500edfcf,000000000..5500edfcf mode 100644,000000..100644 --- a/db/migrate/023_order_relation_members.rb +++ b/db/migrate/023_order_relation_members.rb diff --cc db/migrate/024_add_end_time_to_changesets.rb index b87ce3fde,000000000..b87ce3fde mode 100644,000000..100644 --- a/db/migrate/024_add_end_time_to_changesets.rb +++ b/db/migrate/024_add_end_time_to_changesets.rb