feat: newer grades and parameterized queries (#238)
previously, we were using template strings, which had issues for professors with an apostrophe in their name
This commit is contained in:
Binary file not shown.
@@ -3,6 +3,13 @@ import type { CourseSQLRow, Distribution } from '@shared/types/Distribution';
|
|||||||
|
|
||||||
import { initializeDB } from './initializeDB';
|
import { initializeDB } from './initializeDB';
|
||||||
|
|
||||||
|
type GradeDistributionParams = {
|
||||||
|
':department_code': string;
|
||||||
|
':course_number': string;
|
||||||
|
':instructor_last'?: string;
|
||||||
|
':semester'?: string;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* fetches the aggregate distribution of grades for a given course from the course db, and the semesters that we have data for
|
* fetches the aggregate distribution of grades for a given course from the course db, and the semesters that we have data for
|
||||||
* @param course the course to fetch the distribution for
|
* @param course the course to fetch the distribution for
|
||||||
@@ -11,14 +18,14 @@ import { initializeDB } from './initializeDB';
|
|||||||
*/
|
*/
|
||||||
export async function queryAggregateDistribution(course: Course): Promise<[Distribution, Semester[], boolean]> {
|
export async function queryAggregateDistribution(course: Course): Promise<[Distribution, Semester[], boolean]> {
|
||||||
const db = await initializeDB();
|
const db = await initializeDB();
|
||||||
const query = generateQuery(course, null, true);
|
const [query, params] = generateQuery(course, null, true);
|
||||||
|
|
||||||
let res = db.exec(query)?.[0];
|
let res = db.exec(query, params)?.[0];
|
||||||
let instructorIncluded = true;
|
let instructorIncluded = true;
|
||||||
if (!res?.columns?.length) {
|
if (!res?.columns?.length) {
|
||||||
instructorIncluded = false;
|
instructorIncluded = false;
|
||||||
const queryWithoutInstructor = generateQuery(course, null, false);
|
const [queryWithoutInstructor, paramsWithoutInstructor] = generateQuery(course, null, false);
|
||||||
res = db.exec(queryWithoutInstructor)?.[0];
|
res = db.exec(queryWithoutInstructor, paramsWithoutInstructor)?.[0];
|
||||||
|
|
||||||
if (!res?.columns?.length) {
|
if (!res?.columns?.length) {
|
||||||
throw new NoDataError(course);
|
throw new NoDataError(course);
|
||||||
@@ -87,20 +94,33 @@ export async function queryAggregateDistribution(course: Course): Promise<[Distr
|
|||||||
* @param semester the semester to fetch the distribution for OR null if we want the aggregate distribution
|
* @param semester the semester to fetch the distribution for OR null if we want the aggregate distribution
|
||||||
* @returns a SQL query string
|
* @returns a SQL query string
|
||||||
*/
|
*/
|
||||||
function generateQuery(course: Course, semester: Semester | null, includeInstructor: boolean): string {
|
function generateQuery(
|
||||||
const profName = course.instructors[0]?.lastName;
|
course: Course,
|
||||||
|
semester: Semester | null,
|
||||||
|
includeInstructor: boolean
|
||||||
|
): [string, GradeDistributionParams] {
|
||||||
const query = `
|
const query = `
|
||||||
select * from grade_distributions
|
select * from grade_distributions
|
||||||
where Department_Code = '${course.department}'
|
where Department_Code = :department_code
|
||||||
and Course_Number = '${course.number}'
|
and Course_Number = :course_number
|
||||||
${includeInstructor ? `and Instructor_Last = '${profName}' collate nocase` : ''}
|
${includeInstructor ? `and Instructor_Last = :instructor_last collate nocase` : ''}
|
||||||
${semester ? `and Semester = '${semester.season} ${semester.year}'` : ''}
|
${semester ? `and Semester = :semester` : ''}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
console.log(includeInstructor, { query });
|
const params: GradeDistributionParams = {
|
||||||
|
':department_code': course.department,
|
||||||
|
':course_number': course.number,
|
||||||
|
};
|
||||||
|
|
||||||
return query;
|
if (includeInstructor) {
|
||||||
|
params[':instructor_last'] = course.instructors[0]?.lastName;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (semester) {
|
||||||
|
params[':semester'] = `${semester.season} ${semester.year}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return [query, params];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -111,14 +131,14 @@ function generateQuery(course: Course, semester: Semester | null, includeInstruc
|
|||||||
*/
|
*/
|
||||||
export async function querySemesterDistribution(course: Course, semester: Semester): Promise<[Distribution, boolean]> {
|
export async function querySemesterDistribution(course: Course, semester: Semester): Promise<[Distribution, boolean]> {
|
||||||
const db = await initializeDB();
|
const db = await initializeDB();
|
||||||
const query = generateQuery(course, semester, true);
|
const [query, params] = generateQuery(course, semester, true);
|
||||||
|
|
||||||
let res = db.exec(query)?.[0];
|
let res = db.exec(query, params)?.[0];
|
||||||
let instructorIncluded = true;
|
let instructorIncluded = true;
|
||||||
if (!res?.columns?.length) {
|
if (!res?.columns?.length) {
|
||||||
instructorIncluded = false;
|
instructorIncluded = false;
|
||||||
const queryWithoutInstructor = generateQuery(course, semester, false);
|
const [queryWithoutInstructor, paramsWithoutInstructor] = generateQuery(course, semester, false);
|
||||||
res = db.exec(queryWithoutInstructor)?.[0];
|
res = db.exec(queryWithoutInstructor, paramsWithoutInstructor)?.[0];
|
||||||
if (!res?.columns?.length) {
|
if (!res?.columns?.length) {
|
||||||
throw new NoDataError(course);
|
throw new NoDataError(course);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user