Function generates valid sql statement, fails as if non-object - php

I have a PHP function written that takes a series of parameters and generates a string. That string is then used in a Magento $readConnection->fetchOne($thestring); request and fails to actually read from the database, indicating via error message that the call to fetchOne is on a non-object.
However, the Varien_DB method takes the string query as a parameter, and should return an array as the result.
function updateDB($tablename,$entity,$selector,$id){
$query = 'SELECT entity_id, `value` FROM '.$tablename.' WHERE entity_id = '.$entity.' AND '.$selector.' = '.$id;
$result = $readConnection->fetchOne($query);
}
The reason behind writing this as a function is that I have a large selection of products that get updated pricing on a daily basis, but not all receive the same updates. In addition, the prices are located on different tables in the database, so by passing the relevant values to the function I can run the appropriate query.
The $query generated by passing the values to the function is a valid string, and can be used by itself as a query against the database (verified through Navicat against the db). When the $query is used by $readConnection->fetchOne, it returns an error of "Call to a member function fetchOne() on a non-object", so I am not sure what is going on. The $query does not need to be an object, nor does it fail when run by itself against the db.
Per comments, $readConnection is defined prior to calling the function. I can set it as a global variable and see if that works.
$resource = Mage::getSingleton('core/resource');
$readConnection = $resource->getConnection('core_read');
$writeConnection = $resource->getConnection('core_write');

Related

Multiple queries with Firebird and PHP 7.3

It's my first time working with Firebird database and I need some help in the transactions department. I need to run multiple functions inside a ''main function'', those functions have queries, but if one fails, I need them all to rollback. Can I open the transaction in the top of the main function and close it at the bottom or do I have to open and close for each query? I'll post an example.
public function Main_function()
{
$id = $this->create_user_id();
$connection = ibase_connect($this->_db, $this->_username, $this->_password, '100');
$trans = ibase_trans($connection, IBASE_READ+IBASE_COMMITTED+IBASE_REC_NO_VERSION);
$query = "INSERT INTO USERS (user_id, name) VALUES ('john', '$id')";
$newuser = ibase_query($trans, $query);
$return = $this->insert_new_job($id);
ibase_commit($trans);
ibase_close($connection);
}
public function create_user_id()
{
$id = '2';
return $id;
}
public function insert_new_job($id)
{
///DO I NEED TO OPEN A NEW TRANSACTION OR THE OTHER IS STILL ACTIVE?
$query = "INSER INTO jobs (name, id, job) VALUES ('john',$id,'developer') ";
$result = ibase_query($trans, $query);
return $result;
}
If you want all statements executed in a single transaction, then you need to start the transaction once, use it for all statements you want in that transaction, and then commit at the end of the unit work. In other words: you should not start a transaction for each individual statement.
Starting a transaction for each statement would not have your desired result, as each would be executed in its own transaction, which is - by your own words - not what you want. In addition, as Firebird supports multiple active transactions on a single connection, you would have the added problem that you need to ensure that you keep track of all transactions handles to properly commit or rollback, as starting a new transaction will not automatically end a previous transaction.
As an aside, I don't program in PHP, but it looks like $connection and $trans (and other variables) are global variables, and it would be better to declare them as local variables and pass them to your query methods instead of relying on access to global variables.

what does sqlsrv_query return for ALTER INDEX all ON tbl REORGANIZE query and why does sqlsrv_num_rows return FALSE?

I've created a pull request to add a Database\ResultInterface::getNumRows() function to CodeIgniter 4. Some changes I've made have broken a unit test. Specifically, an SQLSRV table optimization test is barfing because this framework tries to fetch a result array from the SQLSRV response to this table optimization query:
ALTER INDEX all ON db_job REORGANIZE
It's also a bit tricky to trace all the code being called that leads to this, but here's an exception:
1) CodeIgniter\Database\Live\DbUtilsTest::testUtilsOptimizeDatabase
CodeIgniter\Database\Exceptions\DatabaseException: Error retrieving row count
/home/runner/work/CodeIgniter4/CodeIgniter4/system/Database/SQLSRV/Result.php:198
/home/runner/work/CodeIgniter4/CodeIgniter4/system/Database/BaseResult.php:193
/home/runner/work/CodeIgniter4/CodeIgniter4/system/Database/BaseUtils.php:177
/home/runner/work/CodeIgniter4/CodeIgniter4/tests/system/Database/Live/DbUtilsTest.php:105
Dissecting that, we see that the DBUtilsTest line 105 calls the BaseUtils::optimizeTable function with a table name, "db_job", and that uses the SQLSRV\Utils::optimizeTable var to construct the query I provided above. This sql is then fed to a db object that calls CodeIgniter\Database\SQLSRV\Connection::query() which, through inheritance and various function calls routes that SQL through BaseConnection::query() which feeds the sql to BaseConnection::simpleQuery which hands the sql to SQLSRV\Connection::execute which finally feeds the sql to sqlsrv_query and returns the result of that function back up through the call stack. So I guess this brings me to my first question:
Question 1: What is the value of $stmt if this ALTER command a) succeeds or b) fails?:
$stmt = sqlsrv_query($connID, 'ALTER INDEX all ON db_job REORGANIZE');
According to the sqlsrv_query documentation, this function:
Returns a statement resource on success and false if an error occurred.
Whatever that value is gets returned back up the call stack to line 625 of BaseConnection::query where, if successful, it is stored as $this->resultID and fed as the second parameter to the constructor at line 676 which effectively returns new SQLSRV\Result($this->connID, $this->resultID). To be clear, connID refers to the SQLSRV db connection and resultID refers to whatever value of $stmt was returned by the sqlsrv_query call above.
The resulting $query variable is an instance of system\Database\SQLSRV\Result in this function:
public function optimizeTable(string $tableName)
{
if ($this->optimizeTable === false)
{
if ($this->db->DBDebug)
{
throw new DatabaseException('Unsupported feature of the database platform you are using.');
}
return false;
}
$query = $this->db->query(sprintf($this->optimizeTable, $this->db->escapeIdentifiers($tableName)));
if ($query !== false)
{
$query = $query->getResultArray();
return current($query);
}
return false;
}
An instance of SQLSRV\Result will not be false so that code will attempt to call SQLSRV\Result::getResultArray which through inheritance calls BaseResult::getResultArray. This seems wrong to try to getResultArray from a query that optimizes a table or any sort of ALTER query, however an MySQL server will return a series of records in response to an OPTIMIZE query. Also, the sqlsrv_query function we just ran is just returning some of sqlserver statement or resource as its result.
I guess this brings me to my second question:
Question 2: How does one tell from the $stmt result of sqlsrv_query whether the ALTER statement above succeeded?
Curiously, none of these pecularities caused any problem before. The problem appears to have arisen because I've deprecated an unused BaseResult::numRows property that was never being set in the old getResultArray code and have replaced it and all references to it with a new getNumRows method. In my new BaseResult::getResultArray function we now check getNumRows instead of numRows. This works fine for MySQLi, SQLite3, and PostGreSQL, but barfs in SQLSRV because the aforementioned $stmt result of the sqlsrv_query ALTER statement gets fed to sqlsrv_num_rows and returns false, which signifies an error according to the docs. Here's the code for SQLSRV\Result::getNumRows function:
public function getNumRows() : int
{
// $this->resultID contains the sqlsrv_query result of our ALTER statement
// and $retval comes up false
$retval = sqlsrv_num_rows($this->resultID);
if ($retval === false)
{
throw new DatabaseException('Error retrieving row count');
}
return intval($retval);
}
This brings me to:
Question 3: would it ever make any sense to try and fetch results from or call sqlsrv_num_rows on the result of an ALTER INDEX query?

How to execute delete raw query in codeigniter

I have sql query for delete multiple record from database
$sql="delete from users where id IN(4,5,6..)";
How to run this query in codeigniter
Per the documents, you can use the query builder, or you can run a direct query on the database.
The query() function returns a database result object when “read” type
queries are run, which you can use to show your results. When “write”
type queries are run it simply returns TRUE or FALSE depending on
success or failure. When retrieving data you will typically assign the
query to your own variable, like this:
$query = $this->db->query('delete from users where id IN(4,5,6..)');
Or you can use the query builder class which allows you to do the following:
$this->db->where_in('id', array(4,5,6));
$this->db->delete('users');
Create a function in you model
function rowDelete($ids)
{
$this->db->where_in('id', $ids);
$this->db->delete('testimonials');
}
And call that in your controller
$this->your_model->rowDelete($ids) // $ids = array(4,5,6);
You can also execute query like this
$delete = "id IN('4','5','6')";
$this->db->where($delete);
$this->db->delete("user");
In this you can also execure your core query.

How to use the result set from a stored procedure in codeigniter?

I'm trying to call a stored procedure (from mysql) with codeIgniter (3.0.4).
My issue is that I have always the message "Commands out of sync; you can't run this command now".
Here is my code
$this->db->trans_start();
$sql = "CALL setup_resource('{$p1}','{$p2}','{$p3}',#id)";
$this->db->query($sql);
$query = $this->db->query("SELECT #id as my_id");
$this->db->trans_complete();
$my_id = 0;
foreach ($query->result_array() as $row) $my_id = $row['my_id'];
I'm trying to execute with SP and with #id retreive the id returned by my stored procedure => procedure seems that I cannot call another query in the same transaction.
I saw in many topic that CI does not handle correctly multiples query string, and advise tu use "next_results()" function but the result is the same (or I have a message "none next_result() you have to use more_results()").
Also saw that i should use multi_query function from mysqli but did not saw examples of it.
Did anyone have this issue ? What would be the workaround for codeIgniter to handle it?
Thanks for your help ;)

Controller Variable not Showing up in Query Builder Laravel

I am encountering a strange issue in Laravel.
The below is an index function in one of my controllers.
public function index($merchant_url_text)
{
//
$deals = DB::table('tbl_deal')
-> join ('tbl_merchant', 'tbl_deal.merchant_id', '=', 'tbl_merchant.merchant_id')
-> where ('merchant_url_text', $merchant_url_text) -> toSql();
//return $merchant_url_text.$deal_id;
dd($deals);
//return $merchant_url_text;
}
As you can see I am passing merchant_url_text from route.
Route::get('/testroute/{merchant_url_text}', ['uses' =>'dealsVisibleController#index']);
When I am trying to debug the query by printing it, I am getting
"select * from `tbl_deal` inner join `tbl_merchant` on `tbl_deal`.`merchant_id` = `tbl_merchant`.`merchant_id` where `merchant_url_text` = ?"
This means that the query builder is not reading the $merchant_url_text variable. However, when I return just that variable, it is being printed.
Just can't figure out why the query builder is not able to include the $merchant_url_text variable in the query when it is available in the index function.
Any suggestions.
I am pretty sure that your code is correct. The SQL output function toSql() does not show the values of variables and only prints out a ? for security reasons.
You may access all your queries by using
$queries = DB::getQueryLog();
It is also printing the query parameters as array.
To get the last query:
dd(end($queries));
To disable the log:
DB::connection()->disableQueryLog();
See the docs for further information.

Categories