-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #16 from Bardin08/vbardin/implement-sql-schema-parser
SQL Schema construction
- Loading branch information
Showing
8 changed files
with
144 additions
and
22 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,46 @@ | ||
namespace DbSeeder.Schema; | ||
|
||
public class Column(string name, string dataType, string dataTypeConstraint, string[] constraints) | ||
public record Column | ||
{ | ||
public string Name { get; } = name; | ||
public string DataType { get; } = dataType; | ||
public string DataTypeConstraint { get; set; } = dataTypeConstraint; | ||
public string[] Constraints { get; set; } = constraints; | ||
public Column(string name, | ||
string dataType, | ||
string dataTypeConstraint, | ||
string[] constraints) | ||
{ | ||
Name = name; | ||
DataType = dataType; | ||
DataTypeConstraint = dataTypeConstraint; | ||
|
||
constraints = constraints.Select(c => c.ToLower()).ToArray(); | ||
IsAutoIncrement = constraints.Contains("auto_increment", StringComparer.OrdinalIgnoreCase); | ||
IsNotNull = constraints.Contains("not null", StringComparer.OrdinalIgnoreCase); | ||
IsUnique = constraints.Contains("unique", StringComparer.OrdinalIgnoreCase); | ||
IsPrimaryKey = constraints.Contains("primary key", StringComparer.OrdinalIgnoreCase); | ||
|
||
var fkConstraint = constraints.FirstOrDefault( | ||
c => c.StartsWith("foreign key", StringComparison.OrdinalIgnoreCase)); | ||
IsForeignKey = fkConstraint is not null; | ||
|
||
if (IsForeignKey) | ||
{ | ||
var refTableAndCol = fkConstraint![12..].Split("|"); | ||
|
||
var refTableName = refTableAndCol[0]; | ||
var refColumnName = refTableAndCol[1]; | ||
|
||
ForeignKeyRef = new ForeignKeyRef(refTableName, refColumnName); | ||
} | ||
} | ||
|
||
public string Name { get; } | ||
public string DataType { get; } | ||
public string DataTypeConstraint { get; } | ||
|
||
public bool IsAutoIncrement { get; } | ||
public bool IsPrimaryKey { get; } | ||
public bool IsForeignKey { get; } | ||
public bool IsNotNull { get; } | ||
public bool IsUnique { get; } | ||
|
||
public ForeignKeyRef? ForeignKeyRef { get; } | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
namespace DbSeeder.Schema; | ||
|
||
public record ForeignKey( | ||
Table Table, | ||
Column Column, | ||
Table RefTable, | ||
Column RefColumn); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
namespace DbSeeder.Schema; | ||
|
||
public record ForeignKeyRef( | ||
string TableName, | ||
string ColumnName); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
namespace DbSeeder.Schema; | ||
|
||
public record PrimaryKey( | ||
Table Table, | ||
Column Column); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,74 @@ | ||
namespace DbSeeder.Schema; | ||
|
||
public class Table(string name) | ||
public class Table(string name, SqlSchema schema) | ||
{ | ||
private readonly List<Column> _columns = []; | ||
private readonly List<ForeignKey> _foreignKeys = []; | ||
|
||
// There are some rules how to deal if PK is not defined | ||
// ex: find the first attribute with NOT NULL & UNIQUE constraints | ||
public PrimaryKey? PrimaryKey { get; private set; } | ||
public string Name { get; } = name; | ||
public List<Column> Columns { get; } = []; | ||
public IReadOnlyList<Column> Columns => _columns; | ||
public IReadOnlyList<ForeignKey> ForeignKeys => _foreignKeys; | ||
|
||
public void AddColumns(IEnumerable<Column> columns) | ||
{ | ||
foreach (var column in columns) | ||
{ | ||
AddColumn(column); | ||
} | ||
} | ||
|
||
private void AddColumn(Column column) | ||
{ | ||
ArgumentNullException.ThrowIfNull(column); | ||
_columns.Add(column); | ||
|
||
if (column.IsPrimaryKey) | ||
{ | ||
SetTablePrimaryKey(column); | ||
} | ||
else if (column.IsForeignKey) | ||
{ | ||
SetTableForeignKey(column); | ||
} | ||
} | ||
|
||
private void SetTablePrimaryKey(Column column) | ||
{ | ||
if (PrimaryKey != null) | ||
{ | ||
throw new ArgumentException("Table can not contains more that one PRIMARY KEY"); | ||
} | ||
|
||
PrimaryKey = new PrimaryKey(this, column); | ||
} | ||
|
||
private void SetTableForeignKey(Column column) | ||
{ | ||
ArgumentNullException.ThrowIfNull(column.ForeignKeyRef); | ||
|
||
var refTable = schema.GetTableByName(column.ForeignKeyRef.TableName); | ||
if (refTable is null) | ||
{ | ||
throw new InvalidOperationException($"Referenced table {column.ForeignKeyRef.TableName} is not exists " + | ||
$"in current schema. Validate the order of the create statements, " + | ||
$"it's matter"); | ||
} | ||
|
||
var refColumn = refTable.GetColumnByName(column.ForeignKeyRef.ColumnName); | ||
if (refColumn is null) | ||
{ | ||
throw new InvalidOperationException($"Referenced table {column.ForeignKeyRef.TableName} is not exists " + | ||
$"in current schema. Validate the order of the create statements, " + | ||
$"it's matter"); | ||
} | ||
|
||
var fk = new ForeignKey(this, column, refTable, refColumn); | ||
_foreignKeys.Add(fk); | ||
} | ||
|
||
private Column? GetColumnByName(string columnName) | ||
=> Columns.FirstOrDefault(c => c.Name.Equals(columnName, StringComparison.Ordinal)); | ||
} |