Форум поддержки пользователей. LibreOffice, Apache OpenOffice, OpenOffice.org

Форум поддержки пользователей. LibreOffice, Apache OpenOffice, OpenOffice.org

15 Май 2021, 08:56 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
Новости: Здесь можно поблагодарить участников форума Улыбка
 
   Начало   Помощь Поиск Войти Регистрация    задать вопрос  
Страниц: 1 2 »   Вниз
  Печать  
Автор Тема: LO Calc падает при обращении к sqlite_sequence БД SQLite из StarBasic  (Прочитано 723 раз)
0 Пользователей и 1 Гость смотрят эту тему.
ost
Форумчанин
***
Offline Offline

Сообщений: 175


« Стартовое сообщение: 29 Апрель 2021, 06:31 »

Доброго.
Что-то делаю не так. Помогите, пож., разобраться.

Есть БД SQLite3. Код StarBasic обращается к ней посредством трансляции SQL-запросов ч/з БД ".odb", зарегистрированную в LO, и ODBC-драйвер версии 0.9998.00.00 отсюда http://www.ch-werner.de/sqliteodbc/.

В коде нужно определить количество и id новых записей, которые были вставлены в БД в ходе исполнения некого "куска" кода.
Для этого до и после исполнения "куска" запрашиваю значение поля "seq" из таблицы "sqlite_sequence" БД SQLite таким образом:
Код:
sSQL = "SELECT seq FROM sqlite_sequence WHERE name = """ & sTablNameInt &""""
oRs = MySet._CreateRowSet(DBName, sSQL)

При этом код корректно отрабатывает первый раз (до исполнения "куска"). При выполнении этого же кода после вставки записей в БД LO падает. Записи в ходе выполнения "куска" в БД вставляются корректно.

Функция "_CreateRowSet" в MySet выглядит так:
Код:
Function _CreateRowSet(sDBName, sSQLCommand as String)
'===Функция создает объект RowSet из имени базы и SQLкоманды
RowSet = createUnoService("com.sun.star.sdb.RowSet")
RowSet.DataSourceName = sDBName
RowSet.CommandType = com.sun.star.sdb.CommandType.Command
RowSet.EscapeProcessing=False

RowSet.Command=sSQLCommand
RowSet.execute() ' выполняем
_CreateRowSet=RowSet
End Function '_CreateRowSet

На борту:
Version: 7.1.1.2 (x64) / LibreOffice Community
Build ID: fe0b08f4af1bacafe4c7ecc87ce55bb426164676
CPU threads: 4; OS: Windows 6.1 Service Pack 1 Build 7601; UI render: Skia/Raster; VCL: win
Locale: ru-RU (ru_RU); UI: ru-RU
Calc: CL

SQLite3:
3.35.4
 
« Последнее редактирование: 29 Апрель 2021, 07:04 от ost » Записан
economist
Форумчанин
***
Offline Offline

Сообщений: 1 461


« Ответ #1: 29 Апрель 2021, 08:18 »

1) Зачем запрашивать весь столбец seq, когда "дешевле" запросить max(seq) ?

2) Для определения количества и id новых записей до/после - можно считать всегда имеющееся готовое поле max(ROWID) до и после вставки

3) Попробуйте не-литералы обрамлять ' вместо "" - так код чище, SQLite позволяет.

sSQL = "SELECT seq FROM sqlite_sequence WHERE name = " '" & sTablNameInt &"' "

Но ваш код чистый, падать не должно. Самые частые падучие ситуации с Base, имхо, это запрос полей по индексу за пределами имеющихся.
« Последнее редактирование: 29 Апрель 2021, 08:21 от economist » Записан

Руб. за сто, что Питоньяк
Любит водку и коньяк!
Потому что мне, без оных, -
Не понять его никак...
ost
Форумчанин
***
Offline Offline

Сообщений: 175


« Ответ #2: 29 Апрель 2021, 10:09 »

economist,
благодарю за ответ и замечания.

Поправил так:
Код:
sSQL = "SELECT max(ROWID) FROM " & sTablNameInt

Результат тот же. LO падает на втором по счету запросе (после вставки записей в БД) на строке
Код:
RowSet.execute() ' выполняем
функции "_CreateRowSet" из MySet.
У меня включена поддержка внешних ключей. Возможно что-то здесь. Хотя я не понимаю, как это может быть связано.
Записи в БД вставляются корректно. =(

UPD
А можно ли "обнулить" объект RowSet? И как?
Отвечу. Видимо, так "oRs = Nothing"

UPD
"оRs = Nothing", а так же отключение от БД и повторное подключение к ней перед вторым запросом не помогают.
« Последнее редактирование: 29 Апрель 2021, 10:46 от ost » Записан
kompilainenn
Мастер
*****
Offline Offline

Сообщений: 3 268



« Ответ #3: 29 Апрель 2021, 10:46 »

Не поленитесь запилить баг репорт
Записан

Поддержать разработчиков LibreOffice можно тут, а наш форум вот тут
ost
Форумчанин
***
Offline Offline

Сообщений: 175


« Ответ #4: 29 Апрель 2021, 11:01 »

Не понимаю даже где проблема. В БД или в кривых руках, или в LO.
Записан
economist
Форумчанин
***
Offline Offline

Сообщений: 1 461


« Ответ #5: 29 Апрель 2021, 11:14 »

Покажите свои картинки вот этого (вложения):


* sqlite ODBC setting.jpg (35.79 Кб, 629x517 - просмотрено 7 раз.)

* sqlite BASE setting.jpg (58.85 Кб, 600x824 - просмотрено 6 раз.)
Записан

Руб. за сто, что Питоньяк
Любит водку и коньяк!
Потому что мне, без оных, -
Не понять его никак...
economist
Форумчанин
***
Offline Offline

Сообщений: 1 461


« Ответ #6: 29 Апрель 2021, 11:26 »

Рекордсет RowSet - странная штука, способная изумлять. Попробуйте подвигать курсор перед вторым запросом (по одному варианту):

RowSet.beforefirst()
RowSet.first()
RowSet.next()
RowSet.last()

Вы также можете узнать число строк в нём прямо в Basic: RowSet.RowCount()
Также можно прочесть без "переусложнения" SQL - заголовок поля и его значение в текущей строке:

RowSet.Columns(0).Name ' заголовок 0-го поля
RowSet.getString(1) ' значение 0-го поля (хотя стоит 1 Непонимающий)
 
Записан

Руб. за сто, что Питоньяк
Любит водку и коньяк!
Потому что мне, без оных, -
Не понять его никак...
ost
Форумчанин
***
Offline Offline

Сообщений: 175


« Ответ #7: 29 Апрель 2021, 12:27 »

Покажите свои картинки

Попробовал сейчас релизы LO 7.1.2 и 7.0.5. В обоих случаях  - падения на упомянутой строке.





* odbc.png (9.72 Кб, 422x334 - просмотрено 8 раз.)

* LO Base.png (20.55 Кб, 376x518 - просмотрено 8 раз.)
« Последнее редактирование: 29 Апрель 2021, 12:29 от ost » Записан
ost
Форумчанин
***
Offline Offline

Сообщений: 175


« Ответ #8: 29 Апрель 2021, 12:36 »

Попробуйте подвигать курсор перед вторым запросом
А имеет ли это смысл, поскольку делал перед вторым запросом:
"оRecordSet = Nothing", а так же отключение от БД и повторное подключение к ней?
Записан
economist
Форумчанин
***
Offline Offline

Сообщений: 1 461


« Ответ #9: 29 Апрель 2021, 12:38 »

Имеет, потому что оRecordSet = Nothing лучше убрать и проверить многократное срабатывает первого запроса.
Записан

Руб. за сто, что Питоньяк
Любит водку и коньяк!
Потому что мне, без оных, -
Не понять его никак...
ost
Форумчанин
***
Offline Offline

Сообщений: 175


« Ответ #10: 29 Апрель 2021, 12:50 »

RowSet.beforefirst() не помогло.
Если закомментировать второй запрос. Весь код всегда выполняется успешно. Данные в БД вставляются.
Записан
mikekaganski
Гуру
*******
Offline Offline

Пол: Мужской
Расположение: Хабаровск -> Москва
Сообщений: 2 080


« Ответ #11: 29 Апрель 2021, 13:24 »

LO падает
Не поленитесь запилить баг репорт
Не понимаю даже где проблема. В БД или в кривых руках, или в LO.

LO падает никогда не бывает из-за "кривых рук". Программа не должна падать. Проблема может быть в ЛО, или в драйверах БД (если они загружаются в программу).
Пожалуйста, последуйте совету kompilainenn. Вы уже столько тут дискутируете, а если бы был пример БД с кодом, который можно было бы запустить, я уже давно бы нашёл, где сбой (не факт, что исправил бы, но по крайней мере ситуация была бы ясна). И может быть, посоветовал бы, как обойти. Но ведь дискутировать вокруг чёрного ящика интереснее, верно? Подмигивающий
Записан

С уважением,
Михаил Каганский
economist
Форумчанин
***
Offline Offline

Сообщений: 1 461


« Ответ #12: 29 Апрель 2021, 13:36 »

Еще можно попробовать вместо второго запроса обратиться к БД через Statement (всё равно создается recordset, но он точно другой):

DatabaseContext = createUnoService("com.sun.star.sdb.DatabaseContext")
DataSource = DatabaseContext.getByName("ИМЯБАЗЫ") ' указать!
Connection = DataSource.GetConnection("", "")   
Statement = Connection.createStatement()
rs = Statement.executeQuery("SELECT max(seq) FROM sqlite_sequence")
rs.next()
msgbox rs.getString(1)


UPD: Воссоздал ситуацию у себя и понял что вставка новых строк "портит" прежний RowSet, при обращении к нему возникает ошибка (у меня либра не падает). То есть нужно после вставки:
1) пересоздать заново RowSet
2) шагнуть в него RowSet.next()

Следующий псевдокод (некогда) у меня отработал без ошибок:

RowSet = Statement.executeQuery("SELECT max(ROWID) FROM ЗАЯВКИ")
RowSet.next()
msgbox RowSet.getString(1) ' ок
Statement.executeUpdate("INSERT INTO ЗАЯВКИ (Материал, Марка) VALUES ('123', '123')")
RowSet = Statement.executeQuery("SELECT max(ROWID) FROM ЗАЯВКИ")
RowSet.next()
msgbox RowSet.getString(1) ' ок


 
« Последнее редактирование: 29 Апрель 2021, 14:15 от economist » Записан

Руб. за сто, что Питоньяк
Любит водку и коньяк!
Потому что мне, без оных, -
Не понять его никак...
ost
Форумчанин
***
Offline Offline

Сообщений: 175


« Ответ #13: 29 Апрель 2021, 18:33 »

Но ведь дискутировать вокруг чёрного ящика интереснее, верно?
Не верно. Но, "как есть" выложить в общий доступ не могу. Чтобы "навести анонимность" нужно потратить время. На корректировку базы, кода, и пр.
Мне показалось, что затраты времени (коего сейчас крайне мало) не оправданы, тем более, что вопрос касался, как мне казалось, моей элементарной ошибки в коде. Видимо, моя оценка была не верна (ибо не программист от слова совсем), поэтому и диспут.
Стараюсь, по-возможности, разобраться сам. Пользуюсь, конечно, знаниями и опытом участников форума. Благодарен. Отдельное спасибо, economist'у за терпение и толковые предложения. Постараюсь выложить пример базы и кода. Позже. Если не получится как то решить проблему.
« Последнее редактирование: 29 Апрель 2021, 18:54 от ost » Записан
ost
Форумчанин
***
Offline Offline

Сообщений: 175


« Ответ #14: 30 Апрель 2021, 08:50 »

Следующий псевдокод (некогда) у меня отработал без ошибок:
У меня тоже. Супер! Спасибо.
Записан
Страниц: 1 2 »   Вверх
  Печать  
 
Перейти в:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.21 | SMF © 2006-2009, Simple Machines Valid XHTML 1.0! Valid CSS!