Что нового

Функции для работы с БД SQLite как с ini-файлом.

Kalisnik

Эволюция
Сообщения
295
Репутация
63
Функции являются альтернативой функциям ini и позволяют сохранять в файл большие объемы данных с простотой и удобством ini.

Код:
#include <SQLite.au3>
#include <SQLite.dll.au3>
#include <Array.au3>

$Return = _SQ_IniWrite('Base.db', 'Box is mine', 'Golden Key', 'jewel')

;Возвращаемое значение.
;Успешное выполнение: возвращает 0.
;Ошибка: -1 невозможно запустить библиотеку SQLite.
;		 -2 ошибка открытия файла БД.
;		 -3 ошибка создания таблицы БД.
;		 -4 ошибка записи или перезаписи значения в таблице БД.

Func _SQ_IniWrite($Filename, $Section, $Key, $Value) ;Имена переменных говорят за себя.
	Local $aResult, $iRows, $iColumns, $iRval, $Key_Vr, $Retr = 0
	$Filename = StringReplace($Filename, ".ini", ".db")
	$Section = StringToBinary($Section)
	$Section = "t" & $Section
	$Key = "'" & $Key & "'"
	$Value = "'" & $Value & "'"
	_SQLite_Startup ()
	If @error Then
		Return -1
	EndIf
	$Hnd_DB = _SQLite_Open($Filename)
	If @error Then
		_SQLite_Shutdown()
		Return -2
	EndIf
	If _SQLite_Exec(-1, "CREATE TABLE " & $Section & " (id INTEGER PRIMARY KEY, Key TEXT, Value TEXT);") <> $SQLITE_OK Then
		If _SQLite_ErrMsg() = "table " & $Section & " already exists" Then
			_SQLite_GetTable2d(-1, "SELECT Key FROM " & $Section & " ;", $aResult, $iRows, $iColumns)
			$Key_Vr = StringReplace($Key, "'", "")
			For $i = 1 To $iRows
				If $aResult[$i][0] = $Key_Vr Then
					If _SQLite_Exec(-1, "UPDATE " & $Section & " SET Value = " & $Value & " WHERE id = " & $i & ";")  <> $SQLITE_OK Then
						_SQLite_Close ()
						_SQLite_Shutdown()
						Return -4
					EndIf
					ExitLoop
				ElseIf $i = $iRows Then
					If _SQLite_Exec(-1, 'Insert into ' & $Section & '(Key, Value) values (' & $Key & ', ' & $Value & ');')  <> $SQLITE_OK Then
						_SQLite_Close ()
						_SQLite_Shutdown()
						Return -4
					EndIf
				EndIf
			Next
		Else
			_SQLite_Close ()
			_SQLite_Shutdown()
			Return -3
		EndIf
	Else
		If _SQLite_Exec(-1, 'Insert into ' & $Section & '(Key, Value) values (' & $Key & ', ' & $Value & ');')  <> $SQLITE_OK Then
			_SQLite_Close ()
			_SQLite_Shutdown()
			Return -4
		EndIf
	EndIf
	_SQLite_Close ()
	_SQLite_Shutdown()
	Return 0
EndFunc
Код:
#include <SQLite.au3>
#include <SQLite.dll.au3>
#include <Array.au3>

$Data = _SQ_IniRead('Base.db', 'Box is mine', 'Golden Key', 'no jewel')

;Возвращаемое значение.
;Успешное выполнение: возвращает значение ячейки БД.
;Ошибка: "Стандартное значение", указанное пользователем.

Func _SQ_IniRead($Filename, $Section, $Key, $empty)
	Local $aResult, $iRows, $iColumns, $iRval, $Hnd_DB, $index, $Key_Vr, $ValData
	$Filename = StringReplace($Filename, ".ini", ".db")
	$Section = StringToBinary($Section)
	$Section = "t" & $Section
	$Key = "'" & $Key & "'"
	_SQLite_Startup ()
	If @error Then
		Return $empty
	EndIf
	If FileExists($Filename) Then
		$Hnd_DB = _SQLite_Open($Filename)
		If @error Then
			_SQLite_Shutdown()
			Return $empty
		EndIf
	Else
		_SQLite_Shutdown()
		Return $empty
	EndIf
	$iRval = _SQLite_GetTable(-1, "SELECT Key FROM " & $Section & ";", $aResult, $iRows, $iColumns)
	If $iRval = $SQLITE_OK Then
		$Key_Vr = StringReplace($Key, "'", "")
		For $i = 2 To $aResult[0]
			If $aResult[$i] = $Key_Vr Then
				$index = $i - 1
				$iRval = _SQLite_GetTable(-1, "SELECT Value FROM " & $Section & " WHERE id = " & $index & ";", $aResult, $iRows, $iColumns)
				If _SQLite_ErrMsg() <> "not an error" Then
					_SQLite_Close ()
					_SQLite_Shutdown()
					Return $empty
				EndIf
				ExitLoop
			ElseIf $i = $aResult[0] Then
				_SQLite_Close ()
				_SQLite_Shutdown()
				Return $empty
			EndIf
		Next
	Else
		_SQLite_Close ()
		_SQLite_Shutdown()
		Return $empty
	EndIf
	$ValData = $aResult[2]
	_SQLite_Close ()
	_SQLite_Shutdown()
	Return $ValData
EndFunc
Код:
#include <SQLite.au3>
#include <SQLite.dll.au3>
#include <Array.au3>

$Array = _SQ_IniReadSectionNames("Base.db")

;Возвращаемое значение.
;Успешное выполнение: возвращает массив с именами таблиц (аналоги разделов в ini-файле).
;					 Переменная $Array[0] содержит число записей в массиве.
;Ошибка: -1 невозможно запустить библиотеку SQLite.
;		 -2 указанный файл БД не существует.
;		 -3 ошибка открытия файла БД.
;		 -4 ошибка чтения имен таблиц БД.

Func _SQ_IniReadSectionNames($Filename)
	Local $aResult, $iRows, $iColumns, $iRval, $Hnd_DB
	$Filename = StringReplace($Filename, ".ini", ".db")
	_SQLite_Startup ()
	If @error Then
		Return -1
	EndIf
	If FileExists($Filename) Then
		$Hnd_DB = _SQLite_Open($Filename)
		If @error Then
			_SQLite_Shutdown()
			Return -3
		EndIf
	Else
		_SQLite_Shutdown()
		Return -2
	EndIf
	$iRval = _SQLite_GetTable(-1, "SELECT name FROM sqlite_master WHERE type='table' ORDER BY name;", $aResult, $iRows, $iColumns)
	If $iRval = $SQLITE_OK Then
		For $i = 2 To $aResult[0]
			$aResult[$i] = StringTrimLeft($aResult[$i], 1)
			$aResult[$i] = BinaryToString($aResult[$i])
		Next
	Else
		_SQLite_Close ()
		_SQLite_Shutdown()
		Return -4
	EndIf
	$aResult[0] -= 1
	_ArrayDelete($aResult, 1)
	_SQLite_Close ()
	_SQLite_Shutdown()
	Return $aResult
EndFunc
Код:
#include <SQLite.au3>
#include <SQLite.dll.au3>
#include <Array.au3>

$Data = _SQ_IniReadKeyNames('Base.db', 'Box is mine')

;Возвращаемое значение.
;Успешное выполнение: возвращает массив со значениями столбца "Key" (аналоги ключей в ini-файле).
;                    Переменная $Array[0] содержит число значений в массиве.
;Ошибка: -1 невозможно запустить библиотеку SQLite.
;        -2 указанный файл БД не существует.
;        -3 ошибка открытия файла БД.
;        -4 ошибка чтения БД.

Func _SQ_IniReadKeyNames($Filename, $Section)
    Local $aResult, $iRows, $iColumns, $iRval, $Hnd_DB, $index, $ValData
    $Filename = StringReplace($Filename, ".ini", ".db")
    $Section = StringToBinary($Section)
    $Section = "t" & $Section
    _SQLite_Startup ()
    If @error Then
        Return -1
    EndIf
    If FileExists($Filename) Then
        $Hnd_DB = _SQLite_Open($Filename)
        If @error Then
            _SQLite_Shutdown()
            Return -3
        EndIf
    Else
        _SQLite_Shutdown()
        Return -2
    EndIf
    $iRval = _SQLite_GetTable(-1, "SELECT Key FROM " & $Section & ";", $aResult, $iRows, $iColumns)
    If $iRval = $SQLITE_OK Then
		$aResult[0] -= 1
		_ArrayDelete($aResult, 1)
		_SQLite_Close ()
		_SQLite_Shutdown()
		Return $aResult
    Else
        _SQLite_Close ()
        _SQLite_Shutdown()
        Return -4
    EndIf
EndFunc
Код:
#include <SQLite.au3>
#include <SQLite.dll.au3>
#include <Array.au3>

$Data = _SQ_IniDeleteKey('Base.db', 'Box is mine', 'Golden Key')

;Возвращаемое значение.
;Успешное выполнение: возвращает 0
;
;Ошибка: -1 невозможно запустить библиотеку SQLite.
;        -2 указанный файл БД не существует.
;        -3 ошибка открытия файла БД.
;        -4 ошибка запроса БД.

;Примичание: Если для удаления указать несуществующий ключь, то функция все равно возвратит 0.

Func _SQ_IniDeleteKey($Filename, $Section, $Key)
    Local $iRval, $Hnd_DB
    $Filename = StringReplace($Filename, ".ini", ".db")
    $Section = StringToBinary($Section)
    $Section = "t" & $Section
    $Key = "'" & $Key & "'"
    _SQLite_Startup ()
    If @error Then
        Return 1
    EndIf
    If FileExists($Filename) Then
        $Hnd_DB = _SQLite_Open($Filename)
        If @error Then
            _SQLite_Shutdown()
            Return 3
        EndIf
    Else
        _SQLite_Shutdown()
        Return 2
    EndIf
    $iRval = _SQLite_Exec(-1, "DELETE FROM " & $Section & " WHERE Key=" & $Key & ";")
    If $iRval = $SQLITE_OK Then
        _SQLite_Close ()
        _SQLite_Shutdown()
        Return 0
    Else
        _SQLite_Close ()
        _SQLite_Shutdown()
        Return 4
    EndIf
EndFunc
Код:
#include <SQLite.au3>
#include <SQLite.dll.au3>
#include <Array.au3>

$Data = _SQ_IniDeleteSection('Base.db', 'Box is mine')

;Возвращаемое значение.
;Успешное выполнение: возвращает 0
;
;Ошибка: -1 невозможно запустить библиотеку SQLite.
;        -2 указанный файл БД не существует.
;        -3 ошибка открытия файла БД.
;        -4 ошибка запроса БД - возможно запрашивамая секция (таблица) не существует.

Func _SQ_IniDeleteSection($Filename, $Section)
    Local $iRval, $Hnd_DB
    $Filename = StringReplace($Filename, ".ini", ".db")
    $Section = StringToBinary($Section)
    $Section = "t" & $Section
    _SQLite_Startup ()
    If @error Then
        Return 1
    EndIf
    If FileExists($Filename) Then
        $Hnd_DB = _SQLite_Open($Filename)
        If @error Then
            _SQLite_Shutdown()
            Return 3
        EndIf
    Else
        _SQLite_Shutdown()
        Return 2
    EndIf
    $iRval = _SQLite_Exec(-1, "DROP TABLE " & $Section & ";")
    If $iRval = $SQLITE_OK Then
        _SQLite_Close ()
        _SQLite_Shutdown()
        Return 0
    Else
        _SQLite_Close ()
        _SQLite_Shutdown()
        Return 4
    EndIf
EndFunc

P.S. Устранил все ограничения функций связанные с именами таблиц БД. Теперь везде можно вводить любые значения.

Дополнительные функции:
Код:
#include <SQLite.au3>
#include <SQLite.dll.au3>
#include <Array.au3>

$Return = _SQ_IniWritePlus('Base.db', 'Box is mine', 'Golden Key', 'jewel', 'TEXT')

;Возвращаемое значение.
;Успешное выполнение: возвращает 0.
;Ошибка: -1 невозможно запустить библиотеку SQLite.
;        -2 ошибка открытия файла БД.
;        -3 ошибка создания таблицы БД.
;        -4 ошибка записи или перезаписи значения в таблице БД.
;		 -5 неверный параметр ТИПА данных.

;Замечания: В функцию добавлен параметр ТИПА данных записываемых в БД. Например, указывать тип данных необходимо
;			для правильной сортировки значений в функции '_SQ_IniReadSectionPlus'.
;			Параметр $Type может принимать следующие значения:
;					1. 'TEXT' - строка.
;					2. 'INTEGER' - целое число.
;					3. 'REAL' - дробное число.
;			Если в качестве параметра $Type указать пустые кавычки (''), то по-умолчанию будет использован тип 'TEXT'.
;			Следует помнить, что тип данных присваивается всем значениям на уровне таблицы (секции ini) один раз при ее создании.
;			В последствии параметр $Type роли уже не играет, поскольку тип данных в созданной таблице уже не меняется 
;			при добавлении новых значений.

Func _SQ_IniWritePlus($Filename, $Section, $Key, $Value, $Type)
    Local $aResult, $iRows, $iColumns, $iRval, $Key_Vr, $Retr = 0
    $Filename = StringReplace($Filename, ".ini", ".db")
    $Section = StringToBinary($Section)
    $Section = "t" & $Section
    $Key = "'" & $Key & "'"
	$Value = "'" & $Value & "'"
	If $Type = 'TEXT' Or $Type = 'INTEGER' Or $Type = 'REAL' Then
		$Type = "'" & $Type & "'"
	ElseIf $Type = '' Then
		$Type = 'TEXT'
	Else
		Return -5
	EndIf

    _SQLite_Startup ()
    If @error Then
        Return -1
    EndIf
    $Hnd_DB = _SQLite_Open($Filename)
    If @error Then
        _SQLite_Shutdown()
        Return -2
    EndIf
    If _SQLite_Exec(-1, "CREATE TABLE " & $Section & " (id INTEGER PRIMARY KEY, Key TEXT, Value " & $Type & ");") <> $SQLITE_OK Then
        If _SQLite_ErrMsg() = "table " & $Section & " already exists" Then
            _SQLite_GetTable2d(-1, "SELECT Key FROM " & $Section & " ;", $aResult, $iRows, $iColumns)
            $Key_Vr = StringReplace($Key, "'", "")
            For $i = 1 To $iRows
                If $aResult[$i][0] = $Key_Vr Then
                    If _SQLite_Exec(-1, "UPDATE " & $Section & " SET Value = " & $Value & " WHERE id = " & $i & ";")  <> $SQLITE_OK Then
                        _SQLite_Close ()
                        _SQLite_Shutdown()
                        Return -4
                    EndIf
                    ExitLoop
                ElseIf $i = $iRows Then
                    If _SQLite_Exec(-1, 'Insert into ' & $Section & '(Key, Value) values (' & $Key & ', ' & $Value & ');')  <> $SQLITE_OK Then
                        _SQLite_Close ()
                        _SQLite_Shutdown()
                        Return -4
                    EndIf
                EndIf
            Next
        Else
            _SQLite_Close ()
            _SQLite_Shutdown()
            Return -3
        EndIf
    Else
        If _SQLite_Exec(-1, 'Insert into ' & $Section & '(Key, Value) values (' & $Key & ', ' & $Value & ');')  <> $SQLITE_OK Then
            _SQLite_Close ()
            _SQLite_Shutdown()
            Return -4
        EndIf
    EndIf
    _SQLite_Close ()
    _SQLite_Shutdown()
    Return 0
EndFunc
Код:
#include <SQLite.au3>
#include <SQLite.dll.au3>
#include <Array.au3>

$Data = _SQ_IniReadSectionPlus('Base.db', 'Box is mine', '+', '')

;_SQ_IniReadSectionPlus($Filename, $Section, $Sorting, $Limit)
;Описание параметров:
;					1. $Sorting: может иметь только три значения. '+' - сортировка по возрастанию (или по алфавиту), 
;								'-' - сортировка по убыванию (или по алфавиту в обратном порядке), 
;								'' - вывести как есть, без сортировки.
;					2. $Limit: определяет общее количество значений от начала списка, которые необходимо вывести из БД.
;								Значение определяется положительным целым числом. Если необходимо вывести все значения,
;								ставятся пустые кавычки ''.
;Замечания:
;					Для правильной сортировки значений БД (значений ключей ini), 
;								при записи данных используйте функцию '_SQ_IniWritePlus'.

;Возвращаемое значение.
;Успешное выполнение: возвращает двумерный массив со значениями столбцов "Key" и "Value" (по аналоги ключей в ini-файле и их значения).
;
;Ошибка: -1 невозможно запустить библиотеку SQLite.
;        -2 указанный файл БД не существует.
;        -3 ошибка открытия файла БД.
;        -4 ошибка чтения БД.
;		 -5 неверно указан параметр LIMIT.

Func _SQ_IniReadSectionPlus($Filename, $Section, $Sorting, $Limit)
    Local $aResult, $iRows, $iColumns, $iRval, $Hnd_DB, $index, $ValData
    $Filename = StringReplace($Filename, ".ini", ".db")
    $Section = StringToBinary($Section)
    $Section = "t" & $Section

	If $Sorting = '+' Then
		$Sorting = " ORDER BY Value"
	ElseIf $Sorting = '-' Then
		$Sorting = " ORDER BY Value DESC"
	Else
		$Sorting = ''
	EndIf

	If StringIsDigit($Limit) And $Limit <> '0' And $Limit <> 0 Then
		$Limit = " LIMIT " & "'" & $Limit & "'"
	ElseIf $Limit <> '' Then
		Return -5
	EndIf


    _SQLite_Startup ()
    If @error Then
        Return -1
    EndIf
    If FileExists($Filename) Then
        $Hnd_DB = _SQLite_Open($Filename)
        If @error Then
            _SQLite_Shutdown()
            Return -3
        EndIf
    Else
        _SQLite_Shutdown()
        Return -2
    EndIf
    $iRval = _SQLite_GetTable2d(-1, "SELECT Key, Value FROM " & $Section & $Sorting & $Limit & ";", $aResult, $iRows, $iColumns)
    If $iRval = $SQLITE_OK Then
		_ArrayDelete($aResult, 0)
		_SQLite_Close ()
		_SQLite_Shutdown()
		Return $aResult
    Else
        _SQLite_Close ()
        _SQLite_Shutdown()
        Return -4
    EndIf
EndFunc
 

Suppir

Продвинутый
Сообщения
967
Репутация
62
Дело полезное, но меня интересует вот что.


1. Средний пользователь не может открыть db-файл, но отредактировать ini ему нужно.
Необходимы функции text_to_db() и db_to_text(). Первая из них будет "выливать" db в обычный текстовый ini(или txt), а вторая - сможет прочитать этот текстовый ini в базу данных. Это нужно для того, чтобы средний пользователь мог в блокноте редактировать значения в базе данных.


2. В ini файле часто возникает потребность написать в определенную секцию просто ключи, без значений. Но приходится писать
[Секция]
ключ1=0
ключ2=0
ключ3=0

т.е. дорисовывать ненужные значения с нулями. Это загромождает ini и делает его малопонятным пользователю. Необходимо сделать так, чтобы функция читала ini даже в том случае, когда написано:

[Секция]
ключ1
ключ2
ключ3

и при этом сама добавляла значение = 0, если значение отсутствует.
 
Автор
K

Kalisnik

Эволюция
Сообщения
295
Репутация
63
Suppir [?]
Средний пользователь не может открыть db-файл, но отредактировать ini ему нужно.
Так не годится? :smile: - это что касается ручного редактирования.
А так, могу еще написать функции _SQ_IniReadKeyNames, _SQ_IniDeleteSection, _SQ_IniDeleteKey.
 

Kari

Новичок
Сообщения
5
Репутация
0
Автор, может допишешь остальное? 8)
 

Kari

Новичок
Сообщения
5
Репутация
0
Kalisnik сказал(а):
Kari [?]
Автор, может допишешь остальное?
Обязательно, как будет свободное время. :smile:

P.S. Добавил: _SQ_IniReadKeyNames.
а поиск реалистично сделать? например если я хочу выводить первые 10 ключей с максимальной/минимальной цифрой (ну или еще по каким-то параметрам), я имею ввиду без циклов и т.д., это же вроде можно сделать в дб (с sql не знаком).
 
Автор
K

Kalisnik

Эволюция
Сообщения
295
Репутация
63
Kari [?]
а поиск реалистично сделать? например если я хочу выводить первые 10 ключей с максимальной/минимальной цифрой
В MySQL это возможно, наверно и в SQLite тоже, надо почитать. Я сейчас больше с MySQL'ем работаю. :laugh:
 

Kari

Новичок
Сообщения
5
Репутация
0
Kalisnik сказал(а):
Kari [?]
а поиск реалистично сделать? например если я хочу выводить первые 10 ключей с максимальной/минимальной цифрой
В MySQL это возможно, наверно и в SQLite тоже, надо почитать. Я сейчас больше с MySQL'ем работаю. :laugh:
хорошо если возможно, и если ты это реализуешь в дополнение к ини=)
 
Автор
K

Kalisnik

Эволюция
Сообщения
295
Репутация
63
Kari

Хотя я пожалуй не совсем понял. Можно сделать _SQ_IniReadSectionPlus функцию - она будет выводить все значения (либо можно сделать ключ=значение) в секции, а также можно добавить дополнительные параметры. Например вывести первые 10-ть значений из секции, или вывести десять значений (подряд) начиная с 30-ой записи и т.п. Можно также выводить значения по какому-то критерию - если я правильно понял, это и требуется?
 

Kari

Новичок
Сообщения
5
Репутация
0
Kalisnik сказал(а):
Kari

Хотя я пожалуй не совсем понял. Можно сделать _SQ_IniReadSectionPlus функцию - она будет выводить все значения (либо можно сделать ключ=значение) в секции, а также можно добавить дополнительные параметры. Например вывести первые 10-ть значений из секции, или вывести десять значений (подряд) начиная с 30-ой записи и т.п. Можно также выводить значения по какому-то критерию - если я правильно понял, это и требуется?
Думаю требуется выделенное черным! Например будет скрипт связанный с какой-нибудь игрой, а там кучка (игроков) допустим в этом "ини", player=points, там 100-200 не важно, тобишь захочется получить "лучших" 10(ну или другое число, не суть) либо "худших", Так понятно? Вот для этого нужен такой поиск (по критерию)
 
Автор
K

Kalisnik

Эволюция
Сообщения
295
Репутация
63
Добавил _SQ_IniWritePlus и _SQ_IniReadSectionPlus.
 
Автор
K

Kalisnik

Эволюция
Сообщения
295
Репутация
63
Kari

Завтрецом :smile:
 
Автор
K

Kalisnik

Эволюция
Сообщения
295
Репутация
63
Для UDF эти функции нужно обтесать и отладить :smile:. А про глобальную переменную $g_hDll_SQLite я не знал, спасибо за подсказку AZJIO.
Да, постоянная подгрузка выгрузка SQLite не самый лучши вариант - на досуге это дело надо будет обдумать.
 
Автор
K

Kalisnik

Эволюция
Сообщения
295
Репутация
63
Добавил _SQ_IniDeleteKey и _SQ_IniDeleteSection.
 
Верх