This commit is contained in:
Jayvant Javier Pujara
2012-11-01 16:05:12 -04:00
commit 3bde7c3d5f
52 changed files with 6914 additions and 0 deletions
+52
View File
@@ -0,0 +1,52 @@
/*
* Provides Static ADO Helper classes and Enums
*
*/
class ADO
{
class CursorType
{
static adOpenUnspecified := -1
static adOpenForwardOnly := 0
static adOpenKeyset := 1
static adOpenDynamic := 2
static adOpenStatic := 3
}
class LockType
{
static adLockUnspecified := -1
static adLockReadOnly := 1
static adLockPessimistic := 2
static adLockOptimistic := 3
static adLockBatchOptimistic := 4
}
class CommandType
{
static adCmdUnspecified := -1
static adCmdText := 1
static adCmdTable := 2
static adCmdStoredProc := 4
static adCmdUnknown := 8
static adCmdFile := 256
static adCmdTableDirect := 512
}
class AffectEnum
{
static adAffectCurrent := 1
static adAffectGroup := 2
}
class ObjectStateEnum
{
static adStateClosed := 0 ; The object is closed
static adStateOpen := 1 ; The object is open
static adStateConnecting := 2 ; The object is connecting
static adStateExecuting := 4 ; The object is executing a command
static adStateFetching := 8 ; The rows of the object are being retrieved
}
}
+94
View File
@@ -0,0 +1,94 @@
/**************************************
base classes
***************************************
*/
global null := 0 ; for better readability
/*
Check for same (base) Type
*/
is(obj, type){
if(IsObject(type))
type := typeof(type)
while(IsObject(obj)){
if(obj.__Class == type){
return true
}
obj := obj.base
}
return false
}
typeof(obj){
if(IsObject(obj)){
cls := obj.__Class
if(cls != "")
return cls
while(IsObject(obj)){
if(obj.__Class != ""){
return obj.__Class
}
obj := obj.base
}
return "Object"
}
return "NonObject"
}
IsObjectMember(obj, memberStr){
if(IsObject(obj)){
return ObjHasKey(obj, memberStr) || IsMetaProperty(memberStr)
}
}
IsMetaProperty(str){
static metaProps := "__New,__Get,__Set,__Class"
if str in %metaProps%
return true
else
return false
}
/**
* Provides some common used Exception Templates
*
*/
class Exceptions
{
NotImplemented(){
return Exception("A not implemented Method was called.",-1)
}
MustOverride(){
return Exception("This Method must be overriden",-1)
}
ArgumentException(furtherInfo=""){
return Exception("A wrong Argument has been passed to this Method`n" furtherInfo,-1)
}
}
;Base
{
"".base.__Call := "Default__Warn"
"".base.__Set := "Default__Warn"
"".base.__Get := "Default__Warn"
Default__Warn(nonobj, p1="", p2="", p3="", p4="")
{
ListLines
MsgBox A non-object value was improperly invoked.`n`nSpecifically: %nonobj%
}
}
+104
View File
@@ -0,0 +1,104 @@
#Include <Base>
/*
Basic Collection implementation
*/
class Collection
{
; Methoden Implementation
/*
Fügt ein Element der Collection hinzu
*/
Add(obj){
this.Insert(obj)
}
/*
Fügt eine Auflistung dieser Collection hinzu
*/
AddRange(objs){
if(IsObject(objs)){
for each, item in objs
this.Insert(item)
} else
throw Exceptions.ArgumentException("Must submit Array!")
}
Clear(){
this.Remove(this.MinIndex(), this.MaxIndex())
}
RemoveItem(item){
for k, e in this
if(e = item)
this.Remove(k)
}
/*
Returns the count of elements contained in this collection
*/
Count(){
return this.SetCapacity(0)
}
/*
* Returns true if this collection is empty
*/
IsEmpty(){
return this.Count() == 0
}
First(){
return this[this.MinIndex()]
}
Last(){
return this[this.MaxIndex()]
}
/*
Sortiert die Liste
*/
Sort(comparer=""){
if(IsFunc(comparer))
comparer := "F " comparer
for each, num in this
nums .= num "`n"
Sort, nums, % comparer
this.Clear()
Loop, parse, nums, `,
this.Add(A_LoopField)
}
ToString(){
str := ""
for k, v in this
{
valStr := ""
if(IsObject(v)){
valStr := "{" . typeof(v) . "}"
if(IsFunc(v.ToString)){
valStr .= " " . v.ToString()
}
}else{
valStr := "'" v "'"
}
str .= k ": " . valStr . "`n"
}
return str
}
/*
Konstruktor - erstellt eine neue, (leere) Collection
enum : Element die zubign vorhanden sein sollen
*/
__New(enum = 0){
if(IsObject(enum)){
this.AddRange(enum)
}
}
}
+27
View File
@@ -0,0 +1,27 @@
/*
DataBase NameSpace Import
*/
#Include <Base>
#Include <Collection>
;drivers
#Include <SQLite_L>
#Include <mySQL>
#Include <ADO>
class DBA ; namespace DBA
{
#Include <DataBaseFactory>
#Include <DataBaseAbstract>
; Concrete SQL Providers
#Include <DataBaseSQLLite>
#Include <DataBaseMySQL>
#Include <DataBaseADO>
#Include <RecordSetSqlLite>
#Include <RecordSetADO>
#Include <RecordSetMySQL>
}
+200
View File
@@ -0,0 +1,200 @@
;namespace DBA
/*
Represents a Connection to a ADO Database
*/
class DataBaseADO extends DBA.DataBase
{
_connection := null
_connectionData := ""
__New(connectionString){
this._connectionData := connectionString
this.Connect()
}
/*
(Re) Connects to the db with the given creditals
*/
Connect(){
if(IsObject(this._connection))
{
this.Close()
}
this._connection := ComObjCreate("ADODB.connection")
;connection.Open connectionstring,userID,password,options
this._connection.Open(this._connectionData)
}
Close(){
if(this.IsConnected())
{
this._connection.Close()
this._connection := null
}
}
/*
* Is this connection open?
*/
IsConnected(){
return (IsObject(this._connection) && this._connection.State != ADO.ObjectStateEnum.adStateClosed)
}
IsValid(){
return IsObject(this._connection)
}
GetLastError(){
; todo
}
GetLastErrorMsg(){
errMsg := ""
for objErr in this._connection.Errors
{
errMsg .= objErr.Number " " objErr.Description " Source:" objErr.Source "`n"
}
return errMsg
}
SetTimeout(timeout = 1000){
if(this.IsValid())
this._connection.ConnectionTimeout := (timeout / 1000)
}
Changes() {
/*
ToDo
*/
}
/*
Querys the DB and returns a RecordSet
*/
OpenRecordSet(sql, editable = false){
return new DBA.RecordSetADO(sql, this._connection, editable)
}
/*
Querys the DB and returns a ResultTable or true/false
*/
Query(sql){
ret := false
if(this.IsValid())
{
;Execute( commandtext,ra,options)
affectedRows := 0
rs := this._connection.Execute(sql, affectedRows)
if(IsObject(rs) && rs.State != ADO.ObjectStateEnum.adStateClosed)
{
ret := this.FetchADORecordSet(rs)
rs.Close()
}else{
ret := affectedRows
}
}
return ret
}
EscapeString(str){
return Mysql_escape_string(str)
}
BeginTransaction(){
if(this.IsValid())
this._connection.BeginTrans()
}
EndTransaction(){
if(this.IsValid())
this._connection.CommitTrans()
}
Rollback(){
if(this.IsValid())
this._connection.RollbackTrans()
}
FetchADORecordSet(adoRS){
tbl := null
if(IsObject(adoRS) && !adoRS.EOF)
{
columnNames := new Collection()
myRows := new Collection()
for field in adoRS.Fields
columnNames.add(field.Name)
fetchedArray := adoRS.GetRows() ; returns a COM-SafeArray Wrapper
colSize := fetchedArray.MaxIndex(1) + 1
rowSize := fetchedArray.MaxIndex(2) + 1
loop, % rowSize
{
i := A_index - 1
datafields := new Collection()
loop, % colSize
{
j := A_index - 1
datafields.add(fetchedArray[j,i])
}
myRows.Add(new DBA.Row(columnNames, datafields))
}
tbl := new DBA.Table(myRows, columnNames)
}
return tbl
}
InsertMany(records, tableName){
;objRecordset.Open source,actconn,cursortyp,locktyp,opt
rs := ComObjCreate("ADODB.Recordset")
/* batch
rs.Open(tableName, this._connection, ADO.CursorType.adOpenKeyset, ADO.LockType.adLockBatchOptimistic, ADO.CommandType.adCmdTable)
for each, record in records
{
rs.AddNew()
for column, value in record
{
rs.Fields[column].Value := value
}
}
rs.UpdateBatch()
*/
rs.Open(tableName, this._connection, ADO.CursorType.adOpenKeyset, ADO.LockType.adLockOptimistic, ADO.CommandType.adCmdTable)
for each, record in records
{
rs.AddNew()
for column, value in record
{
rs.Fields[column].Value := value
}
rs.Update()
}
rs.Close()
}
Insert(record, tableName){
records := new Collection()
records.Add(record)
return this.InsertMany(records, tableName)
}
}
+308
View File
@@ -0,0 +1,308 @@
; namespace DBA
/*
#####################################################################################
Abstract Database Classes
Base for all concrete implementations for the supported DataBases.
#####################################################################################
*/
/*
data := Row[index]
data := Row["ColumnName"]
*/
class Row
{
_columns := 0
_fields := new Collection()
Count(){
return this._fields.Count()
}
ToString(){
return this._fields.ToString()
}
__Get(param){
if(IsObject(param)){
throw Exception("Expected Index or Column Name!", -1)
}
if(!IsObjectMember(this, param)){
if param is Integer
{
; // assume that an indexed access is desired
; // return the corresponding ROW
if(this.ContainsIndex(param))
return this._fields[param]
} else {
; // assume that an columnname access is desired
; // find index
index := 0
for i, col in this._columns
{
if(col = param){
index := i
break
}
}
if(this.ContainsIndex(index)){
return this._fields[index]
}
}
}
}
ContainsIndex(index){
return ((index > 0) && (index <= this._fields.Count()))
}
/*
Creates a New Row.
columns : Collection of the Columnames
fields: Collection of the Fields (Data)
*/
__New(columns, fields){
if(!is(columns, "Collection")){
throw Exception("columns must be a Collection Object",-1)
}
if(!is(fields, "Collection")){
throw Exception("fields must be a Collection Object",-1)
}
this._fields := fields
this._columns := columns
}
__NewEnum() {
return new DBA.Row.Enumerator(this)
}
class Enumerator {
__new(row) {
this.columnEnum := ObjNewEnum(row.columns)
this.fieldEnum := ObjNewEnum(row.fields)
}
next(ByRef key, ByRef val) {
return this.columnEnum.next("", key)
&& this.fieldEnum.next("",val)
}
}
}
/*
row := table[index]
*/
class Table
{
Rows := new Collection()
Columns := new Collection()
Count(){
return this.Rows.Count()
}
ToString(){
colstr := this.Columns.ToString()
StringReplace, colstr, colstr, `n, |
return "(" this.Rows.Count() ")" . colstr
}
__Get(param){
if(IsObject(param)){
throw Exception("Expected non-Object Index!",-1)
}
if(!IsObjectMember(this, param)){
if param is Integer
{
; // assume that an indexed access is desired
; // return the corresponding ROW
if((param > 0) && (param < this.Rows.Count()) )
return this.Rows[param]
}
}
}
/*
Creates a New Table.
rows: Collection of the Rows (Data)
columns : Collection of the Columnames
*/
__New(rows, columns){
if(!is(rows, "Collection")){
throw Exception("rows must be a Collection Object",-1)
}
if(!is(columns, "Collection")){
throw Exception("rows must be a Collection Object",-1)
}
this.Rows := rows
this.Columns := columns
}
__NewEnum() {
return ObjNewEnum(this.rows)
}
}
class DataBase
{
static NULL := Object()
static TRUE := Object()
static FALSE := Object()
__delete() {
this.Close()
}
IsValid(){
throw Exceptions.MustOverride()
}
Query(sql){
throw Exceptions.MustOverride()
}
QueryValue(sQry){
rs := this.OpenRecordSet(sQry)
value := rs[1]
rs.Close()
return value
}
QueryRow(sQry){
rs := this.OpenRecordSet(sQry)
myrow := rs.getCurrentRow()
rs.Close()
return myrow
}
OpenRecordSet(sql, editable = false){
throw Exceptions.MustOverride()
}
ToSqlLiteral(value) {
if (IsObject(value)) {
if (value == DBA.DataBase.NULL)
return "NULL"
if (value == DBA.DataBase.TRUE)
return "TRUE"
if (value == DBA.DataBase.FALSE)
return "FALSE"
}
return "'" this.EscapeString(value) "'"
}
EscapeString(string){
throw Exceptions.MustOverride()
}
QuoteIdentifier(identifier){
throw Exceptions.MustOverride()
}
BeginTransaction(){
throw Exceptions.MustOverride()
}
EndTransaction(){
throw Exceptions.MustOverride()
}
Rollback(){
throw Exceptions.MustOverride()
}
Insert(record, tableName){
throw Exceptions.MustOverride()
}
InsertMany(records, tableName){
throw Exceptions.MustOverride()
}
Update(fields, constraints, tableName, safe = True){
throw Exceptions.MustOverride()
}
Close(){
throw Exceptions.MustOverride()
}
}
class RecordSet
{
_currentRow := 0 ; Row
__delete() {
this.Close()
}
AddNew(){
throw Exceptions.MustOverride()
}
MoveNext(){
throw Exceptions.MustOverride()
}
Delete(){
throw Exceptions.MustOverride()
}
Update(){
throw Exceptions.MustOverride()
}
Close(){
throw Exceptions.MustOverride()
}
getEOF(){
throw Exceptions.MustOverride()
}
IsValid(){
throw Exceptions.MustOverride()
}
getColumnNames(){
throw Exceptions.MustOverride()
}
getCurrentRow(){
return this._currentRow
}
__Get(param){
if(IsObject(param)){
throw Exception("Expected Index or Column Name!",-1)
}
if(param = "EOF")
return this.getEOF()
if(!IsObjectMember(this, param) && param != "_currentRow"){
if(!is(this._currentRow, DBA.Row))
return ""
;// assume memberaccess are the column names/indexes
return this._currentRow[param]
}
}
}
+36
View File
@@ -0,0 +1,36 @@
class DataBaseFactory
{
static AvaiableTypes := ["SQLite", "MySQL", "ADO"]
/*
This static Method returns an Instance of an DataBase derived Object
*/
OpenDataBase(dbType, connectionString){
if(dbType = "SQLite")
{
OutputDebug, Open Database of known type [%dbType%]
SQLite_Startup()
;//parse connection string. for now assume its a path to the requested DB
handle := SQLite_OpenDB(connectionString)
if(handle == 0)
throw Exception("SQLite: The connection to the the given Datebase could not be etablished. Is the following SQLite connection string valid?`n`n" connectionString,-1)
return new DBA.DataBaseSQLLite(handle)
} if(dbType = "MySQL") {
OutputDebug, Open Database of known type [%dbType%]
MySQL_StartUp()
conData := MySQL_CreateConnectionData(connectionString)
return new DBA.DataBaseMySQL(conData)
} if(dbType = "ADO") {
OutputDebug, Open Database of known type [%dbType%]
return new DBA.DataBaseADO(connectionString)
} else {
throw Exception("The given Database Type is unknown! [" . dbType "]",-1)
}
}
__New(){
throw Exception("This is a static class, dont instante it!",-1)
}
}
+249
View File
@@ -0,0 +1,249 @@
;namespace DBA
/*
Represents a Connection to a SQLite Database
*/
class DataBaseMySQL extends DBA.DataBase
{
_handleDB := 0
_connectionData := []
__New(connectionData){
if(!IsObject(connectionData))
throw Exception("Expected connectionData Array!")
this._connectionData := connectionData
this.Connect()
}
/*
(Re) Connects to the db with the given creditals
*/
Connect(){
connectionData := this._connectionData
if(!connectionData.Port){
dbHandle := MySQL_Connect(connectionData.Server, connectionData.Uid, connectionData.Pwd, connectionData.Database)
} else {
dbHandle := MySQL_Connect(connectionData.Server, connectionData.Uid, connectionData.Pwd, connectionData.Database, connectionData.Port)
}
this._handleDB := dbHandle
}
Close(){
/*
ToDo!
*/
}
IsValid(){
return (this._handleDB != 0)
}
GetLastError(){
return MySQL_GetLastErrorNo(this._handleDB)
}
GetLastErrorMsg(){
return MySQL_GetLastErrorMsg(this._handleDB)
}
SetTimeout(timeout = 1000){
/*
todo
*/
}
ErrMsg() {
return DllCall("libmySQL.dll\mysql_error", "UInt", this._handleDB, "AStr")
}
ErrCode() {
return DllCall("libmySQL.dll\mysql_errno", "UInt", this._handleDB) ; "Cdecl UInt"
}
Changes() {
/*
ToDo
*/
}
/*
Querys the DB and returns a RecordSet
*/
OpenRecordSet(sql, editable = false){
result := MySQL_Query(this._handleDB, sql)
if (result != 0) {
errCode := this.ErrCode()
if(errCode == 2003 || errCode == 2006 || errCode == 0){ ;// we've lost the connection
;// try reconnect
this.Connect()
result := MySQL_Query(this._handleDB, sql)
if (result != 0)
throw new Exception(BuildMySQLErrorStr(this._handleDB, "Query failed because of lost connection. Reconnect failed too." errCode, sql), -1)
} else {
throw new Exception(BuildMySQLErrorStr(this._handleDB, "Query Failed Error " errCode, sql), -1)
}
}
requestResult := MySQL_Use_Result(this._handleDB)
if(!requestResult)
return false
return new DBA.RecordSetMySQL(this._handleDB, requestResult)
}
/*
Querys the DB and returns a ResultTable or true/false
*/
Query(sql){
return this._GetTableObj(sql)
}
EscapeString(str){
return Mysql_escape_string(str)
}
QuoteIdentifier(identifier) {
; ` characters are actually valid. Technically everthing but a literal null U+0000.
; Everything else is fair game: http://dev.mysql.com/doc/refman/5.0/en/identifiers.html
StringReplace, identifier, identifier, ``, ````, All
return "``" identifier "``"
}
BeginTransaction(){
this.Query("START TRANSACTION;")
}
EndTransaction(){
this.Query("COMMIT;")
}
Rollback(){
this.Query("ROLLBACK;")
}
InsertMany(records, tableName){
if(!is(records, Collection) || records.IsEmpty())
return false
sql := "INSERT INTO " tableName "`n"
colString := ""
for column, value in records.First()
{
colstring .= this.QuoteIdentifier(column) ","
}
StringTrimRight, colstring, colstring, 1
sql .= "(" colstring ")`nVALUES`n"
for each, record in records
{
valString := ""
for column, value in record
{
valString .= this.ToSqlLiteral(value) ","
}
StringTrimRight, valString, valString, 1
sql .= "(" valString "),`n"
}
StringTrimRight, colstring, colstring, 1
sql := Trim(sql," `t`r`n,") ";"
;FileAppend,`n---------`n%sql%`n, dba_sql.log
return this.Query(sql)
}
Insert(record, tableName){
records := new Collection()
records.Add(record)
return this.InsertMany(records, tableName)
}
Update(fields, constraints, tableName, safe = True) {
if (safe) ;limitation: information_schema doesn't work with temp tables
for k, row in this.Query("SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE COLUMN_KEY = 'PRI' AND TABLE_NAME = " this.ToSqlLiteral(tableName)).Rows
if (!constraints.HasKey(row[1]))
return -1 ; error handling....
WHERE := ""
for col, val in constraints
WHERE .= ", " this.QuoteIdentifier(col) " = " this.ToSqlLiteral(val)
WHERE := SubStr(WHERE, 3)
SET := ""
for col, val in fields
SET .= "AND " this.QuoteIdentifier(col) " = " this.EscapeString(val)
SET := SubStr(SET, 5)
query := "UPDATE " this.QuoteIdentifier(tableName) " SET " SET " WHERE " WHERE
return db.Query(query)
}
_GetTableObj(sql, maxResult = -1) {
result := MySQL_Query(this._handleDB, sql)
/*
* Instant reconnect attempt
*/
if (result != 0) {
errCode := this.ErrCode()
if(errCode == 2003 || errCode == 2006 || errCode == 0){ ;// we've lost the connection
;// try reconnect
this.Connect()
result := MySQL_Query(this._handleDB, sql)
if (result != 0)
throw new Exception(BuildMySQLErrorStr(this._handleDB, "Query failed because of lost connection. Reconnect failed too." errCode, sql), -1)
} else {
throw new Exception(BuildMySQLErrorStr(this._handleDB, "Query Failed Error " errCode, sql), -1)
}
}
requestResult := MySql_Store_Result(this._handleDB)
if (!requestResult) ; the query was a non {SELECT, SHOW, DESCRIBE, EXPLAIN or CHECK TABLE} statement which doesn't yield any resultset
return
mysqlFields := MySQL_fetch_fields(requestResult)
colNames := new Collection()
columnCount := 0
for each, mysqlField in mysqlFields
{
colNames.Add(mysqlField.Name())
columnCount++
}
rowptr := 0
myRows := new Collection()
while((rowptr := MySQL_fetch_row(requestResult)))
{
rowIndex := A_Index
datafields := new Collection()
lengths := MySQL_fetch_lengths(requestResult)
Loop, % columnCount
{
length := GetUIntAtAddress(lengths, A_Index - 1)
fieldPointer := GetPtrAtAddress(rowptr, A_Index - 1)
if (fieldPointer != 0) ; "NULL values in the row are indicated by NULL pointers." See http://dev.mysql.com/doc/refman/5.0/en/mysql-fetch-row.html
fieldValue := StrGet(fieldPointer, length, "CP0")
else
fieldValue := "" ; Should use DBA.DataBase.NULL from database-types branch?
datafields.Add(fieldValue)
}
myRows.Add(new DBA.Row(colNames, datafields))
}
MySQL_free_result(requestResult)
tbl := new DBA.Table(myRows, colNames)
return tbl
}
}
+310
View File
@@ -0,0 +1,310 @@
; namespace DBA
class SQLite
{
GetVersion(){
return SQLite_LibVersion()
}
SQLiteExe(dbFile, commands, ByRef output){
return SQLite_SQLiteExe(dbFile, commands, output)
}
__New(){
throw Exception("This is a static Class. Don't create Instances from it!",-1)
}
}
/*
Represents a Connection to a SQLite Database
*/
class DataBaseSQLLite extends DBA.DataBase
{
_handleDB := 0
__New(handleDB){
this._handleDB := handleDB
if(!this.IsValid())
{
throw Exception("Can not create a DataBaseSQLLite instance, because the connection handle is not valid!")
}
}
Close(){
return SQLite_CloseDB(this._handleDB)
}
IsValid(){
return (this._handleDB != 0)
}
GetLastError(){
code := 0
SQLite_ErrCode(this._handleDB, code)
return code
}
GetLastErrorMsg(){
msg := ""
SQLite_ErrMsg(this._handleDB, msg)
return msg
}
SetTimeout(timeout = 1000){
return SQLite_SetTimeout(this._handleDB, timeout)
}
ErrMsg() {
if (RC := DllCall("SQLite3\sqlite3_errmsg", "UInt", this._handleDB, "Cdecl UInt"))
return StrGet(RC, "UTF-8")
return ""
}
ErrCode() {
return DllCall("SQLite3\sqlite3_errcode", "UInt", this._handleDB, "Cdecl UInt")
}
Changes() {
return DllCall("SQLite3\sqlite3_changes", "UInt", this._handleDB, "Cdecl UInt")
}
/*
Querys the DB and returns a RecordSet
*/
OpenRecordSet(sql, editable = false){
return new DBA.RecordSetSqlLite(this, SQlite_Query(this._handleDB, sql))
}
/*
Querys the DB and returns a ResultTable or true/false
*/
Query(sql){
ret := null
if (RegExMatch(sql, "i)^\s*SELECT\s")){ ; check if this is a selection query
try
{
ret := this._GetTableObj(sql)
} catch e
throw Exception("Select Query failed.`n`n" sql "`n`nChild Exception:`n" e.What "`n" e.Message "`n" e.File "@" e.Line, -1)
} else {
try
{
ret := SQLite_Exec(this._handleDB, sql)
} catch e
throw Exception("Non Selection Query failed.`n`n" sql "`n`nChild Exception:`n" e.What " `n" e.Message, -1)
}
return ret
}
EscapeString(str){
StringReplace, str, str, ', '', All ; replace all single quotes with double single-quotes. pascal escape'
return str
}
QuoteIdentifier(identifier) {
; ` characters are actually valid. Technically everthing but a literal null U+0000.
; Everything else is fair game: http://dev.mysql.com/doc/refman/5.0/en/identifiers.html
StringReplace, identifier, identifier, ``, ````, All
return "``" identifier "``"
}
BeginTransaction(){
this.Query("BEGIN TRANSACTION;")
}
EndTransaction(){
this.Query("COMMIT TRANSACTION;")
}
Rollback(){
this.Query("ROLLBACK TRANSACTION;")
}
InsertMany(records, tableName){
if(!is(records, Collection) || records.IsEmpty())
return false
colString := ""
valString := ""
columns := {}
for column, value in records.First()
{
colString .= "," this.QuoteIdentifier(column)
valString .= ",?"
columns[column] := A_Index
}
sql := "INSERT INTO " this.QuoteIdentifier(tableName) "`n(" SubStr(colstring, 2) ")`nVALUES`n(" SubStr(valString, 2) ")"
types := []
for i,row in this._GetTableObj("PRAGMA table_info(" this.QuoteIdentifier(tableName) ")").Rows
{
if columns.HasKey(row.name)
types[columns[row.name]] := row.types
}
this.BeginTransaction()
query := SQLite_Query(this._handleDB, sql) ;prepare the query
if ErrorLevel
msgbox % errorlevel
try
{
for i, record in records
{
for col, val in record
{
if (!columns.HasKey(col) || !types.HasKey(columns[col]))
throw "Irregular params"
SQLite_bind(query, columns[col], val, types[columns[col]])
}
SQLite_Step(query)
SQLite_Reset(query)
}
}
catch e
{
this.Rollback()
throw Exception("InsertMany failed.`n`nChild Exception:`n" e.What " `n" e.Message, -1)
}
SQLite_QueryFinalize(query)
this.EndTransaction()
return True
}
Insert(record, tableName){
col := new Collection()
col.Add(record)
return this.InsertMany(col, tableName)
}
_GetTableObj(sql, maxResult = -1) {
err := 0, rc := 0, GetRows := 0
i := 0
rows := cols := 0
names := new Collection()
dbh := this._handleDB
SQLite_LastError(" ")
if(!_SQLite_CheckDB(dbh)) {
SQLite_LastError("ERROR: Invalid database handle " . dbh)
ErrorLevel := _SQLite_ReturnCode("SQLITE_ERROR")
return False
}
if maxResult Is Not Integer
maxResult := -1
if (maxResult < -1)
maxResult := -1
mytable := ""
Err := 0
_SQLite_StrToUTF8(SQL, UTF8)
RC := DllCall("SQlite3\sqlite3_get_table", "Ptr", dbh, "Ptr", &UTF8, "Ptr*", mytable
, "Ptr*", rows, "Ptr*", cols, "Ptr*", err, "Cdecl Int")
If (ErrorLevel) {
SQLite_LastError("ERROR: DLLCall sqlite3_get_table failed!")
Return False
}
If (rc) {
SQLite_LastError(StrGet(err, "UTF-8"))
DllCall("SQLite3\sqlite3_free", "Ptr", err, "cdecl")
ErrorLevel := rc
return false
}
if (maxResult = 0) {
DllCall("SQLite3\sqlite3_free_table", "Ptr", mytable, "Cdecl")
If (ErrorLevel) {
SQLite_LastError("ERROR: DLLCall sqlite3_close failed!")
Return False
}
Return True
}
if (maxResult = 1)
GetRows := 0
else if (maxResult > 1) && (maxResult < rows)
GetRows := MaxResult
else
GetRows := rows
Offset := 0
Loop, % cols
{
names.Add(StrGet(NumGet(mytable+0, Offset), "UTF-8"))
Offset += A_PtrSize
}
myRows := new Collection()
Loop, %GetRows% {
i := A_Index
fields := new Collection()
Loop, % Cols
{
fields.Add(StrGet(NumGet(mytable+0, Offset), "UTF-8"))
Offset += A_PtrSize
}
myRows.Add(new DBA.Row(Names, fields))
}
tbl := new DBA.Table(myRows, Names)
; Free Results Memory
DllCall("SQLite3\sqlite3_free_table", "Ptr", mytable, "Cdecl")
if (ErrorLevel) {
SQLite_LastError("ERROR: DLLCall sqlite3_close failed!")
return false
}
return tbl
}
ReturnCode(RC) {
static RCODE := {SQLITE_OK: 0 ; Successful result
, SQLITE_ERROR: 1 ; SQL error or missing database
, SQLITE_INTERNAL: 2 ; NOT USED. Internal logic error in SQLite
, SQLITE_PERM: 3 ; Access permission denied
, SQLITE_ABORT: 4 ; Callback routine requested an abort
, SQLITE_BUSY: 5 ; The database file is locked
, SQLITE_LOCKED: 6 ; A table in the database is locked
, SQLITE_NOMEM: 7 ; A malloc() failed
, SQLITE_READONLY: 8 ; Attempt to write a readonly database
, SQLITE_INTERRUPT: 9 ; Operation terminated by sqlite3_interrupt()
, SQLITE_IOERR: 10 ; Some kind of disk I/O error occurred
, SQLITE_CORRUPT: 11 ; The database disk image is malformed
, SQLITE_NOTFOUND: 12 ; NOT USED. Table or record not found
, SQLITE_FULL: 13 ; Insertion failed because database is full
, SQLITE_CANTOPEN: 14 ; Unable to open the database file
, SQLITE_PROTOCOL: 15 ; NOT USED. Database lock protocol error
, SQLITE_EMPTY: 16 ; Database is empty
, SQLITE_SCHEMA: 17 ; The database schema changed
, SQLITE_TOOBIG: 18 ; String or BLOB exceeds size limit
, SQLITE_CONSTRAINT: 19 ; Abort due to constraint violation
, SQLITE_MISMATCH: 20 ; Data type mismatch
, SQLITE_MISUSE: 21 ; Library used incorrectly
, SQLITE_NOLFS: 22 ; Uses OS features not supported on host
, SQLITE_AUTH: 23 ; Authorization denied
, SQLITE_FORMAT: 24 ; Auxiliary database format error
, SQLITE_RANGE: 25 ; 2nd parameter to sqlite3_bind out of range
, SQLITE_NOTADB: 26 ; File opened that is not a database file
, SQLITE_ROW: 100 ; sqlite3_step() has another row ready
, SQLITE_DONE: 101} ; sqlite3_step() has finished executing
return RCODE.HasKey(RC) ? RCODE[RC] : ""
}
}
+415
View File
@@ -0,0 +1,415 @@
;——————————————————————————————————————————————————————
;———————— Notify() 0.4991 by gwarble ————————
;————— —————
;——— easy multiple tray area notifications ———
;—— http://www.autohotkey.net/~gwarble/Notify/ ——
;——————————————————————————————————————————————————————
;
; Notify([Title,Message,Duration,Options])
;
; Duration seconds to show notification [Default: 30]
; 0 for permanent/remain until clicked (flashing)
; -3 negative value to ExitApp on click/timeout
; "-0" for permanent and ExitApp when clicked (needs "")
;
; Options string of options, single-space seperated, ie:
; "TS=16 TM=8 TF=Times New Roman GC_=Blue SI_=1000"
; most options are remembered (static), some not (local)
; Option_= can be used for non-static call, ie:
; "GC=Blue" makes all future blue, "GC_=Blue" only takes effect once
; "Wait=ID" to wait for a notification
; "Update=ID" to change Title, Message, and Progress Bar (with 'Duration')
;
; Return ID (Gui Number used)
; 0 if failed (too many open most likely)
; VarValue if Options includes: Return=VarName
;——————————————————————————————————————————————————————
Notify(Title="Notify()",Message="",Duration="",Options="")
{
static GNList, ACList, ATList, AXList, Exit, _Wallpaper_, _Title_, _Message_, _Progress_, _Image_, Saved
static GF := 50 ; Gui First Number
static GL := 74 ; Gui Last Number (which defines range and allowed count)
static GC,GR,GT,BC,BK,BW,BR,BT,BF ; static options, remembered between calls
static TS,TW,TC,TF,MS,MW,MC,MF
static SI,SC,ST,IW,IH,IN,XC,XS,XW,PC,PB
If (Options) ; skip parsing steps if Options param isn't used
{
If (A_AutoTrim = "Off")
{
AutoTrim, On
_AutoTrim = 1
} ; ¶
Options = %Options%
Options.=" " ; poor whitespace handling for next parsing step (ensures last option is parsed)
Loop,Parse,Options,= ; parse options string at "="s, needs better whitespace handling
{
If A_Index = 1 ; first option handling
Option := A_LoopField ; sets options VarName
Else ; for the rest after the first,
{ ; split at the last space, apply the first chunk to the VarValue for the last Option
%Option% := SubStr(A_LoopField, 1, (pos := InStr(A_LoopField, A_Space, false, 0))-1)
%Option% = % %Option%
Option := SubStr(A_LoopField, pos+1) ; and set the next option to the last chunk (from the last space to the "=")
}
}
If _AutoTrim
AutoTrim, Off
If Wait <> ; option Wait=ID used, normal Notify window not being created
{
If Wait Is Number ; waits for a specific notify
{
Gui %Wait%:+LastFound ; i'd like to remove this to not affect calling script...
If NotifyGuiID := WinExist() ; but think i have to use hWnd's for reference instead of gui numbers which will
{ ; probably happen in my AHK_L transition since gui numbers won't matter anymore
WinWaitClose, , , % Abs(Duration) ; wait to close for duration
If (ErrorLevel && Duration < 1) ; destroys window when done waiting if duration is negative
{ ; otherwise lets the calling script procede after waiting the duration (without destroying)
Gui, % Wait + GL - GF + 1 ":Destroy" ; destroys border gui
If ST
DllCall("AnimateWindow","UInt",NotifyGuiID,"Int",ST,"UInt","0x00050001") ; slides window out to the right if ST or SC are used
Gui, %Wait%:Destroy ; and destroys it
}
}
}
Else ; wait for all notify's if "Wait=All" is used in the options string
{ ; loops through all existing notify's and performs the same wait logic
Loop, % GL-GF ; (with or without destroying if negative or not)
{
Wait := A_Index + GF - 1
Gui %Wait%:+LastFound
If NotifyGuiID := WinExist()
{
WinWaitClose, , , % Abs(Duration)
If (ErrorLevel && Duration < 1)
{
Gui, % Wait + GL - GF + 1 ":Destroy" ; destroys border gui
If ST
DllCall("AnimateWindow","UInt",NotifyGuiID,"Int",ST,"UInt","0x00050001") ; slides window out to the right if ST or SC are used
Gui, %Wait%:Destroy ; and destroys it
}
}
}
GNList := ACList := ATList := AXList := "" ; clears internal variables since they're all destroyed now
}
Return
}
If Update <> ; option "Update=ID" being used, Notify window will not be created
{ ; title, message, image and progress position can be updated
If Title <>
GuiControl, %Update%:,_Title_,%Title%
If Message <>
GuiControl, %Update%:,_Message_,%Message%
If Duration <>
GuiControl, %Update%:,_Progress_,%Duration%
If Image <>
GuiControl, %Update%:,_Image_,%Image%
If Wallpaper <>
GuiControl, %Update%:,_Wallpaper_,%Image%
Return
}
If Style = Save ; option "Style=Save" is used to save the existing window style
{ ; and call it back later with "Style=Load"
Saved := Options " GC=" GC " GR=" GR " GT=" GT " BC=" BC " BK=" BK " BW=" BW " BR=" BR " BT=" BT " BF=" BF
Saved .= " TS=" TS " TW=" TW " TC=" TC " TF=" TF " MS=" MS " MW=" MW " MC=" MC " MF=" MF
Saved .= " IW=" IW " IH=" IH " IN=" IN " PW=" PW " PH=" PH " PC=" PC " PB=" PB " XC=" XC " XS=" MS " XW=" XW
Saved .= " SI=" SI " SC=" SC " ST=" ST " WF=" Image " IF=" IF
} ; this needs some major improvement to have multiple saved instead of just one, otherwise pointless
If Return <>
Return, % (%Return%)
If Style <> ; option "Style=Default will reset all variables back to defaults... except options also specified
{ ; so "Style=Default GC=Blue" is allowed, which will reset all defaults and then set GC=Blue
If Style = Default
Return % Notify(Title,Message,Duration, ; maybe handled poorly by calling itself, but it saves having to have the defaults set in two areas... thoughts?
(
"GC= GR= GT= BC= BK= BW= BR= BT= BF= TS= TW= TC= TF=
MS= MW= MC= MF= SI= ST= SC= IW=
IH= IN= XC= XS= XW= PC= PB= " Options "Style=")
) ; below are more internally saved styles, which may move to an auxiliary function at some point, but could use some improvement
Else If Style = ToolTip
Return % Notify(Title,Message,Duration,"SI=50 GC=FFFFAA BC=00000 GR=0 BR=0 BW=1 BT=255 TS=8 MS=8 " Options "Style=")
Else If Style = BalloonTip
Return % Notify(Title,Message,Duration,"SI=350 GC=FFFFAA BC=00000 GR=13 BR=15 BW=1 BT=255 TS=10 MS=8 AX=1 XC=999922 IN=8 Image=" A_WinDir "\explorer.exe " Options "Style=")
Else If Style = Error
Return % Notify(Title,Message,Duration,"SI=250 GC=Default BC=00000 GR=0 BR=0 BW=1 BT=255 TS=12 MS=12 AX=1 XC=666666 IN=10 IW=32 IH=32 Image=" A_WinDir "\explorer.exe " Options "Style=")
Else If Style = Warning
Return % Notify(Title,Message,Duration,"SI=250 GC=Default BC=00000 GR=0 BR=0 BW=1 BT=255 TS=12 MS=12 AX=1 XC=666666 IN=9 IW=32 IH=32 Image=" A_WinDir "\explorer.exe " Options "Style=")
Else If Style = Info
Return % Notify(Title,Message,Duration,"SI=250 GC=Default BC=00000 GR=0 BR=0 BW=1 BT=255 TS=12 MS=12 AX=1 XC=666666 IN=8 IW=32 IH=32 Image=" A_WinDir "\explorer.exe " Options "Style=")
Else If Style = Question
Return % Notify(Title,Message,Duration,"SI=250 GC=Default BC=00000 GR=0 BR=0 BW=1 BT=255 TS=12 MS=12 AX=1 XC=666666 Image=24 IW=32 IH=32 " Options "Style=")
Else If Style = Progress
Return % Notify(Title,Message,Duration,"SI=100 GC=Default BC=00000 GR=9 BR=13 BW=2 BT=105 TS=10 MS=10 PG=100 PH=10 GW=300 " Options "Style=")
Else If Style = Huge
Return % Notify(Title,Message,Duration,"SI=100 ST=200 SC=200 GC=FFFFAA BC=00000 GR=27 BR=39 BW=6 BT=105 TS=24 MS=22 " Options "Style=")
Else If Style = Load
Return % Notify(Title,Message,Duration,Saved)
}
}
;—————— end if options ————————————————————————————————————————————————————————————————————————————
GC_ := GC_<>"" ? GC_ : GC := GC<>"" ? GC : "FFFFAA" ; defaults are set here, and static overrides are used and saved
GR_ := GR_<>"" ? GR_ : GR := GR<>"" ? GR : 9 ; and non static options (with OP_=) are used but not saved
GT_ := GT_<>"" ? GT_ : GT := GT<>"" ? GT : "Off"
BC_ := BC_<>"" ? BC_ : BC := BC<>"" ? BC : "000000"
BK_ := BK_<>"" ? BK_ : BK := BK<>"" ? BK : "Silver"
BW_ := BW_<>"" ? BW_ : BW := BW<>"" ? BW : 2
BR_ := BR_<>"" ? BR_ : BR := BR<>"" ? BR : 13
BT_ := BT_<>"" ? BT_ : BT := BT<>"" ? BT : 105
BF_ := BF_<>"" ? BF_ : BF := BF<>"" ? BF : 350
TS_ := TS_<>"" ? TS_ : TS := TS<>"" ? TS : 10
TW_ := TW_<>"" ? TW_ : TW := TW<>"" ? TW : 625
TC_ := TC_<>"" ? TC_ : TC := TC<>"" ? TC : "Default"
TF_ := TF_<>"" ? TF_ : TF := TF<>"" ? TF : "Default"
MS_ := MS_<>"" ? MS_ : MS := MS<>"" ? MS : 10
MW_ := MW_<>"" ? MW_ : MW := MW<>"" ? MW : "Default"
MC_ := MC_<>"" ? MC_ : MC := MC<>"" ? MC : "Default"
MF_ := MF_<>"" ? MF_ : MF := MF<>"" ? MF : "Default"
SI_ := SI_<>"" ? SI_ : SI := SI<>"" ? SI : 0
SC_ := SC_<>"" ? SC_ : SC := SC<>"" ? SC : 0
ST_ := ST_<>"" ? ST_ : ST := ST<>"" ? ST : 0
IW_ := IW_<>"" ? IW_ : IW := IW<>"" ? IW : 32
IH_ := IH_<>"" ? IH_ : IH := IH<>"" ? IH : 32
IN_ := IN_<>"" ? IN_ : IN := IN<>"" ? IN : 0
XF_ := XF_<>"" ? XF_ : XF := XF<>"" ? XF : "Arial Black"
XC_ := XC_<>"" ? XC_ : XC := XC<>"" ? XC : "Default"
XS_ := XS_<>"" ? XS_ : XS := XS<>"" ? XS : 12
XW_ := XW_<>"" ? XW_ : XW := XW<>"" ? XW : 800
PC_ := PC_<>"" ? PC_ : PC := PC<>"" ? PC : "Default"
PB_ := PB_<>"" ? PB_ : PB := PB<>"" ? PB : "Default"
wPW := ((PW<>"") ? ("w" PW) : ("")) ; needs improvement, poor handling of explicit sizes and progress widths
hPH := ((PH<>"") ? ("h" PH) : (""))
If GW <>
{
wGW = w%GW%
wPW := "w" GW - 20
}
hGH := ((GH<>"") ? ("h" GH) : (""))
wGW_ := ((GW<>"") ? ("w" GW - 20) : (""))
hGH_ := ((GH<>"") ? ("h" GH - 20) : (""))
;————————————————————————————————————————————————————————————————————————
If Duration = ; default if duration is not used or set to ""
Duration = 30
GN := GF ; find the next available gui number to use, starting from GF (default 50)
Loop ; within the defined range GF to GL
IfNotInString, GNList, % "|" GN
Break
Else
If (++GN > GL) ;=== too many notifications open, returns 0, handle this error in the calling script
Return 0 ; this is uncommon as the screen is too cluttered by this point anyway
GNList .= "|" GN
GN2 := GN + GL - GF + 1
If AC <> ; saves the action to be used when clicked or timeout (or x-button is clicked)
ACList .= "|" GN "=" AC ; need to add different clicks for Title, Message, Image as well
If AT <> ; saved internally in a list, then parsed by the timer or click routine
ATList .= "|" GN "=" AT ; to run the script-side subroutine/label "AC=LabelName"
If AX <>
AXList .= "|" GN "=" AX
P_DHW := A_DetectHiddenWindows ; start finding location based on what other Notify() windows are on the screen
P_TMM := A_TitleMatchMode ; saved to restore these settings after changing them, so the calling script won't know
DetectHiddenWindows On ; as they are needed to find all as they are being made as well... or hidden for some reason...
SetTitleMatchMode 1 ; and specific window title match is a little more failsafe
If (WinExist("_Notify()_GUI_")) ;=== find all Notifications from ALL scripts, for placement
WinGetPos, OtherX, OtherY ;=== change this to a loop for all open notifications and find the highest?
DetectHiddenWindows %P_DHW% ;=== using the last Notify() made at this point, which may be better
SetTitleMatchMode %P_TMM% ; and the global settings are restored for the calling thread
Gui, %GN%:-Caption +ToolWindow +AlwaysOnTop -Border ; here begins the creation of the window
Gui, %GN%:Color, %GC_% ; with the logic to add or not add certain controls, Wallpaper, Image, Title, Progress, Message
If FileExist(WP) ; and some placement logic depending if they are used or not... could definitely be improved
{
Gui, %GN%:Add, Picture, x0 y0 w0 h0 v_Wallpaper_, % WP ; wallpaper added first, stretched to size later
ImageOptions = x+8 y+4
}
If Image <> ; icon image added next, sized, and spacing added for whats next
{
If FileExist(Image)
Gui, %GN%:Add, Picture, w%IW_% h%IH_% Icon%IN_% v_Image_ %ImageOptions%, % Image
Else
Gui, %GN%:Add, Picture, w%IW_% h%IH_% Icon%Image% v_Image_ %ImageOptions%, %A_WinDir%\system32\shell32.dll
ImageOptions = x+10
}
If Title <> ; title text control added next, if used
{
Gui, %GN%:Font, w%TW_% s%TS_% c%TC_%, %TF_%
Gui, %GN%:Add, Text, %ImageOptions% BackgroundTrans v_Title_, % Title
}
If PG ; then the progress bar, if called for
Gui, %GN%:Add, Progress, Range0-%PG% %wPW% %hPH% c%PC_% Background%PB_% v_Progress_
Else
If ((Title) && (Message)) ; some spacing tweaks if both used
Gui, %GN%:Margin, , -5
If Message <> ; and finally the message text control if used
{
Gui, %GN%:Font, w%MW_% s%MS_% c%MC_%, %MF_%
Gui, %GN%:Add, Text, BackgroundTrans v_Message_, % Message
}
If ((Title) && (Message)) ; final spacing
Gui, %GN%:Margin, , 8
Gui, %GN%:Show, Hide %wGW% %hGH%, _Notify()_GUI_ ; final sizing
Gui %GN%:+LastFound ; would like to get rid of this to prevent calling script being affected
WinGetPos, GX, GY, GW, GH ; final positioning
GuiControl, %GN%:, _Wallpaper_, % "*w" GW " *h" GH " " WP ; stretch that wallpaper to size
GuiControl, %GN%:MoveDraw, _Title_, % "w" GW-20 " h" GH-10 ; poor handling of text wrapping when gui has explicit size called
GuiControl, %GN%:MoveDraw, _Message_, % "w" GW-20 " h" GH-10 ; needs improvement (and if image is used or not)
If AX <> ; add the corner "X" for closing with a different action than otherwise clicked
{
GW += 10
Gui, %GN%:Font, w%XW_% s%XS_% c%XC_%, Arial Black ; × (multiply) is the character used for the X-Button
Gui, %GN%:Add, Text, % "x" GW-15 " y-2 Center w12 h20 g_Notify_Kill_" GN - GF + 1, % chr(0x00D7) ;××
}
Gui, %GN%:Add, Text, x0 y0 w%GW% h%GH% BackgroundTrans g_Notify_Action_Clicked_ ; to catch clicks anywhere on the gui
If (GR_) ; may have to be removed for seperate title/message/etc actions
WinSet, Region, % "0-0 w" GW " h" GH " R" GR_ "-" GR_
If (GT_) ; non-functioning GT option, since the border gui gets in the way
WinSet, Transparent, % GT_ ; will be addressed someday, leaving it in
SysGet, Workspace, MonitorWorkArea ; positioning
NewX := WorkSpaceRight-GW-5
If (OtherY)
NewY := OtherY-GH-2-BW_*2
Else
NewY := WorkspaceBottom-GH-5
If NewY < % WorkspaceTop
NewY := WorkspaceBottom-GH-5
Gui, %GN2%:-Caption +ToolWindow +AlwaysOnTop -Border +E0x20 ; border gui
Gui, %GN2%:Color, %BC_%
Gui %GN2%:+LastFound
If (BR_)
WinSet, Region, % "0-0 w" GW+(BW_*2) " h" GH+(BW_*2) " R" BR_ "-" BR_
If (BT_)
WinSet, Transparent, % BT_
Gui, %GN2%:Show, % "Hide x" NewX-BW_ " y" NewY-BW_ " w" GW+(BW_*2) " h" GH+(BW_*2), _Notify()_BGGUI_ ; actual creation of border gui! but still not shown
Gui, %GN%:Show, % "Hide x" NewX " y" NewY " w" GW, _Notify()_GUI_ ; actual creation of Notify() gui! but still not shown
Gui %GN%:+LastFound ; need to get rid of this so calling script isn't affected
If SI_
DllCall("AnimateWindow","UInt",WinExist(),"Int",SI_,"UInt","0x00040008") ; animated in, if SI is used
Else
Gui, %GN%:Show, NA, _Notify()_GUI_ ; otherwise, just shown
Gui, %GN2%:Show, NA, _Notify()_BGGUI_ ; and the border shown
WinSet, AlwaysOnTop, On ; and set to Always on Top
If ((Duration < 0) OR (Duration = "-0")) ; saves internally that ExitApp should happen when this
Exit := GN ; notify dissappears
If (Duration)
SetTimer, % "_Notify_Kill_" GN - GF + 1, % - Abs(Duration) * 1000 ; timer set depending on Duration parameter
Else
SetTimer, % "_Notify_Flash_" GN - GF + 1, % BF_ ; timer set to flash border if the Notify has 0 (infinite) duration
Return %GN% ; end of Notify(), returns Gui ID number used
;==========================================================================
;========================================== when a notification is clicked:
_Notify_Action_Clicked_: ; option AC=Label means Label: subroutine will be called here when clicked
; Critical
SetTimer, % "_Notify_Kill_" A_Gui - GF + 1, Off
Gui, % A_Gui + GL - GF + 1 ":Destroy"
If SC
{
Gui, %A_Gui%:+LastFound
DllCall("AnimateWindow","UInt",WinExist(),"Int",SC,"UInt", "0x00050001")
}
Gui, %A_Gui%:Destroy
If (ACList)
Loop,Parse,ACList,|
If ((Action := SubStr(A_LoopField,1,2)) = A_Gui)
{
Temp_Notify_Action:= SubStr(A_LoopField,4)
StringReplace, ACList, ACList, % "|" A_Gui "=" Temp_Notify_Action, , All
If IsLabel(_Notify_Action := Temp_Notify_Action)
Gosub, %_Notify_Action%
_Notify_Action =
Break
}
StringReplace, GNList, GNList, % "|" A_Gui, , All
SetTimer, % "_Notify_Flash_" A_Gui - GF + 1, Off
If (Exit = A_Gui)
ExitApp
Return
;==========================================================================
;=========================================== when a notification times out:
_Notify_Kill_1:
_Notify_Kill_2: ; this needs a different method, too many labels
_Notify_Kill_3: ; they are used for Timers, different for each Notify() based on duration...
_Notify_Kill_4:
_Notify_Kill_5:
_Notify_Kill_6:
_Notify_Kill_7:
_Notify_Kill_8:
_Notify_Kill_9:
_Notify_Kill_10:
_Notify_Kill_11:
_Notify_Kill_12:
_Notify_Kill_13:
_Notify_Kill_14:
_Notify_Kill_15:
_Notify_Kill_16:
_Notify_Kill_17:
_Notify_Kill_18:
_Notify_Kill_19:
_Notify_Kill_20:
_Notify_Kill_21:
_Notify_Kill_22:
_Notify_Kill_23:
_Notify_Kill_24:
_Notify_Kill_25:
Critical
StringReplace, GK, A_ThisLabel, _Notify_Kill_
SetTimer, _Notify_Flash_%GK%, Off
GK := GK + GF - 1
Gui, % GK + GL - GF + 1 ":Destroy"
If ST
{
Gui, %GK%:+LastFound
DllCall("AnimateWindow","UInt",WinExist(),"Int",ST,"UInt", "0x00050001")
}
Gui, %GK%:Destroy
StringReplace, GNList, GNList, % "|" GK, , All
If (Exit = GK)
ExitApp
Return 1
;==========================================================================
;======================================== flashes a permanent notification:
_Notify_Flash_1:
_Notify_Flash_2:
_Notify_Flash_3:
_Notify_Flash_4: ; this needs a different method, too many labels
_Notify_Flash_5: ; they are used for Timers, different for each Notify() based on flash speed...
_Notify_Flash_6: ; when duration is 0 (infinite)
_Notify_Flash_7: ; this may feature may be removed completely, Update given the ability to affect GC and BC
_Notify_Flash_8: ; and then the flashing could be handled script-side via returned gui number and a script-side timer
_Notify_Flash_9:
_Notify_Flash_10:
_Notify_Flash_11:
_Notify_Flash_12:
_Notify_Flash_13:
_Notify_Flash_14:
_Notify_Flash_15:
_Notify_Flash_16:
_Notify_Flash_17:
_Notify_Flash_18:
_Notify_Flash_19:
_Notify_Flash_20:
_Notify_Flash_21:
_Notify_Flash_22:
_Notify_Flash_23:
_Notify_Flash_24:
_Notify_Flash_25:
StringReplace, FlashGN, A_ThisLabel, _Notify_Flash_
FlashGN += GF - 1
FlashGN2 := FlashGN + GL - GF + 1
If Flashed%FlashGN2% := !Flashed%FlashGN2%
Gui, %FlashGN2%:Color, %BK%
Else
Gui, %FlashGN2%:Color, %BC%
Return
}
+109
View File
@@ -0,0 +1,109 @@
;namespace DBA
/*
Represents a result set of ADO
http://www.w3schools.com/ado/ado_ref_recordset.asp
*/
class RecordSetADO extends DBA.RecordSet
{
_adoRS := 0 ; ado recordset
__New(sql, adoConnection, editable = false){
this._adoRS := ComObjCreate("ADODB.Recordset")
if(editable)
this._adoRS.Open(sql, adoConnection, ADO.CursorType.adOpenKeyset, ADO.LockType.adLockOptimistic, ADO.CommandType.adCmdTable)
else
this._adoRS.Open(sql, adoConnection)
}
/*
Is this RecordSet valid?
*/
IsValid(){
return (IsObject(this._adoRS))
}
/*
Returns an Array with all Column Names
*/
getColumnNames(){
colNames := new Collection()
for adoField in this._adoRS.Fields
colNames.add(adoField.Name)
return colNames
}
getEOF(){
return this._adoRS.EOF
}
AddNew(){
if(this.IsValid())
{
this._adoRS.AddNew()
}
}
MoveNext() {
if(this.IsValid())
{
this._adoRS.MoveNext()
}
}
Delete(){
if(this.IsValid() && !this.getEOF())
{
this._adoRS.Delete(ADO.AffectEnum.adAffectCurrent)
}
}
Update(){
if(this.IsValid() && !this.getEOF())
{
this._adoRS.Update()
}
}
Reset() {
if(this.IsValid()){
this._adoRS.MoveFirst()
}
}
Count(){
cnt := 0
if(this.IsValid())
cnt := this._adoRS.RecordCount
return cnt
}
Close() {
if(this.IsValid())
this._adoRS.Close()
}
__Get(param){
if(IsObject(param)){
throw Exception("Expected Index or Column Name!",-1)
}
if(param = "EOF")
return this.getEOF()
if(!IsObjectMember(this, param) && param != "_currentRow"){
if(this.IsValid())
{
df := this._adoRS.Fields[param]
return df.Value
}
}
}
}
+109
View File
@@ -0,0 +1,109 @@
;namespace DBA
/*
Represents a result set of an MySQL Query
*/
class RecordSetMySQL extends DBA.RecordSet
{
_colNames := 0 ; Collection<ColumnNames>
_colCount := 0
_query := 0 ; ptr to Resultset/Query
_db := 0 ; ptr to DataBase
_eof := false ; bool
CurrentRow := 0 ; int - row number
__New(db, requestResult){
this._db := db
this._query := requestResult
if(this._query != 0){
this._colNames := this.getColumnNames()
this.MoveNext()
}
}
/*
Is this RecordSet valid?
*/
IsValid(){
return (this._query != 0)
}
/*
Returns an Array with all Column Names
*/
getColumnNames(){
mysqlFields := MySQL_fetch_fields(this._query)
colNames := new Collection()
i := 0
for each, mysqlField in mysqlFields
{
colNames.Add(mysqlField.Name())
i++
}
this._colCount := i
return colNames
}
getEOF(){
return this._eof
}
MoveNext() {
static EOR := -1
this.ErrorMsg := ""
this.ErrorCode := 0
this._currentRow := 0
if (!this._query) {
this.ErrorMsg := "Invalid query handle!"
this._eof := true
return false
}
rowptr := MySQL_fetch_row(this._query)
if (!rowptr){
; // we reached eof
this.ErrorMsg := "RecordSet is empty! (eof)"
this.ErrorCode := 1
this._eof := true
return false
}
lengths := MySQL_fetch_lengths(this._query)
datafields := new Collection()
Loop % this._colCount
{
length := GetUIntAtAddress(lengths, A_Index - 1)
fieldPointer := GetPtrAtAddress(rowptr, A_Index - 1)
fieldValue := StrGet(fieldPointer, length, "CP0")
datafields.Add(fieldValue)
}
this._currentRow := new DBA.Row(this._colNames, datafields)
this.CurrentRow++
return true
}
Reset() {
throw Exception("Not Supported!",-1)
}
Close() {
this.ErrorMsg := ""
this.ErrorCode := 0
if(this._query == 0)
return true
MySQL_free_result(this._query)
this._query := 0
return true
}
}
+139
View File
@@ -0,0 +1,139 @@
;namespace DBA
/*
Represents a result set of an SQLite Query
*/
class RecordSetSqlLite extends DBA.RecordSet
{
_currentRow := 0 ; Row
_colNames := 0 ; Collection<ColumnNames>
_query := 0 ; int Handle to the Query
_db := 0 ; SQLiteDataBase
_eof := false ; bool
/*
Is this RecordSet valid?
*/
IsValid(){
return (this._query != 0)
}
/*
Returns an Array with all Column Names
*/
getColumnNames(){
SQLite_FetchNames(this._query, names)
return new Collection(names)
}
getEOF(){
return this._eof
}
MoveNext() {
static SQLITE_NULL := 5
static EOR := -1
this.ErrorMsg := ""
this.ErrorCode := 0
this._currentRow := 0
if (!this._query) {
this.ErrorMsg := "Invalid query handle!"
this._eof := true
return false
}
rc := DllCall("SQlite3\sqlite3_step", "UInt", this._query, "Cdecl Int")
if (rc != this._db.ReturnCode("SQLITE_ROW")) {
if (rc = this._db.ReturnCode("SQLITE_DONE")) {
this.ErrorMsg := "EOR"
this.ErrorCode := rc
this._eof := true
return EOR
}
this.ErrorMessage := This._db.ErrMsg()
this.ErrorCode := rc
this._eof := true
return false
}
rc := DllCall("SQlite3\sqlite3_data_count", "UInt", this._query, "Cdecl Int")
if (rc < 1) {
this.ErrorMsg := "RecordSet is empty!"
this.ErrorCode := this._db.ReturnCode("SQLITE_EMPTY")
this._eof := true
return false
}
; fill the internal row structure
;_currentRow := new Row()
fields := new Collection()
Loop, %rc% {
ctype := DllCall("SQlite3\sqlite3_column_type", "UInt", this._query, "Int", A_Index - 1, "Cdecl Int")
if (ctype == SQLITE_NULL) {
fields[A_Index] := ""
} else {
strPtr := DllCall("SQlite3\sqlite3_column_text", "UInt", this._query, "Int", A_Index - 1, "Cdecl UInt")
fields[A_Index] := StrGet(strPtr, "UTF-8")
}
}
this._currentRow := new DBA.Row(this._colNames, fields)
this.CurrentRow++
return true
}
Reset() {
this.ErrorMsg := ""
this.ErrorCode := 0
if (!this._query) {
this.ErrorMsg := "Invalid query handle!"
return false
}
rc := DllCall("SQlite3\sqlite3_reset", "UInt", this._query, "Cdecl Int")
if (rc) {
this.ErrorMsg := This._db.ErrMsg()
this.ErrorCode := rc
return false
}
this.CurrentRow := 0
this.MoveNext()
return true
}
Close() {
this.ErrorMsg := ""
this.ErrorCode := 0
if(this._query == 0)
return true
rc := DllCall("SQlite3\sqlite3_finalize", "UInt", this._query, "Cdecl Int")
if (rc) {
this.ErrorMsg := this._db.ErrMsg()
this.ErrorCode := rc
return false
}
this._query := 0
return true
}
__New(db, query){
if(!is(db, DBA.DataBaseSQLLite)){
throw Exception("db must be a DataBaseSQLLite Object",-1)
}
this._db := db
this._query := query
if(query != 0){
this._colNames := this.getColumnNames()
this.MoveNext()
}
}
}
+1044
View File
File diff suppressed because it is too large Load Diff
+1
View File
@@ -0,0 +1 @@
del *.bak
+15
View File
@@ -0,0 +1,15 @@
AHK DBA - OOP Database Access Framework
Copyright (C) 2012 IsNull and other contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
+431
View File
@@ -0,0 +1,431 @@
/*============================================================
mysql.ahk
Provides a set of functions to connect and query a mysql database
Based upon the published lib of panofish
http://www.autohotkey.com/forum/topic67280.html
Offical Documentation of the C-API
http://dev.mysql.com/doc/refman/5.0/en/c.html
============================================================
*/
/*
Parses the given Connectionstring to a ConnectionData
An typical Connectionstring looks like:
Server=myServerAddress;Port=1234;Database=myDataBase;Uid=myUsername;Pwd=myPassword;
Further Info: http://www.connectionstrings.com/mysql
*/
MySQL_CreateConnectionData(connectionString){
connectionData := {}
StringSplit, connstr, connectionString, `;
Loop, % connstr0
{
StringSplit, segment, connstr%a_index%, =
connectionData[segment1] := segment2
}
return connectionData
}
MySQL_StartUp(){
global MySQL_ExternDir
MySQL_ExternDir := A_WorkingDir
libDllpath := MySQL_DLLPath()
if(!FileExist(libDllpath))
{
msg := "MySQL Libaray not found!`n" libDllpath " (file missing)"
OutputDebug, %msg%
throw Exception(msg,-1)
}
hModule := DllCall("LoadLibrary", "Str", libDllpath)
if (hModule == 0)
{
msg := "LoadLibrary failed, can't load module:`n" libDllpath
OutputDebug, %msg%
throw Exception(msg, -1)
}else
return hModule
}
MySQL_DLLPath(forcedPath = "") {
static DLLPath := ""
static dllname := "libmySQL.dll"
if(DLLPath == ""){
; search the dll
prefix := (A_PtrSize == 8) ? "x64\" : ""
dllpath := prefix . dllname
if (FileExist(A_ScriptDir . "\" . dllpath))
DLLPath := A_ScriptDir . "\" . dllpath
else
DLLPath := A_ScriptDir . "\Lib\" . dllpath
}
if (forcedPath != "")
DLLPath := forcedPath
return DLLPath
}
/*****************************************************************
Connect to mysql database and return db handle
host:
user:
password:
database:
port: 3306(default)
******************************************************************
*/
MySQL_Connect(host, user, password, database, port = 3306){
db := DllCall("libmySQL.dll\mysql_init", "ptr", 0)
if (db = 0)
throw Exception("MySQL Error 445, Not enough memory to connect to MySQL", -1)
connection := DllCall("libmySQL.dll\mysql_real_connect"
, "ptr", db
, "AStr", host ; host name
, "AStr", user ; user name
, "AStr", password ; password
, "AStr", database ; database name
, "UInt", port ; port
, "UInt", 0 ; unix_socket
, "UInt", 0) ; client_flag
If (connection == 0)
throw Exception(BuildMySQLErrorStr(db, "Cannot connect to database"), -1)
;debugging only:
;MsgBox % "Ping database: " . MySQL_Ping(db) . "`nServer version: " . MySQL_GetVersion(db)
return db
}
MySQL_Close(db){
DllCall("libmySQL.dll\mysql_close", "ptr", db)
}
MySQL_GetVersion(db){
serverVersion := DllCall("libmySQL.dll\mysql_get_server_info", "ptr", db, "AStr")
return serverVersion
}
MySQL_Ping(db){
return DllCall("libmySQL.dll\mysql_ping", "ptr", db)
}
MySQL_GetLastErrorNo(db){
return DllCall("libmySQL.dll\mysql_errno", "ptr", db)
}
MySQL_GetLastErrorMsg(db){
return DllCall("libmySQL.dll\mysql_error", "ptr", db, "AStr")
}
/*
Retrieves a complete result set to the client.
*/
MySQL_Store_Result(db) {
return DllCall("libmySQL.dll\mysql_store_result", "ptr", db)
}
/*
Retrieves the resultset row-by-row
*/
MySQL_Use_Result(db) {
return DllCall("libmySQL.dll\mysql_use_result", "ptr", db)
}
/*
Returns a requestResult for the given query
*/
MySQL_Query(db, query){
return DllCall("libmySQL.dll\mysql_query", "ptr", db , "AStr", query)
}
MySQL_free_result(requestResult){
return DllCall("libmySQL.dll\mysql_free_result", "ptr", requestResult)
}
/*
Returns the number of columns in a result set.
*/
MySQL_num_fields(requestResult) {
Return DllCall("libmySQL.dll\mysql_num_fields", "ptr", requestResult)
}
/*
Returns the lengths of all columns in the current row.
*/
MySQL_fetch_lengths(requestResult) {
Return , DllCall("libmySQL.dll\mysql_fetch_lengths", "ptr", requestResult)
}
/*
Fetches the next row from the result set.
*/
MySQL_fetch_row(requestResult) {
Return , DllCall("libmySQL.dll\mysql_fetch_row", "ptr", requestResult)
}
/*
Fetches given Field
*/
Mysql_fetch_field_direct(requestResult, fieldnum) {
return DllCall("libmySQL.dll\mysql_fetch_field_direct", "ptr", requestResult, "Uint", fieldnum)
}
/*
Fetches the next field from the result set.
*/
Mysql_fetch_field(requestResult) {
return DllCall("libmySQL.dll\mysql_fetch_field", "ptr", requestResult)
}
/*
Fetches all fields of the resultSet
*/
MySQL_fetch_fields(requestResult){
global MySQL_Field
fields := []
fieldCount := MySQL_num_fields(requestResult)
Loop, % fieldCount
{
fptr := Mysql_fetch_field(requestResult)
fields[A_index] := new MySQL_Field(fptr)
}
return fields
}
/*
; mysql error handling
*/
BuildMySQLErrorStr(db, message, query="") {
errorCode := DllCall("libmySQL.dll\mysql_errno", "UInt", db)
errorStr := DllCall("libmySQL.dll\mysql_error", "UInt", db, "AStr")
Return, "MySQL Error: " message "Error " errorCode ": " errorStr "`n`n" query
}
;============================================================
; mysql get address
;============================================================
GetUIntAtAddress(_addr, _offset)
{
return NumGet(_addr+0,_offset * 4, "uint")
}
GetPtrAtAddress(_addr, _offset)
{
return NumGet(_addr+0,_offset * A_PtrSize, "ptr")
}
;============================================================
; internal: dump resultset from given Query to string
;============================================================
__MySQL_Query_Dump(_db, _query)
{
local resultString, result, requestResult, fieldCount
local row, lengths, length, fieldPointer, field
result := DllCall("libmySQL.dll\mysql_query", "UInt", _db , "AStr", _query)
If (result != 0)
throw new Exception(BuildMySQLErrorStr(_db, "dbQuery Fail", RegExReplace(_query , "\t", " ")), -1)
requestResult := MySql_Store_Result(_db)
if (requestResult = 0) { ; call must have been an insert or delete ... a select would return results to pass back
return
}
fieldCount := MySQL_num_fields(requestResult)
myfields := MySQL_fetch_fields(requestResult)
for each, fifi in myfields
{
MsgBox % "name: " fifi.Name() "`n org name: " fifi.OrgName() "`ntable: " fifi.Table() "`norg table: " fifi.OrgTable()
}
Loop
{
row := MySQL_fetch_row(requestResult)
if (!row)
break
; Get a pointer on a table of lengths (unsigned long)
lengths := MySQL_fetch_lengths(requestResult)
Loop %fieldCount%
{
length := GetUIntAtAddress(lengths, A_Index - 1)
fieldPointer := GetPtrAtAddress(row, A_Index - 1)
field := StrGet(fieldPointer, length, "CP0")
resultString := resultString . field
if (A_Index < fieldCount)
resultString := resultString . "|" ; seperator for fields
}
resultString := resultString . "`n" ; seperator for records
}
MySQL_free_result(requestResult)
resultString := RegExReplace(resultString , "`n$", "")
return resultString
}
;============================================================
; Escape mysql special characters
; This must be done to sql insert columns where the characters might contain special characters, such as user input fields
;
; Escape Sequence Character Represented by Sequence
; \' A single quote (“'”) character.
; \" A double quote (“"”) character.
; \n A newline (linefeed) character.
; \r A carriage return character.
; \t A tab character.
; \\ A backslash (“\”) character.
; \% A “%” character. Usually indicates a wildcard character
; \_ A “_” character. Usually indicates a wildcard character
; \b A backspace character.
;
; these 2 have not yet been included yet
; \Z ASCII 26 (Control+Z). Stands for END-OF-FILE on Windows
; \0 An ASCII NUL (0x00) character.
;
; example call:
; description := mysql_escape_string(description)
;============================================================
Mysql_escape_string(unescaped_string)
{
escaped_string := RegExReplace(unescaped_string, "\\", "\\") ; \
escaped_string := RegExReplace(escaped_string, "'", "\'") ; '
escaped_string := RegExReplace(escaped_string, "`t", "\t") ; \t
escaped_string := RegExReplace(escaped_string, "`n", "\n") ; \n
escaped_string := RegExReplace(escaped_string, "`r", "\r") ; \r
escaped_string := RegExReplace(escaped_string, "`b", "\b") ; \b
; these characters appear to insert fine in mysql
;escaped_string := RegExReplace(escaped_string, "%", "\%") ; %
;escaped_string := RegExReplace(escaped_string, "_", "\_") ; _
;escaped_string := RegExReplace(escaped_string, """", "\""") ; "
return escaped_string
}
/*
typedef struct st_mysql_field {
char *name; /* Name of column */
char *org_name; /* Original column name, if an alias */
char *table; /* Table of column if column was a field */
char *org_table; /* Org table name, if table was an alias */
char *db; /* Database for table */
char *catalog; /* Catalog for table */
char *def; /* Default value (set by mysql_list_fields) */
unsigned long length; /* Width of column (create length) */
unsigned long max_length; /* Max width for selected set */
unsigned int name_length;
unsigned int org_name_length;
unsigned int table_length;
unsigned int org_table_length;
unsigned int db_length;
unsigned int catalog_length;
unsigned int def_length;
unsigned int flags; /* Div flags */
unsigned int decimals; /* Number of decimals in field */
unsigned int charsetnr; /* Character set */
enum enum_field_types type; /* Type of field. See mysql_com.h for types */
void *extension;
} MYSQL_FIELD;
*/
/*
'mysql_port is a long
'mysql_unix port is a long (pointer)
'sizeof(MYSQL_FIELD)=32
Public Type API_MYSQL_FIELD
name As Long
table As Long
def As Long
type As API_enum_field_types
length As Long
max_length As Long
flags As Long
decimals As Long
End Type
*/
class MySQL_Field
{
ptr := 0
__new(ptr){
this.ptr := ptr
}
Name(){
adr := GetPtrAtAddress(this.ptr, 0)
return StrGet(adr, 255, "CP0")
}
OrgName(){
adr := GetPtrAtAddress(this.ptr, 4)
return StrGet(adr, 255, "CP0")
}
Table(){
adr := GetPtrAtAddress(this.ptr, 8)
return StrGet(adr, 255, "CP0")
}
OrgTable(){
adr := GetPtrAtAddress(this.ptr, 12)
return StrGet(adr, 255, "CP0")
}
}
+27
View File
@@ -0,0 +1,27 @@
AHK DBA - OOP Database Access Framework for AutoHotkey (_L)
Currently DBA supports SQLite, MySQL and ADO.
DBA is an object oriented wrapper around several different
databases/database providers to standardize the access interface.
It is similar to ADO from MS or the jdbc driver in Java.
Copyright (C) 2012 IsNull and other contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
+203
View File
@@ -0,0 +1,203 @@
EXPORTS
sqlite3_aggregate_context
sqlite3_aggregate_count
sqlite3_auto_extension
sqlite3_backup_finish
sqlite3_backup_init
sqlite3_backup_pagecount
sqlite3_backup_remaining
sqlite3_backup_step
sqlite3_bind_blob
sqlite3_bind_double
sqlite3_bind_int
sqlite3_bind_int64
sqlite3_bind_null
sqlite3_bind_parameter_count
sqlite3_bind_parameter_index
sqlite3_bind_parameter_name
sqlite3_bind_text
sqlite3_bind_text16
sqlite3_bind_value
sqlite3_bind_zeroblob
sqlite3_blob_bytes
sqlite3_blob_close
sqlite3_blob_open
sqlite3_blob_read
sqlite3_blob_reopen
sqlite3_blob_write
sqlite3_busy_handler
sqlite3_busy_timeout
sqlite3_changes
sqlite3_clear_bindings
sqlite3_close
sqlite3_collation_needed
sqlite3_collation_needed16
sqlite3_column_blob
sqlite3_column_bytes
sqlite3_column_bytes16
sqlite3_column_count
sqlite3_column_database_name
sqlite3_column_database_name16
sqlite3_column_decltype
sqlite3_column_decltype16
sqlite3_column_double
sqlite3_column_int
sqlite3_column_int64
sqlite3_column_name
sqlite3_column_name16
sqlite3_column_origin_name
sqlite3_column_origin_name16
sqlite3_column_table_name
sqlite3_column_table_name16
sqlite3_column_text
sqlite3_column_text16
sqlite3_column_type
sqlite3_column_value
sqlite3_commit_hook
sqlite3_compileoption_get
sqlite3_compileoption_used
sqlite3_complete
sqlite3_complete16
sqlite3_config
sqlite3_context_db_handle
sqlite3_create_collation
sqlite3_create_collation16
sqlite3_create_collation_v2
sqlite3_create_function
sqlite3_create_function16
sqlite3_create_function_v2
sqlite3_create_module
sqlite3_create_module_v2
sqlite3_data_count
sqlite3_db_config
sqlite3_db_filename
sqlite3_db_handle
sqlite3_db_mutex
sqlite3_db_readonly
sqlite3_db_release_memory
sqlite3_db_status
sqlite3_declare_vtab
sqlite3_enable_load_extension
sqlite3_enable_shared_cache
sqlite3_errcode
sqlite3_errmsg
sqlite3_errmsg16
sqlite3_exec
sqlite3_expired
sqlite3_extended_errcode
sqlite3_extended_result_codes
sqlite3_file_control
sqlite3_finalize
sqlite3_free
sqlite3_free_table
sqlite3_get_autocommit
sqlite3_get_auxdata
sqlite3_get_table
sqlite3_global_recover
sqlite3_initialize
sqlite3_interrupt
sqlite3_last_insert_rowid
sqlite3_libversion
sqlite3_libversion_number
sqlite3_limit
sqlite3_load_extension
sqlite3_log
sqlite3_malloc
sqlite3_memory_alarm
sqlite3_memory_highwater
sqlite3_memory_used
sqlite3_mprintf
sqlite3_mutex_alloc
sqlite3_mutex_enter
sqlite3_mutex_free
sqlite3_mutex_leave
sqlite3_mutex_try
sqlite3_next_stmt
sqlite3_open
sqlite3_open16
sqlite3_open_v2
sqlite3_os_end
sqlite3_os_init
sqlite3_overload_function
sqlite3_prepare
sqlite3_prepare16
sqlite3_prepare16_v2
sqlite3_prepare_v2
sqlite3_profile
sqlite3_progress_handler
sqlite3_randomness
sqlite3_realloc
sqlite3_release_memory
sqlite3_reset
sqlite3_reset_auto_extension
sqlite3_result_blob
sqlite3_result_double
sqlite3_result_error
sqlite3_result_error16
sqlite3_result_error_code
sqlite3_result_error_nomem
sqlite3_result_error_toobig
sqlite3_result_int
sqlite3_result_int64
sqlite3_result_null
sqlite3_result_text
sqlite3_result_text16
sqlite3_result_text16be
sqlite3_result_text16le
sqlite3_result_value
sqlite3_result_zeroblob
sqlite3_rollback_hook
sqlite3_rtree_geometry_callback
sqlite3_set_authorizer
sqlite3_set_auxdata
sqlite3_shutdown
sqlite3_sleep
sqlite3_snprintf
sqlite3_soft_heap_limit
sqlite3_soft_heap_limit64
sqlite3_sourceid
sqlite3_sql
sqlite3_status
sqlite3_step
sqlite3_stmt_busy
sqlite3_stmt_readonly
sqlite3_stmt_status
sqlite3_stricmp
sqlite3_strnicmp
sqlite3_table_column_metadata
sqlite3_test_control
sqlite3_thread_cleanup
sqlite3_threadsafe
sqlite3_total_changes
sqlite3_trace
sqlite3_transfer_bindings
sqlite3_update_hook
sqlite3_uri_boolean
sqlite3_uri_int64
sqlite3_uri_parameter
sqlite3_user_data
sqlite3_value_blob
sqlite3_value_bytes
sqlite3_value_bytes16
sqlite3_value_double
sqlite3_value_int
sqlite3_value_int64
sqlite3_value_numeric_type
sqlite3_value_text
sqlite3_value_text16
sqlite3_value_text16be
sqlite3_value_text16le
sqlite3_value_type
sqlite3_vfs_find
sqlite3_vfs_register
sqlite3_vfs_unregister
sqlite3_vmprintf
sqlite3_vsnprintf
sqlite3_vtab_config
sqlite3_vtab_on_conflict
sqlite3_wal_autocheckpoint
sqlite3_wal_checkpoint
sqlite3_wal_checkpoint_v2
sqlite3_wal_hook
sqlite3_win32_mbcs_to_utf8
sqlite3_win32_utf8_to_mbcs
BIN
View File
Binary file not shown.
Binary file not shown.