不要怂,就是干,撸起袖子干!

Commit a72a3f50 by Sushant Committed by GitHub

fix(mariadb): properly escape json path key (#11089)

1 parent 3dca9fa0
...@@ -1053,12 +1053,12 @@ class QueryGenerator { ...@@ -1053,12 +1053,12 @@ class QueryGenerator {
* https://bugs.mysql.com/bug.php?id=81896 * https://bugs.mysql.com/bug.php?id=81896
*/ */
paths = paths.map(subPath => Utils.addTicks(subPath, '"')); paths = paths.map(subPath => Utils.addTicks(subPath, '"'));
pathStr = ['$'].concat(paths).join('.'); pathStr = this.escape(['$'].concat(paths).join('.'));
return `(${quotedColumn}->>'${pathStr}')`; return `(${quotedColumn}->>${pathStr})`;
case 'mariadb': case 'mariadb':
pathStr = ['$'].concat(paths).join('.'); pathStr = this.escape(['$'].concat(paths).join('.'));
return `json_unquote(json_extract(${quotedColumn},'${pathStr}'))`; return `json_unquote(json_extract(${quotedColumn},${pathStr}))`;
case 'sqlite': case 'sqlite':
pathStr = this.escape(['$'] pathStr = this.escape(['$']
......
...@@ -72,7 +72,7 @@ ...@@ -72,7 +72,7 @@
"lint-staged": "^8.1.5", "lint-staged": "^8.1.5",
"mariadb": "^2.0.3", "mariadb": "^2.0.3",
"markdownlint-cli": "^0.14.1", "markdownlint-cli": "^0.14.1",
"mocha": "^6.0.2", "mocha": "6.0.2",
"mysql2": "^1.6.5", "mysql2": "^1.6.5",
"nyc": "^13.3.0", "nyc": "^13.3.0",
"pg": "^7.8.1", "pg": "^7.8.1",
...@@ -80,8 +80,8 @@ ...@@ -80,8 +80,8 @@
"pg-types": "^2.0.0", "pg-types": "^2.0.0",
"rimraf": "^2.6.3", "rimraf": "^2.6.3",
"semantic-release": "^15.13.3", "semantic-release": "^15.13.3",
"sinon": "^7.2.6", "sinon": "7.2.6",
"sinon-chai": "^3.2.0", "sinon-chai": "3.2.0",
"sqlite3": "^4.0.6", "sqlite3": "^4.0.6",
"tedious": "^6.0.0", "tedious": "^6.0.0",
"typescript": "^3.3.3333" "typescript": "^3.3.3333"
......
...@@ -73,6 +73,7 @@ describe(Support.getTestDialectTeaser('Include'), () => { ...@@ -73,6 +73,7 @@ describe(Support.getTestDialectTeaser('Include'), () => {
}); });
}); });
}); });
it('should be able to include a required model. Result rows should match count', function() { it('should be able to include a required model. Result rows should match count', function() {
const User = this.sequelize.define('User', { name: DataTypes.STRING(40) }, { paranoid: true }), const User = this.sequelize.define('User', { name: DataTypes.STRING(40) }, { paranoid: true }),
SomeConnection = this.sequelize.define('SomeConnection', { SomeConnection = this.sequelize.define('SomeConnection', {
......
...@@ -685,6 +685,18 @@ describe(Support.getTestDialectTeaser('Model'), () => { ...@@ -685,6 +685,18 @@ describe(Support.getTestDialectTeaser('Model'), () => {
}); });
}); });
it('should properly escape path keys', function() {
return this.Model.findAll({
raw: true,
attributes: ['id'],
where: {
data: {
"a')) AS DECIMAL) = 1 DELETE YOLO INJECTIONS; -- ": 1
}
}
});
});
it('should properly escape the single quotes in array', function() { it('should properly escape the single quotes in array', function() {
return this.Model.create({ return this.Model.create({
data: { data: {
......
...@@ -851,7 +851,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { ...@@ -851,7 +851,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => {
prefix: 'User' prefix: 'User'
}, { }, {
mariadb: "json_unquote(json_extract(`User`.`data`,'$.nested.attribute')) = 'value'", mariadb: "json_unquote(json_extract(`User`.`data`,'$.nested.attribute')) = 'value'",
mysql: "(`User`.`data`->>'$.\"nested\".\"attribute\"') = 'value'", mysql: "(`User`.`data`->>'$.\\\"nested\\\".\\\"attribute\\\"') = 'value'",
postgres: "(\"User\".\"data\"#>>'{nested,attribute}') = 'value'", postgres: "(\"User\".\"data\"#>>'{nested,attribute}') = 'value'",
sqlite: "json_extract(`User`.`data`, '$.nested.attribute') = 'value'" sqlite: "json_extract(`User`.`data`, '$.nested.attribute') = 'value'"
}); });
...@@ -866,7 +866,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { ...@@ -866,7 +866,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => {
} }
}, { }, {
mariadb: "CAST(json_unquote(json_extract(`data`,'$.nested')) AS DECIMAL) IN (1, 2)", mariadb: "CAST(json_unquote(json_extract(`data`,'$.nested')) AS DECIMAL) IN (1, 2)",
mysql: "CAST((`data`->>'$.\"nested\"') AS DECIMAL) IN (1, 2)", mysql: "CAST((`data`->>'$.\\\"nested\\\"') AS DECIMAL) IN (1, 2)",
postgres: "CAST((\"data\"#>>'{nested}') AS DOUBLE PRECISION) IN (1, 2)", postgres: "CAST((\"data\"#>>'{nested}') AS DOUBLE PRECISION) IN (1, 2)",
sqlite: "CAST(json_extract(`data`, '$.nested') AS DOUBLE PRECISION) IN (1, 2)" sqlite: "CAST(json_extract(`data`, '$.nested') AS DOUBLE PRECISION) IN (1, 2)"
}); });
...@@ -881,7 +881,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { ...@@ -881,7 +881,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => {
} }
}, { }, {
mariadb: "CAST(json_unquote(json_extract(`data`,'$.nested')) AS DECIMAL) BETWEEN 1 AND 2", mariadb: "CAST(json_unquote(json_extract(`data`,'$.nested')) AS DECIMAL) BETWEEN 1 AND 2",
mysql: "CAST((`data`->>'$.\"nested\"') AS DECIMAL) BETWEEN 1 AND 2", mysql: "CAST((`data`->>'$.\\\"nested\\\"') AS DECIMAL) BETWEEN 1 AND 2",
postgres: "CAST((\"data\"#>>'{nested}') AS DOUBLE PRECISION) BETWEEN 1 AND 2", postgres: "CAST((\"data\"#>>'{nested}') AS DOUBLE PRECISION) BETWEEN 1 AND 2",
sqlite: "CAST(json_extract(`data`, '$.nested') AS DOUBLE PRECISION) BETWEEN 1 AND 2" sqlite: "CAST(json_extract(`data`, '$.nested') AS DOUBLE PRECISION) BETWEEN 1 AND 2"
}); });
...@@ -900,7 +900,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { ...@@ -900,7 +900,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => {
prefix: current.literal(sql.quoteTable.call(current.dialect.QueryGenerator, { tableName: 'User' })) prefix: current.literal(sql.quoteTable.call(current.dialect.QueryGenerator, { tableName: 'User' }))
}, { }, {
mariadb: "(json_unquote(json_extract(`User`.`data`,'$.nested.attribute')) = 'value' AND json_unquote(json_extract(`User`.`data`,'$.nested.prop')) != 'None')", mariadb: "(json_unquote(json_extract(`User`.`data`,'$.nested.attribute')) = 'value' AND json_unquote(json_extract(`User`.`data`,'$.nested.prop')) != 'None')",
mysql: "((`User`.`data`->>'$.\"nested\".\"attribute\"') = 'value' AND (`User`.`data`->>'$.\"nested\".\"prop\"') != 'None')", mysql: "((`User`.`data`->>'$.\\\"nested\\\".\\\"attribute\\\"') = 'value' AND (`User`.`data`->>'$.\\\"nested\\\".\\\"prop\\\"') != 'None')",
postgres: "((\"User\".\"data\"#>>'{nested,attribute}') = 'value' AND (\"User\".\"data\"#>>'{nested,prop}') != 'None')", postgres: "((\"User\".\"data\"#>>'{nested,attribute}') = 'value' AND (\"User\".\"data\"#>>'{nested,prop}') != 'None')",
sqlite: "(json_extract(`User`.`data`, '$.nested.attribute') = 'value' AND json_extract(`User`.`data`, '$.nested.prop') != 'None')" sqlite: "(json_extract(`User`.`data`, '$.nested.attribute') = 'value' AND json_extract(`User`.`data`, '$.nested.prop') != 'None')"
}); });
...@@ -919,7 +919,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { ...@@ -919,7 +919,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => {
prefix: 'User' prefix: 'User'
}, { }, {
mariadb: "(json_unquote(json_extract(`User`.`data`,'$.name.last')) = 'Simpson' AND json_unquote(json_extract(`User`.`data`,'$.employment')) != 'None')", mariadb: "(json_unquote(json_extract(`User`.`data`,'$.name.last')) = 'Simpson' AND json_unquote(json_extract(`User`.`data`,'$.employment')) != 'None')",
mysql: "((`User`.`data`->>'$.\"name\".\"last\"') = 'Simpson' AND (`User`.`data`->>'$.\"employment\"') != 'None')", mysql: "((`User`.`data`->>'$.\\\"name\\\".\\\"last\\\"') = 'Simpson' AND (`User`.`data`->>'$.\\\"employment\\\"') != 'None')",
postgres: "((\"User\".\"data\"#>>'{name,last}') = 'Simpson' AND (\"User\".\"data\"#>>'{employment}') != 'None')", postgres: "((\"User\".\"data\"#>>'{name,last}') = 'Simpson' AND (\"User\".\"data\"#>>'{employment}') != 'None')",
sqlite: "(json_extract(`User`.`data`, '$.name.last') = 'Simpson' AND json_extract(`User`.`data`, '$.employment') != 'None')" sqlite: "(json_extract(`User`.`data`, '$.name.last') = 'Simpson' AND json_extract(`User`.`data`, '$.employment') != 'None')"
}); });
...@@ -933,7 +933,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { ...@@ -933,7 +933,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => {
} }
}, { }, {
mariadb: "(CAST(json_unquote(json_extract(`data`,'$.price')) AS DECIMAL) = 5 AND json_unquote(json_extract(`data`,'$.name')) = 'Product')", mariadb: "(CAST(json_unquote(json_extract(`data`,'$.price')) AS DECIMAL) = 5 AND json_unquote(json_extract(`data`,'$.name')) = 'Product')",
mysql: "(CAST((`data`->>'$.\"price\"') AS DECIMAL) = 5 AND (`data`->>'$.\"name\"') = 'Product')", mysql: "(CAST((`data`->>'$.\\\"price\\\"') AS DECIMAL) = 5 AND (`data`->>'$.\\\"name\\\"') = 'Product')",
postgres: "(CAST((\"data\"#>>'{price}') AS DOUBLE PRECISION) = 5 AND (\"data\"#>>'{name}') = 'Product')", postgres: "(CAST((\"data\"#>>'{price}') AS DOUBLE PRECISION) = 5 AND (\"data\"#>>'{name}') = 'Product')",
sqlite: "(CAST(json_extract(`data`, '$.price') AS DOUBLE PRECISION) = 5 AND json_extract(`data`, '$.name') = 'Product')" sqlite: "(CAST(json_extract(`data`, '$.price') AS DOUBLE PRECISION) = 5 AND json_extract(`data`, '$.name') = 'Product')"
}); });
...@@ -948,7 +948,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { ...@@ -948,7 +948,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => {
} }
}, { }, {
mariadb: "json_unquote(json_extract(`data`,'$.nested.attribute')) = 'value'", mariadb: "json_unquote(json_extract(`data`,'$.nested.attribute')) = 'value'",
mysql: "(`data`->>'$.\"nested\".\"attribute\"') = 'value'", mysql: "(`data`->>'$.\\\"nested\\\".\\\"attribute\\\"') = 'value'",
postgres: "(\"data\"#>>'{nested,attribute}') = 'value'", postgres: "(\"data\"#>>'{nested,attribute}') = 'value'",
sqlite: "json_extract(`data`, '$.nested.attribute') = 'value'" sqlite: "json_extract(`data`, '$.nested.attribute') = 'value'"
}); });
...@@ -963,7 +963,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { ...@@ -963,7 +963,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => {
} }
}, { }, {
mariadb: "CAST(json_unquote(json_extract(`data`,'$.nested.attribute')) AS DECIMAL) = 4", mariadb: "CAST(json_unquote(json_extract(`data`,'$.nested.attribute')) AS DECIMAL) = 4",
mysql: "CAST((`data`->>'$.\"nested\".\"attribute\"') AS DECIMAL) = 4", mysql: "CAST((`data`->>'$.\\\"nested\\\".\\\"attribute\\\"') AS DECIMAL) = 4",
postgres: "CAST((\"data\"#>>'{nested,attribute}') AS DOUBLE PRECISION) = 4", postgres: "CAST((\"data\"#>>'{nested,attribute}') AS DOUBLE PRECISION) = 4",
sqlite: "CAST(json_extract(`data`, '$.nested.attribute') AS DOUBLE PRECISION) = 4" sqlite: "CAST(json_extract(`data`, '$.nested.attribute') AS DOUBLE PRECISION) = 4"
}); });
...@@ -980,7 +980,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { ...@@ -980,7 +980,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => {
} }
}, { }, {
mariadb: "CAST(json_unquote(json_extract(`data`,'$.nested.attribute')) AS DECIMAL) IN (3, 7)", mariadb: "CAST(json_unquote(json_extract(`data`,'$.nested.attribute')) AS DECIMAL) IN (3, 7)",
mysql: "CAST((`data`->>'$.\"nested\".\"attribute\"') AS DECIMAL) IN (3, 7)", mysql: "CAST((`data`->>'$.\\\"nested\\\".\\\"attribute\\\"') AS DECIMAL) IN (3, 7)",
postgres: "CAST((\"data\"#>>'{nested,attribute}') AS DOUBLE PRECISION) IN (3, 7)", postgres: "CAST((\"data\"#>>'{nested,attribute}') AS DOUBLE PRECISION) IN (3, 7)",
sqlite: "CAST(json_extract(`data`, '$.nested.attribute') AS DOUBLE PRECISION) IN (3, 7)" sqlite: "CAST(json_extract(`data`, '$.nested.attribute') AS DOUBLE PRECISION) IN (3, 7)"
}); });
...@@ -997,7 +997,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { ...@@ -997,7 +997,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => {
} }
}, { }, {
mariadb: "CAST(json_unquote(json_extract(`data`,'$.nested.attribute')) AS DECIMAL) > 2", mariadb: "CAST(json_unquote(json_extract(`data`,'$.nested.attribute')) AS DECIMAL) > 2",
mysql: "CAST((`data`->>'$.\"nested\".\"attribute\"') AS DECIMAL) > 2", mysql: "CAST((`data`->>'$.\\\"nested\\\".\\\"attribute\\\"') AS DECIMAL) > 2",
postgres: "CAST((\"data\"#>>'{nested,attribute}') AS DOUBLE PRECISION) > 2", postgres: "CAST((\"data\"#>>'{nested,attribute}') AS DOUBLE PRECISION) > 2",
sqlite: "CAST(json_extract(`data`, '$.nested.attribute') AS DOUBLE PRECISION) > 2" sqlite: "CAST(json_extract(`data`, '$.nested.attribute') AS DOUBLE PRECISION) > 2"
}); });
...@@ -1014,7 +1014,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { ...@@ -1014,7 +1014,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => {
} }
}, { }, {
mariadb: "CAST(json_unquote(json_extract(`data`,'$.nested.attribute')) AS DECIMAL) > 2", mariadb: "CAST(json_unquote(json_extract(`data`,'$.nested.attribute')) AS DECIMAL) > 2",
mysql: "CAST((`data`->>'$.\"nested\".\"attribute\"') AS DECIMAL) > 2", mysql: "CAST((`data`->>'$.\\\"nested\\\".\\\"attribute\\\"') AS DECIMAL) > 2",
postgres: "CAST((\"data\"#>>'{nested,attribute}') AS INTEGER) > 2", postgres: "CAST((\"data\"#>>'{nested,attribute}') AS INTEGER) > 2",
sqlite: "CAST(json_extract(`data`, '$.nested.attribute') AS INTEGER) > 2" sqlite: "CAST(json_extract(`data`, '$.nested.attribute') AS INTEGER) > 2"
}); });
...@@ -1032,7 +1032,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { ...@@ -1032,7 +1032,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => {
} }
}, { }, {
mariadb: `CAST(json_unquote(json_extract(\`data\`,'$.nested.attribute')) AS DATETIME) > ${sql.escape(dt)}`, mariadb: `CAST(json_unquote(json_extract(\`data\`,'$.nested.attribute')) AS DATETIME) > ${sql.escape(dt)}`,
mysql: `CAST((\`data\`->>'$."nested"."attribute"') AS DATETIME) > ${sql.escape(dt)}`, mysql: `CAST((\`data\`->>'$.\\"nested\\".\\"attribute\\"') AS DATETIME) > ${sql.escape(dt)}`,
postgres: `CAST(("data"#>>'{nested,attribute}') AS TIMESTAMPTZ) > ${sql.escape(dt)}`, postgres: `CAST(("data"#>>'{nested,attribute}') AS TIMESTAMPTZ) > ${sql.escape(dt)}`,
sqlite: `json_extract(\`data\`, '$.nested.attribute') > ${sql.escape(dt.toISOString())}` sqlite: `json_extract(\`data\`, '$.nested.attribute') > ${sql.escape(dt.toISOString())}`
}); });
...@@ -1047,7 +1047,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { ...@@ -1047,7 +1047,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => {
} }
}, { }, {
mariadb: "json_unquote(json_extract(`data`,'$.nested.attribute')) = 'true'", mariadb: "json_unquote(json_extract(`data`,'$.nested.attribute')) = 'true'",
mysql: "(`data`->>'$.\"nested\".\"attribute\"') = 'true'", mysql: "(`data`->>'$.\\\"nested\\\".\\\"attribute\\\"') = 'true'",
postgres: "CAST((\"data\"#>>'{nested,attribute}') AS BOOLEAN) = true", postgres: "CAST((\"data\"#>>'{nested,attribute}') AS BOOLEAN) = true",
sqlite: "CAST(json_extract(`data`, '$.nested.attribute') AS BOOLEAN) = 1" sqlite: "CAST(json_extract(`data`, '$.nested.attribute') AS BOOLEAN) = 1"
}); });
...@@ -1064,7 +1064,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { ...@@ -1064,7 +1064,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => {
} }
}, { }, {
mariadb: "json_unquote(json_extract(`meta_data`,'$.nested.attribute')) = 'value'", mariadb: "json_unquote(json_extract(`meta_data`,'$.nested.attribute')) = 'value'",
mysql: "(`meta_data`->>'$.\"nested\".\"attribute\"') = 'value'", mysql: "(`meta_data`->>'$.\\\"nested\\\".\\\"attribute\\\"') = 'value'",
postgres: "(\"meta_data\"#>>'{nested,attribute}') = 'value'", postgres: "(\"meta_data\"#>>'{nested,attribute}') = 'value'",
sqlite: "json_extract(`meta_data`, '$.nested.attribute') = 'value'" sqlite: "json_extract(`meta_data`, '$.nested.attribute') = 'value'"
}); });
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!