I'm trying to figure out how to execute a SQL query from my MainActivity. I'm currently using a large portion of this example. Upon clicking my Acknowledge button, it finds the selected rows, gets the jsonID of said row, then I'm wanting to update a value in my SQLite table of those rows.
So my question is, how do I execute my "jsonQuery" string, to my SQLite database upon clicking my Acknowledge button?
Here's the code I have in my MainActivity:
acknowledge.setOnClickListener {
var jsonData_text: String = ""
for (i in 0 until JSONParser.MrAdapter.public_modelArrayList!!.size) {
if (JSONParser.MrAdapter.public_modelArrayList!!.get(i).getSelecteds()) {
jsonData_text = jsonData_text + JSONParser.MrAdapter.public_modelArrayList!!.get(i).getJSONID() + ","
}
}
val jsonSQLQuery = jsonData_text.dropLast(1)
val jsonQuery = "update Notes set acknowledged = 1 WHERE jsonID in ("+jsonSQLQuery+")"
Log.d("logged_json", jsonQuery)
}
Thanks for any help!
Related
I have the following realtime database schema:
schema
I'm working on a social app where a user can like another user. When the user clicks on the like button, a new entry will be added to myLikes->userId list
MyLike myLike = new MyLike(userId, System.currentTimeMillis();
FirebaseDatabase.getInstance().getReference().child("myLikes").child(userId).child(System.currentTimeMillis()).setValue(myLike);
When the new entry is completed, the cloud function gets triggered to write a new entry in whoLikedMe>userId list for the other User who has been liked.
exports.whoLikedMe = functions.database.ref('/myLikes/{userId}')
.onWrite((change, context) => {
// Only edit data when it is first created.
if (change.before.exists()) {
return null;
}
// Exit when the data is deleted.
if (!change.after.exists()) {
return null;
}
// Grab the current value of what was written to the Realtime Database.
const data2 = change.after.val();
const likedDate = data2.date;
const myUserId = data2.I_Liked_UserId;
var likedMe = {
date: likedDate,
Who_Liked_Me_UserId: myUserId,
}
//get the current date in millis
var hrTime = process.hrtime();
const dateMillis = hrTime[0];
return admin.database().ref('/WholikedMe/'+myUserId+'/'+hrTime[0]).set(likedMe);
});
The function gets triggered ok but no entries are inserted into the realtime database. What I'm doing wrong?
EDIT:
When I changed:
exports.whoLikedMe = functions.database.ref('/myLikes/{userId}')
with
exports.whoLikedMe = functions.database.ref('/myLikes/{userId}/915170400000')
(which adds the hardcoded timestamp to the path) all works fine. The problem is that the timestamp is constantly changing. any idea how to accomplish this with the timestamp?
You're using wildcard syntax (curly braces) in the following line:
return change.after.ref('/WholikedMe/{myUserId}/{hrTime[0]}').set(likeMe)
That syntax does not apply to a set statement. You need to use :
return change.after.ref('/WholikedMe/' + myUserId + '/' + hrTime[0]).set(likeMe)
... I think, doing this on my phone so can't double check. :-)
I figure d out. In addition to the syntax correction suggested by #GrahamD I had to change
exports.whoLikedMe = functions.database.ref('/myLikes/{userId}')
with
exports.whoLikedMe = functions.database.ref('/myLikes/{userId}/{timestamp')
and now all is working fine.
I have a list of notes in room database. I want to choose the list of specific notes depending on some characteristic. For this propose I add a second field note_second_id to a PrimaryKey:
#PrimaryKey(autoGenerate = true)
private long note_id;
private long note_second_id;
Then I create the next query:
#Query("SELECT * FROM " + Constants.TABLE_NAME_NOTE + " WHERE note_second_id = :second_id ")
List<Note> getNotes(long second_id);
When I want to add a new note I use:
long j = activityReference.get().dataBase.getNoteDao().insertNote(note);
deck.setNote_id(j);
deck.setNote_second_id(note000);
where methods .setNote_id(), and setNote_second_id() look like:
public void setNote_id(long deck_id) {this.note_id = note_id; }
public void setNote_second_id(long notesecondid) {
this.note_second_id = notesecondid; }
and note000 is a constant:
Long note000 = 11111L;
And in the activity, where I want these list to be shown I write:
private class RetrieveTaskDeck extends AsyncTask<Void,Void,List<Deck>> {
private WeakReference<MainActivity> activityReference;
// only retain a weak reference to the activity
RetrieveTaskDeck(MainActivity context) {
activityReference = new WeakReference<>(context); }
#Override
protected List<Note> doInBackground(Void... voids) {
if (activityReference.get()!=null)
return activityReference.get().dataBase.getNotesDao().getNotes(note000);
else
return null; }
#Override
protected void onPostExecute(List<Note> notes) {
if (notes !=null && notes.size()>0 ){
activityReference.get().notes.clear();
activityReference.get().notes.addAll(notes);
// hides empty text view
activityReference.get().textViewMsgDeck.setVisibility(View.GONE);
activityReference.get().decksAdapter.notifyDataSetChanged(); } } }
The problem is that this way does not work. It does not show any of the notes. Only when I use the query:
#Query("SELECT * FROM " + Constants.TABLE_NAME_NOTE)
List<Note> getAllNotes();
and
activityReference.get().dataBase.getNotesDao().getAllNotes();
only then I get the list of all notes, which I have. But I need only some specially marked notes to be shown.
What is wrong and what can I do? It seems like something is wrong with query... Maybe someone, who had an experience working with room databes and queries for it, may give some advice...
Actually, I have solved the problem. Here is a solution.
I used the next query:
#Query("SELECT * FROM " + Constants.TABLE_NAME_NOTE + " where note_content LIKE :second_id ")
List<Note> getNotes(String second_id);
Where "note_content" is a name of a column and "second_id" is a first row, written after the column name:
#ColumnInfo(name = "note_content")
private String second_id;
Pay attention, if I write String second_id somewhere after the first String value (second or third) after the proclamation of the column, it does not make search by this word. But in this way, written above, it works.
So, I can set this String value "second_id" of the column dynamically, depending on the task, and a user does not need to know that it even exists. I tried playing with ID in PrimaryKey to solve the same task, but it didn't work. Actually, using of the String value in Column works. Hope it will help someone. Also, if anyone knows how to solve the same task using IDs in PrimaryKey, let me know writing your solution here.
I am learning to fetching data from sqlite using anko. I can print the data successfully (if the record exist) but my application always crash when the data doesn't exist.
the error says:
parseSingle accepts only cursors with a single entry
I know exactly the meaning of error, I just dont know how to solve it.
here is the code for query:
fun getUserByUid(uid: Int): UserModel
{
val data = context.database.use {
val db = context.database.readableDatabase
val columns = UserModel.COLUMN_ID + "," + UserModel.COLUMN_NAME + "," + UserModel.COLUMN_API_KEY
val query = db.select(UserModel.TABLE_NAME, columns)
.whereArgs("(uid = {userId})",
"userId" to uid)
query.exec {
val rowParser = classParser<UserModel>()
parseSingle(rowParser) // this line that trigger error exception
}
}
return data
}
I tried to find count function in query or rowParser variable to check if the record exist or not but could not find it.
From the wiki page.
https://github.com/Kotlin/anko/wiki/Anko-SQLite#parsing-query-results
Parsing query results
So we have some Cursor, and how can we parse it into regular classes? Anko provides functions parseSingle, parseOpt and parseList to do it much more easily.
Method Description
parseSingle(rowParser): T Parse exactly one row
parseOpt(rowParser): T? Parse zero or one row
parseList(rowParser): List Parse zero or more rows
Note that parseSingle() and parseOpt() will throw an exception if the received Cursor contains more than one row.
I am trying to build a simple Library Management System for a class project. I am using SQLite to do that.
The app looks like this:
At first I select and load everything from the table, which works fine as seen in the above image:
Here is the create table query:
"CREATE TABLE IF NOT EXISTS books (id INTEGER PRIMARY KEY AUTOINCREMENT, title TEXT, isbn TEXT, category TEXT, authors TEXT, publisher TEXT, edition INTEGER, copies INTEGER, pdf TEXT, cover TEXT)";
Here is the query that selects the whole table:
"SELECT id, title, isbn, authors, publisher, edition, copies, pdf, cover FROM books ORDER BY id";
To implement the search functionality, I tried using the 'LIKE' clause, like this:
"SELECT id, title, isbn, category, authors, publisher, edition, copies, pdf, cover FROM books WHERE title LIKE %'"+userInput+"'% ORDER BY id";
When I search with the above query, I get this error:
TypeError: Error #1009: Cannot access a property or method of a null object reference.
at (address-removed)/BooksContainer.as:124]
And here is line 124:
var numResults:uint = result.data.length;
I tried to change the code but after working with for about a week, I still get the same error.
Yesterday, however I tried to approach it in a different as I was really frustrated and I was sure this approach would work. What I did is I selected the entire table like this:
public function searchBooks(userInput:String)
{
var stat:SQLStatement = new SQLStatement();
stat.sqlConnection = _connection;
stat.text = "SELECT id, title, isbn, category, authors, publisher, edition, copies, pdf, cover FROM books ORDER BY id";
//stat.parameters['#search'] = "%" + userInput + "%";
stat.execute();
trace(stat.text);
searchedString = userInput;
stat.addEventListener(SQLEvent.RESULT, createSearchedContent, false, 0, true);
}
private function createSearchedContent(e:SQLEvent):void
{
var result:SQLResult = e.target.getResult();
_allBooks = result;
trace(result.data);
var numResults:uint = result.data.length;
var currentY:Number = 0;
var xIterator:Number = 0;
for (var i:int = 0; i < numResults; i++)
{
var row:Object = result.data[i];
var bookTitle:String = String(result.data[i].title);
if (bookTitle.toLowerCase().indexOf(searchedString.toLowerCase()) > -1)
{
var book:Book = new Book(row.title, row.isbn, row.category, row.authors, row.publisher, row.edition, row.copies, row.pdf, row.cover);
book.x = book.width * xIterator + 10;
book.y = currentY;
addChild(book);
xIterator++;
if (xIterator == 7)
{
xIterator = 0;
currentY += book.height + 10;
}
}
}
}
Surprisingly enough, I got the same error. I didn't get it at all. Then I put this in the above loop:
var a:String = _main.search_txt.text.toLowerCase();
var b:String = String(row.title.toLowerCase());
trace(b.indexOf(a), a, b);
What I found out is that , in the trace I always get -1 for the searched term.
Here is the output window:
-1 data dark matter and the dinosaures
-1 data a history of religious ideas
-1 data steve jobs
-1 data digital logic design
-1 data thomas calculus
-1 data Data structures and algorithms in java
-1 data data structures in c++
-1 data data structures and algorithms in java
-1 data data structures and algorithms in java
So can any one help me out here?? I've only got a week to finish this project. Thanks in advance.
It looks that percent operators position issue.
Collect query
where something like '%foo%'
Your query
where something like %'foo'%
Put the percent operators inside single quotations.
"SELECT id, title, isbn, category, authors, publisher, edition, copies, pdf, cover FROM books WHERE title LIKE '%"+userInput+"%' ORDER BY id";
You also able to use like clause with parameters.
ActionScript and SQLite parameters on Select using Like
I am trying to fetch all the entries in a database table using SQLite. I ran a query, stored the values in a cursor and then via a loop I fetched all the values. However I can access all the entries except for the first one. Here is my code :
mydb1=new Database_CustomTransaction(getApplicationContext());
Cursor c12 = mydb1.executeQuery("Select * from table1");
System.out.println(c12);
if(c12 == null)
{
TextView nodataView = new TextView(this);
nodataView.setId(20);
nodataView.setText("No Data here !");
nodataView.setTextSize(20);
}
else
{
if(flagValue == false)
{
c12.moveToFirst();
flagValue = true;
}
while(c12.moveToNext())
{
type=c12.getString(0);
amount = c12.getInt(1);
spentOn = c12.getString(2);
date = c12.getString(3);
listType.add(i,type);
listSpentOn.add(i,spentOn);
listAmount.add(i,amount);
listDate.add(i,date);
i++;
}
}
latesttrans2.setAdapter(new TestAdapter2(this, listType, listSpentOn,listAmount,listDate));
Any ideas what I am doing wrong ?
c12.moveToFirst();
This moves to the first row.
while(c12.moveToNext())
This moves to the next row after the first row.
I would guess that the first call should be just dropped, but only you know what you intended with flagValue.
Use do while instead of using just while.I think it is skipping the first entry and straight away moving to next entry.