Editor: problems creating new record
Editor: problems creating new record
Thank you Allan for your response to my previous questions, in which I presented a simplified three-field table. Following your recommendations, that isolated test case worked, as did the rest of my application, until now.
However, when trying to integrate that automatic default sequence auto-increment solution into my real-world problem, I couldn't make it work. Since I'm pretty sure that the problem lies at my end, I've paid a 99€ quick support to compensate you for your time looking at my specific situation.
I'll start by describing what I want to do. I'm writing a budget application for a French-speaking public organisation. Subsidies and expenditures have, in addition to the budget year, foreign-key attributes pointing to three tables: direction for the directorate receiving the subsidy or making the expenditure, pouvoir for the subsidising power which we will use as columns for a cross-tab output, and type_depense as the type of expenditure.
The budget application is actually quite simple. For each year (annee), subsidies are summed by direction, pouvoir, and type_depense. Expenditures are summed by the same three keys, and the budget is simply the difference between the sum of the subsidies minus the sum of the expenditures, grouped by direction, pouvoir, and type_depense.
I'm using PostgreSQL as the backend for this project, so I simply create views with the information I need. I can use cross tab functions to output spreadsheet-like columnar data, or a sub-select to create a virtual column summing the amounts of related child records.
I use Datables to present these views, and Editor to modify the underlying tables and create new records.
This approach has been successful for the subsidies side of the application. I can edit and create these records. These records have an auto-increment sequence global ID gid
as a default SQL value, in addition to their five-field compound primary key, so I simply do not submit gid
on record creation. The Postgres backend automatically adds the default gid
. This has been working properly, after reading your response to my previous question.
For expenditures (depenses) the situation is different: a depense is the actual cash outlay or bank transfer amount for the that expenditure, with an accompanying invoice or receipt. To break down that depense by direction, pouvoir, and type_depense, we (in a very French manner) cut it up into slices or tranches.
I envision the following workflow: the user pays for a service to goods and receives an invoice, which is the basis of a depense entered into the budget system. The user creates a new depense record, and is responsible for giving it a unique alphanumeric code_depense. In this case, I just say that it's the user's responsibility to use a unique key, otherwise the database throws an error. This is the type of hybrid local/remote variable I mentioned at the end of my previous question, but here I'm just tossing the ball back to the user.
They choose the supplier (fournisseur) and the payment method (moyen_de_paiement). They click to create the new depense record. At that point, they must then assign one or more parts of that depense to a triplet of direction, pouvoir, and type_depense in tranche records. This is where each new tranche record is created.
I have set up a DataTables instance and PHP back end that works just as expected: if the user tries to create a record with a duplicate code_depense, Editor throws a SQLSTATE[23505]: Unique violation: 7 ERROR: duplicate key value violates unique constraint error. Then manually modifying this code_depense key and resubmitting also works: the record is created as expected.
But my problem lies with the next level, where we slice up these depenses into tranches. This table has a compound primary key: code_depense pointing to the parent depense record, then the three budgetary keys: direction, pouvoir, and type_depense. Since as far as I know neither DataTables nor Editor can work with compound primary keys, I added a gid
field to my tranches table, just as I did for the subsides table described above.
When I submit the new tranches record, it blocks with the message SQLSTATE[22P02]: Invalid text representation: 7 ERROR: invalid input syntax for integer just like I was submitting a text value (it seems to be using the value of code_depense) to the gid
field. However, I'm not submitting that field, and I've added ->set(false)
as well to the PHP code. I also checked the submission in the browser debugger, and only the fields I want set are sent.
This, here, Allan is where I've been stuck for three days now. I ran the debugger on it, but didn't see anything I could find useful. I'll of course load it again if you want. Should I then send the link to you by private email?
Here's what seems useful to me to describe the environment, but I seem to have attained some kind of post limit. I'll be glad to supply any additional info you need.
This is a view with a virtual column, based on the amount as yet unattributed called depenses_non_ventiles from a sub-select of related records. This view is used successfully to view and modify records in Datables and Editor, and shows the calculated amount based on tranches related to that depense.
DROP VIEW IF EXISTS v_depenses;
CREATE OR REPLACE VIEW v_depenses
AS (
select
annee,
code_depense,
date_depense,
code_moyen_de_paiement,
code_fournisseur,
montant_depense,
montant_depense - (
SELECT sum(montant_tranche)
FROM tranches
WHERE depenses.code_depense = tranches.code_depense
) AS depenses_non_ventiles
from
depenses
order by 1,2
)
;
var editor_tranches; // use a global for the submit and return data rendering
var editor_tranches_new; // use a global for the submit and return data rendering
$(document).ready(function() {
// --------------------------------------------------------------
editor_tranches = new $.fn.dataTable.Editor( {
ajax: "php/tranches-data.php",
table: "#tranches",
fields: [ {
label: "Code dépense:",
name: "tranches.code_depense",
type: "select",
placeholder: "Choissez la code dépense pour associer cette tranche à un autre dépense"
}, {
label: "Direction:",
name: "tranches.code_direction",
type: "select",
placeholder: "Choissez la Direction"
}, {
label: "Pouvoir:",
name: "tranches.code_pouvoir",
type: "select",
placeholder: "Choissez le Pouvoir Subsidiant"
}, {
label: "Type de dépense:",
name: "tranches.code_type_depense",
type: "select",
placeholder: "Choissez le type de dépense"
}, {
label: "Montant tranche:",
name: "tranches.montant_tranche"
}
]
} );
$('#tranches').DataTable( {
dom: "Blfrtip",
ajax: "php/tranches-data.php",
columns: [
{ data: "tranches.code_depense" },
{ data: "v_depenses.annee" },
{ data: "v_depenses.date_depense" },
{ data: "moyens_de_paiement.nom_moyen_de_paiement" },
{ data: "fournisseurs.nom_fournisseur" },
{ data: "v_depenses.montant_depense", render: $.fn.dataTable.render.number( '.', ',', 2, '€' ) },
{ data: "v_depenses.depenses_non_ventiles", render: $.fn.dataTable.render.number( '.', ',', 2, '€' ) },
{ data: "tranches.code_direction" },
{ data: "tranches.code_pouvoir" },
{ data: "tranches.code_type_depense" },
{ data: "tranches.montant_tranche", render: $.fn.dataTable.render.number( '.', ',', 2, '€' ) },
],
select: true,
buttons: [
{ extend: "create", editor: editor_tranches },
{ extend: "edit", editor: editor_tranches },
{ extend: "remove", editor: editor_tranches }
]
} );
} );
Replies
Hi,
Thanks for picking up the DataTables support option and the details of the issue you are facing!
DataTables itself doesn't really "care" about what the primary key is, or even if there is a primary key. It will just accept an array of data it needs to display. Indeed Editor on the client-side is the same, where it breaks down is Editor's PHP server-side libraries. They currently do not support compound keys (although that will change with Editor 1.6 in a few months time).
So if you only need to view this particular piece of data and not edit it, you could simply query the database directly to get the data (rather than using Editor's PHP libraries to get it). However, if you do need to edit it we'll need to address this issue.
Does the
gid
have a default value assigned to in the SQL schema (presumably a uuid or a sequence value in this case)? Can you insert into the table if you can't using Editor (i.e. a straightINSERT
command)?Regards,
Allan
That's exactly what I do for all the "view-only" tables. I have my usual data access functions which return json data for DataTables. I will later use a separate database user with read-only privileges to access the view-only derived tables.
In this application, I am using Editor to alter only the three underlying data tables: subsides, depenses, and tranches. Both subsides and tranches have multi-column compound keys, and an added
gid
default sequence for use with Editor only. The subsides table works fine, I just add the record without specifying thegid
and it works with Editor. I am only encountering problems with tranches.Let's first look at what we have in the parent depenses table
And related tranches child records
We can now attempt a tranches insertion with a non-existent depense foreign key:
But when we put in proper values for all foreign keys, but do NOT give a value for
gid
(or even mention it anywhere):And we see it here inserted, with a shiny new
gid
And maybe not particularly useful, here are the definitions of the tables:
Here's the editor javascript code. Notice that I've actually created two editor variables, with different PHP ajax data sources, one for modifying the record, and one for record creation, in an attempt to get this working. Neither variant works for record creation. I'll include the two PHP scripts later.
The corresponding HTML for the tranches table
And here is the (working) PHP ajax source for viewing and editing, based on a postgres view, in the referenced file
php/tranches-data.php
:I'll put the the stripped-down Php for record creation, which STILL doesn't work in the next comment, since I've hit the character limit...
Finally, here's the stripped-down PHP for record creation
php/tranches-data-only.php
, which STILL doesn't work for record creation. I don't mention a view at all, only real-life tables. I tried to remove the mention ofgid
as the key field, but then editor objected with the complaint that it could not find the "id" field.This is what is called as the function editor_tranches_new from the "create" button attached to the table #tranches, as described in the javascript above.
Thanks for the extra information! With that I've just tried to create a local test case. I used the following SQL:
I don't have the external tables, so I removed those constraints and added a new sequence, which I presume basically matches your own.
I've used the HTML and Javascript from above. Changes in my local test case:
->options()
in the PHPtext
in the Editor JavascriptWith that I can insert a row without any problems. The
gid
is inserted correctly and shown in the table. The DataTable complains about the missing columns since there is no join and I haven't altered the initialisation of the table, but that's expected.So I'm afraid I don't have a good answer for you immediately. We'll need to do a little debugging...
In the file
php/Database/Drivers/Postgres/Query.php
you'll find a function called_prepare
. At the end of that function could you add:You might need to update the file name to be somewhere writable on your server.
That will dump the SQL and values that Editor is using to that file. If you then try to create a new row in the
tranches
table, what gets put into that file?Thanks,
Allan