PDA

View Full Version : Stored Procedure, PHP(Extern) und das Result Set



bussibaer
06-09-10, 17:59
Hallo zusammen,

ich rufe eine Stored Procedure auf einer iSeries V5R3 mittels PHP über ODBC auf:


CREATE PROCEDURE RAUSER1.RTVWTRINF (
IN VARINPUT CHAR(20) )
DYNAMIC RESULT SETS 1
LANGUAGE RPGLE
SPECIFIC RAUSER1.RTVWTRINF
NOT DETERMINISTIC
MODIFIES SQL DATA
CALLED ON NULL INPUT
EXTERNAL NAME 'RAUSER1/RTVWTRINF'
PARAMETER STYLE GENERAL ;
Das RPGLE Programm wird auch aufgerufen und ausgeführt. Dieses Programm soll mit Hilfe des API QSPROUTQ Informationen über eine Druckerwarteschlange zurück liefern.

Am Ende des Programms mache ich:


C/exec sql
c+ SET RESULT SETS FOR RETURN TO CLIENT ARRAY :pWtrE FOR 1 ROWS
C/end-exec um mir das ermittelte Array(das auch Inhalt hat) an mein Script zurück zu geben.
Aber im PHP kommt kein Result Set an.

Hat vielleicht jemand eine Idee woran das liegt? Falls noch mehr Informationen benötigt werden, bitte Bescheid sagen.

Danke schon mal für eure Hilfe.

Fuerchau
06-09-10, 19:39
Die PHP-Syntax kenn ich nicht, aber ich denke, der Unterschied liegt im Aufruf des Statements.
Statement.Execute gibt kein Resultset zurück, Statement.Open liefert ein Resultset.
Auch wenn du eine Prozedur aufrufst, die aber ein Resultset liefert, musst du Open verwenden.

B.Hauser
07-09-10, 06:17
@bussibaer:

Siehst Du das Result Set, wenn Du die Prozedur im iSeries Navigator - Run an SQL Skript/Eine Prozedur ausführen aufrufst?

Vielleicht hilft Dir auch der folgende Abschnitt aus der SQL Reference weiter:

TO CLIENT
Specifies that the cursor can return a result set to the client application. This cursor is invisible to any intermediate nested procedures. If a function or trigger called the procedure either directly or indirectly, result sets cannot be returned to the client and the cursor will be closed after the procedure finishes.

TO CALLER
Specifies that the cursor can return a result set to the caller of the procedure. For example, if the caller is a client application, the result set is returned to the client application.


Birgitta

KM
07-09-10, 07:21
Hallo,

lass doch mal den Zusatz FOR RETURN TO CLIENT weg. Der Rest sieht in Ordnung aus.

Zeige evtl. auch mal den PHP-Teil.

Gruß,
KM

bussibaer
07-09-10, 15:28
@Fuerchau,

leider habe ich keine irgendwie geartete open Anweisung in der PHP-Referenz gefunden.

@Birgitta

Das mit dem OpsNav war eine gute Idee, wenn ich da die Prozedur aufrufe, dann erhalte ich das Result Set zurück. Ich habe vorher den SET RESULT SETS mal auf RETURN TO CALLER geändert, leider nicht bei meinem Script. Aber wenn ich das richtig in Erinnerung habe, dann kommuniziert der OpsNav über JDBC-Treiber und nicht über den ODBC-Treiber. Ich weiß nicht, ob das irgendwelchen Einfluss hat.

@KM

Als erstes hatte ich schon, wie von dir vorgeschlagen den SET RESULT SETS ohne das FOR RETURN TO CLIENT gemacht. Da klappte der Aufruf zumindest auch.

Hier mal die Teile des Aufrufs:
Nicht nervös machen lassen, ich habe den Prozedure Namen geändert, um zu sehen ob der Aufruf auch eindeutig erfolgt.
1. Definition des Calls im Script:


$sql = "CALL RAUSER1.PRCWTRINF (WRITER=RAUOUT01 RAUSER1 )";
if ( !$db->sql_procedure($sql) )

/*$sql = "CALL RAUSER1.PRCWTRINF ('RAUOUT01 RAUSER1 ')";
if ( !$db->sql_query($sql) )*/
{
$db_error = $db->sql_error();
$error_status = TRUE ;
$message[$message_counter]["errtxt"] = $lang['error_sql'] . $db_error['message'] . "\nSQL: " .....
$message_counter++ ;
}
else
{
$obj_array = $db->sql_fetchrow($sql_result);
$db->sql_freeresult($sql_result);
print_r($obj_array);
}
Ich habe den ERROR-Teil mal ein bisschen gekürzt, damit er hier nicht das design zerreißt. ;)

Das Zurück geben der Daten ist der gleiche Aufruf, den ich auch bei normalen SQL-Abfragen verwende, und die funktionieren Super.

Hier der eigentliche Aufruf:


function sql_procedure($query = '')
{
$this->last_query_text = $query;
$p_start = '(';
$p_end = ')';
$p_equal = '=';

if ($query != '')
{
$no_parm = true;
$parm_start = 0;
$start_found = false;
$parm_end = 0;
$end_found = false;

// check for parameters on string
if ( stripos($query, $p_start) !== false )
{
$parm_start = stripos($query, $p_start);
$start_found = true;
}
if ( stripos($query, $p_end) !== false )
{
$parm_end = stripos($query, $p_end);
$end_found = true;
}

// No parameters or error on building
if ( $start_found and $end_found )
{
$no_parm = false;
}
else
{
if ( !$start_found and !$end_found )
{
}
else
{
return false;
}
}

if ( !$no_parm )
{
$var_string = substr($query, $parm_start+1, $parm_end - $parm_start - 1);
$cmd_string = substr($query, 0, $parm_start - 1);

$exp_array = explode(",", $var_string);
$count_var = count($exp_array);


$x = 0;
foreach( $exp_array as $exp_element )
{
$exp_element = trim($exp_element);
if ( stripos($exp_element, $p_equal) !== false )
{
$exp_delimiter = stripos($exp_element, $p_equal);
$par_array[$x] = substr($exp_element, $exp_delimiter + 1, strlen($exp_element) - $exp_delimiter - 1);
}
else
{
$par_array[$x] = '';
}
$x++;
}
//$this->testvar[] = $par_array;

$var_string = '(';
for( $i=1; $i <= $count_var; $i++ )
{
$var_string .= '?';
if ( $i < $count_var )
{
$var_string .=',';
}
}
$var_string .= ')';

$query = $cmd_string . ' ' . $var_string;
}

// Execute the preapare statement
if ( ($this->prepare_result = @odbc_prepare($this->db_connect_id, $query)) === false )
{
$this->sql_error($query);
$this->error_connect_id = $this->db_connect_id;
return false;
}
else
{
if ( !$no_parm )
{
if ( ($this->query_result = @odbc_execute($this->prepare_result, $par_array)) === false )
{
$this->sql_error($query);
$this->error_connect_id = $this->db_connect_id;
}
}
else
{
if ( ($this->query_result = @odbc_execute($this->prepare_result)) === false )
{
$this->sql_error($query);
$this->error_connect_id = $this->db_connect_id;
}
}
}
}
else
{
return false;
}

return ($this->query_result) ? $this->query_result : false;
}

bussibaer
08-09-10, 08:57
@All,

habe eben meinen Fehler gefunden, lag wie so oft, zwischen den Ohren des Programmierers.

Wenn ich im PHP keine Ergebniskennung ermittle, weiß das Script natürlich auch nicht, was es zurück holen soll. Außerdem habe ich festgestellt, das ich meine Procedure-Routine nicht brauche dafür. Sorry, das ich euch die Zeit gestohlen habe. :rolleyes: