import pandas as pd import argparse import textwrap def generate_acl_sql(df): # Group by schema, table, grantee grouped = df.groupby(['table_schema', 'table_name', 'grantee'])['privilege_type'].apply(lambda x: sorted(set(x))).reset_index() lines = [] lines.append("DO $$") lines.append("BEGIN") for _, row in grouped.iterrows(): schema = row['table_schema'] table = row['table_name'] grantee = row['grantee'] privileges = ", ".join(row['privilege_type']) lines.append(f" IF EXISTS (SELECT 1 FROM information_schema.tables WHERE table_schema = '{schema}' AND table_name = '{table}') THEN") lines.append(f" GRANT {privileges} ON {schema}.{table} TO {grantee};") lines.append(" END IF;") lines.append("END") lines.append("$$;") return "\n".join(lines) def main(): parser = argparse.ArgumentParser(description="Generate idempotent ACL SQL with IF statements") parser.add_argument('--input', '-i', required=True, help="Path to ACL CSV file") parser.add_argument('--output', '-o', default='acl_generated.sql', help="Output SQL file path") args = parser.parse_args() # Read ACL CSV df = pd.read_csv(args.input) # Expect columns: grantee, table_schema, table_name, privilege_type required_cols = {'grantee', 'table_schema', 'table_name', 'privilege_type'} if not required_cols.issubset(df.columns): raise ValueError(f"Input CSV must contain columns: {', '.join(required_cols)}") sql_script = generate_acl_sql(df) with open(args.output, 'w', encoding='utf-8') as f: f.write(sql_script) print(f"✔ ACL idempotent SQL has been generated in {args.output}") if __name__ == "__main__": main()