Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tech - kysely - retirer executeKyselyRawSqlQuery util #2917

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 1 addition & 7 deletions back/src/config/pg/kysely/kyselyUtils.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import {
CompiledQuery,
Expression,
ExpressionWrapper,
Kysely,
Expand All @@ -8,7 +7,7 @@ import {
Simplify,
sql,
} from "kysely";
import { Pool, QueryResultRow } from "pg";
import { Pool } from "pg";
import { Falsy } from "ramda";
import { createLogger } from "../../../utils/logger";
import { notifyErrorObjectToTeam } from "../../../utils/notifyTeam";
Expand Down Expand Up @@ -36,11 +35,6 @@ type StripNullRecursive<T> = {
export const jsonStripNulls = <T>(
obj: RawBuilder<T>,
): RawBuilder<StripNullRecursive<T>> => sql`json_strip_nulls(${obj})`;
export const executeKyselyRawSqlQuery = <T extends QueryResultRow>(
transaction: KyselyDb,
sqlQuery: string,
values?: any[],
) => transaction.executeQuery<T>(CompiledQuery.raw(sqlQuery, values));

type KyselyOptions = {
skipErrorLog?: boolean;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
import { ConventionId, FtExternalId } from "shared";
import {
KyselyDb,
executeKyselyRawSqlQuery,
} from "../../../../../config/pg/kysely/kyselyUtils";
import { KyselyDb } from "../../../../../config/pg/kysely/kyselyUtils";
import { createLogger } from "../../../../../utils/logger";
import { parseZodSchemaAndLogErrorOnParsingFailure } from "../../../../../utils/schema.utils";
import {
Expand Down Expand Up @@ -30,19 +27,17 @@ export class PgConventionFranceTravailAdvisorRepository
conventionId: ConventionId,
peExternalId: FtExternalId,
): Promise<ConventionAndFtExternalIds> {
const pgResult = await executeKyselyRawSqlQuery(
this.transaction,
`
UPDATE partners_pe_connect
SET convention_id = $1
WHERE user_pe_external_id = $2
AND convention_id = $3`,
[conventionId, peExternalId, CONVENTION_ID_DEFAULT_UUID],
);
const result = await this.transaction
.updateTable("partners_pe_connect")
.set({ convention_id: conventionId })
.where("user_pe_external_id", "=", peExternalId)
.where("convention_id", "=", CONVENTION_ID_DEFAULT_UUID)
.returning("convention_id")
.execute();

if (Number(pgResult.numAffectedRows) !== 1)
if (result.length !== 1)
throw new Error(
`Association between Convention and userAdvisor failed. rowCount: ${pgResult.rows.length}, conventionId: ${conventionId}, peExternalId: ${peExternalId}`,
`Association between Convention and userAdvisor failed. rowCount: ${result.length}, conventionId: ${conventionId}, peExternalId: ${peExternalId}`,
);

return {
Expand All @@ -54,16 +49,19 @@ export class PgConventionFranceTravailAdvisorRepository
public async getByConventionId(
conventionId: ConventionId,
): Promise<ConventionFtUserAdvisorEntity | undefined> {
const pgResult =
await executeKyselyRawSqlQuery<PgConventionFranceTravailUserAdvisorDto>(
this.transaction,
`SELECT *
FROM partners_pe_connect
WHERE convention_id = $1`,
[conventionId],
);
const result = await this.transaction
.selectFrom("partners_pe_connect")
.where("convention_id", "=", conventionId)
.select([
"user_pe_external_id",
"convention_id",
"firstname",
"lastname",
"email",
"type",
])
.executeTakeFirst();

const result = pgResult.rows.at(0);
const conventionPeUserAdvisor =
result && toConventionFranceTravailUserAdvisorDTO(result);

Expand All @@ -84,22 +82,29 @@ export class PgConventionFranceTravailAdvisorRepository
): Promise<void> {
const { user, advisor } = peUserAndAdvisor;

await executeKyselyRawSqlQuery(
this.transaction,
upsertOnCompositePrimaryKeyConflict,
[
user.peExternalId,
CONVENTION_ID_DEFAULT_UUID,
advisor?.firstName ?? null,
advisor?.lastName ?? null,
advisor?.email ?? null,
advisor?.type ?? null,
],
);
await this.transaction
.insertInto("partners_pe_connect")
.values({
user_pe_external_id: user.peExternalId,
convention_id: CONVENTION_ID_DEFAULT_UUID,
firstname: advisor?.firstName,
lastname: advisor?.lastName,
email: advisor?.email,
type: advisor?.type,
})
.onConflict((oc) =>
oc.columns(["user_pe_external_id", "convention_id"]).doUpdateSet({
firstname: (eb) => eb.ref("excluded.firstname"),
lastname: (eb) => eb.ref("excluded.lastname"),
email: (eb) => eb.ref("excluded.email"),
type: (eb) => eb.ref("excluded.type"),
}),
)
.execute();
}
}

export type PgConventionFranceTravailUserAdvisorDto = {
type PgConventionFranceTravailUserAdvisorDto = {
user_pe_external_id: string;
convention_id: string;
firstname: string | null;
Expand Down Expand Up @@ -135,12 +140,3 @@ const toConventionFranceTravailUserAdvisorEntity = (
...dto,
_entityName: "ConventionFranceTravailAdvisor",
});

// On primary key conflict we update the data columns (firstname, lastname, email, type) with the new values.
// (the special EXCLUDED table is used to reference values originally proposed for insertion)
// ref: https://www.postgresql.org/docs/current/sql-insert.html
const upsertOnCompositePrimaryKeyConflict = `
INSERT INTO partners_pe_connect(user_pe_external_id, convention_id, firstname, lastname, email, type)
VALUES($1, $2, $3, $4, $5, $6)
ON CONFLICT (user_pe_external_id, convention_id) DO UPDATE
SET (firstname, lastname, email, type) = (EXCLUDED.firstname, EXCLUDED.lastname, EXCLUDED.email, EXCLUDED.type)`;
13 changes: 0 additions & 13 deletions back/src/domains/core/short-link/adapters/PgShortLinkHelpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,19 +15,6 @@ export const pgShortLinkRepositorySchema: z.Schema<PgShortLinkRepositoryDto> =
created_at: z.date(),
});

export const pgGetShortLinkByIdResultsSchema: z.Schema<
PgShortLinkRepositoryDto[]
> = z.array(pgShortLinkRepositorySchema);

export const pgShortLinkRepositoryStructure = {
tableName: "short_links",
columnNames: {
shortLinkId: "short_link_id",
url: "url",
createAt: "created_at",
},
};

export const insertShortLinkQuery = async (
db: KyselyDb,
shortLinkId: ShortLinkId,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,7 @@
import { AbsoluteUrl, ShortLinkId, castError } from "shared";
import {
KyselyDb,
executeKyselyRawSqlQuery,
} from "../../../../../config/pg/kysely/kyselyUtils";
import { AbsoluteUrl, ShortLinkId, absoluteUrlSchema, castError } from "shared";
import { KyselyDb } from "../../../../../config/pg/kysely/kyselyUtils";
import { createLogger } from "../../../../../utils/logger";
import { ShortLinkQuery } from "../../ports/ShortLinkQuery";
import {
PgShortLinkRepositoryDto,
pgGetShortLinkByIdResultsSchema,
pgShortLinkRepositoryStructure,
} from "../PgShortLinkHelpers";

const logger = createLogger(__filename);

Expand All @@ -18,19 +10,18 @@ export class PgShortLinkQuery implements ShortLinkQuery {

public getById(shortLinkId: ShortLinkId): Promise<AbsoluteUrl> {
logger.info({ message: `PgShortLinkQueryGetById ${shortLinkId}` });
return executeKyselyRawSqlQuery<PgShortLinkRepositoryDto>(
this.transaction,
`SELECT * FROM ${pgShortLinkRepositoryStructure.tableName} WHERE ${pgShortLinkRepositoryStructure.columnNames.shortLinkId} = $1`,
[shortLinkId],
)
.then(({ rows }) => {
const result = pgGetShortLinkByIdResultsSchema.parse(rows).at(0);
return this.transaction
.selectFrom("short_links")
.where("short_link_id", "=", shortLinkId)
.select(["short_link_id", "url"])
.executeTakeFirst()
.then((result) => {
if (!result)
throw new Error(shortLinkIdNotFoundErrorMessage(shortLinkId));
logger.info({
message: `PgShortLinkQueryGetByIdSuccess ${result.short_link_id}`,
});
return result.url as AbsoluteUrl;
return absoluteUrlSchema.parse(result.url);
})
.catch((error) => {
logger.error({
Expand All @@ -41,6 +32,7 @@ export class PgShortLinkQuery implements ShortLinkQuery {
});
}
}

export const shortLinkIdNotFoundErrorMessage = (
shortLinkId: ShortLinkId,
): string => `ShortLinkId '${shortLinkId}' not found.`;
Original file line number Diff line number Diff line change
Expand Up @@ -1578,6 +1578,10 @@ describe("PgEstablishmentAggregateRepository", () => {
locationId:
establishmentWithOfferA1101_AtPosition.establishment.locations[0]
.id,
createdAt:
establishmentWithOfferA1101_AtPosition.establishment.createdAt.toISOString(),
updatedAt:
establishmentWithOfferA1101_AtPosition.establishment.updatedAt.toISOString(),
},
);
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { Location, SearchResultDto } from "shared";
import { Location } from "shared";
import { EstablishmentAggregate } from "../entities/EstablishmentAggregate";
import { OfferEntity } from "../entities/OfferEntity";
import { OfferEntityBuilder } from "../helpers/EstablishmentBuilders";
import { RepositorySearchResultDto } from "../ports/EstablishmentAggregateRepository";

export const makeExpectedSearchResult = ({
establishment: establishmentAggregate,
Expand All @@ -13,7 +14,7 @@ export const makeExpectedSearchResult = ({
withOffers: OfferEntity[];
withLocationAndDistance: Location & { distance?: number };
nafLabel: string;
}): SearchResultDto => {
}): RepositorySearchResultDto => {
const firstOffer = withOffers.at(0);
if (!firstOffer)
throw new Error(
Expand Down Expand Up @@ -50,12 +51,12 @@ export const makeExpectedSearchResult = ({
!establishmentAggregate.establishment.isMaxDiscussionsForPeriodReached, // <<<<< Donnée renvoyée actuellement alors que pas spécifié dans le DTO?!
updatedAt: establishmentAggregate.establishment.updatedAt?.toISOString(),
createdAt: establishmentAggregate.establishment.createdAt.toISOString(),
} as SearchResultDto; // d'où le as
} as RepositorySearchResultDto; // d'où le as
};

export const sortSearchResultsByDistanceAndRomeAndSiretOnRandomResults = (
a: SearchResultDto,
b: SearchResultDto,
a: RepositorySearchResultDto,
b: RepositorySearchResultDto,
): number => {
if (a.distance_m && b.distance_m) {
if (a.distance_m > b.distance_m) return 1;
Expand Down
Loading
Loading