Added postgresql support.

This commit is contained in:
Martin Edenhofer 2016-01-19 23:30:23 +01:00
parent 7b8fef1991
commit a00be78195
13 changed files with 280 additions and 136 deletions

View file

@ -54,6 +54,7 @@ gem 'therubyracer'
# e. g. for mysql you need to load mysql # e. g. for mysql you need to load mysql
gem 'mysql2', '~> 0.3.20' gem 'mysql2', '~> 0.3.20'
gem 'pg'
gem 'net-ldap' gem 'net-ldap'

View file

@ -194,6 +194,7 @@ GEM
omniauth-oauth (~> 1.1) omniauth-oauth (~> 1.1)
parser (2.3.0.1) parser (2.3.0.1)
ast (~> 2.2) ast (~> 2.2)
pg (0.18.4)
pluginator (1.3.0) pluginator (1.3.0)
polyglot (0.3.5) polyglot (0.3.5)
power_assert (0.2.7) power_assert (0.2.7)
@ -355,6 +356,7 @@ DEPENDENCIES
omniauth-google-oauth2 omniauth-google-oauth2
omniauth-linkedin omniauth-linkedin
omniauth-twitter omniauth-twitter
pg
pre-commit pre-commit
puma puma
rack-livereload rack-livereload

View file

@ -303,11 +303,12 @@ returns
=begin =begin
lookup model from cache (if exists) or retrieve it from db, id, name or login possible lookup model from cache (if exists) or retrieve it from db, id, name, login or email possible
result = Model.lookup(id: 123) result = Model.lookup(id: 123)
result = Model.lookup(name: 'some name') result = Model.lookup(name: 'some name')
result = Model.lookup(login: 'some login') result = Model.lookup(login: 'some login')
result = Model.lookup(email: 'some login')
returns returns
@ -328,7 +329,11 @@ returns
return cache if cache return cache if cache
# do lookup with == to handle case insensitive databases # do lookup with == to handle case insensitive databases
records = where(name: data[:name]) records = if Rails.application.config.db_case_sensitive
where('LOWER(name) = LOWER(?)', data[:name])
else
where(name: data[:name])
end
records.each {|loop_record| records.each {|loop_record|
if loop_record.name == data[:name] if loop_record.name == data[:name]
cache_set(data[:name], loop_record) cache_set(data[:name], loop_record)
@ -341,7 +346,11 @@ returns
return cache if cache return cache if cache
# do lookup with == to handle case insensitive databases # do lookup with == to handle case insensitive databases
records = where(login: data[:login]) records = if Rails.application.config.db_case_sensitive
where('LOWER(login) = LOWER(?)', data[:login])
else
where(login: data[:login])
end
records.each {|loop_record| records.each {|loop_record|
if loop_record.login == data[:login] if loop_record.login == data[:login]
cache_set(data[:login], loop_record) cache_set(data[:login], loop_record)
@ -349,9 +358,26 @@ returns
end end
} }
return return
elsif data[:email]
cache = cache_get(data[:email])
return cache if cache
# do lookup with == to handle case insensitive databases
records = if Rails.application.config.db_case_sensitive
where('LOWER(email) = LOWER(?)', data[:email])
else
where(email: data[:email])
end
records.each {|loop_record|
if loop_record.email == data[:email]
cache_set(data[:email], loop_record)
return loop_record
end
}
return
end end
fail 'Need name, id or login for lookup()' fail 'Need name, id, login or email for lookup()'
end end
=begin =begin
@ -373,28 +399,44 @@ returns
elsif data[:name] elsif data[:name]
# do lookup with == to handle case insensitive databases # do lookup with == to handle case insensitive databases
records = where(name: data[:name]) records = if Rails.application.config.db_case_sensitive
where('LOWER(name) = LOWER(?)', data[:name])
else
where(name: data[:name])
end
records.each {|loop_record| records.each {|loop_record|
return loop_record if loop_record.name == data[:name] return loop_record if loop_record.name == data[:name]
} }
elsif data[:login] elsif data[:login]
# do lookup with == to handle case insensitive databases # do lookup with == to handle case insensitive databases
records = where(login: data[:login]) records = if Rails.application.config.db_case_sensitive
where('LOWER(login) = LOWER(?)', data[:login])
else
where(login: data[:login])
end
records.each {|loop_record| records.each {|loop_record|
return loop_record if loop_record.login == data[:login] return loop_record if loop_record.login == data[:login]
} }
elsif data[:email] elsif data[:email]
# do lookup with == to handle case insensitive databases # do lookup with == to handle case insensitive databases
records = where(email: data[:email]) records = if Rails.application.config.db_case_sensitive
where('LOWER(email) = LOWER(?)', data[:email])
else
where(email: data[:email])
end
records.each {|loop_record| records.each {|loop_record|
return loop_record if loop_record.email == data[:email] return loop_record if loop_record.email == data[:email]
} }
elsif data[:locale] && data[:source] elsif data[:locale] && data[:source]
# do lookup with == to handle case insensitive databases # do lookup with == to handle case insensitive databases
records = where(locale: data[:locale], source: data[:source]) records = if Rails.application.config.db_case_sensitive
where('LOWER(locale) = LOWER(?) AND LOWER(source) = LOWER(?)', data[:locale], data[:source])
else
where(locale: data[:locale], source: data[:source])
end
records.each {|loop_record| records.each {|loop_record|
return loop_record if loop_record.source == data[:source] return loop_record if loop_record.source == data[:source]
} }
@ -427,7 +469,11 @@ returns
elsif data[:name] elsif data[:name]
# do lookup with == to handle case insensitive databases # do lookup with == to handle case insensitive databases
records = where(name: data[:name]) records = if Rails.application.config.db_case_sensitive
where('LOWER(name) = LOWER(?)', data[:name])
else
where(name: data[:name])
end
records.each {|loop_record| records.each {|loop_record|
if loop_record.name == data[:name] if loop_record.name == data[:name]
loop_record.update_attributes(data) loop_record.update_attributes(data)
@ -440,7 +486,11 @@ returns
elsif data[:login] elsif data[:login]
# do lookup with == to handle case insensitive databases # do lookup with == to handle case insensitive databases
records = where(login: data[:login]) records = if Rails.application.config.db_case_sensitive
where('LOWER(login) = LOWER(?)', data[:login])
else
where(login: data[:login])
end
records.each {|loop_record| records.each {|loop_record|
if loop_record.login.casecmp(data[:login]).zero? if loop_record.login.casecmp(data[:login]).zero?
loop_record.update_attributes(data) loop_record.update_attributes(data)
@ -453,7 +503,11 @@ returns
elsif data[:email] elsif data[:email]
# do lookup with == to handle case insensitive databases # do lookup with == to handle case insensitive databases
records = where(email: data[:email]) records = if Rails.application.config.db_case_sensitive
where('LOWER(email) = LOWER(?)', data[:email])
else
where(email: data[:email])
end
records.each {|loop_record| records.each {|loop_record|
if loop_record.email.casecmp(data[:email]).zero? if loop_record.email.casecmp(data[:email]).zero?
loop_record.update_attributes(data) loop_record.update_attributes(data)
@ -466,7 +520,11 @@ returns
elsif data[:locale] elsif data[:locale]
# do lookup with == to handle case insensitive databases # do lookup with == to handle case insensitive databases
records = where(locale: data[:locale]) records = if Rails.application.config.db_case_sensitive
where('LOWER(locale) = LOWER(?)', data[:locale])
else
where(locale: data[:locale])
end
records.each {|loop_record| records.each {|loop_record|
if loop_record.locale.casecmp(data[:locale]).zero? if loop_record.locale.casecmp(data[:locale]).zero?
loop_record.update_attributes(data) loop_record.update_attributes(data)

View file

@ -346,6 +346,7 @@ condition example
# remember query and bind params # remember query and bind params
query = '' query = ''
bind_params = [] bind_params = []
like = Rails.application.config.db_like
# get tables to join # get tables to join
tables = '' tables = ''
@ -437,11 +438,11 @@ condition example
bind_params.push selector['value'] bind_params.push selector['value']
end end
elsif selector['operator'] == 'contains' elsif selector['operator'] == 'contains'
query += "#{attribute} LIKE (?)" query += "#{attribute} #{like} (?)"
value = "%#{selector['value']}%" value = "%#{selector['value']}%"
bind_params.push value bind_params.push value
elsif selector['operator'] == 'contains not' elsif selector['operator'] == 'contains not'
query += "#{attribute} NOT LIKE (?)" query += "#{attribute} NOT #{like} (?)"
value = "%#{selector['value']}%" value = "%#{selector['value']}%"
bind_params.push value bind_params.push value
elsif selector['operator'] == 'before (absolute)' elsif selector['operator'] == 'before (absolute)'

View file

@ -0,0 +1,17 @@
# set database preferences
# defaults
Rails.application.config.db_case_sensitive = false
Rails.application.config.db_like = 'LIKE'
Rails.application.config.db_4bytes_utf8 = true
# postgresql
if ActiveRecord::Base.connection_config[:adapter] == 'postgresql'
Rails.application.config.db_case_sensitive = true
Rails.application.config.db_like = 'ILIKE'
end
# mysql
if ActiveRecord::Base.connection_config[:adapter] == 'mysql2'
Rails.application.config.db_4bytes_utf8 = false
end

View file

@ -3352,6 +3352,13 @@ Scheduler.create_or_update(
created_by_id: 1, created_by_id: 1,
) )
# reset primary key sequences
if ActiveRecord::Base.connection_config[:adapter] == 'postgresql'
ActiveRecord::Base.connection.tables.each do |t|
ActiveRecord::Base.connection.reset_pk_sequence!(t)
end
end
# install locales and translations # install locales and translations
Locale.create_if_not_exists( Locale.create_if_not_exists(
locale: 'en-us', locale: 'en-us',

View file

@ -0,0 +1,31 @@
require 'active_record/connection_adapters/postgresql/schema_statements'
module ActiveRecord
module ConnectionAdapters
module PostgreSQL
module SchemaStatements
# on postgres create lower indexes to support case insensetive wherer conditions
def add_index(table_name, column_name, options = {}) #:nodoc:
index_name, index_type, index_columns, index_options, index_algorithm, index_using = add_index_options(table_name, column_name, options)
column_names = index_columns.split ', '
if column_names.class == Array
index_columns_new = []
column_names.each {|i|
if i =~ /^"(name|login|locale|alias)"$/ || i =~ /name"$/
index_columns_new.push "LOWER(#{i})"
else
index_columns_new.push i
end
}
index_columns = index_columns_new.join ', '
end
execute "CREATE #{index_type} INDEX #{index_algorithm} #{quote_column_name(index_name)} ON #{quote_table_name(table_name)} #{index_using} (#{index_columns})#{index_options}"
end
end
end
end
end

View file

@ -57,7 +57,7 @@ class String
# unfortunaly UTF8mb4 will raise other limitaions of max varchar and lower index sizes # unfortunaly UTF8mb4 will raise other limitaions of max varchar and lower index sizes
# More details: http://pjambet.github.io/blog/emojis-and-mysql/ # More details: http://pjambet.github.io/blog/emojis-and-mysql/
def utf8_to_3bytesutf8 def utf8_to_3bytesutf8
return self if ActiveRecord::Base.connection_config[:adapter] != 'mysql2' return self if Rails.application.config.db_4bytes_utf8
each_char.select {|c| each_char.select {|c|
if c.bytes.count > 3 if c.bytes.count > 3
Rails.logger.warn "strip out 4 bytes utf8 chars '#{c}' of '#{self}'" Rails.logger.warn "strip out 4 bytes utf8 chars '#{c}' of '#{self}'"

View file

@ -1,7 +1,8 @@
# encoding: utf-8 # encoding: utf-8
# inital data set as extention to db/seeds.rb # inital data set as extention to db/seeds.rb
# create email address and apply it to all groups
email_address = EmailAddress.create_if_not_exists( email_address = EmailAddress.create_if_not_exists(
id: 1,
realname: 'Zammad', realname: 'Zammad',
email: 'zammad@localhost', email: 'zammad@localhost',
updated_by_id: 1, updated_by_id: 1,

View file

@ -16,7 +16,7 @@ class ActivityStreamTest < ActiveSupport::TestCase
updated_by_id: 1, updated_by_id: 1,
created_by_id: 1 created_by_id: 1
) )
current_user = User.lookup( login: 'nicole.braun@zammad.org' ) current_user = User.lookup(email: 'nicole.braun@zammad.org')
test 'ticket+user' do test 'ticket+user' do
tests = [ tests = [
@ -138,7 +138,7 @@ class ActivityStreamTest < ActiveSupport::TestCase
ticket_id = ticket.id ticket_id = ticket.id
ticket.destroy ticket.destroy
found = Ticket.where(id: ticket_id).first found = Ticket.where(id: ticket_id).first
assert( !found, 'Ticket destroyed') assert_not(found, 'Ticket destroyed')
} }
end end
@ -279,7 +279,7 @@ class ActivityStreamTest < ActiveSupport::TestCase
user_id = user.id user_id = user.id
user.destroy user.destroy
found = User.where( id: user_id ).first found = User.where( id: user_id ).first
assert( !found, 'User destroyed') assert_not(found, 'User destroyed')
} }
end end

View file

@ -32,15 +32,16 @@ Setting.create_or_update(
frontend: false frontend: false
) )
user = User.lookup( login: 'nicole.braun@zammad.org' ) user = User.lookup(email: 'nicole.braun@zammad.org')
if user if user
user.update_attributes( user.update_attributes(
login: 'nicole.braun',
password: 'some_pass', password: 'some_pass',
active: true, active: true,
) )
else else
User.create_if_not_exists( User.create_if_not_exists(
login: 'nicole.braun@zammad.org', login: 'nicole.braun',
firstname: 'Nicole', firstname: 'Nicole',
lastname: 'Braun', lastname: 'Braun',
email: 'nicole.braun@zammad.org', email: 'nicole.braun@zammad.org',
@ -63,6 +64,42 @@ class AuthTest < ActiveSupport::TestCase
}, },
# test 2 # test 2
{
username: 'nicole.braun@zammad.org',
password: 'some_pass',
result: true,
verify: {
firstname: 'Nicole',
lastname: 'Braun',
email: 'nicole.braun@zammad.org',
}
},
# test 3
{
username: 'nicole.bRaUn@zammad.org',
password: 'some_pass',
result: true,
verify: {
firstname: 'Nicole',
lastname: 'Braun',
email: 'nicole.braun@zammad.org',
}
},
# test 4
{
username: 'nicole.bRaUn',
password: 'some_pass',
result: true,
verify: {
firstname: 'Nicole',
lastname: 'Braun',
email: 'nicole.braun@zammad.org',
}
},
# test 5
{ {
username: 'paige.chen@example.org', username: 'paige.chen@example.org',
password: 'password', password: 'password',
@ -74,17 +111,6 @@ class AuthTest < ActiveSupport::TestCase
} }
}, },
# test 3
{
username: 'nicole.braun@zammad.org',
password: 'some_pass',
result: true,
verify: {
firstname: 'Nicole',
lastname: 'Braun',
email: 'nicole.braun@zammad.org',
}
},
] ]
tests.each { |test| tests.each { |test|
user = User.authenticate(test[:username], test[:password]) user = User.authenticate(test[:username], test[:password])

View file

@ -2,7 +2,7 @@
require 'test_helper' require 'test_helper'
class HistoryTest < ActiveSupport::TestCase class HistoryTest < ActiveSupport::TestCase
current_user = User.lookup( login: 'nicole.braun@zammad.org' ) current_user = User.lookup(email: 'nicole.braun@zammad.org')
test 'ticket' do test 'ticket' do
tests = [ tests = [
@ -189,7 +189,7 @@ class HistoryTest < ActiveSupport::TestCase
ticket_id = ticket.id ticket_id = ticket.id
ticket.destroy ticket.destroy
found = Ticket.where(id: ticket_id).first found = Ticket.where(id: ticket_id).first
assert( !found, 'Ticket destroyed') assert_not(found, 'Ticket destroyed')
} }
end end
@ -281,7 +281,7 @@ class HistoryTest < ActiveSupport::TestCase
user_id = user.id user_id = user.id
user.destroy user.destroy
found = User.where(id: user_id).first found = User.where(id: user_id).first
assert( !found, 'User destroyed') assert_not(found, 'User destroyed')
} }
end end
@ -350,7 +350,7 @@ class HistoryTest < ActiveSupport::TestCase
organization_id = organization.id organization_id = organization.id
organization.destroy organization.destroy
found = Organization.where(id: organization_id).first found = Organization.where(id: organization_id).first
assert( !found, 'Organization destroyed') assert_not(found, 'Organization destroyed')
} }
end end
@ -387,7 +387,7 @@ class HistoryTest < ActiveSupport::TestCase
if check_item[:result] if check_item[:result]
assert(match, "history check not matched! #{check_item.inspect}") assert(match, "history check not matched! #{check_item.inspect}")
else else
assert( !match, "history check matched but should not! #{check_item.inspect}") assert_not(match, "history check matched but should not! #{check_item.inspect}")
end end
} }
end end

View file

@ -28,7 +28,7 @@ class OnlineNotificationTest < ActiveSupport::TestCase
updated_by_id: 1, updated_by_id: 1,
created_by_id: 1 created_by_id: 1
) )
customer_user = User.lookup( login: 'nicole.braun@zammad.org' ) customer_user = User.lookup(email: 'nicole.braun@zammad.org')
test 'ticket notification' do test 'ticket notification' do
tests = [ tests = [