MSSQL UPDATE works but INSERT fails - php

I'm on it since 2 days and can't figure it out this case.
I'm working with PHP 5.5 ans MSSQL, and it seems I can't insert in some table whereas an update works on this table and the same insert works on another table.
Of course I've check my user have the correct rights on this table.
Here's the code maybe I'm dumb...
// Establish connection
try {
$pdo = new PDO(DSN, UID, PWD);
} catch (PDOException $e) {
die("Error! ".$e->getMessage());
}
$pdo->beginTransaction();
// Merge-like event
try {
$updateStmt->execute();
$rows = $updateStmt->rowCount();
if($rows == 0) {
$insertStmt->execute();
}
} catch (Exception $e) {
$pdo->rollBack();
die("Error! ".$e->getMessage());
} finally {
$insertHistoryStmt->execute();
$pdo->commit();
}
All my PDO Statements objects are corrects with suitable values.
I've got no error on the INSERT seems it seems to never been executed on the DB.
Please ask if you need more code to understand I don't want to put my whole code here and say "please do my work".
Thanks I'm really stuck :/

Maybe my question's title isn't suitable now that I found the error source. But I write this answer down because it's a great tutorial which explains to debug different errors from ourselves.
If you go throw any PDO errors follow this link and you will find the way.
Thank to #Your Common Sense for providing a method to learn solving errors rather than a ready to use solution.

Related

PHP PDOException not catching

I need some guidance on PDO error handling.
I got this code:
<?php
$config = include('config.php');
try{
$handler = new PDO('mysql:host-127.0.0.1;dbname=not_a_valid_dbname', $config->username, $config->password);
$handler->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
echo 'Yup!';
}catch(PDOException $e){
echo 'Caught! '.$e->getMessage();
}
As you can see I provided an unvalid db name. This page outputs 'Yup!' instead of letting me know that there is no such database. Same goes when changing 'mysql:not_valid_host'. Only when I change driver name it throws an error letting me know that there is no driver by that name.
I tried:
Checking php.ini for settigs (I have hard time getting around with this)
Adding
error_reporting(E_ALL);
ini_set("display_errors", 1);
ini_set("display_startup_errors", 1);
Adding
ini_set('display_errors',true);
Also tried adding a backslash in catch param:
catch(\PDOException $e)
Still the same result. Help me break my code :D
The documentation is very unclear, but I've made some tests and drawn some conclusions. This is pure speculation. I'll try to back some of these claims up if I find further information.
If host is not present, localhost is then assumed.
Database name is not mandatory. This is, I imagine, so you can connect to a server and create a new database through PDO.
If you have a syntax error, the string will stop being considered thereafter.
With those suppositions, we can assume why your code is working the way it is. Your DSN is:
mysql:host-127.0.0.1;dbname=not_a_valid_dbname
Since there's a syntax error (- after host), neither of the parameters are considered, and there's no DB selected, with the host being localhost. This is why you get no errors. If you delete the host parameter, however:
mysql:dbname=not_a_valid_dbname
localhost is used as host (selected by default), but not_a_valid_dbname is tried as the database, which results in
Caught! SQLSTATE[HY000] [1049] Unknown database '1234'
mysql:not_valid_host would be the same case as the first example. The DSN is invalid so localhost is assumed with no database selected.
Further, you get no error because no actual DB is selected but you didn't try to run a query. As soon as you do,
try {
$handler = new PDO('mysql:', "root", "root");
$handler->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$handler->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$handler->query("SELECT * FROM test");
echo 'Yup!';
} catch(PDOException $e) {
echo 'Caught! '.$e->getMessage();
}
You'll get an PDOException, as expected:
Caught! SQLSTATE[3D000]: Invalid catalog name: 1046 No database selected
Like I said, all of this is speculation as I couldn't really find concrete evidence on most of this. I hope this guides you in the right direction. I'll keep looking for more information and edit if I find anything.

Simple Query using sqlite 3, php and PDO fails

This is first post of a question. Tried to find an answer here, but all relevant posts seems dated or use deprecated mysql.
New to sqlite, so forgive what might appear stupid, but the query in the code below never works. Note: we are running sqlite3 and PDO on site with php 5.6.
A Program to create the db worked fine. And the app "Db Browser for SQL Lite" shows DB and tables and data just fine. But this:
<?php
//open the database
$myPDO = new PDO('sqlite:MySqlitedb1');
print "<p>db opened</p>";
$result = $myPDO->query('SELECT * FROM users');
//if the query works
if ($result !== FALSE) {
print "<p>query ran</p>";
foreach($result as $row){
print "<p>".$row."</p>";
}
} else {
// when the query fails
print "<p>query failed</p>";
} //end if
// close the database connection
$myPDO = NULL;
?>
Always results in a 'query failed'. Queries for specific records that ARE there also fails.
Also Tried some other testing in code above using fetch and fetchall, and they generated errors like:
mod_fcgid: stderr: PHP Fatal error: Call to a member function fetchAll()
on boolean in (path emoved)/testpdo2.php on line 27
Which I am sure was caused by the fact the query fails so $result is null/false
I am obviously missing something stupid here?
Joe C.
This is solved. The code should have worked (it does now). It was not
a directory issue
a permissions issue
a debug_kit.sqlite file in the tmp directory, or any files in the tmp dir.
a SCP or 'sync' directory issue
I altered the code and trapped an exception (1st with 'bad' DB then good one):
<?php
$myPDO = NULL; //close db just in case...
//open the database
$myPDO = new PDO('sqlite:newsqlite2.db');
//throw exceptions
$myPDO->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
if ($myPDO != null)
print "<p>db connected</p>";
else
print "<p>db did not connect</p>";
// result: db does open
//1st test
try
{
$result0=$myPDO->query('SELECT * from users');
print "<p>query ran</p>";
}
catch(PDOException $e)
{
echo "Statement failed: " . $e->getMessage();
return false;
}
// close the database connection
$myPDO = NULL;
?>
This threw an error with the original DB (MySqlitedb1) and an PDO exception:
SQLSTATE[HY000]: General error: 11 database disk image is malformed
Now, DESPITE analyse tools run on the database saying it was 'fine' and being able to work on the database with tools like "DB Browser for SQLite" without ANY issues, nor having issues creating other DB's, SOMETHING was amiss with the file. This caused the query's to fail and always return as a Boolean 'false', so the code failed.
We fixed the DB by dumping it to a sql file, then importing it (with "DB Browser for SQLite") to create a new database (newsqlite2.db), with the data. Using that DB, the code ran fine, extracted data etc.
As to why/how the database became "corrupt" or what the weird corruption was, I have not a clue. :)
Joe C.

MySQL InnoDB transaction rollback is not working

I had a problem with a transaction sent from Yii framework (using PDO) to InnoDB MySql database, the problem was: rollback was not working, update statement was committing right away.
I tried setting autoCommit explicitly, with no luck.
Checked Mysql general log, only one Connection is being open, with one Start transaction sent, and later only one rollback.
In the general log, "Start transaction", "rollback" and the update statement were all from the same client thread.
No commit was found in the whole log.
Tried a rollback example from a mysql client (MySQLWorkbench) and rollback worked!
The problem was just that MySql was committing right away when its sent from the Yii app and I didn't know why.
For no particular reason, I just tried enabling log_bin in my.cnf and the rollback worked!!
Can someone please explain what just happened?
I'm using MySql 5.6.25, with PHP 5.6.10 and Yii 1.1.14.
Update:
Turns out that I have made a mistake, I thought the rollback worked after enabling log_bin, but it didn't.
So now I'm back to the original problem, the rollback is not working, and here is the source code:
$transaction = Yii::app()->db->beginTransaction();
try {
$data = array();
// fill some data here..
$model = Model::createOrUpdate($data);
$errors = $model->getErrors();
} catch (Exception $e) {
$errors []= $e->getMessage();
}
if (empty($errors)) {
$msg = 'Success message!';
$transaction->commit();
echo CJSON::encode(array('success', $msg));
} else {
if ($transaction->active) {
$transaction->rollback();
}
echo CJSON::encode(array('error', implode(', ', $errors)));
}
Yii::app()->end();
After some debugging, I found the reason behind that.
Basically the method:
Model::createOrUpdate($data);
is calling a stored procedure within, so if anyone is having this issue, please check if that's covered.

InnoDB transactions - doesn't work

I wanted to try out transactions and how they work practically. So I decided to write two scripts in order to test the main function of transactions (handling simultaneous accesses to the database)
I already asked a question here on stackOverflow, and the following was an Edit of that question. But I read through the rules again and I thought it might be wrong to post it under my original question because it's something different. So I ask this in a new question:
My Code (and the database table is set to InnoDB):
On page1.php:
$db->query("START TRANSACTION;");
$db->query("SET AUTOCOMMIT = 0;");
try {
$i = 0;
while ($i <= 120000000) {
$i++;
}
var_dump($db->query("INSERT INTO test VALUES (NULL, 'testvalue')"));
$db->query("COMMIT;");
}
catch (Exception $e) {
$db->query("ROLLBACK;");
echo $e->getMessage();
}
the query-method works. It just queries the string. And the while-loop is just for me. I need a bit time to go to the other browser tab to load page2.php:
$db->query("START TRANSACTION;");
$db->query("SET AUTOCOMMIT = 0;");
try {
// outputs an array with the data
var_dump($db->query("SELECT * FROM test", "assoc"));
$db->query("COMMIT;");
}
catch (Exception $e) {
$db->query("ROLLBACK");
echo $e->getMessage();
}
With the SELECT I get an array with all of the values inside the database table, which was empty at first.
Now I opened page1.php which will insert new data into the database. But first it runs through the loop, which takes about 3-4 seconds. Meanwhile, I open up page2.php.
From my understanding, page2.php should have waited for page1.php to complete its transaction?? But it just loads as usual and outputs an empty Array.
When I refresh page2.php after page1.php finished loading, I get the correct output with the new data.
Where is my mistake? I don't quite understand it.
EDIT: Here is another one I tried:
page1.php
$db->query("SET AUTOCOMMIT = 0;");
$db->query("START TRANSACTION;");
try {
//print_r($db->query("DELETE FROM test;", "affected"));
$i = 200;
while ($i <= 700) {
var_dump($db->query("INSERT INTO test VALUES ({$i}, 'testvaluetestvaluetestvaluetestvaluetestvalue')"));
$i++;
}
$db->query("COMMIT;");
}
catch (Exception $e) {
$db->query("ROLLBACK;");
echo $e->getMessage();
}
page2.php
$db->query("SET AUTOCOMMIT = 0;");
$db->query("START TRANSACTION;");
try {
var_dump($db->query("SELECT * FROM test", "assoc"));
$db->query("COMMIT;");
}
catch (Exception $e) {
$db->query("ROLLBACK");
echo $e->getMessage();
}
While page1.php is not completed, page 2 should output nothing, but it outputs the first 70 rows (depending on how fast I reloaded)
transactions try to avoid locking tables / rows wherever possible to improve concurrency. that is a good thing.
what they are for is to ensure that a set of sql statements all execute as an atomic unit.
meaning if an error occurs all the queries within the transaction are rolled back.
how strict / aggressive the locking is can be controlled with isolation modes, more infos in the mysql documentation.
so it sounds like you are misunderstanding theire purpose, the are not a semaphore mechanism.
This is the expected behavior by transactions... What you expected is a pessimistic locking mechanism, but every relational database uses optimistic locking and transaction isolation to make thing faster.
You can read more about this in the pgsql manual. I know your question is about mysql, but it does not really matter, because it's about concurrency control conceptions: ACID properties and transaction isolation levels, etc...

Basic php/mysql query struggles

I am frustrated and I am beginning to wonder if there is some catch with my hosting company that might be causing this issue. I have done this type of thing before (not with this hosting company) so I am at a loss.
<?php
$q = "SELECT * FROM sunsetUsers";
$r = #mysqli_query($dbh, $q);
if ($r) {
echo 'good job';
} else {
echo 'you suck';
}?>
The connection info is being called in the header and it works. It will connect to the database and supply me with a good message when I tell it to. Yet, when I try to execute a simple query, I get nothing. No errors at all other than it tells me, "you suck." Heh...which is what it should do when the query fails. I am not trying to do anything with the data...I just want to ensure that the query executes with no problems.
Is there any other information I can give that might help here? This seems really simple to me...yet so confused here as to why this isn't working.
You can see your mysql errors with mysql_error (for the purposes of learning):
if (!$r) {
echo mysqli_error(); // display the last error detected
}
Also using the mysql_* & mysqli_* functions are a very old & insecure way of communicating with mysql. Look into pdo for a better way.

Categories