Explorar o código

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 %!s(int64=11) %!d(string=hai) anos
pai
achega
9d2933d752

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

@@ -66,6 +66,7 @@ type
     function CheckError(const Ret: RETCODE): RETCODE;
     procedure Execute(const cmd: string); overload;
     procedure ExecuteDirectSQL(const Query: string);
+    procedure GetParameters(cursor: TSQLCursor; AParams: TParams);
     function TranslateFldType(SQLDataType: integer): TFieldType;
     function ClientCharset: TClientCharset;
     function AutoCommit: boolean;
@@ -467,7 +468,7 @@ begin
     try
       Prepare(format('SELECT cast(%s as varchar), @@version, user_name()', [VERSION_NUMBER[IsSybase]]), nil);
       Execute(nil);
-      if Fetch then
+      while Fetch do
       begin
         Put(1, FServerInfo.ServerVersion);
         Put(2, FServerInfo.ServerVersionString);
@@ -620,6 +621,9 @@ begin
     begin
       repeat until dbnextrow(FDBProc) = NO_MORE_ROWS;
       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;
   until c.FSelectable or (res = NO_MORE_RESULTS) or (res = FAIL);
 
@@ -629,6 +633,21 @@ begin
     Fstatus := MORE_ROWS;
 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;
 begin
   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:
 =================
-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
 
 
@@ -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)
 - 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
 - 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)