Skip to content

Commit 476855f

Browse files
dcm-migrate: address PR #20 review feedback and add qualifier fixes
- Align degraded-lookup rows to status=WARNING (semantic view, schema, procedure/function language lookups) to match the documented contract. - Add identifier validation and safe quoting for dynamic SQL; all generated DDL and FQNs now use fully quoted "DB"."SCHEMA"."NAME" form. - Aggregate grant-collector failures into one WARNING row per schema instead of silently swallowing the exception. - Two-pass fqn_expand: Pass 1 expands SCHEMA.OBJECT cross-schema references to fully qualified form; Pass 2 expands bare same-schema names. - Pass TRUE to all GET_DDL calls (the callable branch was missing it). - SKILL: fetch account_identifier from the current session (CURRENT_ORGANIZATION_NAME || '-' || CURRENT_ACCOUNT_NAME) before writing manifest.yml, and substitute it for the DEV target.
1 parent 88b03a2 commit 476855f

3 files changed

Lines changed: 35 additions & 3 deletions

File tree

migration-tools/Cortex_Code_Skill/dcm-migrate/SKILL.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,14 +168,19 @@ Collect from the user:
168168
- Ask for the project identifier (`DB.SCHEMA.PROJECT_NAME`)
169169
- The project's parent DB and schema CANNOT be defined inside the project itself
170170
- Ask if multi-environment templating is needed
171+
- **Fetch the current account identifier** from the active session before writing the manifest. Run:
172+
```sql
173+
SELECT CURRENT_ORGANIZATION_NAME() || '-' || CURRENT_ACCOUNT_NAME() AS ACCOUNT_IDENTIFIER
174+
```
175+
Use the returned value as `account_identifier` for the target matching the current connection (typically `DEV`). For additional targets that point to other accounts (e.g. `PROD`), leave a placeholder like `<PROD_ORG>-<PROD_ACCOUNT>` and tell the user to fill it in.
171176
- Create local directory structure:
172177
```
173178
<project_dir>/
174179
├── manifest.yml
175180
└── sources/
176181
└── definitions/
177182
```
178-
- Create `manifest.yml` using this template:
183+
- Create `manifest.yml` using this template (substitute `<ACCOUNT_IDENTIFIER>` with the value fetched above):
179184

180185
**Minimal manifest (no templating):**
181186
```yaml
@@ -185,6 +190,7 @@ Collect from the user:
185190

186191
targets:
187192
DEV:
193+
account_identifier: '<ACCOUNT_IDENTIFIER>' # from CURRENT_ORGANIZATION_NAME() || '-' || CURRENT_ACCOUNT_NAME()
188194
project_name: 'DB_NAME.SCHEMA_NAME.PROJECT_NAME'
189195
project_owner: DCM_DEVELOPER
190196
```
@@ -197,10 +203,12 @@ Collect from the user:
197203

198204
targets:
199205
DEV:
206+
account_identifier: '<ACCOUNT_IDENTIFIER>' # current session
200207
project_name: 'DB_NAME.SCHEMA_NAME.PROJECT_NAME_DEV'
201208
project_owner: DCM_DEVELOPER
202209
templating_config: 'DEV'
203210
PROD:
211+
account_identifier: '<PROD_ORG>-<PROD_ACCOUNT>' # replace with the PROD account identifier
204212
project_name: 'DB_NAME.SCHEMA_NAME.PROJECT_NAME'
205213
project_owner: DCM_PROD_DEPLOYER
206214
templating_config: 'PROD'

migration-tools/Cortex_Code_Skill/dcm-migrate/scripts/ddl_to_dcm.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,18 @@ def escape_jinja_conflicts(ddl_text):
107107

108108

109109
def fqn_expand(text, source_schema, object_map):
110+
# Pass 1: expand SCHEMA.OBJECT references (any schema in this database)
111+
# to the fully qualified "DB"."SCHEMA"."OBJECT" form. Skip if already
112+
# preceded by another qualifier (e.g. "DB"."SCHEMA".NAME).
113+
for target_obj in object_map:
114+
t_schema = target_obj["schema"]
115+
t_name = target_obj["name"]
116+
t_fqn = target_obj["fqn"]
117+
pattern = r'(?i)(?<!\.|")\b{}\.{}\b'.format(
118+
re.escape(t_schema), re.escape(t_name)
119+
)
120+
text = re.sub(pattern, t_fqn, text)
121+
# Pass 2: expand bare OBJECT references in the source schema.
110122
for target_obj in object_map:
111123
if target_obj["schema"] != source_schema:
112124
continue
@@ -538,7 +550,7 @@ def collect_future_grants(show_cmd, schema):
538550
sig_for_ddl = f"{fqn}()"
539551

540552
try:
541-
res = session.sql(f"SELECT GET_DDL('{domain}', '{sig_for_ddl}') as DDL").collect()
553+
res = session.sql(f"SELECT GET_DDL('{domain}', '{sig_for_ddl}', TRUE) as DDL").collect()
542554
ddl_text = res[0]["DDL"]
543555
except Exception as e:
544556
results.append({"schema": schema, "object_type": domain, "object_name": short_name, "status": "ERROR", "file_path": str(e)})

migration-tools/DDL_to_DCM_sproc.sql

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -389,6 +389,18 @@ def main(session, db_name, schema_allow_list, output_path, group_by_type):
389389
return full_stage_path
390390

391391
def fqn_expand(text, source_schema):
392+
# Pass 1: expand SCHEMA.OBJECT references (any schema in this database)
393+
# to the fully qualified "DB"."SCHEMA"."OBJECT" form. Skip if already
394+
# preceded by another qualifier (e.g. "DB"."SCHEMA".NAME).
395+
for target_obj in object_map:
396+
t_schema = target_obj['schema']
397+
t_name = target_obj['name']
398+
t_fqn = target_obj['fqn']
399+
pattern = r'(?i)(?<!\.|")\b{}\.{}\b'.format(
400+
re.escape(t_schema), re.escape(t_name)
401+
)
402+
text = re.sub(pattern, t_fqn, text)
403+
# Pass 2: expand bare OBJECT references in the source schema.
392404
for target_obj in object_map:
393405
if target_obj['schema'] != source_schema:
394406
continue
@@ -523,7 +535,7 @@ def main(session, db_name, schema_allow_list, output_path, group_by_type):
523535
sig_for_ddl = f"{fqn}()"
524536

525537
try:
526-
res = session.sql(f"SELECT GET_DDL('{domain}', '{sig_for_ddl}') as DDL").collect()
538+
res = session.sql(f"SELECT GET_DDL('{domain}', '{sig_for_ddl}', TRUE) as DDL").collect()
527539
ddl_text = res[0]['DDL']
528540
except Exception as e:
529541
generated_files.append((schema, domain, short_name, "ERROR", str(e)))

0 commit comments

Comments
 (0)