typeorm 0.3.7-dev.ec05f1d → 0.3.8-dev.03317a3

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.
Files changed (185) hide show
  1. package/browser/data-source/DataSource.d.ts +2 -0
  2. package/browser/data-source/DataSource.js +2 -0
  3. package/browser/data-source/DataSource.js.map +1 -1
  4. package/browser/driver/Driver.d.ts +4 -0
  5. package/browser/driver/Driver.js.map +1 -1
  6. package/browser/driver/DriverUtils.d.ts +1 -0
  7. package/browser/driver/DriverUtils.js +5 -0
  8. package/browser/driver/DriverUtils.js.map +1 -1
  9. package/browser/driver/aurora-mysql/AuroraMysqlQueryRunner.js +4 -1
  10. package/browser/driver/aurora-mysql/AuroraMysqlQueryRunner.js.map +1 -1
  11. package/browser/driver/better-sqlite3/BetterSqlite3ConnectionOptions.d.ts +4 -0
  12. package/browser/driver/better-sqlite3/BetterSqlite3ConnectionOptions.js.map +1 -1
  13. package/browser/driver/better-sqlite3/BetterSqlite3Driver.d.ts +1 -1
  14. package/browser/driver/better-sqlite3/BetterSqlite3Driver.js +4 -3
  15. package/browser/driver/better-sqlite3/BetterSqlite3Driver.js.map +1 -1
  16. package/browser/driver/cockroachdb/CockroachQueryRunner.js +4 -1
  17. package/browser/driver/cockroachdb/CockroachQueryRunner.js.map +1 -1
  18. package/browser/driver/mysql/MysqlDriver.d.ts +4 -0
  19. package/browser/driver/mysql/MysqlDriver.js +1 -0
  20. package/browser/driver/mysql/MysqlDriver.js.map +1 -1
  21. package/browser/driver/mysql/MysqlQueryRunner.js +9 -1
  22. package/browser/driver/mysql/MysqlQueryRunner.js.map +1 -1
  23. package/browser/driver/oracle/OracleConnectionOptions.d.ts +1 -1
  24. package/browser/driver/oracle/OracleConnectionOptions.js.map +1 -1
  25. package/browser/driver/oracle/OracleQueryRunner.js +4 -1
  26. package/browser/driver/oracle/OracleQueryRunner.js.map +1 -1
  27. package/browser/driver/postgres/PostgresConnectionOptions.d.ts +1 -1
  28. package/browser/driver/postgres/PostgresConnectionOptions.js.map +1 -1
  29. package/browser/driver/postgres/PostgresDriver.d.ts +4 -0
  30. package/browser/driver/postgres/PostgresDriver.js +3 -2
  31. package/browser/driver/postgres/PostgresDriver.js.map +1 -1
  32. package/browser/driver/postgres/PostgresQueryRunner.d.ts +1 -1
  33. package/browser/driver/postgres/PostgresQueryRunner.js +22 -13
  34. package/browser/driver/postgres/PostgresQueryRunner.js.map +1 -1
  35. package/browser/driver/sap/SapQueryRunner.d.ts +7 -0
  36. package/browser/driver/sap/SapQueryRunner.js +28 -3
  37. package/browser/driver/sap/SapQueryRunner.js.map +1 -1
  38. package/browser/driver/spanner/SpannerQueryRunner.js +4 -1
  39. package/browser/driver/spanner/SpannerQueryRunner.js.map +1 -1
  40. package/browser/driver/sqlite-abstract/AbstractSqliteQueryRunner.d.ts +1 -1
  41. package/browser/driver/sqlite-abstract/AbstractSqliteQueryRunner.js +20 -13
  42. package/browser/driver/sqlite-abstract/AbstractSqliteQueryRunner.js.map +1 -1
  43. package/browser/driver/sqlserver/SqlServerConnectionOptions.d.ts +7 -2
  44. package/browser/driver/sqlserver/SqlServerConnectionOptions.js.map +1 -1
  45. package/browser/driver/sqlserver/SqlServerQueryRunner.js +4 -1
  46. package/browser/driver/sqlserver/SqlServerQueryRunner.js.map +1 -1
  47. package/browser/entity-manager/EntityManager.js +1 -0
  48. package/browser/entity-manager/EntityManager.js.map +1 -1
  49. package/browser/entity-manager/MongoEntityManager.d.ts +1 -1
  50. package/browser/entity-manager/MongoEntityManager.js +17 -10
  51. package/browser/entity-manager/MongoEntityManager.js.map +1 -1
  52. package/browser/find-options/FindOneOptions.d.ts +1 -0
  53. package/browser/find-options/FindOneOptions.js.map +1 -1
  54. package/browser/find-options/FindOptionsOrder.d.ts +1 -1
  55. package/browser/find-options/FindOptionsOrder.js.map +1 -1
  56. package/browser/find-options/FindOptionsRelations.d.ts +1 -1
  57. package/browser/find-options/FindOptionsRelations.js.map +1 -1
  58. package/browser/find-options/FindOptionsSelect.d.ts +1 -1
  59. package/browser/find-options/FindOptionsSelect.js.map +1 -1
  60. package/browser/find-options/FindOptionsWhere.d.ts +1 -1
  61. package/browser/find-options/FindOptionsWhere.js.map +1 -1
  62. package/browser/migration/MigrationExecutor.d.ts +8 -0
  63. package/browser/migration/MigrationExecutor.js +13 -5
  64. package/browser/migration/MigrationExecutor.js.map +1 -1
  65. package/browser/persistence/SubjectTopoligicalSorter.js +6 -1
  66. package/browser/persistence/SubjectTopoligicalSorter.js.map +1 -1
  67. package/browser/query-builder/QueryExpressionMap.d.ts +4 -0
  68. package/browser/query-builder/QueryExpressionMap.js +1 -0
  69. package/browser/query-builder/QueryExpressionMap.js.map +1 -1
  70. package/browser/query-builder/SelectQueryBuilder.d.ts +4 -0
  71. package/browser/query-builder/SelectQueryBuilder.js +57 -18
  72. package/browser/query-builder/SelectQueryBuilder.js.map +1 -1
  73. package/browser/query-builder/UpdateQueryBuilder.js +1 -0
  74. package/browser/query-builder/UpdateQueryBuilder.js.map +1 -1
  75. package/browser/query-builder/transformer/RawSqlResultsToEntityTransformer.js +2 -1
  76. package/browser/query-builder/transformer/RawSqlResultsToEntityTransformer.js.map +1 -1
  77. package/browser/query-runner/BaseQueryRunner.d.ts +5 -0
  78. package/browser/query-runner/BaseQueryRunner.js +7 -0
  79. package/browser/query-runner/BaseQueryRunner.js.map +1 -1
  80. package/browser/schema-builder/options/TableOptions.d.ts +4 -0
  81. package/browser/schema-builder/options/TableOptions.js.map +1 -1
  82. package/browser/schema-builder/table/Table.d.ts +4 -0
  83. package/browser/schema-builder/table/Table.js +8 -0
  84. package/browser/schema-builder/table/Table.js.map +1 -1
  85. package/browser/util/DateUtils.d.ts +1 -1
  86. package/browser/util/DateUtils.js +7 -8
  87. package/browser/util/DateUtils.js.map +1 -1
  88. package/commands/CommandUtils.js +7 -3
  89. package/commands/CommandUtils.js.map +1 -1
  90. package/commands/InitCommand.js +1 -1
  91. package/commands/InitCommand.js.map +1 -1
  92. package/commands/MigrationRevertCommand.d.ts +2 -0
  93. package/commands/MigrationRevertCommand.js +6 -0
  94. package/commands/MigrationRevertCommand.js.map +1 -1
  95. package/commands/MigrationRunCommand.d.ts +2 -0
  96. package/commands/MigrationRunCommand.js +8 -0
  97. package/commands/MigrationRunCommand.js.map +1 -1
  98. package/data-source/DataSource.d.ts +2 -0
  99. package/data-source/DataSource.js +2 -0
  100. package/data-source/DataSource.js.map +1 -1
  101. package/driver/Driver.d.ts +4 -0
  102. package/driver/Driver.js.map +1 -1
  103. package/driver/DriverUtils.d.ts +1 -0
  104. package/driver/DriverUtils.js +5 -0
  105. package/driver/DriverUtils.js.map +1 -1
  106. package/driver/aurora-mysql/AuroraMysqlQueryRunner.js +4 -1
  107. package/driver/aurora-mysql/AuroraMysqlQueryRunner.js.map +1 -1
  108. package/driver/better-sqlite3/BetterSqlite3ConnectionOptions.d.ts +4 -0
  109. package/driver/better-sqlite3/BetterSqlite3ConnectionOptions.js.map +1 -1
  110. package/driver/better-sqlite3/BetterSqlite3Driver.d.ts +1 -1
  111. package/driver/better-sqlite3/BetterSqlite3Driver.js +6 -5
  112. package/driver/better-sqlite3/BetterSqlite3Driver.js.map +1 -1
  113. package/driver/cockroachdb/CockroachQueryRunner.js +4 -1
  114. package/driver/cockroachdb/CockroachQueryRunner.js.map +1 -1
  115. package/driver/mysql/MysqlDriver.d.ts +4 -0
  116. package/driver/mysql/MysqlDriver.js +1 -0
  117. package/driver/mysql/MysqlDriver.js.map +1 -1
  118. package/driver/mysql/MysqlQueryRunner.js +9 -1
  119. package/driver/mysql/MysqlQueryRunner.js.map +1 -1
  120. package/driver/oracle/OracleConnectionOptions.d.ts +1 -1
  121. package/driver/oracle/OracleConnectionOptions.js.map +1 -1
  122. package/driver/oracle/OracleQueryRunner.js +4 -1
  123. package/driver/oracle/OracleQueryRunner.js.map +1 -1
  124. package/driver/postgres/PostgresConnectionOptions.d.ts +1 -1
  125. package/driver/postgres/PostgresConnectionOptions.js.map +1 -1
  126. package/driver/postgres/PostgresDriver.d.ts +4 -0
  127. package/driver/postgres/PostgresDriver.js +3 -2
  128. package/driver/postgres/PostgresDriver.js.map +1 -1
  129. package/driver/postgres/PostgresQueryRunner.d.ts +1 -1
  130. package/driver/postgres/PostgresQueryRunner.js +22 -13
  131. package/driver/postgres/PostgresQueryRunner.js.map +1 -1
  132. package/driver/sap/SapQueryRunner.d.ts +7 -0
  133. package/driver/sap/SapQueryRunner.js +28 -3
  134. package/driver/sap/SapQueryRunner.js.map +1 -1
  135. package/driver/spanner/SpannerQueryRunner.js +4 -1
  136. package/driver/spanner/SpannerQueryRunner.js.map +1 -1
  137. package/driver/sqlite-abstract/AbstractSqliteQueryRunner.d.ts +1 -1
  138. package/driver/sqlite-abstract/AbstractSqliteQueryRunner.js +20 -13
  139. package/driver/sqlite-abstract/AbstractSqliteQueryRunner.js.map +1 -1
  140. package/driver/sqlserver/SqlServerConnectionOptions.d.ts +7 -2
  141. package/driver/sqlserver/SqlServerConnectionOptions.js.map +1 -1
  142. package/driver/sqlserver/SqlServerQueryRunner.js +4 -1
  143. package/driver/sqlserver/SqlServerQueryRunner.js.map +1 -1
  144. package/entity-manager/EntityManager.js +1 -0
  145. package/entity-manager/EntityManager.js.map +1 -1
  146. package/entity-manager/MongoEntityManager.d.ts +1 -1
  147. package/entity-manager/MongoEntityManager.js +17 -10
  148. package/entity-manager/MongoEntityManager.js.map +1 -1
  149. package/find-options/FindOneOptions.d.ts +1 -0
  150. package/find-options/FindOneOptions.js.map +1 -1
  151. package/find-options/FindOptionsOrder.d.ts +1 -1
  152. package/find-options/FindOptionsOrder.js.map +1 -1
  153. package/find-options/FindOptionsRelations.d.ts +1 -1
  154. package/find-options/FindOptionsRelations.js.map +1 -1
  155. package/find-options/FindOptionsSelect.d.ts +1 -1
  156. package/find-options/FindOptionsSelect.js.map +1 -1
  157. package/find-options/FindOptionsWhere.d.ts +1 -1
  158. package/find-options/FindOptionsWhere.js.map +1 -1
  159. package/migration/MigrationExecutor.d.ts +8 -0
  160. package/migration/MigrationExecutor.js +13 -5
  161. package/migration/MigrationExecutor.js.map +1 -1
  162. package/package.json +1 -1
  163. package/persistence/SubjectTopoligicalSorter.js +6 -1
  164. package/persistence/SubjectTopoligicalSorter.js.map +1 -1
  165. package/query-builder/QueryExpressionMap.d.ts +4 -0
  166. package/query-builder/QueryExpressionMap.js +1 -0
  167. package/query-builder/QueryExpressionMap.js.map +1 -1
  168. package/query-builder/SelectQueryBuilder.d.ts +4 -0
  169. package/query-builder/SelectQueryBuilder.js +57 -18
  170. package/query-builder/SelectQueryBuilder.js.map +1 -1
  171. package/query-builder/UpdateQueryBuilder.js +1 -0
  172. package/query-builder/UpdateQueryBuilder.js.map +1 -1
  173. package/query-builder/transformer/RawSqlResultsToEntityTransformer.js +2 -1
  174. package/query-builder/transformer/RawSqlResultsToEntityTransformer.js.map +1 -1
  175. package/query-runner/BaseQueryRunner.d.ts +5 -0
  176. package/query-runner/BaseQueryRunner.js +7 -0
  177. package/query-runner/BaseQueryRunner.js.map +1 -1
  178. package/schema-builder/options/TableOptions.d.ts +4 -0
  179. package/schema-builder/options/TableOptions.js.map +1 -1
  180. package/schema-builder/table/Table.d.ts +4 -0
  181. package/schema-builder/table/Table.js +8 -0
  182. package/schema-builder/table/Table.js.map +1 -1
  183. package/util/DateUtils.d.ts +1 -1
  184. package/util/DateUtils.js +7 -8
  185. package/util/DateUtils.js.map +1 -1
@@ -568,6 +568,13 @@ class SelectQueryBuilder extends QueryBuilder_1.QueryBuilder {
568
568
  this.expressionMap.lockTables = lockTables;
569
569
  return this;
570
570
  }
571
+ /**
572
+ * Sets lock handling by adding NO WAIT or SKIP LOCKED.
573
+ */
574
+ setOnLocked(onLocked) {
575
+ this.expressionMap.onLocked = onLocked;
576
+ return this;
577
+ }
571
578
  /**
572
579
  * Disables the global condition of "non-deleted" for the entity with delete date columns.
573
580
  */
@@ -1002,7 +1009,8 @@ class SelectQueryBuilder extends QueryBuilder_1.QueryBuilder {
1002
1009
  select += `/*+ MAX_EXECUTION_TIME(${this.expressionMap.maxExecutionTime}) */ `;
1003
1010
  }
1004
1011
  }
1005
- if (driver.options.type === "postgres" && selectDistinctOn.length > 0) {
1012
+ if (DriverUtils_1.DriverUtils.isPostgresFamily(driver) &&
1013
+ selectDistinctOn.length > 0) {
1006
1014
  const selectDistinctOnMap = selectDistinctOn
1007
1015
  .map((on) => this.replacePropertyNames(on))
1008
1016
  .join(", ");
@@ -1332,7 +1340,7 @@ class SelectQueryBuilder extends QueryBuilder_1.QueryBuilder {
1332
1340
  const driver = this.connection.driver;
1333
1341
  let lockTablesClause = "";
1334
1342
  if (this.expressionMap.lockTables) {
1335
- if (!(driver.options.type === "postgres" ||
1343
+ if (!(DriverUtils_1.DriverUtils.isPostgresFamily(driver) ||
1336
1344
  driver.options.type === "cockroachdb")) {
1337
1345
  throw new error_1.TypeORMError("Lock tables not supported in selected driver");
1338
1346
  }
@@ -1341,14 +1349,29 @@ class SelectQueryBuilder extends QueryBuilder_1.QueryBuilder {
1341
1349
  }
1342
1350
  lockTablesClause = " OF " + this.expressionMap.lockTables.join(", ");
1343
1351
  }
1352
+ let onLockExpression = "";
1353
+ if (this.expressionMap.onLocked === "nowait") {
1354
+ onLockExpression = " NOWAIT";
1355
+ }
1356
+ else if (this.expressionMap.onLocked === "skip_locked") {
1357
+ onLockExpression = " SKIP LOCKED";
1358
+ }
1344
1359
  switch (this.expressionMap.lockMode) {
1345
1360
  case "pessimistic_read":
1346
- if (DriverUtils_1.DriverUtils.isMySQLFamily(driver) ||
1361
+ if (driver.options.type === "mysql" ||
1347
1362
  driver.options.type === "aurora-mysql") {
1363
+ if (DriverUtils_1.DriverUtils.isReleaseVersionOrGreater(driver, "8.0.0")) {
1364
+ return (" FOR SHARE" + lockTablesClause + onLockExpression);
1365
+ }
1366
+ else {
1367
+ return " LOCK IN SHARE MODE";
1368
+ }
1369
+ }
1370
+ else if (driver.options.type === "mariadb") {
1348
1371
  return " LOCK IN SHARE MODE";
1349
1372
  }
1350
- else if (driver.options.type === "postgres") {
1351
- return " FOR SHARE" + lockTablesClause;
1373
+ else if (DriverUtils_1.DriverUtils.isPostgresFamily(driver)) {
1374
+ return " FOR SHARE" + lockTablesClause + onLockExpression;
1352
1375
  }
1353
1376
  else if (driver.options.type === "oracle") {
1354
1377
  return " FOR UPDATE";
@@ -1363,11 +1386,11 @@ class SelectQueryBuilder extends QueryBuilder_1.QueryBuilder {
1363
1386
  if (DriverUtils_1.DriverUtils.isMySQLFamily(driver) ||
1364
1387
  driver.options.type === "aurora-mysql" ||
1365
1388
  driver.options.type === "oracle") {
1366
- return " FOR UPDATE";
1389
+ return " FOR UPDATE" + onLockExpression;
1367
1390
  }
1368
- else if (driver.options.type === "postgres" ||
1391
+ else if (DriverUtils_1.DriverUtils.isPostgresFamily(driver) ||
1369
1392
  driver.options.type === "cockroachdb") {
1370
- return " FOR UPDATE" + lockTablesClause;
1393
+ return " FOR UPDATE" + lockTablesClause + onLockExpression;
1371
1394
  }
1372
1395
  else if (driver.options.type === "mssql") {
1373
1396
  return "";
@@ -1376,7 +1399,7 @@ class SelectQueryBuilder extends QueryBuilder_1.QueryBuilder {
1376
1399
  throw new LockNotSupportedOnGivenDriverError_1.LockNotSupportedOnGivenDriverError();
1377
1400
  }
1378
1401
  case "pessimistic_partial_write":
1379
- if (driver.options.type === "postgres") {
1402
+ if (DriverUtils_1.DriverUtils.isPostgresFamily(driver)) {
1380
1403
  return " FOR UPDATE" + lockTablesClause + " SKIP LOCKED";
1381
1404
  }
1382
1405
  else if (DriverUtils_1.DriverUtils.isMySQLFamily(driver)) {
@@ -1386,7 +1409,7 @@ class SelectQueryBuilder extends QueryBuilder_1.QueryBuilder {
1386
1409
  throw new LockNotSupportedOnGivenDriverError_1.LockNotSupportedOnGivenDriverError();
1387
1410
  }
1388
1411
  case "pessimistic_write_or_fail":
1389
- if (driver.options.type === "postgres" ||
1412
+ if (DriverUtils_1.DriverUtils.isPostgresFamily(driver) ||
1390
1413
  driver.options.type === "cockroachdb") {
1391
1414
  return " FOR UPDATE" + lockTablesClause + " NOWAIT";
1392
1415
  }
@@ -1397,16 +1420,18 @@ class SelectQueryBuilder extends QueryBuilder_1.QueryBuilder {
1397
1420
  throw new LockNotSupportedOnGivenDriverError_1.LockNotSupportedOnGivenDriverError();
1398
1421
  }
1399
1422
  case "for_no_key_update":
1400
- if (driver.options.type === "postgres" ||
1423
+ if (DriverUtils_1.DriverUtils.isPostgresFamily(driver) ||
1401
1424
  driver.options.type === "cockroachdb") {
1402
- return " FOR NO KEY UPDATE" + lockTablesClause;
1425
+ return (" FOR NO KEY UPDATE" +
1426
+ lockTablesClause +
1427
+ onLockExpression);
1403
1428
  }
1404
1429
  else {
1405
1430
  throw new LockNotSupportedOnGivenDriverError_1.LockNotSupportedOnGivenDriverError();
1406
1431
  }
1407
1432
  case "for_key_share":
1408
- if (driver.options.type === "postgres") {
1409
- return " FOR KEY SHARE" + lockTablesClause;
1433
+ if (DriverUtils_1.DriverUtils.isPostgresFamily(driver)) {
1434
+ return (" FOR KEY SHARE" + lockTablesClause + onLockExpression);
1410
1435
  }
1411
1436
  else {
1412
1437
  throw new LockNotSupportedOnGivenDriverError_1.LockNotSupportedOnGivenDriverError();
@@ -1469,7 +1494,7 @@ class SelectQueryBuilder extends QueryBuilder_1.QueryBuilder {
1469
1494
  const asText = useLegacy ? "AsText" : "ST_AsText";
1470
1495
  selectionPath = `${asText}(${selectionPath})`;
1471
1496
  }
1472
- if (this.connection.driver.options.type === "postgres")
1497
+ if (DriverUtils_1.DriverUtils.isPostgresFamily(this.connection.driver))
1473
1498
  if (column.precision) {
1474
1499
  // cast to JSON to trigger parsing in the driver
1475
1500
  selectionPath = `ST_AsGeoJSON(${selectionPath}, ${column.precision})::json`;
@@ -1526,7 +1551,7 @@ class SelectQueryBuilder extends QueryBuilder_1.QueryBuilder {
1526
1551
  }
1527
1552
  // For everything else, we'll need to do some hackery to get the correct count values.
1528
1553
  if (this.connection.driver.options.type === "cockroachdb" ||
1529
- this.connection.driver.options.type === "postgres") {
1554
+ DriverUtils_1.DriverUtils.isPostgresFamily(this.connection.driver)) {
1530
1555
  // Postgres and CockroachDB can pass multiple parameters to the `DISTINCT` function
1531
1556
  // https://www.postgresql.org/docs/9.5/sql-select.html#SQL-DISTINCT
1532
1557
  return ("COUNT(DISTINCT(" +
@@ -1754,6 +1779,9 @@ class SelectQueryBuilder extends QueryBuilder_1.QueryBuilder {
1754
1779
  })
1755
1780
  : undefined;
1756
1781
  this.setLock(this.findOptions.lock.mode, undefined, tableNames);
1782
+ if (this.findOptions.lock.onLocked) {
1783
+ this.setOnLocked(this.findOptions.lock.onLocked);
1784
+ }
1757
1785
  }
1758
1786
  }
1759
1787
  if (this.findOptions.loadRelationIds === true) {
@@ -2230,9 +2258,9 @@ class SelectQueryBuilder extends QueryBuilder_1.QueryBuilder {
2230
2258
  ? order[key].nulls
2231
2259
  : undefined;
2232
2260
  nulls =
2233
- nulls === "first"
2261
+ (nulls === null || nulls === void 0 ? void 0 : nulls.toLowerCase()) === "first"
2234
2262
  ? "NULLS FIRST"
2235
- : nulls === "last"
2263
+ : (nulls === null || nulls === void 0 ? void 0 : nulls.toLowerCase()) === "last"
2236
2264
  ? "NULLS LAST"
2237
2265
  : undefined;
2238
2266
  this.addOrderBy(`${alias}.${propertyPath}`, direction, nulls);
@@ -2400,6 +2428,17 @@ class SelectQueryBuilder extends QueryBuilder_1.QueryBuilder {
2400
2428
  " " +
2401
2429
  parseInt(where[key].value));
2402
2430
  }
2431
+ else {
2432
+ if (relation.isManyToOne ||
2433
+ (relation.isOneToOne &&
2434
+ relation.isOneToOneOwner)) {
2435
+ const aliasPath = `${alias}.${propertyPath}`;
2436
+ andConditions.push(this.createWhereConditionExpression(this.getWherePredicateCondition(aliasPath, where[key])));
2437
+ }
2438
+ else {
2439
+ throw new Error(`This relation isn't supported by given find operator`);
2440
+ }
2441
+ }
2403
2442
  }
2404
2443
  else {
2405
2444
  // const joinAlias = alias + "_" + relation.propertyName;