|
@@ -154,7 +154,7 @@ begin
|
|
|
end;
|
|
|
end;
|
|
|
|
|
|
-procedure ODBCCheckResult(HandleType:SQLSMALLINT; AHandle: SQLHANDLE; ErrorMsg: string);
|
|
|
+procedure ODBCCheckResult(LastReturnCode:SQLRETURN; HandleType:SQLSMALLINT; AHandle: SQLHANDLE; ErrorMsg: string);
|
|
|
|
|
|
// check return value from SQLGetDiagField/Rec function itself
|
|
|
procedure CheckSQLGetDiagResult(const Res:SQLRETURN);
|
|
@@ -172,13 +172,11 @@ procedure ODBCCheckResult(HandleType:SQLSMALLINT; AHandle: SQLHANDLE; ErrorMsg:
|
|
|
var
|
|
|
NativeError:SQLINTEGER;
|
|
|
TextLength:SQLSMALLINT;
|
|
|
- Res,LastReturnCode:SQLRETURN;
|
|
|
+ Res:SQLRETURN;
|
|
|
SqlState,MessageText,TotalMessage:string;
|
|
|
RecNumber:SQLSMALLINT;
|
|
|
begin
|
|
|
// check result
|
|
|
- Res:=SQLGetDiagField(HandleType,AHandle,0,SQL_DIAG_RETURNCODE,@LastReturnCode,SQL_IS_SMALLINT,TextLength);
|
|
|
- CheckSQLGetDiagResult(Res);
|
|
|
if ODBCSucces(LastReturnCode) then
|
|
|
Exit; // no error; all is ok
|
|
|
|
|
@@ -253,7 +251,7 @@ begin
|
|
|
else if EqualSignPos=1 then
|
|
|
raise EODBCException.CreateFmt('Invalid parameter in Params[%d]; no identifier before the ''='' in ''%s''',[i, Param])
|
|
|
else
|
|
|
- Result:=Result + EscapeParamValue(Copy(Param,1,EqualSignPos-1))+'='+EscapeParamValue(Copy(Param,EqualSignPos+1,MaxInt));
|
|
|
+ Result:=Result + EscapeParamValue(Copy(Param,1,EqualSignPos-1))+'='+EscapeParamValue(Copy(Param,EqualSignPos+1,MaxInt))+';';
|
|
|
end;
|
|
|
end;
|
|
|
|
|
@@ -286,17 +284,19 @@ begin
|
|
|
IntVal:=AParams[ParamIndex].AsInteger;
|
|
|
Move(IntVal,Buf^,4);
|
|
|
ODBCCursor.FParamBuf[i]:=Buf;
|
|
|
- SQLBindParameter(ODBCCursor.FSTMTHandle, // StatementHandle
|
|
|
- i+1, // ParameterNumber
|
|
|
- SQL_PARAM_INPUT, // InputOutputType
|
|
|
- SQL_C_LONG, // ValueType
|
|
|
- SQL_INTEGER, // ParameterType
|
|
|
- 10, // ColumnSize
|
|
|
- 0, // DecimalDigits
|
|
|
- Buf, // ParameterValuePtr
|
|
|
- 0, // BufferLength
|
|
|
- nil); // StrLen_or_IndPtr
|
|
|
- ODBCCheckResult(SQL_HANDLE_STMT, ODBCCursor.FSTMTHandle, Format('Could not bind parameter %d',[i]));
|
|
|
+ ODBCCheckResult(
|
|
|
+ SQLBindParameter(ODBCCursor.FSTMTHandle, // StatementHandle
|
|
|
+ i+1, // ParameterNumber
|
|
|
+ SQL_PARAM_INPUT, // InputOutputType
|
|
|
+ SQL_C_LONG, // ValueType
|
|
|
+ SQL_INTEGER, // ParameterType
|
|
|
+ 10, // ColumnSize
|
|
|
+ 0, // DecimalDigits
|
|
|
+ Buf, // ParameterValuePtr
|
|
|
+ 0, // BufferLength
|
|
|
+ nil), // StrLen_or_IndPtr
|
|
|
+ SQL_HANDLE_STMT, ODBCCursor.FSTMTHandle, Format('Could not bind parameter %d',[i])
|
|
|
+ );
|
|
|
end;
|
|
|
ftString:
|
|
|
begin
|
|
@@ -306,17 +306,19 @@ begin
|
|
|
Move(StrLen, buf^, SizeOf(SQLINTEGER));
|
|
|
Move(StrVal[1],(buf+SizeOf(SQLINTEGER))^,StrLen);
|
|
|
ODBCCursor.FParamBuf[i]:=Buf;
|
|
|
- SQLBindParameter(ODBCCursor.FSTMTHandle, // StatementHandle
|
|
|
- i+1, // ParameterNumber
|
|
|
- SQL_PARAM_INPUT, // InputOutputType
|
|
|
- SQL_C_CHAR, // ValueType
|
|
|
- SQL_CHAR, // ParameterType
|
|
|
- StrLen, // ColumnSize
|
|
|
- 0, // DecimalDigits
|
|
|
- buf+SizeOf(SQLINTEGER), // ParameterValuePtr
|
|
|
- StrLen, // BufferLength
|
|
|
- Buf); // StrLen_or_IndPtr
|
|
|
- ODBCCheckResult(SQL_HANDLE_STMT, ODBCCursor.FSTMTHandle, Format('Could not bind parameter %d',[i]));
|
|
|
+ ODBCCheckResult(
|
|
|
+ SQLBindParameter(ODBCCursor.FSTMTHandle, // StatementHandle
|
|
|
+ i+1, // ParameterNumber
|
|
|
+ SQL_PARAM_INPUT, // InputOutputType
|
|
|
+ SQL_C_CHAR, // ValueType
|
|
|
+ SQL_CHAR, // ParameterType
|
|
|
+ StrLen, // ColumnSize
|
|
|
+ 0, // DecimalDigits
|
|
|
+ buf+SizeOf(SQLINTEGER), // ParameterValuePtr
|
|
|
+ StrLen, // BufferLength
|
|
|
+ Buf), // StrLen_or_IndPtr
|
|
|
+ SQL_HANDLE_STMT, ODBCCursor.FSTMTHandle, Format('Could not bind parameter %d',[i])
|
|
|
+ );
|
|
|
end;
|
|
|
else
|
|
|
raise EDataBaseError.CreateFmt('Parameter %d is of type %s, which not supported yet',[ParamIndex, Fieldtypenames[AParams[ParamIndex].DataType]]);
|
|
@@ -359,38 +361,49 @@ begin
|
|
|
end;
|
|
|
|
|
|
// allocate connection handle
|
|
|
- SQLAllocHandle(SQL_HANDLE_DBC,Environment.FENVHandle,FDBCHandle);
|
|
|
- ODBCCheckResult(SQL_HANDLE_ENV,Environment.FENVHandle,'Could not allocate ODBC Connection handle.');
|
|
|
+ ODBCCheckResult(
|
|
|
+ SQLAllocHandle(SQL_HANDLE_DBC,Environment.FENVHandle,FDBCHandle),
|
|
|
+ SQL_HANDLE_ENV,Environment.FENVHandle,'Could not allocate ODBC Connection handle.'
|
|
|
+ );
|
|
|
|
|
|
// connect
|
|
|
ConnectionString:=CreateConnectionString;
|
|
|
SetLength(OutConnectionString,BufferLength-1); // allocate completed connection string buffer (using the ansistring #0 trick)
|
|
|
- SQLDriverConnect(FDBCHandle, // the ODBC connection handle
|
|
|
- nil, // no parent window (would be required for prompts)
|
|
|
- PChar(ConnectionString), // the connection string
|
|
|
- Length(ConnectionString), // connection string length
|
|
|
- @(OutConnectionString[1]),// buffer for storing the completed connection string
|
|
|
- BufferLength, // length of the buffer
|
|
|
- ActualLength, // the actual length of the completed connection string
|
|
|
- SQL_DRIVER_NOPROMPT); // don't prompt for password etc.
|
|
|
- ODBCCheckResult(SQL_HANDLE_DBC,FDBCHandle,Format('Could not connect with connection string "%s".',[ConnectionString]));
|
|
|
- if ActualLength<BufferLength-1 then
|
|
|
- SetLength(OutConnectionString,ActualLength); // fix completed connection string length
|
|
|
+ ODBCCheckResult(
|
|
|
+ SQLDriverConnect(FDBCHandle, // the ODBC connection handle
|
|
|
+ nil, // no parent window (would be required for prompts)
|
|
|
+ PChar(ConnectionString), // the connection string
|
|
|
+ Length(ConnectionString), // connection string length
|
|
|
+ @(OutConnectionString[1]),// buffer for storing the completed connection string
|
|
|
+ BufferLength, // length of the buffer
|
|
|
+ ActualLength, // the actual length of the completed connection string
|
|
|
+ SQL_DRIVER_NOPROMPT), // don't prompt for password etc.
|
|
|
+ SQL_HANDLE_DBC,FDBCHandle,Format('Could not connect with connection string "%s".',[ConnectionString])
|
|
|
+ );
|
|
|
+
|
|
|
+// commented out as the OutConenctionString is not used further at the moment
|
|
|
+// if ActualLength<BufferLength-1 then
|
|
|
+// SetLength(OutConnectionString,ActualLength); // fix completed connection string length
|
|
|
|
|
|
// set connection attributes (none yet)
|
|
|
end;
|
|
|
|
|
|
procedure TODBCConnection.DoInternalDisconnect;
|
|
|
+var
|
|
|
+ Res:SQLRETURN;
|
|
|
begin
|
|
|
inherited DoInternalDisconnect;
|
|
|
|
|
|
// disconnect
|
|
|
- SQLDisconnect(FDBCHandle);
|
|
|
- ODBCCheckResult(SQL_HANDLE_DBC,FDBCHandle,'Could not disconnect.');
|
|
|
+ ODBCCheckResult(
|
|
|
+ SQLDisconnect(FDBCHandle),
|
|
|
+ SQL_HANDLE_DBC,FDBCHandle,'Could not disconnect.'
|
|
|
+ );
|
|
|
|
|
|
// deallocate connection handle
|
|
|
- if SQLFreeHandle(SQL_HANDLE_DBC, FDBCHandle)=SQL_ERROR then
|
|
|
- ODBCCheckResult(SQL_HANDLE_DBC,FDBCHandle,'Could not free connection handle.');
|
|
|
+ Res:=SQLFreeHandle(SQL_HANDLE_DBC, FDBCHandle);
|
|
|
+ if Res=SQL_ERROR then
|
|
|
+ ODBCCheckResult(Res,SQL_HANDLE_DBC,FDBCHandle,'Could not free connection handle.');
|
|
|
end;
|
|
|
|
|
|
function TODBCConnection.AllocateCursorHandle: TSQLCursor;
|
|
@@ -427,8 +440,10 @@ begin
|
|
|
buf := AParams.ParseSQL(buf,false,psInterbase,ODBCCursor.FParamIndex);
|
|
|
|
|
|
// prepare statement
|
|
|
- SQLPrepare(ODBCCursor.FSTMTHandle, PChar(Buf), Length(Buf));
|
|
|
- ODBCCheckResult(SQL_HANDLE_STMT, ODBCCursor.FSTMTHandle, 'Could not prepare statement.');
|
|
|
+ ODBCCheckResult(
|
|
|
+ SQLPrepare(ODBCCursor.FSTMTHandle, PChar(buf), Length(buf)),
|
|
|
+ SQL_HANDLE_STMT, ODBCCursor.FSTMTHandle, 'Could not prepare statement.'
|
|
|
+ );
|
|
|
|
|
|
ODBCCursor.FQuery:=Buf;
|
|
|
end;
|
|
@@ -478,8 +493,10 @@ begin
|
|
|
SetParameters(ODBCCursor, AParams);
|
|
|
|
|
|
// execute the statement
|
|
|
- SQLExecute(ODBCCursor.FSTMTHandle);
|
|
|
- ODBCCheckResult(SQL_HANDLE_STMT, ODBCCursor.FSTMTHandle, 'Could not execute statement.');
|
|
|
+ ODBCCheckResult(
|
|
|
+ SQLExecute(ODBCCursor.FSTMTHandle),
|
|
|
+ SQL_HANDLE_STMT, ODBCCursor.FSTMTHandle, 'Could not execute statement.'
|
|
|
+ );
|
|
|
|
|
|
// free parameter buffers
|
|
|
FreeParamBuffers(ODBCCursor);
|
|
@@ -495,7 +512,7 @@ begin
|
|
|
// fetch new row
|
|
|
Res:=SQLFetch(ODBCCursor.FSTMTHandle);
|
|
|
if Res<>SQL_NO_DATA then
|
|
|
- ODBCCheckResult(SQL_HANDLE_STMT, ODBCCursor.FSTMTHandle, 'Could not fetch new row from result set');
|
|
|
+ ODBCCheckResult(Res,SQL_HANDLE_STMT, ODBCCursor.FSTMTHandle, 'Could not fetch new row from result set');
|
|
|
|
|
|
// result is true iff a new row was available
|
|
|
Result:=Res<>SQL_NO_DATA;
|
|
@@ -509,6 +526,7 @@ var
|
|
|
ODBCTimeStruct:SQL_TIME_STRUCT;
|
|
|
ODBCTimeStampStruct:SQL_TIMESTAMP_STRUCT;
|
|
|
DateTime:TDateTime;
|
|
|
+ Res:SQLRETURN;
|
|
|
begin
|
|
|
ODBCCursor:=cursor as TODBCCursor;
|
|
|
|
|
@@ -517,44 +535,44 @@ begin
|
|
|
// TODO: finish this
|
|
|
case FieldDef.DataType of
|
|
|
ftFixedChar,ftString: // are both mapped to TStringField
|
|
|
- SQLGetData(ODBCCursor.FSTMTHandle, FieldDef.Index+1, SQL_C_CHAR, buffer, FieldDef.Size, @StrLenOrInd);
|
|
|
+ Res:=SQLGetData(ODBCCursor.FSTMTHandle, FieldDef.Index+1, SQL_C_CHAR, buffer, FieldDef.Size, @StrLenOrInd);
|
|
|
ftSmallint: // mapped to TSmallintField
|
|
|
- SQLGetData(ODBCCursor.FSTMTHandle, FieldDef.Index+1, SQL_C_SSHORT, buffer, SizeOf(Smallint), @StrLenOrInd);
|
|
|
+ Res:=SQLGetData(ODBCCursor.FSTMTHandle, FieldDef.Index+1, SQL_C_SSHORT, buffer, SizeOf(Smallint), @StrLenOrInd);
|
|
|
ftInteger,ftWord: // mapped to TLongintField
|
|
|
- SQLGetData(ODBCCursor.FSTMTHandle, FieldDef.Index+1, SQL_C_SLONG, buffer, SizeOf(Longint), @StrLenOrInd);
|
|
|
+ Res:=SQLGetData(ODBCCursor.FSTMTHandle, FieldDef.Index+1, SQL_C_SLONG, buffer, SizeOf(Longint), @StrLenOrInd);
|
|
|
ftLargeint: // mapped to TLargeintField
|
|
|
- SQLGetData(ODBCCursor.FSTMTHandle, FieldDef.Index+1, SQL_C_SBIGINT, buffer, SizeOf(Largeint), @StrLenOrInd);
|
|
|
+ Res:=SQLGetData(ODBCCursor.FSTMTHandle, FieldDef.Index+1, SQL_C_SBIGINT, buffer, SizeOf(Largeint), @StrLenOrInd);
|
|
|
ftFloat: // mapped to TFloatField
|
|
|
- SQLGetData(ODBCCursor.FSTMTHandle, FieldDef.Index+1, SQL_C_DOUBLE, buffer, SizeOf(Double), @StrLenOrInd);
|
|
|
+ Res:=SQLGetData(ODBCCursor.FSTMTHandle, FieldDef.Index+1, SQL_C_DOUBLE, buffer, SizeOf(Double), @StrLenOrInd);
|
|
|
ftTime: // mapped to TTimeField
|
|
|
begin
|
|
|
- SQLGetData(ODBCCursor.FSTMTHandle, FieldDef.Index+1, SQL_C_TYPE_TIME, @ODBCTimeStruct, SizeOf(SQL_TIME_STRUCT), @StrLenOrInd);
|
|
|
+ Res:=SQLGetData(ODBCCursor.FSTMTHandle, FieldDef.Index+1, SQL_C_TYPE_TIME, @ODBCTimeStruct, SizeOf(SQL_TIME_STRUCT), @StrLenOrInd);
|
|
|
DateTime:=TimeStructToDateTime(@ODBCTimeStruct);
|
|
|
Move(DateTime, buffer^, SizeOf(TDateTime));
|
|
|
end;
|
|
|
ftDate: // mapped to TDateField
|
|
|
begin
|
|
|
- SQLGetData(ODBCCursor.FSTMTHandle, FieldDef.Index+1, SQL_C_TYPE_DATE, @ODBCDateStruct, SizeOf(SQL_DATE_STRUCT), @StrLenOrInd);
|
|
|
+ Res:=SQLGetData(ODBCCursor.FSTMTHandle, FieldDef.Index+1, SQL_C_TYPE_DATE, @ODBCDateStruct, SizeOf(SQL_DATE_STRUCT), @StrLenOrInd);
|
|
|
DateTime:=DateStructToDateTime(@ODBCDateStruct);
|
|
|
Move(DateTime, buffer^, SizeOf(TDateTime));
|
|
|
end;
|
|
|
ftDateTime: // mapped to TDateTimeField
|
|
|
begin
|
|
|
- SQLGetData(ODBCCursor.FSTMTHandle, FieldDef.Index+1, SQL_C_TYPE_TIMESTAMP, @ODBCTimeStampStruct, SizeOf(SQL_TIMESTAMP_STRUCT), @StrLenOrInd);
|
|
|
+ Res:=SQLGetData(ODBCCursor.FSTMTHandle, FieldDef.Index+1, SQL_C_TYPE_TIMESTAMP, @ODBCTimeStampStruct, SizeOf(SQL_TIMESTAMP_STRUCT), @StrLenOrInd);
|
|
|
DateTime:=TimeStampStructToDateTime(@ODBCTimeStampStruct);
|
|
|
Move(DateTime, buffer^, SizeOf(TDateTime));
|
|
|
end;
|
|
|
ftBoolean: // mapped to TBooleanField
|
|
|
- SQLGetData(ODBCCursor.FSTMTHandle, FieldDef.Index+1, SQL_C_BIT, buffer, SizeOf(Wordbool), @StrLenOrInd);
|
|
|
+ Res:=SQLGetData(ODBCCursor.FSTMTHandle, FieldDef.Index+1, SQL_C_BIT, buffer, SizeOf(Wordbool), @StrLenOrInd);
|
|
|
ftBytes: // mapped to TBytesField
|
|
|
- SQLGetData(ODBCCursor.FSTMTHandle, FieldDef.Index+1, SQL_C_BINARY, buffer, FieldDef.Size, @StrLenOrInd);
|
|
|
+ Res:=SQLGetData(ODBCCursor.FSTMTHandle, FieldDef.Index+1, SQL_C_BINARY, buffer, FieldDef.Size, @StrLenOrInd);
|
|
|
ftVarBytes: // mapped to TVarBytesField
|
|
|
- SQLGetData(ODBCCursor.FSTMTHandle, FieldDef.Index+1, SQL_C_BINARY, buffer, FieldDef.Size, @StrLenOrInd);
|
|
|
+ Res:=SQLGetData(ODBCCursor.FSTMTHandle, FieldDef.Index+1, SQL_C_BINARY, buffer, FieldDef.Size, @StrLenOrInd);
|
|
|
// TODO: Loading of other field types
|
|
|
else
|
|
|
raise EODBCException.CreateFmt('Tried to load field of unsupported field type %s',[Fieldtypenames[FieldDef.DataType]]);
|
|
|
end;
|
|
|
- ODBCCheckResult(SQL_HANDLE_STMT, ODBCCursor.FSTMTHandle, Format('Could not get field data for field ''%s'' (index %d).',[FieldDef.Name, FieldDef.Index+1]));
|
|
|
+ ODBCCheckResult(Res,SQL_HANDLE_STMT, ODBCCursor.FSTMTHandle, Format('Could not get field data for field ''%s'' (index %d).',[FieldDef.Name, FieldDef.Index+1]));
|
|
|
Result:=StrLenOrInd<>SQL_NULL_DATA; // Result indicates whether the value is non-null
|
|
|
|
|
|
// writeln(Format('Field.Size: %d; StrLenOrInd: %d',[FieldDef.Size, StrLenOrInd]));
|
|
@@ -572,8 +590,10 @@ var
|
|
|
begin
|
|
|
ODBCCursor:=cursor as TODBCCursor;
|
|
|
|
|
|
- SQLFreeStmt(ODBCCursor.FSTMTHandle, SQL_CLOSE);
|
|
|
- ODBCCheckResult(SQL_HANDLE_STMT, ODBCCursor.FSTMTHandle, 'Could not close ODBC statement cursor.');
|
|
|
+ ODBCCheckResult(
|
|
|
+ SQLFreeStmt(ODBCCursor.FSTMTHandle, SQL_CLOSE),
|
|
|
+ SQL_HANDLE_STMT, ODBCCursor.FSTMTHandle, 'Could not close ODBC statement cursor.'
|
|
|
+ );
|
|
|
end;
|
|
|
|
|
|
procedure TODBCConnection.AddFieldDefs(cursor: TSQLCursor; FieldDefs: TFieldDefs);
|
|
@@ -592,24 +612,28 @@ begin
|
|
|
ODBCCursor:=cursor as TODBCCursor;
|
|
|
|
|
|
// get number of columns in result set
|
|
|
- SQLNumResultCols(ODBCCursor.FSTMTHandle, ColumnCount);
|
|
|
- ODBCCheckResult(SQL_HANDLE_STMT, ODBCCursor.FSTMTHandle, 'Could not determine number of columns in result set.');
|
|
|
+ ODBCCheckResult(
|
|
|
+ SQLNumResultCols(ODBCCursor.FSTMTHandle, ColumnCount),
|
|
|
+ SQL_HANDLE_STMT, ODBCCursor.FSTMTHandle, 'Could not determine number of columns in result set.'
|
|
|
+ );
|
|
|
|
|
|
for i:=1 to ColumnCount do
|
|
|
begin
|
|
|
SetLength(ColName,ColNameDefaultLength); // also garantuees uniqueness
|
|
|
|
|
|
// call with default column name buffer
|
|
|
- SQLDescribeCol(ODBCCursor.FSTMTHandle, // statement handle
|
|
|
- i, // column number, is 1-based (Note: column 0 is the bookmark column in ODBC)
|
|
|
- @(ColName[1]), // default buffer
|
|
|
- ColNameDefaultLength+1, // and its length; we include the #0 terminating any ansistring of Length > 0 in the buffer
|
|
|
- ColNameLength, // actual column name length
|
|
|
- DataType, // the SQL datatype for the column
|
|
|
- ColumnSize, // column size
|
|
|
- DecimalDigits, // number of decimal digits
|
|
|
- Nullable); // SQL_NO_NULLS, SQL_NULLABLE or SQL_NULLABLE_UNKNOWN
|
|
|
- ODBCCheckResult(SQL_HANDLE_STMT, ODBCCursor.FSTMTHandle, Format('Could not get column properties for column %d.',[i]));
|
|
|
+ ODBCCheckResult(
|
|
|
+ SQLDescribeCol(ODBCCursor.FSTMTHandle, // statement handle
|
|
|
+ i, // column number, is 1-based (Note: column 0 is the bookmark column in ODBC)
|
|
|
+ @(ColName[1]), // default buffer
|
|
|
+ ColNameDefaultLength+1, // and its length; we include the #0 terminating any ansistring of Length > 0 in the buffer
|
|
|
+ ColNameLength, // actual column name length
|
|
|
+ DataType, // the SQL datatype for the column
|
|
|
+ ColumnSize, // column size
|
|
|
+ DecimalDigits, // number of decimal digits
|
|
|
+ Nullable), // SQL_NO_NULLS, SQL_NULLABLE or SQL_NULLABLE_UNKNOWN
|
|
|
+ SQL_HANDLE_STMT, ODBCCursor.FSTMTHandle, Format('Could not get column properties for column %d.',[i])
|
|
|
+ );
|
|
|
|
|
|
// truncate buffer or make buffer long enough for entire column name (note: the call is the same for both cases!)
|
|
|
SetLength(ColName,ColNameLength);
|
|
@@ -617,14 +641,16 @@ begin
|
|
|
if ColNameLength>ColNameDefaultLength then
|
|
|
begin
|
|
|
// request column name with buffer that is long enough
|
|
|
- SQLColAttribute(ODBCCursor.FSTMTHandle, // statement handle
|
|
|
- i, // column number
|
|
|
- SQL_DESC_NAME, // the column name or alias
|
|
|
- @(ColName[1]), // buffer
|
|
|
- ColNameLength+1, // buffer size
|
|
|
- @ColNameLength, // actual length
|
|
|
- nil); // no numerical output
|
|
|
- ODBCCheckResult(SQL_HANDLE_STMT, ODBCCursor.FSTMTHandle, Format('Could not get column name for column %d.',[i]));
|
|
|
+ ODBCCheckResult(
|
|
|
+ SQLColAttribute(ODBCCursor.FSTMTHandle, // statement handle
|
|
|
+ i, // column number
|
|
|
+ SQL_DESC_NAME, // the column name or alias
|
|
|
+ @(ColName[1]), // buffer
|
|
|
+ ColNameLength+1, // buffer size
|
|
|
+ @ColNameLength, // actual length
|
|
|
+ nil), // no numerical output
|
|
|
+ SQL_HANDLE_STMT, ODBCCursor.FSTMTHandle, Format('Could not get column name for column %d.',[i])
|
|
|
+ );
|
|
|
end;
|
|
|
|
|
|
// convert type
|
|
@@ -702,15 +728,20 @@ begin
|
|
|
raise EODBCException.Create('Could not allocate ODBC Environment handle'); // we can't retrieve any more information, because we don't have a handle for the SQLGetDiag* functions
|
|
|
|
|
|
// set odbc version
|
|
|
- SQLSetEnvAttr(FENVHandle, SQL_ATTR_ODBC_VERSION, SQLPOINTER(SQL_OV_ODBC3), 0);
|
|
|
- ODBCCheckResult(SQL_HANDLE_ENV, FENVHandle,'Could not set ODBC version to 3.');
|
|
|
+ ODBCCheckResult(
|
|
|
+ SQLSetEnvAttr(FENVHandle, SQL_ATTR_ODBC_VERSION, SQLPOINTER(SQL_OV_ODBC3), 0),
|
|
|
+ SQL_HANDLE_ENV, FENVHandle,'Could not set ODBC version to 3.'
|
|
|
+ );
|
|
|
end;
|
|
|
|
|
|
destructor TODBCEnvironment.Destroy;
|
|
|
+var
|
|
|
+ Res:SQLRETURN;
|
|
|
begin
|
|
|
// free environment handle
|
|
|
- if SQLFreeHandle(SQL_HANDLE_ENV, FENVHandle)=SQL_ERROR then
|
|
|
- ODBCCheckResult(SQL_HANDLE_ENV, FENVHandle, 'Could not free ODBC Environment handle.');
|
|
|
+ Res:=SQLFreeHandle(SQL_HANDLE_ENV, FENVHandle);
|
|
|
+ if Res=SQL_ERROR then
|
|
|
+ ODBCCheckResult(Res,SQL_HANDLE_ENV, FENVHandle, 'Could not free ODBC Environment handle.');
|
|
|
|
|
|
// free odbc if not used by any TODBCEnvironment object anymore
|
|
|
Dec(ODBCLoadCount);
|
|
@@ -722,19 +753,24 @@ end;
|
|
|
constructor TODBCCursor.Create(Connection:TODBCConnection);
|
|
|
begin
|
|
|
// allocate statement handle
|
|
|
- SQLAllocHandle(SQL_HANDLE_STMT, Connection.FDBCHandle, FSTMTHandle);
|
|
|
- ODBCCheckResult(SQL_HANDLE_DBC, Connection.FDBCHandle, 'Could not allocate ODBC Statement handle.');
|
|
|
+ ODBCCheckResult(
|
|
|
+ SQLAllocHandle(SQL_HANDLE_STMT, Connection.FDBCHandle, FSTMTHandle),
|
|
|
+ SQL_HANDLE_DBC, Connection.FDBCHandle, 'Could not allocate ODBC Statement handle.'
|
|
|
+ );
|
|
|
end;
|
|
|
|
|
|
destructor TODBCCursor.Destroy;
|
|
|
+var
|
|
|
+ Res:SQLRETURN;
|
|
|
begin
|
|
|
inherited Destroy;
|
|
|
|
|
|
if FSTMTHandle<>SQL_INVALID_HANDLE then
|
|
|
begin
|
|
|
// deallocate statement handle
|
|
|
- if SQLFreeHandle(SQL_HANDLE_STMT, FSTMTHandle)=SQL_ERROR then
|
|
|
- ODBCCheckResult(SQL_HANDLE_STMT, FSTMTHandle, 'Could not free ODBC Statement handle.');
|
|
|
+ Res:=SQLFreeHandle(SQL_HANDLE_STMT, FSTMTHandle);
|
|
|
+ if Res=SQL_ERROR then
|
|
|
+ ODBCCheckResult(Res,SQL_HANDLE_STMT, FSTMTHandle, 'Could not free ODBC Statement handle.');
|
|
|
end;
|
|
|
end;
|
|
|
|