Why PDO connection sowing "SQLSTATE[HY000]: General error"? - php

I am using pdo connection. I am trying to run a delete query but it is showing this message in the browser
*SQLSTATE[HY000]: General error*
Here is my query:
$user_id = $_POST['user_id']; $result = query($conn, "DELETE FROM user WHERE user_id = '$user_id'");
I don't know why happening this. Any kind of help will be appreciated.Thanks

I think there is a query() function does not exists in PHP .. It should be mysql_query or mysqli_query
Using Mysql query is bad because it is depreciated in Updated version of php
$result = mysqli_query($conn, "DELETE FROM user WHERE user_id = '$user_id'");
//So using mysqli :)
$result = mysqli_query($conn, "DELETE FROM user WHERE user_id = '$user_id'");

Per MySQL 5.5.35 source code, sql/sql_prepare.cc:
bool
Reprepare_observer::report_error(THD *thd)
{
/*
This 'error' is purely internal to the server:
- No exception handler is invoked,
- No condition is added in the condition area (warn_list).
The diagnostics area is set to an error status to enforce
that this thread execution stops and returns to the caller,
backtracking all the way to Prepared_statement::execute_loop().
*/
thd->stmt_da->set_error_status(thd, ER_NEED_REPREPARE,
ER(ER_NEED_REPREPARE), "HY000");
m_invalidated= TRUE;
return TRUE;
}
It appears that your error (SQL state HY000) will happen when there is a wrong sequence of prepare/execute statements. Double-check our logic to make sure you are properly using prepared statements, e.g properly fetching all of the results after the call to query() before calling it again.
If you cannot figure it out, isolate the problem to a minimal, complete, and verifiable example (https://stackoverflow.com/help/mcve), and post the code here.
UPDATE:
Does the problem go away (or do you at least get a meaningful error message) if you do
$conn->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
prior to the query?

Related

MySql Trigger when attempting to insert into the same table and selecting the last record of the same data

I have a table T1 and firing a trigger after insert on T1 and calling external PHP programm using UDF where the app is looking for a last inserted data and do a action on condition base but it is not working as expected.. Please help as I guess that we cannot select the data from the same table where we are firing a trigger?? Is it so?
TRIGGER
DELIMITER ##
CREATE TRIGGER CALL
AFTER INSERT ON call_test
FOR EACH ROW
BEGIN
DECLARE cmd CHAR(255);
DECLARE result int(10);
SET cmd=CONCAT('php /var/www/html/test/call.php');
SET result = sys_exec(cmd);
END;
##
DELIMITER ;
call.php
function connect_db() {
$db_connection = mysql_connect("localhost","root","test") or die (mysql_error());
$db_select = mysql_select_db('testdb') or die (mysql_error());
}
connect_db();
$sql2=mysql_query("SELECT * FROM call_test ORDER BY createtime desc limit 1") or die(mysql_error());
$res = mysql_fetch_array($sql2);
if(strstr($res['name'],'go')!=false)
{
echo "inserted";
//sleep(10);
$sql4=mysql_query("insert into call_test_auto (name,createtime) values ('from UDF automatic2','".$today."')") or die(mysql_error());
}
else
{
echo "not inserted";
}
yes you can Sam. It is in row aliased by NEW. See Trigger Syntax and Examples
Your task is to do whatever is necessary to get things into variables so that you can concat and call your UDF with them as command line parameters. As seen here, where that gentleman sent a command line argument of Sarbajit to his C program he had compiled.
In your case, you are just calling PHP and nothing is happening!
Enabling sys_exec
It is not as if your average Joe is likely to even going to survive the call to sys_exec() without receiving a Syntax Error. See This Question on the Stack and the link for github at top of that question.
Things Failing silently
Remember that mysql Triggers and Events (as in Create Event) run and succeed to your wishes or don't, but do so silently. You might not even know that the above Syntax Error occurred. That would not be the case for a Stored Procedure run by a user in a query that had error reporting.
Of course, a Trigger or Event could call a Stored Procedure, but there is no UX to that, so sys_exec() syntax errors would go unnoticed.

How to skip non-object error in PHP mysqli?

When having an error in SQL syntax in classic PHP mysql, the query will not take place without any other effect. But in mysqli, it will kill the PHP script with Fatal error
mysql_query("SELECT title, misspelled_column FROM posts");
$mysqli->query("SELECT title, misspelled_column FROM posts");
In the first case, it will show the other queries and php output; but the second case kills the script by
Fatal error: Call to a member function fetch_assoc() on a non-object
The problem is related to non-object returned by false query. I can skip this error by
if($result){$row = $result->fetch_assoc();}
but my question is that why I did not need this check in classic mysql? With a more advanced system, one expects new features not missing what we had.
An error generated by MySQL should not be stopping execution. In fact, you can have your script show you any SQL errors by using $mysqli->error (assuming $mysqli is your database connection, like in your example). However, what may be happening is that your mysqli error causes a particular object not to be created, and then calling a method on that object will create a fatal PHP error. For example:
$dbconn = new mysqli("localhost", $username, $password, $dbname);
$stmt = $dbconn->prepare("bluh"); // not a valid statement. fails to create a mysqli statement object in $stmt.
echo($dbconn->error); // your script is still running, and this will show your MySQL syntax error.
$stmt->execute();
This will die not because you made an SQL error, but because $stmt was null and didn't have the expected execute() method. So like everyone else has said, check your logs and see what the actual error is.
Using # to ignore errors is going to be hit-or-miss until you figure out which specific command is creating the error.
update: If you know that the error is in the query, then you could check to see whether the query succeeded before you try to do anything with it. One way is to check the error parameter; another is to check to make sure that it actually returned the kind of object you want.
Here are examples of both:
$result = $db->query("select firstname, lastname from people where firstname = 'egbert';");
if($db->error == '') {
// the query worked, so fetch results from $result and do stuff with them.
}
else {
// the query didn't work, so don't try to do anything with $result
}
// alternately:
if(gettype($result) == "object") {
// the query worked.
}
else {
// it didn't.
}
A SQL error doesn't kill mysqli in my experience. I suspect you actually have a PHP error in the relevant statement. Check your error log.
In PHP, you can use # to suppress errors. It's a bad idea to use it here. But if that's what you really want, it's documented at http://php.net/manual/en/language.operators.errorcontrol.php.

my sql query failing and yet returns no mySQL errors

I have been writing php and mySQL functions all day and as I was writing the simplest part of my project I have hit a wall.
The function should simply count how many entries are in the database and return that number (If there is a more simple way please let me know, this is my first php + mysql project)
Here is the code:
function quoteCount(){
global $db;
$totalQuoteNum = array();
$query = "SELECT * FROM Quotes";
$result_set = mysqli_query($db, $query)
or die ("Query $query failed ".mysqli_error($db)); //fails here
$totalQuoteNum = mysql_num_rows($result_set)
or die ('couldnt count rows'.mysqli_error($db));
echo 'COUNTED EVERYTHING!!!';
return $totalQuoteNum;
};
Now when the die statement prints I get the string but not the mysqli error.
Things I have tried and ruled out:
$db is correct
query works in mysql
I wasnt sure if the database was connected, so I added the connect inside this function and stil nothing.
Any ideas? From what I see it should work and its not giving me any error to work from. Please help!
Based on the comments, it seems as though $db is the database name.
Functions such as mysqli_query() expect a database link (resource), not simply the database name.
This resource is created by constructing a new mysqli object. Following your procedural style, use mysqli_connect().

mysqli never returns anything

As part of a PHP web application, I'm querying a MySQL database using mysqli and prepared statements.
I've used exactly the same code on a few queries and it works, but on one particular query, it always returns an empty record set. I've run exactly the same query from the MySQL command line, and it correctly returns the result. I've checked the parameters being passed in, and they're fine.
I've spent the best part of a day trying to figure out why I'm always getting an empty record set with no errors or warnings. I've got PHP's errors set to display on the page, and I've got them set to E_ALL|E_STRICT. I still don't get any warnings or errors.
I've tried all the obvious things, like making sure I can actually connect to the database, checking the parameters that are being passed in, and making sure the row I'm trying to return actually exists in the database. I've had var_dump()s and die()s all over the page to check what's coming back, and it's always a legitimate, but empty, recordset.
function salt() {
return("I've removed my salt from this sample code");
}
function openDatabase() {
$conn = new mysqli("127.0.0.1", "username", "password", "database")
or die("Error: Could not connect to database.");
return($conn);
}
function checkUserCredentials($username, $password) {
$goodPassword = md5(salt().$username.$password);
$conn = openDatabase();
$query = $conn->stmt_init();
$query->prepare("SELECT id FROM users WHERE email = ? AND passwordHash = ?")
or die('Problem with query');
$query->bind_param("ss", $username, $goodPassword)
or die('Error binding parameters');
$query->execute() or die("Could not execute");
$query->bind_result($col1) or die ("Could not bind result");
if ($col1 !== 0) {
die("Authentication Complete");
} else {
die("Authentication Failure! Number of Rows: ".$query->num_rows." Username: " . $username . " Password Hash: " . $goodPassword);
}
}
Any feedback is appreciated. I'm sure I'm missing something simple, but if I didn't shave my head I'd be tearing my hair out right now.
Thanks
I'm not familiar with the mysqli library (I usually use PDO which provides a very similar cross platform API) so I can't immediately see any problem. However, you might try watching the mysqld log. See here for info:
http://dev.mysql.com/doc/refman/5.1/en/query-log.html
By tailing the log, you should be able to see the exact query that was submitted.
One final note, I notice you're using a fixed salt value. Wouldn't it be better to generate this value randomly each time you need it and then store it in the users table? Generally, a salt is not intended to be secret, it's just there to prevent people precomputing tables of passwords using the hash algorithm that you use.
In case anyone else runs into similar issues, it really helps if you run fetch() on your mysqli_stmt object.
In my code above, the solution looks like this:
$query->bind_result($col1) or die ("Could not bind result");
$query->fetch(); // <--- How could I forget to do this?
if ($col1 !== 0) {
return true;
} else {
return false;
}
Added on behalf of OP

PDO Unbuffered queries

I'm trying to get into PDO details. So I coded this:
$cn = getConnection();
// get table sequence
$comando = "call p_generate_seq('bitacora')";
$id = getValue($cn, $comando);
//$comando = 'INSERT INTO dsa_bitacora (id, estado, fch_creacion) VALUES (?, ?, ?)';
$comando = 'INSERT INTO dsa_bitacora (id, estado, fch_creacion) VALUES (:id, :estado, :fch_creacion)';
$parametros = array (
':id'=> (int)$id,
':estado'=>1,
':fch_creacion'=>date('Y-m-d H:i:s')
);
execWithParameters($cn, $comando, $parametros);
my getValue function works fine, and I get the next sequence for the table. But when I get into execWithParameters, i get this exception:
PDOException: SQLSTATE[HY000]: General error: 2014 Cannot execute queries while other unbuffered queries are active. Consider using PDOStatement::fetchAll(). Alternatively, if your code is only ever going to run against mysql, you may enable query buffering by setting the PDO::MYSQL_ATTR_USE_BUFFERED_QUERY attribute. in D:\Servidor\xampp_1_7_1\htdocs\bitacora\func_db.php on line 77
I tried to modify the connection attributes but it doesn't work.
These are my core db functions:
function getConnection() {
try {
$cn = new PDO("mysql:host=$host;dbname=$bd", $usuario, $clave, array(
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
));
$cn->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, true);
return $cn;
} catch (PDOException $e) {
print "Error!: " . $e->getMessage() . "<br/>";
die();
}
}
function getValue($cn, $comando) {
$resul = $cn->query($comando);
if (!$resul) return null;
while($res = $resul->fetch()) {
$retorno = $res[0][0];
break;
}
return $retorno;
}
function execWithParameters($cn, $comando, $parametros) {
$q = $cn->prepare($comando);
$q->execute($parametros);
if ($q->errorInfo() != null) {
$e = $q->errorInfo();
echo $e[0].':'.$e[1].':'.$e[2];
}
}
Somebody who can shed a light for this? PD. Please do not suggest doing autonumeric id, cause i am porting from another system.
The issue is that mysql only allows for one outstanding cursor at a given time. By using the fetch() method and not consuming all the pending data, you are leaving a cursor open.
The recommended approach is to consume all the data using the fetchAll() method.
An alternative is to use the closeCursor() method.
If you change this function, I think you will be happier:
<?php
function getValue($cn, $comando) {
$resul = $cn->query($comando);
if (!$resul) return null;
foreach ($resul->fetchAll() as $res) {
$retorno = $res[0];
break;
}
return $retorno;
}
?>
I don't think PDOStatement::closeCursor() would work if you're not doing a query that returns data (i.e. an UPDATE, INSERT, etc).
A better solution is to simply unset() your PDOStatement object after calling PDOStatement::execute():
$stmt = $pdo->prepare('UPDATE users SET active = 1');
$stmt->execute();
unset($stmt);
The problem seems to be---I'm not too familiar with PDO--- that after your getValue call returns, the query is still bound to the connection (You only ever ask for the first value, yet the connection returns several, or expects to do so).
Perhaps getValue can be fixed by adding
$resul->closeCursor();
before the return.
Otherwise, if queries to getValue will always return a single (or few enough) value, it seems that using fetchAll will be preferred.
I just spend 15 minutes googling all around the internet, and viewed at least 5 different Stackoverflow questions, some who claimed my bug apparently arose from the wrong version of PHP, wrong version of MySQL library or any other magical black-box stuff...
I changed all my code into using "fetchAll" and I even called closeCursor() and unset() on the query object after each and every query. I was honestly getting desperate! I also tried the MYSQL_ATTR_USE_BUFFERED_QUERY flag, but it did not work.
FINALLY I threw everything out the window and looked at the PHP error, and tracked the line of code where it happened.
SELECT AVG((original_bytes-new_bytes)/original_bytes) as saving
FROM (SELECT original_bytes, new_bytes FROM jobs ORDER BY id DESC LIMIT 100) AS t1
Anyway, the problem happened because my original_bytes and new_bytes both where unsigned bigints, and that meant that if I ever had a job where the new_bytes where actually LARGER than the original_bytes, then I would have a nasty MySQL "out of range" error. And that just happened randomly after running my minification service for a little while.
Why the hell I got this weird MySQL error instead of just giving me the plain error, is beyond me! It actually showed up in SQLBuddy (lightweight PHPMyAdmin) when I ran the raw query.
I had PDO exceptions on, so it should have just given me the MySQL error.
Never mind, the bottom line is:
If you ever get this error, be sure to check that your raw MySQL is actually correct and STILL working!!!
A friend of mine had very much the same problem with the xampp 1.7.1 build. After replacing xampp/php/* by the 5.2.9-2 php.net build and copying all necessary files to xampp/apache/bin it worked fine.
If you're using XAMPP 1.7.1, you just need to upgrade to 1.7.2.

Categories