javascript - Node.js - PostgreSQL - nelze určit datový typ parametru $1 chyba
Snažím se vytvořit připravený příkaz PostgreSQL pomocí balíčku pg npm v node.js. Nicméně stále dostávám chybu:
nelze určit datový typ parametru $1
function promiseQuery(sql, values) {
return new Promise(function(resolve, reject) {
pool.query('select $1 from workers', ['name'], function(err, result) {
if (err) {console.log(err); reject(err)}
else resolve(result.rows);
})
});
}
V databázi je pole name nastaveno na typ text not null.
Také jsem zkoušel pg-promise, ale také bez úspěchu.
Odpověď č. 1
V dotazu select name from workers je z hlediska syntaxi SQL name identifikátorem a identifikátory nemohou být nikdy předávány jako parametry $N, musí se objevit doslovně v příkazu. Jinak nelze dotaz připravit.
Parametry $N se mohou v dotazu objevit pouze na místech, kde by se vyskytovaly literály (konstanty).
Měli byste stejnou chybu, pokud byste zkoušeli něco podobného s SQL příkazem PREPARE, mimo jakoukoli knihovnu na straně klienta:
PREPARE p as SELECT $1 FROM pg_class;
ERROR: could not determine data type of parameter $1
Řešením je sestavit dotaz v JavaScriptu pomocí technik nahrazování řetězců pro názvy sloupců nebo názvy tabulek, před jeho odesláním do databáze.
pg-promise podporuje vkládání identifikátorů do dotazu se specifickou syntaxí. Z jeho dokumentace:
db.query('SELECT $1:name FROM $2:name', ['*', 'table']);
//=> SELECT * FROM "table"
Odpověď č. 2
Navazující na odpověď Daniela Vérité...
Nelze kombinovat připravené příkazy s dynamickými názvy sloupců, museli byste dotaz generovat na straně klienta.
Při použití syntaxe pg-promise pro názvy SQL můžete svůj dotaz správně uzavřít takto:
db.any('SELECT $1~ FROM table', [colName])
// OR:
db.any('SELECT $1:name FROM table', [colName])
// OR:
db.any('SELECT ${colName~} FROM table', {colName})
// OR:
db.any('SELECT ${colName:name} FROM table', {colName})
// Etc, other variable syntax, like $[], $//, $<>, $()
A pokud to chcete udělat pro seznam sloupců, nejjednodušší způsob, jak to udělat, je takto:
const colNames = ['one', 'two', 'three'];
db.any('SELECT $1~ FROM table', [colNames])
// etc, the same variations as above, all will generate:
// SELECT "one","two","three" FROM table
nebo ze všech vlastností objektu:
const data = {
one: 123,
two: true,
three: 'text'
};
db.any('SELECT $1~ FROM table', [data])
// etc, the same variations as above, all will generate:
// SELECT "one","two","three" FROM table
Všechny tyto metody správně ošetří dotaz, čímž zajistí, že SQL injection není možná.
