Kohana 3.2 relationship - Joins - kohana

i have the current design in mysql :
Table filesubject
Is there a way in Kohana to set relationship in a way that if i make something like
ORM::factory('filesubject')->where('file_id','=',$file->id)->find_all()->as_array());
That i get all the joins from the other tables ?

I'm not sure about your question. To automatically join models, first setup your relationships ($_belongs_to etc) and then look at:
In your model:
ORM property: $_load_with. eg: protected $_load_with= array(model1, model2, etc)
Or at run time:
ORM method: with(). eg: ORM::factory('filesubject')->with('model')->with('model2')->find_all()
I don't think the as_array() function pulls in the joined data though. Once it's actually performing the join you'd need to overwrite as_array (or write your own function) to output the nested key/pair values from the joined properties.

Related

In Sequelize How to order by `column_a - column_b`?

In my project I am using node.js v10, sequelize 5.8.9 and Postgres 11.
In database there is a Task table and a few child tables. I have done the sequelize model definition, and the create, update, query through sequelize just works perfectly.
Today I was going to make the query ordered by Task.end_time - Task.start_time, sounds easy, doesn't it? However it proved to be very tricky if not impossible using sequelize.
As the options object passed into findAll method contains nested include arrays to retrieve the child tables, the SQL generated actually is complicated and containing subqueries.
I have tried sequelize.literal, sequelize.fn, none worked, and the reasons are the same - sequelize put the ORDER BY clause in two places - one in a subquery where the field names are still in underscored form, e.g. start_time and end_time and the other in the end of the sql, where the field names have been aliased to startTime and endTime, therefore the order I specified can never satisfy both at the same time.
I also think of Sequelize.VIRTUAL data type, found this post however the trick didn't work either. The SQL generated was wrong:
"Task"."endTime - startTime as runningTime" FROM "task"
Any advice / suggestion is appreciated.

Multi insert inside a QueryFile

I'm able to generate query for multi inserts or update thanks to pg-promise helpers but I was wondering if I could follow the advice of the author and put all queries outside of my javascript code (See here https://github.com/vitaly-t/pg-promise/wiki/SQL-Files and here : https://github.com/vitaly-t/pg-promise-demo).
When I use the insert helpers, the return query looks like :
INSERT INTO "education"("candidate_id","title","content","degree","school_name","start_date","still_in","end_date","picture_url") VALUES('6','My degree','Business bachelor','Bachelor +','USC','2018-05-15T02:00:00.000+02:00'::date,false,null::date,null),('6','Another degree','Engineering','Master degree','City University','2018-05-15T02:00:00.000+02:00'::date,false,null::date,null)
The idea is that I don't know how many inserts I want to do at the same time, so it has to be dynamic.
The following code doesn't work as I'm passing an array of object instead of an object :
db.none(`INSERT INTO "education"("candidate_id","title","content","degree","school_name","start_date","still_in","end_date","picture_url")
VALUES($<candidate_id>, $<title>, $<content>, $<degree>, $<school_name>, $<start_date>, $<still_in>, $<end_date>, $<picture_url>)`, data)
This code spreads the object but is still not correct to make a proper query :
db.none(`INSERT INTO "education"("candidate_id","title","content","degree","school_name","start_date","still_in","end_date","picture_url")
VALUES($1:list)`,
[data])
Any idea ? Is it at least possible or in the case where I don't know how many records I want to insert in advance I have to call pgp.helpers everytime ?
You confuse static and dynamic SQL. SQL files are there for SQL queries that are mainly static, i.e. you still can inject dynamically a lot, but when most of the query is dynamic, there is no longer any point putting it into an SQL file.
And the helpers namespace is there for dynamic queries only. So you are asking about two separate things, to join things that do not need to be joined.

How can I get the entire updated entry in a $afterUpdate hook in objection models?

Im using Objection.js as my ORM for a simple rainfall application. I need to be able to dynamically update and entry of one table when a lower level tables entires has been updated. To do this I need the whole entry I am updating so I can use that data to correctly update the dynamically updated entry.
Im using the $afterUpdate hook for the lower level table entry which. The issue I am having is that when I log this within the $afterUpdate hook function it only contains the properties for the parts of the entry I want to update. How can I get the entire entry? Im sure I could get the record by running an additional query to the DB but I was hoping there would be away to avoid this. Any help would be appreciated
I think, as of right now, you can only get the whole model with an extra query.
If you are doing the update with an instance query ($query) you can get the other properties from options.old.
Query:
const user = await User.query().findById(userId);
await user.$query()
.patch({ name: 'Tom Jane' })
Hook:
$afterUpdate(opt, queryContext) {
console.log(opt.old)
}
Patch
If you don't need to do this in the hook, you might want to use patch function chained with first().returning('*') to get the whole model in a single query, it's more efficient than patchAndFetchById in postgreSQL. Like stated in the documentation.
Because PostgreSQL (and some others) support returning('*') chaining, you can actually insert a row, or update / patch / delete (an) existing row(s), and receive the affected row(s) as Model instances in a single query, thus improving efficiency. See the examples for more clarity.
const jennifer = await Person
.query()
.patch({firstName: 'Jenn', lastName: 'Lawrence'})
.where('id', 1234)
.returning('*')
.first();
References:
http://vincit.github.io/objection.js/#postgresql-quot-returning-quot-tricks
https://github.com/Vincit/objection.js/issues/185
https://github.com/Vincit/objection.js/issues/695

Join three table using library knex.js

I am using knex.js
suppose we have three table :-
table1-- id,name,address
table2--id,city,sate,table1_id as fk
table3--id,housenumber,table1_id as fk
I want to join these three table using knex.js libraray of node and express
so that i want to get output json like this.
{
"id":1,
"name":"abc",
"address:"xyz",
"table2":{"id":1,"city":"ttt","state":"www" }//i want check if table1.id == table2.table1_id then put table details
"table3":[]//if no relation found between table1.id === table3.table1.id then kept it as an array
}
tl;dr knex is too low level tool for the thing you are trying to do, you should use an ORM for that kind of task
However you can do that with lots of manual work.
First you have to make the query with proper joins and creating aliases with table prefixes for each column of table to be able to get result data in a format where all data is in a flat array like:
knex('table1' as t1)
.join('table2 as t2', 't2.t1_id', 't1.id')
.select(
't1.id as t1_id',
't1.other_column as t1_other_column',
't2.id as t2_id', <more columns you want to extract>)
Results something like
[ { t1_id: 1, t1_other_column: 'foo', t2_id: 4}, ... more rows with flat data... }]
Then you need to write javascript code for restructuring flat data to nested objects.
But you should not do that kind of work manually. All knex based ORMs has already implemented general solutions for writing that kind of queries in easy manner.

Waterline - Postgres - DataTypes

I am having difficulties with Waterline models and creating the Postgres tables related to those models.
No matter what I do to create a varchar(n) in the table through a model, it converts the attribute to text. And bigint also is being converted to integer!
Should I change the ORM?
Is there a way to do that?
You can do a more pleasant approach, using Waterline to "RUD" in "CRUD" but not to "C" - create! This because Waterline can be very "bad" at creating intermediary tables, primary keys (composite keys) and etc. So what I do today is this:
Compose a full .sql file archive to create indexes and tables.
Create the database once. (Alter if needed).
Declare all the tables as models. Just insert the type, primary key (if it is a single one) and lifecycle callbacks.
Make sure that config/models.js is set to migrate : safe.
Conclusion: I can insert, read and delete rows with Waterline, but I don't trust it (performance-wise) to create my tables. Sequelize on the other hand is a much more mature ORM and can be used if you need it. For me the hybrid waterline + SQL is sufficient.
EDIT: My models dont have any aggregation (like my_pets: { model: pet} ), just row names and types, as simple as possible.
Sails supported datatype:
String, text, integer, float, date, datetime, boolean, binary, array, json, mediumtext, longtext, objectid
If you need to specify exact length -> varchar(n), you need to use supported data type as shown above, or sails provide option called query.
Model.query() method which you can use to perform any kind of query you want.
var queryString='CREATE TABLE if not exists sailsusers.test (id INT NOT NULL,name VARCHAR(45) NULL,PRIMARY KEY (id))'
Test.query(queryString,function(err,a){
if(err)
return console.log(err);
console.log(a,'\n',b);
res.ok();
});

Resources