Newsgroup: it.comp.www.php
Titolo: Esecuzione "stored" su AS400 con parametri IN OUT

Salve,
 
al lavoro mi capita di dovermi interfacciare con una struttura (hardware e sistemisti)che fornisce servizi as400 e con un altra che gestisce i server linux +php+mysql definiti di "sviluppo" e "servizio".
 
Per vari motivi la connessione , l'unica possibile verso as400 è ODBC.
 
Sono riuscito dopo vari ticket a farmi configurare lato linux una connessione funzionante.
Lato as400 mi han dato un documento che riporta (i nomi ovviamente non son quelli reali)
 
DSN PIPPO
Sono create due "Stored Procedure" (proprio così scritto)...
 
Una delle "stored"
 
ST3PIPPO.GAPIPPO1
 
IN Codice Fornitore CHAR(6)
OUT Ragione sociale1 CHAR(30)
OUT Ragione sociale2 CHAR(30)
OUT Codice errore CHAR(7)
OUT Descrizione errore CHAR(60)
 
La documentazione mi dice che se passo un codice valido mi valorizza i valori di ritorno altrimenti COMUNQUE mi restituisce un codice di errore
 
Il codice php
$as400connectResult = odbc_connect($dsn, $user, $password);    
    if (!$as400connectResult) { 
        echo 'Errore connessione AS400.';
        $error .= "\n\r >> [".date("Ymd H:i:s")." - SERVER: $HOST ] *** Errore connessione AS400.";
        die($error);
    }
 
Dopo vari ticket come detto  lancio questo codice e si connette
 
 
Quindi passo alla seconda parte...provare con un prepared statment o una chiamata diretta mi da il medesimo errore
 
 
Il codice
$IN1=Codice che so esiste nell'as400
 
$call = "\"CALL ST3PIPPO.GAPIPPO1 ($IN1, ?, ?, ?, ?) \"";
 
$callResult = odbc_exec($as400connectResult,"{$call}");
            $error = odbc_error($as400connectResult);
            $errormsg = odbc_errormsg($as400connectResult);
            if (!$callResult) {
              echo("\nErrore: $error - $errormsg<br/>\n");
              exit;
            }
 
L'errore è
Errore: 37000 - [unixODBC][IBM][System i Access ODBC Driver][DB2 for i5/OS]SQL0104 - Token "CALL ST3PIPPO.GAPIPPO1 (11157 was not valid. Valid tokens: ( CL END GET SET CALL DROP FREE HOLD.
 
 
Se cambio la $call in
$call = "CALL ST3PIPPO.GAPIPPO1($IN1, ?, ?, ?, ?) ";
 
Errore: S0002 - [unixODBC][IBM][System i Access ODBC Driver][DB2 for i5/OS]SQL0204 - GAPIPPO1 in ST3PIPPO type *N not found.
 
 
Se chiamo l'assistenza AS400 mi dice: abbiamo verificato la procedura è corretta ....arrangiati ...è un problema tuo di configurazione client! La struttura Linux  , i loro sistemisti, ne sanno meno di me...ossia una mazza!
 
Alle mie obiezioni....ma si USA CALL? é Corretto? Ma non è che si deve impostare imposta prima il DB o qualche altro parametro?....non sanno che dire!...e non rispondono!
 
 
Mi sà aiutare qualcuno????
 
Grazie infinite.

 Mi sà aiutare qualcuno?
 
Io stamperei il valore di $call per verificare il quoting.
 
Se separi odbc_exec in _prepare ed _execute puoi localizzare meglio 
l'errore, inoltre tieni conto che da [1]:
"""
Some databases (such as IBM DB2, MS SQL Server, and Oracle) support 
stored procedures that accept parameters of type IN, INOUT, and OUT as 
defined by the ODBC specification. However, the Unified ODBC driver 
currently only supports parameters of type IN to stored procedures.
[…]
If you need to call a stored procedure using INOUT or OUT parameters, 
the recommended workaround is to use a native extension for your 
database (for example, mssql for MS SQL Server, or oci8 for Oracle).
"""
 
E tu hai parametri OUT.
 
 
[1] 
http://www.php.net/manual/en/function.odbc-prepare.php
 
 
-- 
Andrea
 

Innanzitutto ti ringrazio.
 
Punto 1) Il quoting è uno dei problemi. Non lo so ....sono andato un po a naso un po a info trovate a giro per la rete. Ho messo apici singoli...virgolette....o fatto un cast (string) e passato i parametri.Tutto appare inutile. E poi so na mazza DB2 come usa le stored sono andata a richiamarle come faccio con MySQL o SqlServer.
 
Il punto 2 l'avevo letto anche io ma speravo in una lungimiranza di qualche libreria installata.
Il punto 2 è insormontabile. Prima di tutto perchè non sono un sistemista, secondo perchè il sistema non è mio.
 
Mi ha spiegato, l'help desk LAMP, che librerie native ASSOLUTAMENTE non ne installano perchè devono ricompilare php e per loro è impattante un casino sui servizi erogati e perchè il dirigente del dipartimento non vuole infilarsi in questi eventuali casini per una stored(come avrai capito è una multi nazionale parecchio multi e poco nazionale.....e che prima d'ora nessuno nella struttura locale, aveva richiamato da php una stored procedure su as400... men che meno con parametri!).
 
Mi confermi che posso spiegare , al mio capo, che non si può chiamare quella stored perchè non c'è l'infrastruttura corretta? Ossia ODBC non può chiamare Stored che ritornano valori?
 
Grazie della tua disponibilità! 

 Salve,
 
vedi se quesro esempio pu� esserti utile
 
 
<?
define("DB2_HOST", "10.0.1.232");
define("DB2_NAME", "DBNAME");
define("DB2_USER", "DBUSER");
define("DB2_PASS", "password");
 
/**
  * Creates a PDO connection and executes a stored procedure
  * using bound values and parameters
  * Returns an associative array
  * 		array("CNUMBER", "CNAME", "CEMAIL", "CPHONE")
  *
  * If error, status1 = error, status2 = cause
  *
  * @param string $strContactNumber
  * @return array
  */
function getContact($strContactNumber)
{
	$arrContact = array();
	$strContactNumber = strtoupper($strContactNumber);
	// construct the connection string
	$dbName = DB2_NAME;
	$dbHost = DB2_HOST;
	$dbUsername = DB2_USER;
	$dbPassword = DB2_PASS;
 
	// odbc is used to tell ODBC what driver set to use
	$connectionString = "odbc:DRIVER={iSeries Access ODBC Driver}; ".
						"SYSTEM={$dbHost}; ".
						"DATABASE={$dbName}; ".
						"UID={$dbUsername}; ".
						"PWD={$dbPassword}; ";
 
	$intTries = 0;
 
	// attempt to create a PDO connection
	// try at least 5 times to connect
	while( $intTries <= 5 )
	{		
		// increment the number of connection attempts
		$intTries++;
 
		try
		{
		    $dbh = new PDO($connectionString, "", "");
 
		}	//end try
 
		catch (PDOException $e)
		{
		    $arrAvailability["CNUMBER"] = $strContactNumber;
		    $arrAvailability["CNAME"] = "Error";
		    $arrAvailability["CEMAIL"] = "";
		    $arrAvailability["CPHONE"] = "";
		    $dbh = null;
		}	//end catch
 
		// if PDO was created, exit the loop
		if( $dbh )
			break;
 
	}	//end while loop
 
	// if PDO object was created, then run the statement
	if( $dbh )
	{
		// execute a stored procedure
		$sql = "call TOSLIB.SP_CONTACT ( :CNUMBER, :CNAME, :CEMAIL, :CPHONE)";
 
		// create parameter variables
		$strContactName = "";
 
		$strContactEmail = "";
 
		// create a prepared statement
		$statement = $dbh->prepare($sql);
 
		// bindValue sets the value of the named parameter
		$statement->bindValue(':CNUMBER', $strContactNumber, PDO::PARAM_STR);
 
		// bind the parameters to the statement
		// bound parameters allows you to see the final result
		$statement->bindParam(':CNAME', $strContactName, PDO::PARAM_STR, 25);
 
		$statement->bindParam(':CEMAIL', $strContactEmail, PDO::PARAM_STR, 255);
 
		$statement->bindParam(':CPHONE', $strContactPhone, PDO::PARAM_STR, 15);
 
		// now execute the statement, the bound php variables will 
automagically be updatd
		$blnExecuted = $statement->execute();
 
		// if the statement executed, then get the status results
		if($blnExecuted)
		{
			// if there's a value, remove the special character at the end
			if( strlen(trim($strContactName)) > 0 )
			{
				// remove the last character
				$strContactName = substr($strContactName, 0, 24);
 
			}	//end if
 
		    // if there's a value, remove the special character at the end
			if( strlen(trim($strContactEmail)) > 0 )
			{
				// remove the last character
				$strContactEmail = substr($strContactEmail, 0, 254);
 
			}	//end if
 
		    // if there's a value, remove the special character at the end
			if( strlen(trim($strContactEmail)) > 0 )
			{
				// remove the last character
				$strContactPhone = substr($strContactPhone, 0, 14);
 
			}	//end if
 
		    $arrAvailability["CNUMBER"] = $strContactNumber;
 
			$arrAvailability["CNAME"] = $strContactName;
 
		    $arrAvailability["CEMAIL"] = $strContactEmail;
 
		    $arrAvailability["CPHONE"] = $strContactPhone;
 
		}	//end if
 
		// else the statement failed, add error description
		else
		{
			$arrAvailability["CNUMBER"] = $strContactNumber;
 
		    $arrAvailability["CNAME"] = "Error";
 
		    $arrAvailability["CEMAIL"] = "";
 
		    $arrAvailability["CPHONE"] = "";
 
		}	//end else
 
	}	//end if
 
	return $arrAvailability;
 
}	//end function
 
?>