From a0f29eb5b8524736f7de6a5f7fd47c0e5cc6e2e7 Mon Sep 17 00:00:00 2001 From: Untone Date: Fri, 1 Nov 2024 20:11:58 +0300 Subject: [PATCH] json-builder-compat --- resolvers/reader.py | 16 ++++++++-------- services/db.py | 18 +++++++++++++++++- 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/resolvers/reader.py b/resolvers/reader.py index c76d3847..081be088 100644 --- a/resolvers/reader.py +++ b/resolvers/reader.py @@ -7,7 +7,7 @@ from orm.author import Author from orm.reaction import Reaction, ReactionKind from orm.shout import Shout, ShoutAuthor, ShoutTopic from orm.topic import Topic -from services.db import local_session +from services.db import local_session, json_builder, json_array_builder from services.schema import query from services.search import search_text from services.viewed import ViewedStorage @@ -71,7 +71,7 @@ def query_with_stat(info): # main_author q = q.join(main_author, main_author.id == Shout.created_by) q = q.add_columns( - func.json_object( + json_builder( 'id', main_author.id, 'name', main_author.name, 'slug', main_author.slug, @@ -92,7 +92,7 @@ def query_with_stat(info): main_topic.id == main_topic_join.topic ) q = q.add_columns( - func.json_object( + json_builder( 'id', main_topic.id, 'title', main_topic.title, 'slug', main_topic.slug, @@ -103,8 +103,8 @@ def query_with_stat(info): if has_field(info, "topics"): topics_subquery = ( select( - func.json_group_array( - func.json_object( + json_array_builder( + json_builder( 'id', Topic.id, 'title', Topic.title, 'slug', Topic.slug, @@ -122,8 +122,8 @@ def query_with_stat(info): if has_field(info, "authors"): authors_subquery = ( select( - func.json_group_array( - func.json_object( + json_array_builder( + json_builder( 'id', Author.id, 'name', Author.name, 'slug', Author.slug, @@ -175,7 +175,7 @@ def query_with_stat(info): q = q.outerjoin(stats_subquery, stats_subquery.c.shout == Shout.id) # aggregate in one column q = q.add_columns( - func.json_object( + json_builder( 'comments_count', stats_subquery.c.comments_count, 'rating', stats_subquery.c.rating, 'last_reacted_at', stats_subquery.c.last_reacted_at, diff --git a/services/db.py b/services/db.py index 5a689da4..c351122e 100644 --- a/services/db.py +++ b/services/db.py @@ -5,7 +5,7 @@ import traceback import warnings from typing import Any, Callable, Dict, TypeVar -from sqlalchemy import JSON, Column, Engine, Integer, create_engine, event, exc, inspect +from sqlalchemy import JSON, Column, Engine, Integer, create_engine, event, exc, func, inspect from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import Session, configure_mappers from sqlalchemy.sql.schema import Table @@ -148,3 +148,19 @@ def after_cursor_execute(conn, cursor, statement, parameters, context, executema logger.debug("*" * (elapsed_n)) logger.debug(f"{elapsed:.3f} s") del conn.cursor_id # Удаление идентификатора курсора после выполнения + + +def get_json_builder(): + """ + Возвращает подходящие функции для построения JSON объектов в зависимости от драйвера БД + """ + dialect = engine.dialect.name + if dialect.startswith('postgres'): + return func.json_build_object, func.json_agg + elif dialect.startswith('sqlite') or dialect.startswith('mysql'): + return func.json_object, func.json_group_array + else: + raise NotImplementedError(f"JSON builder not implemented for dialect {dialect}") + +# Используем их в коде +json_builder, json_array_builder = get_json_builder() \ No newline at end of file