Can raw SQL be parsed into a Zend\Db\Sql\Select object? - php

is there a way to parse a SQL statement string into a Zend\Db\Sql\Select object?
something along the lines of:
$sql = 'SELECT * FROM table WHERE col1 = "x"';
$select = new Select();
$select->parseSql($sql);
I have many uses for this, basically maintaining the use of a Select object when executing a raw SQL statement, for example to pass to Zend\Paginator\Adapter\DbSelect without having to write a custom Zend\Paginator\Adapter\DbSelect Class.

got one answer through a twitter response, specific to the Paginator use case:
$resultSet = iterator_to_array($adapter->query($sql_statement)->execute());
$iteratorAdapter = new ArrayAdapter($resultSet);
$paginator = new Paginator($iteratorAdapter);

Related

Yii-How to write this query in yii?

I am trying to fetch the no of records, but I am unable to write this query in yii. My sql query is given below.
select count(review) from review_business where (date_created>=DATE_FORMAT(NOW() ,'%Y-11-01')) and (date_created<=DATE_FORMAT(NOW() ,'%Y-12-01')) . I am currently writing this query in yii is given below.
$results=Yii::app()->db->createCommand()
->Select('count(review)')
->from('review_business')
->where('date_created'>=DATE_FORMAT(NOW() ,'%Y-11-01'))
->queryAll();
But I am getting this error Fatal error: Call to undefined function NOW() in G:\www\ba.dev\protected\views\business\stats.php on line 19. I am sure it is because of my poor yii query. Kindly correct my query.
If you are willing to run the entire query and not use the active record pattern You can try built-in YII commands to do that.
$query = 'select * from post where category=:category';
$list= Yii::app()->db->createCommand($query)->bindValue('category',$category)->queryAll();
Explanation: $query should be obvious and =:category is binding the variable category dynamically to the query for security reasons. In next line I am creating the query and substituting the value of category variable by using bindValue() function, finally queryAll retrieves all the records in the database. Hope it is clear now.
In your case
$query = "select count(review) as result from review_business where (date_created>=DATE_FORMAT(NOW() ,'%Y-11-01')) and (date_created<=DATE_FORMAT(NOW() ,'%Y-12-01'))" ;
$list= Yii::app()->db->createCommand($query)->queryAll();
Now you can access the result like this:
foreach ($rows as $row) {
$result = $row["result"];
}
Try this,
$results=Yii::app()->db->createCommand()
->Select('count(review)')
->from('review_business')
->where('date_created >=DATE_FORMAT(NOW() ,"%Y-11-01")')
->queryScalar();

SQL query result to string

I'm using SQL in Yii framework.
I need to show the person's latest active week (it's number and date).So I wrote following code:
public function latestWeek()
{
$datalogin=//the login is working fine
$sql ="SELECT w.number,MAX(w.start_date)
FROM tbl_person_week t, tbl_week w
WHERE t.person_id=$this->id AND t.week_id=w.id";
$query = mysqli_query($datalogin, $sql);
return $query;
}
Now , I checked this query on the server and it works fine (almost) but first thing: I need to convert it into string , because yii's CgridView can't read it , and I couldn't find a working solution for this.
Second: on the server , it gave me the max date indeed , but not it's correct number , but the first number available. How can I fix this as well?
Queries like that should never be used in objective framework. If yu want to execute your own query, you should do it this way:
$sql = "your sql code";
$array = Yii::app()->db->createCommand($sql)->queryAll();
As result you will get multidimensional array with selected columns and rows
If you want to use it in grid view, you should do it this way:
$count = Yii::app()->db->createCommand($sql)->queryScalar();
$dataProvider = new CSqlDataProvider($sql, array('totalItemCount'=>$count));
$this->widget('zii.widgets.grid.CGridView', array(
'id'=>'grid-id',
'dataProvider'=> $dataProvider,
));
You can also use connection other than Yii::app()->db. Check CDbConnection class in docs.
edit: if you wanna use queries like mysql_fetch_assoc, check out also queryRow() method instead of queryAll()
Use Mysql_fetch _array
public function latestWeek()
{
$datalogin=//the login is working fine
$sql ="SELECT w.number,MAX(w.start_date)
FROM tbl_person_week t, tbl_week w
WHERE t.person_id=$this->id AND t.week_id=w.id";
$query = mysqli_query($datalogin, $sql);
while($row = mysqli_fetch_array($query)){
echo $row;
}
}
Assuming from your qu. that you want the week number and start date as one string, you have to concatenate the two columns in the sql.
You also need to specify that the week number is from the row with the maximum start date, which isn't as simple as you might first think.
I don't like injecting the person_id straight into SQL, it isn't awful in this case but is a bad habit to get into security-wise. There are binding methods available in the framework and I agree with Arek, that you should lean on the yii framework as much as possible.
To get the scalar string value, if you are insisting on using your own SQL.. I suggest the following:
$sql='
SELECT CONCAT('Week ',tw.number,' starting ',tw.start_date)
FROM tbl_week tw
JOIN (
SELECT MAX(twi.start_date) max_start_date
FROM tbl_week twi
JOIN tbl_person_week tpwi
ON tpwi.week_id = twi.id
AND tpwi.person_id = :person_id
) i
ON tw.start_date = i.max_start_date;
';
$command=Yii::app()->db->createCommand($sql);
$command->bindParam(":person_id", $this->id);
return $command->queryScalar();

Dynamic query creation MySQL

I'm working on a project using mysqli library, and I have reached the point where I need to create a SELECT query inside a method, depending on the parameters that were sent.
The behavior I'm looking for is similar to Android's SQLite where you pass the columns as a parameter and the values as the next paramenter.
I know I could create the query string if the parameter sent where the columns and the values, by iterating over them and then manually concatenating strings to a final query string, but I wonder if there is any core library that let you do this or any other way
You should use PDO prepared statements
//$param = array(":querycon1" => "querycon", ":querycon2" => "querycon2");
// $condition = "abc=:querycon1 AND xyz=:querycon2";
protected function setQuery($column,$condition,$param){
$this->query = "SELECT $column FROM tablename WHERE $condition";
$this->param = $param //
$this->getQuery($this->query, $this->param); // to a method that processes the query
}

how to add additional select columns in symfony 1.0

How can I add an additional column to my select query so when I execute TableA::doSelect($c) I could also get some columns of TableB? It does not seem that addSelectColumn is available in symfony 1.0, unless I'm missing something.
$c = new Criteria();
$c->setDistinct();
// need to add TableB::START_DATE to select
$c->addJoin(TableA::ID, TableB::ID);
...
$c->addAscendingOrderByColumn ( TableB::START_DATE );
$result = TableA::doSelect($c);
You could use addSelectColumn() with Symfony 1.0 but should avoid adding doSelect() in such cases.
This method is executing an object and expects to get all its fields in the same order they are described in the schema file. Trying to skip a field or add one from another table will be ignored in the result set.
Depending on your Propel version you could try and use the doSelectStmt(), doSelectRS() or doSelectJoin() methods instead.
Or go with the easiest way and just use a prepareStatement():
$con = Propel::getConnection();
$sql = "SELECT `table1`.field1, `table2`.field2 FROM `table1` JOIN `table2`. ON ..."
$st = $con->prepareStatement($sql);
$rs = $st->executeQuery();
while ($rs->next())
{
...
}
http://symfony.com/legacy/doc/cookbook/1_0/en/behaviors

Select ignores where clause using Zend_Db_Select

$table = new Zend_Db_Table(array('name'=>'rules'));
$select = $table->select();
$select->setTable($table);
$select->setIntegrityCheck(false);
$select = $select
->from(array('ru'=>'rules'),array('ru.*'))
->join(array('ro'=>'roles'),'ro.id=ru.role_id',array('role_id'=>'ro.id'))
->join(array('g'=>'groups'),'ro.group_id=g.id',array('group_id'=>'g.id'))
->join(array('ug'=>'user_groups'),"ug.group_id=g.id",array('user_group_id'=>'ug.id'))
->where("ug.user_id={$userId}")
->where("ru.resource='{$resource}'")
->where("ru.privilege='{$privilege}'");
echo "select: ".$select->__toString();
$row = $table->fetchAll();
I have the preceding code,but when I try fetchAll() it returns all rows in the table, ignoring the where clause, when I use fetchRow() it returns the first row it finds, ignoring the where clause, I printed the SQL statement and run it separately and it executes correctly
any clue ?
This is how you would create a db select object correctly
$db = Zend_Db::factory( ...options... );
$select = new Zend_Db_Select($db);
Or you use the database adapter's select() method
$db = Zend_Db::factory( ...options... );
$select = $db->select();
And you can add clauses
// Build this query:
// SELECT *
// FROM "table1"
// JOIN "table2"
// ON "table1".column1 = "table2".column1
// WHERE column2 = 'foo'
$select = $db->select()
->from('table1')
->joinUsing('table2', 'column1')
->where('column2 = ?', 'foo');
Have a look at the Zend_Db Reference Guide for more information
#ArtWorkAD is right in a certain way. But in your case you're not just using a Zend_Db_Select. You tried to extend a Zend_Db_Select obtained from a Zend_Db_Table (well, you should try to handle a Singleton pattern with Zend_Db_Table but this is another problem). Your current problem (if we except the fact you are certainly reading documentation too fast) is that this line was correct:
$select->setIntegrityCheck(false);
It make your 'select-from-a-zend-db-table' not anymore restricted to the Active Record Mode, and available for extra joins.
But just after that you make a:
$select = new Zend_Db_Select($table);
This is the complete creation of a new object, that you put into your variable. Nothing is kept from previous variable value. You could add a $select=null; just before it would be the same. So this is just canceling the 3 previous lines.
In quite the same confusion mode this line:
$select->setTable($table);
Is not necessary as you're already taking the select from a Zend_Db_Table so the table is already there.
EDIT
And your last and bigger error is:
$table->fetchAll()
You do not use your built $select but your $table, so effectively everything done in your $select is ignored :-) . Fecthing from the $select shoudl give you better results
This should work. Just tested it.
$table = new Zend_Db_Table('rules');
$select = $table->getAdapter()->select();
$select->from(array('ru' => 'rules'), array('ru.*'))
->join(array('ro'=>'roles'), 'ro.id = ru.role_id', array('role_id'=>'ro.id'))
->join(array('g'=>'groups'), 'ro.group_id = g.id', array('group_id'=>'g.id'))
->join(array('ug'=>'user_groups'),"ug.group_id=g.id",array('user_group_id'=>'ug.id'))
->where('ug.user_id = ?', $userId)
->where('ru.resource = ?', $resource)
->where("ru.privilege = ?", $privilege);
echo (string)$select;

Categories