Migration on two schemas - postgresql

I have 2 schemas on my db:schema1 and public and I want to create some tables there. I tried code like this in my migration:
return knex.schema
.raw('CREATE SCHEMA IF NOT EXISTS schema1;')
.createTableIfNotExists('table1', table => {
table.increments('id')
})
.withSchema('public')
.createTableIfNotExists('table2', table => {
table.increments('id')
})
And I hoped to have: schema1.table1 and public.table2 but I don't. Any ideas how to do that?

Belayer is quite correct in the comments, but I'll expand into an answer to demonstrate the syntax. You'll also need to avoid doing things like:
createTableIfNotExists('schema1.table1', table => {
per Identifier Syntax, this won't work: just get into the habit of always using withSchema.
Further, I don't recommend issuing subsequent createTables without waiting for the previous one to finish. While it might work, I think you'll run into trouble with relations etc. That makes your original code more like:
exports.up = knex =>
knex
.raw("CREATE SCHEMA IF NOT EXISTS schema1")
.then(() =>
knex.withSchema("schema1").createTableIfNotExists("table1", table => {
table.increments("id");
})
)
.then(() =>
knex.withSchema("public").createTableIfNotExists("table2", table => {
table.increments("id");
})
);

Related

knex.js migrations create tables with relationship between each other fails

I've looked all over the place, there are quite a few examples, but nothing complete or working.
Use case:
Simple database structure, a few tables and some relationships. Set up node, knex and pg - in a docker container.
All works well.
Created the migration file for the first table (table A) - ok.
Added the second table (table B) and a 1:n relationship from table B to A. All good.
Added a 1:n relationship from table A to table B. And the script errored out.
table info:
exports.up = function(knex) {
return knex.schema
.createTable('user', t => {
t.uuid('user_id').primary()
t.string('name', 100).notNullable()
t.string('surname', 100)
t.string('email').notNullable().unique()
t.string('password')
t
.boolean('email_confirmed')
.notNullable()
.defaultTo(false)
t
.datetime('last_login', { precision: 6 })
.defaultTo(knex.fn.now(6))
t.string('language')
t.string('newsletter')
t.timestamps(true, true)
t
.uuid('company_id')
.references('company_id')
.inTable('company')
})
.createTable('company', t => {
t.uuid('company_id').primary()
t.string('address_id')
t.string('name', 100).notNullable()
t.string('phone')
t.timestamps(true, true)
t
.uuid('owner_user_id')
.references('user_id')
.inTable('user')
})
}
error:
migration failed with error: alter table "user" add constraint
"user_company_uuid_foreign" foreign key ("company_uuid") references
"company" ("company_id") - relation "company" does not exist
I'd say it tries to create a table and add the foreign key before creating the second table (which the FK references).
Any idea on how to solve this.
it is not a m:n relationship really. A company can and should only have 1 owner. A user has to belong to a company, otherwise it can't exist. If this is not solvable I can have the user.company_id field as a simple string w/o any relationship.
Having a different table for user_companies would be overkill.
Thanks!
You are correct that it is trying to create the reference before the table it is referencing exists. The easiest way would probably be to simply delay the creation of the foreign key until after the companies table has been created. i.e.
exports.up = async function(knex) {
await knex.schema.createTable('user', t => {
t.uuid('user_id').primary()
t.string('name', 100).notNullable()
t.string('surname', 100)
t.string('email').notNullable().unique()
t.string('password')
t.boolean('email_confirmed')
.notNullable()
.defaultTo(false)
t.datetime('last_login', { precision: 6 })
.defaultTo(knex.fn.now(6))
t.string('language')
t.string('newsletter')
t.timestamps(true, true)
t.uuid('company_id')
});
await knex.schema.createTable('company', t => {
t.uuid('company_id').primary()
t.string('address_id')
t.string('name', 100).notNullable()
t.string('phone')
t.timestamps(true, true)
t.uuid('owner_user_id')
.references('user_id')
.inTable('user')
});
await knex.schema.table('user', t => {
t.foreign('company_id')
.references('company_id')
.inTable('company')
});
}

Query Combinaton

I am trying to build a query using asp.net core c#
https://www.reflectionit.nl/blog/2017/paging-in-asp-net-core-mvc-and-entityframework-core
I trying to do a filtering however I need the data from another table which have my unique id
var result = _context.UserRoles.Where(y => y.RoleId.Contains(selectedRoles.Id)); // Retrieve the the userid i have from another table with the selected roleid
var query = _context.Users.Where(x => //I have already tried contains, where join );
If there is a site where i can learn this query please recommend. "Join()" does not work as I am doing paging
a least two solutions (please note that I do not check the identity classes members, so the following is the "spirit" of the solution (you miss the select clauses) ):
var result = _context.UserRoles.
Where(y => selectedRoles.Contains(y.RoleId)).
Select(y => y.User);
or
var result = _context.UserRoles.
Where(y => selectedRoles.Contains(y.RoleId)).
Select(y => y.UserId);
query = _context.Users.
Where(x => result.Contains(x.Id));
That said, assuming that there is no UserRoles table exposed in Identity (v2), you probably want:
userManager.Users.
Where(u => u.Roles.Any(r => selectecRoles.Contains(r.RoleId)));
Up to you to instanciate the userManager.

Inner actions are not getting executed inside transaction in slick

I have requirement where i have to insert into book table and based on auto Id generated , I have to insert into bookModules table.For every bookModule autoincrement Id , I have to insert into bookAssoc table. But bookModule is populated using seq[bookMods] and bookAssociation data is populated using Seq[userModRoles].
I have written below code to achieve this but it is only executing action1. My inner actions are not getting executed. Please help me .
val action1 =bookDao.insert(book)
val action2 = action1.map { id => DBIO.sequence(
bookMods.map { bookMod =>
bookModDao.insert(new bookModule(None, id, bookMod.moduleId, bookMod.isActive))
.map { bookModId =>
userModRoles.map { userModRole =>
bookAssocDao.insert(new bookAssociation(None, bookModId, userModRole.moduleId, userModRole.roleId))
}
}
})
}
db.run(action2.transactionally)
EDIT 1: Adding code in for comphrension
val action1 = for{
bookId<-bookDao.insert(book) // db transaction
bookMod<-bookModules// this is scala collection // Iterate each element and Insert into tables
bookModId<-bookModDao.insert(new bookModule(None, bookId, bookMod.moduleId, bookMod.isActive))
userModRole<-userModRoles //// this is scala collection // Iterate each element and Insert into tables
bookAssocDao.insert(new bookAssociation(None, bookModId, userModRole.moduleId, userModRole.roleId))
}yield()
db.run(action2.transactionally)
You need to split your logic into two parts.
1) DBIO
2) iterates over collections.
In that case, a solution should be easy. But without using for comprehension.
bookModules.map{ bookMod =>
userModRoles.map{ userModRole =>
db.run(bookDao.insert(book).flatMap{ bookId =>
bookModDao.inser(new bookModule(None, bookId, bookMod.moduleId, bookMod.isActive)).map{ bookModId =>
bookAssocDao.insert(new bookAssociation(None, bookModId, userModRole.moduleId, userModRole.roleId))
}
}).transactionally
}
}
Try something like this. It should work. You can think about move db.run to Dao classes. And here, probably it's service you should work on Futures.
And sorry if I make some mistake with parenthesis, but here it's difficult to have everything clear :)

Perl Catalyst: Resultset and Relations

I have two tables in my database and one of the tables is associated with my Accounts table.
So in my Schema Result for Account.pm I added the following line.
__PACKAGE__->has_many('subjects', 'MyApp::DBIC::Schema::Subject', {'foreight.account_id' => 'self.account_id'});
Then in my controller I make a search like this.
$c->stash->{search_results} = $c->model('DB::Account')->search(
{ -or => [
firstname => {like => '%'.$search_term.'%'},
'subjects.subject_title' => {like => '%'.$search_term.'%'},
]
},
{
join => 'subjects',
rows => '3',
},
{
order_by => 'first name ASC',
page => 1,
rows => 10,
}
);
It does not output any errors, but I can't figure out how to output the results on my view file. Is this a correct method of making relations between two tables?
My goal: provided a search_term, search two tables and output the result in view file. My SQL would look something like this:
SELECT FROM Accounts,Subjects WHERE Accounts.firstname=$search_term OR Subjects.subject_title=$search_term LEFT JOIN Subjects ON Accounts.account_id=Subject.account_id
And would want to output the result in view file, as I stated above.
I am fairly new to Perl and some of the documentations don't make that much sense to me, still. So any help and tips are appreciated.
The join looks OK to me, but it would make sense to try a simplified version without the join to check that everything else is OK.
The behaviour of DBIx::Class::ResultSet::search differs depending on the context in which it's called. If it's called in list context then it executes the database query and returns an array of MyApp::DBIC::Schema::Account objects. For example:
my #accounts = $c->model('DB::Account')->search();
In your case you're calling search in scalar context, which means that rather than returning an array it will return a DBIx::Class::ResultSet object (or a subclass thereof), and crucially it won't actually execute a db query. For that to happen you need to call the all method on your resultset. So, assuming you're using the default template toolkit view you probably want something like this:
[% FOREACH search_result IN search_results.all %]
[% search_result.first_name %]
[% END %]
This 'lazy' behaviour of DBIx::Class is actually very useful, and in my opinion somewhat undersold in the documentation. It means you can keep a resultset in a variable and keep executing different search calls on it without actually hitting the DB, it can allow much nicer code in cases where you want to conditionally build up a complex query. See the DBIx::Class::Resultset documentation for further details.
You have error in your query:
Try:
$c->stash->{search_results} = $c->model('DB::Account')->search(
{ -or => [
firstname => {like => '%'.$search_term.'%'},
'subjects.subject_title' => {like => '%'.$search_term.'%'},
]
},
{
join => 'subjects',
order_by => 'firstname ASC',
page => 1,
rows => 10,
}
);

Select all with Squeryl scala

I'm trying to select ALL of some table in a query. I have to specify a where clause (or so I tihnk), so what goes in there?
def all() = transaction { from(AppDB.users)(s => where(WHAT GOES HERE?) select(s)).toIndexedSeq }
This should do it.
from(AppDB.users)(s => select(s))