Skip to content

Commit

Permalink
fix(format): apply prettier changes post bestpracts upgrade
Browse files Browse the repository at this point in the history
  • Loading branch information
uladkasach committed Feb 12, 2023
1 parent be703c1 commit df2354a
Show file tree
Hide file tree
Showing 158 changed files with 2,175 additions and 750 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,27 +5,41 @@ import { config } from './getDbConnection';
describe('connectToDatabase', () => {
describe('mysql', () => {
it('should return a database connection', async () => {
const connection = await connectToDatabase({ language: DatabaseLanguage.MYSQL, config: config.mysql });
const connection = await connectToDatabase({
language: DatabaseLanguage.MYSQL,
config: config.mysql,
});
expect(connection).toHaveProperty('query');
expect(connection).toHaveProperty('end');
await connection.end();
});
it('should be possible to query the database with the connection', async () => {
const connection = await connectToDatabase({ language: DatabaseLanguage.MYSQL, config: config.mysql });
const connection = await connectToDatabase({
language: DatabaseLanguage.MYSQL,
config: config.mysql,
});
await connection.query({ sql: 'SHOW TABLES' });
await connection.end();
});
});
describe('postgres', () => {
it('should return a database connection', async () => {
const connection = await connectToDatabase({ language: DatabaseLanguage.POSTGRES, config: config.postgres });
const connection = await connectToDatabase({
language: DatabaseLanguage.POSTGRES,
config: config.postgres,
});
expect(connection).toHaveProperty('query');
expect(connection).toHaveProperty('end');
await connection.end();
});
it('should be possible to query the database with the connection', async () => {
const connection = await connectToDatabase({ language: DatabaseLanguage.POSTGRES, config: config.postgres });
await connection.query({ sql: 'SELECT tablename FROM pg_catalog.pg_tables' });
const connection = await connectToDatabase({
language: DatabaseLanguage.POSTGRES,
config: config.postgres,
});
await connection.query({
sql: 'SELECT tablename FROM pg_catalog.pg_tables',
});
await connection.end();
});
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,13 @@ const connectionAdapters = {
});
await client.connect();
return {
query: async ({ sql, values }: { sql: string; values?: (string | number)[] }) => {
query: async ({
sql,
values,
}: {
sql: string;
values?: (string | number)[];
}) => {
const result = await client.query(sql, values);
return { rows: result.rows };
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,8 @@ export const config = {
},
};

export const getDbConnection = async ({ language }: { language: DatabaseLanguage }) =>
connectToDatabase({ language, config: config[language] });
export const getDbConnection = async ({
language,
}: {
language: DatabaseLanguage;
}) => connectToDatabase({ language, config: config[language] });
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
/**
* replace `,(` patterns w/ space in between, since our formatter downstream does not like that
*/
export const addSpacesBetweenCommaParenthesisOccurances = ({ ddl }: { ddl: string }) => {
export const addSpacesBetweenCommaParenthesisOccurances = ({
ddl,
}: {
ddl: string;
}) => {
return ddl.replace(/,\(/g, ', (');
};
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@
*
* for some reason, SHOW CREATE lowercases all tokens EXCEPT `as`, which it explicitly upper cases...)
*/
export const lowercaseAllAsTokensExceptFirstOne = ({ ddl }: { ddl: string }) => {
export const lowercaseAllAsTokensExceptFirstOne = ({
ddl,
}: {
ddl: string;
}) => {
return ddl
.replace(/ AS /g, ' as ') // /g to apply to each
.replace(/ as /, ' AS '); // no /g so only apply to first case
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
*/
export const lowercaseEverythingAfterFirstAs = ({ ddl }: { ddl: string }) => {
const casedAsDdlParts = ddl.split(' AS ');
const casedDdl = [casedAsDdlParts[0], casedAsDdlParts[1].toLowerCase()].join(' AS ');
const casedDdl = [casedAsDdlParts[0], casedAsDdlParts[1].toLowerCase()].join(
' AS ',
);
return casedDdl;
};
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@
*
* until we have an example where that breaks something, they're just too much to force users to have to maintain
*/
export const removeAllBackticks = ({ ddl }: { ddl: string }) => ddl.replace(/`/g, '');
export const removeAllBackticks = ({ ddl }: { ddl: string }) =>
ddl.replace(/`/g, '');
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
/**
* strip out the "double parenthesis" that SHOW CREATE likes to put on the "join on" statements
*/
export const removeDoubleParenthesisInJoinOnConditions = ({ sql }: { sql: string }) => {
export const removeDoubleParenthesisInJoinOnConditions = ({
sql,
}: {
sql: string;
}) => {
return sql.replace(/ on\(\((\w+\.\w+\s=\s\w+\.\w+)\)\)/g, ' on $1 '); // note: strictly only do this if matching the SHOW CREATE weird format of ` on((tableA.column = tableB.column))`
};
Original file line number Diff line number Diff line change
@@ -1,16 +1,26 @@
/**
* strip out all of the parenthesis (since SHOW CREATE adds them everywhere and thats too much to force users to maintain); unideal since it modifies the meaning, but this is only relevant for diffing
*/
export const removeParenthesisFromWhereConditions = ({ flattenedSql }: { flattenedSql: string }) => {
export const removeParenthesisFromWhereConditions = ({
flattenedSql,
}: {
flattenedSql: string;
}) => {
const whereCasing = !!flattenedSql.match(/\sWHERE\s/) ? 'WHERE' : 'where'; // determine if user is using upper case or lower case "where"
const sqlSplitOnWhere = flattenedSql.split(whereCasing);
if (sqlSplitOnWhere.length > 2) {
// should not occur because the sql should have been flattened already
throw new Error('found more than two parts of DDL after splitting on where; unexpected'); // fail fast
throw new Error(
'found more than two parts of DDL after splitting on where; unexpected',
); // fail fast
}
const sqlWithoutParens =
sqlSplitOnWhere.length === 2
? sqlSplitOnWhere[0] + '\n' + whereCasing + '\n' + sqlSplitOnWhere[1].replace(/[\(\)]/g, '') // tslint:disable-line prefer-template
? sqlSplitOnWhere[0] +
'\n' +
whereCasing +
'\n' +
sqlSplitOnWhere[1].replace(/[\(\)]/g, '') // tslint:disable-line prefer-template
: sqlSplitOnWhere[0]; // if no where clause, then nothing to replace
return sqlWithoutParens;
};
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ from
join contractor_version v on v.id = cvp.contractor_version_id
)
`.trim();
const normalizedSql = removeParenthesisSurroundingJoinsInFromClause({ flattenedSql: exampleSql });
const normalizedSql = removeParenthesisSurroundingJoinsInFromClause({
flattenedSql: exampleSql,
});
expect(normalizedSql).not.toContain('(');
expect(normalizedSql).not.toContain(')');
expect(normalizedSql).toMatchSnapshot();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,31 @@
*
* show create likes to wrap the whole "FROM" section w/ parens... its unreasonable to ask people to do that too.
*/
export const removeParenthesisSurroundingJoinsInFromClause = ({ flattenedSql }: { flattenedSql: string }) => {
export const removeParenthesisSurroundingJoinsInFromClause = ({
flattenedSql,
}: {
flattenedSql: string;
}) => {
// check that this sql has this situation going on, if not, do nothing
const ddlHasParenOpenRightAfterFromClause = !!flattenedSql.match(/\sfrom\s+\(/gi); // note, we're not worried about subqueries because we expect flattenedSql as input
const ddlHasParenOpenRightAfterFromClause =
!!flattenedSql.match(/\sfrom\s+\(/gi); // note, we're not worried about subqueries because we expect flattenedSql as input
if (!ddlHasParenOpenRightAfterFromClause) return flattenedSql; // do nothing if the situation does not exist

// split DDL on the from statement, since we know it exists
const flattenedSqlParts = flattenedSql.split(/\sfrom\s/gi);
if (flattenedSqlParts.length !== 2) throw new Error('not exactly two parts after splitting on from; unexpected'); // fail fast
if (flattenedSqlParts.length !== 2)
throw new Error(
'not exactly two parts after splitting on from; unexpected',
); // fail fast

// remove the parens that encapsulate each join
const fromClauseWithoutParens = flattenedSqlParts[1].replace(/\(/g, '').replace(/\)/g, ''); // note: we replace all parens, since subqueries are taken care of
const fromClauseWithoutParens = flattenedSqlParts[1]
.replace(/\(/g, '')
.replace(/\)/g, ''); // note: we replace all parens, since subqueries are taken care of

// join them back and the ddl w/o this mess
const flattenedSqlWithoutOpenCloseParenInFromClause = flattenedSqlParts[0] + '\nfrom\n' + fromClauseWithoutParens; // tslint:disable-line prefer-template
const flattenedSqlWithoutOpenCloseParenInFromClause =
flattenedSqlParts[0] + '\nfrom\n' + fromClauseWithoutParens; // tslint:disable-line prefer-template

// return without the parens
return flattenedSqlWithoutOpenCloseParenInFromClause;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@ SELECT s.id,
JOIN home_cvp cvp ON ((s.id = cvp.home_id)))
JOIN home_version v ON ((v.id = cvp.home_version_id)));
`;
const normalizedDdl = recursivelyHeavilyNormalizeViewDdl({ ddl: rawCreateDefDdl });
const normalizedDdl = recursivelyHeavilyNormalizeViewDdl({
ddl: rawCreateDefDdl,
});
expect(normalizedDdl).not.toContain('FROM ((home'); // there is no reason to wrap the "from" clauses in parens...
expect(normalizedDdl).toMatchSnapshot();
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,11 @@ import { recursivelyHeavilyNormalizeViewQuerySql } from './recursivelyHeavilyNor
*
* we also do it recursively, because we support subqueries
*/
export const recursivelyHeavilyNormalizeViewDdl = ({ ddl }: { ddl: string }) => {
export const recursivelyHeavilyNormalizeViewDdl = ({
ddl,
}: {
ddl: string;
}) => {
// 0. strip comments
const strippedDdl = strip(ddl);

Expand All @@ -24,13 +28,17 @@ export const recursivelyHeavilyNormalizeViewDdl = ({ ddl }: { ddl: string }) =>
normalizedDdl = lowercaseEverythingAfterFirstAs({ ddl: normalizedDdl });
normalizedDdl = removeAllBackticks({ ddl: normalizedDdl });
normalizedDdl = removeFinalSemicolon({ ddl: normalizedDdl });
normalizedDdl = addSpacesBetweenCommaParenthesisOccurances({ ddl: normalizedDdl });
normalizedDdl = addSpacesBetweenCommaParenthesisOccurances({
ddl: normalizedDdl,
});

// 2. recursively normalize the query body; do so recursively to support the subqueries that may be present
const ddlParts = normalizedDdl.split(' AS '); // NOTE: there is only one upper case AS, so it splits the sql from the view initial create statement
const viewCreateHeader = ddlParts[0];
const viewQuerySql = ddlParts[1];
const normalizedViewQuerySql = recursivelyHeavilyNormalizeViewQuerySql({ sql: viewQuerySql });
const normalizedViewQuerySql = recursivelyHeavilyNormalizeViewQuerySql({
sql: viewQuerySql,
});
normalizedDdl = viewCreateHeader + ' AS ' + normalizedViewQuerySql; // tslint:disable-line prefer-template

// 3. return the results
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,33 +17,54 @@ import { removeRedundantAliasDeclarations } from './normalizations/removeRedunda
*
* we also do it recursively, because we support subqueries
*/
export const recursivelyHeavilyNormalizeViewQuerySql = ({ sql }: { sql: string }) => {
export const recursivelyHeavilyNormalizeViewQuerySql = ({
sql,
}: {
sql: string;
}) => {
// 1. flatten the ddl by extracting subqueries as referenced tokens
const { flattenedSql, references } = flattenSqlByReferencingAndTokenizingSubqueries({ sql });
const { flattenedSql, references } =
flattenSqlByReferencingAndTokenizingSubqueries({ sql });

// 2. normalize the top level flat ddl; hover over the fn's for jsdoc based intellisense explanations for each normalization
let normalizedFlattenedSql = flattenedSql;
normalizedFlattenedSql = removeParenthesisFromWhereConditions({ flattenedSql: normalizedFlattenedSql });
normalizedFlattenedSql = removeDoubleParenthesisInJoinOnConditions({ sql: normalizedFlattenedSql });
normalizedFlattenedSql = removeParenthesisSurroundingJoinsInFromClause({ flattenedSql: normalizedFlattenedSql });
normalizedFlattenedSql = removeRedundantAliasDeclarations({ sql: normalizedFlattenedSql });
normalizedFlattenedSql = removeParenthesisFromWhereConditions({
flattenedSql: normalizedFlattenedSql,
});
normalizedFlattenedSql = removeDoubleParenthesisInJoinOnConditions({
sql: normalizedFlattenedSql,
});
normalizedFlattenedSql = removeParenthesisSurroundingJoinsInFromClause({
flattenedSql: normalizedFlattenedSql,
});
normalizedFlattenedSql = removeRedundantAliasDeclarations({
sql: normalizedFlattenedSql,
});

// 3. recursively apply this function to each referenced sql and replace the sql in the reference, ready to hydrate back
const normalizedReferences = references.map((reference) => {
const referencedSqlWithoutStartEndParen = reference.sql.slice(1, -1); // the flatten function puts subquery inside of parens
const normalizedReferencedSql = recursivelyHeavilyNormalizeViewQuerySql({ sql: referencedSqlWithoutStartEndParen });
const normalizedReferencedSql = recursivelyHeavilyNormalizeViewQuerySql({
sql: referencedSqlWithoutStartEndParen,
});
const normalizedReferencedSqlWithStartEndParens = `(${normalizedReferencedSql})`; // add those parens back
return new SqlSubqueryReference({ id: reference.id, sql: normalizedReferencedSqlWithStartEndParens });
return new SqlSubqueryReference({
id: reference.id,
sql: normalizedReferencedSqlWithStartEndParens,
});
});

// 4. hydrate the references back up
const hydratedNormalizedSql = hydrateSqlByReferencingAndReplacingSubqueryTokens({
flattenedSql: normalizedFlattenedSql,
references: normalizedReferences,
});
const hydratedNormalizedSql =
hydrateSqlByReferencingAndReplacingSubqueryTokens({
flattenedSql: normalizedFlattenedSql,
references: normalizedReferences,
});

// 5. prettify it!
const prettifiedHydratedNormalizedSql = sqlFormatter.format(hydratedNormalizedSql);
const prettifiedHydratedNormalizedSql = sqlFormatter.format(
hydratedNormalizedSql,
);

// 6. return the normalized sql
return prettifiedHydratedNormalizedSql;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,19 @@
import { ResourceType } from '../../../../../types';
import { stripIrrelevantContentFromResourceDDL } from './stripIrrelevantContentFromResourceDDL/stripIrrelevantContentFromResourceDDL';
import { normalizeDDLToSupportLossyShowCreateStatements } from './normalizeDDLToSupportLossyShowCreateStatements/normalizeDDLToSupportLossyShowCreateStatements';
import { stripIrrelevantContentFromResourceDDL } from './stripIrrelevantContentFromResourceDDL/stripIrrelevantContentFromResourceDDL';

export const normalizeCreateDdlMysql = async ({ type, ddl }: { type: ResourceType; ddl: string }) => {
export const normalizeCreateDdlMysql = async ({
type,
ddl,
}: {
type: ResourceType;
ddl: string;
}) => {
// TODO: consider refactoring these commands below to be more "per resource" instead of so generic
const stripedDdl = stripIrrelevantContentFromResourceDDL({ ddl, resourceType: type });
const stripedDdl = stripIrrelevantContentFromResourceDDL({
ddl,
resourceType: type,
});
const normalizedDdl = normalizeDDLToSupportLossyShowCreateStatements({
ddl: stripedDdl,
resourceType: type,
Expand Down
Loading

0 comments on commit df2354a

Please sign in to comment.