Merge revisions: r44040, r43881, r43700, r43699, r43698, r43602

Revision: 44040
Author: ondrej
Date: Sonntag, 26. Januar 2020 18:49:08
Message:
fcl-db: allow 0 length in binary field (MSSQL can have a null/0 field length in a view)
----
Modified : /trunk/packages/fcl-db/src/base/fields.inc

Revision: 43881
Author: ondrej
Date: Dienstag, 7. Januar 2020 10:41:20
Message:
odbc: fix international column names
----
Modified : /trunk/packages/fcl-db/src/sqldb/odbc/odbcconn.pas
Modified : /trunk/packages/fcl-db/src/sqldb/sqldb.pp

Revision: 43700
Author: ondrej
Date: Donnerstag, 19. Dezember 2019 18:43:34
Message:
sqldb: odbc: use ANSI codepage for connection as default
----
Modified : /trunk/packages/fcl-db/src/sqldb/odbc/odbcconn.pas

Revision: 43699
Author: ondrej
Date: Donnerstag, 19. Dezember 2019 17:54:36
Message:
sqldb: odbc: send SQL to ODBC as WideString to support FPC 3.0.x character conversion
----
Modified : /trunk/packages/fcl-db/src/sqldb/odbc/odbcconn.pas

Revision: 43698
Author: ondrej
Date: Donnerstag, 19. Dezember 2019 17:41:57
Message:
odbc: fix passing ANSI parameters with FPC character conversion
----
Modified : /trunk/packages/fcl-db/src/sqldb/odbc/odbcconn.pas

Revision: 43602
Author: ondrej
Date: Donnerstag, 28. November 2019 13:59:13
Message:
fcl-db: ODBC: allow NULL parameters (TParam.Value := Null sets type to ftUnknown)
----
Modified : /trunk/packages/fcl-db/src/sqldb/odbc/odbcconn.pas

git-svn-id: branches/fixes_3_2@44391 -
This commit is contained in:
ondrej 2020-03-29 06:46:42 +00:00
parent 6b3a22efb5
commit 227f408df9
3 changed files with 48 additions and 33 deletions

View File

@ -2389,7 +2389,7 @@ class procedure TBinaryField.CheckTypeSize(AValue: Longint);
begin
// Just check for really invalid stuff; actual size is
// dependent on the record...
If AValue<1 then
If AValue<0 then // MSSQL can have a null/0 field length in a view
DatabaseErrorFmt(SInvalidFieldSize,[AValue]);
end;

View File

@ -72,6 +72,7 @@ type
procedure FreeParamBuffers(ODBCCursor:TODBCCursor);
protected
// Overrides from TSQLConnection
function GetConnectionCharSet: string; override;
function GetHandle:pointer; override;
// - Connect/disconnect
procedure DoInternalConnect; override;
@ -400,6 +401,7 @@ var
BufferLength, StrLenOrInd: SQLLEN;
CType, SqlType, DecimalDigits:SQLSMALLINT;
APD: SQLHDESC;
BytesVal: TBytes;
begin
// Note: it is assumed that AParams is the same as the one passed to PrepareStatement, in the sense that
// the parameters have the same order and names
@ -440,43 +442,27 @@ begin
SqlType:=SQL_BIGINT;
ColumnSize:=19;
end;
ftString, ftFixedChar, ftBlob, ftMemo, ftGuid,
ftBytes, ftVarBytes:
ftBlob, ftBytes, ftVarBytes:
begin
StrVal:=AParams[ParamIndex].AsString;
StrLenOrInd:=Length(StrVal);
if StrVal='' then //HY104
BytesVal:=AParams[ParamIndex].AsBytes;
StrLenOrInd:=Length(BytesVal);
if Length(BytesVal)=0 then //HY104
begin
StrVal:=#0;
BytesVal:=[0];
StrLenOrInd:=SQL_NTS;
end;
PVal:=@StrVal[1];
Size:=Length(StrVal);
PVal:=@BytesVal[0];
Size:=Length(BytesVal);
ColumnSize:=Size;
BufferLength:=Size;
CType:=SQL_C_BINARY;
case AParams[ParamIndex].DataType of
ftBytes, ftVarBytes:
begin
CType:=SQL_C_BINARY;
SqlType:=SQL_VARBINARY;
end;
ftBlob:
begin
CType:=SQL_C_BINARY;
ftBytes, ftVarBytes: SqlType:=SQL_VARBINARY;
else // ftBlob
SqlType:=SQL_LONGVARBINARY;
end;
ftMemo:
begin
CType:=SQL_C_CHAR;
SqlType:=SQL_LONGVARCHAR;
end
else // ftString, ftFixedChar
begin
CType:=SQL_C_CHAR;
SqlType:=SQL_VARCHAR;
end;
end;
end;
ftString, ftFixedChar, ftMemo, ftGuid, // string parameters must be passed as widestring to support FPC 3.0.x character conversion
ftWideString, ftFixedWideChar, ftWideMemo:
begin
WideStrVal:=AParams[ParamIndex].AsWideString;
@ -492,7 +478,7 @@ begin
BufferLength:=Size;
CType:=SQL_C_WCHAR;
case AParams[ParamIndex].DataType of
ftWideMemo: SqlType:=SQL_WLONGVARCHAR;
ftMemo, ftWideMemo: SqlType:=SQL_WLONGVARCHAR;
else SqlType:=SQL_WVARCHAR;
end;
end;
@ -563,7 +549,19 @@ begin
CType:=SQL_C_BIT;
SqlType:=SQL_BIT;
ColumnSize:=Size;
end
end;
ftUnknown:
begin
if AParams[ParamIndex].IsNull then // Null variant is stored as ftUnknown - send it over as TINYINT (it doesn't really matter what type)
begin
PVal:=nil;
Size:=0;
CType:=SQL_C_TINYINT;
SqlType:=SQL_TINYINT;
ColumnSize:=Size;
end else
raise EDataBaseError.CreateFmt('Not-null unknown Parameter (index %d) is not supported.',[ParamIndex]);
end;
else
raise EDataBaseError.CreateFmt('Parameter %d is of type %s, which not supported yet',[ParamIndex, Fieldtypenames[AParams[ParamIndex].DataType]]);
end;
@ -572,7 +570,8 @@ begin
StrLenOrInd:=SQL_NULL_DATA;
Buf:=GetMem(Size+SizeOf(StrLenOrInd));
Move(PVal^, Buf^, Size);
if Size>0 then
Move(PVal^, Buf^, Size);
if StrLenOrInd<>0 then
begin
PStrLenOrInd:=Buf + Size;
@ -618,6 +617,13 @@ begin
SetLength(ODBCCursor.FParamBuf,0);
end;
function TODBCConnection.GetConnectionCharSet: string;
begin
Result := inherited GetConnectionCharSet;
if Result='' then
Result := TEncoding.ANSI.EncodingName; // by default, ODBC talks in ANSI, which can be different from CP_ACP (DefaultSystemCodePage)
end;
function TODBCConnection.GetHandle: pointer;
begin
// I'm not sure whether this is correct; perhaps we should return nil
@ -737,6 +743,7 @@ end;
procedure TODBCConnection.PrepareStatement(cursor: TSQLCursor; ATransaction: TSQLTransaction; buf: string; AParams: TParams);
var
ODBCCursor:TODBCCursor;
wbuf: widestring;
begin
ODBCCursor:=cursor as TODBCCursor;
@ -759,8 +766,9 @@ begin
ODBCCursor.FQuery:=Buf;
if not (ODBCCursor.FSchemaType in [stTables, stSysTables, stColumns, stProcedures, stIndexes]) then
begin
wbuf := buf;
ODBCCheckResult(
SQLPrepare(ODBCCursor.FSTMTHandle, PChar(buf), Length(buf)),
SQLPrepareW(ODBCCursor.FSTMTHandle, PWideChar(wbuf), Length(wbuf)),
SQL_HANDLE_STMT, ODBCCursor.FSTMTHandle, 'Could not prepare statement.'
);
end;
@ -913,7 +921,7 @@ var
i:integer;
ColNameLength,TypeNameLength,DataType,DecimalDigits,Nullable:SQLSMALLINT;
ColumnSize:SQLULEN;
ColName,TypeName:string;
ColName,TypeName:RawByteString;
FieldType:TFieldType;
FieldSize:word;
AutoIncAttr, FixedPrecScale, Unsigned, Updatable: SQLLEN;
@ -962,6 +970,9 @@ begin
SQL_HANDLE_STMT, ODBCCursor.FSTMTHandle, 'Could not get column name for column %d.',[i]
);
end;
// ColName is received in ANSI - convert to DefaultSystemCodePage
SetCodePage(ColName, CodePage, False);
SetCodePage(ColName, DefaultSystemCodePage, True);
// convert type
// NOTE: I made some guesses here after I found only limited information about TFieldType; please report any problems
@ -1115,6 +1126,9 @@ begin
SQL_HANDLE_STMT, ODBCCursor.FSTMTHandle, 'Could not get datasource dependent type name for column %s.',[ColName]
);
end;
// TypeName is received in ANSI - convert to DefaultSystemCodePage
SetCodePage(TypeName, CodePage, False);
SetCodePage(TypeName, DefaultSystemCodePage, True);
DatabaseErrorFmt('Column %s has an unknown or unsupported column type. Datasource dependent type name: %s. ODBC SQL data type code: %d.', [ColName, TypeName, DataType]);
end;

View File

@ -267,6 +267,7 @@ type
Property Statements : TThreadList Read FStatements;
property Port: cardinal read GetPort write SetPort;
property CodePage: TSystemCodePage read FCodePage;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;