I am new to mobile development and I would like to perform simple queries like deleting a row a specific from my sqlite table. But It doesnt work.The row still exits in my database table
This is my code:
export default class App extends Component{
constructor(props){
super(props);
db = SQlite.openDatabase(
{
name: 'gad.db',
createFromLocation: 1,
},
this.successToOpenDB,
this.failToOpenDB,
);
}
successToOpenDB()
{
db.transaction(tx =>
{
tx.executeSql("DELETE FROM songs WHERE content='content2' ", [] ,(tx, results) =>
{
console.log('DELETION OK');
},
(tx, error) =>
{
console.log("DELETION KO");
});
});
}
failToOpenDB(err){
console.log(err);
alert("not connected to database");
}
Please anyone help.
Thanks in advance
Must be some issue with primary key, if primary key is your condition to delete,
or "content" here.
First try to retrieve primary key of the row you want to delete, and store in
some state maybe:
var deleted= results.rows.item(length-1).ID
I have primary key as ID, so I am now able to get required row.
also, after delete query you can check any rows affected or not in promise returned as follows:
(tx, results) => {
if( results.rowsAffected >0) {
//then proceed ahead.
}
}
Related
I'm using NestJS with mikro-Orm and have a weird behaviour on all of my manyToMany relations.
#ObjectType()
#Entity()
export class Realty {
#Field(() => ID)
#PrimaryKey({ columnType: "uuid" })
id: string = v4();
#Field(() => [Contact])
#ManyToMany(() => Contact, (contact) => contact.realties)
contacts: Collection<Contact>;
}
#ObjectType()
#Entity()
export class Contact {
#Field(() => ID)
#PrimaryKey({ columnType: "uuid" })
id: string = v4();
#Field(() => [Realty])
#ManyToMany(() => Realty, (realty) => realty.contacts, { owner: true })
realties: Collection<Realty>;
}
When I want to delete a realtyReference from a contact, that works fine and the row from the Contact_Realty PivotTable gets removed. But when I try to delete a contactReference from a realty, nothing happens. Does that only work on the owning side?
ContactsService (works):
async update(updateContactInput: UpdateContactInput) {
const { id, realtyIds } = updateContactInput;
const contact = await this.findOneOrFail(id);
const updated = this.contactsRepository.assign(contact, {
realties: await this.realtiesService.find(realtyIds),
});
await this.contactsRepository.persistAndFlush(updated);
return updated;
}
RealtiesService (returns correct updated entity but doesnt remove row in PivotTable):
async update(updateRealtyGeneralInput: UpdateRealtyGeneralInput) {
const { id, contactIds } = updateRealtyGeneralInput;
const realty = await this.realtiesService.findOneOrFail(id);
const updated = this.realtiesRepository.assign(realty, {
contacts: await this.contactsService.find(contactIds),
});
await this.realtiesRepository.persistAndFlush(updated);
return updated;
}
Both return the correct updated entity but only the ContactsService actually removes the row in the pivotTable.
Would really appreciate some help, thanks alot!
I want to remove one or more contacts from a realty and cannot get it to work. Am I doing something wrong?
You always need to have the owning side of your M:N collection initialized/populated, which you apparently don't in the second example. In your case it is Contact.realties, so if you want to manipulate this collection from the inverse side, all the entities you add/remove from the inverse need to have the owning side populated. Only owning side is what is taken into account when computing changesets. I will need to revisit this a bit, we might be able to improve on this thanks to the recent changes like the reference updates added in v5.5.
Also, there is some misunderstanding in your code. assign mutates the parameter, it does not return "modified entity", it mutates the one you pass in the first argument. If that entity is already managed (as in your case), there is no point in re-persisting it again, just flush.
async update(updateRealtyGeneralInput: UpdateRealtyGeneralInput) {
const { id, contactIds } = updateRealtyGeneralInput;
const realty = await this.em.findOneOrFail(Realty, id);
this.realtiesRepository.assign(realty, {
contacts: await this.em.find(Contact, contactIds, { populate: ['realties'] }),
});
await this.em.flush(updated);
return realty;
}
I'm new to using Express.js. I'm working on my first endpoint which is to create a user. To accomplish this, it first has to be checked whether the username or email address already exists. After some research on how to do this, here's the code I've come up with:
// Check whether the user_name or email already exists
pool.query('SELECT CASE WHEN EXISTS (SELECT * FROM users WHERE user_name = $1 OR email = $2) THEN CAST(1 AS BIT) ELSE CAST(0 AS BIT) END', [values.user_name, values.email], (error, results) => {
if (error) {
throw error
}
if (results.rows[0].case === '1') {
console.log('User exists so send message to this effect back to client');
} else {
console.log('User does not exist so we can call INSERT query');
pool.query('INSERT INTO users (first_name, last_name, user_name, email, password, last_password, password_salt) VALUES ($1, $2, $3, $4, $5, $6, $7) RETURNING *', [values.first_name, values.last_name, values.user_name, values.email, values.password, values.password, 'tmp_salt'], (error, results) => {
if (error) {
console.error('Something went wrong');
throw error;
}
console.log('Results from INSERT:', results);
res.status(201).send(`User added with user_id: ${results.rows[0].user_id}`);
});
}
});
It's obviously not finished yet but I'm curious if this nested approach I've used is the best way to do it? In other words, first I'm checking for the existence of user_name and/or email and only if both don't exist am I performing the INSERT.
What do you think?
There are really two different questions there:
Is checking then inserting the right approach?
Is nesting the right approach?
Is checking then inserting the right approach?
Not usually, no, it leaves you open to a race condition:
Client A sends joe#example.com / funkypassword
Client B sends joe#example.com / somethingelse
The main thread picks up the task for Client A's request and starts the asynchronous check to see if the user exists
While waiting for that asynchronous result, the main thread picks up Client B's request and starts the asynchronous check to see if the user exists
Both checks come back clear (no user exists)
The main thread inserts one of those sets of details (Client A's or Client B's)
The main thread tries to insert the other one of those sets of details (Client B's or Client A's)
At this point, if the database is set up correctly, you'll get an insertion error (primary or unique key violation).
Instead, you ensure the DB is set up that way and expect to get an error if the user already exists, and don't do the check at all. Just do the insert, and look at the error if you get one to see if it's a primary or unique key constraint violation.
Is nesting the right approach?
This particular task may not need multiple DB operations (see above), but many others will. So is nesting the right way to handle that?
It's certainly been the main way to handle it for a long time, but it has the issue of quickly becoming "callback hell" where you have lots of nested operations, each in its own callback to a previous operation, etc., etc. It can get very hard to manage. But you can do it that way if you like, and many have done for some time.
The more modern alternative is to use promises and async/await. In an async function, you can make the function wait for an asynchronous process to complete before continuing with its logic. That way, your logic isn't buried in callbacks.
Suppose you have to do two or three database operations, where whether it's two or three depends on the first operation's result, and where information from earlier calls is needed by later ones. With nesting, you might do something like this:
pool.query("DO THE FIRST THING", (error1, results1) => {
if (error1) {
/*...handle/report error...*/
return;
}
const thirdThing = (results2) => {
pool.query("DO THE THIRD THING with results1 and results2 (which may be null)", (error3, results3) => {
if (error3) {
/*...handle/report error...*/
return;
}
/*...finish your work using `results1`, `results2`, and `results3`...*/
});
};
if (/*results1 says we should do the second thing*/) {
pool.query("DO THE SECOND THING with results1", (error2, results2) => {
if (error2) {
/*...handle/report error...*/
return;
}
thirdThing(results2);
});
} else {
thirdThing(null);
}
});
You might isolate the three operations as functions, but while that's good for reuse if it's relevant and possibly for debugging, it doesn't help much with the callback hell:
function firstThing(callback) {
pool.query("DO THE FIRST THING", callback);
}
function secondThing(paramA, callback) {
pool.query("DO THE SECOND THING with paramA", callback);
}
function thirdThing(paramA, paramB, callback) {
pool.query("DO THE THIRD THING with paramA and paramB (which may be null)", callback);
}
// ...and then where your code was:
const done = (error, results1, results2, results3) => {
if (error) {
/*...handle/report error...*/
} else {
/*...do your final work here using `results1`, `results2` (which may be `null`), and `results3`...*/
}
});
firstThing((error1, results1) => {
if (error1) {
done(error1);
} else if (/*results1 says we should do the second thing*/) {
secondThing(results1, (error2, results2) => {
if (error2) {
done(error2);
} else {
thirdThing(results1, results2, (error3, results3) => {
done(error3, results1, results2, results3);
});
}
});
} else {
thirdThing(results1, null, (error3, results3) => {
done(error3, results1, null, results3);
});
}
});
But suppose we had a poolQuery function that put a promise wrapper around pool.query. Here's how that could look:
async function firstThing() {
return await poolQuery("DO THE FIRST THING");
}
async function secondThing(paramA) {
return await poolQuery("DO THE SECOND THING with paramA");
}
async function thirdThing(paramA, paramB) {
return await poolQuery("DO THE THIRD THING with paramA and paramB (which may be null)");
}
// ...and then where your code was, making it an `async` function:
try {
const results1 = await firstThing();
const results2 = (/*results1 says we should do the second thing*/)
? await secondThing(results2)
: null;
const results3 = await thirdThing(results1, results2);
/*...do your final work here using `results1`, `results2` (which may be `null`), and `results3`...*/
} catch (error) {
/*...handle/report error...*/
}
Or if you aren't going to reuse those queries, then:
try {
const results1 = await poolQuery("DO THE FIRST THING");
const results2 = (/*results1 says we should do the second thing*/)
? await poolQuery("DO THE SECOND THING with results1")
: null;
const results3 = await poolQuery("DO THE THIRD THING with results1 and results2 (which may be null)");
/*...do your final work here using `results1`, `results2` (which may be `null`), and `results3`...*/
} catch (error) {
/*...handle/report error...*/
}
How simple and clear is that? :-) It gets even more powerful when you have loops and such involved.
I'm using Vue alongside with Apollo in order to query a GraphQL endpoint in my project. Everything's fine but I want to start programming generic components to ease and fasten the development.
The thing is, in most views, I use the Smart Query system.
For instance, I use :
apollo: {
group: {
query: GROUP_QUERY,
variables () { return { id: this.groupId } },
skip () { return this.groupId === undefined },
result ({ data }) {
this.form.name = data.group.name
}
}
}
With the GROUP_QUERY that is :
const GROUP_QUERY = gql`
query groupQuery ($id: ID) {
group (id: $id) {
id
name
usersCount
userIds {
id
username
}
}
}
`
So my group variable in my apollo smart query has the same name as the query itself group (id: $id). It is this mechanism that is quite annoying for what I try to achieve. Is there a way to avoid that default mechanism ?
I'd like for instance to be able to give a generic name such as record, and it would be records for queries that potentially return multiple records.
With that, I would be able to make generic components or mixins that operate either on record or records.
Or have I to rename all my queries to record and records which would be annoying later on in case of troubleshooting with error messages ?
Or maybe there's another way to achieve that and I didn't think about it ?
Thanks in advance.
You can, in fact, rename the variable of Apollo smart queries using the update option, as seen here in the Vue Apollo documentation. Your example would look like:
apollo: {
record: {
query: GROUP_QUERY,
variables () { return { id: this.groupId } },
update: (data) => data.group,
skip () { return this.groupId === undefined },
result ({ data }) {
this.form.name = data.group.name
}
}
}
You should notice that the Apollo object will create a record variable in your component, and the update statement shows where to get the group for the record.
By doing so :
const GROUP_QUERY = gql`
query groupQuery ($id: ID) {
record: group (id: $id) {
id
name
usersCount
userIds {
id
username
}
}
}
`
If the GROUP_QUERY is used at several places, the result will be accessible under the record name, because it is defined as an alias over group.
See documentation for Aliases.
I have a number of companies in the Vuex Store. Each company object has several objects within it ... to simplify for my question, imagine
company{ id: 1, approval_notes: [{id: 1}, {id: 2}, {id: 3}], fins:
{total_rev: 10000} }
I want to remove the approval_note with id of 2 from the company with the id of 1.
In the view, I have
deleteNote(obj) {
if(confirm('Are you sure you want to delete this note?')) {
let path = '/api/approval_notes/' + obj.id;
axios.delete(path)
.then(function(rsp) {
this.$store.dispatch('delete_approval_note', obj);
}.bind(this))
.catch(function (err) {
console.log('AXIOS ERR', err);
}.bind(this));
}
}
The action is
export const delete_approval_note = ({commit}, payload) => {
commit('DELETE_APPROVAL_NOTE', payload);
};
And the mutation is
export const DELETE_APPROVAL_NOTE = (state, payload) => {
_.each(state.companies, function(co) {
if(co.id = payload.company_id) {
let notes = co.approval_notes;
notes.splice(notes.indexOf(payload), 1);
}
});
};
The note is deleted from the database but the view does not update without a page refresh.
This type of thing I will be doing a bunch so it's important to me to understand this process since I obviously don't get it right now.
Any help is appreciated.
Instead of IndexOf, using
notes.findIndex(obj => obj.id == payload.id)
It can get tricky when using IndexOf with complex object, I mostly rely on indexOf if dealing with simple values (integers, strings, booleans)
Still a little new to Node but this is driving me nuts. I have looked around but cannot find an existing answer that has helped me yet. I know I'm missing something stupid I'm sure. My elements appear to be mapping correctly. I have triple checked my columns and my values. I've even taken the SQL query from my debug session in Visual Studio code and run it directly in DBVis, no issues. But for some reason when I run this in Node I always get "Error: SQLITE_RANGE: bind or column index out of range". Are there any known issues with mapping elements in node and SQLite Im unfamiliar with?? Im using the map function and sql function in other places and it seems to be working fine. Just not here.
Here is the relevant code.
exports.createUserGoogle = createUserGoogle;
function createUserGoogle(jsonObj, cb) {
var sql = "Begin;"
+"Insert into userGoogle (googleId,token,name,email,photoid) values ($googleid,$googleToken,$name,$email,$photoid);"
+"Commit;";
doSQL(sql, mapDataElements(jsonObj), cb);
}
My mapping function
function mapDataElements(jsonObj) {
dataObj = {};
for (key in jsonObj) {
dataObj['$' + key] = jsonObj[key];
}
console.log('mapDataElements: Mapped as: ' + JSON.stringify(dataObj));
return dataObj;
}
My Standard SQL Promise function
function doSQL(sqlStr, bindings, cb) {
var p = new Promise((resolve, reject) => {
db.serialize(() => {
db.run(sqlStr, bindings, (err) => {
if (err) {
console.log('SQL failed: ' + JSON.stringify(bindings));
reject(err);
}
else {
console.log('SQL succeeded: ' + sqlStr);
resolve();
}
});
});
});
p.then(
(data) => {
console.log('Doing callback');
cb('success');
},
(err) => {
cb(null, err);
}
);
}
Also here are what my mapped elements look like (slightly edited for security):
mapDataElements: Mapped as: {"$googleid":"mylongnumber","$googleToken":"myreallylongtokenvalue","$name":"My name","$email":"my.email#gmail.com","$photoid":1}
Any my table if it helps
CREATE TABLE userGoogle(
pk_google INTEGER NOT NULL PRIMARY KEY,
googleId TEXT,
token TEXT,
name TEXT,
email TEXT,
photoid int,
FOREIGN Key(photoid) References photo(pk_photo)
);
I solved similar problem by using db.exec() instead of db.run(). As db.exec() doesn't accept parameters I had to make correct sql query string myself.