After rewind mysql query results, not working to re-use query - php

I'm relatively new to mysql/php rewind. I am execuring a query, and after I mark the current data set and re-wind it, I need to run the same set to run shell scripts that take a really long time. I'm going to run the same script as a cron in a few minutes, so I can mark another set and know I'm fetching a different data set to run the slow shell scripts on. For some reason, the rewind isn't working, so it's not using the data set twice:
if(!($stmt = $mysqli->prepare("SELECT node, model FROM Table WHERE vendor = 'Calix' AND model in ('C7','E7') AND ((update_status NOT in ('u') OR (update_time IS NULL) OR ((DATEDIFF(NOW(),SW_ver_update_time)>14)) )) LIMIT 100"))) //AND ping_reply IS NULL AND software_version IS NULL
{
echo "Prepare failed: (" . $mysqli->errno . ") " . $mysqli->error;
}
if(!$stmt->bind_result($ip, $model))
{
echo "Binding results failed: (" . $stmt->errno . ") " . $stmt->error;
}
if(!$stmt->execute())
{
$tempErr = "Error select node, model c7,e7 status: " . $stmt->error;
printf($tempErr . "\n"); //show mysql execute error if exists
$err->logThis($tempErr);
}
$stmt1 = $mysqli1->prepare("UPDATE Table SET update_status = 'u' , update_time = UTC_TIMESTAMP() WHERE node = ?");
while($stmt->fetch()) {
print "current ip: " . $ip . "\n";
$stmt1->bind_param("s", $ip);
$stmt1->execute(); //write time stamp and 'u' on ones 'in process of Updating'
}
//rewind db pointer
mysql_data_seek($stmt, 0);
//Circulate through 100 dslams fetched that we marked as in process.
//This takes a long time to execuate and will be running this script concurrently in 5 minutes
//so we need to know what we're working on so we don't fetch them again.
while($stmt->fetch()) {
print "hello current ip: " . $ip . "\n";
//will execute shell script here
//I never see hello print statement
}
I looked at mysql_data_seek but I don't see an example that uses fetch(). Can I not use fetch() after a rewind? What's the issue here? Thanks!
*Update:
I tried
$stmt->data_seek(0);
But it's still not letting me re-use that query. If anyone has a suggestion of how to get rewind to work, or a way to get around it, like storing the query results so I can re-use them without re-running the query later, that's ok too.

You can't use mysql_data_seek() with mysqli functions. Each PHP extension for MySQL is separate, and you can't use the functions from one extension with query results from another extension.
You'd want to use the equivalent function in the mysqli extension: mysqli_stmt::data_seek().
Re your comments:
You can use get_result() and then call fetch_all() on the result. This will return an array of rows, in which each row is an array of columns returned by the MySQL query.
if(!($stmt = $mysqli->prepare("SELECT node, model FROM Table WHERE vendor = 'Calix' AND model in ('C7','E7') AND ((update_status NOT in ('u') OR (update_time IS NULL) OR ((DATEDIFF(NOW(),SW_ver_update_time)>14)) )) LIMIT 100"))) //AND ping_reply IS NULL AND software_version IS NULL
{
error_log("Prepare failed: ({$mysqli->errno}) {$mysqli->error}");
die();
}
if(!$stmt->execute())
{
error_log("Error select node, model c7,e7 status: {$stmt->error}");
die();
}
if (!($result = $stmt->get_result()))
{
error_log("Error get result of select node, model c7,e7: {$stmt->error}");
die();
}
$rows = $result->fetch_all(MYSQLI_ASSOC);
I also show use of error_log() which automatically logs to your http error log. If there's an error, I call die() so the code doesn't attempt to go on to the next step. In your script, you might structure it differently, like use return instead, if there's other code to run.
Or else you can fully embrace exceptions.

Related

PHP MYSQLI prepared statement compare datetime to GetDate() err

I open a connection to my database using php and mysqli and make a few queries using prepared statements where everything works dandy but in this query where I attempt to only select rides that are in the future I am inexplicably failing as soon as I add the comparison to GETDATE()
date_default_timezone_set('America/Denver');
if(!($stmt = $con->prepare("SELECT r.destination, r.startDepartureTime, r.seats, r.priceperseat FROM ride r WHERE r.startZipCode = ? AND r.startDepartureTime > GETDATE()"))) echo "Prepare failed: (" . $stmt->errno . ") " . $stmt->error;
if(!$stmt->bind_param("i", $userZipCode)) echo "Binding parameters failed: (" . $stmt->errno . ") " . $stmt->error;
$stmt->execute();
$stmt->store_result();
$stmt->bind_result($destination,$departure,$seats,$price);
while($stmt->fetch()){
echo "Destination : $destination Departure Time : $departure Seats Available : $seats Price Per Seat : $price <br>";
}
$stmt->close();
The php error log reports that on the prepare statement line
PHP Notice: Trying to get property of non-object
and that therefore on the bind_param line we get
PHP Fatal error: Call to a member function bind_param() on a non-object
I originally was trying to use NOW() but tried all of the solutions in this thread SQL NOW() function not working properly and have had no luck.
When I run the statement without the r.startDepartureTime > GETDATE() comparison everything works fine.
And I have ensured that the startDepartureTime column in my database is of type datetime. Here is an example entry : 2016-05-21 10:24:00 that I've made sure is indeed greater than the current time and in the same zipcode to ensure that Im not just receiving an empty set.
GETDATE() is not a MYSQL Function, NOW() should be what you need
Maybe what you mean to do is use less than rather than greater than in the query r.startDepartureTime < NOW()
If the prepare fails then you need to do something more positive that just report an error. So this kind of code will work better.
Also if the prepare fails, $stmt is set to false and therefore using $stmt->errno etc will not work, and will in fact generate even more confusing error messages. So in this case you have to use the connection $con to get the errors from
$sql = "SELECT r.destination, r.startDepartureTime,
r.seats, r.priceperseat
FROM ride r
WHERE r.startZipCode = ?
AND r.startDepartureTime < NOW()";
$stmt = $con->prepare($sql);
if($stmt === false) {
echo "Prepare failed: {$con->errno} : {$con->error}";
exit;
}

PHP - Get affected rows in ADODB

I using ADODB to create a connection to my database. I update the data in my database, there is no error. The problem is that I can't get the number of affected rows by Affected_Rows(). I tried with very simple code but it is not working. Here is my code:
$sql = "UPDATE User SET Name=N'MyName' WHERE Id=1";
$conn = new COM ("ADODB.Connection") or die("Cannot start ADO");
$cs = "provider=sqloledb;"."server=localhost;database=Test;uid=Admin;pwd=123456;Max Pool Size=100";
$conn->open($cs);
//there is no error in connecting process. I can add, update, delete normally.
if($conn->Execute($sql) === false)
{
trigger_error('Wrong SQL: ' . $sql . ' Error: ' . $conn->ErrorMsg(), E_USER_ERROR);
}
else
{
echo $conn->Affected_Rows(); //<-- Error in here
}
I have read about this function in here. My code above is almost same with example here.
Is there any other way to get the number of affected rows in ADODB-PHP?
About Affected_Rows(), I don't know why it isn't working.
There is another very simple way to get the number of affected rows after execute query.
$conn->Execute($sql,$affected_rows);
echo $affected_rows;
$affected_rows return from Execute function will have value equal to number of affected rows of that query.
just for mark.
your code:
echo $conn->Affected_Rows()
is ADODB SDK methods: http://adodb.org/dokuwiki/doku.php?id=v5:reference:connection:affected_rows
NOT a native COM("ADODB.connection") method.
but i have same problem because this method return "variant Object" so i can't get the value.
i fixed this by edit SDK source file : adodb5/drivers/adodb-ado5.inc.php #44 line:
$this->_affectedRows =new VARIANT;
to:
$this->_affectedRows = null;
then Affected_Rows() method can return a real number for me.

mysqli handle prepared procedure call with multiple result sets with different columns

Is there a way to handle multiple result sets from a single prepared query when the result sets have different columns?
I have a procedure like this:
CREATE PROCEDURE usp_CountAndList (in_SomeValue int)
BEGIN
SELECT COUNT(*) AS ListCount FROM Table WHERE SomeValue = in_SomeValue;
SELECT
Name, Cost, Text
FROM Table WHERE SomeValue = in_SomeValue
ORDER BY
Name
LIMIT 25;
END
And my PHP code looks like this:
$some_value = $_POST["SomeValue"];
if($some_value != null) {
$dbh = mysqli_connect(...connection stuff...) or die ('I cannot connect to the database.');
$query = $dbh->prepare("CALL usp_CountAndList( ? );");
$query->bind_param("i", $some_value);
if($query->execute() == true) {
$meta = $query->result_metadata();
$fields = $meta->fetch_fields();
var_dump($fields);
$query->store_result();
$query->bind_result($list_count);
while($query->fetch()) {
print_r("<TR>");
print_r("<TD>" . $list_count ."</TD>");
print_r("</TR>\n");
}
$query->free_result();
$dbh->next_result();
$meta = $query->result_metadata();
$fields = $meta->fetch_fields();
var_dump($fields);
$query->store_result();
$query->bind_result($name, $cost, $text);
while($query->fetch()) {
print_r("<TR>");
print_r("<TD>" . $name . "</TD>");
print_r("</TR>\n");
}
$query->free_result();
$dbh->next_result();
}
else {
print_r("Query failed: " . $query->error . "<BR>\n");
exit(0);
}
$query->close();
$dbh->close();
}
The issue I'm running into is that it looks like I'm getting the same meta-data for the second result set, even though it is returning a completely different set of columns, which means that my second bind_result call results in the following error:
PHP Warning: mysqli_stmt::bind_result() [<a href='mysqli-stmt.bind-result'>mysqli-stmt.bind-result</a>]: Number of bind variables doesn't match number of fields in prepared statement
I've banged my head against this for a while and am just not clear on what I'm doing wrong...it almost seems like a mysqli bug. Does anyone have some example code to show how to do what I'm attempting?
Basically there are a few requirements to make this work properly...
MYSQL 5.5.3 or higher
PHP 5.3 for mysqlnd support
This is a compile time setting so if you are using shared hosting you probably cannot change this.
Basically in your example, use $query->next_result() instead of $dbh->next_result().
mysqli_stmt::next_result
I've only found one SO example of some else attempting to do this.

php pdo query fails to return result despite prepared statement being correct

I have the following php/pdo which calls a a mysql procedure which returns a filename however despite the prepared statement being correct and returning the following from a cut and pasted db query:
db query/result
> call sp_CDRbyCustomer('Wind', 'R2X', DATE(DATE_SUB(NOW(), INTERVAL 10 WEEK)), DATE(NOW()));
> +------------------------------------------------------+
> | Exported filename |
> +------------------------------------------------------+
> | '/tmp/CDR_for_Wind_20140704-20140912_1410516460.csv' |
> +------------------------------------------------------+
> 1 row in set (0.02 sec)
the php/pdo
which should return our filename is:
include('db.ini');
define('DEBUG', true);
if (DEBUG ) {
openlog("$iam", LOG_PID | LOG_ODELAY,LOG_LOCAL4);
syslog(LOG_INFO, "START OF DEBUG LOG.");
}
/***** connect to database using db.ini for credentials *****/
try {
$dbConn = new PDO('mysql:host='.$host.';dbname='.$db, $dbUser, $dbPass, array (PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION));
} catch (PDOException $e) {
print "Error!: " . $e->getMessage() . "<br/>";
die();
}
$structure_name = "'Wind'";
$cug_uid = "'R2X'";
$num_weeks = 10;
/**** Query - export file name ****/
$sqlQuery4filename = ("
call sp_CDRbyCustomer($structure_name, $cug_uid, DATE(DATE_SUB(NOW(), INTERVAL $num_weeks WEEK)), DATE(NOW()))
");
$sqlQuery4filename = preg_replace( "/\r|\n/", "", $sqlQuery4filename );
debug("01: sqlQueryfile string is '" . $sqlQuery4filename . "'");
$stmnt = $dbConn->prepare($sqlQuery4filename);
debug($stmnt);
$stmnt->execute();
$stmnt->closeCursor();
$filename = $stmnt->fetch(PDO::FETCH_ASSOC);
$filename = $filename['Exported filename'];
debug("01: filename string is '" . $filename . "'");
function debug($debug) {
if(!DEBUG) return;
print '
<div class="debug">
';
print_r($debug);
print '
</div><!-- end of debug -->
';
}
However I only ever get an empty string returned.
I have had this working, but after subversioning it I ended up with the wrong version and can no longer get it to work, anybody give me any clues to what I'm doing wrong.
You need to properly debug this:
See what the exact SQL command is you execute (I can't tell from your question).
Test the command against the database, for instance with PHPmyAdmin.
Show what the fetch() result is, before you access it as an array.
If you follow the PHP execution trial from the beginning to the end, you should be able to work out where it goes wrong.
You need to bind the output parameter. See Example #4 in the docs http://php.net/manual/en/pdo.prepared-statements.php
<?php
$stmt = $dbh->prepare("CALL sp_returns_string(?)");
$stmt->bindParam(1, $return_value, PDO::PARAM_STR, 4000);
// call the stored procedure
$stmt->execute();
print "procedure returned $return_value\n";
?>
So after much debugging and many different coding attempts I eventually retrieved teh required result.
I tried numerous attempts to use binParam but the returned result would always be a null string.
I had changed to mysql procedure to output the required filename so the mysql command SELECT #filename would provide the desired result.
I then retrieved this value with the following:
/**** Query - export file name ****/
$sql = 'call sp_CDRbyCustomer( \'' . $structure_name . '\', \'' . $cug_uid . '\', DATE(DATE_SUB(NOW(), INTERVAL ' . $num_weeks . ' WEEK)), DATE(NOW()), #filename )';
$stmnt = $dbConn->prepare($sql);
debug($stmnt);
$stmnt->execute();
$stmnt->closeCursor();
$filename_result = $dbConn->query("select #filename")->fetch();
$filename = $filename_result['#filename'];
I'm not sure if this is the best way to do this but it does produce the result I desire :-)

call stored procedure using php

i have written a basic stored procedure using mysql
DELIMITER //
CREATE PROCEDURE `sp_sel_test`()
BEGIN
SELECT * FROM category c;
END//
DELIMITER ;
now i m calling it from php
the php code is:
<?php
$txt = $_GET['id'];
$name = $_GET['name'];
$con = mysql_connect("localhost","four","password");
if (!$con)
{
die('Could not connect: ' . mysql_error());
}
mysql_select_db("fourthes_a", $con);
//$result = mysql_query("select * from new_c where name like %". $name ."% or c_name like %" . $name . "% order by name asc;");
$result = mysql_query("call sp_sel_test()");
if ($result === FALSE) {
die(mysql_error());
}
while($row = mysql_fetch_array($result))
{
echo $row['category_id'] . " " . $row['c_name'];
?>
<br />
<?php
}
mysql_close($con);
echo $txt;
?>
now its giving the error
PROCEDURE fourthes_a.sp_sel_test can't return a result set in the given context
mysql_query() returns false when the query fails. You didn't check if your sproc query succeeded, so most likely you're passing that boolean FALSE to the fetch function, which is rightfully complaining.
Rewrite your code like this, as a bare mininum, for proper error handling:
$res = mysql_query('call sp_sel_test()');
if ($res === FALSE) {
die(mysql_error());
}
Never ever assume a query succeeded. Even if the SQL syntax is perfect, there's far too many other reasons for a query to fail to NOT check if it worked.
You need to set client flags while connecting for using stored procedures with php. Use this:
mysql_connect($this->h,$this->u,$this->p,false,65536);
See MySQL Client Flags for more details. PHP MySQL does not allow you to run multiple statements in single query. To overcome this you must tell PHP to allow such queries by setting CLIENT_MULTI_STATEMENTS flag in your connection.
I know last answer was a year ago, but...
CREATE PROCEDURE sp_sel_test(OUT yourscalarvariable INT/TEXT...)
Statements that return a result set cannot be used within a stored function. This includes SELECT statements that do not use INTO to fetch column values into variables, SHOW statements, and other statements such as EXPLAIN. For statements that can be determined at function definition time to return a result set, a Not allowed to return a result set from a function error occurs (ER_SP_NO_RETSET_IN_FUNC). For statements that can be determined only at runtime to return a result set, a PROCEDURE %s can't return a result set in the given context error occurs (ER_SP_BADSELECT).
So, your select shoould be like this:
SELECT * FROM category **INTO** c;
http://www.cs.duke.edu/csl/docs/mysql-refman/stored-procedures.html

Categories