forked from fluentmigrator/fluentmigrator
/
PostgresGenerator.cs
244 lines (204 loc) · 9.91 KB
/
PostgresGenerator.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using FluentMigrator.Expressions;
using FluentMigrator.Model;
namespace FluentMigrator.Runner.Generators
{
public class PostgresGenerator : GeneratorBase
{
public PostgresGenerator() : base(new PostgresColumn(), new PostgresFormatter()) { }
public override string Generate(CreateSchemaExpression expression)
{
return string.Format("CREATE SCHEMA {0}", FormatSchema(expression.SchemaName));
}
public override string Generate(DeleteSchemaExpression expression)
{
return string.Format("DROP SCHEMA {0}", FormatSchema(expression.SchemaName));
}
public override string Generate(CreateTableExpression expression)
{
return String.Format("CREATE TABLE {0}.{1} ({2})",FormatSchema(expression.SchemaName), FormatIdentifier(expression.TableName), Column.Generate(expression));
}
public override string Generate(AlterColumnExpression expression)
{
return String.Format("ALTER TABLE {0}.{1} ALTER {2} TYPE {3}", FormatSchema(expression.SchemaName), FormatIdentifier(expression.TableName), FormatIdentifier(expression.Column.Name), ((PostgresColumn)Column).GetColumnType(expression.Column));
}
public override string Generate(CreateColumnExpression expression)
{
return string.Format("ALTER TABLE {0}.{1} ADD {2}", FormatSchema(expression.SchemaName), FormatIdentifier(expression.TableName), Column.Generate(expression.Column));
}
public override string Generate(DeleteTableExpression expression)
{
return String.Format("DROP TABLE {0}.{1}", FormatSchema(expression.SchemaName), FormatIdentifier(expression.TableName));
}
public override string Generate(DeleteColumnExpression expression)
{
return string.Format("ALTER TABLE {0}.{1} DROP COLUMN {2}", FormatSchema(expression.SchemaName), FormatIdentifier(expression.TableName), FormatIdentifier(expression.ColumnName));
}
public override string Generate(CreateForeignKeyExpression expression)
{
var primaryColumns = GetColumnList(expression.ForeignKey.PrimaryColumns);
var foreignColumns = GetColumnList(expression.ForeignKey.ForeignColumns);
const string sql = "ALTER TABLE {0}.{1} ADD CONSTRAINT {2} FOREIGN KEY ({3}) REFERENCES {4}.{5} ({6}){7}{8}";
return string.Format(sql,
FormatSchema(expression.ForeignKey.ForeignTableSchema),
FormatIdentifier(expression.ForeignKey.ForeignTable),
FormatIdentifier(expression.ForeignKey.Name),
foreignColumns,
FormatSchema(expression.ForeignKey.PrimaryTableSchema),
FormatIdentifier(expression.ForeignKey.PrimaryTable),
primaryColumns,
FormatCascade("DELETE", expression.ForeignKey.OnDelete),
FormatCascade("UPDATE", expression.ForeignKey.OnUpdate)
);
}
public override string Generate(DeleteForeignKeyExpression expression)
{
return string.Format("ALTER TABLE {0}.{1} DROP CONSTRAINT {2}", FormatSchema(expression.ForeignKey.ForeignTableSchema), FormatIdentifier(expression.ForeignKey.ForeignTable), FormatIdentifier(expression.ForeignKey.Name));
}
public override string Generate(CreateIndexExpression expression)
{
var result = new StringBuilder("CREATE");
if (expression.Index.IsUnique)
result.Append(" UNIQUE");
result.Append(" INDEX {0} ON {1}.{2} (");
var first = true;
foreach (var column in expression.Index.Columns)
{
if (first)
first = false;
else
result.Append(",");
result.Append("\"" + column.Name + "\"");
result.Append(column.Direction == Direction.Ascending ? " ASC" : " DESC");
}
result.Append(")");
return String.Format(result.ToString(), FormatIdentifier(expression.Index.Name), FormatSchema(expression.Index.SchemaName), FormatIdentifier(expression.Index.TableName));
/*
var idx = String.Format(result.ToString(), expression.Index.Name, FormatSchema(expression.Index.SchemaName), expression.Index.TableName);
if (!expression.Index.IsClustered)
return idx;
// Clustered indexes in Postgres do not cluster updates/inserts to the table after the initial cluster operation is applied.
// To keep the clustered index up to date run CLUSTER TableName periodically
return string.Format("{0}; CLUSTER {1}\"{2}\" ON \"{3}\"", idx, FormatSchema(expression.Index.SchemaName), expression.Index.TableName, expression.Index.Name);
*/
}
public override string Generate(DeleteIndexExpression expression)
{
return string.Format("DROP INDEX {0}.{1}", FormatSchema(expression.Index.SchemaName), FormatIdentifier(expression.Index.Name));
}
public override string Generate(RenameTableExpression expression)
{
return string.Format("ALTER TABLE {0}.{1} RENAME TO {2}", FormatSchema(expression.SchemaName), FormatIdentifier(expression.OldName), FormatIdentifier(expression.NewName));
}
public override string Generate(RenameColumnExpression expression)
{
return string.Format("ALTER TABLE {0}.{1} RENAME COLUMN {2} TO {3}", FormatSchema(expression.SchemaName), FormatIdentifier(expression.TableName), FormatIdentifier(expression.OldName), FormatIdentifier(expression.NewName));
}
public override string Generate(InsertDataExpression expression)
{
var result = new StringBuilder();
foreach (var row in expression.Rows)
{
var columnNames = new List<string>();
var columnData = new List<object>();
foreach (var item in row)
{
columnNames.Add(item.Key);
columnData.Add(item.Value);
}
var columns = GetColumnList(columnNames);
var data = GetDataList(columnData);
result.Append(String.Format("INSERT INTO {0}.{1} ({2}) VALUES ({3});", FormatSchema(expression.SchemaName), FormatIdentifier(expression.TableName), columns, data));
}
return result.ToString();
}
public override string Generate(AlterDefaultConstraintExpression expression)
{
throw new NotImplementedException();
}
public override string Generate(DeleteDataExpression expression)
{
var result = new StringBuilder();
if (expression.IsAllRows)
{
result.Append(String.Format("DELETE FROM {0}.{1};", FormatSchema(expression.SchemaName), FormatIdentifier(expression.TableName)));
}
else
{
foreach (var row in expression.Rows)
{
var where = String.Empty;
var i = 0;
foreach (var item in row)
{
if (i != 0)
{
where += " AND ";
}
where += String.Format("{0} {1} {2}", FormatIdentifier(item.Key), item.Value == null ? "IS" : "=", Constant.Format(item.Value));
i++;
}
result.Append(String.Format("DELETE FROM {0}.{1} WHERE {2};", FormatSchema(expression.SchemaName), FormatIdentifier(expression.TableName), where));
}
}
return result.ToString();
}
public override string Generate(UpdateDataExpression expression)
{
throw new NotImplementedException();
}
public override string Generate(AlterSchemaExpression expression)
{
return string.Format("ALTER TABLE {0}.{1} SET SCHEMA {2}", FormatSchema(expression.SourceSchemaName), FormatIdentifier(expression.TableName), FormatSchema(expression.DestinationSchemaName));
}
protected string FormatIdentifier(string identifier)
{
return string.Format("\"{0}\"", identifier.Replace("'", "''"));
}
protected string FormatSchema(string schemaName)
{
return FormatIdentifier(schemaName ?? "public");
}
protected string GetColumnList(IEnumerable<string> columns)
{
var result = "";
foreach (var column in columns)
{
result += FormatIdentifier(column) + ",";
}
return result.TrimEnd(',');
}
protected string FormatCascade(string onWhat, Rule rule)
{
string action = "NO ACTION";
switch (rule)
{
case Rule.None:
return "";
case Rule.Cascade:
action = "CASCADE";
break;
case Rule.SetNull:
action = "SET NULL";
break;
case Rule.SetDefault:
action = "SET DEFAULT";
break;
}
return string.Format(" ON {0} {1}", onWhat, action);
}
protected string GetDataList(List<object> data)
{
var result = "";
foreach (var column in data)
{
result += Constant.Format(column) + ",";
}
return result.TrimEnd(',');
}
}
}