Changeset 81
- Timestamp:
- 01/30/08 10:46:52 (10 months ago)
- Files:
-
- trunk/dbi/DBIException.d (modified) (1 diff)
- trunk/dbi/Database.d (modified) (2 diffs)
- trunk/dbi/Metadata.d (added)
- trunk/dbi/PreparedStatement.d (modified) (2 diffs)
- trunk/dbi/Row.d (modified) (3 diffs)
- trunk/dbi/Statement.d (modified) (2 diffs)
- trunk/dbi/mysql/MysqlDatabase.d (modified) (4 diffs)
- trunk/dbi/mysql/MysqlPreparedStatement.d (modified) (18 diffs)
- trunk/dbi/mysql/MysqlResult.d (modified) (1 diff)
- trunk/dbi/mysql/imp.d (modified) (1 diff)
- trunk/dbi/mysql/imp_win.d (added)
- trunk/dbi/sqlite/SqliteDatabase.d (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/dbi/DBIException.d
r76 r81 1 /**1 /** 2 2 * Authors: The D DBI project 3 3 * Copyright: BSD license trunk/dbi/Database.d
r76 r81 216 216 } 217 217 218 debug(UnitTest) { 219 218 220 unittest { 219 221 void s1 (char[] s) { … … 233 235 assert (keywords["host"] == "local"); 234 236 } 237 } trunk/dbi/PreparedStatement.d
r74 r81 1 1 module dbi.PreparedStatement; 2 2 3 version (Phobos) { 4 static assert(false, "Phobos version of prepared statements not implemented yet"); 5 } else { 6 public import tango.util.time.DateTime; 7 } 3 public import tango.group.time; 8 4 9 enum BindType { Null, Bool, Byte, Short, Int, Long, UByte, UShort, UInt, ULong, Float, Double, String, Binary,Time };5 enum BindType : ubyte { Null, Bool, Byte, Short, Int, Long, UByte, UShort, UInt, ULong, Float, Double, String, Binary, Time, DateTime }; 10 6 11 7 interface IPreparedStatementProvider 12 8 { 13 IPreparedStatement prepare(string sql); 9 IPreparedStatement prepare(char[] sql); 10 void beginTransact(); 11 void rollback(); 12 void commit(); 14 13 } 15 14 … … 34 33 BindType type; 35 34 } 35 36 BindType getBindType(T)() 37 { 38 static if(is(T == byte)) 39 { 40 return BindType.Byte; 41 } 42 else static if(is(T == ubyte)) 43 { 44 return BindType.UByte; 45 } 46 else static if(is(T == short)) 47 { 48 return BindType.Short; 49 } 50 else static if(is(T == ushort)) 51 { 52 return BindType.UShort; 53 } 54 else static if(is(T == int)) 55 { 56 return BindType.Int; 57 } 58 else static if(is(T == uint)) 59 { 60 return BindType.UInt; 61 } 62 else static if(is(T == long)) 63 { 64 return BindType.Long; 65 } 66 else static if(is(T == ulong)) 67 { 68 return BindType.ULong; 69 } 70 else static if (is(T == float)) 71 { 72 return BindType.Float; 73 } 74 else static if (is(T == double)) 75 { 76 return BindType.Double; 77 } 78 else static if (is(T == char[])) 79 { 80 return BindType.String; 81 } 82 else static if (is(T == ubyte[]) || is(T == void[])) 83 { 84 return BindType.Binary; 85 } 86 else static if (is(T == Time)) 87 { 88 return BindType.Time; 89 } 90 else static if (is(T == DateTime)) 91 { 92 return BindType.DateTime; 93 } 94 else return BindType.Null; 95 } trunk/dbi/Row.d
r77 r81 5 5 module dbi.Row; 6 6 7 private static import tango.io.Stdout;8 7 private import dbi.DBIException; 9 8 … … 183 182 } 184 183 184 debug(UnitTest) { 185 static import tango.io.Stdout; 186 185 187 unittest { 186 version (Phobos) { 187 void s1 (char[] s) { 188 std.stdio.writefln("%s", s); 189 } 190 191 void s2 (char[] s) { 192 std.stdio.writefln(" ...%s", s); 193 } 194 } else { 195 void s1 (char[] s) { 196 tango.io.Stdout.Stdout(s).newline(); 197 } 198 199 void s2 (char[] s) { 200 tango.io.Stdout.Stdout(" ..." ~ s).newline(); 201 } 188 189 void s1 (char[] s) { 190 tango.io.Stdout.Stdout(s).newline(); 191 } 192 193 void s2 (char[] s) { 194 tango.io.Stdout.Stdout(" ..." ~ s).newline(); 202 195 } 203 196 … … 228 221 assert (r1.getFieldDecl(1) == "integer"); 229 222 } 223 } trunk/dbi/Statement.d
r70 r81 232 232 } 233 233 234 debug(UnitTest) { 234 235 unittest { 235 236 version (Phobos) { … … 281 282 assert (stmt.getSql() == resultingSql); 282 283 } 284 } trunk/dbi/mysql/MysqlDatabase.d
r79 r81 1 /**1 /** 2 2 * Authors: The D DBI project 3 3 * Copyright: BSD license … … 8 8 9 9 private import tango.stdc.stringz : toDString = fromUtf8z, toCString = toStringz; 10 private import tango.io.Console;10 private import tango.io.Console; 11 11 private static import tango.text.Util; 12 12 private static import tango.text.convert.Integer; 13 debug (UnitTest) private staticimport tango.io.Stdout;13 debug(UnitTest) import tango.io.Stdout; 14 14 15 15 private import dbi.Database, dbi.DBIException, dbi.Result, dbi.Row, dbi.Statement, dbi.Registry; 16 private import dbi.mysql.imp, dbi.mysql.MysqlError, dbi.mysql.MysqlResult; 16 version(Windows) { 17 private import dbi.mysql.imp_win; 18 } 19 else { 20 private import dbi.mysql.imp; 21 } 22 private import dbi.mysql.MysqlError, dbi.mysql.MysqlResult; 17 23 18 24 static this() { … … 251 257 } 252 258 259 debug(UnitTest) { 253 260 unittest { 254 261 … … 307 314 db.close();+/ 308 315 } 309 310 } 316 } 317 318 } trunk/dbi/mysql/MysqlPreparedStatement.d
r74 r81 3 3 version(dbi_mysql) { 4 4 5 version (Phobos) { 6 private static import std.conv, std.string; 7 private alias std.string.toString toDString; 8 private alias std.string.toStringz toCString; 9 debug (UnitTest) private static import std.stdio; 10 } else { 11 private import tango.stdc.string; 12 private import tango.stdc.stringz : toDString = fromUtf8z, toCString = toUtf8z; 13 private import tango.io.Console; 14 private static import tango.text.Util; 15 private import Integer = tango.text.convert.Integer; 16 debug(UnitTest) { 17 import tango.stdc.stringz; 18 import tango.io.Stdout; 19 import tango.util.log.ConsoleAppender; 20 } 5 import tango.stdc.string; 6 import tango.stdc.stringz : toDString = fromUtf8z, toCString = toStringz; 7 static import tango.text.Util; 8 import Integer = tango.text.convert.Integer; 9 debug(UnitTest) { 10 import tango.stdc.stringz; 11 import tango.io.Stdout; 12 debug = Log; 21 13 } 22 14 debug(Log) { 15 import tango.util.log.ConsoleAppender; 23 16 import tango.util.log.Log; 24 17 } 25 18 26 19 import dbi.mysql.MysqlDatabase; 27 import dbi.mysql.imp; 28 import dbi.PreparedStatement; 20 version(Windows) { 21 private import dbi.mysql.imp_win; 22 } 23 else { 24 private import dbi.mysql.imp; 25 } 26 public import dbi.PreparedStatement, dbi.Metadata; 29 27 30 class MysqlPreparedStatementProvider : IPreparedStatementProvider 31 { 32 debug(Log) 33 { 34 static Logger log; 35 static this() 36 { 37 log = Log.getLogger("dbi.mysql.MysqlPreparedStatement.MysqlPreparedStatementProvider"); 38 } 39 } 40 28 class MysqlPreparedStatementProvider : IPreparedStatementProvider, IMetadataProvider 29 { 41 30 this(MysqlDatabase db) 42 31 { … … 47 36 private MYSQL* mysql; 48 37 49 IPreparedStatement prepare( stringsql)38 IPreparedStatement prepare(char[] sql) 50 39 { 51 40 MYSQL_STMT* stmt = mysql_stmt_init(mysql); … … 60 49 return new MysqlPreparedStatement(stmt); 61 50 } 51 52 void beginTransact() 53 { 54 const char[] sql = "START TRANSACTION"; 55 mysql_real_query(mysql, sql.ptr, sql.length); 56 } 57 58 void rollback() 59 { 60 mysql_rollback(mysql); 61 } 62 63 void commit() 64 { 65 mysql_commit(mysql); 66 } 67 68 bool hasTable(char[] tablename) 69 { 70 MYSQL_RES* res = mysql_list_tables(mysql, toCString(tablename)); 71 if(!res) { 72 debug(Log) { 73 log.warn("mysql_list_tables returned null in method tableExists()"); 74 logError; 75 } 76 return false; 77 } 78 bool exists = mysql_fetch_row(res) ? true : false; 79 mysql_free_result(res); 80 return exists; 81 } 82 83 bool getTableInfo(char[] tablename, inout TableInfo info) 84 { 85 char[] q = "SHOW COLUMNS FROM `" ~ tablename ~ "`"; 86 auto ret = mysql_real_query(mysql, q.ptr, q.length); 87 if(ret != 0) { 88 debug(Log) { 89 log.warn("Unable to SHOW COLUMNS for table " ~ tablename); 90 logError; 91 } 92 return false; 93 } 94 MYSQL_RES* res = mysql_store_result(mysql); 95 if(!res) { 96 debug(Log) { 97 log.warn("Unable to store result for " ~ q); 98 logError; 99 } 100 return false; 101 } 102 if(mysql_num_fields(res) < 1) { 103 debug(Log) 104 log.warn("Result stored, but query " ~ q ~ " has no fields"); 105 return false; 106 } 107 info.fieldNames = null; 108 MYSQL_ROW row = mysql_fetch_row(res); 109 while(row != null) { 110 char[] dbCol = toDString(row[0]).dup; 111 info.fieldNames ~= dbCol; 112 char[] keyCol = toDString(row[3]); 113 if(keyCol == "PRI") info.primaryKeyFields ~= dbCol; 114 row = mysql_fetch_row(res); 115 } 116 mysql_free_result(res); 117 return true; 118 } 119 120 debug(Log) 121 { 122 static Logger log; 123 static this() 124 { 125 log = Log.getLogger("dbi.mysql.MysqlPreparedStatement.MysqlPreparedStatementProvider"); 126 } 127 128 private void logError() 129 { 130 char* err = mysql_error(mysql); 131 log.trace(toDString(err)); 132 } 133 } 62 134 } 63 135 … … 83 155 for(uint i = 0; i < nFields; i++) 84 156 { 85 metadata[i].name = fields[i].name[0 .. fields[i].name_length] ;157 metadata[i].name = fields[i].name[0 .. fields[i].name_length].dup; 86 158 metadata[i].type = fromMysqlType(fields[i].type, fields[i].flags); 87 159 } … … 113 185 for(uint i = 0; i < len; ++i) 114 186 { 115 with(enum_field_types) 116 { 117 switch(paramBind[i].buffer_type) 118 { 119 case(MYSQL_TYPE_STRING): 120 case(MYSQL_TYPE_BLOB): 187 switch(paramHelper.types[i]) 188 { 189 case(BindType.String): 190 case(BindType.Binary): 121 191 ubyte[]* arr = cast(ubyte[]*)(bind[i]); 122 192 paramBind[i].buffer = (*arr).ptr; … … 125 195 paramHelper.len[i] = l; 126 196 break; 127 /* case(BindType.Date): 128 auto date = *cast(Date*)(paramPtr + paramCols[i].offset); 129 paramHelper.time[i].year = date.year; 130 paramHelper.time[i].month = date.month; 131 paramHelper.time[i].day = date.day; 132 paramHelper.time[i].hour = date.hour; 133 paramHelper.time[i].minute = date.min; 134 paramHelper.time[i].second = date.sec; 135 break;*/ 136 case(MYSQL_TYPE_DATETIME): 197 case(BindType.Time): 198 auto time = *cast(Time*)(bind[i]); 199 auto dateTime = Clock.toDate(time); 200 paramHelper.time[i].year = dateTime.date.year; 201 paramHelper.time[i].month = dateTime.date.month; 202 paramHelper.time[i].day = dateTime.date.day; 203 paramHelper.time[i].hour = dateTime.time.hours; 204 paramHelper.time[i].minute = dateTime.time.minutes; 205 paramHelper.time[i].second = dateTime.time.seconds; 206 break; 207 case(BindType.DateTime): 137 208 auto dateTime = *cast(DateTime*)(bind[i]); 138 paramHelper.time[i].year = dateTime. year;139 paramHelper.time[i].month = dateTime. month;140 paramHelper.time[i].day = dateTime.da y;141 paramHelper.time[i].hour = dateTime. hour;142 paramHelper.time[i].minute = dateTime. minute;143 paramHelper.time[i].second = dateTime. second;209 paramHelper.time[i].year = dateTime.date.year; 210 paramHelper.time[i].month = dateTime.date.month; 211 paramHelper.time[i].day = dateTime.date.day; 212 paramHelper.time[i].hour = dateTime.time.hours; 213 paramHelper.time[i].minute = dateTime.time.minutes; 214 paramHelper.time[i].second = dateTime.time.seconds; 144 215 break; 145 216 default: 146 217 paramBind[i].buffer = bind[i]; 147 218 break; 148 }149 219 } 150 220 } … … 214 284 foreach(i, mysqlTime; resHelper.time) 215 285 { 216 DateTime* dateTime = cast(DateTime*)(bind[i]); 217 *dateTime = DateTime(mysqlTime.year, mysqlTime.month, mysqlTime.day); 218 (*dateTime).addHours(mysqlTime.hour); 219 (*dateTime).addMinutes(mysqlTime.minute); 220 (*dateTime).addSeconds(mysqlTime.second); 221 } 222 223 /* case Type.Date: 224 Date* date = cast(Date*)(bind[i]); 225 (*date).year = resHelper.time[i].year; 226 (*date).month = resHelper.time[i].month; 227 (*date).day = resHelper.time[i].day; 228 (*date).hour = resHelper.time[i].hour; 229 (*date).min = resHelper.time[i].minute; 230 (*date).sec = resHelper.time[i].second; 231 break;*/ 286 if(resHelper.types[i] == BindType.Time) { 287 Time* time = cast(Time*)(bind[i]); 288 DateTime dt; 289 dt.date.year = mysqlTime.year; 290 dt.date.month = mysqlTime.month; 291 dt.date.day = mysqlTime.day; 292 dt.time.hours = mysqlTime.hour; 293 dt.time.minutes = mysqlTime.minute; 294 dt.time.seconds = mysqlTime.second; 295 *time = Clock.fromDate(dt); 296 } 297 else if(resHelper.types[i] == BindType.DateTime) { 298 DateTime* dt = cast(DateTime*)(bind[i]); 299 (*dt).date.year = mysqlTime.year; 300 (*dt).date.month = mysqlTime.month; 301 (*dt).date.day = mysqlTime.day; 302 (*dt).time.hours = mysqlTime.hour; 303 (*dt).time.minutes = mysqlTime.minute; 304 (*dt).time.seconds = mysqlTime.second; 305 } 306 } 307 232 308 if(res == 0) { 233 /+for(uint i = 0; i < resBind.length; ++i)234 {235 if(resBind[i].buffer_type != enum_field_types.MYSQL_TYPE_STRING ||236 resBind[i].buffer_type != enum_field_types.MYSQL_TYPE_BLOB)237 {238 ubyte[]* arr = cast(ubyte[]*)(bind[i]);239 //(*arr) = (*arr)[0 .. resHelper.len[i]];240 uint l = resHelper.len[i];241 *arr = resHelper.buffer[i][0 .. l];242 }243 244 }+/245 309 foreach(i, buf; resHelper.buffer) 246 310 { … … 272 336 *arr = buf[0 .. l]; 273 337 } 274 /+ for(uint i = 0; i < resBind.length; ++i)275 {276 if(*(resBind[i].error))277 {278 if(resBind[i].buffer_type != enum_field_types.MYSQL_TYPE_STRING ||279 resBind[i].buffer_type != enum_field_types.MYSQL_TYPE_BLOB)280 {281 debug(Log) {282 log.error("Error in column that is not String of Binary type");283 logError;284 }285 return false;286 }287 288 289 ubyte[]* arr = cast(ubyte[]*)(bind[i]);290 if(!arr) {291 debug(Log) {292 log.error("Error retrieving String of Binary in bind parameters");293 logError;294 }295 return false;296 }297 //(*arr).length = *(resBind[i].length);298 //resBind[i].buffer_length = *(resBind[i].length);299 uint l = resHelper.len[i];300 resHelper.buffer[i].length = l;301 resBind[i].buffer_length = l;302 resBind[i].buffer = resHelper.buffer[i].ptr;303 if(mysql_stmt_fetch_column(stmt, &resBind[i], i, 0) != 0) {304 debug(Log) {305 log.error("Error fetching String of Binary that failed due to truncation");306 logError;307 }308 return false;309 }310 }311 }+/312 338 return true; 313 339 } … … 324 350 { 325 351 mysql_stmt_free_result(stmt); 326 //mysql_stmt_reset(stmt);327 352 } 328 353 … … 382 407 MYSQL_TIME[uint] time; 383 408 ubyte[][uint] buffer; 409 BindType[] types; 384 410 } 385 411 … … 411 437 case MYSQL_TYPE_TIME: 412 438 case MYSQL_TYPE_DATETIME: 413 return Time;439 return DateTime; 414 440 case MYSQL_TYPE_VAR_STRING: 415 441 case MYSQL_TYPE_STRING: … … 506 532 bind[i].is_unsigned = false; 507 533 break; 508 //case(BindType.Date):509 //case(BindType.DateTime):510 534 case(BindType.Time): 511 535 helper.time[i] = MYSQL_TIME(); … … 514 538 bind[i].is_unsigned = false; 515 539 break; 540 case(BindType.DateTime): 541 helper.time[i] = MYSQL_TIME(); 542 bind[i].buffer = &helper.time[i]; 543 bind[i].buffer_type = enum_field_types.MYSQL_TYPE_DATETIME; 544 bind[i].is_unsigned = false; 545 break; 546 case(BindType.Null): 547 bind[i].buffer_type = enum_field_types.MYSQL_TYPE_NULL; 548 break; 516 549 default: 517 assert(false, "Unhandled bind type"); //TODO more detailed information; 550 debug assert(false, "Unhandled bind type"); //TODO more detailed information; 551 bind[i].buffer_type = enum_field_types.MYSQL_TYPE_NULL; 552 break; 518 553 } 519 554 … … 522 557 bind[i].is_null = &helper.is_null[i]; 523 558 } 559 560 helper.types = types; 524 561 } 525 562 … … 539 576 } 540 577 } 578 debug(UnitTest) { 541 579 542 580 unittest … … 558 596 uint id; 559 597 char[] name; 560 DateTime dateofbirth;598 Time dateofbirth; 561 599 BindType[] resTypes; 562 600 resTypes ~= BindType.UInt; … … 571 609 assert(st.execute); 572 610 assert(st.fetch(bind)); 573 Stdout.formatln("id:{},name:{},dateofbirth:{}",id,name,dateofbirth. year);611 Stdout.formatln("id:{},name:{},dateofbirth:{}",id,name,dateofbirth.ticks); 574 612 assert(!st.fetch(bind)); 575 613 … … 585 623 assert(st2.execute(pBind)); 586 624 assert(st2.fetch(bind)); 587 Stdout.formatln("id:{},name:{},dateofbirth:{}",id,name,dateofbirth.year); 625 Stdout.formatln("id:{},name:{},dateofbirth:{}",id,name,dateofbirth.ticks); 626 st2.reset; 627 628 assert(provider.hasTable("test")); 629 TableInfo ti; 630 assert(provider.getTableInfo("test", ti)); 631 assert(ti.fieldNames.length == 3); 632 assert(ti.primaryKeyFields.length == 1); 633 foreach(f; ti.fieldNames) 634 { 635 Stdout.formatln("Field Name:{}", f); 636 } 637 638 foreach(f; ti.primaryKeyFields) 639 { 640 Stdout.formatln("Primary Key:{}", f); 641 } 642 643 db.close; 588 644 } 589 645 590 646 } 647 } trunk/dbi/mysql/MysqlResult.d
r70 r81 13 13 } 14 14 private import dbi.DBIException, dbi.Result, dbi.Row; 15 private import dbi.mysql.imp; 15 version(Windows) { 16 private import dbi.mysql.imp_win; 17 } 18 else { 19 private import dbi.mysql.imp; 20 } 16 21 17 22 /** trunk/dbi/mysql/imp.d
r74 r81 8 8 9 9 extern (C): 10 version (Windows) extern (Windows):11 10 12 11 version (Windows) { trunk/dbi/sqlite/SqliteDatabase.d
r70 r81 15 15 private import tango.util.log.Log; 16 16 } 17 private import dbi.Database, dbi.DBIException, dbi.Result, dbi.Row, dbi.Statement, dbi.Registry ;17 private import dbi.Database, dbi.DBIException, dbi.Result, dbi.Row, dbi.Statement, dbi.Registry, dbi.PreparedStatemt; 18 18 private import dbi.sqlite.imp, dbi.sqlite.SqliteError, dbi.sqlite.SqliteResult; 19 19 … … 272 272 return false; 273 273 } 274 275 IPreparedStatement createStatement(char[] statement) 276 { 277 sqlite3_stmt* stmt; 278 char* pzTail; 279 int res; 280 if((res = sqlite3_prepare_v2(database, toCString(statement), statement.length, &stmt, &pzTail)) != SQLITE_OK) { 281 char* errmsg = sqlite3_errmsg(db_); 282 logger.error("sqlite3_prepare_v2 for statement: \"" ~ statement ~ "\" returned: " ~ Integer.toUtf8(res) ~ ", errmsg: " ~ toDString(errmsg)); 283 return null; 284 } 285 return new SqlitePreparedStatement(stmt, database); 286 } 274 287 } 275 288 … … 289 302 logger.trace("creating Sqlite database: " ~ url); 290 303 return new SqliteDatabase(url); 304 } 305 } 306 307 class SqlitePreparedStatement : IPreparedStatement 308 { 309 static Logger logger; 310 static this() 311 { 312 logger = Log.getLogger("sendero.data.backends.Sqlite.SqlitePreparedStatement"); 313 } 314 315 private this(sqlite3_stmt* stmt, sqlite3* db) 316 { 317 this.stmt = stmt; 318 this.db = db; 319 } 320 321 ~this() 322 { 323 sqlite3_finalize(stmt); 324 } 325 326 327 private sqlite3_stmt* stmt; 328 package sqlite3* db; 329 private BindType[] paramTypes; 330 private BindType[] resTypes; 331 private bool row = false; 332 private bool wasReset = false; 333 334 int setParamTypes(BindType[] paramTypes) 335 { 336 this.paramTypes = paramTypes; 337 } 338 339 int setResultTypes(BindType[] resTypes) 340 { 341 this.resTypes = resTypes; 342 } 343 344 bool execute(StatementBinder binder) 345 { 346 uint i = 0; 347 foreach(p; paramTypes) 348 { 349 void* x; 350 size_t len; 351 binder(i, p, x, len); 352 switch(p) 353 { 354 case BindType.Bool: 355 if(sqlite3_bind_int(stmt, index + 1, *(cast(bool*)x)) != SQLITE_OK) return false; 356 break; 357 case BindType.Byte: 358 if(sqlite3_bind_int(stmt, index + 1, *(cast(byte*)x)) != SQLITE_OK) return false; 359 break; 360 case BindType.Short: 361 if(sqlite3_bind_int(stmt, index + 1, *(cast(short*)x)) != SQLITE_OK) return false; 362 break; 363 case BindType.Int: 364 if(sqlite3_bind_int(stmt, index + 1, *(cast(int*)x)) != SQLITE_OK) return false; 365 break; 366 case BindType.Long: 367 if(sqlite3_bind_int64(stmt, index + 1, *(cast(long*)x)) != SQLITE_OK) return false; 368 break; 369 case BindType.UByte: 370 if(sqlite3_bind_int(stmt, index + 1, *(cast(bool*)x)) != SQLITE_OK) return false; 371 break; 372 case BindType.UShort: 373 if(sqlite3_bind_int(stmt, index + 1, *(cast(ubyte*)x)) != SQLITE_OK) return false; 374 break; 375 case BindType.UInt: 376 if(sqlite3_bind_int64(stmt, index + 1, *(cast(uint*)x)) != SQLITE_OK) return false; 377 break; 378 case BindType.ULong: 379 if(sqlite3_bind_int64(stmt, index + 1, *(cast(ulong*)x)) != SQLITE_OK) return false; 380 break; 381 case BindType.Float: 382 if(sqlite3_bind_double(stmt, index + 1, *(cast(float*)x)) != SQLITE_OK) return false; 383 break; 384 case BindType.Double: 385 if(sqlite3_bind_double(stmt, index + 1, *(cast(double*)x)) != SQLITE_OK) return false; 386 break; 387 case BindType.String: 388 if(sqlite3_bind_text(stmt, index + 1, *cast(char**)x, len, null) != SQLITE_OK) return false; 389 break; 390 case BindType.UByteArray: 391 case BindType.VoidArray: 392 if(sqlite3_bind_blob(stmt, index + 1, *cast(void**)x, len, null) != SQLITE_OK) return false; 393 break; 394 case BindType.DateTime: 395 break; 396 case BindType.Date: 397 break; 398 case BindType.Time: 399 break; 400 default: 401 debug assert(false); 402 break; 403 } 404 ++i; 405 } 406 407 int ret = sqlite3_step(stmt); 408 wasReset = false; 409 switch(ret) 410 { 411 case SQLITE_ROW: 412 row = true; 413 return true; 414 case SQLITE_DONE: 415 row = false; 416 return true; 417 case SQLITE_BUSY: 418 default: 419 row = false; 420 return false; 421 } 422 } 423 424 bool fetch(StatementBinder binder) 425 { 426 if(!row) return false; 427 int ret = sqlite3_step(stmt); 428 wasReset = false; 429 430 uint index = 0; 431 foreach(r; resTypes) 432 { 433 void* x; 434 size_t len; 435 binder(index, r, x, len); 436 switch(p) 437 { 438 case BindType.Bool: 439 int z = sqlite3_column_int(stmt, index); 440 *cast(bool*)x = cast(bool)z; 441 break; 442 case BindType.Byte: 443 int z = sqlite3_column_int(stmt, index); 444 *cast(byte*)x = cast(byte)z; 445 break; 446 case BindType.Short: 447 int z = sqlite3_column_int(stmt, index); 448 *cast(short*)x = cast(short)z; 449 break; 450 case BindType.Int: 451 int z = sqlite3_column_int(stmt, index); 452 *cast(int*)x = z; 453 break; 454 case BindType.Long: 455 long z = sqlite3_column_int64(stmt, index); 456 *cast(long*)x = z; 457 break; 458 case BindType.UByte: 459 int z = sqlite3_column_int(stmt, index); 460 *cast(ubyte*)x = cast(ubyte)z; 461 break; 462 case BindType.UShort: 463 int z = sqlite3_column_int(stmt, index); 464 *cast(ushort*)x = cast(ushort)z; 465 break; 466 case BindType.UInt: 467 long z = sqlite3_column_int64(stmt, index); 468 *cast(uint*)x = cast(uint)z; 469 break; 470 case BindType.ULong: 471 long z = sqlite3_column_int64(stmt, index); 472 *cast(ulong*)x = cast(ulong)z; 473 break; 474 case BindType.Float: 475 double z = sqlite3_column_int(stmt, index); 476 *cast(float*)x = cast(float)z; 477 break; 478 case BindType.Double: 479 double z = sqlite3_column_int(stmt, index); 480 *cast(double*)x = z; 481 break; 482 case BindType.String: 483 char[] z = fromCStringz(sqlite3_column_text(stmt, index)); 484 *cast(char**)x = z.ptr; 485 len = z.length; 486 break; 487 case BindType.UByteArray: 488 case BindType.VoidArray: 489 void* res = sqlite3_column_blob(stmt, index); 490 len = sqlite3_column_bytes(stmt, index); 491 *cast(char**)x = len ? res[0 .. len] : null; 492 break; 493 case BindType.DateTime: 494 break; 495 case BindType.Date: 496 break; 497 case BindType.Time: 498 break; 499 default: 500 debug assert(false); 501 break; 502 } 503 ++i; 504 } 505 506 row = (ret == SQLITE_ROW); 507 return true; 508 } 509 510 void reset() 511 { 512 if(!wasReset) { 513 sqlite3_reset(stmt); 514 wasReset = true; 515 } 516 } 517 518 ulong getLastInsertID() 519 { 520 long id = sqlite3_last_insert_rowid(db); 521 return cast(ulong)id; 291 522 } 292 523 }
