Using Sequelize 4.38.1 against PostgreSQL 10.5, I have the following code:
const criteria = {
attended: '2018-09-21',
location: 'Squirrel Hill',
teacher: 'Doe, John',
classTitle: 'Yoga 1'
};
const sql = `
SELECT
"Attendances"._id,
"Attendances"."UserId",
"Users"."lastName" || ', ' || "Users"."firstName" AS name
FROM
"Attendances" INNER JOIN "Users" ON "Attendances"."UserId" = "Users"._id
WHERE
"Attendances".attended = :attended AND
"Attendances".location = :location AND
"Attendances".teacher = :teacher AND
"Attendances"."classTitle" = :classTitle
ORDER BY "Users"."lastName", "Users"."firstName";`;
sequelize.query(
sql,
{
replacements: criteria,
type: sequelize.QueryTypes.SELECT
})
.then(attendeeList => {
console.log(attendeeList);
return res.status(200).json(attendeeList);
})
With sequelize logging turned on, my query is correctly parameterized with the replacements and executed:
SELECT
"Attendances"._id,
"Attendances"."UserId",
"Users"."lastName" || ', ' || "Users"."firstName" AS name
FROM
"Attendances" INNER JOIN "Users" ON "Attendances"."UserId" = "Users"._id
WHERE
"Attendances".attended = '2018-09-21' AND
"Attendances".location = 'Squirrel Hill' AND
"Attendances".teacher = 'Doe, John' AND
"Attendances"."classTitle" = 'Yoga 1'
ORDER BY "Users"."lastName", "Users"."firstName";
The problem: my results (attendeeList) are getting returned as []. When I run the same query using pgAdmin, I get one row:
_id UserId name
40 24601 "Doe, John"
Anyone have any thoughts as to what I'm doing wrong?
I submitted the example above as an Issue on Sequelize's Github repo as I was able to make it work with a query that did not include an INNER JOIN.
For my situation, pg-native is a better fit (considering ripping out sequelize elsewhere as it's slower)...
const client = new PGNativeClient();
client.connect(config.sequelize.uri, err => {
if(err) {
res.status(401).json({ message: 'Not able to connect to database to get list of attendees.' });
return;
}
const sql = `
SELECT
"Attendances"._id,
"Attendances"."UserId",
"Users"."lastName" || ', ' || "Users"."firstName" AS name
FROM
"Attendances" INNER JOIN "Users" ON "Attendances"."UserId" = "Users"._id
WHERE
"Attendances".attended = $1::DATE AND
"Attendances".location = $2 AND
"Attendances".teacher = $3 AND
"Attendances"."classTitle" = $4
ORDER BY "Users"."lastName", "Users"."firstName";`;
const { attended, location, teacher, classTitle } = req.query;
client.query(sql, [attended, location, teacher, classTitle], (err, rows) => {
if(err) {
res.status(424).json({ message: 'Not able to retrieve attendees from database (but connected successfully).' });
return;
}
res.status(200).json(rows);
});
Related
I use the FETCH API to pull data from the backend, but since some time I am getting an empty paragraph at the beginning of each response. Unfortunately for me, I am not able to track down what change was made that has caused this, so I am looking for possible reasons why this would happen in order to eliminate it.
Below is once such fetch:
await fetch('__transport.php', {
method: "POST",
body: new URLSearchParams("pk="+pk+"&drvr="+drvr+"&col="+col)
})
.then(response => response.text())
.then((response) => {
if(response.substr(0,6) == "Failed") {
alert(response)
} else {
document.getElementById(id).innerHTML = response;
}
})
.catch(err => console.log('s/g went wrong', err));
and here the backend, the mysql query was removed from the end, but it returns a name
$pk = $_POST['pk'];
$drvr = ($_POST['drvr'] != 0 ? $_POST['drvr']:'NULL');
$col = $_POST['col'];
$sql = "UPDATE mytable
SET
$col = $drvr
WHERE pkcolumn = $pk";
if ($conn->Execute($sql)==false) {
exit("Failed to update database\n\n".$conn->ErrorMsg()."\n\n".$sql);
} else if($drvr != 'NULL'){
//mysql query removed for simplification as I get the same result with this
$name = "Jack Sparrow";
exit($name); //returns the name to the above FETCH
} else {
exit(' '); //returns no name as the field should be blank in this case
}
I am expecting the return "Jack Sparrow" to be received by the JavaScript in the variable "response", as:
"Jack Sparrow"
What I get is and empty paragraph followed by the name:
"
Jack Sparrow"
Let's say I am building a search that finds all the teacher and got an input where the user can put in the search term. I tried reading the phalcon documentation but I only see things like binding parameters. I read the other thread about needing prepare statements do I need that in Phalcon as well?
And my function in the model would be something like this:
public function findTeachers($q, $userId, $isUser, $page, $limit, $sort)
{
$sql = 'SELECT id FROM tags WHERE name LIKE "%' . $q . '%"';
$result = new Resultset(null, $this,
$this->getReadConnection()->query($sql, array()));
$tagResult = $result->toArray();
$tagList = array();
foreach ($tagResult as $key => $value) {
$tagList[] = $value['id'];
....
}
}
My question is for the Phalcon framework is there any settings or formats I should code for this line $sql = 'SELECT id FROM tags WHERE name LIKE "%' . $q . '%"';
And also any general recommendation for preventing SQL Injection in PhalconPHP controllers and index would be appreciated.
For reference:
My controller:
public function searchAction()
{
$this->view->disable();
$q = $this->request->get("q");
$sort = $this->request->get("sort");
$searchUserModel = new SearchUsers();
$loginUser = $this->component->user->getSessionUser();
if (!$loginUser) {
$loginUser = new stdClass;
$loginUser->id = '';
}
$page = $this->request->get("page");
$limit = 2;
if (!$page){
$page = 1;
}
$list = $searchUserModel->findTeachers($q, $loginUser->id, ($loginUser->id)?true:false, $page, $limit, $sort);
if ($list){
$list['status'] = true;
}
echo json_encode($list);
}
My Ajax:
function(cb){
$.ajax({
url: '/search/search?q=' + mapObject.q + '&sort=<?php echo $sort;?>' + '&page=' + mapObject.page,
data:{},
success: function(res) {
//console.log(res);
var result = JSON.parse(res);
if (!result.status){
return cb(null, result.list);
}else{
return cb(null, []);
}
},
error: function(xhr, ajaxOptions, thrownError) {
cb(null, []);
}
});
with q being the user's search term.
You should bind the query parameter to avoid an SQL injection. From what I can remember Phalcon can be a bit funny with putting the '%' wildcard in the conditions value so I put them in the bind.
This would be better than just filtering the query.
$tags = Tags::find([
'conditions' => 'name LIKE :name:',
'bind' => [
'name' => "%" . $q . "%"
]
])
Phalcon\Filter is helpful when interacting with the database.
In your controller you can say, remove everything except letters and numbers from $q.
$q = $this->request->get("q");
$q = $this->filter->sanitize($q, 'alphanum');
The shortest way for requests:
$q = $this->request->get('q', 'alphanum');
I want to get the contents from a row in the Postgresql database and compare the lowercase version of it to a lowercase version of a user input to check if it exists in the database.
i tried:
"SELECT LOWER(name) FROM user_names WHERE name LIKE '%$search%' ORDER BY name ASC"
but that make query not working at all.
EDIT
I am trying to implement an autocomplete Jquery UI like here:
http://jqueryui.com/demos/autocomplete/#remote
for search box (for names)
using javascript and php.
php code:
$search = ($_GET['term']);
if (!$con)
{ die('Could not connect: ' . pg_last_error ());}
else
{
$sql = "SELECT name FROM users_table WHERE name LIKE '%$search%' ORDER BY name ASC";
$result = pg_query($sql);
$json = '[';
$first = true;
while ($row = pg_fetch_array($result))
{
if (!$first) { $json .= ','; } else { $first = false; }
$json .= '{"value":"'.$row['name'].'"}';
}
$json .= ']';
echo $json;
exit();
}
JavaScript code:
$(document).ready(function()
{
$('#auto').autocomplete(
{
source: "./file.php",
minLength: 3
})
})
all above work great.. exactly like in Demo here: http://jqueryui.com/demos/autocomplete/#remote
my problem is that the names in database stored in Uppercase (e.g. LORI)
and of course the user prefers to insert a lowercase in search box to search for name (e.g. lori). but since it stored in uppercase, i need to convert it.
i tried as your suggestion :
$sql = "SELECT LOWER(name) FROM users_table WHERE name ILIKE '%$search%' ORDER BY name ASC";
then i got an empty drop down list!
pretty weird!
thanks in advance.
Google is your friend:
SELECT LOWER(name) FROM user_names
WHERE name ILIKE '%$search%' ORDER BY name ASC
How do I do this sql query in Zend Framework, I need to some how do this in the PDO context I think? I tried ->query but not sure if I am getting this right. The three variables are user_id and to and from date.
SELECT
ss.subcategory_id,
ss.subcategory_name,
ss.subcategory_issaving,
IFNULL(SUM(m.mv_monthly_total),0) AS expendsum
FROM
(SELECT
s.subcategory_id,
s.subcategory_name,
s.subcategory_issaving
FROM
subcategory s
WHERE
s.subcategory_isexpend = 'Y'
AND
s.subcategory_issaving = 'Y') ss
LEFT JOIN
mv_monthly m
ON ss.subcategory_id = m.mv_monthly_subcategory_id
AND m.mv_monthly_user_id = 2
AND m.mv_monthly_month >= '2010-01-01'
AND m.mv_monthly_month <= '2020-01-01'
GROUP BY
ss.subcategory_id,
ss.subcategory_name,
ss.subcategory_issaving
ORDER BY
ss.subcategory_issaving DESC,
expendsum;
I have tried the following with no luck
$db = Zend_Db_Table::getDefaultAdapter();
$dbExpr1 = new Zend_Db_Expr("s.subcategory_id, s.subcategory_name, s.subcategory_issaving");
$dbExpr2 = new Zend_Db_Expr("ss.subcategory_id, ss.subcategory_name, ss.subcategory_issaving, IFNULL(SUM(m.mv_monthly_total),0) AS expendsum");
$select = $db->select()
->from(
array(
'ss' => new Zend_Db_Expr(
'('. $db->select()
->from(array("s" => "subcategory"), $dbExpr1)
->where("s.subcategory_isexpend = 'Y'")
->where("s.subcategory_issaving = 'Y'") .')'
)
),
$dbExpr2
)
->joinLeft(array("m" => "mv_monthly"), "ss.subcategory_id = m.mv_monthly_subcategory_id")
->where("m.mv_monthly_user_id = ?", $user_id)
->where("m.mv_monthly_month >= ?", $fromMonth)
->where("m.mv_monthly_month <= ?", $toMonth)
->group(array("ss.subcategory_id","ss.subcategory_name","ss.subcategory_issaving"))
->order(array("ss.subcategory_issaving DESC", "expendsum"));
$row = $db->fetchAll($select);
For such a complex query, you can just execute it directly rather than using the object oriented approach as it gets fairly complicated with a query like that.
Try something like this, replacing my query with yours, and binding your variables into the query:
$db = Zend_Db_Table::getDefaultAdapter();
$stmt = new Zend_Db_Statement_Pdo($db, 'SELECT a, b, c FROM a WHERE username = ? AND date = ?');
try {
$res = $stmt->execute(array($user_id, $fromMonth));
if ($res) {
$rows = $stmt->fetchAll();
}
} catch (Zend_Db_Statement_Exception $dbex) {
// log Query failed with exception $dbex->getMessage();
}
If you prefer to use the object oriented approach, or need to because some parts of the query will be conditional, I usually build by subqueries up first as their own select, and you can simply embed those in to the main query with the select object for the subquery.
Here is what I mean by that:
$subselect = $this->getDbTable()
->select()
->from('mytable', array('time' => 'max(time)', 'id'))
->where('id IN (?)', $serialNumbers)
->group('id');
$select = $this->getDbTable()
->select()
->setIntegrityCheck(false)
->from('mytable')
->join('other', 'mytable.id = other.id', array('label'))
->join(array('dt' => $subselect),
'(mytable.time, mytable.id) = (dt.time, dt.id)', '');
You can get a list of friends of an authenticated user with:
https://graph.facebook.com/me/friends
Anyone have any idea how to order the list by user name? Because it doesn't by default. There's nothing in the documentation.
we do this in several apps just by sorting in javascript.
function sortByName(a, b) {
var x = a.name.toLowerCase();
var y = b.name.toLowerCase();
return ((x < y) ? -1 : ((x > y) ? 1 : 0));
}
var _friend_data = null
function lazy_load_friend_data(uid) {
if (_friend_data == null) {
FB.api('/me/friends', function(response) {
_friend_data = response.data.sort(sortByName);
}
)
}
}
Figured out a solution. Eventually, we'll probably be able to order graph results. For now, I'm just doing this (javascript). Assuming that I got "fb_uid" from my PHP session:
var friends = FB.Data.query("SELECT name, uid FROM user WHERE uid IN (SELECT uid2 FROM friend WHERE uid1={0}) ORDER BY name", parseInt(fb_uid));
friends.wait(function(rows){
console.log(rows);
});
I think the whole OpenGraph API is still in a bit of a transitional stage from FB Connect. In any case, I would just do a good old order-by query in FQL, which you can still use. I can't imagine it will be too hard to change once the open graph way of doing this gets established.
This very good tutorial shows you how to do it:
http://thinkdiff.net/facebook/php-sdk-graph-api-base-facebook-connect-tutorial/
$fql = "select name, hometown_location, sex, pic_square from user where uid=xxxxxxxxxxxxxxx";
$param = array(
'method' => 'fql.query',
'query' => $fql,
'callback' => ''
);
$fqlResult = $facebook->api($param);
What is the problem if you do it on caller side. That means, after you get all friends from that graph API, you can put all of them into a sorted data structure and then display all of them:)
Using FQL in one call.
SELECT uid, name FROM user WHERE uid IN
(SELECT uid2 FROM friend WHERE uid1 = me())
ORDER BY name ASC
for me a simple asort($friends); worked fine ;)
$friends = $facebook->api('me/friends');
foreach ($friends as $key=>$value) {
sort($value);
foreach ($value as $fkey=>$fvalue) {
echo "<img src='https://graph.facebook.com/".$fvalue[id]."/picture' width='50' height='50' title='".$fvalue[name]."' />";
}
}
Building off of #MainSocial's answer, but sorting by last then first name, instead of first name only:
function sortByName(a, b) {
var fn = function(x) { return x.name.toLowerCase(); };
var ln = function(x) { return x.last_name.toLowerCase(); };
if(ln(a) == ln(b)){
if(fn(a) == fn(b)) {
return 0;
}
return (fn(a) < fn(b)) ? -1 : 1;
}
return (ln(a) < ln(b)) ? -1 : 1;
}
function getFriendsList() {
FB.api('/me/friends', {fields: 'name,id,last_name'}, function(response) {
var friends = response.data.sort(sortByName);
for (i=0; i<friends.length; i++) {
$('body').append(friends[i].name + ' - ' + friends[i].id + '<br>');
}
});
}
getFriendsList()
private function _compareFacebookFriends($a, $b)
{
return strcasecmp($a['name'], $b['name']);
}
public function sortFacebookFriendsArray(&$array)
{
usort($array, '_compareFacebookFriends');
}
/* Add here $facebook's initialization. Use Facebook PHP SDK */
$fbFriends = $facebook->api('/me/friends');
sortFacebookFriendsArray($fbFriends);