From 9d2933d7521cdf97e3dfc6a13ad49644b042cd0c Mon Sep 17 00:00:00 2001 From: lacak Date: Wed, 2 Apr 2014 08:57:25 +0000 Subject: [PATCH] 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 - --- packages/fcl-db/src/sqldb/mssql/mssqlconn.pp | 21 +++++++++++++++++++- packages/fcl-db/src/sqldb/mssql/readme.txt | 3 ++- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/packages/fcl-db/src/sqldb/mssql/mssqlconn.pp b/packages/fcl-db/src/sqldb/mssql/mssqlconn.pp index ac06cbe982..a30532d7a5 100644 --- a/packages/fcl-db/src/sqldb/mssql/mssqlconn.pp +++ b/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 diff --git a/packages/fcl-db/src/sqldb/mssql/readme.txt b/packages/fcl-db/src/sqldb/mssql/readme.txt index 3b1f143ee1..9c4f63a8c6 100644 --- a/packages/fcl-db/src/sqldb/mssql/readme.txt +++ b/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)