Sqlite, где предложение не работает (это ошибка?) - PullRequest
2 голосов
/ 15 марта 2012

Я отлаживал движок Ruby on Rails, у которого есть проблемы при работе на Sqlite, у него есть проблема с поиском записей, которые создает само приложение. При запуске на MySQL все работает, но тот же запрос на SQLite не выполняется.

Я разыскал проблему и обнаружил, что проблема заключается в простом запросе WHERE, который не найдет созданную запись. По сути, структура таблицы имеет столбец с именем key, в котором хранятся некоторые хеши md5. Неудачная спецификация вставляет запись с заданным хешем, затем по следующей инструкции выполняет запрос SELECT для того же хеша, но SQLite не возвращает записи для того же ключа. Я извлек сгенерированную базу данных и ошибочный запрос из приложения, и это копия базы данных приложения:

http://dl.dropbox.com/u/2289657/combustion_test.sqlite

Вот расшифровка запросов, выполненных программным обеспечением (сделанных с помощью утилиты командной строки):

# Here I'm selecting all the records from the table
# there is a single record  in it, the key is the third field
$ sqlite3 combustion_test.sqlite 'SELECT * FROM tr8n_translation_keys'
1||b56c67d10759f8012aff28fc03f26cbf|Hello World|We must start with this sentence!||||en-US|0|2012-03-14 11:49:50.335322|2012-03-14 11:49:50.335322|

# Here I'm selecting the record with that key and it doesn't return anything
$ sqlite3 combustion_test.sqlite "SELECT * FROM tr8n_translation_keys WHERE key = 'b56c67d10759f8012aff28fc03f26cbf'"

# Here I'selecting the record with a LIKE clause and it finds the record
$ sqlite3 combustion_test.sqlite "SELECT * FROM tr8n_translation_keys WHERE key LIKE 'b56c67d10759f8012aff28fc03f26cbf'"
1||b56c67d10759f8012aff28fc03f26cbf|Hello World|We must start with this sentence!||||en-US|0|2012-03-14 11:49:50.335322|2012-03-14 11:49:50.335322|

Должен ли я сообщить об этом как об ошибке на сайт SQLite?

P.S. Я пробовал также на другой системе с другой версией SQLite, но результаты те же.

Обновление

Вот схема таблицы

sqlite> .schema tr8n_translation_keys
CREATE TABLE "tr8n_translation_keys" (
   "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, 
   "type" varchar(255), "key" varchar(255) NOT NULL,
   "label" text NOT NULL, 
   "description" text, 
   "verified_at" datetime, 
   "translation_count" integer, 
   "admin" boolean, 
   "locale" varchar(255), 
   "level" integer DEFAULT 0, 
   "created_at" datetime, 
   "updated_at" datetime, 
   "synced_at" datetime
);
CREATE UNIQUE INDEX "index_tr8n_translation_keys_on_key" ON "tr8n_translation_keys" ("key");
CREATE INDEX "index_tr8n_translation_keys_on_synced_at" ON "tr8n_translation_keys" ("synced_at");

Обновление 2

Вот код rails, который вычисляет значение ключа, вставленное в таблицу (я удалил некоторый код, полный метод здесь )

def self.find_or_create(label, desc = "", options = {})
  key = generate_key(label, desc).to_s
  # IF I UNCOMMENT THIS LINE EVERYTHING WORKS
  #key = 'b56c67d10759f8012aff28fc03f26cbf'

  tkey = Tr8n::Cache.fetch("translation_key_#{key}") do
    existing_key = where(:key => key).first ### THIS IS THE FAILING WHERE

    existing_key ||= begin
      new_tkey = create(:key => key.to_s, 
                        :label => label, 
                        :description => desc, 
                        :locale => locale,
                        :level => level,
                        :admin => Tr8n::Config.block_options[:admin])
# rest of method...

А вот метод generate_key, комментарий о sqlite от автора, а не от меня)

def self.generate_key(label, desc = "")
  # TODO: there is something iffy going on with the strings from the hash
  # without the extra ~ = the strings are not seen in the sqlite database - wtf?
  "#{Digest::MD5.hexdigest("#{label};;;#{desc}")}"
end

Ответы [ 2 ]

1 голос
/ 08 июня 2012

На основании следующего ответа переполнения стека ...

https://stackoverflow.com/a/6591427/18064

... вы можете обновить генерацию ключа следующим образом:

def self.generate_key(label, desc = "")
   # TODO: there is something iffy going on with the strings from the hash
   # without the extra ~ = the strings are not seen in the sqlite database - wtf?
   "#{Digest::MD5.hexdigest("#{label};;;#{desc}").encode('UTF-8')}"
end

Обратите внимание на добавление .encode('UTF-8').

Это сработало для меня, когда у меня была такая же проблема, как и у вас.

1 голос
/ 15 марта 2012

Это работает:

SELECT * FROM tr8n_translation_keys WHERE LOWER(key)='b56c67d10759f8012aff28fc03f26cbf';

Но это не так:

SELECT * FROM tr8n_translation_keys WHERE key='b56c67d10759f8012aff28fc03f26cbf' COLLATE NOCASE;

Когда я проверяю базу данных в SQLiteManager, она показывает key как это:

X'6235366336376431303735396638303132616666323866633033663236636266'

, что означает, что он обрабатывает key как BLOB (необработанные двоичные данные), а не TEXT. Вот почему сравнение не удается. Но LOWER(key) вызывает преобразование поля в текст, следовательно, сравнение успешно.

Итак, нам нужно выяснить, почему запись была сохранена как BLOB вместо TEXT. Как эти значения были вставлены в базу данных?


После вашего обновления 2 : я не эксперт по Ruby, но значение, возвращаемое из generate_key, не преобразуется в строку, как вы ожидаете. Попробуйте to_str вместо to_s при звонке generate_key.

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