• [AHK V2]SQLite测试用例


    AutoHotkey v2语言写的SQLite调用示例

    1. ; 创建一个SQLite对象
    2. db := CSQLite()
    3. ; 打开数据库
    4. if !db.OpenDB("example.db") {
    5. MsgBox "Failed to open database: " db.ErrorMsg
    6. ExitApp
    7. }
    8. ; 执行SQL查询
    9. sql := "CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY, name TEXT, age INTEGER);"
    10. if !db.Exec(sql) {
    11. MsgBox "Failed to execute SQL: " db.ErrorMsg
    12. db.CloseDB()
    13. ExitApp
    14. }
    15. ; 插入数据
    16. sql := "INSERT INTO users (name, age) VALUES ('John Doe', 30);"
    17. if !db.Exec(sql) {
    18. MsgBox "Failed to insert data: " db.ErrorMsg
    19. db.CloseDB()
    20. ExitApp
    21. }
    22. ; 查询数据
    23. sql := "SELECT * FROM users;"
    24. TB := {}
    25. if !db.GetTable(sql, &TB) {
    26. MsgBox "Failed to query data: " db.ErrorMsg
    27. db.CloseDB()
    28. ExitApp
    29. }
    30. ; 显示查询结果
    31. for row in TB.Rows {
    32. MsgBox "ID: " row[1] ", Name: " row[2] ", Age: " row[3]
    33. }
    34. ; 关闭数据库
    35. db.CloseDB()

    SQLite类源代码:

    1. /************************************************************************
    2. * @description SQLite class
    3. * @file CSQLite.ahk
    4. * @author thqby
    5. * @date 2022/04/23
    6. * @version 0.0.4
    7. * https://github.com/samfisherirl/Useful-AHK-v2-Libraries-and-Classes/blob/main/__thqby_Translation_SQLite_English/SQLite.ahk
    8. ***********************************************************************/
    9. class CSQLite
    10. {
    11. static Version := "", _SQLiteDLL := A_ScriptDir . "\SQLite3.dll", _RefCount := 0, hModule:=0
    12. static _MinVersion := "3.29", execfunc_ptr := 0, callback_gettable_ptr := 0
    13. __New(DllFolder:="") {
    14. this._Path := "" ; Database path (String)
    15. this._Handle := 0 ; Database handle (Pointer)
    16. if (CSQLite._RefCount = 0) {
    17. SQLiteDLL := CSQLite._SQLiteDLL
    18. if FileExist(DllFolder "\SQLite3.dll")
    19. SQLiteDLL := CSQLite._SQLiteDLL := DllFolder "\SQLite3.dll"
    20. if (!DllCall("GetModuleHandle", "Str", SQLiteDLL, "UPtr")
    21. &&!(CSQLite.hModule:=DllCall("LoadLibrary", "Str", SQLiteDLL, "UPtr"))){
    22. MsgBox("DLL " SQLiteDLL " does not exist!", "CSQLite Error", 16)
    23. ExitApp()
    24. }
    25. CSQLite.Version := StrGet(DllCall("SQLite3.dll\sqlite3_libversion", "Cdecl UPtr"), "UTF-8")
    26. SQLVersion := StrSplit(CSQLite.Version, ".")
    27. MinVersion := StrSplit(CSQLite._MinVersion, ".")
    28. if (SQLVersion[1] < MinVersion[1]) || ((SQLVersion[1] = MinVersion[1]) && (SQLVersion[2] < MinVersion[2])){
    29. DllCall("FreeLibrary", "Ptr", CSQLite.hModule), CSQLite.hModule:=0
    30. MsgBox("Version " . CSQLite.Version . " of SQLite3.dll is not supported!`n`n"
    31. . "You can download the current version from www.sqlite.org!", "SQLite ERROR", 16)
    32. ExitApp()
    33. }
    34. CSQLite.execfunc_ptr := DllCall("GetProcAddress", "Ptr", DllCall("LoadLibrary", "Str", SQLiteDLL, "UPtr"), "AStr", "sqlite3_exec", "Ptr")
    35. CSQLite.callback_gettable_ptr := CallbackCreate(callback_gettable, "F C")
    36. }
    37. CSQLite._RefCount += 1
    38. }
    39. ; ===================================================================================================================
    40. ; DESTRUCTOR __Delete
    41. ; ===================================================================================================================
    42. __Delete() {
    43. if (this._Thread.HasOwnProp("_Threadobj"))
    44. this._Thread._Threadobj:=""
    45. if (this._Handle)
    46. this.CloseDB()
    47. CSQLite._RefCount -= 1
    48. if (CSQLite._RefCount = 0) {
    49. CallbackFree(CSQLite.callback_gettable_ptr)
    50. if (CSQLite.hModule)
    51. DllCall("FreeLibrary", "Ptr", CSQLite.hModule)
    52. }
    53. }
    54. ; ===================================================================================================================
    55. ; PRIVATE _StrToUTF8
    56. ; ===================================================================================================================
    57. _StrToUTF8(Str, &UTF8) => (VarSetStrCapacity(&UTF8, size:=StrPut(Str, "UTF-8")), StrPut(Str, StrPtr(UTF8), "UTF-8"), size)
    58. ; ===================================================================================================================
    59. ; PRIVATE _ErrMsg
    60. ; ===================================================================================================================
    61. _UTF8ToStr(UTF8) => StrGet(StrPtr(UTF8), "UTF-8")
    62. ; ===================================================================================================================
    63. ; PRIVATE _ErrMsg
    64. ; ===================================================================================================================
    65. _ErrMsg() => ((RC := DllCall("SQLite3.dll\sqlite3_errmsg", "Ptr", this._Handle, "Cdecl UPtr")) ? StrGet(StrPtr(RC), "UTF-8") : "")
    66. ; ===================================================================================================================
    67. ; PRIVATE _ErrCode
    68. ; ===================================================================================================================
    69. _ErrCode() => DllCall("SQLite3.dll\sqlite3_errcode", "Ptr", this._Handle, "Cdecl Int")
    70. ; ===================================================================================================================
    71. ; PRIVATE _Changes
    72. ; ===================================================================================================================
    73. _Changes() => DllCall("SQLite3.dll\sqlite3_changes", "Ptr", this._Handle, "Cdecl Int")
    74. ; ===================================================================================================================
    75. ; PRIVATE _Returncode
    76. ; ===================================================================================================================
    77. _ReturnMsg(RC) {
    78. static Msg := Map(1, "SQL error or missing database"
    79. , 2, "SQLite internal logic error"
    80. , 3, "Access denied"
    81. , 4, "Callback function requested operation cancellation"
    82. , 5, "Database file is locked"
    83. , 6, "A table in the database is locked"
    84. , 7, "A malloc() function call failed"
    85. , 8, "Attempt to write to a read-only database"
    86. , 9, "Operation interrupted by sqlite3_interrupt() function"
    87. , 10, "Some disk I/O error occurred"
    88. , 11, "Incorrect database disk image"
    89. , 12, "Unknown opcode in sqlite3_file_control()"
    90. , 13, "Insertion failed due to database full"
    91. , 14, "Unable to open the database file"
    92. , 15, "Database lock protocol error"
    93. , 16, "Database is empty"
    94. , 17, "Data structure has changed"
    95. , 18, "String or binary data exceeds size limit"
    96. , 19, "Cancelled due to constraint violation"
    97. , 20, "Data type mismatch"
    98. , 21, "Incorrect library usage"
    99. , 22, "Use of unsupported operating system feature"
    100. , 23, "Authorization failed"
    101. , 24, "Attached database format error"
    102. , 25, "Second parameter passed to sqlite3_bind() is out of range"
    103. , 26, "The opened file is not a database file"
    104. , 100, "sqlite3_step() has produced a row result"
    105. , 101, "sqlite3_step() completed the execution operation")
    106. return Msg.HasKey(RC) ? Msg[RC] : ""
    107. }
    108. ; ===================================================================================================================
    109. ; Properties
    110. ; ===================================================================================================================
    111. ErrorMsg := "" ; Error message (String)
    112. ErrorCode := 0 ; SQLite error code / ErrorLevel (Variant)
    113. Changes := 0 ; Changes made by last call of Exec() (Integer)
    114. SQL := "" ; Last executed SQL statement (String)
    115. _Thread := {_Threadobj:0, queue:[], pexec:0, DB:0}
    116. OpenDB(DBPath, Access := "W", Create := true) {
    117. static SQLITE_OPEN_READONLY := 0x01 ; Database opened as read-only
    118. static SQLITE_OPEN_READWRITE := 0x02 ; Database opened as read-write
    119. static SQLITE_OPEN_CREATE := 0x04 ; Database will be created if not exists
    120. static MEMDB := ":memory:"
    121. this.ErrorMsg := "", this.ErrorCode := 0
    122. if (DBPath = "")
    123. DBPath := MEMDB
    124. if (DBPath = this._Path) && (this._Handle)
    125. return true
    126. if (this._Handle)
    127. return (this.ErrorMsg := "You must first close DB " . this._Path . "!", false)
    128. Flags := 0, Access := SubStr(Access, 1, 1)
    129. if (Access != "W") && (Access != "R")
    130. Access := "R"
    131. Flags := SQLITE_OPEN_READONLY
    132. if (Access = "W") {
    133. Flags := SQLITE_OPEN_READWRITE
    134. if (Create)
    135. Flags |= SQLITE_OPEN_CREATE
    136. }
    137. this._Path := DBPath, this._StrToUTF8(DBPath, &UTF8:="")
    138. if (RC := DllCall("SQLite3.dll\sqlite3_open_v2", "Ptr", StrPtr(UTF8), "Ptr*", &HDB:=0, "Int", Flags, "Ptr", 0, "Cdecl Int"))
    139. return (this._Path := "", this.ErrorMsg := this._ErrMsg(), this.ErrorCode := RC, false)
    140. this._Handle := HDB
    141. this.createScalarFunction(regexp, 2)
    142. this.createScalarFunction(regex_replace, 3)
    143. return true
    144. }
    145. ; ===================================================================================================================
    146. ; METHOD CloseDB Close database
    147. ; Parameters: None
    148. ; return values: On success - true
    149. ; On failure - false, ErrorMsg / ErrorCode contain additional information
    150. ; ===================================================================================================================
    151. CloseDB() {
    152. this.ErrorMsg := "", this.ErrorCode := 0, this.SQL := ""
    153. if !(this._Handle)
    154. return true
    155. if (RC := DllCall("SQLite3.dll\sqlite3_close", "Ptr", this._Handle, "Cdecl Int"))
    156. return (this.ErrorMsg := this._ErrMsg(), this.ErrorCode := RC, false)
    157. this._Path := "", this._Handle := ""
    158. return true
    159. }
    160. ; ===================================================================================================================
    161. LoadOrSaveDb(DBPath, isSave:=0){
    162. static SQLITE_OPEN_READONLY := 0x01 ; Database opened as read-only
    163. static SQLITE_OPEN_READWRITE := 0x02 ; Database opened as read-write
    164. static SQLITE_OPEN_CREATE := 0x04 ; Database will be created if not exists
    165. this.ErrorMsg := "", this.ErrorCode := 0, HDB := 0
    166. if (DBPath = "")
    167. return false
    168. if (!this._Handle)
    169. return (this.ErrorMsg := "You must first Open Memory DB!", false)
    170. Flags := SQLITE_OPEN_READWRITE, Flags |= SQLITE_OPEN_CREATE
    171. this._StrToUTF8(isSave?(tmp:=StrReplace(DBPath, ".db", ".tmp")):DBPath, &UTF8:="")
    172. if (RC := DllCall("SQLite3.dll\sqlite3_open_v2", "Ptr", StrPtr(UTF8), "Ptr*", &HDB, "Int", Flags, "Ptr", 0, "Cdecl Int"))
    173. return (this.ErrorMsg := this._ErrMsg(), this.ErrorCode := RC, false)
    174. pFrom := (isSave ? this._Handle : HDB), pTo := (isSave ? HDB : this._Handle), this._StrToUTF8("main", &UTF8)
    175. pBackup := DllCall("SQLite3.dll\sqlite3_backup_init", "Ptr", pTo, "Ptr", StrPtr(UTF8), "Ptr", pFrom, "Ptr", StrPtr(UTF8), "Cdecl Int")
    176. if (pBackup){
    177. DllCall("SQLite3.dll\sqlite3_backup_step", "Ptr", pBackup, "Int", -1, "Cdecl Int")
    178. DllCall("SQLite3.dll\sqlite3_backup_finish", "Ptr", pBackup, "Cdecl Int")
    179. }
    180. RC := DllCall("SQLite3.dll\sqlite3_errcode", "Ptr", pTo, "Cdecl Int")
    181. DllCall("SQLite3.dll\sqlite3_close", "Ptr", HDB, "Cdecl Int")
    182. if (RC) {
    183. this._Path := "", this.ErrorMsg := this._ErrMsg(), this.ErrorCode := RC
    184. if (isSave)
    185. FileDelete tmp
    186. return false
    187. }
    188. if (isSave){
    189. if (FileGetSize(tmp, "K")<16)
    190. return (FileDelete(tmp), false)
    191. FileMove tmp, DBPath, 1
    192. this.Changes:=0
    193. }
    194. return true
    195. }
    196. ; ===================================================================================================================
    197. ; METHOD AttachDB Add another database file to the current database connection
    198. ; http://www.sqlite.org/lang_attach.html
    199. ; Parameters: DBPath - Path of the database file
    200. ; DBAlias - Database alias name used internally by SQLite
    201. ; return values: On success - true
    202. ; On failure - false, ErrorMsg / ErrorCode contain additional information
    203. ; ===================================================================================================================
    204. AttachDB(DBPath, DBAlias) => this.Exec("ATTACH DATABASE '" . DBPath . "' As " . DBAlias . ";")
    205. ; ===================================================================================================================
    206. ; METHOD DetachDB Detaches an additional database connection previously attached using AttachDB()
    207. ; http://www.sqlite.org/lang_detach.html
    208. ; Parameters: DBAlias - Database alias name used with AttachDB()
    209. ; return values: On success - true
    210. ; On failure - false, ErrorMsg / ErrorCode contain additional information
    211. ; ===================================================================================================================
    212. DetachDB(DBAlias) => this.Exec("DETACH DATABASE " . DBAlias . ";")
    213. class Thread
    214. {
    215. Ptr:=0, pfunc:=0
    216. __New(funcobj, params, initflag:=0){
    217. this.pfunc:=pfunc:=CallbackCreate(funcobj)
    218. if (!this.Ptr:=DllCall("msvcrt\_beginthreadex", "Ptr", 0, "UInt", 0, "Ptr", pfunc, "Ptr", ObjPtrAddRef(params), "UInt", initflag, "UInt*", &threadid:=0))
    219. throw Error("create thread fail")
    220. this.threadid:=threadid
    221. }
    222. __Delete()=>(CallbackFree(this.pfunc), (this.ExitCode=259)?this.Terminate():"", (this.Ptr?DllCall("Kernel32\CloseHandle", "Ptr", this):0))
    223. Terminate(dwExitCode:=1)=>(DllCall("Kernel32\TerminateThread", "Ptr", this, "UInt", dwExitCode))
    224. ExitCode=>(DllCall("Kernel32\GetExitCodeThread", "Ptr", this, "UInt*", &Code:=0)?Code:0)
    225. }
    226. ExecByThread(SQL){
    227. if !(this._Handle)
    228. return (this.ErrorMsg := "Invalid database handle!", false)
    229. s:=StrPut(SQL, "UTF-8"), this._Thread.queue.Push(Buffer(s)), StrPut(SQL, this._Thread.queue[-1], "UTF-8")
    230. if (this._Thread.pexec)
    231. return
    232. this._Thread.DB:=this, this._Thread.pexec:=CSQLite.execfunc_ptr
    233. this._Thread._Threadobj:=CSQLite.Thread(_Exec, this._Thread)
    234. _Exec(pinfo){
    235. _Thread:=ObjFromPtr(pinfo), hdb:=_Thread.DB._Handle, pexec:=_Thread.pexec
    236. while (_Thread.queue.Has(1)){
    237. if (RC:=DllCall(pexec, "Ptr", hdb, "Ptr", _Thread.queue[1], "Ptr", 0, "Ptr", 0, "Ptr*", &Err:=0, "Cdecl Int")){
    238. ErrMsg:=_Thread.DB._ReturnMsg(RC), DllCall("SQLite3.dll\sqlite3_free", "Ptr", Err, "Cdecl")
    239. throw Error(ErrMsg)
    240. }
    241. _Thread.queue.RemoveAt(1)
    242. }
    243. _Thread.DB:="", _Thread.pexec:=0
    244. return 0
    245. }
    246. }
    247. Exec(SQL, pCallback := 0) {
    248. this.ErrorMsg := "", this.ErrorCode := 0, this.SQL := SQL
    249. if !(this._Handle)
    250. return (this.ErrorMsg := "Invalid database handle!", false)
    251. this._StrToUTF8(SQL, &UTF8:="")
    252. RC := DllCall(CSQLite.execfunc_ptr, "Ptr", this._Handle, "Ptr", StrPtr(UTF8), "Ptr", pCallback, "Ptr", ObjPtrAddRef(this), "Ptr*", &Err:=0, "Cdecl Int")
    253. if (RC) {
    254. this.ErrorMsg := this._ReturnMsg(RC)
    255. if (this.ErrorMsg = "")
    256. this.ErrorMsg := StrGet(Err, "UTF-8")
    257. this.ErrorCode := RC
    258. DllCall("SQLite3.dll\sqlite3_free", "Ptr", Err, "Cdecl")
    259. return false
    260. }
    261. this.Changes := this._Changes()
    262. return true
    263. }
    264. GetTable(SQL, &TB, pcall := 0) {
    265. this.ErrorMsg := "", this.ErrorCode := 0, this.SQL := SQL
    266. if !(this._Handle)
    267. return (this.ErrorMsg := "Invalid database handle!", false)
    268. this._StrToUTF8(SQL, &UTF8:=""), TB := {RowCount:0, Rows:[]}
    269. RC := DllCall(CSQLite.execfunc_ptr, "Ptr", this._Handle, "Ptr", StrPtr(UTF8)
    270. , "Ptr", (pcall>0?pcall:CSQLite.callback_gettable_ptr), "Ptr", ObjPtrAddRef(TB), "Ptr*", &Err:=0, "Cdecl Int")
    271. if (RC) {
    272. this.ErrorMsg := this._ReturnMsg(RC)
    273. if (this.ErrorMsg = "")
    274. this.ErrorMsg := StrGet(Err, "UTF-8"), this.Err := ""
    275. else
    276. this.Err := StrGet(Err, "UTF-8")
    277. this.ErrorCode := RC, DllCall("SQLite3.dll\sqlite3_free", "Ptr", Err, "Cdecl")
    278. return false
    279. } else if (pcall<0){
    280. RC := DllCall("SQlite3.dll\sqlite3_prepare_v2", "Ptr", This._Handle, "Ptr", StrPtr(UTF8), "Int", -1, "Ptr*", &Stmt:=0, "Ptr", 0, "Cdecl Int")
    281. TB.Cols := [], TB.ColCount := DllCall("SQlite3.dll\sqlite3_column_count", "Ptr", Stmt, "Cdecl Int")
    282. Loop TB.ColCount
    283. TB.Cols.Push(StrGet(DllCall("SQlite3.dll\sqlite3_column_name16", "Ptr", Stmt, "Int", A_Index - 1, "Cdecl UPtr"), "UTF-16"))
    284. DllCall("SQLite3.dll\sqlite3_finalize", "Ptr", Stmt, "Cdecl Int")
    285. }
    286. return true
    287. }
    288. createScalarFunction(func, params) {
    289. argType := Type(func)
    290. if (argType != "Func" && argType != "Closure")
    291. throw Error(this.__class "::" A_thisFunc " - First parameter not a Func object", -1)
    292. else if (!func.name)
    293. throw Error(this.__class "::" A_thisFunc " - Function must be named", -1)
    294. this.ErrorMsg := "", this.ErrorCode := 0, cb := CallbackCreate(func, "F C")
    295. if (err := DllCall("SQLite3.dll\sqlite3_create_function16", "Ptr", this._handle, "Str", func.name, "Int", params, "Int", 0x801, "Ptr", 0, "Ptr", cb, "Ptr", 0, "Ptr", 0, "Cdecl Int"))
    296. return (this.ErrorMsg := this._ErrMsg(), this.ErrorCode := err, false)
    297. return true
    298. }
    299. LastInsertRowID(&RowID) {
    300. this.ErrorMsg := "", this.ErrorCode := 0, this.SQL := ""
    301. if !(this._Handle)
    302. return (this.ErrorMsg := "Invalid database handle!", false)
    303. RowID := DllCall("SQLite3.dll\sqlite3_last_insert_rowid", "Ptr", this._Handle, "Cdecl Int64")
    304. return true
    305. }
    306. TotalChanges(&Rows) {
    307. this.ErrorMsg := "", this.ErrorCode := 0, this.SQL := ""
    308. if !(this._Handle)
    309. return (this.ErrorMsg := "Invalid database handle!", false)
    310. Rows := DllCall("SQLite3.dll\sqlite3_total_changes", "Ptr", this._Handle, "Cdecl Int")
    311. return true
    312. }
    313. SetTimeout(Timeout := 1000) {
    314. this.ErrorMsg := "", this.ErrorCode := 0, this.SQL := ""
    315. if !(this._Handle)
    316. return (this.ErrorMsg := "Invalid database handle!", false)
    317. if !IsInteger(Timeout)
    318. Timeout := 1000
    319. RC := DllCall("SQLite3.dll\sqlite3_busy_timeout", "Ptr", this._Handle, "Int", Timeout, "Cdecl Int")
    320. if (RC)
    321. return (this.ErrorMsg := this._ErrMsg(), this.ErrorCode := RC, false)
    322. return true
    323. }
    324. }
    325. regexp(Context, ArgC, vals) {
    326. regexNeedle := DllCall("SQLite3.dll\sqlite3_value_text16", "Ptr", NumGet(vals + 0, "Ptr"), "Cdecl Str")
    327. search := DllCall("SQLite3.dll\sqlite3_value_text16", "Ptr", NumGet(vals + A_PtrSize, "Ptr"), "Cdecl Str")
    328. DllCall("SQLite3.dll\sqlite3_result_int", "Ptr", Context, "Int", RegexMatch(search, regexNeedle), "Cdecl") ; 0 = false, 1 = true
    329. }
    330. regex_replace(Context, ArgC, vals) {
    331. search := DllCall("SQLite3.dll\sqlite3_value_text16", "Ptr", NumGet(vals + 0, "Ptr"), "Cdecl Str")
    332. regexNeedle := DllCall("SQLite3.dll\sqlite3_value_text16", "Ptr", NumGet(vals + A_PtrSize, "Ptr"), "Cdecl Str")
    333. Replacement := DllCall("SQLite3.dll\sqlite3_value_text16", "Ptr", NumGet(vals + A_PtrSize*2, "Ptr"), "Cdecl Str")
    334. DllCall("SQLite3.dll\sqlite3_result_text16", "Ptr", Context, "Str", RegExReplace(search, regexNeedle, Replacement), "Int", -1, "Ptr", 0, "Cdecl")
    335. }
    336. callback_gettable(TB, coln, vals, cols) {
    337. arr := Array(), TBobj := ObjFromPtrAddRef(TB)
    338. Loop coln
    339. arr.Push(StrGet(NumGet(vals + A_PtrSize * (A_Index - 1), "Ptr"), "UTF-8"))
    340. TBobj.Rows.Push(arr), TBobj.RowCount++
    341. return 0
    342. }

  • 相关阅读:
    VUE 2.0——vue入门和v-bind使用
    js中setTimeout定时器不准的原因,以及修正的办法
    Android Studio运行kotlin项目,一直Read timed out
    图论的小技巧以及扩展
    BERT模型的详细介绍
    当今微服务盛行之架构师必经之路-领域驱动设计-上
    八、SpringMVC(2)
    安装Elasticsearch步骤(包含遇到的问题及解决方案)
    系统软件开发平台的介绍
    Java面试题:讨论单例模式的实现方式,包括懒汉式和饿汉式,并讨论线程安全问题
  • 原文地址:https://blog.csdn.net/liuyukuan/article/details/140274815