-
-
Notifications
You must be signed in to change notification settings - Fork 6.5k
Description
Issue Description & steps to reproduce
With postgres, if the same parameter is used multiple times in the query expression, TypeORM still produces multiple parameters $1, $2, etc. in the rendered SQL, which can causes problems with groupBy expressions.
More specifically:
-
I'm using postgres, creating a SELECT query with a GROUP BY
-
The expression being grouped includes a parameter. Example: I wish to group and count rows based on rounding the value in the column
temperature, and I am using a parameter:decimalPlacesto set the rounding precision. -
I include the expression both in the select and the group by, aiming to produce
SELECT round(temperature, :decimalPlaces), count(*) FROM temperature_data GROUP BY round(temperature, :decimalPlaces)
-
As far as I can tell, the best way to do this with typeORM is as follows:
const makeQueryBuilder = ( temperatureRepository: Repository<TemperatureData>, decimalPlaces: number ) => { const builder = temperatureRepository.createQueryBuilder(); builder .select("round(temperature, :decimalPlaces)", "rounded_temperature") .addSelect("count(*)", "count") .groupBy("round(temperature, :decimalPlaces)", "rounded_temperature"); builder.setParameters({ decimalPlaces }); return builder; }; const repository = ... const builder = makeQueryBuilder(repository, 2); const [query, parameters] = builder.getQueryAndParameters();
Inspecting the results in the debugger reveals (adding whitespace for readability):
// console.log(query) => SELECT round(temperature, $1) AS "rounded_temperature", count(*) AS "count" FROM "temperature_readings" GROUP BY round(temperature, $2) // console.log(parameters) => [2, 2]So far this seems reasonable!
-
However, running this query fails with the error
column "temperature_readings.temperature" must appear in the GROUP BY clause or be used in an aggregate functionI believe the parser is objecting because it treats the expressions
round(temperature, $1)andround(temperature, $2)as potentially different. And I can get the same error by attempting the following statement in the postgres console:PREPARE myTemperatureQuery (int, int) AS SELECT round(temperature, $1) AS "rounded_temperature", count(*) AS "count" FROM "temperature_readings" GROUP BY round(temperature, $2)
Expected Behavior
TypeORM should render the query with a single parameter that appears more than once. E.g. as
// console.log(query) =>
SELECT
round(temperature, $1) AS "rounded_temperature",
count(*) AS "count"
FROM "temperature_readings"
GROUP BY round(temperature, $1)
// console.log(parameters) =>
[2]
I believe this will address the problem because if I enter the following into the postgres parser, the statement succeeds:
PREPARE myTemperatureQuery (int, int) AS
SELECT
round(temperature, $1) AS "rounded_temperature",
count(*) AS "count"
FROM "temperature_readings"
GROUP BY round(temperature, $1) -- only change is that this is now $1
My Environment
| Dependency | Version |
|---|---|
| MacOS | 10.15.7 |
| Node.js version | v12.18.3 |
| Typescript version | v3.9.5 |
| TypeORM version | v0.2.29 |
Relevant Database Driver(s)
-
aurora-data-api -
aurora-data-api-pg -
better-sqlite3 -
cockroachdb -
cordova -
expo -
mongodb -
mysql -
nativescript -
oracle -
postgres -
react-native -
sap -
sqlite -
sqlite-abstract -
sqljs -
sqlserver
Are you willing to resolve this issue by submitting a Pull Request?
- Yes, I have the time, and I know how to start.
- Yes, I have the time, but I don't know how to start. I would need guidance.
- No, I don't have the time, although I believe I could do it if I had the time...
- No, I don't have the time and I wouldn't even know how to start.