prisma-client-php 2.3.4 → 2.3.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -121,6 +121,8 @@ final class PPHPUtility
121
121
  */
122
122
  public static function checkFieldsExist(array $select, array $fields, string $modelName)
123
123
  {
124
+ $virtualFields = ['_count', '_max', '_min', '_avg', '_sum'];
125
+
124
126
  foreach ($select as $key => $value) {
125
127
  if (is_numeric($key) && is_string($value)) {
126
128
  if (self::fieldExists($key, $fields))
@@ -129,11 +131,13 @@ final class PPHPUtility
129
131
 
130
132
  if (isset($value) && empty($value) || !is_bool($value)) {
131
133
  if (is_string($key) && !self::fieldExists($key, $fields)) {
134
+ if (in_array($key, $virtualFields)) {
135
+ continue;
136
+ }
132
137
  throw new Exception("The field '$key' does not exist in the $modelName model.");
133
138
  }
134
139
 
135
140
  if (is_array($value) && !empty($value)) {
136
-
137
141
  $isRelatedModel = false;
138
142
 
139
143
  foreach ($fields as $field) {
@@ -162,6 +166,9 @@ final class PPHPUtility
162
166
  foreach (explode(',', $key) as $fieldName) {
163
167
  $fieldName = trim($fieldName);
164
168
  if (!self::fieldExists($fieldName, $fields)) {
169
+ if (in_array($fieldName, $virtualFields)) {
170
+ continue;
171
+ }
165
172
  throw new Exception("The field '$fieldName' does not exist in the $modelName model.");
166
173
  }
167
174
  }
@@ -219,13 +226,15 @@ final class PPHPUtility
219
226
  */
220
227
  public static function checkIncludes(array $include, array &$relatedEntityFields, array &$includes, array $fields, string $modelName)
221
228
  {
229
+ $virtualFields = ['_count', '_max', '_min', '_avg', '_sum'];
230
+
222
231
  if (isset($include) && is_array($include)) {
223
232
  foreach ($include as $key => $value) {
224
233
  if (is_array($value) && array_key_exists('join.type', $value)) {
225
234
  continue;
226
235
  }
227
236
 
228
- if ($key === '_count' && is_array($value) && array_key_exists('select', $value)) {
237
+ if (in_array($key, $virtualFields)) {
229
238
  $includes[$key] = $value;
230
239
  continue;
231
240
  }
@@ -1182,7 +1191,42 @@ final class PPHPUtility
1182
1191
  $records = [$records];
1183
1192
  }
1184
1193
 
1194
+ $virtualFields = ['_count', '_max', '_min', '_avg', '_sum'];
1195
+ foreach ($virtualFields as $virtualField) {
1196
+ if (!isset($includes[$virtualField])) {
1197
+ continue;
1198
+ }
1199
+
1200
+ $aggregateOptions = $includes[$virtualField];
1201
+ if (isset($aggregateOptions['select'])) {
1202
+ foreach ($records as $idx => $record) {
1203
+ $records[$idx][$virtualField] = [];
1204
+
1205
+ foreach ($aggregateOptions['select'] as $relationName => $enabled) {
1206
+ if (!$enabled || !isset($fields[$relationName], $fieldsRelatedWithKeys[$relationName])) {
1207
+ continue;
1208
+ }
1209
+
1210
+ $count = self::countRelatedRecords(
1211
+ $record,
1212
+ $relationName,
1213
+ $fields[$relationName],
1214
+ $fieldsRelatedWithKeys[$relationName],
1215
+ $pdo,
1216
+ $dbType
1217
+ );
1218
+
1219
+ $records[$idx][$virtualField][$relationName] = $count;
1220
+ }
1221
+ }
1222
+ }
1223
+ }
1224
+
1185
1225
  foreach ($includes as $relationName => $relationOpts) {
1226
+ if (in_array($relationName, $virtualFields)) {
1227
+ continue;
1228
+ }
1229
+
1186
1230
  if ($relationOpts === false) {
1187
1231
  continue;
1188
1232
  }
@@ -1267,6 +1311,84 @@ final class PPHPUtility
1267
1311
  return $isSingle ? $records[0] : $records;
1268
1312
  }
1269
1313
 
1314
+ private static function countRelatedRecords(
1315
+ array $record,
1316
+ string $relationName,
1317
+ array $relatedField,
1318
+ array $relatedKeys,
1319
+ PDO $pdo,
1320
+ string $dbType
1321
+ ): int {
1322
+ $relatedInstance = self::makeRelatedInstance($relatedField['type'], $pdo);
1323
+
1324
+ if (!empty($relatedKeys['relationFromFields']) && !empty($relatedKeys['relationToFields'])) {
1325
+ $conditions = [];
1326
+ foreach ($relatedKeys['relationFromFields'] as $i => $fromField) {
1327
+ $toField = $relatedKeys['relationToFields'][$i];
1328
+
1329
+ if (isset($relatedInstance->_fields[$fromField])) {
1330
+ $conditions[$fromField] = $record[$toField] ?? null;
1331
+ } else {
1332
+ $conditions[$toField] = $record[$fromField] ?? null;
1333
+ }
1334
+ }
1335
+
1336
+ if (empty(array_filter($conditions))) {
1337
+ return 0;
1338
+ }
1339
+
1340
+ $whereClause = [];
1341
+ $bindings = [];
1342
+ $counter = 0;
1343
+
1344
+ foreach ($conditions as $field => $value) {
1345
+ $placeholder = ':count_' . $counter++;
1346
+ $quotedField = self::quoteColumnName($dbType, $field);
1347
+ $whereClause[] = "$quotedField = $placeholder";
1348
+ $bindings[$placeholder] = $value;
1349
+ }
1350
+
1351
+ $tableName = self::quoteColumnName($dbType, $relatedInstance->_tableName);
1352
+ $sql = "SELECT COUNT(*) FROM $tableName WHERE " . implode(' AND ', $whereClause);
1353
+
1354
+ $stmt = $pdo->prepare($sql);
1355
+ foreach ($bindings as $key => $value) {
1356
+ $stmt->bindValue($key, $value);
1357
+ }
1358
+ $stmt->execute();
1359
+
1360
+ return (int) $stmt->fetchColumn();
1361
+ }
1362
+
1363
+ if (empty($relatedKeys['relationFromFields']) && empty($relatedKeys['relationToFields'])) {
1364
+ $implicitModelInfo = self::compareStringsAlphabetically($relatedField['type'], get_class($relatedInstance));
1365
+ $searchColumn = ($relatedField['type'] === $implicitModelInfo['A']) ? 'B' : 'A';
1366
+
1367
+ $idField = null;
1368
+ foreach ($record as $key => $value) {
1369
+ if ($key === 'id' || str_ends_with($key, 'Id')) {
1370
+ $idField = $key;
1371
+ break;
1372
+ }
1373
+ }
1374
+
1375
+ if (!$idField || !isset($record[$idField])) {
1376
+ return 0;
1377
+ }
1378
+
1379
+ $tableName = self::quoteColumnName($dbType, $implicitModelInfo['Name']);
1380
+ $searchColumnQuoted = self::quoteColumnName($dbType, $searchColumn);
1381
+
1382
+ $sql = "SELECT COUNT(*) FROM $tableName WHERE $searchColumnQuoted = :id";
1383
+ $stmt = $pdo->prepare($sql);
1384
+ $stmt->execute(['id' => $record[$idField]]);
1385
+
1386
+ return (int) $stmt->fetchColumn();
1387
+ }
1388
+
1389
+ return 0;
1390
+ }
1391
+
1270
1392
  private static function pickOppositeField(array $allFields, string $relationName, bool $isListOnCaller): array
1271
1393
  {
1272
1394
  $candidates = array_values(array_filter(
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "prisma-client-php",
3
3
  "description": "Prisma Client PHP is an auto-generated query builder that enables type-safe database access in PHP.",
4
- "version": "2.3.4",
4
+ "version": "2.3.6",
5
5
  "main": "index.js",
6
6
  "type": "module",
7
7
  "scripts": {