I'm very much a beginner at Drupal development, MySQL, and pretty much everything, so this may seem trivial, but I would really appreciate any help I can get here.
I'm getting this error, and I'm not really sure what's wrong, because everything was working fine before, and I didn't change anything around the area that it mentions since the last time it was working perfectly.
The exact error is:
PDOException: SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'ASC' at line 3: SELECT n.nid AS nid FROM {node} n INNER JOIN {embryo_log} a ON n.nid = a.nid WHERE (n.type = :db_condition_placeholder_0) AND (a.expiration_date > :db_condition_placeholder_1_0) ORDER BY n.sticky DESC, n.changed DESC ASC; Array ( [:db_condition_placeholder_0] => embryo_log [:db_condition_placeholder_1_0] => -1 ) in embryo_log_all() (line 599 of /data/www/drupal-7.34/sites/all/modules/embryo_log/embryo_log.module)."
Here is the entire function that the error is referencing, because I don't know what might be relevant:
function embryo_log_all($option = NULL, $action = NULL) {
$nodes_per_page = variable_get('embryo_log_per_page', variable_get('default_nodes_main', 10));
$output = '<div class="embryo_log">';
// If the optional param is numeric, assume it is a node or term id.
if (is_numeric($option)) {
if ($action == 'group') {
// Get all embryo_log with this term.
// TODO Change fully to a dynamic query
$result = db_query("SELECT n.nid FROM {node} n LEFT JOIN {taxonomy_index} tn USING (nid) WHERE n.type = :n.type AND n.status = :n.status AND tn.tid = :tn.tid", array(':n.type' => 'embryo_log', ':n.status' => 1, ':tn.tid' => $option));
foreach ($result as $nid) {
$embryo_log = node_load($nid->nid);
$output .= '<h2>' . check_plain($embryo_log->title) . '</h2>';
$build = node_view($embryo_log);
$output .= drupal_render($build);
}
return $output . '</div>';
}
else {
$embryo_log = node_load($option);
// If it is an embryo_log, ok, else ignore it.
if ($embryo_log != NULL) {
if ($embryo_log->type == 'embryo_log') {
$build = node_view($embryo_log, 'full');
// Plain node title
$outp = '<h2>' . check_plain($embryo_log->title) . '</h2>';
$build['#node']->title = ''; // Don't render title
return $outp . drupal_render($build);
}
}
}
}
if (user_access('edit embryo_log')) {
$args = array(-1);
}
else {
$args = array(gmdate("U"));
}
// $query = "SELECT n.nid FROM {node} n INNER JOIN {embryo_log} a ON n.nid=a.nid
// WHERE n.type='embryo_log' AND a.expiration_date > %d
// ORDER BY " . variable_get('embryo_log_page_order', 'n.sticky DESC, n.changed DESC');
$query = db_select('node', 'n');
$query->extend('PagerDefault')
->limit($nodes_per_page);
$query->innerJoin('embryo_log', 'a', 'n.nid = a.nid');
$query->condition('n.type', 'embryo_log', '=')
->condition('a.expiration_date', $args, '>')
->fields('n', array('nid'))
->orderBy(variable_get('embryo_log_page_order', 'n.sticky, n.changed'), '');
// $query_result = pager_query(db_rewrite_sql($query, 'n', 'nid'), $nodes_per_page, 0, NULL, $args);
$query_result = $query->execute();
foreach ($query_result as $nid) {
$embryo_log = node_load($nid->nid);
$build = node_view($embryo_log, $option);
$output .= drupal_render($build);
}
$output .= '</div>';
$output .= theme('pager', array('tags' => NULL));
return $output;
}
And the line in there that is specifically being referenced in the error (line 599) is the one towards the bottom that says $query_result = $query->execute();
Any help would be greatly appreciated, because everything looks fine to me, and I'm at a loss.
Thanks!
Related
I'm working on a system that has several server-side datatables but i facing issues with 2 joins when i try to order de columns.
I receive the following message when try to sort the columns:
Query error: Column 'notes' in order clause is ambiguous - Invalid query: SELECT *
FROM `tbl_project`
LEFT JOIN `tbl_client` ON `tbl_project`.`client_id`=`tbl_client`.`client_id`
LEFT JOIN `tbl_account_details` ON `tbl_project`.`created_by` = `tbl_account_details`.`user_id`
LEFT JOIN `tbl_notes` ON `tbl_project`.`notes` = `tbl_notes`.`notes_id`
WHERE `tbl_project`.`client_id` = '100'
ORDER BY `notes` DESC
LIMIT 10
This is the code with my query:
$id = $this->input->post("client_id");
$client_details = get_row('tbl_client', array('client_id' => $id));
$draw = intval($this->input->post("draw"));
$start = intval($this->input->post("start"));
$length = intval($this->input->post("length"));
$order = $this->input->post("order");
$search= $this->input->post("search");
$search = $search['value'];
$col = 0;
$dir = "";
if(!empty($order))
{
foreach($order as $o)
{
$col = $o['column'];
$dir= $o['dir'];
}
}
if($dir != "desc" && $dir != "desc")
{
$dir = "desc";
}
$valid_columns = array(
0=>'project_id',
1=>'client',
2=>'fullname',
3=>'notes',
4=>'origen',
5=>'end_date',
6=>'project_status',
7=>'action',
);
if(!isset($valid_columns[$col]))
{
$order = null;
}
else
{
$order = $valid_columns[$col];
}
if($order !=null)
{
$this->db->order_by($order, $dir);
}
$searchQuery = "";
if($search != ''){
$searchQuery = " (tbl_project.project_id like'%".$search."%' OR tbl_project.end_date like'%".$search."%' OR tbl_project.project_status like'%".$search."%' OR tbl_notes.notes like'%".$search."%' OR tbl_notes.eco like'%".$search."%' OR tbl_account_details.origen like'%".$search."%' OR tbl_client.name like'%".$search."%') ";
}
$this->db->select('*');
$this->db->from('tbl_project');
$this->db->join('tbl_client', 'tbl_project.client_id=tbl_client.client_id','left');
$this->db->join('tbl_account_details', 'tbl_project.created_by = tbl_account_details.user_id','left');
$this->db->join('tbl_notes', 'tbl_project.notes = tbl_notes.notes_id','left');
$this->db->where('tbl_project.client_id', $client_details->client_id);
if($searchQuery != '')
$this->db->where($searchQuery);
$this->db->limit($length,$start);
$cita = $this->db->get()->result();
For some reason the ORDER BY is not set as tbl_notes.notes
Any suggestion on how to fix this?
Thanks in advance
EDIT: i have added more code so there is more visibility of the process
The error occurs, because your column name is not unique, it exists in more than one table.
append the table name of the searched column to your query to make it unique:
for example in this line:
$this->db->order_by('my_table_name.'.$order, $dir);
that would generate something like
ORDER BY `my_table_name.notes` DESC
edit: or in case you have to address columns from several different tables you could change your $valid_columns array:
$valid_columns = array(
0=>'my_table_name1.project_id',
1=>'my_table_name2.client',
2=>'my_table_name2.fullname',
3=>'my_table_name3.notes',
// etc.
);
and maintain the remaining original code.
I have an website there are 5 categories, i only want to show the 1-4 category only in the new posts..how can I edit the code to do this job? thanks
Here is my code, and I do that in my sql by using following code:
SELECT * FROM `ff_se` WHERE Wid in ('1','2','3','4')"
but i dont know how to do that in php code. following is my part of php code:
$this->TableSe = 'ff_se';
$this->TableSeWord = 'ff_se_word';
$this->TableSeSupport = 'ff_se_support';
$this->TableSePost = 'ff_se_post';
$this->TableSePostTableId = 'ff_se_post_tableid';
public function GetAjaxList($Get){
$Results = array();
$Get = $this->StrToGBK($Get);
$Page = $Get['page'] ? intval($Get['page']):0;
$Where = '';
$Order = 'S.updateline';
if($Get['type'] == 'New'){
$Order = 'S.dateline';
}else if($Get['type'] == 'Hot'){
$Order = 'S.updateline';
if($this->Config['PluginVar']['ListHotVal']){
$Where .= ' and (S.support_count >= '.$this->Config['PluginVar']['ListHotVal'].' OR S.comment_count >= '.$this->Config['PluginVar']['ListHotVal'].')';
}
if($this->Config['PluginVar']['ListHotDataline']){
$Where .= ' and S.dateline >= '.strtotime("-".$this->Config['PluginVar']['ListHotDataline']." hours",time());
}
}else if($Get['type'] == 'Nearby'){//
$Order = 'S.updateline';
if($Get['lng'] && $Get['lat']){
$SquarePoint = $this->GetReturnSquarePoint($Get['lng'],$Get['lat'],$this->Config['PluginVar']['Distance']);
$Where .= ' and S.lat <> 0 and S.lat > '.$SquarePoint['right-bottom']['lat'].' and S.lat < '.$SquarePoint['left-top']['lat'].' and S.lng > '.$SquarePoint['left-top']['lng'].' and S.lng < '.$SquarePoint['right-bottom']['lng'];
}else{
return $Results;
}
}
if($_GET['wid']){
$Where .= ' and S.wid = '.intval($_GET['wid']);
}
$Where .= ' and S.display = 1 and S.fast_add_display = 1';
$Where = preg_replace('/and/','where',$Where,1);
$this->Config['PluginVar']['ListNum'] = $this->Config['PluginVar']['ListNum'] ? $this->Config['PluginVar']['ListNum'] : 10;
$Limit = 'LIMIT '.($Page * $this->Config['PluginVar']['ListNum']).','.$this->Config['PluginVar']['ListNum'];
$FetchSql = 'SELECT W.title as Ttitle,S.* FROM '.DB::table($this->Tablese).' S LEFT JOIN '.DB::table($this->TableSeWord).' W on W.id = S.wid '.$Where .' order by topdateline > '.time().' desc,'.$Order.' desc,S.dateline desc '.$Limit;
$Results = $this->ListFormat(DB::fetch_all($FetchSql));
return $Results;
}
I think you should try and understand the code first before you modify it ... but anyway:
You would only need to append the condition to the where clause generated in the PHP code.
You could do that by adding THE LINE MARKED "THIS LINE IS NEW" after this line:
$Where = '';
And this is the relevant part of the code:
$Where = '';
$Order = 'S.updateline';
if($Get['type'] == 'New'){
$Where .= ' and S.wid in (1,2,3,4)'; //THIS LINE IS NEW
$Order = 'S.dateline';
}else .......
As you can see any redundant initial "and"s are replaced with "where" here:
$Where = preg_replace('/and/','where',$Where,1);
so this should work - assuming that $Get['type'] == 'New' means that this is a new post which I can only guess.
I'm having an issue preparing a SQL statement:
$statement = $conexion->prepare(
'SELECT * FROM celulares
WHERE (MARCA = :marca )
AND
(CATEGORIA = :categoria1 OR CATEGORIA = :categoria2 OR CATEGORIA = :categoria3)
AND
(CATEGORIA2 = :categoria1 OR CATEGORIA2 = :categoria2 OR CATEGORIA2= :categoria3)
AND
(CATEGORIA3 = :categoria1 OR CATEGORIA3 = :categoria2 OR CATEGORIA3 = :categoria3)');
Giving placeholders values with this:
$statement->execute(array(':categoria1' => $categoria1,
':categoria2' => $categoria2,
':categoria3' => $categoria3,
':marca' => $query
));
$query value may variate when my application begins depending on some results:
if ($entrada == "LG") {
if ($query == "") {
$query = "LG";
} else {
$query = $query . ' OR MARCA = "LG" ';
}
}
if ($entrada == "APPLE") {
if ($query == "") {
$query = "APPLE";
} else {
$query = $query . ' OR MARCA = "APPLE" ';
}
}
if ($entrada == "HUAWEI") {
if ($query == "") {
$query = "HUAWEI";
} else {
$query = $query . ' OR MARCA = "HUAWEI" ';
}
}
I tried a lot of things, but none of those worked out it returns an empty array, the only one who works was changing this line of my prepared statement:
WHERE (MARCA = :marca OR MARCA = :marca2 OR MARCA = :marca3 )
And as many "MARCA" as results, i think it's not the best way to do it
UPDATED:
Now trying with IN Statement in my Query (Thanks you all for helping me)
Now it looks like:
$marcas = array("LG", "HUAWEI"); (Static values for test)
$inQuery = implode(',', array_fill(0, count($marcas), '?'));
$statement = $conexion->prepare(
'SELECT * FROM celulares
WHERE (MARCA = IN (' . $inQuery . '))
AND
(CATEGORIA = :categoria1 OR CATEGORIA = :categoria2 OR CATEGORIA = :categoria3)
AND
(CATEGORIA2 = :categoria1 OR CATEGORIA2 = :categoria2 OR CATEGORIA2= :categoria3)
AND
(CATEGORIA3 = :categoria1 OR CATEGORIA3 = :categoria2 OR CATEGORIA3 = :categoria3)');
foreach ($marcas as $k => $marca) {
$statement->bindValue(($k+1), $marca);
}
$statement->bindValue(':categoria1', $categoria1);
$statement->bindValue(':categoria2', $categoria2);
$statement->bindValue(':categoria3', $categoria3);
$statement->execute();
Getting: Warning: PDOStatement::execute(): SQLSTATE[HY093]: Invalid parameter number: mixed named and positional parameters
Trying to fix it
You can simplify your query:
SELECT * FROM celulares
WHERE (MARCA = :marca )
AND (:categoria1,:categoria2,:categoria3)
IN (
(CATEGORIA,CATEGORIA2,CATEGORIA3),
(CATEGORIA,CATEGORIA3,CATEGORIA2),
(CATEGORIA2,CATEGORIA,CATEGORIA3),
(CATEGORIA2,CATEGORIA3,CATEGORIA),
(CATEGORIA3,CATEGORIA,CATEGORIA2),
(CATEGORIA3,CATEGORIA2,CATEGORIA)
)
This way you only pass in the categories once, and compare it against the six possible permutations of three categories.
That being said, this is a sign that your database is in very poor shape. Generally speaking having any kind of "column2", "column3" system is a sign that you need to restructure your database - the kind of queries you end up with, like the above, are only going to get worse.
Specifically, in this case, just adding CATEGORIEA4 would increase the amount of permutations you need to define from 6 to 24!!
EDIT: I completely missed the part about :marca and IN - I was too focussed on the bad state of the database with regard to categories, sorry!
Well, i fix it, probably it's not the best way to solve it but i have this now:
I fill array with entries from POST
$query = array();
$index = 0;
foreach ($_POST as $entrada) {
switch($entrada) {
case "SAMSUNG":
$query[] = "SAMSUNG";
break;
case "LG":
$query[] = "LG";
break;
case "APPLE":
$query[] = "APPLE";
break;
case "HUAWEI":
$query[] = "HUAWEI";
break;
}
}
$inQuery = str_repeat('?,', count($query) - 1) . '?';
Here's my new query: Problem was that i was mixing "?" with placeholders (:) which not is recommended
$statement = $conexion->prepare(
"SELECT * FROM celulares
WHERE ( MARCA IN($inQuery))
AND
(CATEGORIA = ? OR CATEGORIA = ? OR CATEGORIA = ?)
AND
(CATEGORIA2 = ? OR CATEGORIA2 = ? OR CATEGORIA2= ?)
AND
(CATEGORIA3 = ? OR CATEGORIA3 = ? OR CATEGORIA3 = ?)");
Then i bindValues like that
$c = 0;
foreach ($query as $q => $queries) {
$c++;
$statement->bindValue(($q+1), $queries);
}
$statement->bindValue($c+1, $categoria1);
$statement->bindValue($c+2, $categoria2);
$statement->bindValue($c+3, $categoria3);
$statement->bindValue($c+4, $categoria1);
$statement->bindValue($c+5, $categoria2);
$statement->bindValue($c+6, $categoria3);
$statement->bindValue($c+7, $categoria1);
$statement->bindValue($c+8, $categoria2);
$statement->bindValue($c+9, $categoria3);
$statement->execute();
$resultados = $statement->fetchAll();
I did many test with a lot of querys and it's working fine, probably it's a "dirty" solution but i'll continue learning
Thanks u all for helping me!
I have some if statements in my code.
e.g:
if($option[0]->posts == 1 && $option[0]->pages == 1){
$results = $wpdb->get_results( 'SELECT * FROM '.$wpdb->prefix.'posts WHERE post_status="publish" AND (post_type="page" OR post_type="post") ORDER BY post_title ASC', OBJECT );
}
if($option[0]->pages == 1 && $option[0]->posts == 0){
$results = $wpdb->get_results( 'SELECT * FROM '.$wpdb->prefix.'posts WHERE post_status="publish" AND post_type="page" ORDER BY post_title ASC', OBJECT );
}
if($option[0]->pages == 0 && $option[0]->posts == 1){
$results = $wpdb->get_results( 'SELECT * FROM '.$wpdb->prefix.'posts WHERE post_status="publish" AND post_type="post" ORDER BY post_title ASC', OBJECT );
}
a bit pseudo code of the code above:
if foo = 1 and bar = 1 -> return foo and bar
if foo = 0 and bar = 1 -> return only bar
if foo = 1 and bar = 0 -> return only foo
if foo = 0 and bar = 0 -> return false
You see:
00
10
01
11
00
If I insert another variable I'll get a lot of more opportunities and that is realy bad. Because I'll get realy big if statements.
Can somebody tells me another opportunitie to achive the same result?
Thank you.
I'd do it like this:
$sql_condition = '( 1=2 '; // one fake-condition, just to make it possible to start with 'OR' later
foreach($option[0] as $key => $value) { // iterate through all possible conditions
if($value===1) { // maybe exclude $keys that should not be used here
$sql_condition.=' OR post_type="'.$key.'"';
}
}
$sql_condition.=')';
$results = $wpdb->get_results( 'SELECT * FROM '.$wpdb->prefix.'posts WHERE post_status="publish" AND '.$sql_condition.' ORDER BY post_title ASC', OBJECT );
Please try this code :
$sub_query = $operator = '';
if($option[0]->posts == 1)
{
$sub_query = 'post_type="page"';
$operator = ' OR';
}
if($option[0]->pages == 1)
{
$sub_query .= $operator.' post_type="post"';
}
if(empty($sub_query))
{
return false;
}
else
{
$results = $wpdb->get_results( 'SELECT * FROM '.$wpdb->prefix.'posts WHERE post_status="publish" AND ('.$sub_query.') ORDER BY post_title ASC', OBJECT );
}
Create an array($arr) and set the key like "0,0" and value like "$sql";
and your code will be like this:
$tempKey = $option[0]->pages . "," . $option[0]->posts;
if(isset($arr[$tempKey]) {
$results = $wpdb->get_results($arr[$tempKey]);
}
So when you want to add more pages and posts all you will do is to change the arr.
$types = [];
if ($option[0]->posts)
$types[] = '"post"';
if ($option[0]->pages)
$types[] = '"page"';
if (!$types)
return null;
$results = $wpdb->get_results( 'SELECT * FROM '.$wpdb->prefix.'posts WHERE post_status="publish" AND (post_type IN ('. implode(',', $types) .')) ORDER BY post_title ASC', OBJECT );
I want to fetch contents with multiple filters, right now there's only one.
For Example:
SELECT * FROM Table1 WHERE status=true AND category = 'Camera' AND
model = 'Samsung' AND type = 'New'
I want to create an array for it. But as I'm a newbie in this one not getting a lead.
function getAllRequests($filter){
if(empty($filter)){
$addfilter = '';
}else{
$addfilter = 'AND cat_id=' . $filter;
}
}
$sql = 'SELECT * FROM Table1 WHERE status=true' . $filter;
Any help will be appreciated.
This will get you closer to the solution, though it will not replace the cat_id in the query, which will certainly be wrong - though impossible to do too much more without the array structure:
function getAllRequests($filter)
{
$addfilter="";
if(!empty($filter))
{
foreach($filter as $val)
{
$addfilter. = ' AND cat_id=' . $val .'\'';
}
}
return $addFilter;
}
$myFilters=getAllRequests($filter);
$sql = 'SELECT * FROM Table1 WHERE status=true' . $myFilters;
On the other hand, if your array is strucutred in a way like this:
array{ category => camera, model => samsung); // etc
you could use the following:
function getAllRequests($filter)
{
$addfilter="";
if(!empty($filter))
{
foreach($filter as $key => $val)
{
$addfilter. = " AND `$key` = '$val'";
}
}
return $addFilter;
}
$myFilters=getAllRequests($filter);
$sql = 'SELECT * FROM Table1 WHERE status=true' . $myFilters;
Edit: You can loop through all the filters in the following manner:
function getAllRequests()
{
$addfilter="";
if(!empty($_REQUEST))
{
foreach($_REQUEST as $key => $val)
{
$addfilter. = " AND `$key` = '$val'";
}
}
return $addFilter;
}
$myFilters=getAllRequests();
$sql = 'SELECT * FROM Table1 WHERE status=true' . $myFilters;
You don't need to pass the $_REQUEST (which will work for both GET and POST) as it already a superglobal.
function getAllRequests($filter){
if(empty($filter)){
$addfilter = '';
}else{
$addfilter = 'AND cat_id=' . $filter;
}
}
$sql = 'SELECT * FROM Table1 WHERE status=true' . $addfilter;
You can use another approach, which is using optional parameters and it will make your WHERE clause dynamic as you want. In this approach you pass all parameters' values directly to the sql query which should look like so:
SELECT *
FROM Table1
WHERE 1 = 1
AND (#status IS NULL OR status = #statusParam)
AND (#category IS NULL OR category = #categoryParam)
AND (#model IS NULL OR model = #modelParam)
AND (#type IS NULL OR type = #typeParam)
Then If any of the parameters #statusParam, #categoryParam, #modelParam or #typeParam passed to the query with NULL values, then the comparison with the column holding that value will be ignored. I used the predicate 1 = 1, in case all the values passed to the query with all NULL values in the case all the WHERE clause will be ignored as it won't presented, since WHERE 1 = 1 always true and it will be like SELECT * FROM Table1.
use this
function getAllRequests($filter){
if(empty($filter)){
$addfilter = '';
}else{
$addfilter .= 'AND cat_id=' . $filter;
}
return $addfilter;
}
$sql = 'SELECT * FROM Table1 WHERE status=true' . getAllRequests($filter);
When you are sending array make sure it has indexes
$conditions = array('category' => 'Camera', 'model' => 'Samsung' , 'type' => 'New')
Now loop through it. in your else condition
foreach($conditions as $key =>$value){
$addfilter .= 'AND ' . $key . ' = ' . $value;
}