1313
1414use Cycle \Database \Driver \Compiler ;
1515use Cycle \Database \Driver \Quoter ;
16+ use Cycle \Database \Query \Enum \LockMode ;
17+ use Cycle \Database \Query \Enum \LockBehavior ;
1618use Cycle \Database \Driver \SQLServer \Injection \CompileJson ;
1719use Cycle \Database \Injection \Fragment ;
1820use Cycle \Database \Injection \FragmentInterface ;
@@ -164,6 +166,42 @@ protected function compileJsonOrderBy(string $path): FragmentInterface
164166 return new CompileJson ($ path );
165167 }
166168
169+ /**
170+ * @param array{mode: LockMode, behavior: LockBehavior}|null $forUpdate
171+ */
172+ protected function forUpdate (?array $ forUpdate ): string
173+ {
174+ if ($ forUpdate !== null ) {
175+ $ arguments = [];
176+
177+ switch ($ forUpdate ['mode ' ]) {
178+ case LockMode::Share:
179+ case LockMode::KeyShare:
180+ $ arguments [] = 'HOLDLOCK ' ;
181+ break ;
182+ case LockMode::Update:
183+ case LockMode::NoKeyUpdate:
184+ $ arguments [] = 'UPDLOCK ' ;
185+ break ;
186+ }
187+
188+ switch ($ forUpdate ['behavior ' ]) {
189+ case LockBehavior::Wait:
190+ break ;
191+ case LockBehavior::NoWait:
192+ $ arguments [] = 'NOWAIT ' ;
193+ break ;
194+ case LockBehavior::SkipLocked:
195+ $ arguments [] = 'READPAST ' ;
196+ break ;
197+ }
198+
199+ return \sprintf ('WITH(%s) ' , \implode (', ' , $ arguments ));
200+ }
201+
202+ return '' ;
203+ }
204+
167205 private function baseSelect (QueryParameters $ params , Quoter $ q , array $ tokens ): string
168206 {
169207 // This statement(s) parts should be processed first to define set of table and column aliases
@@ -175,12 +213,14 @@ private function baseSelect(QueryParameters $params, Quoter $q, array $tokens):
175213 $ this ->nameWithAlias (new QueryParameters (), $ q , $ join ['outer ' ], $ join ['alias ' ], true );
176214 }
177215
216+
217+
178218 return \sprintf (
179219 "SELECT%s %s \nFROM %s%s%s%s%s%s%s%s%s%s%s " ,
180220 $ this ->optional (' ' , $ this ->distinct ($ params , $ q , $ tokens ['distinct ' ])),
181221 $ this ->columns ($ params , $ q , $ tokens ['columns ' ]),
182222 \implode (', ' , $ tables ),
183- $ this ->optional (' ' , $ tokens ['forUpdate ' ] ? ' WITH (UPDLOCK,ROWLOCK) ' : '' , ' ' ),
223+ $ this ->optional (' ' , $ this -> forUpdate ( $ tokens ['forUpdate ' ]) , ' ' ),
184224 $ this ->optional (' ' , $ this ->joins ($ params , $ q , $ tokens ['join ' ]), ' ' ),
185225 $ this ->optional ("\nWHERE " , $ this ->where ($ params , $ q , $ tokens ['where ' ])),
186226 $ this ->optional ("\nGROUP BY " , $ this ->groupBy ($ params , $ q , $ tokens ['groupBy ' ]), ' ' ),
0 commit comments