Russian Qt Forum
Май 07, 2024, 00:21 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: Неужели ни у кого не было проблем с регистронезависимым LIKE в sqlite??  (Прочитано 11603 раз)
nata267
Гость
« : Январь 19, 2011, 12:28 »

Уже почти 2 недели не могу решить данную проблему, расширения готового нет, скомпилировать его под windows не получилось, новый плагин для драйвера sqlite на основе sqlite3.dll уже с поддержкой icu - не работает. как решить сию проблему не пойму, может ктото решал подобные?
Записан
_govorilka
Гость
« Ответ #1 : Январь 19, 2011, 13:19 »

В своём проекте тоже использую SQLite, но написал обертку над SQLite3 API, без использования QtSQL (так работает быстрее). Я могу выложить исходники, если нужно...

После работы почитаю про ICU, попробую собрать обёртку с вместе с этой библиотекой. Тема интересная!
Записан
ax
Чайник
*
Offline Offline

Сообщений: 60


Просмотр профиля
« Ответ #2 : Январь 19, 2011, 13:59 »

В Sqlite есть возможность зарегистрировать свою SQL ф-цию через sqlite3_create_function.

Как делал :

В qsql_sqlite.cpp создал функции
Код:
static void qUpper(sqlite3_context *context, int argc, sqlite3_value **argv)
{
    QByteArray ba = QString::fromUtf8((const char *)sqlite3_value_text(argv[0])).toUpper().toUtf8();
    sqlite3_result_text(context, ba.constData(), ba.size(), NULL);
}

static void qLower(sqlite3_context *context, int argc, sqlite3_value **argv)
{
    QByteArray ba = QString::fromUtf8((const char *)sqlite3_value_text(argv[0])).toLower().toUtf8();
    sqlite3_result_text(context, ba.constData(), ba.size(), NULL);
}

В том же файле зарегил эти ф-ции под именами qupper и qlower.
Код:
bool QSQLiteDriver::open(const QString & db, const QString &, const QString &, const QString &, int, const QString &conOpts)
{
.........

    if (sqlite3_open16(db.constData(), &d->access) == SQLITE_OK)
    {
        sqlite3_busy_timeout(d->access, qGetSqliteTimeout(conOpts));
        setOpen(true);
        setOpenError(false);

        sqlite3_create_function(d->access, "qupper", 1, SQLITE_UTF8, NULL, &qUpper, NULL, NULL);
        sqlite3_create_function(d->access, "qlower", 1, SQLITE_UTF8, NULL, &qLower, NULL, NULL);

        return true;
    }
    else
    {
.......


Теперь могу делать SQL запрос типа
Код:
select * from names where qupper(firstname) like 'АЛЕКС%' 


Записан
nata267
Гость
« Ответ #3 : Январь 19, 2011, 14:34 »

ax, супер, спасибо огромное, все заработало наконец-то...   а то я уже хотела переходить на другой тип бд
Записан
nata267
Гость
« Ответ #4 : Январь 20, 2011, 15:40 »

В своём проекте тоже использую SQLite, но написал обертку над SQLite3 API, без использования QtSQL (так работает быстрее). Я могу выложить исходники, если нужно...

После работы почитаю про ICU, попробую собрать обёртку с вместе с этой библиотекой. Тема интересная!

спасибо, не понадобилось, вопрос решен вышеизложенным методом
Записан
ashagi
Гость
« Ответ #5 : Февраль 07, 2011, 05:13 »

А можно немного поподробней насчет того, как это сделать. Я нашел qsql_sqlite.cpp в (%QTDIR)/qt/src/sql/drivers/sqlite/. Мне нужно сделать поправки в qsql_sqlite.cpp, а потом загрузить проект (%QTDIR)/qt/src/sql/sql.pro и скомпилировать его?

И еще, не могли бы вы поподробней насчет того, где ваш if-statement должен стоять в коде (там где многоточие).

Я его воткнул вот так:
Код:
bool QSQLiteDriver::open(const QString & db, const QString &, const QString &, const QString &, int, const QString &conOpts)
{
    if (isOpen())
        close();

    if (db.isEmpty())
        return false;
if (sqlite3_open16(db.constData(), &d->access) == SQLITE_OK)
    {
        sqlite3_busy_timeout(d->access, qGetSqliteTimeout(conOpts));
        setOpen(true);
        setOpenError(false);

        sqlite3_create_function(d->access, "qupper", 1, SQLITE_UTF8, NULL, &qUpper, NULL, NULL);
        sqlite3_create_function(d->access, "qlower", 1, SQLITE_UTF8, NULL, &qLower, NULL, NULL);

        return true;
    }
    else
    {
         //и весь остальной код метода обернутый в эти скобки
    }
Записан
nata267
Гость
« Ответ #6 : Февраль 07, 2011, 10:00 »

вам нужно открыть проект (%QTDIR)/qt/src/plugins/sqldrivers/sqlite/sqlite.pro, далее в файле qsql_sqlite.cpp внести все изменения описанные выше, то есть добавить определение 2х функций и поправить функцию open, у вас вроде бы правильно.  потом скомпилировать проект в режиме дебаг и релиз, получатся файлы - qsqlited4.dll, libqsqlited4.a, qsqlite4.dll, libqsqlite4.a. Их перенести в папку  (%QTDIR)/qt/plugins/sqldrivers и в папку sqldrivers относительно экзешника вашего проекта. Все библиотеки готовы! Чтобы использовать регистронезависимый поиск, запросы должны выглядеть примерно так:
Код:
select * from names where qupper(firstname) like 'АЛЕКС%' 
« Последнее редактирование: Февраль 07, 2011, 10:03 от nata267 » Записан
ashagi
Гость
« Ответ #7 : Февраль 08, 2011, 20:28 »

Спасибо! Заработало!

У меня правда не хватало дефиниции функции qGetSqliteTimeout. Если у кого-то выйдет такая же ошибка, то вот:
Код:
static int qGetSqliteTimeout(QString opts)
{
    enum { DefaultTimeout = 5000 };

    opts.remove(QLatin1Char(' '));
    if (opts.startsWith(QLatin1String("QSQLITE_BUSY_TIMEOUT="))) {
        bool ok;
        int nt = opts.mid(21).toInt(&ok);
        if (ok)
            return nt;
    }
    return DefaultTimeout;
}


Записан
ujin
Гость
« Ответ #8 : Март 05, 2011, 10:37 »

Я пишу под .NET, и долго искал готовое решение или описание того, как можно эту проблему побороть.
И вообщем нашел способ переопределять функции SQLite. В VB.NET это смотриться примерно так
Код
vb.net
Imports System.Data.SQLite
 
<SQLiteFunction(Name:="lower", Arguments:=1, FuncType:=FunctionType.Scalar)> _
Public Class LCase : Inherits SQLiteFunction
Public Overrides Function Invoke(ByVal args() As Object) As Object
If (args.Length = 0) OrElse (args(0) Is Nothing) Then Return Nothing
Return TryCast(args(0), String).ToLower
End Function
End Class
 

более подробное описание и переопределение и создание других функций типа NOW() для .NET можете смотреть тут http://sargaev.ru/?p=137
Записан
light
Гость
« Ответ #9 : Август 30, 2011, 22:29 »

Не работает с версией qt  4.7.3
функция qlower/qupper выдаёт иероглифы такого типа ����
select rowid,qlower(name)
from names_table
выдаст в столбце name иероглифы , причём столбец будет называться qlower(name)
Записан
charango
Гость
« Ответ #10 : Август 24, 2012, 13:24 »

В своём проекте тоже использую SQLite, но написал обертку над SQLite3 API, без использования QtSQL (так работает быстрее). Я могу выложить исходники, если нужно...

После работы почитаю про ICU, попробую собрать обёртку с вместе с этой библиотекой. Тема интересная!

_govorilka, можете выложить исходники Вашей обёртки?
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.065 секунд. Запросов: 23.