mirror of
https://github.com/github/codeql.git
synced 2026-05-01 19:55:15 +02:00
@@ -28,30 +28,52 @@ module SQL {
|
||||
* Provides classes modelling the (API compatible) `mysql` and `mysql2` packages.
|
||||
*/
|
||||
private module MySql {
|
||||
private string moduleName() { result = ["mysql", "mysql2", "mysql2/promise"] }
|
||||
|
||||
/** Gets the package name `mysql` or `mysql2`. */
|
||||
API::Node mysql() { result = API::moduleImport(["mysql", "mysql2"]) }
|
||||
API::Node mysql() { result = API::moduleImport(moduleName()) }
|
||||
|
||||
/** Gets a reference to `mysql.createConnection`. */
|
||||
API::Node createConnection() { result = mysql().getMember("createConnection") }
|
||||
API::Node createConnection() {
|
||||
result = mysql().getMember(["createConnection", "createConnectionPromise"])
|
||||
}
|
||||
|
||||
/** Gets a reference to `mysql.createPool`. */
|
||||
API::Node createPool() { result = mysql().getMember("createPool") }
|
||||
API::Node createPool() { result = mysql().getMember(["createPool", "createPoolCluster"]) }
|
||||
|
||||
/** Gets a node that contains a MySQL pool created using `mysql.createPool()`. */
|
||||
API::Node pool() { result = createPool().getReturn() }
|
||||
API::Node pool() {
|
||||
result = createPool().getReturn()
|
||||
or
|
||||
result = pool().getMember("on").getReturn()
|
||||
or
|
||||
result = API::Node::ofType(moduleName(), ["Pool", "PoolCluster"])
|
||||
}
|
||||
|
||||
/** Gets a data flow node that contains a freshly created MySQL connection instance. */
|
||||
API::Node connection() {
|
||||
result = createConnection().getReturn()
|
||||
or
|
||||
result = createConnection().getReturn().getPromised()
|
||||
or
|
||||
result = pool().getMember("getConnection").getParameter(0).getParameter(1)
|
||||
or
|
||||
result = pool().getMember("getConnection").getPromised()
|
||||
or
|
||||
exists(API::CallNode call |
|
||||
call = pool().getMember("on").getACall() and
|
||||
call.getArgument(0).getStringValue() = ["connection", "acquire", "release"] and
|
||||
result = call.getParameter(1).getParameter(0)
|
||||
)
|
||||
or
|
||||
result = API::Node::ofType(moduleName(), ["Connection", "PoolConnection"])
|
||||
}
|
||||
|
||||
/** A call to the MySql `query` method. */
|
||||
private class QueryCall extends DatabaseAccess, DataFlow::MethodCallNode {
|
||||
QueryCall() {
|
||||
exists(API::Node recv | recv = pool() or recv = connection() |
|
||||
this = recv.getMember("query").getACall()
|
||||
this = recv.getMember(["query", "execute"]).getACall()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -112,7 +134,20 @@ private module Postgres {
|
||||
// pool.connect(function(err, client) { ... })
|
||||
result = pool().getMember("connect").getParameter(0).getParameter(1)
|
||||
or
|
||||
// await pool.connect()
|
||||
result = pool().getMember("connect").getReturn().getPromised()
|
||||
or
|
||||
result = pgpConnection().getMember("client")
|
||||
or
|
||||
exists(API::CallNode call |
|
||||
call = pool().getMember("on").getACall() and
|
||||
call.getArgument(0).getStringValue() = ["connect", "acquire"] and
|
||||
result = call.getParameter(1).getParameter(0)
|
||||
)
|
||||
or
|
||||
result = client().getMember("on").getReturn()
|
||||
or
|
||||
result = API::Node::ofType("pg", ["Client", "PoolClient"])
|
||||
}
|
||||
|
||||
/** Gets a constructor that when invoked constructs a new connection pool. */
|
||||
@@ -129,6 +164,10 @@ private module Postgres {
|
||||
result = newPool().getInstance()
|
||||
or
|
||||
result = pgpDatabase().getMember("$pool")
|
||||
or
|
||||
result = pool().getMember("on").getReturn()
|
||||
or
|
||||
result = API::Node::ofType("pg", "Pool")
|
||||
}
|
||||
|
||||
/** A call to the Postgres `query` method. */
|
||||
@@ -140,7 +179,11 @@ private module Postgres {
|
||||
|
||||
/** An expression that is passed to the `query` method and hence interpreted as SQL. */
|
||||
class QueryString extends SQL::SqlString {
|
||||
QueryString() { this = any(QueryCall qc).getAQueryArgument().asExpr() }
|
||||
QueryString() {
|
||||
this = any(QueryCall qc).getAQueryArgument().asExpr()
|
||||
or
|
||||
this = API::moduleImport("pg-cursor").getParameter(0).getARhs().asExpr()
|
||||
}
|
||||
}
|
||||
|
||||
/** An expression that is passed as user name or password when creating a client or a pool. */
|
||||
@@ -299,24 +342,17 @@ private module Sqlite {
|
||||
}
|
||||
|
||||
/** Gets an expression that constructs a Sqlite database instance. */
|
||||
API::Node newDb() {
|
||||
API::Node database() {
|
||||
// new require('sqlite3').Database()
|
||||
result = sqlite().getMember("Database").getInstance()
|
||||
or
|
||||
result = API::Node::ofType("sqlite3", "Database")
|
||||
}
|
||||
|
||||
/** A call to a Sqlite query method. */
|
||||
private class QueryCall extends DatabaseAccess, DataFlow::MethodCallNode {
|
||||
QueryCall() {
|
||||
exists(string meth |
|
||||
meth = "all" or
|
||||
meth = "each" or
|
||||
meth = "exec" or
|
||||
meth = "get" or
|
||||
meth = "prepare" or
|
||||
meth = "run"
|
||||
|
|
||||
this = newDb().getMember(meth).getACall()
|
||||
)
|
||||
this = database().getMember(["all", "each", "exec", "get", "prepare", "run"]).getACall()
|
||||
}
|
||||
|
||||
override DataFlow::Node getAQueryArgument() { result = getArgument(0) }
|
||||
@@ -335,15 +371,32 @@ private module MsSql {
|
||||
/** Gets a reference to the `mssql` module. */
|
||||
API::Node mssql() { result = API::moduleImport("mssql") }
|
||||
|
||||
/** Gets an expression that creates a request object. */
|
||||
API::Node request() {
|
||||
// new require('mssql').Request()
|
||||
result = mssql().getMember("Request").getInstance()
|
||||
/** Gets a node referring to an instance of the given class. */
|
||||
API::Node mssqlClass(string name) {
|
||||
result = mssql().getMember(name).getInstance()
|
||||
or
|
||||
// request.input(...)
|
||||
result = request().getMember("input").getReturn()
|
||||
result = API::Node::ofType("mssql", name)
|
||||
}
|
||||
|
||||
/** Gets an API node referring to a Request object. */
|
||||
API::Node request() {
|
||||
result = mssqlClass("Request")
|
||||
or
|
||||
result = request().getMember(["input", "replaceInput", "output", "replaceOutput"]).getReturn()
|
||||
or
|
||||
result = [transaction(), pool()].getMember("request").getReturn()
|
||||
}
|
||||
|
||||
/** Gets an API node referring to a Transaction object. */
|
||||
API::Node transaction() {
|
||||
result = mssqlClass("Transaction")
|
||||
or
|
||||
result = pool().getMember("transaction").getReturn()
|
||||
}
|
||||
|
||||
/** Gets a API node referring to a ConnectionPool object. */
|
||||
API::Node pool() { result = mssqlClass("ConnectionPool") }
|
||||
|
||||
/** A tagged template evaluated as a query. */
|
||||
private class QueryTemplateExpr extends DatabaseAccess, DataFlow::ValueNode {
|
||||
override TaggedTemplateExpr astNode;
|
||||
@@ -359,7 +412,7 @@ private module MsSql {
|
||||
|
||||
/** A call to a MsSql query method. */
|
||||
private class QueryCall extends DatabaseAccess, DataFlow::MethodCallNode {
|
||||
QueryCall() { this = request().getMember(["query", "batch"]).getACall() }
|
||||
QueryCall() { this = [mssql(), request()].getMember(["query", "batch"]).getACall() }
|
||||
|
||||
override DataFlow::Node getAQueryArgument() { result = getArgument(0) }
|
||||
}
|
||||
@@ -410,22 +463,34 @@ private module MsSql {
|
||||
* Provides classes modelling the `sequelize` package.
|
||||
*/
|
||||
private module Sequelize {
|
||||
/** Gets an import of the `sequelize` module. */
|
||||
API::Node sequelize() { result = API::moduleImport("sequelize") }
|
||||
/** Gets an import of the `sequelize` module or one that re-exports it. */
|
||||
API::Node sequelize() { result = API::moduleImport(["sequelize", "sequelize-typescript"]) }
|
||||
|
||||
/** Gets an expression that creates an instance of the `Sequelize` class. */
|
||||
API::Node newSequelize() { result = sequelize().getInstance() }
|
||||
API::Node instance() {
|
||||
result = [sequelize(), sequelize().getMember("Sequelize")].getInstance()
|
||||
or
|
||||
result = API::Node::ofType(["sequelize", "sequelize-typescript"], ["Sequelize", "default"])
|
||||
}
|
||||
|
||||
/** A call to `Sequelize.query`. */
|
||||
private class QueryCall extends DatabaseAccess, DataFlow::MethodCallNode {
|
||||
QueryCall() { this = newSequelize().getMember("query").getACall() }
|
||||
QueryCall() { this = instance().getMember("query").getACall() }
|
||||
|
||||
override DataFlow::Node getAQueryArgument() { result = getArgument(0) }
|
||||
override DataFlow::Node getAQueryArgument() {
|
||||
result = getArgument(0)
|
||||
or
|
||||
result = getOptionArgument(0, "query")
|
||||
}
|
||||
}
|
||||
|
||||
/** An expression that is passed to `Sequelize.query` method and hence interpreted as SQL. */
|
||||
class QueryString extends SQL::SqlString {
|
||||
QueryString() { this = any(QueryCall qc).getAQueryArgument().asExpr() }
|
||||
QueryString() {
|
||||
this = any(QueryCall qc).getAQueryArgument().asExpr()
|
||||
or
|
||||
this = sequelize().getMember(["literal", "asIs"]).getParameter(0).getARhs().asExpr()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -478,6 +543,8 @@ private module Spanner {
|
||||
API::Node database() {
|
||||
result =
|
||||
spanner().getReturn().getMember("instance").getReturn().getMember("database").getReturn()
|
||||
or
|
||||
result = API::Node::ofType("@google-cloud/spanner", "Database")
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -485,61 +552,81 @@ private module Spanner {
|
||||
*/
|
||||
API::Node v1SpannerClient() {
|
||||
result = spanner().getMember("v1").getMember("SpannerClient").getInstance()
|
||||
or
|
||||
result = API::Node::ofType("@google-cloud/spanner", "v1.SpannerClient")
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a node that refers to a transaction object.
|
||||
*/
|
||||
API::Node transaction() {
|
||||
result = database().getMember("runTransaction").getParameter(0).getParameter(1)
|
||||
result =
|
||||
database()
|
||||
.getMember(["runTransaction", "runTransactionAsync"])
|
||||
.getParameter([0, 1])
|
||||
.getParameter(1)
|
||||
or
|
||||
result = API::Node::ofType("@google-cloud/spanner", "Transaction")
|
||||
}
|
||||
|
||||
/** Gets an API node referring to a `BatchTransaction` object. */
|
||||
API::Node batchTransaction() {
|
||||
result = database().getMember("batchTransaction").getReturn()
|
||||
or
|
||||
result = database().getMember("createBatchTransaction").getReturn().getPromised()
|
||||
or
|
||||
result = API::Node::ofType("@google-cloud/spanner", "BatchTransaction")
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to a Spanner method that executes a SQL query.
|
||||
*/
|
||||
abstract class SqlExecution extends DatabaseAccess, DataFlow::InvokeNode {
|
||||
/**
|
||||
* Gets the position of the query argument; default is zero, which can be overridden
|
||||
* by subclasses.
|
||||
*/
|
||||
int getQueryArgumentPosition() { result = 0 }
|
||||
abstract class SqlExecution extends DatabaseAccess, DataFlow::InvokeNode { }
|
||||
|
||||
/**
|
||||
* A SQL execution that takes the input directly in the first argument or in the `sql` option.
|
||||
*/
|
||||
class SqlExecutionDirect extends SqlExecution {
|
||||
SqlExecutionDirect() {
|
||||
this = database().getMember(["run", "runPartitionedUpdate", "runStream"]).getACall()
|
||||
or
|
||||
this = transaction().getMember(["run", "runStream", "runUpdate"]).getACall()
|
||||
or
|
||||
this = batchTransaction().getMember("createQueryPartitions").getACall()
|
||||
}
|
||||
|
||||
override DataFlow::Node getAQueryArgument() {
|
||||
result = getArgument(getQueryArgumentPosition()) or
|
||||
result = getOptionArgument(getQueryArgumentPosition(), "sql")
|
||||
result = getArgument(0)
|
||||
or
|
||||
result = getOptionArgument(0, "sql")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to `Database.run`, `Database.runPartitionedUpdate` or `Database.runStream`.
|
||||
* A SQL execution that takes an array of SQL strings or { sql: string } objects.
|
||||
*/
|
||||
class DatabaseRunCall extends SqlExecution {
|
||||
DatabaseRunCall() {
|
||||
this = database().getMember(["run", "runPartitionedUpdate", "runStream"]).getACall()
|
||||
class SqlExecutionBatch extends SqlExecution, API::CallNode {
|
||||
SqlExecutionBatch() { this = transaction().getMember("batchUpdate").getACall() }
|
||||
|
||||
override DataFlow::Node getAQueryArgument() {
|
||||
// just use the whole array as the query argument, as arrays becomes tainted if one of the elements
|
||||
// are tainted
|
||||
result = getArgument(0)
|
||||
or
|
||||
result = getParameter(0).getUnknownMember().getMember("sql").getARhs()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to `Transaction.run`, `Transaction.runStream` or `Transaction.runUpdate`.
|
||||
* A SQL execution that only takes the input in the `sql` option, and do not accept query strings
|
||||
* directly.
|
||||
*/
|
||||
class TransactionRunCall extends SqlExecution {
|
||||
TransactionRunCall() {
|
||||
this = transaction().getMember(["run", "runStream", "runUpdate"]).getACall()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to `v1.SpannerClient.executeSql` or `v1.SpannerClient.executeStreamingSql`.
|
||||
*/
|
||||
class ExecuteSqlCall extends SqlExecution {
|
||||
ExecuteSqlCall() {
|
||||
class SqlExecutionWithOption extends SqlExecution {
|
||||
SqlExecutionWithOption() {
|
||||
this = v1SpannerClient().getMember(["executeSql", "executeStreamingSql"]).getACall()
|
||||
}
|
||||
|
||||
override DataFlow::Node getAQueryArgument() {
|
||||
// `executeSql` and `executeStreamingSql` do not accept query strings directly
|
||||
result = getOptionArgument(0, "sql")
|
||||
}
|
||||
override DataFlow::Node getAQueryArgument() { result = getOptionArgument(0, "sql") }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
| mysql1.js:7:14:7:21 | 'secret' | password |
|
||||
| mysql1a.js:10:9:10:12 | 'me' | user name |
|
||||
| mysql1a.js:11:13:11:20 | 'secret' | password |
|
||||
| mysql2-promise.js:8:9:8:14 | 'root' | user name |
|
||||
| mysql2.js:7:21:7:25 | 'bob' | user name |
|
||||
| mysql2.js:8:21:8:28 | 'secret' | password |
|
||||
| mysql2tst.js:8:9:8:14 | 'root' | user name |
|
||||
|
||||
@@ -1,28 +1,47 @@
|
||||
| mssql1.js:7:40:7:72 | select ... e id = |
|
||||
| mssql1.js:7:75:7:79 | value |
|
||||
| mssql1.js:10:19:10:30 | 'SELECT 123' |
|
||||
| mssql2.js:5:15:5:34 | 'select 1 as number' |
|
||||
| mssql2.js:13:15:13:66 | 'create ... table' |
|
||||
| mssql2.js:22:24:22:43 | 'select 1 as number' |
|
||||
| mssql2.js:29:30:29:81 | 'create ... table' |
|
||||
| mssql-types.ts:7:31:7:42 | 'SELECT 123' |
|
||||
| mysql1.js:13:18:13:43 | 'SELECT ... lution' |
|
||||
| mysql1.js:18:18:22:1 | {\\n s ... vid']\\n} |
|
||||
| mysql1a.js:17:18:17:43 | 'SELECT ... lution' |
|
||||
| mysql2-promise.js:14:3:14:62 | 'SELECT ... ` > 45' |
|
||||
| mysql2-promise.js:23:3:23:56 | 'SELECT ... e` > ?' |
|
||||
| mysql2-promise.js:31:19:31:39 | 'SELECT ... users' |
|
||||
| mysql2-promise.js:32:21:32:41 | 'SELECT ... users' |
|
||||
| mysql2-types.ts:4:16:4:36 | 'SELECT ... users' |
|
||||
| mysql2.js:12:12:12:37 | 'SELECT ... lution' |
|
||||
| mysql2tst.js:14:3:14:62 | 'SELECT ... ` > 45' |
|
||||
| mysql2tst.js:23:3:23:56 | 'SELECT ... e` > ?' |
|
||||
| mysql2tst.js:31:19:31:39 | 'SELECT ... users' |
|
||||
| mysql2tst.js:32:21:32:41 | 'SELECT ... users' |
|
||||
| mysql3.js:14:20:14:52 | 'SELECT ... etable' |
|
||||
| mysql3.js:26:14:26:31 | 'SELECT something' |
|
||||
| mysql4.js:14:18:14:20 | sql |
|
||||
| mysqlImport.js:3:18:5:1 | {\\n s ... = ?',\\n} |
|
||||
| postgres1.js:37:21:37:24 | text |
|
||||
| postgres2.js:30:16:30:41 | 'SELECT ... number' |
|
||||
| postgres2.js:43:15:43:26 | 'SELECT 123' |
|
||||
| postgres2.js:46:15:46:47 | new Cur ... users') |
|
||||
| postgres2.js:46:26:46:46 | 'SELECT ... users' |
|
||||
| postgres3.js:15:16:15:40 | 'SELECT ... s name' |
|
||||
| postgres5.js:8:21:8:25 | query |
|
||||
| postgres-types.ts:4:18:4:29 | 'SELECT 123' |
|
||||
| postgresImport.js:4:18:4:43 | 'SELECT ... number' |
|
||||
| sequelize2.js:10:17:10:118 | 'SELECT ... Y name' |
|
||||
| sequelize2.js:12:17:15:1 | {\\n que ... [123]\\n} |
|
||||
| sequelize2.js:13:10:13:20 | 'SELECT $1' |
|
||||
| sequelize2.js:17:31:17:41 | '123 + 345' |
|
||||
| sequelize-types.ts:7:24:7:35 | 'SELECT 123' |
|
||||
| sequelize.js:8:17:8:118 | 'SELECT ... Y name' |
|
||||
| sequelizeImport.js:3:17:3:118 | 'SELECT ... Y name' |
|
||||
| spanner2.js:5:26:5:35 | "SQL code" |
|
||||
| spanner2.js:7:35:7:44 | "SQL code" |
|
||||
| spanner-types.ts:4:12:4:23 | 'SELECT 123' |
|
||||
| spanner.js:6:8:6:17 | "SQL code" |
|
||||
| spanner.js:7:8:7:26 | { sql: "SQL code" } |
|
||||
| spanner.js:7:15:7:24 | "SQL code" |
|
||||
@@ -41,7 +60,11 @@
|
||||
| spanner.js:18:16:18:25 | "SQL code" |
|
||||
| spanner.js:19:16:19:34 | { sql: "SQL code" } |
|
||||
| spanner.js:19:23:19:32 | "SQL code" |
|
||||
| spanner.js:23:12:23:23 | 'SELECT 123' |
|
||||
| spanner.js:26:12:26:38 | 'UPDATE ... = @baz' |
|
||||
| spanner.js:31:18:31:24 | queries |
|
||||
| spannerImport.js:4:8:4:17 | "SQL code" |
|
||||
| sqlite-types.ts:4:12:4:49 | "UPDATE ... id = ?" |
|
||||
| sqlite.js:7:8:7:45 | "UPDATE ... id = ?" |
|
||||
| sqliteArray.js:6:12:6:49 | "UPDATE ... id = ?" |
|
||||
| sqliteImport.js:2:8:2:44 | "UPDATE ... id = ?" |
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
import { ConnectionPool } from "mssql";
|
||||
|
||||
class Foo {
|
||||
constructor(private pool: ConnectionPool) {}
|
||||
|
||||
doSomething() {
|
||||
this.pool.request().query('SELECT 123');
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,8 @@ async () => {
|
||||
const pool = await sql.connect('mssql://username:password@localhost/database')
|
||||
const result = await sql.query`select * from mytable where id = ${value}`
|
||||
console.dir(result)
|
||||
|
||||
sql.query('SELECT 123');
|
||||
} catch (err) {
|
||||
// ... error checks
|
||||
}
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
// Adapted from the documentation of https://github.com/sidorares/node-mysql2,
|
||||
// which is licensed under the MIT license; see file node-mysql2-License.
|
||||
const mysql = require('mysql2/promise');
|
||||
|
||||
// create the connection to database
|
||||
const connection = await mysql.createConnection({
|
||||
host: 'localhost',
|
||||
user: 'root',
|
||||
database: 'test'
|
||||
});
|
||||
|
||||
// simple query
|
||||
connection.query(
|
||||
'SELECT * FROM `table` WHERE `name` = "Page" AND `age` > 45',
|
||||
function(err, results, fields) {
|
||||
console.log(results); // results contains rows returned by server
|
||||
console.log(fields); // fields contains extra meta data about results, if available
|
||||
}
|
||||
);
|
||||
|
||||
// with placeholder
|
||||
connection.query(
|
||||
'SELECT * FROM `table` WHERE `name` = ? AND `age` > ?',
|
||||
['Page', 45],
|
||||
function(err, results) {
|
||||
console.log(results);
|
||||
}
|
||||
);
|
||||
|
||||
const conn2 = await mysql.createConnectionPromise();
|
||||
await conn2.query('SELECT * FROM users');
|
||||
await conn2.execute('SELECT * FROM users');
|
||||
@@ -0,0 +1,5 @@
|
||||
import { Connection } from "mysql2";
|
||||
|
||||
export function doSomething(conn: Connection) {
|
||||
conn.query('SELECT * FROM users');
|
||||
}
|
||||
@@ -26,3 +26,7 @@ connection.query(
|
||||
console.log(results);
|
||||
}
|
||||
);
|
||||
|
||||
const conn2 = await mysql.createConnectionPromise();
|
||||
await conn2.query('SELECT * FROM users');
|
||||
await conn2.execute('SELECT * FROM users');
|
||||
|
||||
@@ -21,3 +21,7 @@ pool.getConnection(function(err, connection) {
|
||||
// Don't use the connection here, it has been returned to the pool.
|
||||
});
|
||||
});
|
||||
|
||||
pool.on('connection', conn => {
|
||||
conn.query('SELECT something');
|
||||
});
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
import { Client } from "pg";
|
||||
|
||||
function submitSomething(client: Client) {
|
||||
client.query('SELECT 123');
|
||||
}
|
||||
@@ -38,3 +38,9 @@ pool.connect(function(err, client, done) {
|
||||
//output: 1
|
||||
});
|
||||
});
|
||||
|
||||
let client2 = await pool.connect();
|
||||
client2.query('SELECT 123');
|
||||
|
||||
const Cursor = require('pg-cursor');
|
||||
client2.query(new Cursor('SELECT * from users'));
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
import Sequelize from 'sequelize';
|
||||
|
||||
export class Foo {
|
||||
constructor(private seq: Sequelize) {}
|
||||
|
||||
method() {
|
||||
this.seq.query('SELECT 123');
|
||||
}
|
||||
}
|
||||
@@ -9,3 +9,9 @@ const sequelize = new Sequelize('database', {
|
||||
});
|
||||
sequelize.query('SELECT * FROM Products WHERE (name LIKE \'%' + criteria + '%\') AND deletedAt IS NULL) ORDER BY name');
|
||||
|
||||
sequelize.query({
|
||||
query: 'SELECT $1',
|
||||
values: [123]
|
||||
});
|
||||
|
||||
let value = Sequelize.literal('123 + 345');
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
import { Database } from "@google-cloud/spanner";
|
||||
|
||||
export function doSomething(db: Database) {
|
||||
db.run('SELECT 123');
|
||||
}
|
||||
@@ -17,6 +17,18 @@ db.runTransaction((err, tx) => {
|
||||
tx.runStream({ sql: "SQL code" });
|
||||
tx.runUpdate("SQL code");
|
||||
tx.runUpdate({ sql: "SQL code" });
|
||||
|
||||
const queries = [
|
||||
{
|
||||
sql: 'SELECT 123',
|
||||
},
|
||||
{
|
||||
sql: 'UPDATE foo SET bar = @baz',
|
||||
params: {key: 'baz', value: '123'}
|
||||
}
|
||||
];
|
||||
|
||||
tx.batchUpdate(queries, () => {});
|
||||
});
|
||||
|
||||
exports.instance = instance;
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
import { Database } from "sqlite3";
|
||||
|
||||
export function doSomething(db: Database) {
|
||||
db.run("UPDATE tbl SET name = ? WHERE id = ?", "bar", 2);
|
||||
}
|
||||
Reference in New Issue
Block a user