Zend Pdo_Mysql LOAD DATA forbidden - php

I have been looking for a solution that allows load data queries with zend framework like:
LOAD XML LOCAL INFILE '$dbFile' INTO TABLE mytable ROWS IDENTIFIED BY '<object>';
When I try to execute this query, i get the following error:
Warning: PDO::exec() [pdo.exec]: LOAD DATA LOCAL INFILE forbidden
However if I output the query and copy/paste it into an editor like HeidiSQL the query works.
I searched for an answer and found that I should set the driver option PDO::MYSQL_ATTR_LOCAL_INFILE but it does not seem to work.
I would like to use application.ini to set the driver option:
resources.multidb.mydb.adapter = "Pdo_Mysql"
resources.multidb.mydb.dbname = "mydb"
resources.multidb.mydb.username = "myuser"
resources.multidb.mydb.password = "mypass"
resources.multidb.mydb.driver_options.PDO::MYSQL_ATTR_LOCAL_INFILE = true
resources.multidb.mydb.driver_options.1001 = true
I tried it the following way too but got the same error:
$config = new Zend_Config_Ini(APPLICATION_PATH . '/configs/application.ini', 'testing');
$dbParams = $config->resources->multidb->mydb->toArray();
$dbParams['driver_options'] = array(PDO::MYSQL_ATTR_LOCAL_INFILE => '1');
$db = Zend_Db::factory($config->resources->multidb->mydb->adapter, $dbParams);
Am I overlooking something? Or maybe setting the options wrong? I also read that mysql must be compiled with --enable-load-data or something but the query works with an sql editor so it should work through php.

I found an interesting implementation of local infiles in the Rend (Rapid Zend) Framework.
Basically, the file has a class for the PDO object and has a method like this:
/**
* Set the local infile flag
*
* #param boolean $allowLocalInfile
* #return Rend_Factory_Database_Pdo_Mysql
*/
public function setAllowLocalInfile($allowLocalInfile)
{
$this->_options["driver_options"][PDO::MYSQL_ATTR_LOCAL_INFILE] = $allowLocalInfile;
return $this;
}
I'm sure some more browsing in that open source repository would reveal some tricks to solve your problem.

Related

PHP Warning: "MySQL server has gone away" after MySQL dump in macOS Terminal

I am using a PHP script from CLI to download remote MySQL databases (gzip) and extract them directly to my MacBook's MySQL 5.7 (not MAMP) server.
It works fine, but as a side effect, my PHP apps (MAMP Pro) lose the MySQL connection in the middle of the CLI script with the warning
PHP Warning: mysqli::__construct(): MySQL server has gone away in ...
This happens after roundabout a dozen databases (can't reproduce the exact amount). While the CLI script is running, the MySQL pane in System Preferences goes from green/running to red/stopped to again green/running after each CLI dump, which first does not conflict with the the PHP apps in the browser. But at some point the PHP apps obviously lose the connection.
I played around with my.cnf and set
[mysqld]
max_allowed_packet=128M
max_connections=1024
or other amounts, but it doesn't seem to change anything.
When I manually stop and start MySQL in System Preferences after the CLI script has finished, the PHP continues to work normal again.
Any ideas?
EDIT:
Thanks so far, but it's still not fixed. So here’s the script in principal:
$tmpPath = '/tmp/'
For each of 30 databases with different size:
$dbName = database name
exec('ssh user#server.com "mysqldump --login-path=local --lock-tables=false '.$dbName.' | gzip" > '.$tmpPath.$dbName.'.sql.gz');
exec('gzip -q -dc '.$tmpPath.$dbName.'.sql.gz | mysql -u root -proot '.$dbName)
Like I said, the PHP CLI script in Terminal doesn't complain at all!
It’s my PHP apps (backend for Angular frontend apps) that somewhere in the middle of the 30 dumps stop working because of the mentioned error.
i have similar problem and fixed by just adding max_connections = 1024 in mysql.conf
We had a similar problem, and used this which reconnects if the connection goes away:
<?php
use Exception;
use PDO;
use Our\Package\Common\Config\DbCredentials;
class DbConnectionManager
{
private $credentials;
/** #var PDO $connection */
private $connection;
/**
* DbConnectionManager constructor.
* #param DbCredentials $credentials
*/
public function __construct(DbCredentials $credentials)
{
$this->credentials = $credentials;
$this->reconnect();
}
/**
* #return PDO
*/
public function getConnection()
{
if (!$this->isConnected()) {
$this->reconnect();
}
return $this->connection;
}
/**
* #return bool
*/
private function isConnected()
{
try {
return $this->connection->query('SELECT 1 + 1;');
} catch (Exception $e) {
return false;
}
}
/**
* Reinitialise the connection to MySQL
*/
private function reconnect()
{
$dsn = $this->credentials->getDriver()
.':host='.$this->credentials->getHost()
.';port='.$this->credentials->getPort()
.';dbname='.$this->credentials->getDbName()
;
$connection = new PDO($dsn, $this->credentials->getUser(), $this->credentials->getPassword(), array(
PDO::ATTR_TIMEOUT => 28800,
PDO::ATTR_EMULATE_PREPARES => false,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
));
$this->connection = $connection;
}
}
You can tweak this. The DBCredentials class is just a plain PHP class with getters & setters for driver, hostname, user, password, db name, you could change it to just take arguments as strings if you like.
You can also get these errors if you send a query to the server that
is incorrect or too large. If mysqld gets a packet that is too large.
or out of order, it assumes that something has gone wrong with the
client and closes the connection.
To avoid this problem ,You must ensure that max_allowed_packet is set bigger in the mysqld server than in the client and that all clients uses the same value for max_allowed_packet.
And Remember to restart your server after that !!!!
When you create a mysqldump you lock the tables. I think that is the main problem and that is why your applications is getting that error. Use this options:
--lock-tables, -l
Lock all tables before dumping them. The tables are locked with READ
LOCAL to allow concurrent inserts in the case of MyISAM tables. For
transactional tables such as InnoDB and BDB, --single-transaction is
a much better option, because it does not need to lock the tables at
all.
The original answer here:
Run MySQLDump without Locking Tables
And try user some "sleep" between dump commands.

mongo authorization zend shanty

I trying to add authorization to mongoDB.
I use mongodb 2.2.4, php-mongo 1.4.1 stable, apache2, php 5.4, ZendFramework 1.12 + ShantyMongo
Also I use replicaset with 3 instances.
When I set auth = true mongo create admin database, and when I add user to this database I got this error:
Fatal error: Uncaught exception 'MongoCursorException' with message 'test.server.com:27017: unauthorized db:database_test ns:database_test.options lock type:0 client:127.0.0.1' in /apps/test_app/libs/Shanty/Mongo/Collection.php:3501
If I add user to my database_test all work fine.
<?php
/* Configure logging */
MongoLog::setModule( MongoLog::ALL );
MongoLog::setLevel( MongoLog::ALL );
$m = new MongoClient(); // connect
$db = $m->selectDB("database_test");
$db->authenticate('admin','12345');
this code work fine even if I add user to both admin and database_test.
Maybe someone has similar problem and know what I need to do.
First of all, you should use the following syntax for specifying authentication:
<?php
$m = new MongoClient("mongodb://admin:12345#localhost/database_test");
$db = $m->database_test;
It's a bit difficult to answer your question though, as "when I add user to this database" is not really descriptive. In order to get a proper answer, you need to learn to list the exact steps or code that you used to do this.
I am thinking that you were trying to auth against a normal database (database_test), where you would only have a user/pass set for the admin database. In that case, you need to auth to the admin database, and then select your database_test:
<?php
$m = new MongoClient("mongodb://admin:12345#localhost/admin");
$db = $m->database_test;
Thank you for your answer I figured out this.
Maybe it's will be heplful for some one on future, Shanty-Mongo require username, password and port in array of servers.
It's should looks like:
; Shanty Mongo Config
hosts.0.host = '127.0.0.1'
hosts.0.port = '27017'
hosts.0.username = 'root'
hosts.0.password = 'pass'
hosts.1.host = '127.0.0.1'
hosts.1.port = '27018'
hosts.1.username = 'root'
hosts.1.password = 'pass'
hosts.2.host = '127.0.0.1'
hosts.2.port = '27019'
hosts.2.username = 'root'
hosts.2.password = 'pass'
database = 'database_test'
replicaSet = true
Also what I do:
in mongo:
1. edit config file, enable auth (auth = true)
2. create user in admin database
3. connect as new user
4. create user in target database
in ZF config
update config file, as I describe above.
Also some times I get error: Fatal error: php_network_getaddresses, I think it's because I have some trouble with DNS or php trying resolve address: mongo://root:pass#127.0.0.1:27017,root:pass#127.0.0.1:27018,root:pass#127.0.0.1:27019/database_test

Zend : How to get contents of a CLOB column?

I have a CLOB column in a table. When i query the table and try to echo the data, i get something like
Resource id #102
I searched about this and found this POST . Tried the given solution from it in zend framework like this below:
$clobContent = $data['TEXT']->load();
$data contains the result of the query.
But gets the following error
Fatal error</b>: Call to a member function load() on a non-object
How do i get the contents of the CLOB in zend framework?
Somehow after changing the db adapter from PDO_OCI to Oracle worked for me. Had read in some post that PDO_OCI had problems with reading CLOBS.
resources.db.adapter = oracle // in application.ini
The code below worked for me, not sure of it but can try this and let me know if it worked
$select = $this->_dbAdpt->select()
->from($this->_name)
->where($this->_dbAdpt->quoteInto('LOWER(URL) = ?', strtolower($url)))
->where($this->_dbAdpt->quoteInto('VERSION = ?', $version))
;
$row = $this->_dbAdpt->fetchRow($select);
return $row['CONTENT']->load();

How do I print all the queries in Magento?

Is it possible to display all the query strings in Magento? I really like to see what queries are executed.
Thanks
In Varien_Db_Adapter_Pdo_Mysql
Magento 1.4 : lib/varien/Db/Adapter/Pdo/Mysql.php
set
protected $_debug = true;
protected $_logAllQueries = true;
and (if nor already there) create the folder defined in
protected $_debugFile = 'var/debug/sql.txt';
Give read / write permission
I'm not 100% sure this will catch every query, but most run through the query method Zend_Db_Adapter_Abstract query method in
lib/Zend/Db/Adapter/Abstract.php
With that in mind, you could temporarily add some debugging statements (to a copy you make in app/code/local/Mage to be safe)
public function query($sql, $bind = array())
{
// connect to the database if needed
$this->_connect();
// is the $sql a Zend_Db_Select object?
if ($sql instanceof Zend_Db_Select) {
if (empty($bind)) {
$bind = $sql->getBind();
}
$sql = $sql->assemble();
}
echo "{$sql}\n<br />\n";
var_dump($bind);
If you need to catch them all, you'd be better off doing this at the MySQL level (which isn't always possible depending on your host/IT situation)
Activate the Zend SQL Profiler with the following node in your local.xml
<resources>
<default_setup>
<connection>
<profiler>1</profiler>
Then you can access the profiler somewhere in your code and retrieve a lot of informations about all executed queries:
$profiler = Mage::getSingleton('core/resource')->getConnection('core_write')->getProfiler();
To simply output all queries:
print_r($profiler->getQueryProfiles());
You can add these two lines at the end of index.php to see all queries at the bottom of each page. Be aware that this will break AJAX requests that return a JSON response, so you might consider logging the queries instead of printing them, with this code (again, add it at the end of index.php):
$profiler = Mage::getSingleton('core/resource')->getConnection('core_write')->getProfiler();
Mage::log(print_r($profiler->getQueryProfiles(), true), null, 'queries.log', true);
Then you will find all queries in var/log/queries.log
Don't forget to remove the lines again after you finished debugging!
The queries will vary significantly depending on your activities. If you have some control over your MySQL server, try turning on query logging:
set global general_log = on
Then you can get the SQL log to see queries. As a word or warning, Magento tends to execute dozens of queries on every page load, and hundreds to save an object.
Thanks,
Joe
$collection->printLogQuery(true);
Turn on the MySQL logging will sure log all queries transactions. Here is how you can turn on the logging on.To turn on the logging to log to a file. Place the following in the my.cnf file or my.ini file if on windows, and restart MySQL.
log = /path/to/your/logfile.log
Then if you want to log to the table mysql.general_log, run these queries:
SET GLOBAL log_output = 'TABLE';
SET GLOBAL general_log = 'ON';
Run these if you want to log to the file:
SET GLOBAL log_output = "FILE";
SET GLOBAL general_log = 'ON';

Can't return a result set in the given context

When ever I try to call store procedure in mysql that sends back a result set, it keeps saying me that "can't return a result set in the given context".
I've google it and some said it's mysql bug, some said you should change your mysqli driver and ....
Situation :
Using mysqli driver Client API library version 5.0.51a , PHP Version 5.2.4-2ubuntu5.6, Using Zend 1.9 RC 1 Mysqli adapter.
What should I do!?
The answer is to upgrade your php, I've just upgraded mine to 5.3.0, and it's works likes Candy!
Not sure this is the solution to your problem, but what about trying with a more recent version of PHP ?
PHP 5.2.4 is definitly quite old -- so, if it's a bug in PHP's mysqli driver, it might have been corrected since...
Actually, after a quick search, it seems a problem like the one you are witnessing has been introduced between PHP 5.2.3 and PHP 5.2.4 (and was still here in PHP 5.2.5).
See bug #42548 : PROCEDURE xxx can't return a result set in the given context (works in 5.2.3!!)
Are you able to test with something like PHP 5.2.9 or 5.2.10 ?
I know these are not provided by Ubuntu, even in the last Ubuntu stable version :-( You might have to compile from sources :-(
Yet another idea would be to try mith PDO_MySql adapter : maybe it would work with that one ?
It might be possible to change Adapter without causing too much trouble / without taking hours to test ?
As you are working with Zend Framework 1.9, here's another post that might interest you, and might be easier to test : stored procedure error after upgrade to 1.8
An easy solution to try that would be to go back to Zend Framework 1.7 ; would it be possible for you, just to test ?
Anyway... Good luck !
And, if you find the solution, don't forget to indicate what the problem was, and how you solved it ;-)
I had this problem recently on a contract. The client was using a codebase on windoze and php 5.2.6 and my installation was linux and php 5.3.1 Whatever we did, they wouldn't co-operate so in the end they gave me a windoze vista machine and we installed php 5.2.6 and off we went. Moral of the story: version matching counts. Weird cus I never had this ever before in any other job. But hey, you can't know everything. Very definitely not a MySql issue, just PHP.
It works perfectly with PHP 5.2.10 as well.
From an earlier version, I've successfully used mysqli::multi_query to call a problematic procedure and get the right results.
I know this question is ancient, but for those still working with 5.2.4 and getting this error, you may consider creating a new mysql PDO object to work around this problem.
I still use 5.2.4 on my dev server to ensure backward compatibility for the WordPress plugins I develop.
Below is a wrapper around procedural calls that I use to successfully call procedures in both 5.2.4 (run on my dev server) , which would normally give me the error, and my production server (which runs a newer version that doesn't give the error) .
Its WordPress specific, but it wouldn't be difficult to modify it using straight php.
/*
* Need to cache connection so we don't keep creating connections till we hit max.
*/
private $_dbhCache=null;
/**
* mySQL Call Proc
*
* Provides a wrapper around calling a mySQL stored procedure to ensure against a 5.2.4 bug that
* causes procedure calls to fail.
* Error:'can't return a result set in the given context'
*
* references:
* http://stackoverflow.com/questions/1200193/cant-return-a-result-set-in-the-given-context
* http://php.net/pdo_mysql#69592 //i got empty result set but pointed me in the right direction
* http://php.net/pdo_mysql#80306 //this worked, but returned 0-indexed and assoc, i edited it so it only returns assoc mimicking $wpdb->get_results(
* http://www.php.net/manual/en/pdo.connections.php
* http://www.php.net/manual/en/pdostatement.fetch.php explains about FETCH_ASSOC
*
* #param string $proc The mySQL stored procedure string, including paramaters, but without the call statement. e.g.: "my_procedure_name('my_paramater')";
* #return string The results of the procedure call
*/
public function mySQLCallProc( $proc ) {
global $wpdb;
$query = "call $proc";
try {
/*
* Attempt to call the procedure normally.
*
*/
$query_result = $wpdb->get_results( $query, ARRAY_A );
/*
* Check for a database error
* and throw an exception if one is found.
* We can then attempt it again using a workaround.
*/
if ( $wpdb->last_error !== '' ) {
throw new Exception( 'Database Error While Calling Procedure' );
}
} catch ( Exception $e ) {
try {
/*
* Create a PDO Object for the connection
*/
if ( is_null($this->_dbhCache)) {
$dbh = new PDO( 'mysql:host=' . DB_HOST . ';port=' . DB_HOST . ';dbname=' . DB_NAME, DB_USER, DB_PASSWORD, array( PDO::ATTR_PERSISTENT => true ) );
$this->_dbhCache=$dbh ;
}else{
$dbh = $this->_dbhCache;
}
/*
* Prepare and call the procedure.
*/
$stmt = $dbh->prepare( "call $proc" );
$stmt->execute();
/*
* fetch all rows into an associative array.
*/
$query_result = $stmt->fetchAll( PDO::FETCH_ASSOC ); //FETCH_ASSOC gets results as an assoc array. without it, you'll receive both assoc and 0-indexed array
} catch ( PDOException $e ) {
print "Error!: " . $e->getMessage() . "<br/>";
die();
}
}
return ($query_result);
}

Categories