Reload
This commit is contained in:
+52
@@ -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
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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%
|
||||
}
|
||||
}
|
||||
@@ -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
@@ -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>
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1 @@
|
||||
del *.bak
|
||||
@@ -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
@@ -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")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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
@@ -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
|
||||
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user