From 15d4d8300f0aeb614305320918edf23901667668 Mon Sep 17 00:00:00 2001 From: Type-kun Date: Sat, 17 Sep 2016 23:59:08 +0500 Subject: [PATCH 1/4] Create array index on bit_prefs (#2644) --- ...0917180923_add_index_to_users_bit_prefs.rb | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 db/migrate/20160917180923_add_index_to_users_bit_prefs.rb diff --git a/db/migrate/20160917180923_add_index_to_users_bit_prefs.rb b/db/migrate/20160917180923_add_index_to_users_bit_prefs.rb new file mode 100644 index 000000000..5783390b8 --- /dev/null +++ b/db/migrate/20160917180923_add_index_to_users_bit_prefs.rb @@ -0,0 +1,24 @@ +class AddIndexToUsersBitPrefs < ActiveRecord::Migration + def up + execute "set statement_timeout = 0" + execute <<-'SQL' + CREATE OR REPLACE FUNCTION bit_position_array(x bigint) + RETURNS integer[] AS $BODY$ + select array_agg(i) + from generate_series(0, floor(log(2, x))::integer) i + where (x & (1::bigint << i)) > 0; + $BODY$ LANGUAGE sql IMMUTABLE + SQL + + execute <<-'SQL' + CREATE INDEX index_users_on_bit_prefs_array + ON users USING gin (bit_position_array(bit_prefs) _int4_ops) + SQL + end + + def down + execute "set statement_timeout = 0" + execute "DROP INDEX index_users_on_bit_prefs_array" + execute "DROP FUNCTION bit_position_array(x bigint)" + end +end From 2e4385b6cdb466c479f56ece08992fd75e14e8db Mon Sep 17 00:00:00 2001 From: Type-kun Date: Sun, 18 Sep 2016 00:52:13 +0500 Subject: [PATCH 2/4] Change user prefs search logic to use index (#2644) Sadly, array index failed to cover "unset bits" case, so excluded bits are merged into bigint, and &'d with column, which turned out more readable and simpler than bit string. --- app/models/user.rb | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/app/models/user.rb b/app/models/user.rb index d86a1f6aa..3611be745 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -759,7 +759,6 @@ class User < ActiveRecord::Base q = q.where("id in (?)", params[:id].split(",").map(&:to_i)) end - bitprefs_length = BOOLEAN_ATTRIBUTES.length bitprefs_include = nil bitprefs_exclude = nil @@ -767,25 +766,21 @@ class User < ActiveRecord::Base if params[x].present? attr_idx = BOOLEAN_ATTRIBUTES.index(x.to_s) if params[x] == "true" - bitprefs_include ||= "0"*bitprefs_length - bitprefs_include[attr_idx] = '1' + bitprefs_include ||= [] + bitprefs_include << attr_idx elsif params[x] == "false" - bitprefs_exclude ||= "0"*bitprefs_length - bitprefs_exclude[attr_idx] = '1' + bitprefs_exclude ||= 0 + bitprefs_exclude |= (1 << attr_idx) end end end - + if bitprefs_include - bitprefs_include.reverse! - q = q.where("bit_prefs::bit(:len) & :bits::bit(:len) = :bits::bit(:len)", - {:len => bitprefs_length, :bits => bitprefs_include}) + q = q.where("bit_position_array(bit_prefs) @> ARRAY[?]::integer[]", bitprefs_include) end - + if bitprefs_exclude - bitprefs_exclude.reverse! - q = q.where("bit_prefs::bit(:len) & :bits::bit(:len) = 0::bit(:len)", - {:len => bitprefs_length, :bits => bitprefs_exclude}) + q = q.where("bit_prefs & ? = 0", bitprefs_exclude) end if params[:current_user_first] == "true" && !CurrentUser.is_anonymous? From e7586f4e4af761873eb86887821b9eed0d2dece6 Mon Sep 17 00:00:00 2001 From: Type-kun Date: Sun, 18 Sep 2016 00:57:25 +0500 Subject: [PATCH 3/4] Add is_banned to user search params --- app/models/user.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/user.rb b/app/models/user.rb index 3611be745..d57db6b9d 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -762,7 +762,7 @@ class User < ActiveRecord::Base bitprefs_include = nil bitprefs_exclude = nil - [:can_approve_posts, :can_upload_free, :is_super_voter].each do |x| + [:can_approve_posts, :can_upload_free, :is_super_voter, :is_banned].each do |x| if params[x].present? attr_idx = BOOLEAN_ATTRIBUTES.index(x.to_s) if params[x] == "true" From 6900b78365c2b51f344fbbc6a75fcfaaf94fc7df Mon Sep 17 00:00:00 2001 From: Type-kun Date: Sun, 18 Sep 2016 01:13:24 +0500 Subject: [PATCH 4/4] Include bitprefs in search form (#2644) --- app/views/users/search.html.erb | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/app/views/users/search.html.erb b/app/views/users/search.html.erb index d4cb0264c..62c66c2bb 100644 --- a/app/views/users/search.html.erb +++ b/app/views/users/search.html.erb @@ -18,6 +18,26 @@ <%= select("search", "max_level", [""] + User.level_hash.to_a) %> +
+ + <%= select("search", "can_approve_posts", [[""], ["Yes", "true"], ["No", "false"]]) %> +
+ +
+ + <%= select("search", "can_upload_free", [[""], ["Yes", "true"], ["No", "false"]]) %> +
+ +
+ + <%= select("search", "is_super_voter", [[""], ["Yes", "true"], ["No", "false"]]) %> +
+ +
+ + <%= select("search", "is_banned", [[""], ["Yes", "true"], ["No", "false"]]) %> +
+
<%= select("search", "order", [["Join date", "date"], ["Name", "name"], ["Upload count", "post_upload_count"], ["Note count", "note_count"], ["Post update count", "post_update_count"]]) %>