How can I make this query work in D7? - mysql

I'm trying to rewrite this database query from the line 52 of my template.php D6 site
$uid = db_query('SELECT pm.author FROM {pm_message} pm INNER JOIN {pm_index} pmi ON pmi.mid = pm.mid AND pmi.thread_id = %d WHERE pm.author <> %d ORDER BY pm.timestamp DESC LIMIT 1', $thread['thread_id'], $user->uid);
into D7 standards.
But it keeps giving me
Recoverable fatal error: Argument 2 passed to db_query() must be an
array, string given, called in
C:\wamp2\www\site-name\sites\all\themes\simpler\template.php on line
52 and defined in db_query() (line 2313 of
C:\wamp2\www\site-name\includes\database\database.inc).
This DB query is part of a template.php snippet that shows user pictures in Private Messages module, and makes it look like Facebook or other social networking site. You can see the full snippet here. Because Private Messages has a unified value $participants (or the message thread) this DB query is basically trying to isolate the last author except the current user.
What is the correct syntax?

As the error message says: 'Argument 2 passed to db_query() must be an array ...'.
Drupal 7 switched the database layer to use PDO, so placeholder replacement in db_query() changed a bit - try:
$query = 'SELECT pm.author FROM {pm_message} pm'
. ' INNER JOIN {pm_index} pmi ON pmi.mid = pm.mid AND pmi.thread_id = :thread_id'
. ' WHERE pm.author <> :uid'
. ' ORDER BY pm.timestamp DESC LIMIT 1';
$args = array(
':thread_id' => $thread['thread_id'],
':uid' => $user->uid,
);
$uid = db_query($query, $args)->fetchField();
Splitted and reformatted for readability. Untested, so beware of typos.
Note the ->fetchField() at the end - this will only work for queries returning exactly one field (like this one). If you need to fetch more fields or records, look at the DatabaseStatementInterface documentation.

Related

Codeigniter sql binding

How do I use Codeigniter SQL Binding if there are two target dates?
Is how I did it below correct?
public function getInvestmentForBorrowing($id, $Interest, $Currency, $Loantime, $target_date, $Risk_category)
{
$query = '
select CASE WHEN (a.amount_financed - a.amount_invested - a.amount_withdrawn) < a.amount_per_borrower
THEN round((a.amount_financed - a.amount_invested - a.amount_withdrawn), 2)
ELSE round((a.amount_per_borrower) , 2)
END AS investable_amount, a.*,
c.IBAN as Return_IBAN, c.BIC as Return_BIC,
i.average_rate
from investment a
inner join userinfo c
on a.Owner = c.Owner and
c.UPDATE_DT is null
inner join exchange_rates i
on a.Currency = i.currency_id and
? between i.effective_dt and i.expiration_dt
where a.ORIG_ID = ? and
a.Interest <= ? and
a.Currency = ? and
a.status = 2 and
a.Loantime >= ? and
a.Available >= ? and
a.Risk <= ? and
a.UPDATE_DT is null
having investable_amount > 0';
$query = $this->db->query($query, array($target_date, $id ,$Interest, $Currency, $Loantime ,$target_date ,$Risk_category));
$result = $query->result();
return $result;
}
Write now the question marks just represent the array so I added two $target_date to the array but not sure if thats the right way to do it.
It appears to be ok according to the codeigniter documentation but i say that without regard to your original SQL being correct or not.
Just make sure that the number of ? match the number of values you are providing and they are in the right order.
One way to sanity check it, apart from just running it, is to place the following command right after you perform the query:
echo $this->db->last_query();
And providing it known data, you can cheat and just hard code some dummy values for testing, take the generated SQL and throw that into something like phpmyadmin and run it the generated SQL against the Database and see if it works with the expected results.
Just a side note regarding your variable naming style. I see you are mixing cases i.e. things like $target_date (all lower case) and $Risk_category (First letter uppercase). Just be aware that on a linux based system case does matter and mixing like that can cause errors. It's a good idea to decide on one and stick with it.

DRUPAL PDOException: SQLSTATE[HY093]: Invalid parameter number: number of bound variables does not match number of tokens

I do not know what I am doing wrong here? Can someone please help me? When the following query is executed in Drupal7 custom module, I get the following error:
ERROR:
ResponseText: PDOException: SQLSTATE[HY093]: Invalid parameter number: number of bound variables does not match number of tokens:
SELECT t.tid AS tid, t.name AS name
FROM
{taxonomy_term_data} t
WHERE (t.vid = :vid) AND (LOWER(t.name) LIKE LOWER('%%:last_string%%'))
LIMIT 50 OFFSET 0;
Array
(
[:vid] => 6
[:last_string] => server
)
CODE:
$result = db_select('taxonomy_term_data', 't')
->fields('t', array('tid', 'name'))
->where('t.vid = :vid', array(':vid'=>$vid))
->where("LOWER(t.name) LIKE LOWER('%%:last_string%%')", array(':last_string'=>$last_string))
->range(0, $num_results)
->execute();
The query works if I directly hard code the value for :last_string,
Example:
->where("LOWER(t.name) LIKE LOWER('%%server%%')")
any help is much appreciated..
Try using only one % because: % is a substitute for zero or more characters. You don't need 2 of them.
The LOWER function takes a string as parameter and '%:last_string%' is taken as string not as a binding to the array(':last_string'=>$last_string), that's why it works when you remove the binding. So try to not put :last_string inside the LOWER function because it won't recognize it as a binding.

MySQL subquery not going into Array in PHP

I have the following PHP API which runs a MySQL query, when;
$sql = "select article_id, title, summary, image_url from articles limit 20";
I get the following result;
http://ec2-54-152-162-157.compute-1.amazonaws.com/list_view.php?user_id=1
the above is what I want the format of my output to look.
However when I change the $sql to below I get a blank screen;
$user_id = $_GET["user_id"];
$sql = "
select article_id, title, summary, image_url
from articles
where article_id in
(
select max(article_id) as last_article_id
from articles as a
join media_sources as ms
on a.rss_source_id = ms.media_source_id
where article_id not in
(
select article_id
from responses
where (activity_id = 1 and response = -1 and user_id = '1')
or (activity_id = 2 and user_id = '1')
)
group by category
) limit 20;"
$db = new mysqli("remotehost", "user", "password", "db_name");
$results = $db->query($sql);
$articles["items"] = array();
while($article = $results->fetch_assoc()){
$item = array ();
$item["article_id"] = $article['article_id'];
$item["article_title"] = $article['title'];
$item["article_summary"] = $article['summary'];
$item["article_image"] = $article['image_url'];
array_push($articles["items"], $item);
//echo json_encode($item);
}
echo json_encode($articles);
I've uncommented echo json_encode($item) in the 3rd from the bottom line of code; and put it in the below API. So there is data but I just can't get into the format I need.
http://ec2-54-152-162-157.compute-1.amazonaws.com/list_view2.php?user_id=1
**********************************EDIT******************************************
json_last_error_msg() returns:
Malformed UTF-8 characters, possibly incorrectly encoded.
So I guess there are characters that can not be encoded in Json, I will have to investigate and strip them out. but still not sure why this one works as it is the same data getting encoded;
echo json_encode($item);
If its working from MySQL console then the issue has to most likely be the credentials that the PHP script uses to connect (maybe it can't access something). Is it the same user? does the php user have permissions to create temporary tables and access all the data needed?
Or perhaps it takes to long and is error'ing out. Which command are you using for the php? Try echoing the error that you are getting back or checking the logs. If its failing it would tell you why it failed.
If its php i'd think its either the mysql user permissions, the php max_execution setting, php max memory
Added this line fixed it;
mysqli_set_charset($db, "utf8");

Invalid parameter number: number of bound variables does not match number of tokens

I have a table:
'objects' with few columns:
object_id:int, object_type:int, object_status:int, object_lati:float, object_long:float
My query is :
$stmt = $db->query('SELECT o.object_id, o.object_type, o.object_status, o.object_lati, o.object_long FROM objects o WHERE o.object_id = 1');
$res = $stmt->fetch();
PDO throws an error:
SQLSTATE[HY093]: Invalid parameter number: number of bound variables does not match number of tokens
When I remove column object_lati or object_long query is work fine.
Although this particular question is not a real one, as the code provided will never produce an error like this, it seems that Google is taking delight in sending visitors to this page. For whom is the answer that follows:
This problem can never be caused by query() method call, as it essentially belongs to prepared statement.
The error itself is pretty clear: "number of tokens" stands for the number of ? or :name tokens in the query (which also called "placeholders"), while "number of variables bound" stands for the variables that were ether bound via bindValue or `bindParam, or sent via execute (which is technically the same). So, when one tries to bind more variables than there were tokens defined in the query, PDO raises this error.
For example if there is a query prepared with no tokens defined, but we are trying to bind a variable to it:
$stmt = $db->prepare('SELECT * FROM objects o WHERE o.object_id = 1');
$stmt->execute(array($id));
then it will result in the very error message in question, as the number of bound variables (1) doesn't match the number of tokens (0).
To solve this problem one just have to carefully compare the number of tokens in the prepared query with the number of variables that were bound to the statement.
Try the statement like:
$stmt = $db->query('SELECT object_id, object_type, object_status, object_lati, object_long FROM objects o WHERE object_id = ? ', 1);
try this instead
$row = $db->fetchRow('SELECT o.object_id, o.object_type, o.object_status, o.object_lati, o.object_long FROM objects o WHERE o.object_id = 1');
// return false if no result found
or to get record set
$rs = $db->fetchAll('SELECT o.object_id, o.object_type, o.object_status, o.object_lati, o.object_long FROM objects o WHERE o.object_id = 1');
// returns array with results

MySQL Zend Framework - SQLSTATE[42000]: Syntax error or access violation: 1064

I've read every response I could fine on SO before posting this question. Although similar, none addressed my particular problem (or I didn't recognize them doing so).
I have a table class that extends Zend_Db_Table_Abstract. In the model, I'm trying to return a single row using a join() method and based on the table ID like this:
$getCategoryResults = $this->select();
$getCategoryResults->setIntegrityCheck(false)
->from(array('c'=> 'categories', '*'))
->join(array('e' => 'events'),'c.events_idEvent = e.idEvent', array())
->where("e.idEvent = ?", $idEvent);
when I echo the sql object, I get this:
SELECT `c`.* FROM `categories` AS `c`
INNER JOIN `events` AS `e` ON c.events_idEvent = e.idEvent
WHERE (e.idEvent = '1')
Oddly enough, if I use this format,
->where("e.idEvent = $idEvent");
my output is "WHERE (e.idEvent = 1)". The value is not enclosed in ticks, but either seems to work for MySQL. When I run the query in phpMyAdmin, I get this:
idCategory type displayOrder description localStartTime events_idEvent
1 individual 1 5k Run / Walk 2010-02-18 23:59:59 12 team 2 5k Team Category 2010-02-18 23:59:591 1
which is what I expected to see. But when I run my app in a browser, I get this ugliness:
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 'SELECT c.* FROM categories AS c INNER JOIN events AS e ON c.events_id' at line 1
I've checked every resource that I can think of. Hopefully, the combined awesomeness of SO uber-experts will make this my last stop. :D
Check out the second part of the error statement. Most likely it is regarding an access violation if the mysql elsewhere.
For reasons unknown to me, the app believed my $pageResult variable wasn't set. I discovered this after adding an isset() to the code like this:
try {
$getCategoryResults = $this->select();
$getCategoryResults->setIntegrityCheck(false)
->from(array('c'=> 'categories', '*'))
->join(array('e' => 'events'),'c.events_idEvent = e.idEvent', array())
->where("e.idEvent = ?", $idEvent);
if (isset($pageResult)) {
$pageResult .= $getCategoryResults;
}
else {
$pageResult = $getCategoryResults;
}
} catch (Exception $e) {
echo ( "Could not find matching categories for event id = $idEvent");
}
Problem went away which, of course, revealed the next problem lurking behind it. :D