/** * WPML compatibility functions * * @global array $duplicated_posts Array to store the posts being duplicated. * * @package Yoast\WP\Duplicate_Post * @since 3.2 */ add_action( 'admin_init', 'duplicate_post_wpml_init' ); /** * Add handlers for WPML compatibility. */ function duplicate_post_wpml_init() { if ( defined( 'ICL_SITEPRESS_VERSION' ) ) { add_action( 'dp_duplicate_page', 'duplicate_post_wpml_copy_translations', 10, 3 ); add_action( 'dp_duplicate_post', 'duplicate_post_wpml_copy_translations', 10, 3 ); add_action( 'shutdown', 'duplicate_wpml_string_packages', 11 ); } } global $duplicated_posts; // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals -- Reason: Renaming a global variable is a BC break. $duplicated_posts = []; /** * Copy post translations. * * @global SitePress $sitepress Instance of the Main WPML class. * @global array $duplicated_posts Array of duplicated posts. * * @param int $post_id ID of the copy. * @param WP_Post $post Original post object. * @param string $status Status of the new post. */ function duplicate_post_wpml_copy_translations( $post_id, $post, $status = '' ) { global $sitepress; global $duplicated_posts; remove_action( 'dp_duplicate_page', 'duplicate_post_wpml_copy_translations', 10 ); remove_action( 'dp_duplicate_post', 'duplicate_post_wpml_copy_translations', 10 ); $current_language = $sitepress->get_current_language(); $trid = $sitepress->get_element_trid( $post->ID ); if ( ! empty( $trid ) ) { $translations = $sitepress->get_element_translations( $trid ); $new_trid = $sitepress->get_element_trid( $post_id ); foreach ( $translations as $code => $details ) { if ( $code !== $current_language ) { if ( $details->element_id ) { $translation = get_post( $details->element_id ); if ( ! $translation ) { continue; } $new_post_id = duplicate_post_create_duplicate( $translation, $status ); if ( ! is_wp_error( $new_post_id ) ) { $sitepress->set_element_language_details( $new_post_id, 'post_' . $translation->post_type, $new_trid, $code, $current_language ); } } } } // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals -- Reason: see above. $duplicated_posts[ $post->ID ] = $post_id; } } /** * Duplicate string packages. * * @global array() $duplicated_posts Array of duplicated posts. */ function duplicate_wpml_string_packages() { // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals -- Reason: renaming the function would be a BC-break. global $duplicated_posts; foreach ( $duplicated_posts as $original_post_id => $duplicate_post_id ) { // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals -- Reason: using WPML native filter. $original_string_packages = apply_filters( 'wpml_st_get_post_string_packages', false, $original_post_id ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals -- Reason: using WPML native filter. $new_string_packages = apply_filters( 'wpml_st_get_post_string_packages', false, $duplicate_post_id ); if ( is_array( $original_string_packages ) ) { foreach ( $original_string_packages as $original_string_package ) { $translated_original_strings = $original_string_package->get_translated_strings( [] ); foreach ( $new_string_packages as $new_string_package ) { $cache = new WPML_WP_Cache( 'WPML_Package' ); $cache->flush_group_cache(); $new_strings = $new_string_package->get_package_strings(); foreach ( $new_strings as $new_string ) { if ( isset( $translated_original_strings[ $new_string->name ] ) ) { foreach ( $translated_original_strings[ $new_string->name ] as $language => $translated_string ) { do_action( // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals -- Reason: using WPML native filter. 'wpml_add_string_translation', $new_string->id, $language, $translated_string['value'], $translated_string['status'] ); } } } } } } } } api/app/routers/sql.py – Raqqa

api/app/routers/sql.py

新規で作成するファイル

  1. api/app/services/odoo_db.py
  • Odoo DB(postgres/odoo)の接続生成(psycopg2直なら connect/close・タイムアウト指定・アプリ名など)を一箇所に集約
  1. api/app/services/odoo_sql_executor.py
  • BEGIN → SET LOCAL(statement_timeout等)→ 実行 → fetch → COMMIT/ROLLBACK をここに実装
  • max_rows / fetch_size / truncated などの実行制御もここに寄せる
  1. api/app/utils/sql_result_codec.py
  • cursor.description から **columns(name/typeなど)**を組み立て
  • rows の **JSON化(Decimal/datetime/UUID など)**を担当(APIの返却を安定化)
  1. api/tests/test_sql_execute_params_non_dry_run.py(または同等のテストファイル)
  • “軽いSELECTでrowsが返る”
  • “statement_timeoutで止まる”
    の最低2ケースを固める(統合寄りでもOK)

※「sqlガード(SELECTのみ等)」がPhase7Aで既に別ファイルなら新規不要。無ければ api/app/services/sql_guard.py を新規で切るのが安全です。


修正する既存のファイル

  1. api/app/routers/sql.py(/sql/execute_params のルータがある前提)
  • options.dry_run=false の分岐を追加して odoo_sql_executor を呼ぶ
  • 例外(statement_timeout等)を Problem+JSON にマップして返す
  1. api/app/schemas/sql_execute_params.py(または該当する schemas)
  • レスポンスに columns, rows, row_count を追加
  • 併せて optionstimeout/max_rows 等を追加(必要なら)
  1. api/app/config.py(Settings)
  • Odoo DB接続用ENV(ODOO_DB_HOST/PORT/NAME/USER/PASSWORD
  • 実行制御ENV(SQL_STATEMENT_TIMEOUT_MS, SQL_LOCK_TIMEOUT_MS, SQL_IDLE_TX_TIMEOUT_MS, SQL_MAX_ROWS など)
    を追加
  1. k8s/.../portal-api/*(ConfigMap / Secret / Deployment のenv)
  • ODOO_DB_*SQL_* デフォルト値を注入
  • パスワードは Secret、それ以外は ConfigMap が基本
  1. api/requirements.txt(必要な場合のみ)
  • psycopg2直実装にするなら psycopg2-binary が確実に入っているか確認し、無ければ追記

最小構成(最初のPRでやる範囲)

  • 新規:odoo_db.py, odoo_sql_executor.py, sql_result_codec.py
  • 修正:routers/sql.py, schemas/sql_execute_params.py, config.py, k8s env

了解。いまの Phase 7B(Odoo DB 実行+env 注入)観点で、dev overlay 配下で“修正が必要そう”なファイルは次の4つです(優先順)。

  1. k8s/overlays/dev/kustomization.yaml
  • base/portal-api に追加した secret-odoo-db-auth.yaml を dev overlay が取り込むかで差分が出ます。
  • ここが取り込めてないと odoo-db-auth が無くて Pod が起動しません。
  1. k8s/overlays/dev/patch-api-env.yaml
  • dev overlay が env を “上書き” している場合、ODOO_DB_ / SQL_ の追加・整合**が必要です。
  • 特に CHROMA_COLLECTION_VIEW_JA vs CHROMA_COLLECTION_VIEW_COMMON_JA の扱いもここで吸収できます。
  1. k8s/overlays/dev/patch-api-env-from-secret.yaml
  • envFrom / secretRef 方式で DB系をまとめて入れている場合、ODDO_DB_PASSWORD を読む Secret を追加するのはここが自然です(今は deployment の env に直で secretKeyRef を足したけど、overlayが上書きするならこちらに寄せる必要あり)。
  1. k8s/overlays/dev/patch-api-replicas.yaml(必要なら)
  • 7Bのデバッグ中は replicas=1 が楽、という運用調整が必要ならここ。

Comments

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です