sqlite3 varchar соответствует "like", но не "=" - PullRequest
2 голосов
/ 16 сентября 2011

Использование Rails 3.1 и sqlite3 для среды разработки, тестирования.

Добавлена ​​новая таблица в миграции:

create_table :api_keys do |t|
  t.string :api_key
  t.integer :user_id
  t.timestamps
end

Это создает таблицу со следующей схемой:

create_table "api_keys", :force => true do |t|
  t.string   "api_key"
  t.integer  "user_id"
  t.datetime "created_at"
  t.datetime "updated_at"
end

В модели ActiveRecord:

before_create :fill_api_key

private

def fill_api_key
  self.api_key = SecureRandom.hex(30)
end

Метод динамического поиска ActiveRecord find_by_api_key(api_key) не работает (возвращает ноль). То же самое с:

ApiKey.where({:api_key => 'something'}).first

В sqlite3 я делаю следующее:

insert into api_keys (id, api_key) values (-1, '12345');

Если я сейчас запустил выбор:

select api_keys.* from api_keys where api_keys.api_key = '12345';

запись будет найдена.

Предварительно существующие данные, созданные из моего приложения, отображаются, если я запускаю неотфильтрованный выбор:

select api_keys.* from api_keys;

Если я пытаюсь найти ранее существующую запись, вставив в свой запрос длинную шестнадцатеричную строку из одной из этих ранее существующих записей:

select api_keys.* from api_keys where api_keys.api_key = 'long hex string';

тогда ничего не возвращается. Если я попробую это вместо:

select api_keys.* from api_keys where api_keys.api_key like 'long hex string';

Тогда я получу совпадение.

Я создал индекс для api_keys.api_key, но это не имело никакого эффекта.

Эта проблема затрагивает еще одну модель в моем приложении, которая генерирует аналогичную строку случайных шестнадцатеричных цифр с использованием Digest :: SHA1 :: hexdigest.

Джеймс

Ответы [ 2 ]

8 голосов
/ 19 сентября 2011

ОК, думаю, я понял это.Проблема не в том, что это Rails 3.1, а в том, что вы, вероятно, перешли с Ruby 1.8.7 на Ruby 1.9.2.

В Ruby 1.9 все строки теперь закодированы.По умолчанию все строки должны быть UTF-8, однако SecureRandom.hex(30) возвращает кодировку ASCII-8BIT.

. Вы можете подтвердить это в sqlite3 с помощью этой команды: .dump api_keys, и вы, вероятно, увидитечто поле api_key выглядит примерно так:

INSERT INTO "api_keys" VALUES(1,X'376433356530[...]',1);    
INSERT INTO "api_keys" VALUES(1,'1234567890[...]',1);

Первое - это api_key, сгенерированный SecureRandom.Второй - тот, который создается путем ввода в консоль.X указывает, что поле закодировано как большой двоичный объект, а не как строка.

Чтобы обойти это, измените свой fill_api_key на следующий:

self.api_key = SecureRandom.hex(30).force_encoding('UTF-8')

Я только что получил бит большое время этим, так что, надеюсь, это поможет вам.

Здесь есть несколько хороших подробностей об изменениях в String в 1.9: http://blog.grayproductions.net/articles/ruby_19s_string

0 голосов
/ 16 сентября 2011

Если вы используете строки шестнадцатеричных цифр, важно, чтобы у вас было совпадение регистра, если вы хотите использовать выбор где x = y. В отличие от некоторых баз данных, SQLite чувствителен к регистру.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...