Skip to content

Commit ee0ebab

Browse files
Add PostgreSQL support object migrations (#42)
## Summary - Add declarative YAML, diff, DDL, and inspection support for PostgreSQL roles, functions, grants, and RLS policies. - Add PostgreSQL support-object tests, real Postgres E2E coverage, readback coverage, and RLS spec notes. - Bump DataProviderMigrate to 0.9.8-beta. ## Verification - dotnet csharpier check . - dotnet test Migration/Nimblesite.DataProvider.Migration.Tests/Nimblesite.DataProvider.Migration.Tests.csproj --configuration Release --no-restore - dotnet pack Migration/DataProviderMigrate/DataProviderMigrate.csproj --configuration Release --no-restore --output /tmp/dataprovider-pack-check Closes #33 Closes #34 Closes #35
1 parent 3f2cf90 commit ee0ebab

17 files changed

Lines changed: 1703 additions & 7 deletions

Directory.Build.props

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<NuGetAudit>false</NuGetAudit>
55
<NuGetAuditMode>disabled</NuGetAuditMode>
66
<RestoreAuditProperties>false</RestoreAuditProperties>
7-
<Version>0.9.7-beta</Version>
7+
<Version>0.9.8-beta</Version>
88
<Authors>ChristianFindlay</Authors>
99
<Company>Nimblesite</Company>
1010
<PackageLicenseExpression>MIT</PackageLicenseExpression>

Migration/Nimblesite.DataProvider.Migration.Core/MigrationRunner.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,8 @@ is DropTableOperation
111111
or DropColumnOperation
112112
or DropIndexOperation
113113
or DropForeignKeyOperation
114+
or DropFunctionOperation
115+
or RevokePrivilegesOperation
114116
or DropRlsPolicyOperation
115117
or DisableRlsOperation
116118
or DisableForceRlsOperation;

Migration/Nimblesite.DataProvider.Migration.Core/SchemaDefinition.cs

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,126 @@ public sealed record SchemaDefinition
1010

1111
/// <summary>Tables in this schema.</summary>
1212
public IReadOnlyList<TableDefinition> Tables { get; init; } = [];
13+
14+
/// <summary>
15+
/// PostgreSQL roles managed by this schema. Implements [RLS-PG-SUPPORT-DDL].
16+
/// </summary>
17+
public IReadOnlyList<PostgresRoleDefinition> Roles { get; init; } = [];
18+
19+
/// <summary>
20+
/// PostgreSQL helper functions managed by this schema. Implements [RLS-PG-SUPPORT-DDL].
21+
/// </summary>
22+
public IReadOnlyList<PostgresFunctionDefinition> Functions { get; init; } = [];
23+
24+
/// <summary>
25+
/// PostgreSQL grants managed by this schema. Implements [RLS-PG-SUPPORT-DDL].
26+
/// </summary>
27+
public IReadOnlyList<PostgresGrantDefinition> Grants { get; init; } = [];
28+
}
29+
30+
/// <summary>
31+
/// PostgreSQL role definition for migration-managed application roles.
32+
/// Implements [RLS-PG-SUPPORT-DDL].
33+
/// </summary>
34+
public sealed record PostgresRoleDefinition
35+
{
36+
/// <summary>Role name.</summary>
37+
public string Name { get; init; } = string.Empty;
38+
39+
/// <summary>Whether the role can log in directly.</summary>
40+
public bool Login { get; init; }
41+
42+
/// <summary>Whether the role can bypass row-level security.</summary>
43+
public bool BypassRls { get; init; }
44+
45+
/// <summary>Roles or users that receive membership in this role.</summary>
46+
public IReadOnlyList<string> GrantTo { get; init; } = [];
47+
}
48+
49+
/// <summary>
50+
/// PostgreSQL SQL-language function definition for RLS helper functions.
51+
/// Implements [RLS-PG-SUPPORT-DDL].
52+
/// </summary>
53+
public sealed record PostgresFunctionDefinition
54+
{
55+
/// <summary>Function schema.</summary>
56+
public string Schema { get; init; } = "public";
57+
58+
/// <summary>Function name.</summary>
59+
public string Name { get; init; } = string.Empty;
60+
61+
/// <summary>Function arguments in declaration order.</summary>
62+
public IReadOnlyList<PostgresFunctionArgumentDefinition> Arguments { get; init; } = [];
63+
64+
/// <summary>PostgreSQL return type, such as <c>uuid</c> or <c>boolean</c>.</summary>
65+
public string Returns { get; init; } = "void";
66+
67+
/// <summary>Function language. NAP RLS helpers use <c>sql</c>.</summary>
68+
public string Language { get; init; } = "sql";
69+
70+
/// <summary>PostgreSQL volatility keyword: <c>volatile</c>, <c>stable</c>, or <c>immutable</c>.</summary>
71+
public string Volatility { get; init; } = "stable";
72+
73+
/// <summary>Whether to emit <c>SECURITY DEFINER</c>.</summary>
74+
public bool SecurityDefiner { get; init; }
75+
76+
/// <summary>Function body placed between PostgreSQL dollar quotes.</summary>
77+
public string Body { get; init; } = string.Empty;
78+
79+
/// <summary>Roles granted EXECUTE on this function.</summary>
80+
public IReadOnlyList<string> ExecuteRoles { get; init; } = [];
81+
82+
/// <summary>Whether PUBLIC execute must be revoked.</summary>
83+
public bool RevokePublicExecute { get; init; } = true;
84+
}
85+
86+
/// <summary>
87+
/// PostgreSQL function argument definition.
88+
/// </summary>
89+
public sealed record PostgresFunctionArgumentDefinition
90+
{
91+
/// <summary>Argument name. Optional for inspected function identities.</summary>
92+
public string Name { get; init; } = string.Empty;
93+
94+
/// <summary>PostgreSQL argument type.</summary>
95+
public string Type { get; init; } = string.Empty;
96+
}
97+
98+
/// <summary>
99+
/// PostgreSQL grant definition for schema and table privileges.
100+
/// Implements [RLS-PG-SUPPORT-DDL].
101+
/// </summary>
102+
public sealed record PostgresGrantDefinition
103+
{
104+
/// <summary>Target schema.</summary>
105+
public string Schema { get; init; } = "public";
106+
107+
/// <summary>Grant target kind.</summary>
108+
public PostgresGrantTarget Target { get; init; } = PostgresGrantTarget.Table;
109+
110+
/// <summary>Table name when <see cref="Target" /> is <see cref="PostgresGrantTarget.Table" />.</summary>
111+
public string? ObjectName { get; init; }
112+
113+
/// <summary>Privileges to grant, such as <c>USAGE</c>, <c>SELECT</c>, or <c>INSERT</c>.</summary>
114+
public IReadOnlyList<string> Privileges { get; init; } = [];
115+
116+
/// <summary>Roles receiving the privileges.</summary>
117+
public IReadOnlyList<string> Roles { get; init; } = [];
118+
}
119+
120+
/// <summary>
121+
/// PostgreSQL grant target kind.
122+
/// </summary>
123+
public enum PostgresGrantTarget
124+
{
125+
/// <summary>Target is a schema.</summary>
126+
Schema,
127+
128+
/// <summary>Target is one table.</summary>
129+
Table,
130+
131+
/// <summary>Target is every current table in the schema.</summary>
132+
AllTablesInSchema,
13133
}
14134

15135
/// <summary>

0 commit comments

Comments
 (0)