masonite-orm 2.23.1__tar.gz → 2.23.2__tar.gz

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 (124) hide show
  1. {masonite-orm-2.23.1/src/masonite_orm.egg-info → masonite-orm-2.23.2}/PKG-INFO +1 -1
  2. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/setup.py +1 -1
  3. {masonite-orm-2.23.1 → masonite-orm-2.23.2/src/masonite_orm.egg-info}/PKG-INFO +1 -1
  4. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/connections/MySQLConnection.py +77 -30
  5. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/connections/PostgresConnection.py +72 -12
  6. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/models/Model.py +8 -7
  7. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/query/QueryBuilder.py +20 -21
  8. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/query/grammars/BaseGrammar.py +2 -3
  9. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/relationships/BaseRelationship.py +3 -0
  10. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/relationships/BelongsTo.py +3 -0
  11. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/relationships/HasMany.py +3 -0
  12. masonite-orm-2.23.2/src/masoniteorm/relationships/HasManyThrough.py +270 -0
  13. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/relationships/HasOne.py +3 -0
  14. masonite-orm-2.23.2/src/masoniteorm/relationships/HasOneThrough.py +275 -0
  15. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/relationships/MorphTo.py +3 -0
  16. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/schema/platforms/MSSQLPlatform.py +18 -10
  17. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/schema/platforms/MySQLPlatform.py +40 -28
  18. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/schema/platforms/PostgresPlatform.py +28 -16
  19. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/schema/platforms/SQLitePlatform.py +45 -33
  20. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/testing/BaseTestCaseSelectGrammar.py +15 -0
  21. masonite-orm-2.23.1/src/masoniteorm/relationships/HasManyThrough.py +0 -203
  22. masonite-orm-2.23.1/src/masoniteorm/relationships/HasOneThrough.py +0 -203
  23. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/MANIFEST.in +0 -0
  24. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/README.md +0 -0
  25. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/setup.cfg +0 -0
  26. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masonite_orm.egg-info/SOURCES.txt +0 -0
  27. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masonite_orm.egg-info/dependency_links.txt +0 -0
  28. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masonite_orm.egg-info/entry_points.txt +0 -0
  29. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masonite_orm.egg-info/requires.txt +0 -0
  30. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masonite_orm.egg-info/top_level.txt +0 -0
  31. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/__init__.py +0 -0
  32. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/collection/Collection.py +0 -0
  33. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/collection/__init__.py +0 -0
  34. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/commands/CanOverrideConfig.py +0 -0
  35. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/commands/CanOverrideOptionsDefault.py +0 -0
  36. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/commands/Command.py +0 -0
  37. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/commands/Entry.py +0 -0
  38. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/commands/MakeMigrationCommand.py +0 -0
  39. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/commands/MakeModelCommand.py +0 -0
  40. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/commands/MakeModelDocstringCommand.py +0 -0
  41. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/commands/MakeObserverCommand.py +0 -0
  42. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/commands/MakeSeedCommand.py +0 -0
  43. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/commands/MigrateCommand.py +0 -0
  44. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/commands/MigrateFreshCommand.py +0 -0
  45. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/commands/MigrateRefreshCommand.py +0 -0
  46. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/commands/MigrateResetCommand.py +0 -0
  47. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/commands/MigrateRollbackCommand.py +0 -0
  48. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/commands/MigrateStatusCommand.py +0 -0
  49. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/commands/SeedRunCommand.py +0 -0
  50. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/commands/ShellCommand.py +0 -0
  51. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/commands/__init__.py +0 -0
  52. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/commands/stubs/create_migration.stub +0 -0
  53. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/commands/stubs/create_seed.stub +0 -0
  54. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/commands/stubs/model.stub +0 -0
  55. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/commands/stubs/observer.stub +0 -0
  56. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/commands/stubs/table_migration.stub +0 -0
  57. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/config.py +0 -0
  58. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/connections/BaseConnection.py +0 -0
  59. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/connections/ConnectionFactory.py +0 -0
  60. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/connections/ConnectionResolver.py +0 -0
  61. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/connections/MSSQLConnection.py +0 -0
  62. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/connections/SQLiteConnection.py +0 -0
  63. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/connections/__init__.py +0 -0
  64. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/exceptions.py +0 -0
  65. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/expressions/__init__.py +0 -0
  66. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/expressions/expressions.py +0 -0
  67. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/factories/Factory.py +0 -0
  68. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/factories/__init__.py +0 -0
  69. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/helpers/__init__.py +0 -0
  70. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/helpers/misc.py +0 -0
  71. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/migrations/Migration.py +0 -0
  72. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/migrations/__init__.py +0 -0
  73. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/models/MigrationModel.py +0 -0
  74. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/models/Pivot.py +0 -0
  75. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/models/__init__.py +0 -0
  76. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/observers/ObservesEvents.py +0 -0
  77. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/observers/__init__.py +0 -0
  78. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/pagination/BasePaginator.py +0 -0
  79. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/pagination/LengthAwarePaginator.py +0 -0
  80. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/pagination/SimplePaginator.py +0 -0
  81. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/pagination/__init__.py +0 -0
  82. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/providers/ORMProvider.py +0 -0
  83. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/providers/__init__.py +0 -0
  84. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/query/EagerRelation.py +0 -0
  85. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/query/__init__.py +0 -0
  86. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/query/grammars/MSSQLGrammar.py +0 -0
  87. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/query/grammars/MySQLGrammar.py +0 -0
  88. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/query/grammars/PostgresGrammar.py +0 -0
  89. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/query/grammars/SQLiteGrammar.py +0 -0
  90. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/query/grammars/__init__.py +0 -0
  91. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/query/processors/MSSQLPostProcessor.py +0 -0
  92. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/query/processors/MySQLPostProcessor.py +0 -0
  93. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/query/processors/PostgresPostProcessor.py +0 -0
  94. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/query/processors/SQLitePostProcessor.py +0 -0
  95. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/query/processors/__init__.py +0 -0
  96. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/relationships/BelongsToMany.py +0 -0
  97. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/relationships/MorphMany.py +0 -0
  98. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/relationships/MorphOne.py +0 -0
  99. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/relationships/MorphToMany.py +0 -0
  100. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/relationships/__init__.py +0 -0
  101. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/schema/Blueprint.py +0 -0
  102. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/schema/Column.py +0 -0
  103. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/schema/ColumnDiff.py +0 -0
  104. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/schema/Constraint.py +0 -0
  105. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/schema/ForeignKeyConstraint.py +0 -0
  106. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/schema/Index.py +0 -0
  107. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/schema/Schema.py +0 -0
  108. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/schema/Table.py +0 -0
  109. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/schema/TableDiff.py +0 -0
  110. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/schema/__init__.py +0 -0
  111. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/schema/platforms/Platform.py +0 -0
  112. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/schema/platforms/__init__.py +0 -0
  113. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/scopes/BaseScope.py +0 -0
  114. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/scopes/SoftDeleteScope.py +0 -0
  115. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/scopes/SoftDeletesMixin.py +0 -0
  116. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/scopes/TimeStampsMixin.py +0 -0
  117. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/scopes/TimeStampsScope.py +0 -0
  118. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/scopes/UUIDPrimaryKeyMixin.py +0 -0
  119. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/scopes/UUIDPrimaryKeyScope.py +0 -0
  120. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/scopes/__init__.py +0 -0
  121. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/scopes/scope.py +0 -0
  122. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/seeds/Seeder.py +0 -0
  123. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/seeds/__init__.py +0 -0
  124. {masonite-orm-2.23.1 → masonite-orm-2.23.2}/src/masoniteorm/testing/__init__.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: masonite-orm
3
- Version: 2.23.1
3
+ Version: 2.23.2
4
4
  Summary: The Official Masonite ORM
5
5
  Home-page: https://github.com/masoniteframework/orm
6
6
  Author: Joe Mancuso
@@ -8,7 +8,7 @@ setup(
8
8
  # Versions should comply with PEP440. For a discussion on single-sourcing
9
9
  # the version across setup.py and the project code, see
10
10
  # https://packaging.python.org/en/latest/single_source_version.html
11
- version="2.23.1",
11
+ version="2.23.2",
12
12
  package_dir={"": "src"},
13
13
  description="The Official Masonite ORM",
14
14
  long_description=long_description,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: masonite-orm
3
- Version: 2.23.1
3
+ Version: 2.23.2
4
4
  Summary: The Official Masonite ORM
5
5
  Home-page: https://github.com/masoniteframework/orm
6
6
  Author: Joe Mancuso
@@ -31,10 +31,12 @@ class MySQLConnection(BaseConnection):
31
31
  if str(port).isdigit():
32
32
  self.port = int(self.port)
33
33
  self.database = database
34
+
34
35
  self.user = user
35
36
  self.password = password
36
37
  self.prefix = prefix
37
38
  self.full_details = full_details or {}
39
+ self.connection_pool_size = full_details.get("connection_pooling_max_size", 100)
38
40
  self.options = options or {}
39
41
  self._cursor = None
40
42
  self.open = 0
@@ -48,42 +50,80 @@ class MySQLConnection(BaseConnection):
48
50
  if self._dry:
49
51
  return
50
52
 
53
+ if self.has_global_connection():
54
+ return self.get_global_connection()
55
+
56
+ # Check if there is an available connection in the pool
57
+ self._connection = self.create_connection()
58
+ self.enable_disable_foreign_keys()
59
+
60
+ return self
61
+
62
+ def close_connection(self):
63
+ if (
64
+ self.full_details.get("connection_pooling_enabled")
65
+ and len(CONNECTION_POOL) < self.connection_pool_size
66
+ ):
67
+ CONNECTION_POOL.append(self._connection)
68
+ self.open = 0
69
+ self._connection = None
70
+
71
+ def create_connection(self, autocommit=True):
72
+
51
73
  try:
52
74
  import pymysql
53
75
  except ModuleNotFoundError:
54
76
  raise DriverNotFound(
55
- "You must have the 'pymysql' package installed to make a connection to MySQL. Please install it using 'pip install pymysql'"
77
+ "You must have the 'pymysql' package "
78
+ "installed to make a connection to MySQL. "
79
+ "Please install it using 'pip install pymysql'"
56
80
  )
81
+ import pendulum
82
+ import pymysql.converters
57
83
 
58
- try:
59
- import pendulum
60
- import pymysql.converters
61
-
62
- pymysql.converters.conversions[
63
- pendulum.DateTime
64
- ] = pymysql.converters.escape_datetime
65
- except ImportError:
66
- pass
67
-
68
- if self.has_global_connection():
69
- return self.get_global_connection()
70
-
71
- self._connection = pymysql.connect(
72
- cursorclass=pymysql.cursors.DictCursor,
73
- autocommit=True,
74
- host=self.host,
75
- user=self.user,
76
- password=self.password,
77
- port=self.port,
78
- db=self.database,
79
- **self.options
84
+ pymysql.converters.conversions[pendulum.DateTime] = (
85
+ pymysql.converters.escape_datetime
80
86
  )
81
87
 
82
- self.enable_disable_foreign_keys()
88
+ # Initialize the connection pool if the option is set
89
+ initialize_size = self.full_details.get("connection_pooling_min_size")
90
+ if initialize_size and len(CONNECTION_POOL) < initialize_size:
91
+ for _ in range(initialize_size - len(CONNECTION_POOL)):
92
+ connection = pymysql.connect(
93
+ cursorclass=pymysql.cursors.DictCursor,
94
+ autocommit=autocommit,
95
+ host=self.host,
96
+ user=self.user,
97
+ password=self.password,
98
+ port=self.port,
99
+ database=self.database,
100
+ **self.options
101
+ )
102
+ CONNECTION_POOL.append(connection)
103
+
104
+ if (
105
+ self.full_details.get("connection_pooling_enabled")
106
+ and CONNECTION_POOL
107
+ and len(CONNECTION_POOL) > 0
108
+ ):
109
+ connection = CONNECTION_POOL.pop()
110
+ else:
111
+ connection = pymysql.connect(
112
+ cursorclass=pymysql.cursors.DictCursor,
113
+ autocommit=autocommit,
114
+ host=self.host,
115
+ user=self.user,
116
+ password=self.password,
117
+ port=self.port,
118
+ database=self.database,
119
+ **self.options
120
+ )
121
+
122
+ connection.close = self.close_connection
83
123
 
84
124
  self.open = 1
85
125
 
86
- return self
126
+ return connection
87
127
 
88
128
  def reconnect(self):
89
129
  self._connection.connect()
@@ -139,15 +179,19 @@ class MySQLConnection(BaseConnection):
139
179
  return self._cursor
140
180
 
141
181
  def query(self, query, bindings=(), results="*"):
142
- """Make the actual query that will reach the database and come back with a result.
182
+ """Make the actual query that
183
+ will reach the database and come back with a result.
143
184
 
144
185
  Arguments:
145
- query {string} -- A string query. This could be a qmarked string or a regular query.
186
+ query {string} -- A string query.
187
+ This could be a qmarked string or a regular query.
146
188
  bindings {tuple} -- A tuple of bindings
147
189
 
148
190
  Keyword Arguments:
149
- results {str|1} -- If the results is equal to an asterisks it will call 'fetchAll'
150
- else it will return 'fetchOne' and return a single record. (default: {"*"})
191
+ results {str|1} -- If the results is equal to an
192
+ asterisks it will call 'fetchAll'
193
+ else it will return 'fetchOne' and
194
+ return a single record. (default: {"*"})
151
195
 
152
196
  Returns:
153
197
  dict|None -- Returns a dictionary of results or None
@@ -156,7 +200,10 @@ class MySQLConnection(BaseConnection):
156
200
  if self._dry:
157
201
  return {}
158
202
 
159
- if not self._connection.open:
203
+ if not self.open:
204
+ if self._connection is None:
205
+ self._connection = self.create_connection()
206
+
160
207
  self._connection.connect()
161
208
 
162
209
  self._cursor = self._connection.cursor()
@@ -34,8 +34,10 @@ class PostgresConnection(BaseConnection):
34
34
  self.database = database
35
35
  self.user = user
36
36
  self.password = password
37
+
37
38
  self.prefix = prefix
38
39
  self.full_details = full_details or {}
40
+ self.connection_pool_size = full_details.get("connection_pooling_max_size", 100)
39
41
  self.options = options or {}
40
42
  self._cursor = None
41
43
  self.transaction_level = 0
@@ -56,16 +58,7 @@ class PostgresConnection(BaseConnection):
56
58
  if self.has_global_connection():
57
59
  return self.get_global_connection()
58
60
 
59
- schema = self.schema or self.full_details.get("schema")
60
-
61
- self._connection = psycopg2.connect(
62
- database=self.database,
63
- user=self.user,
64
- password=self.password,
65
- host=self.host,
66
- port=self.port,
67
- options=f"-c search_path={schema}" if schema else "",
68
- )
61
+ self._connection = self.create_connection()
69
62
 
70
63
  self._connection.autocommit = True
71
64
 
@@ -75,6 +68,61 @@ class PostgresConnection(BaseConnection):
75
68
 
76
69
  return self
77
70
 
71
+ def create_connection(self):
72
+ import psycopg2
73
+
74
+ # Initialize the connection pool if the option is set
75
+ initialize_size = self.full_details.get("connection_pooling_min_size")
76
+ if (
77
+ self.full_details.get("connection_pooling_enabled")
78
+ and initialize_size
79
+ and len(CONNECTION_POOL) < initialize_size
80
+ ):
81
+ for _ in range(initialize_size - len(CONNECTION_POOL)):
82
+ connection = psycopg2.connect(
83
+ database=self.database,
84
+ user=self.user,
85
+ password=self.password,
86
+ host=self.host,
87
+ port=self.port,
88
+ sslmode=self.options.get("sslmode"),
89
+ sslcert=self.options.get("sslcert"),
90
+ sslkey=self.options.get("sslkey"),
91
+ sslrootcert=self.options.get("sslrootcert"),
92
+ options=(
93
+ f"-c search_path={self.schema or self.full_details.get('schema')}"
94
+ if self.schema or self.full_details.get("schema")
95
+ else ""
96
+ ),
97
+ )
98
+ CONNECTION_POOL.append(connection)
99
+
100
+ if (
101
+ self.full_details.get("connection_pooling_enabled")
102
+ and CONNECTION_POOL
103
+ and len(CONNECTION_POOL) > 0
104
+ ):
105
+ connection = CONNECTION_POOL.pop()
106
+ else:
107
+ connection = psycopg2.connect(
108
+ database=self.database,
109
+ user=self.user,
110
+ password=self.password,
111
+ host=self.host,
112
+ port=self.port,
113
+ sslmode=self.options.get("sslmode"),
114
+ sslcert=self.options.get("sslcert"),
115
+ sslkey=self.options.get("sslkey"),
116
+ sslrootcert=self.options.get("sslrootcert"),
117
+ options=(
118
+ f"-c search_path={self.schema or self.full_details.get('schema')}"
119
+ if self.schema or self.full_details.get("schema")
120
+ else ""
121
+ ),
122
+ )
123
+
124
+ return connection
125
+
78
126
  def get_database_name(self):
79
127
  return self.database
80
128
 
@@ -93,6 +141,17 @@ class PostgresConnection(BaseConnection):
93
141
  def reconnect(self):
94
142
  pass
95
143
 
144
+ def close_connection(self):
145
+ if (
146
+ self.full_details.get("connection_pooling_enabled")
147
+ and len(CONNECTION_POOL) < self.connection_pool_size
148
+ ):
149
+ CONNECTION_POOL.append(self._connection)
150
+ else:
151
+ self._connection.close()
152
+
153
+ self._connection = None
154
+
96
155
  def commit(self):
97
156
  """Transaction"""
98
157
  if self.get_transaction_level() == 1:
@@ -140,7 +199,7 @@ class PostgresConnection(BaseConnection):
140
199
  dict|None -- Returns a dictionary of results or None
141
200
  """
142
201
  try:
143
- if self._connection.closed:
202
+ if not self._connection or self._connection.closed:
144
203
  self.make_connection()
145
204
 
146
205
  self.set_cursor()
@@ -164,4 +223,5 @@ class PostgresConnection(BaseConnection):
164
223
  finally:
165
224
  if self.get_transaction_level() <= 0:
166
225
  self.open = 0
167
- self._connection.close()
226
+ self.close_connection()
227
+ # self._connection.close()
@@ -354,7 +354,10 @@ class Model(TimeStampsMixin, ObservesEvents, metaclass=ModelMeta):
354
354
  dry=self.__dry__,
355
355
  )
356
356
 
357
- return self.builder.select(*self.__selects__)
357
+ return self.builder.select(*self.get_selects())
358
+
359
+ def get_selects(self):
360
+ return self.__selects__
358
361
 
359
362
  @classmethod
360
363
  def get_columns(cls):
@@ -426,12 +429,12 @@ class Model(TimeStampsMixin, ObservesEvents, metaclass=ModelMeta):
426
429
  builder = cls().where(cls.get_primary_key(), record_id)
427
430
 
428
431
  if query:
429
- return builder.to_sql()
432
+ return builder
430
433
  else:
431
434
  if isinstance(record_id, (list, tuple)):
432
435
  return builder.get()
433
436
 
434
- return builder.first()
437
+ return builder.first()
435
438
 
436
439
  @classmethod
437
440
  def find_or_fail(cls, record_id, query=False):
@@ -560,9 +563,7 @@ class Model(TimeStampsMixin, ObservesEvents, metaclass=ModelMeta):
560
563
  self: A hydrated version of a model
561
564
  """
562
565
  if query:
563
- return cls.builder.create(
564
- dictionary, query=True, cast=cast, **kwargs
565
- ).to_sql()
566
+ return cls.builder.create(dictionary, query=True, cast=cast, **kwargs)
566
567
 
567
568
  return cls.builder.create(dictionary, cast=cast, **kwargs)
568
569
 
@@ -897,7 +898,7 @@ class Model(TimeStampsMixin, ObservesEvents, metaclass=ModelMeta):
897
898
  if self.is_loaded():
898
899
  result = builder.update(
899
900
  self.__dirty_attributes__, dry=query, ignore_mass_assignment=True
900
- ).to_sql()
901
+ )
901
902
  else:
902
903
  result = self.create(self.__dirty_attributes__, query=query)
903
904
 
@@ -1710,15 +1710,12 @@ class QueryBuilder(ObservesEvents):
1710
1710
  if not fields:
1711
1711
  fields = []
1712
1712
 
1713
- if fields:
1714
- self.select(fields)
1713
+ self.select(fields).limit(1)
1715
1714
 
1716
1715
  if query:
1717
- return self.limit(1)
1716
+ return self
1718
1717
 
1719
- result = self.new_connection().query(
1720
- self.limit(1).to_qmark(), self._bindings, results=1
1721
- )
1718
+ result = self.new_connection().query(self.to_qmark(), self._bindings, results=1)
1722
1719
 
1723
1720
  return self.prepare_result(result)
1724
1721
 
@@ -1778,11 +1775,13 @@ class QueryBuilder(ObservesEvents):
1778
1775
  dictionary -- Returns a dictionary of results.
1779
1776
  """
1780
1777
  _column = column if column else self._model.get_primary_key()
1778
+ self.limit(1).order_by(_column, direction="DESC")
1779
+
1781
1780
  if query:
1782
- return self.limit(1).order_by(_column, direction="DESC")
1781
+ return self
1783
1782
 
1784
1783
  result = self.new_connection().query(
1785
- self.limit(1).order_by(_column, direction="DESC").to_qmark(),
1784
+ self.to_qmark(),
1786
1785
  self._bindings,
1787
1786
  results=1,
1788
1787
  )
@@ -1792,7 +1791,7 @@ class QueryBuilder(ObservesEvents):
1792
1791
  def _get_eager_load_result(self, related, collection):
1793
1792
  return related.eager_load_from_collection(collection)
1794
1793
 
1795
- def find(self, record_id):
1794
+ def find(self, record_id, query=False):
1796
1795
  """Finds a row by the primary key ID. Requires a model
1797
1796
 
1798
1797
  Arguments:
@@ -1801,8 +1800,12 @@ class QueryBuilder(ObservesEvents):
1801
1800
  Returns:
1802
1801
  Model|None
1803
1802
  """
1803
+ self.where(self._model.get_primary_key(), record_id)
1804
1804
 
1805
- return self.where(self._model.get_primary_key(), record_id).first()
1805
+ if query:
1806
+ return self
1807
+
1808
+ return self.first()
1806
1809
 
1807
1810
  def find_or(self, record_id: int, callback: Callable, args=None):
1808
1811
  """Finds a row by the primary key ID (Requires a model) or raise a ModelNotFound exception.
@@ -1868,7 +1871,7 @@ class QueryBuilder(ObservesEvents):
1868
1871
  """
1869
1872
 
1870
1873
  if query:
1871
- return self.limit(1)
1874
+ return self.first(query=True)
1872
1875
 
1873
1876
  result = self.first()
1874
1877
 
@@ -1963,10 +1966,7 @@ class QueryBuilder(ObservesEvents):
1963
1966
  return self
1964
1967
 
1965
1968
  def _map_related(self, related_result, related):
1966
- if related.__class__.__name__ == 'MorphTo':
1967
- return related_result
1968
-
1969
- return related_result.group_by(related.foreign_key)
1969
+ return related.map_related(related_result)
1970
1970
 
1971
1971
  def all(self, selects=[], query=False):
1972
1972
  """Returns all records from the table.
@@ -1974,9 +1974,11 @@ class QueryBuilder(ObservesEvents):
1974
1974
  Returns:
1975
1975
  dictionary -- Returns a dictionary of results.
1976
1976
  """
1977
+
1977
1978
  self.select(*selects)
1979
+
1978
1980
  if query:
1979
- return self.to_sql()
1981
+ return self
1980
1982
 
1981
1983
  result = self.new_connection().query(self.to_qmark(), self._bindings) or []
1982
1984
 
@@ -2088,9 +2090,8 @@ class QueryBuilder(ObservesEvents):
2088
2090
  Returns:
2089
2091
  self
2090
2092
  """
2091
- for name, scope in self._global_scopes.get(self._action, {}).items():
2092
- scope(self)
2093
2093
 
2094
+ self.run_scopes()
2094
2095
  grammar = self.get_grammar()
2095
2096
  sql = grammar.compile(self._action, qmark=False).to_sql()
2096
2097
  return sql
@@ -2117,11 +2118,9 @@ class QueryBuilder(ObservesEvents):
2117
2118
  Returns:
2118
2119
  self
2119
2120
  """
2120
- for name, scope in self._global_scopes.get(self._action, {}).items():
2121
- scope(self)
2122
2121
 
2122
+ self.run_scopes()
2123
2123
  grammar = self.get_grammar()
2124
-
2125
2124
  sql = grammar.compile(self._action, qmark=True).to_sql()
2126
2125
 
2127
2126
  self._bindings = grammar._bindings
@@ -10,7 +10,6 @@ from ...expressions.expressions import (
10
10
 
11
11
 
12
12
  class BaseGrammar:
13
-
14
13
  """The keys in this dictionary is how the ORM will reference these aggregates
15
14
 
16
15
  The values on the right are the matching functions for the grammar
@@ -251,13 +250,13 @@ class BaseGrammar:
251
250
  on_string += f"{keyword} {self._table_column_string(clause.column1)} {clause.equality} {self._table_column_string(clause.column2)} "
252
251
  else:
253
252
  if clause.value_type == "NULL":
254
- sql_string = self.where_null_string()
253
+ sql_string = f"{self.where_null_string()} "
255
254
  on_string += sql_string.format(
256
255
  keyword=keyword,
257
256
  column=self.process_column(clause.column),
258
257
  )
259
258
  elif clause.value_type == "NOT NULL":
260
- sql_string = self.where_not_null_string()
259
+ sql_string = f"{self.where_not_null_string()} "
261
260
  on_string += sql_string.format(
262
261
  keyword=keyword,
263
262
  column=self.process_column(clause.column),
@@ -193,3 +193,6 @@ class BaseRelationship:
193
193
  )
194
194
 
195
195
  return related_builder
196
+
197
+ def map_related(self, related_result):
198
+ return related_result
@@ -66,3 +66,6 @@ class BelongsTo(BaseRelationship):
66
66
  related = collection.get(getattr(model, self.local_key), None)
67
67
 
68
68
  model.add_relation({key: related[0] if related else None})
69
+
70
+ def map_related(self, related_result):
71
+ return related_result.group_by(self.foreign_key)
@@ -30,3 +30,6 @@ class HasMany(BaseRelationship):
30
30
  model.add_relation(
31
31
  {key: collection.get(getattr(model, self.local_key)) or Collection()}
32
32
  )
33
+
34
+ def map_related(self, related_result):
35
+ return related_result.group_by(self.foreign_key)