AutoHotkey Homepage AutoHotkey Community
Let's help each other out
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

#INCLUDE SQLite.ahk - Functions to access SQLite3 DB's
Goto page 1, 2, 3  Next
 
Post new topic   Reply to topic    AutoHotkey Community Forum Index -> Scripts & Functions
View previous topic :: View next topic  
Author Message
nick



Joined: 24 Aug 2005
Posts: 345
Location: Berlin / Germany

PostPosted: Wed Sep 20, 2006 8:54 am    Post subject: #INCLUDE SQLite.ahk - Functions to access SQLite3 DB's Reply with quote

Hello,

I found an interesting script SQlite.au3 at http://www.autoitscript.com/forum/index.php?showtopic=17099 and thought it could be interesting for the AHK community too. So I tried a "translation" and now in my opinion the important functions are realized and raw tested. I'll try to use for some productive tool, but I'd want some others to test it too and give response for missing functions and/or optimizations.

To try out you need the SQLite3.exe and SQLite3.dll (3.3.7) from http://www.sqlite.org/download.html. Both are free and don't need any installation. Once there, you should have a look on http://www.sqlite.org/lang.html and
http://www.sqlite.org/sqlite.html. This Documentation is rather brief, but I found no other.

Now, what's the script for:

The script's functions give full access on SQLite3 databases. You even can create databases - if you really need - using the _SQLite_SQLiteExe function.

Queries (SELECT statements) are supported as follows:

_SQLite_GetTable returns the full result of a query including column names in a string with column values/names separated by "|" and rows seperated by "`n".

_SQLite_Query prepares a query and creates a query handle. To get column names, you have to call _SQLite_Fetchnames, to get the values of first/next row, you have to call _SQLite_FetchData. The results are passed out in a string with "|" separated values.

All non query SQL-statements (INSERT, UPDATE, DELETE...) are executed via _SQLite_Exec.

To make testing a little bit easier I added the script SQLite_sample.ahk. It creates a small database, tries some functions on it and displays the result of a SELECT * FROM ... in a ListView.

Changelog:

2006-09-23
    New global $SQLITE_s_ERROR for functions error messages instead of "ByRef $sErr" parameter in function calls.
    New optional parameter $iMaxResult in _SQLite_GetTable to restrict the amount of returned rows.
    SQLite_sample.ahk adapted.

2006-11-15
    Adjusted code in _SQLite_GetTable to run under AHK 1.0.45.
    Maybe some more changes will be needed!

SQLite.ahk - 2006-11-15

Please download the script from http://www.autohotkey.net/~dwuttke/SQLite/SQLite.ahk



Here's some sample code to show how to use the functions:

Code:
;===============================================================================
; Script Function:  Sample script for SQLite.ahk
; AHK Version:      1.0.44.13
; Language:         English
; Platform:         WinXP
; Author:           nick
; Version:          0.00.01/2006-09-23/nick
;===============================================================================
; Autoexec Section
;===============================================================================
; AHK Settings
;===============================================================================
#NoEnv
#SingleInstance force
#Persistent
SetWorkingDir %A_ScriptDir%
SetBatchLines -1
SetWinDelay -1
;===============================================================================
; Includes
;===============================================================================
#Include %A_ScriptDir%
#Include SQLite.ahk
;===============================================================================
; Variables
;===============================================================================
$iRC := 0
$sErr := ""
;===============================================================================
;   Use SQLITE3.EXE - Create a Database and Table
;===============================================================================
$sDBFileName := "TEST.DB"
$sCSVFileName := "TEST.CSV"
$sDBFileName := "TEST.DB"
$sCSVFileName := "TEST.CSV"
$sInput =
(Ltrim
   CREATE TABLE Test (Name, Fname, Phone, Room);
   .separator \t
   .import '%$sCSVFileName%' Test
)
$sOutput := ""
IfExist %$sDBFileName%
{
   FileDelete %$sDBFileName%
}
IfExist %$sCSVFileName%
{
   FileDelete %$sCSVFileName%
}
Loop 99
{
   FileAppend,
   (LTrim Join
      Name%A_Index%%A_Tab%Fname%A_Index%%A_Tab%
      Phone%A_Index%%A_Tab%Room%A_Index%`n
   ),%$sCSVFileName%
}
$iRC := _SQLite_SQLiteExe($sDBFileName, $sInput, $sOutput)
If ($iRC <> 0)
{
   MsgBox Fehler bei SQLITEEXE: %$iRC%`n%$SQLITE_s_ERROR%`n%$sOutput%
   ExitApp
}
;===============================================================================
;   Use SQLITE3.DLL - Query the Database
;===============================================================================
$iCols := 0
$iRows := 0
$sRC := ""
$sResult := ""
$iRC := _SQLite_Startup()
If ($iRC <> 0)
{
   MsgBox Fehler bei STARTUP: %$iRC%
}
$sRC := _SQLite_LibVersion()
If ($SQLITE_s_VERSION <> $sRC)
{
   MsgBox,
   (LTrim
      SQLite Scriptversion = %$SQLITE_s_VERSION%
      SQLite DLL version   = %$sRC%
   )
}
$iRC := _SQLite_OpenDB($sDBFileName)
If ($iRC <> 0)
{
   MsgBox Fehler bei OPENDB: %$iRC%
}
$sSQL := "INSERT INTO Test VALUES('Name111', 'Fname111', 'Phone111', 'Room111');"
$iRC := _SQLite_Exec($SQLITE_h_DB, $sSQL)
If ($iRC <> 0)
{
   MsgBox Fehler bei EXEC: %$iRC%`n%$SQLITE_s_ERROR%
}
$iRC := _SQLite_LastInsertRowID(-1, $iRows)
If ($iRC <> 0)
{
   MsgBox Fehler bei EXEC: %$iRC%`n%$SQLITE_s_ERROR%
}
Msgbox Last inserted Row = %$iRows%
$sSQL := "SELECT * FROM Test;"
$i := A_TickCount
$iRC := _SQLite_GetTable($SQLITE_h_DB, $sSQL, $sResult, $iRows, $iCols)
If ($iRC <> 0)
{
   MsgBox Fehler bei GETTABLE: %$iRC%
}
MsgBox % A_TickCount - $i
Msgbox Zeilen : %$iRows%, Spalten : %$iCols%
/*
$iRC := _SQLite_Query($SQLITE_h_DB, $sSQL)
If ($iRC <> 0)
{
   MsgBox Fehler bei QUERY: %$iRC%
}
$iRC := _SQLite_FetchNames(-1, $sResult)
If ($iRC <> 0)
{
   MsgBox Fehler bei FETCHNAMES: %$iRC%
}
$sResult = %$sResult%`n
MsgBox %$sResult%
$iRC := _SQLite_FetchData(-1, $sResult)
If ($iRC <> 0)
{
   MsgBox Fehler bei FETCHNAMES: %$iRC%
}
MsgBox %$sResult%
$iRC := _SQLite_QueryFinalize(-1)
If ($iRC <> 0)
{
   MsgBox Fehler bei FINALIZE: %$iRC%
}
*/
; Show the Result in Listview
Gosub SHOW_LISTVIEW
;  Wait for GUiClose
WinWait, SQLite Result - Close with ESC, , 20
IfWinExist, SQLite Result - Close with ESC
{
   WinWaitClose, SQLite Result - Close with ESC
}
Sleep 100
; Now GUI is closed
$iRC := _SQLite_CloseDB(-1)
If ($iRC <> 0)
{
   MsgBox Fehler bei CLOSEDB: %$iRC%
}
$iRC := _SQLite_ShutDown()
If ($iRC <> 0)
{
   MsgBox Fehler bei SHUTDOWN: %$iRC%
}
ExitApp
;===============================================================================
;   Gui Subs
;===============================================================================
SHOW_LISTVIEW:
$LV =
$LVCOUNT := $iRows + 1
Loop, Parse, $sResult, `n
{
   If (A_Index = 1)
   {
      Gui, Add, ListView, r20 w420 Grid Count%$LVCOUNT%, %A_LoopField%
   }
   Else
   {
      StringSplit, $LV, A_LoopField, |
      LV_ADD("", $LV1, $LV2, $LV3, $LV4)
   }
}
LV_ModifyCol(1, 100)
LV_ModifyCol(2, 100)
LV_ModifyCol(3, 100)
LV_ModifyCol(4, 100)
Gui, Show, Autosize Center, SQLite Result - Close with ESC
Return
;===============================================================================
GuiClose:
GuiEscape:
Gui, Destroy
Return


Have a nice time and tell me your opinions![list=][/list]
_________________
nick

denick @ http://de.autohotkey.com/forum/


Last edited by nick on Wed Nov 15, 2006 6:17 am; edited 2 times in total
Back to top
View user's profile Send private message
PhiLho



Joined: 27 Dec 2005
Posts: 6721
Location: France (near Paris)

PostPosted: Wed Sep 20, 2006 9:34 am    Post subject: Reply with quote

Oh, I suppose it is a follow-up of http://www.autohotkey.com/forum/viewtopic.php?t=8324
Thank you for sharing, I am sure lot of people will find this interesting.
The alternative is Cheetah -- lighter, but less common, no SQL.
Or the big MySQL...
Or using ODBC for abstracting the database.
_________________
vPhiLho := RegExReplace("Philippe Lhoste", "^(\w{3})\w*\s+\b(\w{3})\w*$", "$1$2")
Back to top
View user's profile Send private message Visit poster's website
nick



Joined: 24 Aug 2005
Posts: 345
Location: Berlin / Germany

PostPosted: Wed Sep 20, 2006 10:40 am    Post subject: Reply with quote

PhiLho wrote:
Oh, I suppose it is a follow-up of http://www.autohotkey.com/forum/viewtopic.php?t=8324


Yes, you're right. There was not much response, but I wanted to have it, so I went on.

PhiLho wrote:
The alternative is Cheetah -- lighter, but less common, no SQL.
Or the big MySQL...
Or using ODBC for abstracting the database.


I don't know Cheetah, but in my opinion AHK and SQlite seem to be perfect for each other. To deploy tools, no installation is needed, you have only to copy the script.exe and the SQLite3.dll (and SQLite3.exe, when used) into the same folder (or SQLite... into the system path) for direct, simple and fast database access with SQL support. I like it.
_________________
nick

denick @ http://de.autohotkey.com/forum/
Back to top
View user's profile Send private message
Chris
Site Admin


Joined: 02 Mar 2004
Posts: 10474

PostPosted: Thu Sep 21, 2006 11:05 am    Post subject: Reply with quote

I like your introductory remarks and the nicely structured script. Thanks for creating and sharing this resource.
Back to top
View user's profile Send private message Send e-mail
Guest






PostPosted: Fri Sep 22, 2006 8:05 am    Post subject: error message in sample script Reply with quote

Thanks for your work.

The sample script returns an error message

Quote:
Error at line 159.

Line Text: SHOW_LISTVIEW
Error: Duplicate label.



Dirk
Back to top
PhiLho



Joined: 27 Dec 2005
Posts: 6721
Location: France (near Paris)

PostPosted: Fri Sep 22, 2006 8:28 am    Post subject: Reply with quote

Dirk, remember to use a nickname, even if not logged in, thanks.
You should do a search in the code you try to run. Searching SHOW_LISTVIEW in the topic shows it only thrice: a Gosub, the label definition, and in your message.
Perhaps you accidentally pasted the code twice?
_________________
vPhiLho := RegExReplace("Philippe Lhoste", "^(\w{3})\w*\s+\b(\w{3})\w*$", "$1$2")
Back to top
View user's profile Send private message Visit poster's website
finet



Joined: 22 Sep 2006
Posts: 4
Location: Belgium

PostPosted: Fri Sep 22, 2006 2:13 pm    Post subject: error message sample script Reply with quote

I copied the script one again. Error message remains.

Dirk
Back to top
View user's profile Send private message
Dolby
Guest





PostPosted: Fri Sep 22, 2006 3:09 pm    Post subject: Reply with quote

I had no problems with the script. It works fine. The issue must be on your end.
Back to top
finet



Joined: 22 Sep 2006
Posts: 4
Location: Belgium

PostPosted: Mon Sep 25, 2006 8:31 am    Post subject: Reply with quote

It was indeed on my end.
Sorry!
Dirk
Back to top
View user's profile Send private message
valenfor



Joined: 26 Feb 2005
Posts: 20

PostPosted: Tue Nov 14, 2006 8:56 am    Post subject: Reply with quote

OK, as I noted in the thread I had started thanks again for this module. In my excitement I have been up way past the time I should be sleeping however trying to figure out an error I am having.

I am sorry for what may be a double post, however I wanted to make sure I got this in the right spot since you started a new thread. I also realize the above person's note that 'it worked for them so it must be on my machine'. I wouldn't disagree, however I could use some pointers if someone has any as to what might be the cause.

On my first run, I had experience a strange error where the program was overwriting itself replacing items with 'name name' as I mention in the original thread here http://www.autohotkey.com/forum/viewtopic.php?t=8324

However I started fresh and now I am getting another error that feels similar stating: Error in #include file "C:\dev\sqliteahk\SQLite.ahk": This DllCall requires a prior VarSetCapacity. The program is now unstable and will exit. It no longer hard crashes to the point it wants to send a note to Microsoft (as it did in my first error description) however it does still fail after showing the 'Last Insert ID'. It is not overwriting the code with various pieces of 'Name Name'

Now I have made sure I am on the same SQLite version, and have moved from 3.7 to 3.8 without any changes. I had 1.0.45 of AHK installed, and that was when I had the first error described (name name replacing items in the running file). I tried downgrading to 1.0.44 as the author points out in the source with no change, however when I moved up to the latest version that is when the error did change.

Again, any thoughts on what I may have done wrong here would be appreciated. I look forward to implementing all kinds of goodies using SQLite which I didn't have the ability to complete myself - KUDO's.
Back to top
View user's profile Send private message
PhiLho



Joined: 27 Dec 2005
Posts: 6721
Location: France (near Paris)

PostPosted: Tue Nov 14, 2006 9:50 am    Post subject: Reply with quote

This is because AutoHotkey has become, with latest version, more picky on the size of variables used as buffer, ie. where the WinAPI will write.
That's a good thing, the old versions probably has hidden side effects, like memory overwriting.

Quick fix: Search in the code all the "UInt *" declarations in DllCalls.
Look at the variable name after this declaration. It is, most of the time, initialized like $h_DB := 0. Just change 0 to 0000 and it should be OK.
In _SQLite_Exec, $iErr isn't even initialized, add a $iErr := 0000 line after $i_RC init.

I suppose nick will update his script. nick, I suggest you remove the code pasted in the message and upload the file to AutoHotkey.net, if possible. Above a given number of lines, this becomes impractical. Thanks.
Note that the sample can remain there, it is rather small and it gives an idea of what the API looks like.

I fear the day the v.2 will be out... Will lot of scripts no longer working, we will have lot of similar messages...
_________________
vPhiLho := RegExReplace("Philippe Lhoste", "^(\w{3})\w*\s+\b(\w{3})\w*$", "$1$2")
Back to top
View user's profile Send private message Visit poster's website
nick



Joined: 24 Aug 2005
Posts: 345
Location: Berlin / Germany

PostPosted: Tue Nov 14, 2006 11:34 am    Post subject: Reply with quote

PhiLho wrote:
I suppose nick will update his script. nick, I suggest you remove the code pasted in the message and upload the file to AutoHotkey.net, if possible. Above a given number of lines, this becomes impractical. Thanks.
Note that the sample can remain there, it is rather small and it gives an idea of what the API looks like.


Hello PhiLho and valenfor,

I'll try to find out what's wrong, but it may need a few days. I'll also follow the suggestion to move the script to AutoHotkey.net.

See you!
_________________
nick

denick @ http://de.autohotkey.com/forum/
Back to top
View user's profile Send private message
PhiLho



Joined: 27 Dec 2005
Posts: 6721
Location: France (near Paris)

PostPosted: Tue Nov 14, 2006 12:18 pm    Post subject: Reply with quote

nick wrote:
I'll try to find out what's wrong, but it may need a few days.
Please, re-read my post, I explain how to correct it... I didn't tested it, though! Some issues might remain.
_________________
vPhiLho := RegExReplace("Philippe Lhoste", "^(\w{3})\w*\s+\b(\w{3})\w*$", "$1$2")
Back to top
View user's profile Send private message Visit poster's website
valenfor



Joined: 26 Feb 2005
Posts: 20

PostPosted: Tue Nov 14, 2006 12:41 pm    Post subject: Reply with quote

Thank you for the tip. I did the changes you suggested PhiLho, however the error still persisted. I traced back and found that when this call was made inside _SQLite_GetTable the $s_Col doesn't have its capacity set. So, just trying to find the solution I added this line as shown in the code below:

VarSetCapacity($s_Col, 1024)


Code:

   VarSetCapacity($sResult, $i_GetRows * $iCols * $iCharSize)
   VarSetCapacity($s_Col, 1024)
   $i_Off := 0
   Loop %$i_GetRows%
   {
      $s_Row =
      Loop %$iCols%
      {
         $s_Col =
         DllCall("lstrcpyA"
               , "Str", $s_Col
               , "Uint", _#SQLite_ExtractInt($p_Result, $i_Off))
         $s_Row = %$s_Row%%$s_Col%|
         $i_Off += 4
      }
      StringTrimRight $s_Row, $s_Row, 1
      $sResult = %$sResult%%$s_Row%`n
   }



This did fix the problem and it ran. I realize that the column size should be calculated, however I wanted to see if I at least found the right location. Just figured I would post in case it saves you some time Nick.

Thanks again for the help.

Val.
Back to top
View user's profile Send private message
nick



Joined: 24 Aug 2005
Posts: 345
Location: Berlin / Germany

PostPosted: Tue Nov 14, 2006 3:36 pm    Post subject: Reply with quote

valenfor wrote:
This did fix the problem and it ran. I realize that the column size should be calculated, however I wanted to see if I at least found the right location. Just figured I would post in case it saves you some time Nick.


Hi,

I fixed it too, but too late! Sad

What do you think about an additional optional parameter like iMaxLength=256 to pass the maximum column width to the function whenever needed?

THX for using the script and supporting me! Very Happy
_________________
nick

denick @ http://de.autohotkey.com/forum/
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    AutoHotkey Community Forum Index -> Scripts & Functions All times are GMT
Goto page 1, 2, 3  Next
Page 1 of 3

 
Jump to:  
You can post new topics in this forum
You can reply to topics in this forum


Powered by phpBB © 2001, 2005 phpBB Group