[unixODBC-support] inputOutput parameter problem in calling stored Procedure

Martin Evans martin.evans at easysoft.com
Mon Feb 16 11:06:54 GMT 2009


Bartolomeo Nicolotti wrote:

>> You turn on tracing by adding something like the following to your 
>> odbcinst.ini file:
>>
>> [ODBC]
>> Trace           = yes
>> TraceFile               = /tmp/unixodbc.log
>>
>> The code you show only does prepare and nothing else. Usually, if you 
>> were calling a procedure that takes a parameter you would do something
>> like:
>>
>> SQLPrepare({ call myproc(?)})
>>   optionally SQLNumParams but some drivers don't support it
>> SQLBindParameter(1, variable);
>> SQLExecute
>>
>> ">>> ExecSQL.Parameters.Count:1 " looked interesting - it suggested 
>> someone knew there was a parameter. Guess you'll have to look closer at 
>> Mono.

> 
> I'll repeat: the c# code I've written to test is:

and I'll repeat, the code needs to call SQLPrepare, SQLBindParameter and 
SQLExecute in that order - how Mono does it I don't know but looking at 
the code you provide suggests:

> 
> 				string comandoAS2="{call QGPL.PROVACS('AA')}";
> 				comandoAS2="{CALL GIANLUCA.Provacs( ? )}";
> 				//string strcomando2="CALL "+ comandoAS2;
> 				OdbcCommand command2 = conn.CreateCommand();
> 				command2.CommandText= comandoAS2;
> 				command2.CommandType=CommandType.StoredProcedure;
> 
> 				OdbcParameter param1 = command2.Parameters.Add("PAR1", OdbcType.Char,
> 2);
> 				param1.Direction= ParameterDirection.InputOutput;
> 				param1.Value="AA";
> 				
> 				System.Console.WriteLine("Eseguo:"+comandoAS2);
> 				command2.ExecuteNonQuery();
> 				System.Console.WriteLine("Ottengo:"+command2.Parameters[0].Value);
> 
> 
> The SQLBindParameter you say with mono is command2.Parameters.Add
> When command2.ExecuteNonQuery() is executed this method from the mono source
> is executed:
> 
> 		private int ExecuteNonQuery (bool freeHandle) 
> 		{
> 			System.Console.WriteLine("ExecuteNonQuery");
> 			int records = 0;
> 			if (Connection == null)
> 				throw new InvalidOperationException ("No open connection");
> 			if (Connection.State == ConnectionState.Closed)
> 				throw new InvalidOperationException ("Connection state is closed");
> 			// FIXME: a third check is mentioned in .NET docs
> 
> 			ExecSQL(CommandText);
> 
> and the ExecSQL is:
> 
> 		private void ExecSQL (string sql)
> 		{
> 			OdbcReturn ret;
> 			System.Console.WriteLine("ExecSQL.Parameters.Count:"+Parameters.Count);
> 			if (! prepared && Parameters.Count <= 0) {
> 				System.Console.WriteLine("ExecSQL not prepared || Parameters.Count >0
> ");
> 
> 				ReAllocStatment ();
> 				
> 				ret = libodbc.SQLExecDirect (hstmt, sql, libodbc.SQL_NTS);

If it calls this SQLExecDirect it is wrong or you have called the wrong 
methods in Mono - I don't use Mono, I was just trying to help you.


> 				if ((ret != OdbcReturn.Success) && (ret != OdbcReturn.SuccessWithInfo)
> &&
> 				    (ret != OdbcReturn.NoData))
> 					throw connection.CreateOdbcException (OdbcHandleType.Stmt, hstmt);
> 				return;
> 			}
> 
> 			if (!prepared){
> 				System.Console.WriteLine( "Just before Prepare" );
> 				Prepare();
> 			}
> the Prepare is executed and in the Prepare we got an error from DB2 iSeries
> (mind that this version of DB2 is different from the i386 version)
> 
> 		void Prepare()
> 		{
> 			System.Console.WriteLine("OdbcCommand.Prepare: begins!");
> 			ReAllocStatment ();
> 			
> 			OdbcReturn ret;
> 
> 			System.Console.WriteLine("OdbcCommand.Prepare: Just before
> libodbc.SQLPrepare");
> 			ret = libodbc.SQLPrepare(hstmt, CommandText, CommandText.Length);
> 			System.Console.WriteLine("OdbcCommand.Prepare: Just after
> libodbc.SQLPrepare");
> 
> 			if ((ret!=OdbcReturn.Success) && (ret!=OdbcReturn.SuccessWithInfo)){
> 				System.Console.WriteLine("OdbcCommand.Prepare: Throwing
> connection.CreateOdbcException");
> 				throw connection.CreateOdbcException (OdbcHandleType.Stmt, hstmt);
> 			}
> 			prepared = true;
> 			System.Console.WriteLine("OdbcCommand.Prepare: ends!");
> 		}
> 
> I've switched on trace and the method called is:
> 
> 
> [ODBC][11917][SQLPrepareW.c][126]
> 		Entry:            
> 			Statement = 0x83df158            
> 			SQL = [{CALL GIANLUCA.Provacs( ? )}][length = 28]
> [ODBC][11917][SQLPrepareW.c][300]
> 		Exit:[SQL_ERROR]
> 		DIAG [42S02] [IBM][iSeries Access ODBC Driver][DB2 UDB]SQL0204 - PROVACS
> in GIANLUCA di tipo *N non trovato.

It should be ok to call SQLPrepare like this but I see all the examples 
on IBMs web site do not use the ODBC syntax for calling procs i.e., they do:

SQLPrepare('call gianluca.provacs(?)')

> 
> the error means that the prepare is searching a PROVACS without parameters

When I looked up SQL0204 on IBMs site it suggests this error means 
provacs is undefined in gianluca.

> As I've already said the CALL GIANLUCA.PROVACS('AA') works.

I understood that. I wonder if you have overloaded provacs? Have you got 
more than one version of provacs that take different arguments?

> The problem is with the question mark ? that doesn't seem to be recognized
> as a parameter. this is strange as from jdbc we use ? with no problem
> 
> Do you know how can I use named parameters
> 
> Many thanks 
> 
> Best regards
> 
> 

Martin
-- 
Martin J. Evans
Easysoft Limited
http://www.easysoft.com


More information about the unixODBC-support mailing list