Issue in update() function in sqlserver.php in CakePHP - php

We have developed our app in CakePHP running with MYSQL and this is working fine. PHP version is 5.4.16, Apache 2.4.4, latest XAMP. CakePHP version: 2.3.0
We already have similar Database in MSSQL also. Now we want to run our app with this MSSQL also.
We are using php_pdo_sqlsrv_54_ts.dll and php_sqlsrv_54_ts.dll for MSSQL driver for this. Its sql server 2005.
Whenever we are updating values in tables, we are using UpdateAll() of Model.Php which further calls update() of the corresponding datasource. Our code is like this.
if ($this->Configurationtable->updateAll(array('Configurationtable.configuration_optionsetting' => $limit ),
array('Configurationtable.configuration_optionname =' => $optionName))) {
$this->Session->setFlash('The Result Limit has been updated');
$this->redirect(array('action' => 'edit'));
} else
{
$this->Session->setFlash('The configuration could not be saved. Please, try again.');
}
Now this works fine in MySql and generated the following Update query
UPDATE ipa.configurationtable AS Configurationtable SET Configurationtable.configuration_optionsetting = 12 WHERE Configurationtable.configuration_optionname = 'searchPaginationLimit'
But in MS Sql Server, it fails and generates completely wrong query which is
SELECT [Configurationtable].[id] AS [Configurationtable__id] FROM [configurationtable] AS [Configurationtable] WHERE [Configurationtable].[configuration_optionname] = N'searchPaginationLimit'
Now, If I make Update() function in \lib\Cake\Model\Datasource\Database\Sqlserver.php similar to Update() in \lib\Cake\Model\Datasource\Database\Mysql.php then it works fine. It generates proper correct "Update" query
I could not figure out why is it going so? Is it something I am going wrong OR there is bug in cake?
Any would be of great help.

I would file a bug, but first make sure that upgrading to the latest version doesn't fix your problem. Also see the commit log of Sqlserver.php.

Related

ZF2 TableGateway query returning empty resultset, Adapter query works

I've moved an application between servers.
From:
Windows 2008 R2
ISS 6.1
PHP 5.4.11
SQL Server 10
ZF 2.4
To:
Windows 10
PHP built-in server
PHP 7.2.5
SQL Server 14
ZF 2.4
Below the TableGateway selectWith() returns an empty resultset but when the same $select is queried via Adapter->query() it works as expected. It worked fine on the previous server. The TableGateway selectWith() is the original code and needs to work. Apart from the version numbers above, nothing else has changed.
$select = $this->tableGateway->getSql()->select()->where(array(
'col1 = ?' => $input
));
// via selectWith
$resultSet = $this->tableGateway->selectWith($select);
// via query
$selectString = $this->tableGateway->getSql()->buildSqlString($select);
$adapter = $this->tableGateway->getAdapter();
$results = $adapter->query($selectString, $adapter::QUERY_MODE_EXECUTE);
// works
var_dump($results->current());
// doesn't work
var_dump($resultSet->current());
Update:
$select = $this->tableGateway->getSql()->select()->where(array(
'col1 = \''.$input.'\''
));
The above code works. So the problem must be with the way TableGateway Select placeholder and replacements. I've tried all the variations in the docs and they should work but don't.
Further update:
Obviously one of these uses sqlsrv_query and the other uses sqlsrv_execute. I've been through the library and there must be a problem with the way it binds params to sqlsrv_prepare but I haven't got to the bottom of it yet. sqlsrv_prepare requires pass by reference. I suspect the bug is an incompability with this breaking change between 5.6 and 7.
The issue here is that ZF2 is not compatible with PHP > 5.6. In this instance the API for sqlsrv has been made stricter due to deprecation of "call-time pass-by-reference". The solution is to stick with PHP 5.6 or refactor a large amount of the code.

how to print SQL statement in Laravel 5

As you know, we can use the method DB::getQueryLog() to print the sql statement in Laravel 4.
But it doesn't work in Laravel 5.
Query log is disabled by default in L5. Call
DB::connection()->enableQueryLog();
$queries = DB::getQueryLog();
before trying to log it. See the docs for more info
.
if you want to see the currently running SQL query you can use this
https://github.com/itsgoingd/clockwork
installation instructions are clearly mentioned in the README file

Renaming a Mongo Collection in PHP

PHP's Mongo driver lacks a renameCommand function. There is reference to do this through the admin database. But it seems more recent versions of the Mongo driver don't let you just "use" the admin database if do don't have login privileges on that database. So this method no longer works. I've also read this doesn't work in sharded environments although this isn't a concern for me currently.
The other suggestion people seem to have is to iterate through the "from" collection and insert into the "to" collection. With the proper WriteConcern (fire and forget) this could be fairly fast. But it still means pulling down each record over the network into the PHP process and then uploading it back over the network back into the database.
I ideally want a way to do it all server-side. Sort of like an INSERT INTO ... SELECT ... in SQL. This way it is fast, network efficient and a low load on PHP.
I have just tested this, it works as designed ( http://docs.mongodb.org/manual/reference/command/renameCollection/ ):
$mongo->admin->command(array('renameCollection'=>'ns.user','to'=>'ns.e'));
That is how you rename an unsharded collection. One problem with MR is that it will change the shape of the output from the original collection. As such it is not very good at copying a collection. You would be better off copying it manually if your collection is sharded.
As an added note I upgraded to 1.4.2 (which for some reason comes out from the pecl channel into phpinfo() as 1.4.3dev :S) and it still works.
Updates:
Removed my old map/reduce method since I found out (and Sammaye pointed out) that this changes the structure
Made my exec version secondary since I found out how to do it with renameCollection.
I believe I have found a solution. It appears some versions of the PHP driver will auth against the admin database even though it doesn't need to. But there is a workaround where the authSource connection param is used to change this behavior so it doesn't auth against the admin database but instead the database of your choice. So now my renameCollection function is just a wrapper around the renameCollection command again.
The key is to add authSource when connecting. In the below code $_ENV['MONGO_URI'] holds my connection string and default_database_name() returns the name of the database I want to auth against.
$class = 'MongoClient';
if( !class_exists($class) ) $class = 'Mongo';
$db_server = new $class($_ENV['MONGO_URI'].'?authSource='.default_database_name());
Here is my older version that used eval which should also work although some environments don't allow you to eval (MongoLab gives you a crippled setup unless you have a dedicated system). But if you are running in a sharded environment this seems like a reasonable solution.
function renameCollection($old_name, $new_name) {
db()->$new_name->drop();
$copy = "function() {db.$old_name.find().forEach(function(d) {db.$new_name.insert(d)})}";
db()->execute($copy);
db()->$old_name->drop();
}
you can use this. "dropTarget" flag is true then delete exist database.
$mongo = new MongoClient('_MONGODB_HOST_URL_');
$query = array("renameCollection" => "Database.OldName", "to" => "Database.NewName", "dropTarget" => "true");
$mongo->admin->command($query);

PHP's SQLSRV driver would not complete a Stored Procedure query that works normally elsewhere

So I'm confident that the stored procedure works, I've tested it in SQL Server Management Studio just fine and it runs in other service instances. The query used to run this SP follows;
exec sp_getAgentCommissionDetails_v3 201000023762230, 5
So it runs fine on SSMS and under the old MSSQL driver. But I run the query with SQLSRV like so;
function mssql_query($string, $linkID = null, $batch = 0) {
if (!$linkID) {
global $dbhandle;
$linkID = $dbhandle;
}
// SQLSRV_CURSOR_KEYSET ensures mssql_num_rows() works in most cases. Default scrollablility does not support this.
return sqlsrv_query($linkID, $string, array(), array("Scrollable" => SQLSRV_CURSOR_KEYSET));
}
The function is named mssql_query because we're updating an old system from MSSQL to SQLSRV, but we're working with an extremely messy old system. So rather than trying to refactor it we're overwriting the MSSQL_query function (having disabled the mssql extension) with one that uses SQLSRV.
$dbhandle is our SQLSRV connection resource. Other queries run just fine using this method.
So my question- is there any reason the query to run a stored procedure would not run under this SQLSRV function?
Couple notes on my troubleshooting;
I'm aware SQLSRV and PDO have a specific method to run stored procedures. Using that is not an option due to the massive codebase that uses the method above in various places and because we haven't got the man hours to refactor every page.
I pulled up SQLSRV_errors() and it returned 'Executing SQL directly; no cursor'. After a bit of research this seems to be a bug in the driver that returns this generic error message instead of a more specific useful one, so it can mean very many things.
There are no cursors or loops involved in the stored procedure.
Found a solution to this. SQLSRV seems to by default treat warnings as errors. Fixed this with a config change in the connection file;
sqlsrv_configure("WarningsReturnAsErrors",0);
It now runs fine.

Codeigniter and Doctrine 500 internal error

I've tried to combine Doctrine with Codeigniter and I'm almost there, I think.
The version of Codeigniter is 2.0.2 and from Doctrine is 2.0.0.
The problem is now that I get an 500 internal server error using the flush() method of Doctrine.
I am following a tutorial (http://wildlyinaccurate.com/integrating-doctrine-2-with-codeigniter-2/) to install doctrine with codeigniter. But at the last step it just fails and I don't know why.
This is my code in my controller:
$app = new models\application;
$app->setName("Test applicatie");
$app->setGuid();
$this->doctrine->em->persist($app);
$this->doctrine->em->flush(); //If I comment this out, it loads the view...
$this->load->view('welcome_message');
When I comment out the flush method it loads the view.
Thanks in advance.
Well, since $this->doctrine->em->flush(); is what actually does the write to the DB, Make sure you have the required MySQL user rights to do the DB action.
Write the query directly in MySQL and make sure that the error isn't thrown there.
Make sure to put some content in fields that cannot be null.

Categories