typeorm 1.0.0-beta.2 → 1.0.0-beta.3

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 (330) hide show
  1. package/README.md +1 -3
  2. package/browser/connection/ConnectionOptionsReader.js +1 -1
  3. package/browser/connection/ConnectionOptionsReader.js.map +1 -1
  4. package/browser/data-source/DataSource.d.ts +1 -1
  5. package/browser/data-source/DataSource.js.map +1 -1
  6. package/browser/decorator/options/JoinColumnOptions.js.map +1 -1
  7. package/browser/driver/DriverUtils.d.ts +1 -0
  8. package/browser/driver/DriverUtils.js +27 -29
  9. package/browser/driver/DriverUtils.js.map +1 -1
  10. package/browser/driver/aurora-mysql/AuroraMysqlDriver.js +4 -4
  11. package/browser/driver/aurora-mysql/AuroraMysqlDriver.js.map +1 -1
  12. package/browser/driver/aurora-mysql/AuroraMysqlQueryRunner.d.ts +2 -1
  13. package/browser/driver/aurora-mysql/AuroraMysqlQueryRunner.js +9 -6
  14. package/browser/driver/aurora-mysql/AuroraMysqlQueryRunner.js.map +1 -1
  15. package/browser/driver/aurora-postgres/AuroraPostgresQueryRunner.d.ts +2 -1
  16. package/browser/driver/aurora-postgres/AuroraPostgresQueryRunner.js +3 -0
  17. package/browser/driver/aurora-postgres/AuroraPostgresQueryRunner.js.map +1 -1
  18. package/browser/driver/better-sqlite3/BetterSqlite3QueryRunner.d.ts +2 -1
  19. package/browser/driver/better-sqlite3/BetterSqlite3QueryRunner.js +3 -0
  20. package/browser/driver/better-sqlite3/BetterSqlite3QueryRunner.js.map +1 -1
  21. package/browser/driver/capacitor/CapacitorQueryRunner.d.ts +1 -1
  22. package/browser/driver/capacitor/CapacitorQueryRunner.js +5 -1
  23. package/browser/driver/capacitor/CapacitorQueryRunner.js.map +1 -1
  24. package/browser/driver/cockroachdb/CockroachDriver.js +3 -3
  25. package/browser/driver/cockroachdb/CockroachDriver.js.map +1 -1
  26. package/browser/driver/cockroachdb/CockroachQueryRunner.d.ts +2 -1
  27. package/browser/driver/cockroachdb/CockroachQueryRunner.js +55 -50
  28. package/browser/driver/cockroachdb/CockroachQueryRunner.js.map +1 -1
  29. package/browser/driver/cordova/CordovaQueryRunner.d.ts +1 -1
  30. package/browser/driver/cordova/CordovaQueryRunner.js +2 -0
  31. package/browser/driver/cordova/CordovaQueryRunner.js.map +1 -1
  32. package/browser/driver/expo/ExpoDataSourceOptions.d.ts +5 -3
  33. package/browser/driver/expo/ExpoDataSourceOptions.js.map +1 -1
  34. package/browser/driver/expo/ExpoDriver.d.ts +16 -1
  35. package/browser/driver/expo/ExpoDriver.js +68 -6
  36. package/browser/driver/expo/ExpoDriver.js.map +1 -1
  37. package/browser/driver/expo/ExpoQueryRunner.d.ts +2 -1
  38. package/browser/driver/expo/ExpoQueryRunner.js +3 -0
  39. package/browser/driver/expo/ExpoQueryRunner.js.map +1 -1
  40. package/browser/driver/mysql/MysqlDriver.js +4 -4
  41. package/browser/driver/mysql/MysqlDriver.js.map +1 -1
  42. package/browser/driver/mysql/MysqlQueryRunner.d.ts +2 -1
  43. package/browser/driver/mysql/MysqlQueryRunner.js +78 -82
  44. package/browser/driver/mysql/MysqlQueryRunner.js.map +1 -1
  45. package/browser/driver/nativescript/NativescriptQueryRunner.d.ts +1 -1
  46. package/browser/driver/nativescript/NativescriptQueryRunner.js +3 -0
  47. package/browser/driver/nativescript/NativescriptQueryRunner.js.map +1 -1
  48. package/browser/driver/oracle/OracleDriver.js +2 -2
  49. package/browser/driver/oracle/OracleDriver.js.map +1 -1
  50. package/browser/driver/postgres/PostgresDriver.js +8 -8
  51. package/browser/driver/postgres/PostgresDriver.js.map +1 -1
  52. package/browser/driver/postgres/PostgresQueryRunner.d.ts +2 -1
  53. package/browser/driver/postgres/PostgresQueryRunner.js +12 -8
  54. package/browser/driver/postgres/PostgresQueryRunner.js.map +1 -1
  55. package/browser/driver/react-native/ReactNativeDriver.js +1 -1
  56. package/browser/driver/react-native/ReactNativeDriver.js.map +1 -1
  57. package/browser/driver/react-native/ReactNativeQueryRunner.d.ts +1 -1
  58. package/browser/driver/react-native/ReactNativeQueryRunner.js +3 -0
  59. package/browser/driver/react-native/ReactNativeQueryRunner.js.map +1 -1
  60. package/browser/driver/sap/SapDriver.js +5 -3
  61. package/browser/driver/sap/SapDriver.js.map +1 -1
  62. package/browser/driver/sap/SapQueryRunner.d.ts +2 -1
  63. package/browser/driver/sap/SapQueryRunner.js +171 -16
  64. package/browser/driver/sap/SapQueryRunner.js.map +1 -1
  65. package/browser/driver/spanner/SpannerDriver.d.ts +1 -1
  66. package/browser/driver/spanner/SpannerDriver.js +6 -8
  67. package/browser/driver/spanner/SpannerDriver.js.map +1 -1
  68. package/browser/driver/spanner/SpannerQueryRunner.d.ts +16 -1
  69. package/browser/driver/spanner/SpannerQueryRunner.js +75 -7
  70. package/browser/driver/spanner/SpannerQueryRunner.js.map +1 -1
  71. package/browser/driver/sqlite-abstract/AbstractSqliteDriver.js +1 -1
  72. package/browser/driver/sqlite-abstract/AbstractSqliteDriver.js.map +1 -1
  73. package/browser/driver/sqlite-abstract/AbstractSqliteQueryRunner.js +10 -14
  74. package/browser/driver/sqlite-abstract/AbstractSqliteQueryRunner.js.map +1 -1
  75. package/browser/driver/sqljs/SqljsQueryRunner.d.ts +2 -1
  76. package/browser/driver/sqljs/SqljsQueryRunner.js +3 -0
  77. package/browser/driver/sqljs/SqljsQueryRunner.js.map +1 -1
  78. package/browser/driver/sqlserver/SqlServerDriver.js +1 -1
  79. package/browser/driver/sqlserver/SqlServerDriver.js.map +1 -1
  80. package/browser/driver/sqlserver/SqlServerQueryRunner.d.ts +2 -1
  81. package/browser/driver/sqlserver/SqlServerQueryRunner.js +65 -60
  82. package/browser/driver/sqlserver/SqlServerQueryRunner.js.map +1 -1
  83. package/browser/entity-manager/EntityManager.d.ts +1 -1
  84. package/browser/entity-manager/EntityManager.js.map +1 -1
  85. package/browser/error/NamedPlaceholdersNotSupportedError.d.ts +7 -0
  86. package/browser/error/NamedPlaceholdersNotSupportedError.js +14 -0
  87. package/browser/error/NamedPlaceholdersNotSupportedError.js.map +1 -0
  88. package/browser/error/QueryFailedError.d.ts +3 -2
  89. package/browser/error/QueryFailedError.js.map +1 -1
  90. package/browser/error/index.d.ts +1 -0
  91. package/browser/error/index.js +1 -0
  92. package/browser/error/index.js.map +1 -1
  93. package/browser/index.d.ts +0 -1
  94. package/browser/index.js +1 -3
  95. package/browser/index.js.map +1 -1
  96. package/browser/logger/AbstractLogger.d.ts +5 -4
  97. package/browser/logger/AbstractLogger.js +3 -1
  98. package/browser/logger/AbstractLogger.js.map +1 -1
  99. package/browser/logger/DebugLogger.js +3 -1
  100. package/browser/logger/DebugLogger.js.map +1 -1
  101. package/browser/logger/Logger.d.ts +5 -4
  102. package/browser/logger/Logger.js.map +1 -1
  103. package/browser/naming-strategy/DefaultNamingStrategy.d.ts +7 -26
  104. package/browser/naming-strategy/DefaultNamingStrategy.js +19 -37
  105. package/browser/naming-strategy/DefaultNamingStrategy.js.map +1 -1
  106. package/browser/naming-strategy/NamingStrategyInterface.d.ts +9 -13
  107. package/browser/naming-strategy/NamingStrategyInterface.js.map +1 -1
  108. package/browser/persistence/EntityPersistExecutor.js +20 -8
  109. package/browser/persistence/EntityPersistExecutor.js.map +1 -1
  110. package/browser/persistence/SubjectDatabaseEntityLoader.js +15 -5
  111. package/browser/persistence/SubjectDatabaseEntityLoader.js.map +1 -1
  112. package/browser/persistence/SubjectExecutor.js +50 -30
  113. package/browser/persistence/SubjectExecutor.js.map +1 -1
  114. package/browser/platform/PlatformTools.js +1 -1
  115. package/browser/platform/PlatformTools.js.map +1 -1
  116. package/browser/query-builder/JoinAttribute.js +3 -3
  117. package/browser/query-builder/JoinAttribute.js.map +1 -1
  118. package/browser/query-builder/QueryBuilder.d.ts +0 -1
  119. package/browser/query-builder/QueryBuilder.js +3 -13
  120. package/browser/query-builder/QueryBuilder.js.map +1 -1
  121. package/browser/query-builder/SelectQueryBuilder.js +33 -27
  122. package/browser/query-builder/SelectQueryBuilder.js.map +1 -1
  123. package/browser/query-builder/SoftDeleteQueryBuilder.js +0 -2
  124. package/browser/query-builder/SoftDeleteQueryBuilder.js.map +1 -1
  125. package/browser/query-builder/UpdateQueryBuilder.js +0 -2
  126. package/browser/query-builder/UpdateQueryBuilder.js.map +1 -1
  127. package/browser/query-builder/relation-id/RelationIdAttribute.js +4 -4
  128. package/browser/query-builder/relation-id/RelationIdAttribute.js.map +1 -1
  129. package/browser/query-builder/relation-id/RelationIdLoader.js +16 -9
  130. package/browser/query-builder/relation-id/RelationIdLoader.js.map +1 -1
  131. package/browser/query-runner/BaseQueryRunner.d.ts +44 -21
  132. package/browser/query-runner/BaseQueryRunner.js +61 -21
  133. package/browser/query-runner/BaseQueryRunner.js.map +1 -1
  134. package/browser/query-runner/QueryRunner.d.ts +11 -2
  135. package/browser/query-runner/QueryRunner.js.map +1 -1
  136. package/browser/repository/BaseEntity.d.ts +2 -1
  137. package/browser/repository/BaseEntity.js.map +1 -1
  138. package/browser/repository/Repository.d.ts +1 -1
  139. package/browser/repository/Repository.js.map +1 -1
  140. package/browser/subscriber/Broadcaster.d.ts +4 -4
  141. package/browser/subscriber/Broadcaster.js.map +1 -1
  142. package/browser/subscriber/event/QueryEvent.d.ts +2 -1
  143. package/browser/subscriber/event/QueryEvent.js.map +1 -1
  144. package/browser/util/DirectoryExportedClassesLoader.js +1 -1
  145. package/browser/util/DirectoryExportedClassesLoader.js.map +1 -1
  146. package/browser/util/ImportUtils.js +1 -1
  147. package/browser/util/ImportUtils.js.map +1 -1
  148. package/browser/util/OrmUtils.js +1 -1
  149. package/browser/util/OrmUtils.js.map +1 -1
  150. package/browser/util/PathUtils.js +1 -1
  151. package/browser/util/PathUtils.js.map +1 -1
  152. package/browser/util/RandomGenerator.d.ts +1 -10
  153. package/browser/util/RandomGenerator.js +1 -10
  154. package/browser/util/RandomGenerator.js.map +1 -1
  155. package/browser/util/StringUtils.js +9 -9
  156. package/browser/util/StringUtils.js.map +1 -1
  157. package/browser/util/escapeRegExp.js +1 -1
  158. package/browser/util/escapeRegExp.js.map +1 -1
  159. package/commands/InitCommand.d.ts +0 -3
  160. package/commands/InitCommand.js +4 -31
  161. package/commands/InitCommand.js.map +1 -1
  162. package/commands/MigrationGenerateCommand.js +3 -1
  163. package/commands/MigrationGenerateCommand.js.map +1 -1
  164. package/commands/VersionCommand.js +2 -2
  165. package/commands/VersionCommand.js.map +1 -1
  166. package/connection/ConnectionOptionsReader.js +1 -1
  167. package/connection/ConnectionOptionsReader.js.map +1 -1
  168. package/data-source/DataSource.d.ts +1 -1
  169. package/data-source/DataSource.js.map +1 -1
  170. package/decorator/options/JoinColumnOptions.js.map +1 -1
  171. package/driver/DriverUtils.d.ts +1 -0
  172. package/driver/DriverUtils.js +27 -29
  173. package/driver/DriverUtils.js.map +1 -1
  174. package/driver/aurora-mysql/AuroraMysqlDriver.js +4 -4
  175. package/driver/aurora-mysql/AuroraMysqlDriver.js.map +1 -1
  176. package/driver/aurora-mysql/AuroraMysqlQueryRunner.d.ts +2 -1
  177. package/driver/aurora-mysql/AuroraMysqlQueryRunner.js +9 -6
  178. package/driver/aurora-mysql/AuroraMysqlQueryRunner.js.map +1 -1
  179. package/driver/aurora-postgres/AuroraPostgresQueryRunner.d.ts +2 -1
  180. package/driver/aurora-postgres/AuroraPostgresQueryRunner.js +3 -0
  181. package/driver/aurora-postgres/AuroraPostgresQueryRunner.js.map +1 -1
  182. package/driver/better-sqlite3/BetterSqlite3QueryRunner.d.ts +2 -1
  183. package/driver/better-sqlite3/BetterSqlite3QueryRunner.js +3 -0
  184. package/driver/better-sqlite3/BetterSqlite3QueryRunner.js.map +1 -1
  185. package/driver/capacitor/CapacitorQueryRunner.d.ts +1 -1
  186. package/driver/capacitor/CapacitorQueryRunner.js +5 -1
  187. package/driver/capacitor/CapacitorQueryRunner.js.map +1 -1
  188. package/driver/cockroachdb/CockroachDriver.js +3 -3
  189. package/driver/cockroachdb/CockroachDriver.js.map +1 -1
  190. package/driver/cockroachdb/CockroachQueryRunner.d.ts +2 -1
  191. package/driver/cockroachdb/CockroachQueryRunner.js +55 -50
  192. package/driver/cockroachdb/CockroachQueryRunner.js.map +1 -1
  193. package/driver/cordova/CordovaQueryRunner.d.ts +1 -1
  194. package/driver/cordova/CordovaQueryRunner.js +2 -0
  195. package/driver/cordova/CordovaQueryRunner.js.map +1 -1
  196. package/driver/expo/ExpoDataSourceOptions.d.ts +5 -3
  197. package/driver/expo/ExpoDataSourceOptions.js.map +1 -1
  198. package/driver/expo/ExpoDriver.d.ts +16 -1
  199. package/driver/expo/ExpoDriver.js +68 -6
  200. package/driver/expo/ExpoDriver.js.map +1 -1
  201. package/driver/expo/ExpoQueryRunner.d.ts +2 -1
  202. package/driver/expo/ExpoQueryRunner.js +3 -0
  203. package/driver/expo/ExpoQueryRunner.js.map +1 -1
  204. package/driver/mysql/MysqlDriver.js +4 -4
  205. package/driver/mysql/MysqlDriver.js.map +1 -1
  206. package/driver/mysql/MysqlQueryRunner.d.ts +2 -1
  207. package/driver/mysql/MysqlQueryRunner.js +78 -82
  208. package/driver/mysql/MysqlQueryRunner.js.map +1 -1
  209. package/driver/nativescript/NativescriptQueryRunner.d.ts +1 -1
  210. package/driver/nativescript/NativescriptQueryRunner.js +3 -0
  211. package/driver/nativescript/NativescriptQueryRunner.js.map +1 -1
  212. package/driver/oracle/OracleDriver.js +2 -2
  213. package/driver/oracle/OracleDriver.js.map +1 -1
  214. package/driver/postgres/PostgresDriver.js +8 -8
  215. package/driver/postgres/PostgresDriver.js.map +1 -1
  216. package/driver/postgres/PostgresQueryRunner.d.ts +2 -1
  217. package/driver/postgres/PostgresQueryRunner.js +12 -8
  218. package/driver/postgres/PostgresQueryRunner.js.map +1 -1
  219. package/driver/react-native/ReactNativeDriver.js +1 -1
  220. package/driver/react-native/ReactNativeDriver.js.map +1 -1
  221. package/driver/react-native/ReactNativeQueryRunner.d.ts +1 -1
  222. package/driver/react-native/ReactNativeQueryRunner.js +3 -0
  223. package/driver/react-native/ReactNativeQueryRunner.js.map +1 -1
  224. package/driver/sap/SapDriver.js +5 -3
  225. package/driver/sap/SapDriver.js.map +1 -1
  226. package/driver/sap/SapQueryRunner.d.ts +2 -1
  227. package/driver/sap/SapQueryRunner.js +171 -16
  228. package/driver/sap/SapQueryRunner.js.map +1 -1
  229. package/driver/spanner/SpannerDriver.d.ts +1 -1
  230. package/driver/spanner/SpannerDriver.js +6 -8
  231. package/driver/spanner/SpannerDriver.js.map +1 -1
  232. package/driver/spanner/SpannerQueryRunner.d.ts +16 -1
  233. package/driver/spanner/SpannerQueryRunner.js +75 -7
  234. package/driver/spanner/SpannerQueryRunner.js.map +1 -1
  235. package/driver/sqlite-abstract/AbstractSqliteDriver.js +1 -1
  236. package/driver/sqlite-abstract/AbstractSqliteDriver.js.map +1 -1
  237. package/driver/sqlite-abstract/AbstractSqliteQueryRunner.js +10 -14
  238. package/driver/sqlite-abstract/AbstractSqliteQueryRunner.js.map +1 -1
  239. package/driver/sqljs/SqljsQueryRunner.d.ts +2 -1
  240. package/driver/sqljs/SqljsQueryRunner.js +3 -0
  241. package/driver/sqljs/SqljsQueryRunner.js.map +1 -1
  242. package/driver/sqlserver/SqlServerDriver.js +1 -1
  243. package/driver/sqlserver/SqlServerDriver.js.map +1 -1
  244. package/driver/sqlserver/SqlServerQueryRunner.d.ts +2 -1
  245. package/driver/sqlserver/SqlServerQueryRunner.js +65 -60
  246. package/driver/sqlserver/SqlServerQueryRunner.js.map +1 -1
  247. package/entity-manager/EntityManager.d.ts +1 -1
  248. package/entity-manager/EntityManager.js.map +1 -1
  249. package/error/NamedPlaceholdersNotSupportedError.d.ts +7 -0
  250. package/error/NamedPlaceholdersNotSupportedError.js +14 -0
  251. package/error/NamedPlaceholdersNotSupportedError.js.map +1 -0
  252. package/error/QueryFailedError.d.ts +3 -2
  253. package/error/QueryFailedError.js.map +1 -1
  254. package/error/index.d.ts +1 -0
  255. package/error/index.js +1 -0
  256. package/error/index.js.map +1 -1
  257. package/index.d.ts +0 -1
  258. package/index.js +1 -3
  259. package/index.js.map +1 -1
  260. package/index.mjs +2 -2
  261. package/logger/AbstractLogger.d.ts +5 -4
  262. package/logger/AbstractLogger.js +3 -1
  263. package/logger/AbstractLogger.js.map +1 -1
  264. package/logger/DebugLogger.js +3 -1
  265. package/logger/DebugLogger.js.map +1 -1
  266. package/logger/Logger.d.ts +5 -4
  267. package/logger/Logger.js.map +1 -1
  268. package/naming-strategy/DefaultNamingStrategy.d.ts +7 -26
  269. package/naming-strategy/DefaultNamingStrategy.js +19 -37
  270. package/naming-strategy/DefaultNamingStrategy.js.map +1 -1
  271. package/naming-strategy/NamingStrategyInterface.d.ts +9 -13
  272. package/naming-strategy/NamingStrategyInterface.js.map +1 -1
  273. package/package.json +6 -6
  274. package/persistence/EntityPersistExecutor.js +20 -8
  275. package/persistence/EntityPersistExecutor.js.map +1 -1
  276. package/persistence/SubjectDatabaseEntityLoader.js +15 -5
  277. package/persistence/SubjectDatabaseEntityLoader.js.map +1 -1
  278. package/persistence/SubjectExecutor.js +50 -30
  279. package/persistence/SubjectExecutor.js.map +1 -1
  280. package/platform/PlatformTools.js +1 -1
  281. package/platform/PlatformTools.js.map +1 -1
  282. package/query-builder/JoinAttribute.js +3 -3
  283. package/query-builder/JoinAttribute.js.map +1 -1
  284. package/query-builder/QueryBuilder.d.ts +0 -1
  285. package/query-builder/QueryBuilder.js +3 -13
  286. package/query-builder/QueryBuilder.js.map +1 -1
  287. package/query-builder/SelectQueryBuilder.js +33 -27
  288. package/query-builder/SelectQueryBuilder.js.map +1 -1
  289. package/query-builder/SoftDeleteQueryBuilder.js +0 -2
  290. package/query-builder/SoftDeleteQueryBuilder.js.map +1 -1
  291. package/query-builder/UpdateQueryBuilder.js +0 -2
  292. package/query-builder/UpdateQueryBuilder.js.map +1 -1
  293. package/query-builder/relation-id/RelationIdAttribute.js +4 -4
  294. package/query-builder/relation-id/RelationIdAttribute.js.map +1 -1
  295. package/query-builder/relation-id/RelationIdLoader.js +16 -9
  296. package/query-builder/relation-id/RelationIdLoader.js.map +1 -1
  297. package/query-runner/BaseQueryRunner.d.ts +44 -21
  298. package/query-runner/BaseQueryRunner.js +61 -21
  299. package/query-runner/BaseQueryRunner.js.map +1 -1
  300. package/query-runner/QueryRunner.d.ts +11 -2
  301. package/query-runner/QueryRunner.js.map +1 -1
  302. package/repository/BaseEntity.d.ts +2 -1
  303. package/repository/BaseEntity.js.map +1 -1
  304. package/repository/Repository.d.ts +1 -1
  305. package/repository/Repository.js.map +1 -1
  306. package/subscriber/Broadcaster.d.ts +4 -4
  307. package/subscriber/Broadcaster.js.map +1 -1
  308. package/subscriber/event/QueryEvent.d.ts +2 -1
  309. package/subscriber/event/QueryEvent.js.map +1 -1
  310. package/util/DirectoryExportedClassesLoader.js +1 -1
  311. package/util/DirectoryExportedClassesLoader.js.map +1 -1
  312. package/util/ImportUtils.js +1 -1
  313. package/util/ImportUtils.js.map +1 -1
  314. package/util/OrmUtils.js +1 -1
  315. package/util/OrmUtils.js.map +1 -1
  316. package/util/PathUtils.js +1 -1
  317. package/util/PathUtils.js.map +1 -1
  318. package/util/RandomGenerator.d.ts +1 -10
  319. package/util/RandomGenerator.js +1 -10
  320. package/util/RandomGenerator.js.map +1 -1
  321. package/util/StringUtils.js +9 -9
  322. package/util/StringUtils.js.map +1 -1
  323. package/util/escapeRegExp.js +1 -1
  324. package/util/escapeRegExp.js.map +1 -1
  325. package/browser/naming-strategy/LegacyOracleNamingStrategy.d.ts +0 -21
  326. package/browser/naming-strategy/LegacyOracleNamingStrategy.js +0 -49
  327. package/browser/naming-strategy/LegacyOracleNamingStrategy.js.map +0 -1
  328. package/naming-strategy/LegacyOracleNamingStrategy.d.ts +0 -21
  329. package/naming-strategy/LegacyOracleNamingStrategy.js +0 -49
  330. package/naming-strategy/LegacyOracleNamingStrategy.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"NamingStrategyInterface.js","sourceRoot":"../build/browser/src/","sources":["naming-strategy/NamingStrategyInterface.ts"],"names":[],"mappings":"","sourcesContent":["import type { Table } from \"../schema-builder/table/Table\"\nimport type { View } from \"../schema-builder/view/View\"\n\n/**\n * Naming strategy defines how auto-generated names for such things like table name, or table column gonna be\n * generated.\n */\nexport interface NamingStrategyInterface {\n /**\n * Naming strategy name.\n */\n name?: string\n\n /**\n * Normalizes table name.\n *\n * @param targetName Name of the target entity that can be used to generate a table name.\n * @param userSpecifiedName For example if user specified a table name in a decorator, e.g. `@Entity(\"name\")`\n */\n tableName(targetName: string, userSpecifiedName: string | undefined): string\n\n /**\n * Creates a table name for a junction table of a closure table.\n *\n * @param originalClosureTableName Name of the closure table which owns this junction table.\n */\n closureJunctionTableName(originalClosureTableName: string): string\n\n /**\n * Gets the table's column name from the given property name.\n */\n columnName(\n propertyName: string,\n customName: string | undefined,\n embeddedPrefixes: string[],\n ): string\n\n /**\n * Gets the table's relation name from the given property name.\n */\n relationName(propertyName: string): string\n\n /**\n * Gets the table's primary key name from the given table name and column names.\n */\n primaryKeyName(tableOrName: Table | string, columnNames: string[]): string\n\n /**\n * Gets the table's unique constraint name from the given table name and column names.\n */\n uniqueConstraintName(\n tableOrName: Table | string,\n columnNames: string[],\n ): string\n\n /**\n * Gets the relation constraint (UNIQUE or UNIQUE INDEX) name from the given table name, column names\n * and WHERE condition, if UNIQUE INDEX used.\n */\n relationConstraintName(\n tableOrName: Table | string,\n columnNames: string[],\n where?: string,\n ): string\n\n /**\n * Gets the table's default constraint name from the given table name and column name.\n */\n defaultConstraintName(\n tableOrName: Table | string,\n columnName: string,\n ): string\n\n /**\n * Gets the name of the foreign key.\n */\n foreignKeyName(\n tableOrName: Table | string,\n columnNames: string[],\n referencedTablePath?: string,\n referencedColumnNames?: string[],\n ): string\n\n /**\n * Gets the name of the index - simple and compose index.\n */\n indexName(\n tableOrName: Table | View | string,\n columns: string[],\n where?: string,\n ): string\n\n /**\n * Gets the name of the check constraint.\n *\n * \"isEnum\" parameter is used to indicate if this check constraint used\n * to handle \"simple-enum\" type for databases that are not supporting \"enum\"\n * type out of the box. If \"true\", constraint is ignored during CHECK constraints\n * synchronization.\n */\n checkConstraintName(\n tableOrName: Table | string,\n expression: string,\n isEnum?: boolean,\n ): string\n\n /**\n * Gets the name of the exclusion constraint.\n */\n exclusionConstraintName(\n tableOrName: Table | string,\n expression: string,\n ): string\n\n /**\n * Gets the name of the join column used in the one-to-one and many-to-one relations.\n */\n joinColumnName(relationName: string, referencedColumnName: string): string\n\n /**\n * Gets the name of the join table used in the many-to-many relations.\n */\n joinTableName(\n firstTableName: string,\n secondTableName: string,\n firstPropertyName: string,\n secondPropertyName: string,\n ): string\n\n /**\n * Columns in join tables can have duplicate names in case of self-referencing.\n * This method provide a resolution for such column names.\n */\n joinTableColumnDuplicationPrefix(columnName: string, index: number): string\n\n /**\n * Gets the name of the column used for columns in the junction tables.\n *\n * The reverse?:boolean parameter denotes if the joinTableColumnName is called for the junctionColumn (false)\n * or the inverseJunctionColumns (true)\n */\n joinTableColumnName(\n tableName: string,\n propertyName: string,\n columnName?: string,\n ): string\n\n /**\n * Gets the name of the column used for columns in the junction tables from the invers side of the relationship.\n */\n joinTableInverseColumnName(\n tableName: string,\n propertyName: string,\n columnName?: string,\n ): string\n\n /**\n * Adds globally set prefix to the table name.\n * This method is executed no matter if prefix was set or not.\n * Table name is either user's given table name, either name generated from entity target.\n * Note that table name comes here already normalized by #tableName method.\n */\n prefixTableName(prefix: string, tableName: string): string\n\n /**\n * Column names for nested sets.\n */\n nestedSetColumnNames: { left: string; right: string }\n\n /**\n * Column name for materialized paths.\n */\n materializedPathColumnName: string\n}\n"]}
1
+ {"version":3,"file":"NamingStrategyInterface.js","sourceRoot":"../build/browser/src/","sources":["naming-strategy/NamingStrategyInterface.ts"],"names":[],"mappings":"","sourcesContent":["import type { Table } from \"../schema-builder/table/Table\"\nimport type { View } from \"../schema-builder/view/View\"\n\n/**\n * Naming strategy defines how auto-generated names for such things like table name, or table column gonna be\n * generated.\n */\nexport interface NamingStrategyInterface {\n /**\n * Column name for materialized paths.\n */\n materializedPathColumnName: string\n\n /**\n * Column names for nested sets.\n */\n nestedSetColumnNames: { left: string; right: string }\n\n /**\n * Normalizes table name.\n *\n * @param targetName Name of the target entity that can be used to generate a table name.\n * @param userSpecifiedName For example if user specified a table name in a decorator, e.g. `@Entity(\"name\")`\n */\n tableName(targetName: string, userSpecifiedName: string | undefined): string\n\n /**\n * Creates a table name for a junction table of a closure table.\n *\n * @param originalClosureTableName Name of the closure table which owns this junction table.\n */\n closureJunctionTableName(originalClosureTableName: string): string\n\n /**\n * Gets the table's column name from the given property name.\n */\n columnName(\n propertyName: string,\n customName: string | undefined,\n embeddedPrefixes: string[],\n ): string\n\n /**\n * Gets the table's relation name from the given property name.\n */\n relationName(propertyName: string): string\n\n /**\n * Gets the table's primary key name from the given table name and column names.\n */\n primaryKeyName(tableOrName: Table | string, columnNames: string[]): string\n\n /**\n * Gets the table's unique constraint name from the given table name and column names.\n */\n uniqueConstraintName(\n tableOrName: Table | string,\n columnNames: string[],\n ): string\n\n /**\n * Gets the relation constraint (UNIQUE or UNIQUE INDEX) name from the given table name, column names\n * and WHERE condition, if UNIQUE INDEX used.\n */\n relationConstraintName(\n tableOrName: Table | string,\n columnNames: string[],\n where?: string,\n ): string\n\n /**\n * Gets the table's default constraint name from the given table name and column name.\n */\n defaultConstraintName(\n tableOrName: Table | string,\n columnName: string,\n ): string\n\n /**\n * Gets the name of the foreign key.\n */\n foreignKeyName(\n tableOrName: Table | string,\n columnNames: string[],\n referencedTablePath?: string,\n referencedColumnNames?: string[],\n ): string\n\n /**\n * Gets the name of the index - simple and compose index.\n */\n indexName(\n tableOrName: Table | View | string,\n columns: string[],\n where?: string,\n ): string\n\n /**\n * Gets the name of the check constraint.\n *\n * \"isEnum\" parameter is used to indicate if this check constraint used\n * to handle \"simple-enum\" type for databases that are not supporting \"enum\"\n * type out of the box. If \"true\", constraint is ignored during CHECK constraints\n * synchronization.\n */\n checkConstraintName(\n tableOrName: Table | string,\n expression: string,\n isEnum?: boolean,\n ): string\n\n /**\n * Gets the name of the exclusion constraint.\n */\n exclusionConstraintName(\n tableOrName: Table | string,\n expression: string,\n ): string\n\n /**\n * Gets the name of the join column used in the one-to-one and many-to-one relations.\n */\n joinColumnName(relationName: string, referencedColumnName: string): string\n\n /**\n * Gets the name of the join table used in the many-to-many relations.\n */\n joinTableName(\n firstTableName: string,\n secondTableName: string,\n firstPropertyName: string,\n secondPropertyName: string,\n ): string\n\n /**\n * Columns in join tables can have duplicate names in case of self-referencing.\n * This method provide a resolution for such column names.\n */\n joinTableColumnDuplicationPrefix(columnName: string, index: number): string\n\n /**\n * Gets the name of the column used for columns in the junction tables.\n *\n * The reverse?:boolean parameter denotes if the joinTableColumnName is called for the junctionColumn (false)\n * or the inverseJunctionColumns (true)\n */\n joinTableColumnName(\n tableName: string,\n propertyName: string,\n columnName?: string,\n ): string\n\n /**\n * Gets the name of the column used for columns in the junction tables from the invers side of the relationship.\n */\n joinTableInverseColumnName(\n tableName: string,\n propertyName: string,\n columnName?: string,\n ): string\n\n /**\n * Adds globally set prefix to the table name.\n * This method is executed no matter if prefix was set or not.\n * Table name is either user's given table name, either name generated from entity target.\n * Note that table name comes here already normalized by #tableName method.\n */\n prefixTableName(prefix: string, tableName: string): string\n}\n"]}
@@ -44,7 +44,7 @@ class EntityPersistExecutor {
44
44
  // save data in the query runner - this is useful functionality to share data from outside of the world
45
45
  // with third classes - like subscribers and listener methods
46
46
  const oldQueryRunnerData = queryRunner.data;
47
- if (this.options && this.options.data) {
47
+ if (this.options?.data) {
48
48
  queryRunner.data = this.options.data;
49
49
  }
50
50
  try {
@@ -52,11 +52,9 @@ class EntityPersistExecutor {
52
52
  const entities = Array.isArray(this.entity)
53
53
  ? this.entity
54
54
  : [this.entity];
55
- const entitiesInChunks = this.options && this.options.chunk && this.options.chunk > 0
56
- ? OrmUtils_1.OrmUtils.chunk(entities, this.options.chunk)
57
- : [entities];
58
- // console.time("building subject executors...");
59
- const executors = await Promise.all(entitiesInChunks.map(async (entities) => {
55
+ const chunkSize = this.options?.chunk ?? 0;
56
+ const entitiesInChunks = chunkSize > 0 ? OrmUtils_1.OrmUtils.chunk(entities, chunkSize) : [entities];
57
+ const buildExecutor = async (entities) => {
60
58
  const subjects = [];
61
59
  // create subjects for all entities we received for the persistence
62
60
  entities.forEach((entity) => {
@@ -111,7 +109,21 @@ class EntityPersistExecutor {
111
109
  // console.log("subjects", subjects);
112
110
  // create a subject executor
113
111
  return new SubjectExecutor_1.SubjectExecutor(queryRunner, subjects, this.options);
114
- }));
112
+ };
113
+ // console.time("building subject executors...");
114
+ // Avoid concurrent queries on the same pg client; see #12238.
115
+ // CockroachDB uses the pg package over a single connection too.
116
+ const driverType = this.dataSource.options.type;
117
+ let executors;
118
+ if (driverType === "postgres" || driverType === "cockroachdb") {
119
+ executors = [];
120
+ for (const entities of entitiesInChunks) {
121
+ executors.push(await buildExecutor(entities));
122
+ }
123
+ }
124
+ else {
125
+ executors = await Promise.all(entitiesInChunks.map(buildExecutor));
126
+ }
115
127
  // console.timeEnd("building subject executors...");
116
128
  // make sure we have at least one executable operation before we create a transaction and proceed
117
129
  // if we don't have operations it means we don't really need to update or remove something
@@ -126,7 +138,7 @@ class EntityPersistExecutor {
126
138
  // open transaction if its not opened yet
127
139
  if (!queryRunner.isTransactionActive) {
128
140
  if (this.dataSource.driver.transactionSupport !== "none" &&
129
- (!this.options || this.options.transaction !== false)) {
141
+ this.options?.transaction !== false) {
130
142
  // start transaction until it was not explicitly disabled
131
143
  isTransactionStartedByUs = true;
132
144
  await queryRunner.startTransaction();
@@ -1 +1 @@
1
- {"version":3,"file":"EntityPersistExecutor.js","sourceRoot":"../build/browser/src/","sources":["persistence/EntityPersistExecutor.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ObjectLiteral } from \"../common/ObjectLiteral\"\nimport type { SaveOptions } from \"../repository/SaveOptions\"\nimport type { RemoveOptions } from \"../repository/RemoveOptions\"\nimport { MustBeEntityError } from \"../error/MustBeEntityError\"\nimport { SubjectExecutor } from \"./SubjectExecutor\"\nimport { CannotDetermineEntityError } from \"../error/CannotDetermineEntityError\"\nimport type { QueryRunner } from \"../query-runner/QueryRunner\"\nimport type { DataSource } from \"../data-source/DataSource\"\nimport { Subject } from \"./Subject\"\nimport { OneToManySubjectBuilder } from \"./subject-builder/OneToManySubjectBuilder\"\nimport { OneToOneInverseSideSubjectBuilder } from \"./subject-builder/OneToOneInverseSideSubjectBuilder\"\nimport { ManyToManySubjectBuilder } from \"./subject-builder/ManyToManySubjectBuilder\"\nimport { SubjectDatabaseEntityLoader } from \"./SubjectDatabaseEntityLoader\"\nimport { CascadesSubjectBuilder } from \"./subject-builder/CascadesSubjectBuilder\"\nimport { OrmUtils } from \"../util/OrmUtils\"\n\n/**\n * Persists a single entity or multiple entities - saves or removes them.\n */\nexport class EntityPersistExecutor {\n // -------------------------------------------------------------------------\n // Constructor\n // -------------------------------------------------------------------------\n\n constructor(\n protected dataSource: DataSource,\n protected queryRunner: QueryRunner | undefined,\n protected mode: \"save\" | \"remove\" | \"soft-remove\" | \"recover\",\n protected target: Function | string | undefined,\n protected entity: ObjectLiteral | ObjectLiteral[],\n protected options?: SaveOptions & RemoveOptions,\n ) {}\n\n // -------------------------------------------------------------------------\n // Public Methods\n // -------------------------------------------------------------------------\n\n /**\n * Executes persistence operation ob given entity or entities.\n */\n async execute(): Promise<void> {\n // check if entity we are going to save is valid and is an object\n if (!this.entity || typeof this.entity !== \"object\")\n return Promise.reject(new MustBeEntityError(this.mode, this.entity))\n\n // we MUST call \"fake\" resolve here to make sure all properties of lazily loaded relations are resolved\n await Promise.resolve()\n\n // if query runner is already defined in this class, it means this entity manager was already created for a single connection\n // if its not defined we create a new query runner - single connection where we'll execute all our operations\n const queryRunner =\n this.queryRunner ?? this.dataSource.createQueryRunner()\n\n // save data in the query runner - this is useful functionality to share data from outside of the world\n // with third classes - like subscribers and listener methods\n const oldQueryRunnerData = queryRunner.data\n if (this.options && this.options.data) {\n queryRunner.data = this.options.data\n }\n\n try {\n // collect all operate subjects\n const entities: ObjectLiteral[] = Array.isArray(this.entity)\n ? this.entity\n : [this.entity]\n const entitiesInChunks =\n this.options && this.options.chunk && this.options.chunk > 0\n ? OrmUtils.chunk(entities, this.options.chunk)\n : [entities]\n\n // console.time(\"building subject executors...\");\n const executors = await Promise.all(\n entitiesInChunks.map(async (entities) => {\n const subjects: Subject[] = []\n\n // create subjects for all entities we received for the persistence\n entities.forEach((entity) => {\n const entityTarget = this.target ?? entity.constructor\n if (entityTarget === Object)\n throw new CannotDetermineEntityError(this.mode)\n\n const metadata = this.dataSource\n .getMetadata(entityTarget)\n .findInheritanceMetadata(entity)\n\n subjects.push(\n new Subject({\n metadata,\n entity: entity,\n canBeInserted: this.mode === \"save\",\n canBeUpdated: this.mode === \"save\",\n mustBeRemoved: this.mode === \"remove\",\n canBeSoftRemoved: this.mode === \"soft-remove\",\n canBeRecovered: this.mode === \"recover\",\n }),\n )\n })\n\n // console.time(\"building cascades...\");\n // go through each entity with metadata and create subjects and subjects by cascades for them\n const cascadesSubjectBuilder = new CascadesSubjectBuilder(\n subjects,\n )\n subjects.forEach((subject) => {\n // next step we build list of subjects we will operate with\n // these subjects are subjects that we need to insert or update alongside with main persisted entity\n cascadesSubjectBuilder.build(subject, this.mode)\n })\n // console.timeEnd(\"building cascades...\");\n\n // load database entities for all subjects we have\n // next step is to load database entities for all operate subjects\n // console.time(\"loading...\");\n await new SubjectDatabaseEntityLoader(\n queryRunner,\n subjects,\n ).load(this.mode)\n // console.timeEnd(\"loading...\");\n\n // console.time(\"other subjects...\");\n // build all related subjects and change maps\n if (\n this.mode === \"save\" ||\n this.mode === \"soft-remove\" ||\n this.mode === \"recover\"\n ) {\n new OneToManySubjectBuilder(subjects).build()\n new OneToOneInverseSideSubjectBuilder(subjects).build()\n new ManyToManySubjectBuilder(subjects).build()\n } else {\n subjects.forEach((subject) => {\n if (subject.mustBeRemoved) {\n new ManyToManySubjectBuilder(\n subjects,\n ).buildForAllRemoval(subject)\n }\n })\n }\n // console.timeEnd(\"other subjects...\");\n // console.timeEnd(\"building subjects...\");\n // console.log(\"subjects\", subjects);\n\n // create a subject executor\n return new SubjectExecutor(\n queryRunner,\n subjects,\n this.options,\n )\n }),\n )\n // console.timeEnd(\"building subject executors...\");\n\n // make sure we have at least one executable operation before we create a transaction and proceed\n // if we don't have operations it means we don't really need to update or remove something\n const executorsWithExecutableOperations = executors.filter(\n (executor) => executor.hasExecutableOperations,\n )\n if (executorsWithExecutableOperations.length === 0) return\n\n // start execute queries in a transaction\n // if transaction is already opened in this query runner then we don't touch it\n // if its not opened yet then we open it here, and once we finish - we close it\n let isTransactionStartedByUs = false\n try {\n // open transaction if its not opened yet\n if (!queryRunner.isTransactionActive) {\n if (\n this.dataSource.driver.transactionSupport !== \"none\" &&\n (!this.options || this.options.transaction !== false)\n ) {\n // start transaction until it was not explicitly disabled\n isTransactionStartedByUs = true\n await queryRunner.startTransaction()\n }\n }\n\n // execute all persistence operations for all entities we have\n // console.time(\"executing subject executors...\");\n for (const executor of executorsWithExecutableOperations) {\n await executor.execute()\n }\n // console.timeEnd(\"executing subject executors...\");\n\n // commit transaction if it was started by us\n // console.time(\"commit\");\n if (isTransactionStartedByUs === true)\n await queryRunner.commitTransaction()\n // console.timeEnd(\"commit\");\n } catch (error) {\n // rollback transaction if it was started by us\n if (isTransactionStartedByUs) {\n try {\n await queryRunner.rollbackTransaction()\n } catch (rollbackError) {}\n }\n throw error\n }\n } finally {\n queryRunner.data = oldQueryRunnerData\n\n // release query runner only if its created by us\n if (!this.queryRunner) await queryRunner.release()\n }\n }\n}\n"]}
1
+ {"version":3,"file":"EntityPersistExecutor.js","sourceRoot":"../build/browser/src/","sources":["persistence/EntityPersistExecutor.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ObjectLiteral } from \"../common/ObjectLiteral\"\nimport type { SaveOptions } from \"../repository/SaveOptions\"\nimport type { RemoveOptions } from \"../repository/RemoveOptions\"\nimport { MustBeEntityError } from \"../error/MustBeEntityError\"\nimport { SubjectExecutor } from \"./SubjectExecutor\"\nimport { CannotDetermineEntityError } from \"../error/CannotDetermineEntityError\"\nimport type { QueryRunner } from \"../query-runner/QueryRunner\"\nimport type { DataSource } from \"../data-source/DataSource\"\nimport { Subject } from \"./Subject\"\nimport { OneToManySubjectBuilder } from \"./subject-builder/OneToManySubjectBuilder\"\nimport { OneToOneInverseSideSubjectBuilder } from \"./subject-builder/OneToOneInverseSideSubjectBuilder\"\nimport { ManyToManySubjectBuilder } from \"./subject-builder/ManyToManySubjectBuilder\"\nimport { SubjectDatabaseEntityLoader } from \"./SubjectDatabaseEntityLoader\"\nimport { CascadesSubjectBuilder } from \"./subject-builder/CascadesSubjectBuilder\"\nimport { OrmUtils } from \"../util/OrmUtils\"\n\n/**\n * Persists a single entity or multiple entities - saves or removes them.\n */\nexport class EntityPersistExecutor {\n // -------------------------------------------------------------------------\n // Constructor\n // -------------------------------------------------------------------------\n\n constructor(\n protected dataSource: DataSource,\n protected queryRunner: QueryRunner | undefined,\n protected mode: \"save\" | \"remove\" | \"soft-remove\" | \"recover\",\n protected target: Function | string | undefined,\n protected entity: ObjectLiteral | ObjectLiteral[],\n protected options?: SaveOptions & RemoveOptions,\n ) {}\n\n // -------------------------------------------------------------------------\n // Public Methods\n // -------------------------------------------------------------------------\n\n /**\n * Executes persistence operation ob given entity or entities.\n */\n async execute(): Promise<void> {\n // check if entity we are going to save is valid and is an object\n if (!this.entity || typeof this.entity !== \"object\")\n return Promise.reject(new MustBeEntityError(this.mode, this.entity))\n\n // we MUST call \"fake\" resolve here to make sure all properties of lazily loaded relations are resolved\n await Promise.resolve()\n\n // if query runner is already defined in this class, it means this entity manager was already created for a single connection\n // if its not defined we create a new query runner - single connection where we'll execute all our operations\n const queryRunner =\n this.queryRunner ?? this.dataSource.createQueryRunner()\n\n // save data in the query runner - this is useful functionality to share data from outside of the world\n // with third classes - like subscribers and listener methods\n const oldQueryRunnerData = queryRunner.data\n if (this.options?.data) {\n queryRunner.data = this.options.data\n }\n\n try {\n // collect all operate subjects\n const entities: ObjectLiteral[] = Array.isArray(this.entity)\n ? this.entity\n : [this.entity]\n const chunkSize = this.options?.chunk ?? 0\n const entitiesInChunks =\n chunkSize > 0 ? OrmUtils.chunk(entities, chunkSize) : [entities]\n\n const buildExecutor = async (\n entities: ObjectLiteral[],\n ): Promise<SubjectExecutor> => {\n const subjects: Subject[] = []\n\n // create subjects for all entities we received for the persistence\n entities.forEach((entity) => {\n const entityTarget = this.target ?? entity.constructor\n if (entityTarget === Object)\n throw new CannotDetermineEntityError(this.mode)\n\n const metadata = this.dataSource\n .getMetadata(entityTarget)\n .findInheritanceMetadata(entity)\n\n subjects.push(\n new Subject({\n metadata,\n entity: entity,\n canBeInserted: this.mode === \"save\",\n canBeUpdated: this.mode === \"save\",\n mustBeRemoved: this.mode === \"remove\",\n canBeSoftRemoved: this.mode === \"soft-remove\",\n canBeRecovered: this.mode === \"recover\",\n }),\n )\n })\n\n // console.time(\"building cascades...\");\n // go through each entity with metadata and create subjects and subjects by cascades for them\n const cascadesSubjectBuilder = new CascadesSubjectBuilder(\n subjects,\n )\n subjects.forEach((subject) => {\n // next step we build list of subjects we will operate with\n // these subjects are subjects that we need to insert or update alongside with main persisted entity\n cascadesSubjectBuilder.build(subject, this.mode)\n })\n // console.timeEnd(\"building cascades...\");\n\n // load database entities for all subjects we have\n // next step is to load database entities for all operate subjects\n // console.time(\"loading...\");\n await new SubjectDatabaseEntityLoader(\n queryRunner,\n subjects,\n ).load(this.mode)\n // console.timeEnd(\"loading...\");\n\n // console.time(\"other subjects...\");\n // build all related subjects and change maps\n if (\n this.mode === \"save\" ||\n this.mode === \"soft-remove\" ||\n this.mode === \"recover\"\n ) {\n new OneToManySubjectBuilder(subjects).build()\n new OneToOneInverseSideSubjectBuilder(subjects).build()\n new ManyToManySubjectBuilder(subjects).build()\n } else {\n subjects.forEach((subject) => {\n if (subject.mustBeRemoved) {\n new ManyToManySubjectBuilder(\n subjects,\n ).buildForAllRemoval(subject)\n }\n })\n }\n // console.timeEnd(\"other subjects...\");\n // console.timeEnd(\"building subjects...\");\n // console.log(\"subjects\", subjects);\n\n // create a subject executor\n return new SubjectExecutor(queryRunner, subjects, this.options)\n }\n\n // console.time(\"building subject executors...\");\n // Avoid concurrent queries on the same pg client; see #12238.\n // CockroachDB uses the pg package over a single connection too.\n const driverType = this.dataSource.options.type\n let executors: SubjectExecutor[]\n if (driverType === \"postgres\" || driverType === \"cockroachdb\") {\n executors = []\n for (const entities of entitiesInChunks) {\n executors.push(await buildExecutor(entities))\n }\n } else {\n executors = await Promise.all(\n entitiesInChunks.map(buildExecutor),\n )\n }\n // console.timeEnd(\"building subject executors...\");\n\n // make sure we have at least one executable operation before we create a transaction and proceed\n // if we don't have operations it means we don't really need to update or remove something\n const executorsWithExecutableOperations = executors.filter(\n (executor) => executor.hasExecutableOperations,\n )\n if (executorsWithExecutableOperations.length === 0) return\n\n // start execute queries in a transaction\n // if transaction is already opened in this query runner then we don't touch it\n // if its not opened yet then we open it here, and once we finish - we close it\n let isTransactionStartedByUs = false\n try {\n // open transaction if its not opened yet\n if (!queryRunner.isTransactionActive) {\n if (\n this.dataSource.driver.transactionSupport !== \"none\" &&\n this.options?.transaction !== false\n ) {\n // start transaction until it was not explicitly disabled\n isTransactionStartedByUs = true\n await queryRunner.startTransaction()\n }\n }\n\n // execute all persistence operations for all entities we have\n // console.time(\"executing subject executors...\");\n for (const executor of executorsWithExecutableOperations) {\n await executor.execute()\n }\n // console.timeEnd(\"executing subject executors...\");\n\n // commit transaction if it was started by us\n // console.time(\"commit\");\n if (isTransactionStartedByUs === true)\n await queryRunner.commitTransaction()\n // console.timeEnd(\"commit\");\n } catch (error) {\n // rollback transaction if it was started by us\n if (isTransactionStartedByUs) {\n try {\n await queryRunner.rollbackTransaction()\n } catch (rollbackError) {}\n }\n throw error\n }\n } finally {\n queryRunner.data = oldQueryRunnerData\n\n // release query runner only if its created by us\n if (!this.queryRunner) await queryRunner.release()\n }\n }\n}\n"]}
@@ -30,7 +30,7 @@ class SubjectDatabaseEntityLoader {
30
30
  async load(operationType) {
31
31
  // we are grouping subjects by target to perform more optimized queries using WHERE IN operator
32
32
  // go through the groups and perform loading of database entities of each subject in the group
33
- const promises = this.groupByEntityTargets().map(async (subjectGroup) => {
33
+ const loadSubjectGroup = async (subjectGroup) => {
34
34
  // prepare entity ids of the subjects we need to load
35
35
  const allIds = [];
36
36
  const allSubjects = [];
@@ -82,8 +82,7 @@ class SubjectDatabaseEntityLoader {
82
82
  };
83
83
  // load database entities for all given ids
84
84
  let entities;
85
- if (this.queryRunner.dataSource.driver.options.type ===
86
- "mongodb") {
85
+ if (this.queryRunner.dataSource.driver.options.type === "mongodb") {
87
86
  const mongoRepo = this.queryRunner.manager.getRepository(subjectGroup.target);
88
87
  entities = await mongoRepo.findByIds(allIds, findOptions);
89
88
  }
@@ -112,8 +111,19 @@ class SubjectDatabaseEntityLoader {
112
111
  for (const subject of allSubjects) {
113
112
  subject.databaseEntityLoaded = true;
114
113
  }
115
- });
116
- await Promise.all(promises);
114
+ };
115
+ const subjectGroups = this.groupByEntityTargets();
116
+ // Avoid concurrent queries on the same pg client; see #12238.
117
+ // CockroachDB uses the pg package over a single connection too.
118
+ const driverType = this.queryRunner.dataSource.options.type;
119
+ if (driverType === "postgres" || driverType === "cockroachdb") {
120
+ for (const subjectGroup of subjectGroups) {
121
+ await loadSubjectGroup(subjectGroup);
122
+ }
123
+ }
124
+ else {
125
+ await Promise.all(subjectGroups.map(loadSubjectGroup));
126
+ }
117
127
  }
118
128
  // ---------------------------------------------------------------------
119
129
  // Protected Methods
@@ -1 +1 @@
1
- {"version":3,"file":"SubjectDatabaseEntityLoader.js","sourceRoot":"../build/browser/src/","sources":["persistence/SubjectDatabaseEntityLoader.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Subject } from \"./Subject\"\nimport type { ObjectLiteral } from \"../common/ObjectLiteral\"\nimport type { QueryRunner } from \"../query-runner/QueryRunner\"\nimport type { FindManyOptions } from \"../find-options/FindManyOptions\"\nimport type { MongoRepository } from \"../repository/MongoRepository\"\nimport { OrmUtils } from \"../util/OrmUtils\"\n\n/**\n * Loads database entities for all operate subjects which do not have database entity set.\n * All entities that we load database entities for are marked as updated or inserted.\n * To understand which of them really needs to be inserted or updated we need to load\n * their original representations from the database.\n */\nexport class SubjectDatabaseEntityLoader {\n // ---------------------------------------------------------------------\n // Constructor\n // ---------------------------------------------------------------------\n\n constructor(\n protected queryRunner: QueryRunner,\n protected subjects: Subject[],\n ) {}\n\n // ---------------------------------------------------------------------\n // Public Methods\n // ---------------------------------------------------------------------\n\n /**\n * Loads database entities for all subjects.\n *\n * loadAllRelations flag is used to load all relation ids of the object, no matter if they present in subject entity or not.\n * This option is used for deletion.\n *\n * @param operationType\n */\n async load(\n operationType: \"save\" | \"remove\" | \"soft-remove\" | \"recover\",\n ): Promise<void> {\n // we are grouping subjects by target to perform more optimized queries using WHERE IN operator\n // go through the groups and perform loading of database entities of each subject in the group\n const promises = this.groupByEntityTargets().map(\n async (subjectGroup) => {\n // prepare entity ids of the subjects we need to load\n const allIds: ObjectLiteral[] = []\n const allSubjects: Subject[] = []\n subjectGroup.subjects.forEach((subject) => {\n // we don't load if subject already has a database entity loaded\n if (subject.databaseEntity || !subject.identifier) return\n\n allIds.push(subject.identifier)\n allSubjects.push(subject)\n })\n\n // if there no ids found (means all entities are new and have generated ids) - then nothing to load there\n if (!allIds.length) return\n\n const loadRelationPropertyPaths: string[] = []\n\n // for the save, soft-remove and recover operation\n // extract all property paths of the relations we need to load relation ids for\n // this is for optimization purpose - this way we don't load relation ids for entities\n // whose relations are undefined, and since they are undefined its really pointless to\n // load something for them, since undefined properties are skipped by the orm\n if (\n operationType === \"save\" ||\n operationType === \"soft-remove\" ||\n operationType === \"recover\"\n ) {\n subjectGroup.subjects.forEach((subject) => {\n // gets all relation property paths that exist in the persisted entity.\n subject.metadata.relations.forEach((relation) => {\n const value = relation.getEntityValue(\n subject.entityWithFulfilledIds!,\n )\n if (value === undefined) return\n\n if (\n loadRelationPropertyPaths.indexOf(\n relation.propertyPath,\n ) === -1\n )\n loadRelationPropertyPaths.push(\n relation.propertyPath,\n )\n })\n })\n } else {\n // remove\n\n // for remove operation\n // we only need to load junction relation ids since only they are removed by cascades\n loadRelationPropertyPaths.push(\n ...subjectGroup.subjects[0].metadata.manyToManyRelations.map(\n (relation) => relation.propertyPath,\n ),\n )\n }\n\n const findOptions: FindManyOptions<any> = {\n loadEagerRelations: false,\n loadRelationIds: {\n relations: loadRelationPropertyPaths,\n disableMixedMap: true,\n },\n // include soft-deleted entities so save, soft-remove, recover,\n // and remove can find them by PK and load their relation IDs\n withDeleted: true,\n }\n\n // load database entities for all given ids\n let entities: any[]\n if (\n this.queryRunner.dataSource.driver.options.type ===\n \"mongodb\"\n ) {\n const mongoRepo =\n this.queryRunner.manager.getRepository<ObjectLiteral>(\n subjectGroup.target,\n ) as MongoRepository<ObjectLiteral>\n entities = await mongoRepo.findByIds(allIds, findOptions)\n } else {\n entities = await this.queryRunner.manager\n .getRepository<ObjectLiteral>(subjectGroup.target)\n .createQueryBuilder()\n .setFindOptions(findOptions)\n .whereInIds(allIds)\n .getMany()\n }\n\n // Now when we have entities we need to find subject of each entity\n // and insert that entity into database entity of the found subjects.\n // A single entity can be applied to many subjects as there might be duplicates.\n // This will likely result in the same row being updated multiple times during a transaction.\n entities.forEach((entity) => {\n const entityId =\n allSubjects[0].metadata.getEntityIdMap(entity)\n allSubjects.forEach((subject) => {\n if (subject.databaseEntity) return\n if (OrmUtils.compareIds(subject.identifier, entityId))\n subject.databaseEntity = entity\n })\n })\n\n // this way we tell what subjects we tried to load database entities of\n for (const subject of allSubjects) {\n subject.databaseEntityLoaded = true\n }\n },\n )\n\n await Promise.all(promises)\n }\n\n // ---------------------------------------------------------------------\n // Protected Methods\n // ---------------------------------------------------------------------\n\n /**\n * Groups given Subject objects into groups separated by entity targets.\n */\n protected groupByEntityTargets(): {\n target: Function | string\n subjects: Subject[]\n }[] {\n return this.subjects.reduce(\n (groups, operatedEntity) => {\n let group = groups.find(\n (group) => group.target === operatedEntity.metadata.target,\n )\n if (!group) {\n group = {\n target: operatedEntity.metadata.target,\n subjects: [],\n }\n groups.push(group)\n }\n group.subjects.push(operatedEntity)\n return groups\n },\n [] as { target: Function | string; subjects: Subject[] }[],\n )\n }\n}\n"]}
1
+ {"version":3,"file":"SubjectDatabaseEntityLoader.js","sourceRoot":"../build/browser/src/","sources":["persistence/SubjectDatabaseEntityLoader.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Subject } from \"./Subject\"\nimport type { ObjectLiteral } from \"../common/ObjectLiteral\"\nimport type { QueryRunner } from \"../query-runner/QueryRunner\"\nimport type { FindManyOptions } from \"../find-options/FindManyOptions\"\nimport type { MongoRepository } from \"../repository/MongoRepository\"\nimport { OrmUtils } from \"../util/OrmUtils\"\n\n/**\n * Loads database entities for all operate subjects which do not have database entity set.\n * All entities that we load database entities for are marked as updated or inserted.\n * To understand which of them really needs to be inserted or updated we need to load\n * their original representations from the database.\n */\nexport class SubjectDatabaseEntityLoader {\n // ---------------------------------------------------------------------\n // Constructor\n // ---------------------------------------------------------------------\n\n constructor(\n protected queryRunner: QueryRunner,\n protected subjects: Subject[],\n ) {}\n\n // ---------------------------------------------------------------------\n // Public Methods\n // ---------------------------------------------------------------------\n\n /**\n * Loads database entities for all subjects.\n *\n * loadAllRelations flag is used to load all relation ids of the object, no matter if they present in subject entity or not.\n * This option is used for deletion.\n *\n * @param operationType\n */\n async load(\n operationType: \"save\" | \"remove\" | \"soft-remove\" | \"recover\",\n ): Promise<void> {\n // we are grouping subjects by target to perform more optimized queries using WHERE IN operator\n // go through the groups and perform loading of database entities of each subject in the group\n const loadSubjectGroup = async (subjectGroup: {\n target: Function | string\n subjects: Subject[]\n }): Promise<void> => {\n // prepare entity ids of the subjects we need to load\n const allIds: ObjectLiteral[] = []\n const allSubjects: Subject[] = []\n subjectGroup.subjects.forEach((subject) => {\n // we don't load if subject already has a database entity loaded\n if (subject.databaseEntity || !subject.identifier) return\n\n allIds.push(subject.identifier)\n allSubjects.push(subject)\n })\n\n // if there no ids found (means all entities are new and have generated ids) - then nothing to load there\n if (!allIds.length) return\n\n const loadRelationPropertyPaths: string[] = []\n\n // for the save, soft-remove and recover operation\n // extract all property paths of the relations we need to load relation ids for\n // this is for optimization purpose - this way we don't load relation ids for entities\n // whose relations are undefined, and since they are undefined its really pointless to\n // load something for them, since undefined properties are skipped by the orm\n if (\n operationType === \"save\" ||\n operationType === \"soft-remove\" ||\n operationType === \"recover\"\n ) {\n subjectGroup.subjects.forEach((subject) => {\n // gets all relation property paths that exist in the persisted entity.\n subject.metadata.relations.forEach((relation) => {\n const value = relation.getEntityValue(\n subject.entityWithFulfilledIds!,\n )\n if (value === undefined) return\n\n if (\n loadRelationPropertyPaths.indexOf(\n relation.propertyPath,\n ) === -1\n )\n loadRelationPropertyPaths.push(\n relation.propertyPath,\n )\n })\n })\n } else {\n // remove\n\n // for remove operation\n // we only need to load junction relation ids since only they are removed by cascades\n loadRelationPropertyPaths.push(\n ...subjectGroup.subjects[0].metadata.manyToManyRelations.map(\n (relation) => relation.propertyPath,\n ),\n )\n }\n\n const findOptions: FindManyOptions<any> = {\n loadEagerRelations: false,\n loadRelationIds: {\n relations: loadRelationPropertyPaths,\n disableMixedMap: true,\n },\n // include soft-deleted entities so save, soft-remove, recover,\n // and remove can find them by PK and load their relation IDs\n withDeleted: true,\n }\n\n // load database entities for all given ids\n let entities: any[]\n if (this.queryRunner.dataSource.driver.options.type === \"mongodb\") {\n const mongoRepo =\n this.queryRunner.manager.getRepository<ObjectLiteral>(\n subjectGroup.target,\n ) as MongoRepository<ObjectLiteral>\n entities = await mongoRepo.findByIds(allIds, findOptions)\n } else {\n entities = await this.queryRunner.manager\n .getRepository<ObjectLiteral>(subjectGroup.target)\n .createQueryBuilder()\n .setFindOptions(findOptions)\n .whereInIds(allIds)\n .getMany()\n }\n\n // Now when we have entities we need to find subject of each entity\n // and insert that entity into database entity of the found subjects.\n // A single entity can be applied to many subjects as there might be duplicates.\n // This will likely result in the same row being updated multiple times during a transaction.\n entities.forEach((entity) => {\n const entityId = allSubjects[0].metadata.getEntityIdMap(entity)\n allSubjects.forEach((subject) => {\n if (subject.databaseEntity) return\n if (OrmUtils.compareIds(subject.identifier, entityId))\n subject.databaseEntity = entity\n })\n })\n\n // this way we tell what subjects we tried to load database entities of\n for (const subject of allSubjects) {\n subject.databaseEntityLoaded = true\n }\n }\n\n const subjectGroups = this.groupByEntityTargets()\n\n // Avoid concurrent queries on the same pg client; see #12238.\n // CockroachDB uses the pg package over a single connection too.\n const driverType = this.queryRunner.dataSource.options.type\n if (driverType === \"postgres\" || driverType === \"cockroachdb\") {\n for (const subjectGroup of subjectGroups) {\n await loadSubjectGroup(subjectGroup)\n }\n } else {\n await Promise.all(subjectGroups.map(loadSubjectGroup))\n }\n }\n\n // ---------------------------------------------------------------------\n // Protected Methods\n // ---------------------------------------------------------------------\n\n /**\n * Groups given Subject objects into groups separated by entity targets.\n */\n protected groupByEntityTargets(): {\n target: Function | string\n subjects: Subject[]\n }[] {\n return this.subjects.reduce(\n (groups, operatedEntity) => {\n let group = groups.find(\n (group) => group.target === operatedEntity.metadata.target,\n )\n if (!group) {\n group = {\n target: operatedEntity.metadata.target,\n subjects: [],\n }\n groups.push(group)\n }\n group.subjects.push(operatedEntity)\n return groups\n },\n [] as { target: Function | string; subjects: Subject[] }[],\n )\n }\n}\n"]}
@@ -65,7 +65,7 @@ class SubjectExecutor {
65
65
  // console.time("SubjectExecutor.execute");
66
66
  // broadcast "before" events before we start insert / update / remove operations
67
67
  let broadcasterResult = undefined;
68
- if (!this.options || this.options.listeners !== false) {
68
+ if (this.options?.listeners !== false) {
69
69
  // console.time(".broadcastBeforeEventsForAll");
70
70
  broadcasterResult = this.broadcastBeforeEventsForAll();
71
71
  if (broadcasterResult.promises.length > 0)
@@ -116,7 +116,7 @@ class SubjectExecutor {
116
116
  this.updateSpecialColumnsInPersistedEntities();
117
117
  // console.timeEnd(".updateSpecialColumnsInPersistedEntities");
118
118
  // finally broadcast "after" events after we finish insert / update / remove operations
119
- if (!this.options || this.options.listeners !== false) {
119
+ if (this.options?.listeners !== false) {
120
120
  // console.time(".broadcastAfterEventsForAll");
121
121
  broadcasterResult = this.broadcastAfterEventsForAll();
122
122
  if (broadcasterResult.promises.length > 0)
@@ -262,9 +262,7 @@ class SubjectExecutor {
262
262
  .insert()
263
263
  .into(subjects[0].metadata.target)
264
264
  .values(bulkInsertMaps)
265
- .updateEntity(this.options && this.options.reload === false
266
- ? false
267
- : true)
265
+ .updateEntity(this.options?.reload !== false)
268
266
  .callListeners(false)
269
267
  .execute();
270
268
  bulkInsertSubjects.forEach((subject, index) => {
@@ -286,9 +284,7 @@ class SubjectExecutor {
286
284
  .insert()
287
285
  .into(subject.metadata.target)
288
286
  .values(subject.insertedValueSet)
289
- .updateEntity(this.options && this.options.reload === false
290
- ? false
291
- : true)
287
+ .updateEntity(this.options?.reload !== false)
292
288
  .callListeners(false)
293
289
  .execute()
294
290
  .then((insertResult) => {
@@ -363,9 +359,7 @@ class SubjectExecutor {
363
359
  .createQueryBuilder()
364
360
  .update(subject.metadata.target)
365
361
  .set(updateMap)
366
- .updateEntity(this.options && this.options.reload === false
367
- ? false
368
- : true)
362
+ .updateEntity(this.options?.reload !== false)
369
363
  .callListeners(false);
370
364
  if (subject.entity) {
371
365
  updateQueryBuilder.whereEntity(subject.identifier);
@@ -407,11 +401,21 @@ class SubjectExecutor {
407
401
  await updateSubject(subject);
408
402
  }
409
403
  };
410
- // Run all remaining subjects in parallel
411
- await Promise.all([
412
- ...remainingSubjects.map(updateSubject),
413
- updateNestSetSubjects(),
414
- ]);
404
+ // Avoid concurrent queries on the same pg client; see #12238.
405
+ // CockroachDB uses the pg package over a single connection too.
406
+ const driverType = this.queryRunner.dataSource.options.type;
407
+ if (driverType === "postgres" || driverType === "cockroachdb") {
408
+ for (const subject of remainingSubjects) {
409
+ await updateSubject(subject);
410
+ }
411
+ await updateNestSetSubjects();
412
+ }
413
+ else {
414
+ await Promise.all([
415
+ ...remainingSubjects.map(updateSubject),
416
+ updateNestSetSubjects(),
417
+ ]);
418
+ }
415
419
  }
416
420
  /**
417
421
  * Removes all given subjects from the database.
@@ -470,7 +474,7 @@ class SubjectExecutor {
470
474
  * Soft-removes all given subjects in the database.
471
475
  */
472
476
  async executeSoftRemoveOperations() {
473
- await Promise.all(this.softRemoveSubjects.map(async (subject) => {
477
+ const softRemoveSubject = async (subject) => {
474
478
  if (!subject.identifier)
475
479
  throw new SubjectWithoutIdentifierError_1.SubjectWithoutIdentifierError(subject);
476
480
  let updateResult;
@@ -489,8 +493,7 @@ class SubjectExecutor {
489
493
  if (subject.metadata.deleteDateColumn?.propertyName) {
490
494
  partialEntity[subject.metadata.deleteDateColumn.propertyName] = new Date();
491
495
  }
492
- const manager = this.queryRunner
493
- .manager;
496
+ const manager = this.queryRunner.manager;
494
497
  updateResult = await manager.update(subject.metadata.target, subject.identifier, partialEntity);
495
498
  }
496
499
  else {
@@ -502,9 +505,7 @@ class SubjectExecutor {
502
505
  .createQueryBuilder()
503
506
  .softDelete()
504
507
  .from(subject.metadata.target)
505
- .updateEntity(this.options && this.options.reload === false
506
- ? false
507
- : true)
508
+ .updateEntity(this.options?.reload !== false)
508
509
  .callListeners(false);
509
510
  if (subject.entity) {
510
511
  softDeleteQueryBuilder.whereEntity(subject.identifier);
@@ -536,13 +537,24 @@ class SubjectExecutor {
536
537
  // }
537
538
  // }));
538
539
  // }
539
- }));
540
+ };
541
+ // Avoid concurrent queries on the same pg client; see #12238.
542
+ // CockroachDB uses the pg package over a single connection too.
543
+ const driverType = this.queryRunner.dataSource.options.type;
544
+ if (driverType === "postgres" || driverType === "cockroachdb") {
545
+ for (const subject of this.softRemoveSubjects) {
546
+ await softRemoveSubject(subject);
547
+ }
548
+ }
549
+ else {
550
+ await Promise.all(this.softRemoveSubjects.map(softRemoveSubject));
551
+ }
540
552
  }
541
553
  /**
542
554
  * Recovers all given subjects in the database.
543
555
  */
544
556
  async executeRecoverOperations() {
545
- await Promise.all(this.recoverSubjects.map(async (subject) => {
557
+ const recoverSubject = async (subject) => {
546
558
  if (!subject.identifier)
547
559
  throw new SubjectWithoutIdentifierError_1.SubjectWithoutIdentifierError(subject);
548
560
  let updateResult;
@@ -561,8 +573,7 @@ class SubjectExecutor {
561
573
  if (subject.metadata.deleteDateColumn?.propertyName) {
562
574
  partialEntity[subject.metadata.deleteDateColumn.propertyName] = null;
563
575
  }
564
- const manager = this.queryRunner
565
- .manager;
576
+ const manager = this.queryRunner.manager;
566
577
  updateResult = await manager.update(subject.metadata.target, subject.identifier, partialEntity);
567
578
  }
568
579
  else {
@@ -574,9 +585,7 @@ class SubjectExecutor {
574
585
  .createQueryBuilder()
575
586
  .restore()
576
587
  .from(subject.metadata.target)
577
- .updateEntity(this.options && this.options.reload === false
578
- ? false
579
- : true)
588
+ .updateEntity(this.options?.reload !== false)
580
589
  .callListeners(false);
581
590
  if (subject.entity) {
582
591
  softDeleteQueryBuilder.whereEntity(subject.identifier);
@@ -608,7 +617,18 @@ class SubjectExecutor {
608
617
  // }
609
618
  // }));
610
619
  // }
611
- }));
620
+ };
621
+ // Avoid concurrent queries on the same pg client; see #12238.
622
+ // CockroachDB uses the pg package over a single connection too.
623
+ const driverType = this.queryRunner.dataSource.options.type;
624
+ if (driverType === "postgres" || driverType === "cockroachdb") {
625
+ for (const subject of this.recoverSubjects) {
626
+ await recoverSubject(subject);
627
+ }
628
+ }
629
+ else {
630
+ await Promise.all(this.recoverSubjects.map(recoverSubject));
631
+ }
612
632
  }
613
633
  /**
614
634
  * Updates all special columns of the saving entities (create date, update date, version, etc.).