Skip to content

Commit 6f6533f

Browse files
committed
Fix import queries
1 parent 0228e56 commit 6f6533f

File tree

1 file changed

+72
-19
lines changed

1 file changed

+72
-19
lines changed

setup_staging_environment.py

Lines changed: 72 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,9 @@ def refresh_collation_version(self):
142142
cursor = conn.cursor()
143143

144144
db_name = self.staging_db_config["database"]
145-
cursor.execute(f'ALTER DATABASE "{db_name}" REFRESH COLLATION VERSION')
145+
cursor.execute(
146+
f'ALTER DATABASE "{db_name}" REFRESH COLLATION VERSION'
147+
)
146148
logger.info(f"✓ Refreshed collation version for database {db_name}")
147149

148150
except psycopg2.Error as e:
@@ -347,7 +349,9 @@ def copy_recent_scripts(self, superadmin_id):
347349
"""
348350
SELECT id, name, slug, description, created_at, updated_at, status,
349351
public, cpu_reservation, cpu_limit, memory_reservation,
350-
memory_limit, environment, environment_version
352+
memory_limit, environment, environment_version,
353+
COALESCE(restricted, false) as restricted,
354+
allowed_roles, allowed_users, build_error
351355
FROM script
352356
WHERE created_at >= %s OR updated_at >= %s
353357
ORDER BY created_at ASC
@@ -401,9 +405,11 @@ def copy_recent_scripts(self, superadmin_id):
401405
updated_at, user_id, status, public,
402406
cpu_reservation, cpu_limit,
403407
memory_reservation, memory_limit,
404-
environment, environment_version)
408+
environment, environment_version,
409+
restricted, allowed_roles, allowed_users,
410+
build_error)
405411
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s,
406-
%s, %s, %s)
412+
%s, %s, %s, %s, %s, %s, %s)
407413
ON CONFLICT (slug) DO UPDATE SET
408414
id = EXCLUDED.id,
409415
name = EXCLUDED.name,
@@ -417,7 +423,11 @@ def copy_recent_scripts(self, superadmin_id):
417423
memory_reservation = EXCLUDED.memory_reservation,
418424
memory_limit = EXCLUDED.memory_limit,
419425
environment = EXCLUDED.environment,
420-
environment_version = EXCLUDED.environment_version
426+
environment_version = EXCLUDED.environment_version,
427+
restricted = EXCLUDED.restricted,
428+
allowed_roles = EXCLUDED.allowed_roles,
429+
allowed_users = EXCLUDED.allowed_users,
430+
build_error = EXCLUDED.build_error
421431
RETURNING id, (xmax = 0) AS inserted
422432
""",
423433
(
@@ -436,6 +446,10 @@ def copy_recent_scripts(self, superadmin_id):
436446
script[11], # memory_limit
437447
script[12], # environment
438448
script[13], # environment_version
449+
script[14], # restricted
450+
script[15], # allowed_roles
451+
script[16], # allowed_users
452+
script[17], # build_error
439453
),
440454
)
441455

@@ -597,16 +611,58 @@ def copy_recent_status_logs(self):
597611
# Calculate date one month ago
598612
one_month_ago = datetime.now(UTC) - timedelta(days=30)
599613

600-
# Get recent status logs from production (excluding ID for reassignment)
614+
# Get recent status logs from production
615+
# Note: Production may have different column names, so we query
616+
# dynamically based on what exists
601617
prod_cursor.execute(
602618
"""
603-
SELECT timestamp, executions_active, executions_ready,
604-
executions_running, executions_finished, executions_failed,
605-
executions_count, users_count, scripts_count
619+
SELECT column_name FROM information_schema.columns
620+
WHERE table_name = 'status_log'
621+
ORDER BY ordinal_position
622+
"""
623+
)
624+
prod_columns = [row[0] for row in prod_cursor.fetchall()]
625+
logger.info(f"Production status_log columns: {prod_columns}")
626+
627+
# Skip status log import if schemas don't match - not critical
628+
# The status_log table may have different schemas between prod and staging
629+
staging_cursor.execute(
630+
"""
631+
SELECT column_name FROM information_schema.columns
632+
WHERE table_name = 'status_log'
633+
ORDER BY ordinal_position
634+
"""
635+
)
636+
staging_columns = [row[0] for row in staging_cursor.fetchall()]
637+
logger.info(f"Staging status_log columns: {staging_columns}")
638+
639+
# Find common columns (excluding 'id' which we'll auto-generate)
640+
common_columns = [
641+
col for col in staging_columns
642+
if col in prod_columns and col != 'id'
643+
]
644+
logger.info(f"Common columns for import: {common_columns}")
645+
646+
if not common_columns or 'timestamp' not in common_columns:
647+
logger.warning(
648+
"No compatible columns found between production and staging "
649+
"status_log tables. Skipping status log import."
650+
)
651+
return
652+
653+
# Build dynamic query with common columns
654+
columns_str = ', '.join(common_columns)
655+
placeholders = ', '.join(['%s'] * len(common_columns))
656+
657+
# Note: columns_str is derived from information_schema, not user input
658+
# so this is safe from SQL injection
659+
prod_cursor.execute(
660+
f"""
661+
SELECT {columns_str}
606662
FROM status_log
607663
WHERE timestamp >= %s
608664
ORDER BY timestamp ASC
609-
""",
665+
""", # noqa: S608
610666
(one_month_ago,),
611667
)
612668

@@ -616,16 +672,13 @@ def copy_recent_status_logs(self):
616672
imported_count = 0
617673
for log in status_logs:
618674
try:
619-
# Insert without ID to let the sequence generate new IDs
675+
# Insert using dynamic columns (columns derived from
676+
# information_schema, safe from SQL injection)
620677
staging_cursor.execute(
621-
"""
622-
INSERT INTO status_log (timestamp, executions_active,
623-
executions_ready, executions_running,
624-
executions_finished, executions_failed,
625-
executions_count, users_count,
626-
scripts_count)
627-
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s)
628-
""",
678+
f"""
679+
INSERT INTO status_log ({columns_str})
680+
VALUES ({placeholders})
681+
""", # noqa: S608
629682
log,
630683
)
631684
imported_count += 1

0 commit comments

Comments
 (0)