소스 검색

fcl-db: mssql: initial attempt to implement support for output parameters of stored procedures. Beause MS in newer versions of TDS protocol has breaked it we must use other way how to do it (use dbrpc*() API functions). But return status of stored procedures execution is returned as before, so start with it.
This patch depends on rev.27445

git-svn-id: trunk@27447 -

lacak 11 년 전
부모
커밋
9d2933d752
2개의 변경된 파일22개의 추가작업 그리고 2개의 파일을 삭제
  1. 20 1
      packages/fcl-db/src/sqldb/mssql/mssqlconn.pp
  2. 2 1
      packages/fcl-db/src/sqldb/mssql/readme.txt

+ 20 - 1
packages/fcl-db/src/sqldb/mssql/mssqlconn.pp

@@ -66,6 +66,7 @@ type
     function CheckError(const Ret: RETCODE): RETCODE;
     function CheckError(const Ret: RETCODE): RETCODE;
     procedure Execute(const cmd: string); overload;
     procedure Execute(const cmd: string); overload;
     procedure ExecuteDirectSQL(const Query: string);
     procedure ExecuteDirectSQL(const Query: string);
+    procedure GetParameters(cursor: TSQLCursor; AParams: TParams);
     function TranslateFldType(SQLDataType: integer): TFieldType;
     function TranslateFldType(SQLDataType: integer): TFieldType;
     function ClientCharset: TClientCharset;
     function ClientCharset: TClientCharset;
     function AutoCommit: boolean;
     function AutoCommit: boolean;
@@ -467,7 +468,7 @@ begin
     try
     try
       Prepare(format('SELECT cast(%s as varchar), @@version, user_name()', [VERSION_NUMBER[IsSybase]]), nil);
       Prepare(format('SELECT cast(%s as varchar), @@version, user_name()', [VERSION_NUMBER[IsSybase]]), nil);
       Execute(nil);
       Execute(nil);
-      if Fetch then
+      while Fetch do
       begin
       begin
         Put(1, FServerInfo.ServerVersion);
         Put(1, FServerInfo.ServerVersion);
         Put(2, FServerInfo.ServerVersionString);
         Put(2, FServerInfo.ServerVersionString);
@@ -620,6 +621,9 @@ begin
     begin
     begin
       repeat until dbnextrow(FDBProc) = NO_MORE_ROWS;
       repeat until dbnextrow(FDBProc) = NO_MORE_ROWS;
       res := CheckError( dbresults(FDBProc) );
       res := CheckError( dbresults(FDBProc) );
+      // stored procedure information (return status and output parameters)
+      // are available only after normal results are processed
+      //if res = NO_MORE_RESULTS then GetParameters(cursor, AParams);
     end;
     end;
   until c.FSelectable or (res = NO_MORE_RESULTS) or (res = FAIL);
   until c.FSelectable or (res = NO_MORE_RESULTS) or (res = FAIL);
 
 
@@ -629,6 +633,21 @@ begin
     Fstatus := MORE_ROWS;
     Fstatus := MORE_ROWS;
 end;
 end;
 
 
+procedure TMSSQLConnection.GetParameters(cursor: TSQLCursor; AParams: TParams);
+var Param: TParam;
+begin
+  // Microsoft SQL Server no more returns OUTPUT parameters as a special result row
+  // so we can not use dbret*() functions, but instead we must use dbrpc*() functions
+  // only procedure return status number is returned
+  if dbhasretstat(FDBProc) = 1 then
+    begin
+    Param := AParams.FindParam('RETURN_STATUS');
+    if not assigned(Param) then
+      Param := AParams.CreateParam(ftInteger, 'RETURN_STATUS', ptOutput);
+    Param.AsInteger := dbretstatus(FDBProc);
+    end;
+end;
+
 function TMSSQLConnection.RowsAffected(cursor: TSQLCursor): TRowsCount;
 function TMSSQLConnection.RowsAffected(cursor: TSQLCursor): TRowsCount;
 begin
 begin
   if assigned(cursor) then
   if assigned(cursor) then

+ 2 - 1
packages/fcl-db/src/sqldb/mssql/readme.txt

@@ -41,7 +41,7 @@ Compiling FreeTDS with iconv support:
 
 
 Using in Lazarus:
 Using in Lazarus:
 =================
 =================
-1. Put on the form TSQLConnector and set property ConnectorType=MSSQLServer
+1. Put on the form TMSSQLConnection or TSQLConnector and set property ConnectorType=MSSQLServer
 2. Put into uses clause mssqlconn unit
 2. Put into uses clause mssqlconn unit
 
 
 
 
@@ -49,6 +49,7 @@ Known problems:
 ===============
 ===============
 - CHAR/VARCHAR data truncated to column length when encoding to UTF-8 (use NCHAR/NVARCHAR instead or CAST char/varchar to nchar/nvarchar)
 - CHAR/VARCHAR data truncated to column length when encoding to UTF-8 (use NCHAR/NVARCHAR instead or CAST char/varchar to nchar/nvarchar)
 - Multiple result sets (for example when SP returns more than 1 result set only 1st is processed)
 - Multiple result sets (for example when SP returns more than 1 result set only 1st is processed)
+- Output parameters of stored procedure are not returned. See FreeTDS FAQ: "I'm not getting my output parameters returned, but I seem to be doing everything right!"
 - DB-Library error 10038 "Results Pending" - set TSQLQuery.PacketRecords=-1 to fetch all pendings rows
 - DB-Library error 10038 "Results Pending" - set TSQLQuery.PacketRecords=-1 to fetch all pendings rows
 - BLOB data (IMAGE/TEXT columns) larger than 16MB are truncated to 16MB - (set TMSSQLConnection.Params: 'TEXTSIZE=2147483647' or execute 'SET TEXTSIZE 2147483647')
 - BLOB data (IMAGE/TEXT columns) larger than 16MB are truncated to 16MB - (set TMSSQLConnection.Params: 'TEXTSIZE=2147483647' or execute 'SET TEXTSIZE 2147483647')
   (create temporary stored procedures for prepared statements)
   (create temporary stored procedures for prepared statements)