codeigniter change complex query into active record - sql

I have a codeigniter app.
My active record syntax works perfectly and is:
function get_as_09($q){
$this->db->select('m3');
$this->db->where('ProductCode', $q);
$query = $this->db->get('ProductList');
if($query->num_rows > 0){
foreach ($query->result_array() as $row){
$row_set[] = htmlentities(stripslashes($row['m3'])); //build an array
}
return $row_set;
}
}
This is effectively
select 'm3' from 'ProductList' where ProductCode='$1'
What I need to do is convert the below query into an active record type query and return it to the controller as per above active record syntax:
select length from
(SELECT
[Length]
,CONCAT(([width]*1000),([thickness]*1000),REPLACE([ProductCode],concat(([width]*1000),([thickness]*1000),REPLACE((convert(varchar,convert(decimal(8,1),length))),'.','')),'')) as options
FROM [dbo].[dbo].[ProductList]) as p
where options='25100cr' order by length
I picture something like below but this does not work.
$this->db->select(length);
$this->db->from(SELECT [Length],CONCAT(([width]*1000),([thickness]*1000),REPLACE[ProductCode],concat(([width]*1000),([thickness]*1000),REPLACE((convert(varchar,convert(decimal(8,1),length))),'.','')),'')) as options
FROM [dbo].[dbo].[ProductList]);
$this->db->where(options, $q);
$this->db->order(length, desc);
Help appreciated as always. Thanks again.

You can use sub query way of codeigniter to do this for this purpose you will have to hack codeigniter. like this
Go to system/database/DB_active_rec.php Remove public or protected keyword from these functions
public function _compile_select($select_override = FALSE)
public function _reset_select()
Now subquery writing in available And now here is your query with active record
$select = array(
'Length'
'CONCAT(([width]*1000)',
'thickness * 1000',
'REPLACE(ProductCode, concat((width*1000),(thickness*1000),REPLACE((convert(varchar,convert(decimal(8,1),length))),'.','')),'')) as options'
);
$this->db->select($select);
$this->db->from('ProductList');
$Subquery = $this->db->_compile_select();
$this->db->_reset_select();
$this->db->select('length');
$this->db->from("($Subquery)");
$this->db->where('options','25100cr');
$this->db->order_by('length');
And the thing is done. Cheers!!!
Note : While using sub queries you must use
$this->db->from('myTable')
instead of
$this->db->get('myTable')
which runs the query.
Source

Related

Typo3 9.5 - Custom flexform ordering, wrong backquotes in sql

i have an custom extension, where you can select the different entries at the backend, to show them at the list view. I have a custom sorting at my backend, but the system always sort them Descending.
I implemented an "orderBy" function, which doesnt work, because the system uses wrong backspaces.
My code looks like this:
I call the sort function in my "findByUid($uid)" function like this:
$query->setOrderings($this->orderByKey('uid', $uidArray));
protected function orderByKey($key, $uidlist) {
$order = array();
foreach ($uidlist as $uid) {
//$order["$key=$uid"] = \TYPO3\CMS\Extbase\Persistence\QueryInterface::ORDER_DESCENDING;
$order["$key=$uid"] = "ASC";
\TYPO3\CMS\Extbase\Utility\DebuggerUtility::var_dump($order);
}
return $order;
}
The result at the sql query is:
ORDER BY `tx_MYEXTENSION_domain_model_FIELD`.`uid=3` DESC
But it must be:
ORDER BY `tx_MYEXTENSION_domain_model_FIELD`.`uid` = 3 DESC
Is there a way to change this?
After a lot of search, I found this solution on an stackoverflow entry:
$ids = explode(',',$this->settings['entries'])
foreach($ids as $key => $id){
$entries[$id] = $this->entriesRepository->findByUid($id);
}
This code snippet has to be intergrated at the controller.
For me its working.

Laravel DB::update don't working, doing nothing at all, without any errors

I am learning how to run raw SQL queries and stuck at UPDATE operation.
I have route for INSERT:
Route::get('/insert', function (){
DB::insert('insert into posts (title, content) values (?, ?)', ['PHP with Laravel', 'Just testing']);
return 'after insert';
});
And route for SELECT:
Route::get('/read', function (){
$results = DB::select('select * from posts');
return var_dump($results);
});
After SELECT query I see:
/home/pavel/www_mysite/TestLaravel/routes/web.php:31:
array (size=1)
0 =>
object(stdClass)[239]
public 'id' => int 11
public 'title' => string 'PHP with Laravel' (length=16)
public 'content' => string 'Just testing' (length=12)
public 'created_at' => null
public 'updated_at' => null
public 'is_admin' => int 0
And at least UPDATE query:
Route::get('/update', function (){
DB::update('update posts set title = "Nothing here"');
});
After that query the new SELECT query shows the same data and in PHPPgAdmin I found no changes. I installed LaravelDebugBar and may see it at the bottom of the browser at pages for INSERT and SELECT queries, but don't see it at the page for UPDATE query. I cannot realize, where is the mistake.
try to use where clause.
example :
$affected = DB::update('update users set votes = 100 where name = ?', ['John']);
I tested you code too and it work
see this picture
I run your update code on my local environment (laravel 5.2, mysql 5.1). It's updated OK.
How about your log?
After some extra research I found that PostrgreSQL may store case-sensitive names of tables and columns. For that case you need to take their names in double quotes in your query. I think that when PostrgreSQL found double quotes in the query - it "thinks" that it is table/column name. But there is no column with those name.

Yii left join query

I want to execute the below sql query using Yii framework and need help on this.
SQL query
SELECT t.*, LP.name AS lp_name FROM `user` AS `t` LEFT JOIN `level_profiles` AS `LP` ON t.prof_i = LP.id WHERE t.bld_i IN (17)
So, i tried the below steps.
$usql = 't.bld_i IN (17)';
$criteria1 = new CDbCriteria;
$criteria1->select = 't.*, LP.*';
$criteria1->join = ' LEFT JOIN `level_profiles` AS `LP` ON t.prof_i = LP.id';
$criteria1->addCondition($usql);
$criteria1->order = 't.prof_i';
$result = User::model()->findAll($criteria1);
The above step is not allowing me to access the value from 'level_profiles' table.
Then, i tried to execute:
$usql = 't.bld_i IN (17)';
$result = User::model()->with('level_profiles', array(
'level_profiles'=>array(
'select'=>'name',
'joinType'=>'LEFT JOIN',
'condition'=>'level_profiles.id="prof_i"',
),
))->findAll($usql);
This is returning an error 'Relation "level_profiles" is not defined in active record class "User". '
I know this could be executed using the below method.
Yii::app()->db->createCommand('SELECT query')->queryAll();
But i dont want to use the above.
I am a beginner with Yii and tried to look into the forums. But, i am getting confused how to execute the query using "User::model()" approach .
class User extends CActiveRecord
{
......
public function relations()
{
return array(
'level_porfile_relation'=>array(self::BELONGS_TO, 'Level_Profiles_Modelname', 'prof_i'),
);
}
and your query will be:
$result = User::model()->with('level_porfile_relation')->findAll($usql);

How to get the result of the join operations?

Whenever I tried to execute this sql query in a function module in drupal I am not able to get the results but when I try to execute this in MySQL I can view the result. My code looks like this :
function _get_subject_sub_category() {
$options = array();
$sql = "SELECT father.Subject_Code, child.Subject_Category
FROM {subjects} as child
INNER JOIN {subjects} as father ON (child.Parent_Category = father.Subject_Code
AND child.Level =2 )";
$result = db_query($sql);
foreach ($result as $row) {
$options[$row->father.Subject_Code] = $row->child.Subject_Category;
}
return $options;
}
The error I encountered is in the line $options[$row->father.Subject_Code] = $row->child.Subject_Category;`.
Any help will be highly appreciated.
Try changing this line:
$options[$row->father.Subject_Code] = $row->child.Subject_Category;
To this:
$options[$row->Subject_Code] = $row->Subject_Category;
The name of the table is not in the result. If you need to avoid confusion, you can use alias in your SQL query.
I don't know drupal and don't use php, but I would say :
remove
father. in $row->father.Subject_Code
and
child. in $row->child.Subject_Category
as father and child are just db aliases.

Extbase - get created sql from query

i want to get some database tables from my typo3 extensions.
The Extension is based on extbase.
The query always returns nothing but the data exists
I've tried this:
$query = $this->createQuery();
$query->statement('SELECT * FROM `my_table`
WHERE field = ? ORDER BY date DESC LIMIT 1',
array($condition));
$results = $query->execute();
and this:
$query = $this->createQuery();
$query->matching($query->equals('field', $condition));
$query->setOrderings(array('date' => Tx_Extbase_Persistence_QueryInterface::ORDER_DESCENDING));
$query->setLimit(1);
$results = $query->execute();
both returns null as result.
Is it possible to get the sql that the class creates to look where the bug is?
I've looked in some extbase persistent classes but didn't find a clue
EDIT:
For those who are interested.. i found a "solution".
If you create the query with the statement() method, you can print the query with this function
echo $query->getStatement()->getStatement();
It doesn't replace the placeholder.
But you can get the Variables with this method
var_dump($query->getStatement()->getBoundVariables());
Thats the best Solution that i found, without editing the extbase extenstions
In TYPO3 6.2 you can use Extbase DebuggerUtility to debug the query.
Add this code before $query->execute():
$queryParser = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Extbase\\Persistence\\Generic\\Storage\\Typo3DbQueryParser');
\TYPO3\CMS\Extbase\Utility\DebuggerUtility::var_dump($queryParser->parseQuery($query));
For TYPO3 8.7+ use this code instead:
$queryParser = \TYPO3\CMS\Core\Utility\GeneralUtilityGeneralUtility::makeInstance(\TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbQueryParser::class);
$doctrineQueryBuilder = $queryParser->convertQueryToDoctrineQueryBuilder($query);
$doctrineQueryBuilderSQL = $doctrineQueryBuilder->getSQL();
$doctrineQueryBuilderParameters = $doctrineQueryBuilder->getParameters();
Check this snippet, although it's not very comfortable in use it helps a lot:
in general you need this code at the end of the buildQuery(array $sql) method (*) - right before return $statement;
if (in_array("your_table_name", $sql['tables'])) {
var_dump($statement);
print_r($statement);
}
(*) Class file:
TYPO3 ver.: 4.x: typo3/sysext/extbase/Classes/Persistence/Storage/Typo3DbBackend.php
TYPO3 ver.: 6.x: typo3/sysext/extbase/Classes/Persistence/Generic/Storage/Typo3DbBackend.php
In 6.2.x ...
You can try within \TYPO3\CMS\Core\Database\DatabaseConnection::exec_SELECTquery method, just add the condition after fetching the $query, like (trim is important!):
public function exec_SELECTquery($select_fields, $from_table, $where_clause, $groupBy = '', $orderBy = '', $limit = '') {
$query = $this->SELECTquery($select_fields, $from_table, $where_clause, $groupBy, $orderBy, $limit);
if (trim($from_table) == 'fe_users') {
DebuggerUtility::var_dump($query);
}
// rest of method
An easy way without changing any Typo3 core code and not mentioned in any forum so far is using the php "serialize()" method:
$result = $query->execute();
echo (serialize($result));
In the result object you find the SQL query ("statement;" ...)
Improvement to biesiors answer:
As Extbase replaces some placeholders after calling buildQuery(), you might prefer to place the debug output into getObjectDataByQuery(), just after $this->replacePlaceholders($sql, $parameters, $tableName);
if (strpos($sql, "your_table_name.")) {
debug($sql, 'my debug output');
};
Also, better use debug() instead of var_dump().
[File: typo3\sysext\extbase\Classes\Persistence\Generic\Storage\Typo3DbBackend.php. Line 339 in version 6.1]:
$query = $this->createQuery();
$query->getQuerySettings()->setReturnRawQueryResult(TRUE);
$getHotelInfo = 'SELECT * FROM `my_table` WHERE field = ? ORDER BY date DESC LIMIT 1';
return $query->statement($getHotelInfo)->execute();
For executing query you have to write 'setReturnQueryResult' on your repository
I just extended the above snippet, with a $_GET condition.
for debugging, just append "?dbg_table=tx_some_of_my_tables" to your address, and you're ready to go ;-)
if (in_array($_GET['dbg_table'], $sql['tables'])) {
echo('<div style="background: #ebebeb; border: 1px solid #999; margin-bottom: 20px; padding: 10px;"><pre style="white-space: normal">'.$statement.'</pre></div>');
}
A cleaner way to debug your statements when using TYPO3 6.1 is to use the query parser of Typo3DbBackend.
$parser = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Extbase\\Persistence\\Generic\\Storage\\Typo3DbBackend');
$params = array();
$queryParts = $parser->parseQuery($query, $params);
\TYPO3\CMS\Core\Utility\GeneralUtility::devLog('query', 'my_extension', 1, array('query' => $queryParts, 'params' => $params));
The parser returns an array containing the different parts of the generated SQL statement.
With TYPO3 6.2 the parseQuery method was moved to Typo3DbQueryParser and lost its second parameter.
i suggest set this in typo3conf/LocalConfiguration.php file under 'SYS' array
'SYS' => array(
......
'displayErrors' => 1,
'sqlDebug' => 1
.......
)
and then write wrong field name in query intentionally and then execute code.
this will show last query execute with error.