aiteamutils 0.2.162__py3-none-any.whl → 0.2.163__py3-none-any.whl
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.
aiteamutils/database.py
CHANGED
@@ -8,7 +8,8 @@ from typing import (
|
|
8
8
|
List,
|
9
9
|
Optional,
|
10
10
|
AsyncGenerator,
|
11
|
-
Union
|
11
|
+
Union,
|
12
|
+
Tuple
|
12
13
|
)
|
13
14
|
from sqlalchemy.ext.asyncio import AsyncSession
|
14
15
|
from sqlalchemy import select, and_, or_
|
@@ -20,12 +21,19 @@ from sqlalchemy.ext.asyncio import AsyncSession
|
|
20
21
|
from fastapi import Request
|
21
22
|
from ulid import ULID
|
22
23
|
from sqlalchemy import MetaData, Table, insert
|
24
|
+
from sqlalchemy.sql.elements import BinaryExpression
|
23
25
|
|
24
26
|
#패키지 라이브러리
|
25
27
|
from .exceptions import ErrorCode, CustomException
|
26
28
|
|
27
29
|
ModelType = TypeVar("ModelType", bound=DeclarativeBase)
|
28
30
|
|
31
|
+
JoinTarget = Union[
|
32
|
+
DeclarativeBase, # 모델
|
33
|
+
Tuple[DeclarativeBase, BinaryExpression], # (모델, 조인 조건)
|
34
|
+
Tuple[DeclarativeBase, BinaryExpression, str] # (모델, 조인 조건, 조인 타입)
|
35
|
+
]
|
36
|
+
|
29
37
|
##################
|
30
38
|
# 전처리 #
|
31
39
|
##################
|
@@ -255,6 +263,61 @@ def build_conditions(
|
|
255
263
|
##################
|
256
264
|
# 쿼리 실행 #
|
257
265
|
##################
|
266
|
+
async def execute_query(
|
267
|
+
session: AsyncSession,
|
268
|
+
model: Type[ModelType],
|
269
|
+
explicit_joins: Optional[List[JoinTarget]] = None,
|
270
|
+
loading_joins: Optional[List[Any]] = None,
|
271
|
+
conditions: Optional[List[BinaryExpression]] = None,
|
272
|
+
) -> Select:
|
273
|
+
"""
|
274
|
+
쿼리 실행을 위한 공통 함수
|
275
|
+
|
276
|
+
Args:
|
277
|
+
session: 데이터베이스 세션
|
278
|
+
model: 기본 모델
|
279
|
+
explicit_joins: 명시적 조인 설정
|
280
|
+
- 모델만 전달: 기본 outer join
|
281
|
+
- (모델, 조건): 조건부 outer join
|
282
|
+
- (모델, 조건, 'inner'/'left'/'right'): 조인 타입 지정
|
283
|
+
loading_joins: Relationship 로딩 설정 (joinedload, selectinload 등)
|
284
|
+
conditions: WHERE 조건들
|
285
|
+
"""
|
286
|
+
# 1. 기본 쿼리 생성
|
287
|
+
query = select(model)
|
288
|
+
|
289
|
+
# 2. 명시적 조인 처리
|
290
|
+
if explicit_joins:
|
291
|
+
for join_target in explicit_joins:
|
292
|
+
if isinstance(join_target, DeclarativeBase):
|
293
|
+
# 모델만 전달된 경우
|
294
|
+
query = query.outerjoin(join_target)
|
295
|
+
elif isinstance(join_target, tuple):
|
296
|
+
if len(join_target) == 2:
|
297
|
+
# (모델, 조건)이 전달된 경우
|
298
|
+
target_model, join_condition = join_target
|
299
|
+
query = query.outerjoin(target_model, join_condition)
|
300
|
+
elif len(join_target) == 3:
|
301
|
+
# (모델, 조건, 조인타입)이 전달된 경우
|
302
|
+
target_model, join_condition, join_type = join_target
|
303
|
+
if join_type == 'inner':
|
304
|
+
query = query.join(target_model, join_condition)
|
305
|
+
elif join_type == 'left':
|
306
|
+
query = query.outerjoin(target_model, join_condition)
|
307
|
+
elif join_type == 'right':
|
308
|
+
query = query.outerjoin(target_model, join_condition, full=True)
|
309
|
+
|
310
|
+
# 3. Relationship 로딩 설정
|
311
|
+
if loading_joins:
|
312
|
+
for join_option in loading_joins:
|
313
|
+
query = query.options(join_option)
|
314
|
+
|
315
|
+
# 4. 조건 적용
|
316
|
+
if conditions:
|
317
|
+
query = query.where(and_(*conditions))
|
318
|
+
|
319
|
+
return query
|
320
|
+
|
258
321
|
async def create_entity(
|
259
322
|
session: AsyncSession,
|
260
323
|
model: Type[ModelType],
|
@@ -428,49 +491,22 @@ async def list_entities(
|
|
428
491
|
skip: int = 0,
|
429
492
|
limit: int = 100,
|
430
493
|
filters: Optional[List[Dict[str, Any]]] = None,
|
431
|
-
explicit_joins: Optional[List[
|
494
|
+
explicit_joins: Optional[List[JoinTarget]] = None,
|
432
495
|
loading_joins: Optional[List[Any]] = None,
|
433
496
|
order: Optional[List[Dict[str, str]]] = None
|
434
497
|
) -> List[Dict[str, Any]]:
|
435
|
-
"""
|
436
|
-
엔터티 리스트를 필터 및 조건에 따라 가져오는 함수.
|
437
|
-
|
438
|
-
Args:
|
439
|
-
session: SQLAlchemy AsyncSession.
|
440
|
-
model: SQLAlchemy 모델.
|
441
|
-
skip: 페이지네이션 시작 위치.
|
442
|
-
limit: 페이지네이션 크기.
|
443
|
-
filters: 필터 조건 딕셔너리.
|
444
|
-
예시:
|
445
|
-
filters = {
|
446
|
-
"search": {"field": "username", "operator": "like", "value": "%admin%"},
|
447
|
-
"name": {"field": "name", "operator": "like", "value": "%John%"},
|
448
|
-
"role_ulid": {"field": "role_ulid", "operator": "eq", "value": "1234"}
|
449
|
-
}
|
450
|
-
|
451
|
-
joins: 조인 옵션.
|
452
|
-
예시:
|
453
|
-
joins = [
|
454
|
-
selectinload(YourModel.related_field), # 관련된 필드를 함께 로드
|
455
|
-
joinedload(YourModel.another_related_field) # 다른 관계된 필드를 조인
|
456
|
-
]
|
457
|
-
|
458
|
-
Returns:
|
459
|
-
List[Dict[str, Any]]: 쿼리 결과 리스트.
|
460
|
-
"""
|
461
498
|
try:
|
499
|
+
# 필터 조건 생성
|
500
|
+
conditions = build_conditions(filters, model) if filters else None
|
501
|
+
|
462
502
|
# 기본 쿼리 생성
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
# 필터 조건 적용
|
471
|
-
if filters:
|
472
|
-
conditions = build_conditions(filters, model)
|
473
|
-
query = query.where(and_(*conditions))
|
503
|
+
query = await execute_query(
|
504
|
+
session=session,
|
505
|
+
model=model,
|
506
|
+
explicit_joins=explicit_joins,
|
507
|
+
loading_joins=loading_joins,
|
508
|
+
conditions=conditions
|
509
|
+
)
|
474
510
|
|
475
511
|
# 정렬 조건 적용
|
476
512
|
if order:
|
@@ -505,25 +541,21 @@ async def get_entity(
|
|
505
541
|
session: AsyncSession,
|
506
542
|
model: Type[ModelType],
|
507
543
|
conditions: Dict[str, Any],
|
508
|
-
explicit_joins: Optional[List[
|
544
|
+
explicit_joins: Optional[List[JoinTarget]] = None,
|
509
545
|
loading_joins: Optional[List[Any]] = None
|
510
546
|
) -> ModelType:
|
511
547
|
try:
|
512
|
-
|
513
|
-
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
if conditions:
|
525
|
-
for key, value in conditions.items():
|
526
|
-
query = query.where(getattr(model, key) == value)
|
548
|
+
# 조건을 리스트로 변환
|
549
|
+
condition_list = [getattr(model, key) == value for key, value in conditions.items()]
|
550
|
+
|
551
|
+
# 쿼리 실행
|
552
|
+
query = await execute_query(
|
553
|
+
session=session,
|
554
|
+
model=model,
|
555
|
+
explicit_joins=explicit_joins,
|
556
|
+
loading_joins=loading_joins,
|
557
|
+
conditions=condition_list
|
558
|
+
)
|
527
559
|
|
528
560
|
result = await session.execute(query)
|
529
561
|
return result.scalars().unique().one_or_none()
|
aiteamutils/version.py
CHANGED
@@ -1,2 +1,2 @@
|
|
1
1
|
"""버전 정보"""
|
2
|
-
__version__ = "0.2.
|
2
|
+
__version__ = "0.2.163"
|
@@ -4,13 +4,13 @@ aiteamutils/base_repository.py,sha256=Oy2zE1i5qx60Xf1tnsaKLyFWapiPqt5JH8NejwNrPW
|
|
4
4
|
aiteamutils/base_service.py,sha256=JIeRtFn1Ll4Qcq3v88pgS9lmEQLQoVyyOKqYR8n02S4,21192
|
5
5
|
aiteamutils/cache.py,sha256=07xBGlgAwOTAdY5mnMOQJ5EBxVwe8glVD7DkGEkxCtw,1373
|
6
6
|
aiteamutils/config.py,sha256=YdalpJb70-txhGJAS4aaKglEZAFVWgfzw5BXSWpkUz4,3232
|
7
|
-
aiteamutils/database.py,sha256=
|
7
|
+
aiteamutils/database.py,sha256=zXYhdUVgAisz4BuXZPPbvVLZ9lwRe7aVQP8J1AVE88Y,21771
|
8
8
|
aiteamutils/enums.py,sha256=7WLqlcJqQWtETAga2WAxNp3dJTQIAd2TW-4WzkoHHa8,2498
|
9
9
|
aiteamutils/exceptions.py,sha256=sgIVulllKMM9InTltaB7VD6i7DiQvCoycexsV-BiIBY,16570
|
10
10
|
aiteamutils/files.py,sha256=fxnCu9rErd4vCovMi0jy4adLUiA7rx_q4RdOL4wSgsU,14258
|
11
11
|
aiteamutils/security.py,sha256=McUl3t5Z5SyUDVUHymHdDkYyF4YSeg4g9fFMML4W6Kw,11630
|
12
12
|
aiteamutils/validators.py,sha256=_WHN6jqJQzKM5uPTg-Da8U2qqevS84XeKMkCCF4C_lY,9591
|
13
|
-
aiteamutils/version.py,sha256=
|
14
|
-
aiteamutils-0.2.
|
15
|
-
aiteamutils-0.2.
|
16
|
-
aiteamutils-0.2.
|
13
|
+
aiteamutils/version.py,sha256=MbP3Sxzx6eYugMlpPFw2qfjDxYmMdJwa_4K4MStAl1s,43
|
14
|
+
aiteamutils-0.2.163.dist-info/METADATA,sha256=pgSEMmDcvxJrKq3Y-CmLEuXgd2K5vKvm8SQfa3jIuvA,1743
|
15
|
+
aiteamutils-0.2.163.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
16
|
+
aiteamutils-0.2.163.dist-info/RECORD,,
|
File without changes
|