123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949 |
- ' Copyright (c) 2007-2022 Bruce A Henderson
- ' All rights reserved.
- '
- ' Redistribution and use in source and binary forms, with or without
- ' modification, are permitted provided that the following conditions are met:
- ' * Redistributions of source code must retain the above copyright
- ' notice, this list of conditions and the following disclaimer.
- ' * Redistributions in binary form must reproduce the above copyright
- ' notice, this list of conditions and the following disclaimer in the
- ' documentation and/or other materials provided with the distribution.
- ' * Neither the auther nor the names of its contributors may be used to
- ' endorse or promote products derived from this software without specific
- ' prior written permission.
- '
- ' THIS SOFTWARE IS PROVIDED BY Bruce A Henderson ``AS IS'' AND ANY
- ' EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- ' WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- ' DISCLAIMED. IN NO EVENT SHALL Bruce A Henderson BE LIABLE FOR ANY
- ' DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- ' (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- ' LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- ' ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- ' (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- ' SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- '
- SuperStrict
- Rem
- bbdoc: Database Driver - MariaDB
- about: A MariaDB database driver for #Database.Core
- End Rem
- Module Database.MariaDB
- ModuleInfo "Version: 1.01"
- ModuleInfo "Author: Bruce A Henderson"
- ModuleInfo "License: BSD"
- ModuleInfo "Copyright: Wrapper - 2007-2022 Bruce A Henderson"
- ModuleInfo "History: 1.01"
- ModuleInfo "History: Fixed setting Null binds"
- ModuleInfo "History: 1.00 Initial Release"
- ?win32x86
- ModuleInfo "LD_OPTS: -L%PWD%/lib/win32x86"
- ?win32x64
- ModuleInfo "LD_OPTS: -L%PWD%/lib/win32x64"
- ?win32arm
- ModuleInfo "LD_OPTS: -L%PWD%/lib/win32arm"
- ?win32arm64
- ModuleInfo "LD_OPTS: -L%PWD%/lib/win32arm64"
- ?macos
- ModuleInfo "CC_OPTS: `pkg-config --cflags libmariadb`"
- ModuleInfo "LD_OPTS: `pkg-config --libs-only-L libmariadb`"
- ?linux
- ModuleInfo "CC_OPTS: `pkg-config --cflags libmariadb`"
- ModuleInfo "LD_OPTS: `pkg-config --libs-only-L libmariadb`"
- ?
- Import "common.bmx"
- Type TDBMariaDB Extends TDBConnection
- Field clientVersion:Int
- Field serverVersion:Int
- Function Create:TDBConnection(dbname:String = Null, host:String = Null, ..
- port:Int = Null, user:String = Null, password:String = Null, server:String = Null, options:String = Null)
-
- Local this:TDBMariaDB = New TDBMariaDB
-
- this.init(dbname, host, port, user, password, server, options)
-
- this.clientVersion = mysql_get_client_version()
-
- If this._dbname Then
- this.open(user, password)
- End If
-
- Return this
-
- End Function
- Method close()
- If _isOpen Then
- free() ' tidy up queries and stuff
-
- mysql_close(handle)
- handle = Null
- _isOpen = False
- End If
- End Method
- Method isOpen:Int()
- If _isOpen Then
- ' really check that the database is open
- If mysql_ping(handle) Then
- setError("Connection has closed", Null, TDatabaseError.ERROR_CONNECTION, mysql_errno(handle))
- _isOpen = False
- End If
- End If
-
- Return _isOpen
- End Method
-
- Method commit:Int()
- If Not _isOpen Then
- Return False
- End If
-
- If mysql_query(handle, "COMMIT") Then
- setError("Error committing transaction", Null, TDatabaseError.ERROR_TRANSACTION, mysql_errno(handle))
- Return False
- End If
-
- Return True
- End Method
-
- Method getTables:String[]()
- Local list:String[]
-
- If Not _isOpen Then
- Return list
- End If
-
- Local tableList:TList = New TList
- Local tablesHandle:Byte Ptr = mysql_list_tables(handle, Null)
-
- If tablesHandle Then
- Local row:Byte Ptr = mysql_fetch_row(tablesHandle)
- While row
- Local s:String = String.FromUTF8String(bmx_mysql_rowField_chars(row, 0))
- tableList.addLast(s)
-
- row = mysql_fetch_row(tablesHandle)
- Wend
-
- mysql_free_result(tablesHandle)
- End If
-
- If tableList.count() > 0 Then
- list = New String[tableList.count()]
- Local i:Int = 0
- For Local s:String = EachIn tableList
- list[i] = s
- i:+ 1
- Next
- End If
-
- Return list
- End Method
- Method getTableInfo:TDBTable(tableName:String, withDDL:Int = False)
- If Not _isOpen Then
- Return Null
- End If
-
- Local query:TDatabaseQuery = TDatabaseQuery.Create(Self)
-
- Local table:TDBTable
- Local sql:String = "SHOW COLUMNS FROM " + tableName
-
- If query.execute(sql) Then
- table = New TDBTable
- table.name = tableName
-
- Local cols:TList = New TList
-
- For Local rec:TQueryRecord = EachIn query
- Local name:String = rec.GetString(0)
- Local _type:String = rec.GetString(1).Split("(")[0]
- Local dbType:Int
- Select _type
- Case "boolean", "bool", "tinyint", "smallint", "mediumint", "int", "integer"
- dbType = DBTYPE_INT
- Case "bigint"
- dbType = DBTYPE_LONG
- Case "real", "double", "decimal"
- dbType = DBTYPE_DOUBLE
- Case "float"
- dbType = DBTYPE_FLOAT
- Case "date"
- dbType = DBTYPE_DATE
- Case "timestamp", "datetime"
- dbType = DBTYPE_DATETIME
- Case "time"
- dbType = DBTYPE_TIME
- Case "tinyblob", "blob", "mediumblob", "longblob"
- dbType = DBTYPE_BLOB
- Default
- dbType = DBTYPE_STRING
- End Select
-
- Local nullable:Int
- If rec.GetString(2) = "YES" Then
- nullable = True
- End If
-
- Local defaultValue:TDBType = rec.value(4)
-
- cols.AddLast(TDBColumn.Create(name, dbType, nullable, defaultValue))
- Next
-
- table.SetCountColumns(cols.count())
- Local i:Int
- For Local col:TDBColumn = EachIn cols
- table.SetColumn(i, col)
- i:+ 1
- Next
-
- cols.Clear()
-
- If withDDL Then
- sql = "SHOW CREATE TABLE " + tableName
- If query.execute(sql) Then
-
- For Local rec:TQueryRecord = EachIn query
- table.ddl:+ rec.GetString(1) + ";~n~n"
- Next
- End If
-
- End If
- Else
- ' no table?
- End If
-
- Return table
- End Method
-
- Method open:Int(user:String = Null, pass:String = Null)
- If _isOpen Then
- close()
- End If
-
- If user Then
- _user = user
- End If
-
- If pass Then
- _password = pass
- End If
-
- ' initialize the handle
- handle = mysql_init(0)
-
- If handle Then
-
- Local ret:Int = 0
-
- Local d:Byte Ptr = _dbname.ToUTF8String()
- If _host Then
- Local h:Byte Ptr = _host.ToUTF8String()
- If _user Then
- Local u:Byte Ptr = _user.ToUTF8String()
- If _password
- Local p:Byte Ptr = _password.ToUTF8String()
- ret = mysql_real_connect(handle, h, u, p, d, _port, Null, _options.ToInt())
- MemFree(p)
- Else
- ret = mysql_real_connect(handle, h, u, Null, d, _port, Null, _options.ToInt())
- End If
- MemFree(u)
- Else
- ret = mysql_real_connect(handle, h, Null, Null, d, _port, Null, _options.ToInt())
- End If
- MemFree(h)
- Else
- If _user Then
- Local u:Byte Ptr = _user.ToUTF8String()
- If _password
- Local p:Byte Ptr = _password.ToUTF8String()
- ret = mysql_real_connect(handle, Null, u, p, d, _port, Null, _options.ToInt())
- MemFree(p)
- Else
- ret = mysql_real_connect(handle, Null, u, Null, d, _port, Null, _options.ToInt())
- End If
- MemFree(u)
- Else
- ret = mysql_real_connect(handle, Null, Null, Null, d, _port, Null, _options.ToInt())
- End If
- End If
-
- If Not ret Then
- setError("Error connecting to database", String.FromUTF8String(mysql_error(handle)), TDatabaseError.ERROR_CONNECTION, mysql_errno(handle))
- Return False
- End If
-
- If mysql_select_db(handle, _dbname) Then
- setError("Error opening database '" + _dbname + "'", String.FromUTF8String(mysql_error(handle)), TDatabaseError.ERROR_CONNECTION, mysql_errno(handle))
- Return False
- End If
- Else
- setError("Error initializing database", Null, TDatabaseError.ERROR_CONNECTION, 0)
- Return False
- End If
-
- If clientVersion >= 50007 Then
- mysql_set_character_set(handle, "utf8")
- End If
-
- serverVersion = mysql_get_server_version(handle)
-
- _isOpen = True
- Return True
- End Method
-
- Method rollback:Int()
- If Not _isOpen Then
- Return False
- End If
-
- If mysql_query(handle, "ROLLBACK") Then
- setError("Error rolling back transaction", Null, TDatabaseError.ERROR_TRANSACTION, mysql_errno(handle))
- Return False
- End If
-
- Return True
- End Method
-
- Method startTransaction:Int()
- If Not _isOpen Then
- Return False
- End If
-
- If mysql_query(handle, "BEGIN WORK") Then
- setError("Error starting transaction", Null, TDatabaseError.ERROR_TRANSACTION, mysql_errno(handle))
- Return False
- End If
-
- Return True
- End Method
-
- Method databaseHandle:Byte Ptr()
- Return handle
- End Method
-
- Method createResultSet:TQueryResultSet()
- Return TMySQLResultSet.Create(Self)
- End Method
- Method nativeErrorMessage:String(err:Int)
- End Method
-
- Method hasPrepareSupport:Int()
- Return True
- End Method
- Method hasTransactionSupport:Int()
- Return True
- End Method
- End Type
- Type TMySQLField
- Field mySQLField:Byte Ptr
- Field dataValue:Byte Ptr
- Field dataLength:ULongInt
- Field isNull:Byte
- Field flag:Int
- Method clear()
- mySQLField = Null
- If dataValue Then
- MemFree(dataValue)
- dataValue = Null
- End If
- dataLength = 0
- isNull = 0
- End Method
-
- Method Delete()
- clear()
- End Method
-
- End Type
- Type TMySQLResultSet Extends TQueryResultSet
- ' a pointer to a mysql result
- Field resultHandle:Byte Ptr
- Field row:Byte Ptr
-
- ' a pointer to a mysql prepared statement
- Field stmtHandle:Byte Ptr
- Field metaHandle:Byte Ptr
-
- Field preparedQuery:Int
- Field _rowsAffected:Int
- Field parameterBindings:Byte Ptr
- Field selectBindings:Byte Ptr
-
- Field mySQLFields:TMySQLField[]
- Function Create:TQueryResultSet(db:TDBConnection, sql:String = Null)
- Local this:TMySQLResultSet = New TMySQLResultSet
-
- this.init(db, sql)
- this.rec = TQueryRecord.Create()
-
- Return this
- End Function
- Method executeQuery:Int(statement:String)
-
- If Not conn.isOpen() Then
- Return False
- End If
-
- preparedQuery = False
-
- Local q:Byte Ptr = statement.ToUTF8String()
- Local query:Int = mysql_real_query(conn.handle, q, _strlen(q)) Then
- MemFree(q)
-
- If query
- conn.setError("Error executing query", String.FromUTF8String(mysql_error(conn.handle)), TDatabaseError.ERROR_STATEMENT, mysql_errno(conn.handle))
- Return False
- End If
-
- resultHandle = mysql_store_result(conn.handle)
-
- If Not resultHandle And mysql_field_count(conn.handle) > 0 Then
- conn.setError("Error storing result set", String.FromUTF8String(mysql_error(conn.handle)), TDatabaseError.ERROR_STATEMENT, mysql_errno(conn.handle))
- Return False
- End If
-
- Local fieldCount:Int = mysql_field_count(conn.handle)
- initRecord(fieldCount)
- Local af:Long
- bmx_mysql_affected_rows(conn.handle, Varptr af)
- _rowsAffected = af
-
- If fieldCount <> 0 Then
-
- For Local i:Int = 0 Until fieldCount
- Local _field:Byte Ptr = mysql_fetch_field_direct(resultHandle, i)
-
- Local qf:TQueryField = TQueryField.Create(bmx_mysql_field_name(_field), dbTypeFromNative(Null, bmx_mysql_field_type(_field), bmx_mysql_field_flags(_field)))
- qf.length = bmx_mysql_field_length(_field)
- qf.precision = bmx_mysql_field_decimals(_field)
-
- rec.setField(i, qf)
-
- Next
- End If
-
- _isActive = True
- Return True
- End Method
-
- Method prepare:Int(statement:String)
-
- cleanup()
-
- If Not statement Or statement.length = 0 Then
- Return False
- End If
-
- ' initialize the statement if required
- If Not stmtHandle Then
- stmtHandle = mysql_stmt_init(conn.handle)
- End If
-
- If Not stmtHandle Then
- conn.setError("Error preparing statement", String.FromUTF8String(mysql_error(conn.handle)), TDatabaseError.ERROR_STATEMENT, mysql_errno(conn.handle))
- Return False
- End If
-
- ' prepare the statement
- Local q:Byte Ptr = statement.ToUTF8String()
- Local result:Int = mysql_stmt_prepare(stmtHandle, q, _strlen(q))
- MemFree(q)
-
- If result Then
- conn.setError("Error preparing statement", String.FromUTF8String(mysql_stmt_error(stmtHandle)), TDatabaseError.ERROR_STATEMENT, mysql_errno(stmtHandle))
- cleanup()
- Return False
- End If
-
- ' if the param count > 0 there are "?" in the SQL that need to be bound
- If mysql_stmt_param_count(stmtHandle) > 0 Then
- parameterBindings = bmx_mysql_makeBindings(mysql_stmt_param_count(stmtHandle))
- End If
-
- ' **********************************
- ' setup bindings for inbound data...
- If Not metaHandle Then
- metaHandle = mysql_stmt_result_metadata(stmtHandle)
- End If
-
- If metaHandle Then
- Local fieldCount:Int = mysql_num_fields(metaHandle)
- initRecord(fieldCount)
- mySQLFields = New TMySQLField[fieldCount]
-
- selectBindings = bmx_mysql_makeBindings(fieldCount)
-
- For Local i:Int = 0 Until fieldCount
-
- Local _field:Byte Ptr = mysql_fetch_field(metaHandle)
- mySQLFields[i] = New TMySQLField
-
- mySQLFields[i].mySQLField = _field
- mySQLFields[i].dataLength = bmx_mysql_field_length(_field) + 1
- ' make some space for the data...
- Local size:Size_T = bmx_mysql_length_for_field(_field)
- mySQLFields[i].dataValue = MemAlloc(size)
-
- Local ty:Int = bmx_mysql_field_type(_field)
- ' build result set field information
- Local qf:TQueryField = TQueryField.Create(bmx_mysql_field_name(_field), dbTypeFromNative(Null, ty, bmx_mysql_field_flags(_field)))
- qf.length = bmx_mysql_field_length(_field)
- qf.precision = bmx_mysql_field_decimals(_field)
- rec.setField(i, qf)
- bmx_mysql_inbind(selectBindings, i, _field, mySQLFields[i].dataValue, Varptr mySQLFields[i].dataLength, Varptr mySQLFields[i].isNull, ty)
- Next
- End If
-
- Return True
- End Method
-
- Method execute:Int()
- If Not preparedQuery Then
- Return False
- End If
-
- If Not stmtHandle Then
- Return False
- End If
-
- index = SQL_BeforeFirstRow
-
- Local result:Int = 0
-
- result = bmx_mysql_stmt_reset(stmtHandle)
- If result Then
- conn.setError("Error resetting statement", String.FromUTF8String(mysql_stmt_error(stmtHandle)), TDatabaseError.ERROR_STATEMENT, mysql_errno(stmtHandle))
- Return False
- End If
- ' BIND stuff
- Local values:TDBType[] = boundValues
- Local paramCount:Int = mysql_stmt_param_count(stmtHandle)
- Local strings:Byte Ptr[]
- Local times:Byte Ptr[]
- Local nulls:Byte[]
- If paramCount = bindCount Then
- strings = New Byte Ptr[paramCount]
- times = New Byte Ptr[paramCount]
- nulls = New Byte[paramCount]
-
- For Local i:Int = 0 Until paramCount
- Local isNull:Int = False
- Local nullsPtr:Byte Ptr
- If Not values[i] Or values[i].isNull() Then
- isNull = True
- nulls[i] = 1
- nullsPtr = Byte Ptr(nulls) + i
- End If
- Select values[i].kind()
- Case DBTYPE_INT
- bmx_mysql_bind_int(parameterBindings, i, Varptr TDBInt(values[i]).value, nullsPtr)
- Case DBTYPE_FLOAT
- bmx_mysql_bind_float(parameterBindings, i, Varptr TDBFloat(values[i]).value, nullsPtr)
- Case DBTYPE_DOUBLE
- bmx_mysql_bind_double(parameterBindings, i, Varptr TDBDouble(values[i]).value, nullsPtr)
- Case DBTYPE_LONG
- bmx_mysql_bind_long(parameterBindings, i, Varptr TDBLong(values[i]).value, nullsPtr)
- Case DBTYPE_STRING
- local s:Byte Ptr = values[i].getString().ToUTF8String()
- strings[i] = s
- bmx_mysql_bind_string(parameterBindings, i, s, _strlen(s), nullsPtr)
-
- Case DBTYPE_BLOB
- bmx_mysql_bind_blob(parameterBindings, i, TDBBlob(values[i]).value, TDBBlob(values[i])._size, nullsPtr)
- Case DBTYPE_DATE
- Local date:TDBDate = TDBDate(values[i])
- times[i] = bmx_mysql_makeTime()
- bmx_mysql_bind_date(parameterBindings, i, times[i], date.getYear(), date.getMonth(), date.getDay(), nullsPtr)
- Case DBTYPE_DATETIME
- Local date:TDBDateTime = TDBDateTime(values[i])
- times[i] = bmx_mysql_makeTime()
- bmx_mysql_bind_datetime(parameterBindings, i, times[i], date.getYear(), date.getMonth(), date.getDay(), date.getHour(), date.getMinute(), date.getSecond(), nullsPtr)
- Case DBTYPE_TIME
- Local date:TDBTime = TDBTime(values[i])
- times[i] = bmx_mysql_makeTime()
- bmx_mysql_bind_time(parameterBindings, i, times[i], date.getHour(), date.getMinute(), date.getSecond(), nullsPtr)
- End Select
- Next
- ' actually bind the parameters
- result = bmx_mysql_stmt_bind_param(stmtHandle, parameterBindings)
- If result Then
- conn.setError("Error binding values", String.FromUTF8String(mysql_stmt_error(stmtHandle)), TDatabaseError.ERROR_STATEMENT, mysql_errno(stmtHandle))
-
- ' free up the strings
- For Local i:Int = 0 Until paramCount
- If strings[i] Then
- MemFree(strings[i])
- End If
-
- If times[i] Then
- bmx_mysql_deleteTime(times[i])
- End If
- Next
-
- Return False
- End If
-
- End If
-
- ' execute the statement
- result = mysql_stmt_execute(stmtHandle)
- ' free up the strings
- If strings Or times Then
- For Local i:Int = 0 Until paramCount
- If strings[i] Then
- MemFree(strings[i])
- End If
-
- If times[i] Then
- bmx_mysql_deleteTime(times[i])
- End If
- Next
- End If
-
- If result Then
- conn.setError("Error executing statement", String.FromUTF8String(mysql_stmt_error(stmtHandle)), TDatabaseError.ERROR_STATEMENT, mysql_errno(stmtHandle))
- Return False
- End If
-
- Local af:Long
- bmx_mysql_stmt_affected_rows(stmtHandle, Varptr af)
- _rowsAffected = af
- ' if this is set, then there is data returned from the statement execution
- ' in which case we need to bind the results for the result set
- If metaHandle Then
- result = bmx_mysql_stmt_bind_result(stmtHandle, selectBindings)
- If result Then
- conn.setError("Error binding result", String.FromUTF8String(mysql_stmt_error(stmtHandle)), TDatabaseError.ERROR_STATEMENT, mysql_errno(stmtHandle))
- Return False
- End If
- result = mysql_stmt_store_result(stmtHandle)
- If result Then
- conn.setError("Error storing result", String.FromUTF8String(mysql_stmt_error(stmtHandle)), TDatabaseError.ERROR_STATEMENT, mysql_errno(stmtHandle))
- Return False
- End If
-
- End If
- _isActive = True
- Return True
- End Method
- Method initRecord(size:Int)
- rec.clear()
- If size > 0 Then
- rec.init(size)
- End If
-
- resetValues(size)
- End Method
-
- Method firstRow:Int()
- If index = SQL_BeforeFirstRow Then
- Return nextRow()
- End If
-
- Return False
- End Method
-
- Method nextRow:Int()
- If preparedQuery Then
- If Not stmtHandle Then
- Return False
- End If
-
- Local result:Int = bmx_mysql_stmt_fetch(stmtHandle)
- If result Then
- Return False
- End If
- Else
- row = mysql_fetch_row(resultHandle)
- If Not row Then
- Return False
- End If
- End If
-
- ' now populate the values[] array with the fetched data !
- For Local i:Int = 0 Until rec.count()
-
- If values[i] Then
- values[i].clear()
- End If
-
- If preparedQuery Then
-
- If Not mySQLFields[i].isNull Then
-
- Local fieldLength:Int = mySQLFields[i].dataLength
- ' it seems that we need to retrieve all values as if they were "strings"...
- ' Don't ask... it doesn't work otherwise. (except on Windows... haw)
- Select rec.fields[i].fType
- Case DBTYPE_INT
- values[i] = New TDBInt
- values[i].setInt(bmx_mysql_char_to_int(mySQLFields[i].dataValue))
- Case DBTYPE_LONG
- values[i] = New TDBLong
- values[i].setLong(bmx_mysql_char_to_long(mySQLFields[i].dataValue))
- Case DBTYPE_FLOAT
- values[i] = New TDBFloat
- values[i].setFloat(bmx_mysql_char_to_float(mySQLFields[i].dataValue))
- Case DBTYPE_DOUBLE
- values[i] = New TDBDouble
- values[i].setDouble(bmx_mysql_char_to_double(mySQLFields[i].dataValue))
- Case DBTYPE_DATE
- values[i] = bmx_mysql_char_to_date(mySQLFields[i].dataValue)
- Case DBTYPE_DATETIME
- values[i] = bmx_mysql_char_to_datetime(mySQLFields[i].dataValue)
- Case DBTYPE_TIME
- values[i] = bmx_mysql_char_to_time(mySQLFields[i].dataValue)
- Case DBTYPE_BLOB
- values[i] = TDBBlob.Set(mySQLFields[i].dataValue, fieldLength)
- Default
- values[i] = New TDBString
- values[i].setString(sizedUTF8toISO8859(mySQLFields[i].dataValue, fieldLength))
- End Select
-
- End If
-
- Else
- ' a non-prepared query
- If Not bmx_mysql_rowField_isNull(row, i) Then
-
- Local fieldLength:Int = Int(mysql_fetch_lengths(resultHandle)[i])
-
- Select rec.fields[i].fType
- Case DBTYPE_INT
- values[i] = New TDBInt
- values[i].setInt(String.fromBytes(bmx_mysql_rowField_chars(row, i), fieldLength).toInt())
- Case DBTYPE_LONG
- values[i] = New TDBLong
- values[i].setLong(String.fromBytes(bmx_mysql_rowField_chars(row, i), fieldLength).toLong())
- Case DBTYPE_FLOAT
- values[i] = New TDBFloat
- values[i].setFloat(String.fromBytes(bmx_mysql_rowField_chars(row, i), fieldLength).toFloat())
- Case DBTYPE_DOUBLE
- values[i] = New TDBDouble
- values[i].setDouble(String.fromBytes(bmx_mysql_rowField_chars(row, i), fieldLength).toDouble())
- Case DBTYPE_DATE
- values[i] = TDBDate.SetFromString(String.FromUTF8Bytes(bmx_mysql_rowField_chars(row, i), fieldLength))
- Case DBTYPE_DATETIME
- values[i] = TDBDateTime.SetFromString(String.FromUTF8Bytes(bmx_mysql_rowField_chars(row, i), fieldLength))
- Case DBTYPE_TIME
- values[i] = TDBTime.SetFromString(String.FromUTF8Bytes(bmx_mysql_rowField_chars(row, i), fieldLength))
- Case DBTYPE_BLOB
- values[i] = TDBBlob.Set(bmx_mysql_rowField_chars(row, i), fieldLength)
- Default
- values[i] = New TDBString
- values[i].setString(String.FromUTF8Bytes(bmx_mysql_rowField_chars(row, i), fieldLength))
- End Select
-
- End If
-
- End If
- Next
-
-
- index:+ 1
-
- Return True
- End Method
-
- Method lastInsertedId:Long()
- If Not isActive()
- Return -1
- End If
-
- Local id:Long = -1
-
- If preparedQuery Then
- bmx_mysql_stmt_insert_id(stmtHandle, Varptr id)
- Else
- bmx_mysql_insert_id(conn.handle, Varptr id)
- End If
-
- Return id
- End Method
-
- Method rowsAffected:Int()
- Return _rowsAffected
- End Method
- Function dbTypeFromNative:Int(name:String, _type:Int = 0, _flags:Int = 0)
-
- Local dbType:Int
-
- Select _type
- Case MYSQL_TYPE_TINY, MYSQL_TYPE_SHORT, MYSQL_TYPE_LONG, MYSQL_TYPE_INT24
- dbType = DBTYPE_INT
- Case MYSQL_TYPE_YEAR
- dbType = DBTYPE_INT
- Case MYSQL_TYPE_LONGLONG
- dbType = DBTYPE_LONG
- Case MYSQL_TYPE_FLOAT
- dbType = DBTYPE_FLOAT
- Case MYSQL_TYPE_DOUBLE, MYSQL_TYPE_DECIMAL
- dbType = DBTYPE_DOUBLE
- Case MYSQL_TYPE_DATE
- dbType = DBTYPE_DATE
- Case MYSQL_TYPE_TIME
- dbType = DBTYPE_TIME
- Case MYSQL_TYPE_DATETIME, MYSQL_TYPE_TIMESTAMP
- dbType = DBTYPE_DATETIME
- Case MYSQL_TYPE_BLOB, MYSQL_TYPE_TINY_BLOB, MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB
- If _flags & 128 Then ' binary !
- dbType = DBTYPE_BLOB
- Else ' String!
- dbType = DBTYPE_STRING
- End If
- Default
- dbType = DBTYPE_STRING
- End Select
-
- Return dbType
- End Function
- Method cleanup()
- If resultHandle Then
- mysql_free_result(resultHandle)
- resultHandle = Null
- End If
-
- If metaHandle Then
- mysql_free_result(metaHandle)
- metaHandle = Null
- End If
-
- If stmtHandle Then
- If bmx_mysql_stmt_close(stmtHandle) Then
- '
- End If
- stmtHandle = Null
- End If
-
- If parameterBindings Then
- bmx_mysql_deleteBindings(parameterBindings)
- parameterBindings = Null
- End If
- If selectBindings Then
- bmx_mysql_deleteBindings(selectBindings)
- selectBindings = Null
- End If
-
- If mySQLFields Then
- For Local i:Int = 0 Until mySQLFields.length
- If mySQLFields[i] Then
- mySQLFields[i].clear()
- mySQLFields[i] = Null
- End If
- Next
- End If
-
- index = SQL_BeforeFirstRow
- rec.clear()
- _isActive = False
-
- preparedQuery = True
- End Method
-
- Method clear()
- cleanup()
-
- Super.clear()
- End Method
-
- Method reset()
- clear()
- End Method
-
- Method free()
- clear()
- End Method
-
- Method Delete()
- free()
- End Method
-
- End Type
- Type TMariaDBDatabaseLoader Extends TDatabaseLoader
- Method New()
- _type = "MARIADB"
- End Method
- Method LoadDatabase:TDBConnection( dbname:String = Null, host:String = Null, ..
- port:Int = Null, user:String = Null, password:String = Null, ..
- server:String = Null, options:String = Null )
-
- Return TDBMariaDB.Create(dbName, host, port, user, password, server, options)
-
- End Method
- End Type
- AddDatabaseLoader New TMariaDBDatabaseLoader
|