Sequelize migrations - Unable to change reference on column - sql-server

My database is MSSQL.
I have a migration script where I have created the table like this:
module.exports = {
up: function(queryInterface) {
return queryInterface.createTable(
'tablename', {
'column1': {
type: SEQUELIZE.INTEGER,
references: {
model: 'Foobar',
key: 'id',
onDelete: 'cascade'
}
}
}
}
}
};
I want to change the reference for this column, so I wrote another migration script:
module.exports = {
up: function(queryInterface) {
return queryInterface.changeColumn(
'tablename', {
'column1': {
type: SEQUELIZE.INTEGER,
references: {
model: 'BarFoo', //I changed the reference
key: 'id',
onDelete: 'cascade'
}
}
}
}
}
};
However, on running the migration, I find that the reference is not changed in the database. The column still refers to the old reference - FooBar instead of BarFoo. The migration script ran successfully but the change did not happen. Any idea why?
I run the migrations using sequelize cli - sequelize db:migrate

Related

Gatsby-plugin-sitemap, custom config, need to integrate pages and markdown using custom resolvePages and Serialize, what does this line of code do?

just starting with javascript and react thanks to Gatsby so excuse me if this is a total newbie question. Also just starting with posting on stackoverflow, usually just consuming content, sorry about that and if my post is incomplete or unclear in anyway.
I am building a website using GatsbyJs, and want to setup a proper sitemap using gatsby-plugin-sitemap, however i am strugling to understand what the following line of code does so i can try and customize de code to do what I need, which is integrate the pages and blog posts on the sitemap, and adding a proper lastmod when applicable. I am breaking my head but cannot get the last part to work, that is, adding lastmod when it is a blog post.
on gatsby-config.js:
{
resolve: `gatsby-plugin-sitemap`,
options: {
// Exclude specific pages or groups of pages using glob parameters
// See: https://github.com/isaacs/minimatch
// The example below will exclude the single `path/to/page` and all routes beginning with `category`
output: '/',
excludes: [`/legal/*`,`/gracias`],
query: `
{
site {
siteMetadata {
siteUrl
}
buildTime(formatString: "YYYY-MM-DD")
}
allSitePage {
nodes {
path
}
}
allMarkdownRemark(filter: {frontmatter: {path: {regex: "/blog/"}}}) {
nodes {
frontmatter {
path
date
}
}
}
}
`,
resolvePages: ({
allSitePage: { nodes: allPages },
allMarkdownRemark: { nodes: allPosts },
}) => {
const pathToDateMap = {};
allPosts.map(post => {
pathToDateMap [post.frontmatter.path] = { date: post.frontmatter.date };
});
const pages = allPages.map(page => {
return { ...page, ...pathToDateMap [page.path] };//what does this line of code do???
});
return pages;
},
serialize: ({ path, date, buildTime }) => {
let entry = {
url: path,
changefreq: 'monthly',
priority: 0.5,
};
if (date) {
entry.priority = 0.7;
entry.lastmod = date;
} else {
entry.lastmod = buildtime;
}
return entry;
}
}
}
For your knowledge both develop and build are succesful, the sitemap is generated as sitemap-index and sitemap-0.xml, and the output is there but no page has lastmod on it.
Thank you all for your help,
With this:
return { ...page, ...pathToDateMap [page.path] };
You are merging objects using the spread operator (...). So, you are returning an object that is the result of all properties of the page and pathToDateMap(at page.path position).
For example:
let person = {
firstName: 'John',
lastName: 'Doe',
age: 25,
};
let job = {
jobTitle: 'Web developer',
location: 'USA'
};
let employee = {
...person,
...job
};
console.log(employee)
In the snippet above, employee is the result of merging person and job.
The lastmod parameter is not added by default unless your source has it (WordPress normally has) but you can follow this answer https://stackoverflow.com/a/70297982/5585371 to create your own.

Sequelize removeColumn method doesn't remove enum types

I added a column to an already existing database table using a migration file as shown below
module.exports = {
up: (queryInterface, Sequelize) => {
return queryInterface.addColumn('Results', 'mid_term_type', Sequelize.ENUM(['first', 'second']));
},
down: (queryInterface, Sequelize) => {
return queryInterface.removeColumn('Results', 'mid_term_type'));
}
};
If I migrate the file by running sequelize db:migrate, the column is added to the database.
I am having issue is when I run sequelize db:migrate:undo:all and then sequelize db:migrate to undo the addition of the column.
I get the bellow error:
ERROR: type "enum_Results_mid_term_type" already exists
How can I remove the "enum_Results_mid_term_type" by running equelize db:migrate:undo:all
sequelize: ^5.22.3
sequelize-cli: ^5.5.1
module.exports = {
up: (queryInterface, Sequelize) => {
return queryInterface.addColumn('Results', 'mid_term_type', Sequelize.ENUM(['first', 'second']));
},
down: async (queryInterface, Sequelize) => {
await queryInterface.removeColumn('Results', 'mid_term_type'));
await queryInterface.sequelize.query('drop type enum_Results_mid_term_type;');
}
};

Pug able to access a nested array from a mongo database Json

I am trying to output the array dependencies from the mongodb object. I have tried nearly everything but keep getting length of undefined.
I can output the whole object but I want the name version of each dependencies.
{ _id: 5c6eea28c6c23a15beb43419,
Repo_id: [ 1 ],
name: 'express-ibm',
version: '0.0.0',
dependencies:
[ { name: 'async', version: '2.6.1' },
{ name: 'body-parser#1.18.3', version: '1.18.3' },
{ name: 'cookie-parser#~1.4.3', version: '1.4.3' },
{ name: 'debug#~2.6.9', version: '2.6.9' },
{ name: 'express#~4.16.0', version: '4.16.4' },
{ name: 'http-errors#~1.6.2', version: '1.6.3' },
{ name: 'mongoose', version: '5.3.13' },
{ name: 'morgan#~1.9.0', version: '1.9.1' },
{ name: 'pug#2.0.0-beta11', version: '2.0.0-beta11' } ] }
// Display detail page for a specific Repo
exports.repo_search = function(req, res, next) {
Repo.findById(req.params.id).populate('repo').exec(function(err, repo) {
if (err) {
return next(err);
}
if (repo == null) {
// No results.
var err = new Error('Repo copy not found');
err.status = 404;
return next(err);
}
console.log(repo);
Repo.find().exec(function(err, list) {
if (err) {
return next(err);
}
res.render('repo_info_detail', {
title : 'Repo Detail',
repo : repo,
list : list
// repo_dependencies: results.repo_search
});
});
});
};
Pug:
extends layout
block content
p#demo
h1 #[Repository Name :] #{repo.name}
dd #[ IBM Github URL:]
a(href='/'+repo.url) #{repo.url}
dd #[ Repository ID:] #{repo._id}
dd #[ Language Type:] #{repo.filetype}
dd #[Repo ID :] #{repo.Repo_id}
//dd #[dependencies: ] #{repo.dependencies.name}
div(class='col')
div(class='col-sm-8')
p
button.hidediv Hide dependencies
button.showdiv Show dependencies
.divdemo
| Dependencies
.button
a#export(href='#', role='button')
| Click On This Here Link To Export The Table Data into a CSV File
div(class='col')
div(class='col-sm-3')
table
thead
tr: th Name
tbody
each d in repo
tr
td
dd #{repo}
repo is a javascript object, and you're correctly accessing its properties using dot syntax (e.g. repo.name or repo.dependencies). However, repo.dependencies is an array of objects. It doesn't have a name property that can accessed using dot syntax. Instead, you'll have to loop through the child objects and access each of their name properties in turn.
h1 Repository Name: #{repo.name}
dl
dt IBM Github URL:
dd #[a(href='/'+repo.url) #{repo.url}]
dt Repository ID
dd #{repo.Repo_id}
dt Dependencies
each dependency in repo.dependencies
dd #{dependency.name} (v#{dependency.version})
Have a look at the syntax for pug tab interpolation, it looks like you're using it incorrectly in your example.
Also, check out the documentation on the proper usage of dd elements and how they should be used with dt elements. They also must be children of a description list (dl) element: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dl

On saving entity PrimaryGeneratedColumn value not generated, gives NOT NULL constraint error

Typeorm 0.2.8
I'm building an Ionic app for both mobile use and browser (PWA) use. Below is some shortened code from my project. I create a simple entity with a PrimaryGeneratedColumn and try to insert one instance. This generates an error about the primary column being NULL. Doesn't the word 'generated' mean the column value gets generated?
Is this a bug? Something specific to the sqljs driver? Or something obvious and simple I missed?
Entity
#Entity()
export class MyEntity {
#PrimaryGeneratedColumn()
id:number;
#Column()
name:string;
#CreateDateColumn()
createdAt:string;
}
Migration
export class Migration20181022133900 implements MigrationInterface {
async up(queryRunner: QueryRunner): Promise<any> {
await queryRunner.createTable(new Table({
name: 'my_entity',
columns: [
{
name: 'id',
type: 'int',
isPrimary: true,
isGenerated: true
},
{
name: 'name',
type: 'varchar'
},
{
name: 'createdAt',
type: 'timestamp',
'default': 'now()'
}
]
}), true);
}
async down(queryRunner: QueryRunner): Promise<any> {
await queryRunner.dropTable('my_entity');
}
}
Database provider
const DATABASE_SHARED_OPTIONS:Partial<ConnectionOptions> = {
entities: [
MyEntity
],
logging: 'all',
logger: new DatabaseLogger(),
migrationsRun: true,
migrations: [
Migration20181022133900
]
};
#Injectable()
export class Database {
constructor(public platform:Platform) {}
setup(): Promise<Connection> {
let options: CordovaConnectionOptions | SqljsConnectionOptions;
// Mobile app
if (this.platform.is('cordova')) {
options = {
type: 'cordova',
database: 'my_project.db',
location: 'default',
};
options = Object.assign(options, DATABASE_SHARED_OPTIONS);
}
// Browser PWA app
else {
options = {
type: 'sqljs',
autoSave: true,
location: 'my_project',
};
options = Object.assign(options, DATABASE_SHARED_OPTIONS);
}
return createConnection(options);
}
}
App component
export class MyApp {
constructor(
platform: Platform,
database: Database
) {
platform.ready().then(() => {
database.setup()
.then((connection) => {
this.insertTest();
});
});
}
insertTest() {
const myEntity= new MyEntity();
myEntity.name = 'foo';
getRepository(MyEntity).save(myEntity)
.then((data) => {
console.log(data); // never reached due to error
});
}
}
The database log show the following query (with parameters ["foo"]):
INSERT INTO "my_entity"("name", "createdAt") VALUES (?, datetime('now'))
The following error shows up in my console:
ERROR Error: Uncaught (in promise): QueryFailedError: NOT NULL constraint failed: my_entity.id
Update 1
It only seems to give the error when using migrations. Removing the migrations and using synchronize: true on the database setting works and generates an id for the entity. So is there something wrong with my column definition in the migration code?
{
name: 'id',
type: 'int',
isPrimary: true,
isGenerated: true
}
Update 2
Okay, I fixed it. The migration configuration for a #PrimaryGeneratedColumn seems to be very specific. For anyone else facing this issue, this fixed it for me:
{
name: 'id',
type: 'integer', // instead of 'int', required for the increment strategy
isPrimary: true,
isGenerated: true,
generationStrategy: 'increment' // thought this was the default
}
Okay, I fixed it. The migration configuration for a #PrimaryGeneratedColumn seems to be very specific. For anyone else facing this issue, this fixed it for me:
{
name: 'id',
type: 'integer', // instead of 'int', required for the increment strategy
isPrimary: true,
isGenerated: true,
generationStrategy: 'increment' // thought this was the default
}

Formatting return Type of the column in Sequelize

I have used Sequelize to state the type of one of my columns as follows:
userTime: DataTypes.TIME
This declares the column in MS SQL as time(7) format.
I add data to the respective column as a string. e.g: "12:00"
However, when I retrieve the data from the DB it comes out in the following format:
userTime: "1970-01-01T12:00:00.000Z"
How can I change the output to be of the following format, using Sequelize:
userTime: "12:00"
Is there a possibility, to use FORMAT of the return type in Sequelize?
What I would suggest is to create a getterMethods , work like a virtual field , that you will get in each query.
var User = sequelize.define('users',{
userTime:{
type: DataTypes.TIME
},
name:{
type: db.Sequelize.STRING,
allowNull: false
},
image: {
type: db.Sequelize.STRING,
allowNull: true
},
.... // other fields
},{
getterMethods:{
modifiedUserTime() {
return moment(this.userTime); // modify the time as you want
}
}
});
Actually, I solved the problem, was way easier than I thought.
userTime: {
type: DataTypes.TIME,
allowNull: true,
get() {
const userTime = this.getDataValue('userTime');
if(userTime == null) return userTime;
const time = new Date(userTime);
let hours = addZero(time.getUTCHours());
let minutes = addZero(time.getUTCMinutes());
let combinedTime = hours + ":" + minutes;
return combinedTime;
}
}
function addZero(i) {
if (i < 10) {
i = "0" + i;
}
return i;
}

Resources