How to correctly define one-to-many relations with existing joint table using node Sequelize - mysql

I am using Sequelize, but since I also have other servers running other than node.js, I need to let them share the database. So when defining one-to-many relation, I need to let Sequelize use the old existing jointTable.
I write my definition of the association as below, where pid is the primary key of presentations:
this.courses.hasMany(this.presentations,
{as : 'Presentations',
foreignKey : 'cid',
joinTableName : 'course_presentations'
});
Or this one:
this.courses.hasMany(this.presentations,
{as : 'Presentations',
foreignKey : 'pid',
joinTableName : 'course_presentations'
});
I am using the below codes to retrieve the associated presentations:
app.get('/courses/presentations/:cid', function (req, res){
var cid = req.params.cid;
app.models.courses.find({where: {cid:cid}}).success(function(course){
course.getPresentations().success(function(presentations){
res.send(presentations);
});
});
});
The previous one will tell me there is no cid in 'presentations' table.
The latter one will give something like this:
Executing: SELECT * FROM `courses`;
Executing: SELECT * FROM `courses` WHERE `courses`.`cid`='11' LIMIT 1;
Executing: SELECT * FROM `presentations` WHERE `presentations`.`pid`=11;
Check carefully, I found that everytime, it is always using the cid value to query for presentations, which means only when they happen to share the same id value, something can be returned. And even for those, it is not correct.
I am strongly suspecting, Sequelize are not using the joinTable I specified, instead, it is still trying to find the foreign keys in the original two tables. It is viewing pid as the reference of cid in presentations, which causes this problem.
So I am wondering how to correctly set up the junction table so that the two of them can use the foreign keys correctly.

jointTableName : 'course_presentations'
should be (without a t)
joinTableName : 'course_presentations'

Actually AFAIK - this kind of relation is not "pure" one-to-many.
You have one course can have many entries in course_presenation table, and course_presentation have one-to-one relation with presentation. If so, just define that kind of associations in model.

Related

Delete many2many column in table and the table itself - odoo 13

While running a pre-migration script to delete a (wizard) transient model, ended up with below mentioned issue.
from openupgradelib import openupgrade
#openupgrade.migrate()
def migrate(env, version):
openupgrade.delete_records_safely_by_xml_id(
env,
["moduel_name.view_id)"],
delete_childs=True,
)
try:
env.cr.execute("DROP TABLE IF EXISTS table_name CASCADE")
env.cr.execute("DROP TABLE IF EXISTS dependent_table_names CASCADE")
except Exception as e:
raise ("Exception--------------", e)
Error:
psycopg2.errors.ForeignKeyViolation: update or delete on table "ir_model" violates foreign key constraint "ir_model_relation_model_fkey" on table "ir_model_relation"
Similar issue: https://github.com/odoo/odoo/issues/54178
According to the above issue, having Many2many in transient model might cause this issue. It is true in my case as well. I have many2many fields. No solution there.
I kind of tried deleting the problematic fields(Many2many) before deleting columns. But it is known that many2many fields can't be located in db. kind of stuck.
openupgrade.drop_columns(
env.cr,
[
("table_name", "any_other_column_name"), # ---> This works
("table_name", "many2many_column_name"), # ---> This doesn't
],
)
is there anyway to get rid of many2many fields from the model ? Any help is appreciated.
Could you try this :
Let's say your Transient is my_transient_model and the Many2many field is e.g. sale_line_ids = fields.Many2many('sale.order_line')
First thing to know : Did you specify the relation table ? like
sale_line_ids = fields.Many2many('sale.order_line', 'my_relation_table_name') ?
If so, 'my_relation_table_name' is the name you want to delete from ir_model_relation.
If not, the relation table name is my_transient_model_sale_order_line_rel (so model then _ then the model we point to with _ instead of . then _rel.
Second set: delete the data from ir_model_relation:
DELETE FROM ir_model_relation WHERE name='my_transient_model_sale_order_line_rel';
Then you should be able to delete the Many2many table :
DROP TABLE my_transient_model_sale_order_line_rel;
(for sure, change my_transient_model_sale_order_line_rel if you specified the relation table like my_relation_table_name in the example)
Hope it helped, keep me updated :)

when defining a table in SequelizeJs its name is changed when executing

when defining a table in SequelizeJs its name is changed when executing resulting in a ER_NO_SUCH_TABLE.
This is my code :
var API_TOKEN=database.sequelize.define('API_TOKENS',{
user_id:{
type:Sequelize.INTEGER,
},
token:{
type:Sequelize.STRING
}
});
and the error :
Unhandled rejection SequelizeDatabaseError: ER_NO_SUCH_TABLE: Table 'tableName.API_TOKENs' doesn't exist
Note:notice how the table name is changed when executed , i am using mysql database.
You can use one of two available options that can be put in the options of sequelize.define method
freezeTableName
tableName
According to the sequelize documentation (concerning how it names the database table basing on model definition)
By default, sequelize will automatically transform all passed model names (first parameter of define) into plural.
By using the freezeTableName, the database table will be named exactly the same as your model name. On the other hand, if you want fully custom table name, you should use the tableName attribute.

Propel ORM with Two FK Columns To Same Foreign Table

I have a table that contains two foreign keys that map back to a membership table. They are named "from_member" and "to_member."
I am trying to get the Member object that represents this membership table by doing something like:
$feedbackQuery = FeedbackQuery::create()->findOne();
$fromMember = $feedbackQuery->getFromMember();
So that I can go like this:
$firstName = $fromMember->getFirstName();
The only problem is you can't do that, evidently Propel requires you to call $fedbackQuery->getMember()and who knows what that's going to return in this case.
Is there any easy way to accomplish getting the member data like this?
Assuming that you are using from_member_id and to_member_id as your foreign keys, you should have two methods at your disposal. getMemberRelatedByToMemberId() and getMemberRelatedByFromMemberId().
To find your from_member object and to use it.
$fromMember = $feedbackQuery->getMemberRelatedByToMemberId();
$firstname = $fromMember->getFirstName();

Update mapping table in Linq

I have a table Customers with a CustomerId field, and a table of Publications with a PublicationId field. Finally, I have a mapping table CustomersPublications that records which publications a customer can access - it has two fields: CustomerId field PublicationId.
For a given customer, I want to update the CustomersPublications table based on a list of publication ids. I want to remove records in CustomersPublications where the PublicationId is not in the list, and add new records where the PublicationId is in the list but not already in the table.
This would be easy in SQL, but I can't figure out how to do it in Linq.
For the delete part, I tried:
var recordsToDelete = dataContext.CustomersPublications.Where
(
cp => (cp.CustomerId == customerId)
&& ! publicationIds.Contains(cp.PublicationId)
);
dataContext.CustomersPublications.DeleteAllOnSubmit(recordsToDelete);
... but that didn't work. I got an error:
System.NotSupportedException: Method 'Boolean Contains(Int32)' has no supported translation to SQL
So, I tried using Any(), as follows:
var recordsToDelete = dataContext.CustomersPublications.Where
(
cp => (cp.CustomerId == customerId)
&& ! publicationIds.Any(p => p == cp.PublicationId)
);
... and this just gives me another error:
System.NotSupportedException: Local sequence cannot be used in LINQ to SQL implementation of query operators except the Contains() operator
Any pointers?
[I have to say, I find Linq baffling (and frustrating) for all but the simplest queries. Better error messages would help!]
Wow. Almost by chance, I discovered that the reason I couldn't use Contains in my first example was that my publicationIds was an IList<int> rather than a an int[]. I changed it, and it worked.
Thanks, compiler message author! :-|

linq-to-sql How can I get a few rows that don't match my existing rows?

I have a few rows of data pulled into business objects via linq-to-sql from large tables.
Now I want to get a few rows that don't match to test my comparison functions.
Using what I thought would work I get a NotSupportedException:
Local sequence cannot be used in LINQ to SQL implementation of query operators except the Contains() operator.
Here's the code:
//This table has a 2 field primary key, the other has a single
var AllNonMatches = from c in dc.Acaps
where !Matches.Rows.Any((row) => row.Key.Key == c.AppId & row.Key.Value == c.SeqNbr)
select c;
foreach (var item in AllNonMatches.Take(100)) //Exception here
{}
The table has a compound primary key: AppId and SeqNbr.
The Matches.Rows is defined as a dictionary of keyvaluepair(appid,seqnbr).
and the local sequence it is referring to appears to be the local dictionary.
Could you provide more information on the structure and the name(s) of the table(s) plz?
Not sure what you're trying to do...
edit:
Ok.. I think I get it now...
It appears you can't merge/join local tables (dictionary) with a SQL table.
If you can, I'm afraid I don't know how to do it.
The simplest solution I can think of is to put those results in a table ("Match" for instance) with foreign keys related to your table "Acaps" and then use linq-to-sql, like:
var AllNonMatches = dc.Acaps.Where(p=>p.Matchs==null).Take(100).ToList();
Sorry I couldn't come up with any better =(
What about this:
var AllNonMatches = from c in dc.Acaps
where !(Matches.Rows.ContainsKey(c.AppId) && Matches.Rows.ContainsValue(c.SeqNbr))
select c;
That will work fine. I have also used a bitwise AND operator (&&) - I think thats the right term to help improve performance over the standard AND operator.