-1

I am iterating rows of a csv file.

On row 1, I call stored procedure (import_extended_data_sp) and it succeeds.

On row 2, the call fails with :

Strict Standards mysqli::next_result(): There is no next result set.

However, with the call being exactly the same as the first, I am struggling to see why ?

I have now hard coded test values as parameters, and checked that the Sproc has no issue with the same values being given twice.

It still fails on the second call !?

Am wondering if there is some nuance of mysqli, where I need to clear or reset something before making the second call ?

<?php include("cnn.php");?>    
<?php include("fn_db.php");?>

# ... get csv file (skipped for brevity) #

while($row = fgetcsv($file_data))
{
    $line = array_combine($head, $row);
       
    # This call works on every loop - no issues
    $id = placemark_to_db($mysqli,$v_header,$line['id_placemark'],$line['name'],$line['swim_type'],$line['latitude'],$line['longitude'],$line['description']);
        
    # This next line only succeeds on first call, but fails on next while loop
    $x = xtended_to_db($mysqli,'99','[{"xtra":"oo"}]');
} 

** fn_db.php >> xtended_to_db**

function xtended_to_db($cn,$id,$jsonarray){
    # procedure returns a rowcount in output parameter

    $cn->multi_query( "CALL import_extended_data_sp($id,'$jsonarray',@out);select @out as _out");
    $cn->next_result();
    $rs=$cn->store_result();
    $ret = $rs->fetch_object()->_out;
    $rs->free(); 
    return $ret;
}

cnn.php

<?php
$mysqli = new mysqli("xxx.xxx.xxx.xxx","mydb","pass","user");
// Check connection
if ($mysqli -> connect_errno) {
  echo "Failed to connect to MySQL: " . $mysqli -> connect_error;
  exit();
}
?>
Dharman
  • 30,962
  • 25
  • 85
  • 135
SimonB
  • 962
  • 1
  • 14
  • 36
  • Which version of PHP are you using? I can't reproduce this error. If I am not mistaken this was some kind of problem with really old PHP versions. – Dharman Dec 08 '20 at 23:47
  • Ok, I have done my research. It turns out this bug was only fixed in PHP 7.4. If you are still using PHP 7.3 then you need to call `more_results()` just like the error says. If you are using anything older than PHP 7.3 then you really need to consider upgrade. – Dharman Dec 09 '20 at 00:20
  • I've just upgraded to 7.4 and same error. This still wouldn't explain why 1 call succeeds and the 2nd fails. Surely such a bug would fail both calls? – SimonB Dec 09 '20 at 00:36
  • Yeah, you have more problems with that function. Basically when you call `multi_query` then you need to process all results manually, paying close attention to the results. Given that you have no `store_result` before `next_result` it will fail. I really do not recommend using `multi_query()` for anything – Dharman Dec 09 '20 at 00:39
  • Reference: https://stackoverflow.com/a/22469722/2943403 @SimonB I will state that I never use this function in any of my projects. It was more of a passing fad for me. The function does not support parameterized statements, so it is not advisable for any cases when you are incorporating variables into your sql. Consider Dharman's advice. – mickmackusa Dec 09 '20 at 00:55

1 Answers1

1

The best way to fix this error is to avoid multi_query() altogether. While it might sound like a reasonable use case with stored procedures, the truth is this function is mostly useless and very dangerous. You can achieve the same result using the normal way with prepared statements.

function xtended_to_db(mysqli $cn, $id, $jsonarray) {
    $stmt = $cn->prepare('CALL import_extended_data_sp(?,?,@out)');
    $stmt->bind_param('ss', $id, $jsonarray);
    $stmt->execute();

    $stmt = $cn->prepare('select @out as _out');
    $stmt->execute();
    $rs = $stmt->get_result();
    return $rs->fetch_object()->_out;
}

If you are stuborn and you want to keep on using multi_query() then you need to be more careful with how you fetch results. This function is extremely difficult to get right. I am not going to show you how to fix multi_query() as I consider it too dangerous with variable input.

One last note, you really should think about getting rid of stored procedures. They are cumbersome and offer pretty much no benefit. There definitely is a better way to achieve what you want rather than calling stored procedure from PHP, but without seeing its contents I can't give you better advice.

Dharman
  • 30,962
  • 25
  • 85
  • 135
  • Just remember [you cannot use prepare if a cursor is used in the stored procedure](https://stackoverflow.com/a/61291581/285587). Though I doubt there is any cursor in the procedure that simply imports a csv. and of course the best recommendation will be to just to get rid of a stored procedure completely – Your Common Sense Dec 09 '20 at 05:34
  • Oh my, to whom I am telling that. Just followed the links on bugs.php.net, so you're behind the fix. And as far as I get it, a workaround is to use store_result isntead of get_result, right? – Your Common Sense Dec 09 '20 at 09:23
  • @your lol, yes. If cursors are used then you need to fetch data row by row using the fetch method. There are a lot of complications when it comes to stored procedures. It's better not to use them at all. – Dharman Dec 09 '20 at 10:40
  • Dharman, thanks, your code seems to have fixed the issue - I shall do some more reading up to better understand the issues you pointed out :) As for stored procedures, that'd be a whole other discussion - personally I'll keep using database tools to manage my database, seriously cannot imagine PHP doing what my Stored Procs do, at least efficiently ;) – SimonB Dec 09 '20 at 15:56