Gatsby - Getting undefined for MySQL id - mysql

I want to get into Gatsby.
My current problem is, that i can not get the "id" from mysql database.
The result for "id" (Primary "AUTO_INCREMENT") is "mysql__Homepage__undefined" (expected "16" - represented in DB))
The result for "id2" is "4" (represented in DB)
My table structure
CREATE TABLE `homepage` (
`id` int(5) UNSIGNED NOT NULL,
`id2` smallint(1) UNSIGNED NOT NULL,
`release` char(3) NOT NULL DEFAULT 'on',
`headline` varchar(250) NOT NULL,
`lastmodified` varchar(100) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
My Gatsby GQL is
allMysqlHomepage {
edges {
node {
headline
id
id2
}
}
}
Result for id
mysql__Homepage__undefined
Result for id2
4
Someone run into same problem?
Best regards

Found the solution:
In gatsby-config.js I had to set the idFieldName to my id field from db:
{
resolve: `gatsby-source-mysql`,
options: {
connectionDetails: {
host: 'localhost',
user: 'test',
password: 'test',
database: 'test'
},
queries: [
{
statement: 'SELECT * FROM test',
idFieldName: 'id',
name: 'test'
}
]
}
}
```

Related

#mysql/xdevapi How to debug "wrong number of fields in row being inserted" in nodejs?

I successfully connected to a local MySQL server using the new x-authentication. I have a products table with the following schema (DDL):
CREATE TABLE `products` (
`id` int unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(45) NOT NULL,
`description_he` text,
`description_en` text,
`display_name_he` varchar(45) DEFAULT NULL,
`display_name_en` varchar(45) DEFAULT NULL,
`image_path` varchar(255) DEFAULT NULL,
`price` smallint unsigned NOT NULL,
`is_visible` tinyint NOT NULL DEFAULT '1',
PRIMARY KEY (`id`),
UNIQUE KEY `id_UNIQUE` (`id`),
UNIQUE KEY `name_UNIQUE` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COMMENT='contains information about products'
I tried to insert the following javascript object into this table:
Product {
productID: null,
productName: 'product2',
descriptionHE: 'תיאור המוצר',
descriptionEN: 'product description',
displayNameHE: 'מוצר',
displayNameEN: 'Product',
imagePath: 'assets/images/facebook-512.png',
price: 400
}
I did this using the following code:
let table = this.session.getSchema('...').getTable('products')
return table.insert(
'id', 'name', 'description_he', 'description_en', 'display_name_he', 'display_name_en', 'image_path', 'price', 'is_visible')
.values(
5,
product.name,
product.descriptionHE,
product.descriptionEN,
product.displayNameHE,
product.displayNameEN,
product.imagePath,
product.price,
1)
.execute()
.catch((err) => {
console.log(err);
})
This catches the following error:
Error: Wrong number of fields in row being inserted
at SqlResultHandler.BaseHandler.<computed> (C:\Users\...\node_modules\#mysql\xdevapi\lib\Protocol\InboundHandlers\BaseHandler.js:119:17)
at Array.entry (C:\Users\...\node_modules\#mysql\xdevapi\lib\Protocol\InboundHandlers\BaseHandler.js:90:29)
at WorkQueue.process (C:\Users\...\node_modules\#mysql\xdevapi\lib\WorkQueue.js:75:19)
at Client.handleServerMessage (C:\Users\...\node_modules\#mysql\xdevapi\lib\Protocol\Client.js:208:21)
at Client.handleNetworkFragment (C:\Users\...\node_modules\#mysql\xdevapi\lib\Protocol\Client.js:252:14)
at TLSSocket.<anonymous> (C:\Users\...\node_modules\#mysql\xdevapi\lib\Protocol\Client.js:90:36)
at TLSSocket.emit (events.js:315:20)
at addChunk (internal/streams/readable.js:309:12)
at readableAddChunk (internal/streams/readable.js:284:9)
at TLSSocket.Readable.push (internal/streams/readable.js:223:10) {
info: {
severity: 0,
code: 5014,
sqlState: 'HY000',
msg: 'Wrong number of fields in row being inserted'
}
}
I tried playing with the arguments and simplifying the table schema a bit but I can't find the error yet. Do you know how can I debug the query sent to the SQL server to figure out why it's failing?
The problem was that I used product.name instead of product.productName.
Conclusion, use typescript. :)

In nodejs, how to insert data into MySQL using sequelize.bulkcreate?

I have googled and looked up the codes creating data using sequelize.
However, writers are too good to overlook this pity but basic issue.
Where do I write the code?
Here is my directory.
Modeling
/config
config.json
/migrations
(empty)
/models
index.js
platoon.js
section.js
squad.js
team.js
/node_moduels
/seeders
(empty)
app.js
package-lock.json
package.json
The code I am trying to add on my code is
Team.bulkCreate([
{ name: 'team1', platoonID: "4" },
{ username: 'team2', platoonID: "4" },
{ username: 'team3', platoonID: "4" },
{ username: 'team4', platoonID: "4" },
{ username: 'team5', platoonID: "4" }
]).then(() => { // Notice: There are no arguments here, as of right now you'll have to...
return Team.findAll();
}).then(teams => {
console.log(teams) // ... in order to get the array of user objects
})
But the code returns
Executing (default): INSERT INTO `teams` (`id`,`name`,`created_at`,`platoonID`) VALUES (NULL,'1팀',now(),'4'),(NULL,NULL,now(),'4'),(NULL,NULL,now(),'4'),(NULL,NULL,now(),'4'),(NULL,NULL,now(),'4');
Executing (default): CREATE TABLE IF NOT EXISTS `platoons` (`id` INTEGER NOT NULL auto_increment , `name` VARCHAR(20) NOT NULL UNIQUE, `created_at` DATETIME NOT NULL DEFAULT now(), PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_general_ci;
(node:15874) UnhandledPromiseRejectionWarning: SequelizeDatabaseError: Table 'nodejs.teams' doesn't exist
at Query.formatError (/Users/mac/Desktop/modeling/node_modules/sequelize/lib/dialects/mysql/query.js:239:16)
at Query.run (/Users/mac/Desktop/modeling/node_modules/sequelize/lib/dialects/mysql/query.js:54:18)
at processTicksAndRejections (internal/process/task_queues.js:97:5)
(node:15874) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)
(node:15874) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
Executing (default): SHOW INDEX FROM `platoons` FROM `nodejs`
Executing (default): CREATE TABLE IF NOT EXISTS `sections` (`id` INTEGER NOT NULL auto_increment , `name` VARCHAR(20) NOT NULL UNIQUE, `created_at` DATETIME NOT NULL DEFAULT now(), `platoonID` INTEGER, PRIMARY KEY (`id`), FOREIGN KEY (`platoonID`) REFERENCES `platoons` (`id`) ON DELETE SET NULL ON UPDATE CASCADE) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_general_ci;
Executing (default): SHOW INDEX FROM `sections` FROM `nodejs`
Executing (default): CREATE TABLE IF NOT EXISTS `squads` (`id` INTEGER NOT NULL auto_increment , `name` VARCHAR(20) NOT NULL UNIQUE, `created_at` DATETIME NOT NULL DEFAULT now(), `platoonID` INTEGER, PRIMARY KEY (`id`), FOREIGN KEY (`platoonID`) REFERENCES `platoons` (`id`) ON DELETE SET NULL ON UPDATE CASCADE) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_general_ci;
Executing (default): SHOW INDEX FROM `squads` FROM `nodejs`
Executing (default): CREATE TABLE IF NOT EXISTS `teams` (`id` INTEGER NOT NULL auto_increment , `name` VARCHAR(20) NOT NULL UNIQUE, `created_at` DATETIME NOT NULL DEFAULT now(), `sectionID` INTEGER, `squadID` INTEGER, `platoonID` INTEGER, PRIMARY KEY (`id`), FOREIGN KEY (`sectionID`) REFERENCES `sections` (`id`) ON DELETE SET NULL ON UPDATE CASCADE, FOREIGN KEY (`squadID`) REFERENCES `squads` (`id`) ON DELETE SET NULL ON UPDATE CASCADE, FOREIGN KEY (`platoonID`) REFERENCES `platoons` (`id`) ON DELETE SET NULL ON UPDATE CASCADE) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_general_ci;
Executing (default): SHOW INDEX FROM `teams` FROM `nodejs`
connection succeed
I wrote this code in models/index.js.
I guess the code should be written in models/index.js, but it seems not.
How can I insert bulk data into MySQL using sequelize.bulkcreate?
models/index.js
const Sequelize = require('sequelize');
const Team = require("./team");
const Section = require("./section");
const Squad = require("./squad");
const Platoon = require("./platoon");
const env = process.env.NODE_ENV || 'development';
const config = require('../config/config')[env];
const db = {};
const sequelize = new Sequelize(config.database, config.username, config.password, config);
db.sequelize = sequelize;
db.Team = Team;
db.Section = Section;
db.Squad = Squad;
db.Platoon = Platoon;
Team.init(sequelize);
Section.init(sequelize);
Squad.init(sequelize);
Platoon.init(sequelize);
Team.associate(db);
Section.associate(db);
Squad.associate(db);
Platoon.associate(db);
//Team.bulkCreate([
// { name: 'team1', platoonID: "4" },
// { username: 'team2', platoonID: "4" },
// { username: 'team3', platoonID: "4" },
// { username: 'team4', platoonID: "4" },
// { username: 'team5', platoonID: "4" }
//]).then(() => {
// return Team.findAll();
//}).then(teams => {
// console.log(teams)
//})
module.exports = db;
Team.bulkCreate([
{ name: 'team1', platoonID: "4" },
{ username: 'team2', platoonID: "4" },
{ username: 'team3', platoonID: "4" },
{ username: 'team4', platoonID: "4" },
{ username: 'team5', platoonID: "4" }
]).then(() => {
return Team.findAll();
}).then(teams => {
console.log(teams)
})
models/team.js
const Sequelize = require("sequelize");
module.exports = class Team extends Sequelize.Model{
static init(sequelize) {
return super.init({
name : {
type : Sequelize.STRING(20),
allowNull : false,
unique : true,
},
created_at : {
type : Sequelize.DATE,
allowNull : false,
defaultValue : sequelize.literal('now()'),
},
},{
sequelize,
timestamps : false,
underscored : false,
modelName : 'Team',
tableName : 'teams',
paranoid : false,
charset : 'utf8',
collate : 'utf8_general_ci',
});
}
static associate(db) {
db.Team.belongsTo(db.Section, {
foreignKey : "sectionID",
targetKey : 'id'
});
db.Team.belongsTo(db.Squad, {
foreignKey : "squadID",
targetKey : 'id'
});
db.Team.belongsTo(db.Platoon, {
foreignKey : "platoonID",
targetKey : 'id'
});
};
}
I have tried to write the code in models/index.js file but it fails.
Please help where to write the code

#mysql/xdevapi returning invalid input expression when inserting data (MySQL 8)

I'm using the #mysql/xdevapi package with NodeJS and the MySQL 8 docker container.
The error I'm getting is:
Error: invalid input expression
at module.exports (C:\Users\BugHunter\Projects\nines\server\node_modules\#mysql\xdevapi\lib\DevAPI\Util\parseFlexibleParamList.js:43:15)
Here's my table:
CREATE TABLE IF NOT EXISTS `surveyrewards`.`users` (
`id` INT NOT NULL AUTO_INCREMENT,
`firstname` VARCHAR(20) NOT NULL,
`surname` VARCHAR(20) NOT NULL,
`birthday` DATE NULL,
`gender` ENUM("male", "female") NOT NULL,
`email` VARCHAR(255) NOT NULL,
`postcode` VARCHAR(10) NULL,
`is_subscribed` TINYINT NOT NULL DEFAULT 0,
`is_confirmed` TINYINT NOT NULL DEFAULT 0,
`last_mailed` TIMESTAMP NULL,
`created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE INDEX `email_UNIQUE` (`email` ASC) VISIBLE)
ENGINE = InnoDB;
And my node code using these docs:
require('dotenv').config()
const mysqlx = require('#mysql/xdevapi')
const config = {
host: process.env.MYSQL_HOST ,
user: process.env.MYSQL_USER,
port: parseInt(process.env.MYSQL_PORT),
password: process.env.MYSQL_PASSWORD,
schema: process.env.MYSQL_DATABASE
}
mysqlx.getSession(config)
.then(session => {
console.log(process.env)
const table = session.getSchema(config.schema).getTable('users')
return table
.insert([ 'firstname', 'surname', 'email', 'gender', 'is_subscribed', 'is_confirmed' ])
.values('Bob', 'hope', 'bob#example.com', 'male', 0, 0)
.execute()
})
.then(() => console.log('Works'))
.catch(err => console.warn(err))
The error is vauge and I'm not sure how to progress from here as my code is the same. Any advice?
That is actually a bug, which is why the error message is not clear. :)
Falsy values such as 0 are not currently accepted as valid values() arguments. This should not be the case though. If you feel like it, you can report it via the MySQL bug tracker using the Connector for Node.js category, but you can consider this as being tracked.
One sort of nasty workaround is to use strings instead. Even if the SQL datatype is TINYINT like in your case, it will still work and the value will be "coerced".
return table
.insert([ 'firstname', 'surname', 'email', 'gender', 'is_subscribed', 'is_confirmed' ])
.values('Bob', 'hope', 'bob#example.com', 'male', '0', '0')
.execute()
Disclaimer: I'm the lead dev of the connector.

Parse the result of a mysql select query on multiple tables with nodeJS

I'm a nodeJS beginner and am trying to learn it by creating a blog. To do so, I have three tables
CREATE TABLE `articles` (
`article_id` int(11) NOT NULL AUTO_INCREMENT,
`title` varchar(255) NOT NULL,
`content` longtext NOT NULL,
`image` varchar(255) NOT NULL,
`created` datetime NOT NULL,
`author_id` int(11) NOT NULL,
PRIMARY KEY (`article_id`)
)
CREATE TABLE `authors` (
`author_id` int(11) NOT NULL AUTO_INCREMENT,
`email` varchar(255) NOT NULL,
PRIMARY KEY (`author_id`)
)
CREATE TABLE `comments` (
`comment_id` int(11) NOT NULL AUTO_INCREMENT,
`comment_content` longtext NOT NULL,
`created` datetime NOT NULL,
`comment_author` varchar(255) NOT NULL,
`id_article` int(11) NOT NULL,
PRIMARY KEY (`comment_id`)
)
On my page, I want to get all my articles, with their associated authors and comments.
This is my node code to get the data :
app.get('/api/articles', function(req, res){
connection.query('SELECT * FROM articles LEFT JOIN authors ON articles.author_id = authors.author_id LEFT JOIN comments ON articles.article_id = comments.id_article', function(err, row, fields){
if(!err){
res.json(rows);
}else
console.log('Error');
});
});
This query returns the data I need, but I want to parse it to get something that I can use easier in the front part, like
[
{
article_id: 1,
content: 'test',
title: 'test',
image: '',
author: {
author_id: 1,
email: 'test#test.com'
},
comments: [
{
comment_id: 1,
comment_content: 'test',
comment_author: 'test'
},
{
comment_id: 2,
comment_content: 'test',
comment_author: 'test'
}
]
}
]
Instead of the current return that looks like
[
{
article_id: 1,
title: 'test',
content: 'test',
image: '',
author_id: 1,
email: 'test#test.com',
comment_id: 1,
comment_content: 'test',
comment_author: 'test
}
]
I spent some time looking for something to do it, but couldn't find anything, so if someone knows how to do it, I'd be very grateful.
Thanks
You'll need to do two things:
(1) make sure you are sorting by article_id in your query
(2) create a tiny state machine, keeping track of the article_id, and loop through each record aggregating the comments. if your article_id changes, write the record to the table and move on to the next article:
var table = [];
var lastid = -1;
var article = {};
for(var i=0;i<rows.length;i++) {
var row = rows[i];
if (row.article_id!==lastid) {
//The id has changed, so create a new article
if (article.article_id) {
//If this isnt the first time looping, add the last article to the table
table.push(article);
}
article = {};
//create the structure you want
article.article_id = row.article_id;
article.title = row.title,
article.content = row.content,
article.image = row.image,
article.author = {
author_id: row.author_id,
email: row.email,
};
//comments go in this array. add the first one
article.comments = [{
comment_id:row.comment_id,
comment_content:row.commment_content,
comment_author:row.comment_author
}];
} else {
//same article, new comment
article.comments.push({
comment_id:row.comment_id,
comment_content:row.commment_content,
comment_author:row.comment_author
})
}
//update the id to check against the next row
lastid = row.article_id;
}
//make sure you push on the last article
table.push(article);
//Now you can send back the table in the new structure...
return table;

Auto increment id with sequelize in MySQL

I have the following model in NodeJS with sequelize and a MySQL database:
var Sequelize = require('sequelize');
var User = sequelize.define('user', {
id: {
type: Sequelize.INTEGER,
autoIncrement: true,
primaryKey: true
},
...
};
I am trying to add a new user to my databse with the below code:
sequelize.transaction().then(function(t) {
User.create({/* User data without id */}, {
transaction: t
}).then(function() {
t.commit();
}).catch(function(error) {
t.rollback();
});
});
After that, I am getting the next error:
Executing (47f19f7b-a02d-4d72-ba7e-d5045520fffb): START TRANSACTION;
Executing (47f19f7b-a02d-4d72-ba7e-d5045520fffb): SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
Executing (47f19f7b-a02d-4d72-ba7e-d5045520fffb): SET autocommit = 1;
Executing (47f19f7b-a02d-4d72-ba7e-d5045520fffb): INSERT INTO `user` (`id`, /* next fields */) VALUES (DEFAULT, /* next values */);
Executing (47f19f7b-a02d-4d72-ba7e-d5045520fffb): ROLLBACK;
And the error message:
[SequelizeDatabaseError: ER_NO_DEFAULT_FOR_FIELD: Field 'id' doesn't have a default value]
name: 'SequelizeDatabaseError',
message: 'ER_NO_DEFAULT_FOR_FIELD: Field \'id\' doesn\'t have a default value'
However, if I manually set the id value, it works. It seems sequelize is trying to set a default value in the id field, instead setting an autoincrement integer. I have defined this field as autoIncrement in my database too.
How could I do this insertion? Do I have to set the id manually?
EDIT
This is my table definition:
CREATE TABLE `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`uid` varchar(9) NOT NULL,
`name` varchar(20) NOT NULL,
`email` varchar(30) DEFAULT NULL,
`birthdate` date NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `uid_UNIQUE` (`uid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
You must be sure you're not even sending the id key at all.
I have done a quick minimal test and it seemed to work great:
var Sequelize = require('sequelize');
var sequelize = new Sequelize('cake3', 'root', 'root', {
define: {
timestamps: false
},
});
var User = sequelize.define('user1', {
id: {
type: Sequelize.INTEGER,
autoIncrement: true,
primaryKey: true
},
name: {
type: Sequelize.STRING
}
});
sequelize.transaction().then(function(t) {
User.create({name:'test'}, {
transaction: t
}).then(function() {
t.commit();
}).catch(function(error) {
console.log(error);
t.rollback();
});
});
Table dump:
CREATE TABLE `user1s` (
`id` int(11) NOT NULL,
`name` varchar(20) NOT NULL
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
ALTER TABLE `user1s`
ADD PRIMARY KEY (`id`);
ALTER TABLE `user1s`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=1;
In migration, add this line of code:
await queryInterface.sequelize.query("ALTER TABLE table_name AUTO_INCREMENT = 1000000;");