diff --git a/CHANGELOG.md b/CHANGELOG.md index 0b25ff7e6..7b79e434f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed - Removed the deprecated static portfolio analysis rule: _Fees_ (Fee Ratio) +- Refactored queries in the data provider service to use Prisma’s safe query methods ### Fixed diff --git a/apps/api/src/services/data-provider/data-provider.service.ts b/apps/api/src/services/data-provider/data-provider.service.ts index 8ee8761c0..a6b12cce2 100644 --- a/apps/api/src/services/data-provider/data-provider.service.ts +++ b/apps/api/src/services/data-provider/data-provider.service.ts @@ -30,7 +30,7 @@ import { import type { Granularity, UserWithSettings } from '@ghostfolio/common/types'; import { Inject, Injectable, Logger, OnModuleInit } from '@nestjs/common'; -import { DataSource, MarketData, SymbolProfile } from '@prisma/client'; +import { DataSource, MarketData, Prisma, SymbolProfile } from '@prisma/client'; import { Big } from 'big.js'; import { eachDayOfInterval, format, isValid } from 'date-fns'; import { groupBy, isEmpty, isNumber, uniqWith } from 'lodash'; @@ -347,36 +347,35 @@ export class DataProviderService implements OnModuleInit { const granularityQuery = aGranularity === 'month' - ? `AND (date_part('day', date) = 1 OR date >= TIMESTAMP 'yesterday')` - : ''; + ? Prisma.sql`AND (date_part('day', date) = 1 OR date >= TIMESTAMP 'yesterday')` + : Prisma.empty; const rangeQuery = from && to - ? `AND date >= '${format(from, DATE_FORMAT)}' AND date <= '${format( + ? Prisma.sql`AND date >= ${format(from, DATE_FORMAT)}::timestamp AND date <= ${format( to, DATE_FORMAT - )}'` - : ''; + )}::timestamp` + : Prisma.empty; const dataSources = aItems.map(({ dataSource }) => { return dataSource; }); + const symbols = aItems.map(({ symbol }) => { return symbol; }); try { - const queryRaw = ` - SELECT * - FROM "MarketData" - WHERE "dataSource" IN ('${dataSources.join(`','`)}') - AND "symbol" IN ('${symbols.join( - `','` - )}') ${granularityQuery} ${rangeQuery} - ORDER BY date;`; - - const marketDataByGranularity: MarketData[] = - await this.prismaService.$queryRawUnsafe(queryRaw); + const marketDataByGranularity: MarketData[] = await this.prismaService + .$queryRaw` + SELECT * + FROM "MarketData" + WHERE "dataSource"::text IN (${Prisma.join(dataSources)}) + AND "symbol" IN (${Prisma.join(symbols)}) + ${granularityQuery} + ${rangeQuery} + ORDER BY date;`; response = marketDataByGranularity.reduce((r, marketData) => { const { date, marketPrice, symbol } = marketData;