In the following code, I am trying to query the database based on three parameters (search type, search term, operator that connects different search types in one query). As you can see, I gave it two search types along with their terms so that the query will be like search where the author is WayneRooney AND the tag is UCL. Later, it might have more than two search types such as search based on author x, author y, mention z, and tag a.
var search = ['Author','Tag'];
var term = ['WayneRooney','UCL'];
var operator = 'AND';
var queryString = "select Tweet.ID, Tweet.Label, Tweet.TDate, Tweet.RetweetID, User.Name, User.ScreenName from Tweet, User where";
for(var i in search){
if(search.indexOf(search[i]) != 0){
queryString += operator;
}
if(search[i] == 'Author')
{
queryString += "Tweet.UserID IN (select ID from User where ScreenName = '"+ term[i] +"') AND User.ID IN (select ID from User where ScreenName = '"+ term[i] +"')";
}
else if(search[i] == 'Mention')
{
queryString += "select Tweet.ID, Tweet.Label, Tweet.TDate, User.ScreenName, User.Name, Tweet.RetweetID from Tweet, User where Tweet.ID IN (select TweetID from TweetMention where UserID IN (select ID from User where ScreenName = '"+ term[i] +"')) AND User.ID = Tweet.UserID";
}
else if(search[i] == 'Tag')
{
queryString += "select Tweet.ID, Tweet.Label, Tweet.TDate, User.Name, User.ScreenName, Tweet.RetweetID from Tweet, User where Tweet.ID IN (select TweetID from TweetHashs where HashID IN (select ID from Hashtag where Label = '"+ term[i] +"')) AND User.ID = Tweet.UserID";
}
};
var query = connection.query(queryString, function(err, rows) {
if (err) {
throw (err);
}
console.log(rows);
//res.write(JSON.stringify(rows));
var tweet = JSON.parse(JSON.stringify(rows));
var queries_made = 0;
var queries_success = 0;
The error that I got is:
Error: ER_PARSE_ERROR: 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 '.UserID IN (select ID from User where ScreenName = 'WayneRooney') AND User.ID IN'at line 1
I tried to figure out what the problem is but I couldn't.
You're missing prepended spaces when appending to your queryString, otherwise you get run-on keywords like: whereTweet.UserID IN ... or ANDTweet.UserID IN ....
Related
I've started to learn SQL, I'd appreciate some insight and help on the below issue. My task is to: write a query in SQL workbench which returns names and surnames of users with more than 2 posts written (the query copied below). This part seems to work fine.
Then display in test class in a loop names and surnames of users that have published at least 2 posts.
How to write a code that creates that query in the test class? Basically I get syntax error and I'm not sure how it should look like("Column 'POSTS_NUMBERS' not found.").
(then another part of exercise follows - add posts and then check by assertion if the actual number of records in the data base is the same as result of the query)
SELECT USERS.FIRSTNAME, USERS.LASTNAME, USERS.ID, COUNT(*) AS POSTS_NUMBER
FROM USERS
JOIN POSTS ON USERS.ID = POSTS.USER_ID
GROUP BY POSTS.USER_ID
HAVING COUNT(*) >= 2;
#Test
public void testSelectUsersAndPosts() throws SQLException {
//given
DbManager dbManager = DbManager.getInstance();
String countQuery = "SELECT COUNT(*) FROM USERS"; //IS THIS PART CORRECT?
Statement statement = dbManager.getConnection().createStatement();
ResultSet rs = statement.executeQuery(countQuery);
int count = 0;
while (rs.next()) {
System.out.println(rs.getInt("POSTS_NUMBERS") + ", " +
rs.getString("FIRSTNAME") + ", " +
rs.getString("LASTNAME"));
}
String sql = "INSERT INTO POSTS(USER_ID, BODY) VALUES ('3', 'I am Mark')";
statement.executeUpdate(sql);
sql = "INSERT INTO POSTS(USER_ID, BODY) VALUES ('3', 'hey!')";
statement.executeUpdate(sql);
//when
String sqlQuery = "SELECT * FROM USERS";
statement = dbManager.getConnection().createStatement();
rs = statement.executeQuery(sqlQuery);
//then
int counter = 0;
while (rs.next()) {
System.out.println(rs.getInt("USERS.ID") + ", " +
rs.getString("FIRSTNAME") + ", " +
rs.getString("LASTNAME"));
counter++;
int expected = count + 1;
Assert.assertEquals(expected, counter);
rs.close();
statement.close();
}
}
I'm trying make solution by Using MOODLE create users and enroll them in courses via SQL
Add user - done
Add user to course - done
But user without role into course. No roles in role column.
'googleoauth2' as auth value for login with social network API. It's work.
The problem is remains If I change 'auth' value to 'manual'.
Into database all records as in queries.
Help, please.
UPD: sorry, I need to change enlorID to courseID in instanceid field...
Code:
async function test(){
var query = `INSERT INTO mdl_user (auth, confirmed, username, password, firstname, lastname, email, mnethostid)
VALUES ('googleoauth2', 1, '${pseudo}', 'not cached', '${name}',
'${secondname}', '${email}', 1);`;
var insertOutput = await getMysqlQuery(query);
var userId = insertOutput.results.insertId;
var courseRecords = await getMysqlQuery("SELECT id FROM mdl_course WHERE idnumber=\"" + shortname + "\"");
if(courseRecords.length < 1)
throw 'Course not found';
var courseId = courseRecords.results[0].id;
var enrolRecords = await getMysqlQuery(`SELECT id FROM mdl_enrol WHERE courseid=${courseId} AND enrol='manual';`);
if(enrolRecords.length < 1)
throw 'Enrol not found';
var enrolId = enrolRecords.results[0].id;
var contextRecords = await getMysqlQuery(`SELECT id FROM mdl_context WHERE contextlevel=50 AND instanceid=${courseId};`);
if(contextRecords.length < 1)
throw 'Context not found';
var now = (new Date()).getTime() / 1000 ;
var contextId = contextRecords.results[0].id;
await getMysqlQuery(`INSERT INTO mdl_user_enrolments (status, enrolid, userid,
timestart, timeend, timecreated, timemodified) VALUES
(0, ${enrolId}, ${userId}, '${now}', '${now + 60*60*24*2}', '${now}', '${now}')`);
await getMysqlQuery(`INSERT INTO mdl_role_assignments
(roleid, contextid, userid, timemodified)
VALUES (5, ${contextId}, '${userId}', '${now}');`);
}
It looks like you are using JavaScript. I have a solution to enroll the student in course with a role in PHP programming language as below.
$plugin = enrol_get_plugin('manual');
$course = $DB->get_record('course', array('id' => $courseid)); // Get course object by courseid
$instance = $DB->get_record('enrol', array('courseid' => $course->id, 'enrol' => 'manual'));
if (empty($instance)) {
// Only add an enrol instance to the course if non-existent.
$enrolid = $plugin->add_instance($course);
$instance = $DB->get_record('enrol', array('id' => $enrolid));
}
// Take care of timestart/timeend in course settings.
$timestart = time();
// Remove time part from the timestamp and keep only the date part.
$timestart = make_timestamp(date('Y', $timestart), date('m', $timestart), date('d', $timestart), 0, 0, 0);
if ($instance->enrolperiod) {
$timeend = $timestart + $instance->enrolperiod;
} else {
$timeend = 0;
}
// Enrol the user with this plugin instance.
$plugin->enrol_user($instance, $user->id, $roleid); // This will enroll user in course with roleid you provided.
am trying to creating a search function to be able to search for products and also filter the result by relevance but i got Syntax error after the query.
below is the error i got too
sql error
SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'mens', 'winter', 'jacket'%',6,0) + if (title LIKE '%'mens'%',5,0) + if (title LI' at line 5
The SQL being executed was: SELECT p.product_id,p.title,p.price,p.unit_sold,
p.profile_img,p.store_name,p.item_number,
(
(-- Title score
if (title LIKE '%'mens', 'winter', 'jacket'%',6,0) + if (title LIKE '%'mens'%',5,0) + if (title LIKE '%'winter'%',5,0) + if (title LIKE '%'jacket'%',5,0)
)+
(-- description
if (description LIKE '%'mens', 'winter', 'jacket'%',5,0) + if (description LIKE '%'mens'%',4,0) + if (description LIKE '%'winter'%',4,0) + if (description LIKE '%'jacket'%',4,0)
)
) as relevance
FROM products p
WHERE p.is_active = '1'
HAVING relevance > 0
ORDER BY relevance DESC,p.unit_sold DESC
LIMIT 10
and the search function
function search($q){
if (mb_strlen(trim($q))===0){
// no need for empty search
return false;
}
$query = $this->limitChars(trim($q));
// Weighing scores
$scoreFullTitle = 6;
$scoreTitleKeyword = 5;
$scoreFullDescription = 5;
$scoreDescriptionKeyword = 4;
$keywords = $this->filterSearchKeys($query);
$escQuery = $this->escape($keywords);
$titleSQL = array();
$descSQL = array();
/** Matching full occurences **/
if (count($keywords) > 1){
$titleSQL[] = "if (title LIKE '%".$escQuery."%',{$scoreFullTitle},0)";
$descSQL[] = "if (description LIKE '%".$escQuery."%',{$scoreFullDescription},0)";
/** Matching Keywords **/
foreach($keywords as $key){
$titleSQL[] = "if (title LIKE '%".Yii::$app->db->quoteValue($key)."%',{$scoreTitleKeyword},0)";
$descSQL[] = "if (description LIKE '%".Yii::$app->db->quoteValue($key)."%',{$scoreDescriptionKeyword},0)";
}
//add 0 is query string is empty to avoid error
if (empty($titleSQL)){
$titleSQL[] = 0;
}
if (empty($descSQL)){
$descSQL[] = 0;
}
$sql = "SELECT p.product_id,p.title,p.price,p.unit_sold,
p.profile_img,p.store_name,p.item_number,
(
(-- Title score
".implode(" + ", $titleSQL)."
)+
(-- description
".implode(" + ", $descSQL)."
)
) as relevance
FROM products p
WHERE p.is_active = '1'
HAVING relevance > 0
ORDER BY relevance DESC,p.unit_sold DESC
LIMIT 10";
$results = Yii::$app->db->createCommand($sql)->queryAll();
if (!$results){
return false;
}
return $results;
}
I'm also using escape() method to escape the query string in other to avoid sql injection but am not so convince this is the best practice as what the escape method does is adding single quote around the string which in turn will not even return any match in the table, I also try to use mysqli_escape_string() but can't get it work either, so i want to know what's the best practice in Yii2 to escape query string and avoid sql injection attack.
function escape($values)
{
$values = (array)$values;
$escaped = array();
foreach($values as $value) {
if(!is_scalar($value)) {
throw new CException('One of the values passed to values() is not a scalar.');
}
$escaped[] = Yii::$app->db->quoteValue($value);
}
return implode(', ', $escaped);
}
You should escape the whole expression for LIKE, including % wildcards:
$value = Yii::$app->db->quoteValue('%' . implode(', ', (array) $keywords) . '%');
$titleSQL[] = "if (title LIKE $value,$scoreFullTitle,0)";
This will generate something like:
if (title LIKE '%mens, winter, jacket%',6,0)
I add two users and two roles in the webpages_UsersInRoles. I am trying to check to role of the user logging into the application.
Here is my code:
var UserId = WebSecurity.GetUserId(HttpContext.Current.User.Identity.Name);
var User = WebSecurity.CurrentUserName;
var db = Database.Open("ApplicationServices");
var stQueryString = "SELECT * FROM Table1 WHERE (UserId) = (UserId) ORDER BY SubmitDate DESC";
var data = db.Query(stQueryString, UserId);
var grid = new WebGrid(data, rowsPerPage:20);
var AdminQueryString = "SELECT * FROM Table1 ORDER BY SubmitDate DESC";
var AdminData = db.Query(AdminQueryString);
var AdminGrid = new WebGrid(AdminData, rowsPerPage:20);
<div id="Divgrid">
#if (Roles.IsUserInRole(UserId, "admin") && (AdminData.Any())){
#AdminGrid.GetHtml(
tableStyle: "grid",
headerStyle: "grid-header",
footerStyle: "grid-footer",
alternatingRowStyle: "grid-alternating-row",
selectedRowStyle: "grid-selected-row",
rowStyle: "grid-row-style",
columns: AdminGrid.Columns(
AdminGrid.Column(header:"", format:#View),
AdminGrid.Column(header:"", format:#Treatment),
AdminGrid.Column("Name", format:#<text>#item.ClientName</text>),
AdminGrid.Column("Date", format:#<text>#item.SubmitDate</text>))) }
else if (Roles.IsUserInRole(UserId, "user") && (data.Any())) {
#grid.GetHtml(
tableStyle: "grid",
headerStyle: "grid-header",
footerStyle: "grid-footer",
alternatingRowStyle: "grid-alternating-row",
selectedRowStyle: "grid-selected-row",
rowStyle: "grid-row-style",
columns: grid.Columns(
grid.Column(header:"", format:#View),
grid.Column(header:"", format:#Treatment),
grid.Column("Name", format:#<text>#item.ClientName</text>),
grid.Column("Date", format:#<text>#item.SubmitDate</text>))) }
</div>
Here is the error I am getting:
CS1502: The best overloaded method match for 'System.Web.Security.Roles.IsUserInRole(string, string)' has some invalid arguments
The IsUserInRole takes two parameters, the first is the User name, not the user ID. You may be able to use WebSecurity.CurrentUserName in place of where you have UserID.
One problem is the query needs to change to allow passing the username as a parameter:
var stQueryString = "SELECT * FROM Table1 WHERE UserId = #0 ORDER BY SubmitDate DESC";
The #0 indicates to take the parameter being passed in the Query.
what is wrong with this logic?
var selectString = 'SELECT EXISTS(SELECT 1 FROM users WHERE user="'+username+'")';
var queryUserExists = connection.query(selectString);
var resultsLength = queryUserExists._results.length;
console.log(queryUserExists);
if(resultsLength > 0){
socket.write("fail user already exists"+"\r\n");
} else {
console.log('insert=');
var query = connection.query (
'INSERT INTO users '+
'SET user = ?, password = ?, token = ?',
[username, password, token]
);
socket.write("success"+"\r\n");
}
resultsLength is always returned zero.
What is the proper way to use this query?
returned object:
sql: 'SELECT 1 FROM users WHERE user = \'a new user is my name\' ORDER BY user LIMIT 1',
typeCast: true,
nestTables: false,
_resultSet: null,
_results: [],
_fields: [],
_index: 0,
_loadError: null }
The proper code: thanks to https://stackoverflow.com/users/722783/mahmoud-gamal for the database query that is optimized!
connection.query("SELECT 1 FROM users WHERE user = '"+username+"' ORDER BY user LIMIT 1", function (error, results, fields) {
if (error) {
console.log(error);
socket.write("fail internal error"+"\r\n");
}
if (results.length > 0) {
console.log('fail');
socket.write("fail user already exists"+"\r\n");
} else {
console.log('insert');
var query = connection.query (
'INSERT INTO users '+
'SET user = ?, password = ?, token = ?',
[username, password, token]
);
socket.write("success"+"\r\n");
}
console.log(results);
});
Try this:
SELECT 1
FROM users
WHERE EXISTS (SELECT 1
FROM users
WHERE user = 'username')
ORDER BY user
LIMIT 1;
Or: Why not:
SELECT 1
FROM users
WHERE user = 'username'
ORDER BY user
LIMIT 1;
Note that:
ORDER BY user
LIMIT 1;
Are just for performance.