Strange field value is set for INSERT query on joined table
Strange field value is set for INSERT query on joined table
I'm using the PHP Editor libraries to feed a Datatable.
Tables structure and relationship is products(CODE[pk], PRICE, ...)
and descriptions(CODE[fk], DESC_it, DESC_en, ...)
.
In PHP I'm using
->leftJoin( 'descriptions', 'descriptions.code', '=', 'products.code' )
and I guess it's working properly since I can succesfully display and edit product descriptions on the frontend.
However, when I try to create a new entry, even if I set correctly every field, on the bottom of the create form this SQL error appears:
An SQL error occurred: SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails ('productdb'.'descriptions', CONSTRAINT 'FK_descriptions_products' FOREIGN KEY ('code') REFERENCES 'products' ('code') ON DELETE CASCADE ON UPDATE CASCADE)
.
So I enabled the debug and on the network tab of chrome dev tools I took a look at the INSERT query.
As it has to be, it first inserts the product and then inserts the description. However, what I think it's wrong is the value for the code
field it is trying to set for the description query. For reference, after the INSERT query on products
table (which is correct), this is the rest of the code:
...
{
"query": "SELECT * FROM `descriptions` WHERE `code` = :where_0 ",
"bindings": [
{
"name": ":where_0",
"value": "114",
"type": null
}
]
},
{
"query": "INSERT INTO `descriptions` ( `DESC_it`, `code` ) VALUES ( :DESC_it, :code)",
"bindings": [
{
"name": ":DESC_it",
"value": "Example of description trying to be set for a product.",
"type": null
},
{
"name": ":code",
"value": "114",
"type": null
}
]
}
I have no clue where that "114" is coming from. It appears that it's trying to set a 3 digit incremental number (that increases by 1 on each request) for the code
field on descriptions
.
Answers
Hi,
Can you show me the full initialisation code for both the server-side, and the client-side (for the DataTable and Editor)? Also being able to see the data submitted to the server would be useful.
I suspect it is entering this part of the code, although why it is incrementing I'm not sure.
Normally when a left join table needs to be updated (which appears to be the case here?), I would suggest doing it via nested editing.
Allan
Hi Allan,
The payload that Editor sends to PHP Editor when creating a new entry is:
The PHP script is:
I don't know if this is actually enough to troubleshoot, in case I would need to clean up the code a bit first. Thank you!
I think this will be the piece of code that is relevant - it attempts to see if there is a row that matches the condition, and if so updates it, otherwise it will insert. That said, it should just do an insert on
create
without checking if the row exists... Are you using the current release of the PHP libraries, and the debug trace from above was a create action, not edit?Assuming that is correct, then the number (114 above) is the primary key value of the host table (
products
) of the new row being created. It is attempting to create a link between theproducts
and thedescriptions
tables, since a new description is being inserted.Is that what you want to happen, a new description for every new product?
Can you show me your DB schema?
Thanks,
Allan
I can confirm I'm using the latest version of PHP libraries.
Yes the debug trace refers to a 'create' action, which causes the SQL error. The edit action works fine, and even if the record on descriptions doesn't exist, it just gets created.
The 114 value that it is trying to insert is not the primary key of products, since that one is a 12 char alphanumeric. It's a sequential number that I don't know where it's coming from (I may now know it, more on that below). Just to try I rebooted the PHP server and that didn't restart the counter (every new create action shows a +1 higher value).
That's exactly what I'd want: on the creation of a product record, I'd like to have the description record added too.
The DB schema is:
Actually... Exporting the DB schema for this response I noticed that DT is trying to set the value from the AUTO_INCREMENT of order as the primary key on descriptions, which should be 'code'.
As you can see from the PHP code on my previous response, the 'order' field is never called and so I don't understand why DT libraries are using that value.
I've just recreated the issue here, based on the information provided - many thanks for that. Yes, what is happening is that the primary key value from the
products
table is being used and trying to insert that into thedescriptions
as the link value.The Editor PHP libraries are doing that because they use the PDO
lastInsertId()
method to get the value from the database. i.e. regardless of what the third parameter of theEditor()
constructor is set as, it will always get the value of what is actually the primary key in the database.I think that justifiably should be considered a bug in the Editor PHP MySQL implementation and I will look into options to address that, however, I doubt that will be a quick fix - it might have far reaching consequences and I don't want to just dive into that!
In the short term, there are a couple options:
products
to becode
, orSorry I don't have an immediate and fast fix for this.
Allan
I've just had a brief look, and to make this work I'd need to be able to have the query return the value, but there isn't a mechanism for that in MySQL. Postgres has
RETURNING
, SQL Server hasOUTPUT
, but I can't see a way to do it in MySQL.Without that ability I'd need to query the newly created row to get the data, which isn't ideal. I'd probably need to add some kind of switch in there to enable such behaviour.
Based on that, I think it might be best to write to the descriptions table directly, which can be done using the
writeCreate
method (if you can't use either of the two options above):Allan
Many thanks for your time Allan.
Actually, the incremental ID that it is using to link descriptions comes from
order
field, which is a KEY (since it is AUTO_INCREMENT) but not the PRIMARY KEY, since that one iscode
(the 12 char string). So I think the issue is the library always gets the incremental ID (if there's one, I guess) instead of the primary key declared in the object constructor.So I believe the solutions you suggested are already there: products primary key is already
code
and the linking value on descriptions is already its primary key.Am I missing something? Thank you again!