Structured Query Language, with a couple (for our purposes) main categories:
CREATE TABLE, ALTER TABLESELECT, INSERT, UPDATESeparates out the concerns of the behavior of our backend (e.g., how do we respond to a GET request? what do we do on a POST?) and the content (e.g., what information are we saving?)
Like a filter or a search:
SELECT) these attributesFROM this table (or tables)WHERE attributes match as given)Example:
SELECT author,title,body FROM posts WHERE author = 'Fitz' ORDER BY timestamp;
Creates a new place for data to live.
-- Author: Andrew Fitz Gibbon
-- Last updated: 11.22.19
-- Sets up a new posts table in a blog database.
CREATE TABLE `posts` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`timestamp` DATETIME DEFAULT CURRENT_TIMESTAMP,
`author` VARCHAR(200) DEFAULT 'Fitz',
`title` VARCHAR(200) DEFAULT NULL,
`body` text,
PRIMARY KEY (`id`)
);
const mysql = require('mysql2/promise');
const db = mysql.createPool({
// Variables for connections to the database.
host: process.env.DB_URL || 'localhost',
port: process.env.DB_PORT || '8889',
user: process.env.DB_USERNAME || 'root',
password: process.env.DB_PASSWORD || 'root',
database: process.env.DB_NAME || 'Blog'
});
JS
Note: this process.env stuff is required for HW5
Later...
let [rows, fields] = await db.query("SELECT * FROM posts");
demo

Alt: "Her daughter is named Help I'm trapped in a driver's license factory."
Suppose we had a POST endpoint to validate a user logging in:
let user = req.body.username;
let pw = req.body.password;
let qry = "SELECT * FROM users WHERE username='" + user +
"' AND password='" + pw + "'";
// e.g. SELECT * FROM users WHERE username='foo' AND password='bar';
let result = await db.query(qry);
if (result.length === 0) {
res.type("text");
res.status(400).send("user not found");
} else {
res.json(result); // send the user info data (a single row) as JSON
}
JS
CONDITION_A OR CONDITION_B evaluates to TRUE in SQL if either condition is true. 1=1 always evaluates to TRUE. What if we have many users in the users database? What user data could be leaked in such a response?
let user = req.body.username; // "' OR 1=1"
let pw = req.body.password; // "oops :)"
let qry = "SELECT * FROM users WHERE username='" + user +
"' AND password='" + pw + "'";
// e.g. SELECT * FROM users WHERE username='' OR 1=1 -- AND password='oops :)'
let result = await db.query(qry);
if (result.length === 0) {
res.type("text");
res.status(400).send("user not found");
} else {
res.json(result); // send the user info data (a single row) as JSON
}
JS
let user = req.body.username;
let pw = req.body.password;
let qry = "SELECT * FROM users WHERE username=? AND password=?";
// the qry will be escaped internally and no rows will be returned
let result = await db.query(qry, [user, pw]);
if (result.length === 0) {
res.type("text");
res.status(400).send("user not found");
}
JS
Using ? placeholders in the db.query string, we not only avoid evaluating SQL with user-provided parameters, but we also have much cleaner query strings to work with.
The order of each ? placeholder in the query string must match the index of a passed array to the db.query's optional second argument.
Now that we know that inserting user input raw is bad...
Let's finish out that TODO in the blogs...
INSERT INTO tableName (col1, col2) VALUES (val1, val2);