Changeset 15 for trunk/sdbo
- Timestamp:
- 09/20/04 19:49:36 (8 years ago)
- Files:
-
- trunk/sdbo/_odbc_headers/sqltypes.d (modified) (1 diff)
- trunk/sdbo/odbc.d (modified) (2 diffs)
- trunk/sdbo/odbc_env.d (modified) (1 diff)
- trunk/sdbo/odbc_stmt.d (modified) (36 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/sdbo/_odbc_headers/sqltypes.d
r14 r15 16 16 } else { 17 17 18 typedef void *HANDLE; 19 20 /* 21 * Windows style typedefs for UNIX machines 22 * (from iODBC) 23 */ 24 25 alias byte BYTE; 26 alias ushort WORD; 27 alias ulong DWORD; 28 29 alias DWORD* LPDWORD; 30 alias char* LPSTR; 31 alias char* LPCSTR; 32 33 // #if !defined(BOOL) && !defined(_OBJC_OBJC_H_) 34 typedef int BOOL; 35 // #endif 36 18 private extern(C) { 19 typedef void* HANDLE; 20 21 /* 22 * Windows style typedefs for UNIX machines 23 * (from iODBC) 24 */ 25 26 alias ubyte BYTE; 27 alias ushort WORD; 28 alias ulong DWORD; 29 30 alias DWORD* LPDWORD; 31 alias char* LPSTR; 32 alias char* LPCSTR; 33 34 alias int BOOL; 35 } 37 36 } 38 37 trunk/sdbo/odbc.d
r14 r15 43 43 } 44 44 45 public alias sdbo.odbc_env.OdbcEnvironment OdbcEnvironment; 46 public alias sdbo.odbc_dbc.OdbcConnection OdbcConnection; 47 public alias sdbo.odbc_stmt.SqlResult SqlResult; 48 public alias sdbo.odbc_etc.ColumnSpec ColumnSpec; 49 public alias sdbo.odbc_etc.SqlException SqlException; 50 public alias sdbo.odbc_etc.OdbcMessage OdbcMessage; 51 52 53 /*! \brief Shortcut for faster typing 54 */ 55 public alias OdbcEnvironment DBEnv; 56 57 /*! \brief Shortcut for faster typing 58 */ 59 public alias OdbcConnection DBCon; 60 45 61 /*! \endif 46 62 */ … … 66 82 and you just want to connect to a database and execute query statements, without caring about 67 83 odbc handles, data types, and API calls. 84 85 On the other hand, if you need to access the raw odbc api you can still use the classes to hide away 86 bulk operations: 87 88 <pre> 89 SqlResult r = (new OdbcConnection).connect("someserver").execDirect("select something from somewhere"); 90 HSTMT hstmt = r.handle(); 91 </pre> 68 92 69 93 trunk/sdbo/odbc_env.d
r14 r15 130 130 131 131 /*! \brief Sets up an environment for odbc version 3 (SQL_OV_ODBC3) 132 * 133 * Most applications will need only one environment to create all connections. 134 * 135 * 132 136 */ 133 137 public this() trunk/sdbo/odbc_stmt.d
r14 r15 42 42 } 43 43 44 private import sdbo.odbc_env; 44 45 private import sdbo.odbc_dbc; 45 46 private import sdbo.odbc_etc; … … 59 60 { 60 61 61 private struct ColumnBinding62 private struct Binding 62 63 { 63 64 bit allocated; 64 65 bit bound; 65 66 67 SQLPOINTER buffer; 68 SQLINTEGER bufLen; 69 SQLINTEGER* StrLen_or_IndPtr; /* this integer goes into the dll so it must be malloc'd */ 70 } 71 72 private struct ParamBinding 73 { 74 75 SQLINTEGER valueType; 76 SQLINTEGER paramType; 77 78 Binding binding; 79 } 80 81 private struct ColumnBinding 82 { 66 83 SQLINTEGER targetType = UNBOUND; 67 68 SQLPOINTER ptr; 69 SQLINTEGER* bufLen; /* this integer goes into the dll so it must be malloc'd */ 84 85 Binding binding; 70 86 } 71 87 … … 88 104 switch(sqlType) { 89 105 90 case SQL_BIGINT: return SQL_C_SBIGINT;91 case SQL_TYPE_DATE: return SQL_C_CHAR;92 case SQL_TYPE_TIME: return SQL_C_CHAR;93 case SQL_TYPE_TIMESTAMP: return SQL_C_CHAR;94 default: return SQL_C_DEFAULT;106 case SQL_BIGINT: return SQL_C_SBIGINT; /* odbc assigns char as default for this */ 107 case SQL_TYPE_DATE: return SQL_C_CHAR; 108 case SQL_TYPE_TIME: return SQL_C_CHAR; 109 case SQL_TYPE_TIMESTAMP: return SQL_C_CHAR; 110 default: return SQL_C_DEFAULT; 95 111 } 96 112 } … … 108 124 switch(dType) { 109 125 110 case D_LONG: return sqlType == SQL_BIGINT;111 126 case D_INT: return sqlType == SQL_INTEGER; 112 127 case D_SHORT: return sqlType == SQL_SMALLINT; 113 128 case D_DOUBLE: return sqlType == SQL_DOUBLE || sqlType == SQL_FLOAT; 114 129 case D_FLOAT: return sqlType == SQL_REAL; 115 case D_CHAR: return sqlType == SQL_CHAR || sqlType == SQL_VARCHAR || sqlType == SQL_LONGVARCHAR || sqlType == SQL_NUMERIC; 130 case D_CHAR: return sqlType == SQL_CHAR || sqlType == SQL_VARCHAR || sqlType == SQL_LONGVARCHAR || sqlType == SQL_NUMERIC || sqlType == SQL_BIGINT; 131 132 case D_LONG: 116 133 case D_WCHAR: 117 134 default: return false; … … 133 150 private ColumnSpec*[] cspecs; 134 151 private ColumnBinding*[] cbindings; 152 private ParamBinding*[] pbindings; 135 153 136 154 private uint[char[]] cIndex; … … 138 156 private uint fetchCount = 0; 139 157 158 private bit prepared = false; 140 159 private bit executed = false; 160 private bit executedDirectly = false; 161 141 162 142 163 /*! \brief Diagnostics message from the last odbc call that returned SQL_SUCCESS_WITH_INFO … … 179 200 public bit bindAll = true; 180 201 202 203 181 204 private this(OdbcConnection dbc) 182 205 { … … 195 218 this(dbc); 196 219 execDirect(sql); 197 executed = true;220 executedDirectly = true; 198 221 } 199 222 … … 212 235 } 213 236 214 if(executed) 215 close(); 216 217 checkRetcode(SQLFreeHandle(SQL_HANDLE_STMT, hstmt), "SQLFreeHandle"); 218 237 try { 238 239 if(executedDirectly || executed || cbindings.length > 0 || pbindings.length > 0) 240 close(); 241 242 checkRetcode(SQLFreeHandle(SQL_HANDLE_STMT, hstmt), "SQLFreeHandle"); 243 244 } catch(SqlException e) {} 245 219 246 //writefln("/result destructor"); 220 247 } 221 248 222 249 223 /*! \brief The parent connection for this result. 250 /*! \brief The parent connections environment. 251 * 252 * shortcut for result.connection().environment() 253 */ 254 255 public OdbcEnvironment environment() 256 { 257 return dbc.environment(); 258 } 259 260 /*! \brief The parent connection. 224 261 * 225 262 */ … … 240 277 } 241 278 242 /*! \brief Executes a query for this result. 279 280 /*! \brief Prepares a SQL statement for later execution. 281 */ 282 283 public void prepare(char[] query) { 284 285 if(executed || executedDirectly) 286 close(); 287 288 checkRetcode(SQLPrepare( 289 hstmt, 290 cast(SQLCHAR*) toStringz(query), 291 query.length 292 ), "SQLPrepare"); 293 } 294 295 296 /*! \brief Sets an input parameter for a prepared statement 297 * 298 * Parameter index numbers start at 0 for the leftmost parameter. 299 */ 300 public void setInput(int num, long param, int paramType = SQL_BIGINT) { 301 setInputBuffer(num, D_LONG, ¶m, param.sizeof, paramType); 302 } 303 304 /*! \brief Sets an input parameter for a prepared statement 305 * 306 * Parameter index numbers start at 0 for the leftmost parameter. 307 */ 308 public void setInput(int num, int param, int paramType = SQL_INTEGER) { 309 setInputBuffer(num, D_INT, ¶m, param.sizeof, paramType); 310 } 311 312 /*! \brief Sets an input parameter for a prepared statement 313 * 314 * Parameter index numbers start at 0 for the leftmost parameter. 315 */ 316 public void setInput(int num, short param, int paramType = SQL_SMALLINT) { 317 setInputBuffer(num, D_SHORT, ¶m, param.sizeof, paramType); 318 } 319 320 /*! \brief Sets an input parameter for a prepared statement 321 * 322 * Parameter index numbers start at 0 for the leftmost parameter. 323 */ 324 public void setInput(int num, double param, int paramType = SQL_DOUBLE) { 325 setInputBuffer(num, D_DOUBLE, ¶m, param.sizeof, paramType); 326 } 327 328 /*! \brief Sets an input parameter for a prepared statement 329 * 330 * Parameter index numbers start at 0 for the leftmost parameter. 331 */ 332 public void setInput(int num, float param, int paramType = SQL_REAL) { 333 setInputBuffer(num, D_FLOAT, ¶m, param.sizeof, paramType); 334 } 335 336 /*! \brief Sets an input parameter for a prepared statement 337 * 338 * Parameter index numbers start at 0 for the leftmost parameter. 339 * 340 */ 341 public void setInput(int num, char[] param, int paramType = SQL_VARCHAR, int bufLen = 0) { 342 setInputBuffer(num, D_CHAR, cast(void*)param, param.length, paramType, bufLen); 343 } 344 345 /*! \brief Sets an input parameter for a prepared statement 346 * 347 * Parameter index numbers start at 0 for the leftmost parameter. 348 * 349 * This function is called setInputw, otherwise the compiler complains about 350 * ambiguous overload with setInput(... char[] ...) 351 * 352 */ 353 public void setInputw(int num, wchar[] param, int paramType = SQL_WVARCHAR, int bufLen = 0) { 354 setInputBuffer(num, D_WCHAR, cast(void*)param, wchar.sizeof * param.length, paramType, bufLen); 355 } 356 357 358 /*! \if never 359 */ 360 361 private void setInputBuffer(int num, int valueType, void* param, uint paramLen, SQLINTEGER paramType, uint minBufLen = 0) 362 in { 363 assert(minBufLen == 0 || minBufLen >= paramLen); 364 365 } 366 body { 367 /* sets the input parameter buffer for a column to the value submitted by the application. 368 * allocs, reallocs and binds the parameter as necessary. 369 */ 370 371 if(minBufLen == 0) minBufLen = paramLen; 372 373 if(pbindings.length < num + 1) { 374 pbindings.length = num + 1; 375 } 376 377 if(pbindings[num]) { 378 379 if(minBufLen > pbindings[num].binding.bufLen) { 380 381 pbindings[num].binding.bound = false; 382 reallocBinding(&pbindings[num].binding, minBufLen); 383 384 } else if(pbindings[num].binding.bound && ( 385 pbindings[num].valueType != valueType 386 || pbindings[num].paramType != paramType 387 )) { 388 389 pbindings[num].binding.bound = false; 390 } 391 392 } else { 393 394 pbindings[num] = new ParamBinding; 395 allocBinding(&pbindings[num].binding, minBufLen); 396 } 397 398 if(!pbindings[num].binding.bound) { 399 bindParameter(SQL_PARAM_INPUT, num, valueType, paramType); 400 } 401 402 pbindings[num].binding.buffer[0..paramLen] = param[0..paramLen]; 403 *pbindings[num].binding.StrLen_or_IndPtr = paramLen; 404 405 } 406 407 private void bindParameter(SQLSMALLINT iotype, int num, SQLSMALLINT valueType, SQLSMALLINT paramType) 408 in { 409 assert(num < pbindings.length); 410 assert(pbindings[num]); 411 assert(pbindings[num].binding.allocated); 412 } 413 body { 414 415 checkRetcode(SQLBindParameter( 416 hstmt, 417 num + 1, 418 iotype, 419 valueType, 420 paramType, 421 pbindings[num].binding.bufLen, 422 2, 423 pbindings[num].binding.buffer, 424 pbindings[num].binding.bufLen, 425 pbindings[num].binding.StrLen_or_IndPtr 426 ), "SQLBindParameter"); 427 428 } 429 430 /*! \endif 431 */ 432 433 434 /*! \brief Executes a prepared statement for this result. 243 435 * 244 436 * \warning … … 247 439 * 248 440 */ 441 442 public void execute() 443 { 444 checkRetcode(SQLExecute(hstmt), "SQLExecute"); 445 executed = true; 446 } 447 448 449 /*! \brief Executes a query for this result. 450 * 451 * \warning 452 * If the result was bound to a previous query, all resources related to that query will be freed 453 * For instance, a buffer retrieved with rawBuffer will be freed. 454 * 455 */ 249 456 250 457 … … 252 459 { 253 460 254 if(executed ) close();461 if(executedDirectly || executed || prepared) close(); 255 462 256 463 checkRetcode(SQLExecDirect(hstmt, toStringz(sql), SQL_NTS), "SQLEcexDirect"); 257 executed = true;464 executedDirectly = true; 258 465 259 466 short ccount = 0; … … 357 564 } 358 565 359 public static const int UNBOUND = 0;360 361 /* map c data types to d data types */362 363 566 /*! \brief Sets the binding for a column 364 567 * 365 568 * 366 569 * Valid parameters: 367 * 368 * - SqlResult.D_LONG 369 * - SqlResult.D_INT 370 * - SqlResult.D_SHORT 371 * 372 * - SqlResult.D_DOUBLE 373 * - SqlResult.D_FLOAT 374 * 375 * - SqlResult.D_WCHAR 376 * - SqlResult.D_CHAR 377 * 378 * - SqlResult.UNBOUND 570 <pre> 571 SqlResult.D_LONG 572 SqlResult.D_INT 573 SqlResult.D_SHORT 574 575 SqlResult.D_DOUBLE 576 SqlResult.D_FLOAT 577 578 SqlResult.D_WCHAR 579 SqlResult.D_CHAR 580 581 SqlResult.UNBOUND 582 </pre> 583 * 584 * This function sets the binding target type for a column or for all columns, 585 * but it doesn't actually bind the columns. 586 * The columns are bound on the first call to fetch(). 587 * 379 588 * 380 589 * Every D type is mapped to a predefined target C type. Some target types can be extracted 381 590 * with the value functions. 382 591 * 383 <pre>592 384 593 D_LONG = SQL_C_SBIGINT result.vlong(col) 385 594 D_INT = SQL_C_SLONG result.vint(col) … … 389 598 D_CHAR = SQL_C_CHAR result.string(col) result.stringz(col) 390 599 D_WCHAR = SQL_C_WCHAR result.wstring(col) 391 </pre>600 392 601 * 393 602 * … … 395 604 * with the following exceptions: 396 605 <pre> 397 SQL_BIGINT: D_LONG (SQL_C_SBIGINT) 606 SQL_BIGINT: D_LONG (SQL_C_SBIGINT) - odbc default is SQL_C_CHAR 398 607 SQL_TYPE_DATE: D_CHAR (SQL_C_CHAR) 399 608 SQL_TYPE_TIME: D_CHAR (SQL_C_CHAR) … … 401 610 </pre> 402 611 403 * SqlResult.UNBOUND causes the column not to be bound. If the column is bound it will be unbound imediately. 404 * 405 * 406 * 612 * SqlResult.UNBOUND causes the column not to be bound. 613 * \note 614 * If bindAll is true, all columns set to UNBOUND will be set to their default types on the first fetch. 615 * After the first fetch, a column set to UNBOUND stays unbound even if bindAll is true. 616 * 617 * If the column is already bound it will be unbound. 407 618 * \warning 408 * Any previously allocated buffer will be free'd 619 * Allocated buffer for the column will be freed. 620 * 409 621 * 410 622 */ … … 445 657 446 658 foreach(ColumnBinding* cb; cbindings) { 447 cb.bound = false; 448 if(cb.allocated) 449 freeColumn(cb); 450 659 cb.binding.bound = false; 660 if(cb.binding.allocated) 661 freeBinding(&cb.binding); 451 662 } 452 663 … … 573 784 in { 574 785 assert(col < cbindings.length); 575 assert(cbindings[col].b ound);786 assert(cbindings[col].binding.bound); 576 787 577 788 _checkTargetErr(col, D_TYPE); 578 789 } 579 790 body { 580 return *(cast(RET_TYPE*) (cbindings[col]. ptr));791 return *(cast(RET_TYPE*) (cbindings[col].binding.buffer)); 581 792 } 582 793 RET_TYPE val(char[] column) 583 794 in { 584 795 assert(column in cIndex); 585 assert(cbindings[cIndex[column]].bound); 586 587 796 assert(cbindings[cIndex[column]].binding.bound); 588 797 _checkTargetErr(cIndex[column], D_TYPE); 589 798 } 590 799 body { 591 return *(cast(RET_TYPE*) (cbindings[cIndex[column]]. ptr));800 return *(cast(RET_TYPE*) (cbindings[cIndex[column]].binding.buffer)); 592 801 } 593 802 } … … 598 807 in { 599 808 assert(col < cbindings.length); 600 assert(cbindings[col].b ound);809 assert(cbindings[col].binding.bound); 601 810 _checkTargetErr(col, D_TYPE); 602 811 } 603 812 body { 604 813 605 if(*cbindings[col].b ufLen == SQL_NULL_DATA || *cbindings[col].bufLen== 0)814 if(*cbindings[col].binding.StrLen_or_IndPtr == SQL_NULL_DATA || *cbindings[col].binding.StrLen_or_IndPtr == 0) 606 815 return ""; 607 816 608 817 void[] retval; 609 retval.length = *cbindings[col].b ufLen;610 retval[0..length] = ((cast(void*)cbindings[col]. ptr)[0..*cbindings[col].bufLen]);818 retval.length = *cbindings[col].binding.StrLen_or_IndPtr; 819 retval[0..length] = ((cast(void*)cbindings[col].binding.buffer)[0..*cbindings[col].binding.StrLen_or_IndPtr]); 611 820 return cast(RET_TYPE[]) retval; 612 821 } … … 642 851 assert(fetchCount > 0); 643 852 assert(col < cbindings.length); 644 assert(!cbindings[col].b ound);853 assert(!cbindings[col].binding.bound); 645 854 } 646 855 body { … … 677 886 assert(fetchCount > 0); 678 887 assert(col < cbindings.length); 679 assert(!cbindings[col].b ound);888 assert(!cbindings[col].binding.bound); 680 889 } 681 890 body { … … 727 936 728 937 for(int col = 0; col < cbindings.length; col++){ 729 ColumnBinding* cb = cbindings[col];938 /* ColumnBinding* cb = cbindings[col]; */ 730 939 if(_checkTarget(col, D_TYPE)) { 731 940 … … 777 986 RET_TYPE[][char[]] val; 778 987 for(int col = 0; col < cbindings.length; col++){ 779 ColumnBinding* cb = cbindings[col];988 /* ColumnBinding* cb = cbindings[col]; */ 780 989 if(_checkTarget(col, D_TYPE)) { 781 990 … … 806 1015 assert(fetchCount > 0); 807 1016 assert(col < cbindings.length); 808 assert(cbindings[col].b ound);809 810 return *cbindings[col].b ufLen== SQL_NULL_DATA;1017 assert(cbindings[col].binding.bound); 1018 1019 return *cbindings[col].binding.StrLen_or_IndPtr == SQL_NULL_DATA; 811 1020 } 812 1021 … … 817 1026 assert(fetchCount > 0); 818 1027 assert(column in cIndex); 819 assert(cbindings[cIndex[column]].b ound);820 821 return *cbindings[cIndex[column]].b ufLen== SQL_NULL_DATA;1028 assert(cbindings[cIndex[column]].binding.bound); 1029 1030 return *cbindings[cIndex[column]].binding.StrLen_or_IndPtr == SQL_NULL_DATA; 822 1031 } 823 1032 … … 905 1114 * 906 1115 * \warning 907 * The buffer and the integer are malloc'd and will be free'd by the result object's destructor .908 * 1116 * The buffer and the integer are malloc'd and will be free'd by the result object's destructor 1117 * or after a call to setBinding for this column. 909 1118 * 910 1119 * … … 916 1125 assert(col < cbindings.length); 917 1126 918 TargetValuePtr = cbindings[col]. ptr;919 StrLen_or_IndPtr = cbindings[col].b ufLen;1127 TargetValuePtr = cbindings[col].binding.buffer; 1128 StrLen_or_IndPtr = cbindings[col].binding.StrLen_or_IndPtr; 920 1129 } 921 1130 … … 1018 1227 1019 1228 foreach(ColumnBinding* cb; cbindings) { 1020 if(cb.allocated) 1021 freeColumn(cb); 1229 if(cb.binding.allocated) 1230 freeBinding(&cb.binding); 1231 } 1232 1233 foreach(ParamBinding* pb; pbindings) { 1234 if(pb && pb.binding.allocated) 1235 freeBinding(&pb.binding); 1022 1236 } 1023 1237 … … 1027 1241 ), "SQLFreeStmt"); 1028 1242 1243 checkRetcode(SQLFreeStmt( 1244 hstmt, 1245 SQL_RESET_PARAMS 1246 ), "SQLFreeStmt"); 1247 1029 1248 1030 1249 foreach(char[] key; cIndex.keys) … … 1032 1251 1033 1252 cbindings.length = 0; 1253 pbindings.length = 0; 1034 1254 cspecs.length = 0; 1035 1255 fetchCount = 0; … … 1041 1261 ), "SQLFreeStmt"); 1042 1262 1263 prepared = false; 1043 1264 executed = false; 1265 executedDirectly = false; 1044 1266 1045 1267 } … … 1118 1340 1119 1341 for(uint col = 0; col < cbindings.length; col++) { 1120 if(cbindings[col].targetType != UNBOUND || cbindings[col].b ound)1342 if(cbindings[col].targetType != UNBOUND || cbindings[col].binding.bound) 1121 1343 bindColumn(col); 1122 1344 } … … 1128 1350 ColumnSpec* cs = cspecs[col]; 1129 1351 1130 assert(cb.targetType != UNBOUND || cb.b ound);1352 assert(cb.targetType != UNBOUND || cb.binding.bound); 1131 1353 1132 1354 uint ptrSize; … … 1134 1356 if(cb.targetType == UNBOUND) { 1135 1357 ptrSize = 0; 1136 cb. ptr = null;1358 cb.binding.buffer = null; 1137 1359 } else { 1138 1360 … … 1154 1376 //writefln("col %d targettype %d size %d", col, targetType, ptrSize); 1155 1377 1156 if(cb.allocated)1157 freeColumn(cb);1158 1159 1378 assert(cb.targetType == UNBOUND || ptrSize > 0); 1160 1379 1161 allocColumn(cb, ptrSize); 1380 if(cb.binding.allocated) { 1381 if(cb.binding.bufLen < ptrSize) 1382 reallocBinding(&cb.binding, ptrSize); 1383 } else { 1384 allocBinding(&cb.binding, ptrSize); 1385 } 1162 1386 1163 1387 checkRetcode(SQLBindCol( … … 1165 1389 col + 1, 1166 1390 cb.targetType, 1167 cb. ptr,1168 ptrSize,1169 cb.b ufLen1391 cb.binding.buffer, 1392 cb.binding.bufLen, 1393 cb.binding.StrLen_or_IndPtr 1170 1394 ), "SQLBindCol"); 1171 1395 1172 1396 //writefln("bound %d targettype %d octet %d ptrsize %d", col, targetType, cs.octetLength, ptrSize); 1173 1397 1174 cb.b ound = cb.targetType != UNBOUND;1398 cb.binding.bound = cb.targetType != UNBOUND; 1175 1399 1176 1400 } 1177 1401 1178 1402 1179 1180 1181 private void allocColumn(ColumnBinding* cb, uint size) 1182 { 1183 1184 void* p = std.c.stdlib.malloc(size); 1403 private void allocBinding(Binding* b, uint bufLen) 1404 in { 1405 assert(!b.bound); 1406 assert(!b.allocated); 1407 assert(bufLen); 1408 } 1409 body { 1410 void* p = std.c.stdlib.malloc(bufLen); 1411 1412 if(p == null) { 1413 throw new Exception("Out of memory"); 1414 /* don't know if the gc has memory for that exception... 1415 if not, gc handles the error */ 1416 } 1417 1418 b.buffer = cast(SQLPOINTER) p; 1419 1420 p = std.c.stdlib.malloc(b.StrLen_or_IndPtr.sizeof); 1421 1422 if(p == null) { 1423 std.c.stdlib.free(b.buffer); 1424 throw new Exception("Out of memory"); 1425 } 1426 1427 b.StrLen_or_IndPtr = cast(SQLINTEGER*) p; 1428 b.bufLen = bufLen; 1429 1430 b.allocated = true; 1431 } 1432 1433 private void reallocBinding(Binding* b, uint bufLen) 1434 in { 1435 assert(b.allocated); 1436 assert(bufLen > b.bufLen); 1437 } 1438 body { 1439 1440 void* p = std.c.stdlib.realloc(b.buffer, bufLen); 1185 1441 1186 1442 if(p == null) 1187 throw new Exception("Out of memory"); 1188 1189 cb.ptr = cast(SQLPOINTER) p; 1190 1191 cb.allocated = true; 1192 1193 p = std.c.stdlib.malloc(cb.bufLen.sizeof); 1194 1195 if(p == null) 1196 throw new Exception("Out of memory"); 1197 1198 cb.bufLen = cast(SQLINTEGER*) p; 1199 1200 1201 } 1202 1203 private void freeColumn(ColumnBinding* cb) 1204 { 1205 std.c.stdlib.free(cb.ptr); 1206 std.c.stdlib.free(cb.bufLen); 1207 cb.allocated = false; 1443 throw new Exception("Out of memory"); /* probably there won't be memory for that exception? */ 1444 1445 b.buffer = cast(SQLPOINTER) p; 1446 b.bufLen = bufLen; 1447 1448 } 1449 1450 private void freeBinding(Binding* b) 1451 in { 1452 assert(b.allocated); 1453 } 1454 body { 1455 std.c.stdlib.free(b.buffer); 1456 std.c.stdlib.free(b.StrLen_or_IndPtr); 1457 b.allocated = false; 1208 1458 } 1209 1459
