-
Notifications
You must be signed in to change notification settings - Fork 4
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 #334 from mk3008/331-supports-parsing-of-create-ta…
…ble-statement 331 supports parsing of create table statement
- Loading branch information
Showing
23 changed files
with
1,061 additions
and
151 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
using Carbunql.Analysis.Parser; | ||
using Carbunql.Extensions; | ||
using System.Data; | ||
|
||
namespace Carbunql.Analysis; | ||
|
||
public static class CreateTableQueryParser | ||
{ | ||
public static CreateTableQuery Parse(string text) | ||
{ | ||
var r = new SqlTokenReader(text); | ||
var q = Parse(r); | ||
|
||
if (!r.Peek().IsEndToken()) | ||
{ | ||
throw new NotSupportedException($"Parsing terminated despite the presence of unparsed tokens.(token:'{r.Peek()}')"); | ||
} | ||
|
||
return q; | ||
} | ||
|
||
static IEnumerable<string> ConstraintTokens => new[] { "primary key", "unique", "foreign key", "check", "not null", "constraint" }; | ||
|
||
public static CreateTableQuery Parse(ITokenReader r) | ||
{ | ||
var t = ParseAsCreateTableCommand(r); | ||
|
||
var token = r.Peek(); | ||
if (token.IsEqualNoCase("as")) | ||
{ | ||
r.Read("as"); | ||
t.Query = SelectQueryParser.Parse(r); | ||
return t; | ||
} | ||
else if (token == "(") | ||
{ | ||
r.Read("("); | ||
do | ||
{ | ||
r.ReadOrDefault(","); | ||
token = r.Peek(); | ||
if (token.IsEqualNoCase(ConstraintTokens)) | ||
{ | ||
var c = ConstraintParser.Parse(r); | ||
t.Constraints.Add(c); | ||
} | ||
else | ||
{ | ||
var c = ColumnDefinitionParser.Parse(r); | ||
t.Columns.Add(c); | ||
} | ||
} while (r.Peek() == ","); | ||
r.Read(")"); | ||
} | ||
|
||
return t; | ||
} | ||
|
||
private static CreateTableQuery ParseAsCreateTableCommand(ITokenReader r) | ||
{ | ||
var isTemporary = false; | ||
var token = r.Read(); | ||
if (token.IsEqualNoCase("create temporary table")) | ||
{ | ||
isTemporary = true; | ||
} | ||
else if (token.IsEqualNoCase("create table")) | ||
{ | ||
isTemporary = false; | ||
} | ||
else | ||
{ | ||
throw new NotSupportedException($"Token:{token}"); | ||
} | ||
|
||
token = r.Read(); | ||
var schema = string.Empty; | ||
string? table; | ||
if (r.Peek() == ".") | ||
{ | ||
r.Read("."); | ||
schema = token; | ||
table = r.Read(); | ||
} | ||
else | ||
{ | ||
table = token; | ||
} | ||
|
||
return new CreateTableQuery(schema, table) { IsTemporary = isTemporary }; | ||
} | ||
} |
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,27 @@ | ||
namespace Carbunql.Analysis.Parser; | ||
|
||
public class ArrayParser | ||
{ | ||
public static List<string> Parse(string text) | ||
{ | ||
var r = new SqlTokenReader(text); | ||
var q = Parse(r); | ||
return q; | ||
} | ||
|
||
public static List<string> Parse(ITokenReader r) | ||
{ | ||
var lst = new List<string>(); | ||
|
||
r.Read("("); | ||
do | ||
{ | ||
r.ReadOrDefault(","); | ||
lst.Add(r.Read()); | ||
} while (r.Peek() != ")"); | ||
|
||
r.Read(")"); | ||
|
||
return lst; | ||
} | ||
} |
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,100 @@ | ||
using Carbunql.Definitions; | ||
using Carbunql.Extensions; | ||
|
||
namespace Carbunql.Analysis.Parser; | ||
|
||
public static class ColumnDefinitionParser | ||
{ | ||
public static ColumnDefinition Parse(string text) | ||
{ | ||
var r = new SqlTokenReader(text); | ||
var q = Parse(r); | ||
return q; | ||
} | ||
|
||
private static IEnumerable<string> PostgresAutoNumberTypes => new[] { "bigserial", "serial", "serial8", "serial4" }; | ||
|
||
private static IEnumerable<string> GeneraetedIdentitySyntaxs => new[] { "generated always as identity", "generated by default as identity" }; | ||
|
||
|
||
public static ColumnDefinition Parse(ITokenReader r) | ||
{ | ||
var columnName = r.Read(); | ||
var columnType = ValueParser.Parse(r); | ||
|
||
var c = new ColumnDefinition(columnName, columnType); | ||
|
||
if (columnType.ToText().IsEqualNoCase(PostgresAutoNumberTypes)) | ||
{ | ||
//for Postgres | ||
c.IsAutoNumber = true; | ||
} | ||
|
||
var token = r.Peek(); | ||
if (token.IsEqualNoCase("auto_increment")) | ||
{ | ||
//for MySql | ||
c.AutoNumberDefinition = ValueParser.Parse(r); | ||
c.IsAutoNumber = true; | ||
token = r.Peek(); | ||
} | ||
|
||
if (token.IsEqualNoCase("identity")) | ||
{ | ||
//for SQLServer | ||
c.AutoNumberDefinition = ValueParser.Parse(r); | ||
c.IsAutoNumber = true; | ||
token = r.Peek(); | ||
} | ||
|
||
if (token.IsEqualNoCase(GeneraetedIdentitySyntaxs)) | ||
{ | ||
//Generated Indentity | ||
c.AutoNumberDefinition = ValueParser.Parse(r); | ||
c.IsAutoNumber = true; | ||
token = r.Peek(); | ||
} | ||
|
||
if (token.IsEqualNoCase("not null")) | ||
{ | ||
r.Read(); | ||
c.IsNullable = false; | ||
token = r.Peek(); | ||
} | ||
else | ||
{ | ||
c.IsNullable = true; | ||
} | ||
|
||
if (token.IsEqualNoCase("default")) | ||
{ | ||
r.Read(); | ||
c.DefaultValueDefinition = ValueParser.Parse(r); | ||
token = r.Peek(); | ||
} | ||
|
||
if (token.IsEqualNoCase("primary key")) | ||
{ | ||
r.Read(); | ||
c.IsPrimaryKey = true; | ||
token = r.Peek(); | ||
} | ||
|
||
if (token.IsEqualNoCase("unique")) | ||
{ | ||
r.Read(); | ||
c.IsUniqueKey = true; | ||
token = r.Peek(); | ||
} | ||
|
||
if (token.IsEqualNoCase("check")) | ||
{ | ||
r.Read(); | ||
c.CheckDefinition = ValueParser.Parse(r); | ||
token = r.Peek(); | ||
} | ||
|
||
if (token == "," || token == ")") return c; | ||
throw new NotSupportedException($"Token : {token}"); | ||
} | ||
} |
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,78 @@ | ||
using Carbunql.Analysis.Parser; | ||
using Carbunql.Definitions; | ||
using Carbunql.Extensions; | ||
|
||
namespace Carbunql.Analysis; | ||
|
||
public static class ConstraintParser | ||
{ | ||
public static IConstraint Parse(string text) | ||
{ | ||
var r = new SqlTokenReader(text); | ||
var q = Parse(r); | ||
return q; | ||
} | ||
|
||
public static IConstraint Parse(ITokenReader r) | ||
{ | ||
var token = r.Read(); | ||
var name = string.Empty; | ||
if (token.IsEqualNoCase("constraint")) | ||
{ | ||
name = r.Read(); | ||
token = r.Read(); | ||
} | ||
|
||
if (token.IsEqualNoCase("primary key")) | ||
{ | ||
var columns = ArrayParser.Parse(r); | ||
return new PrimaryKeyConstraint() | ||
{ | ||
ConstraintName = name, | ||
ColumnNames = columns | ||
}; | ||
} | ||
|
||
if (token.IsEqualNoCase("unique")) | ||
{ | ||
var columns = ArrayParser.Parse(r); | ||
return new UniqueConstraint() | ||
{ | ||
ConstraintName = name, | ||
ColumnNames = columns | ||
}; | ||
} | ||
|
||
if (token.IsEqualNoCase("check")) | ||
{ | ||
var val = ValueParser.Parse(r); | ||
return new CheckConstraint() | ||
{ | ||
Value = val | ||
}; | ||
} | ||
|
||
if (token.IsEqualNoCase("not null")) | ||
{ | ||
return new NotNullConstraint() | ||
{ | ||
ConstraintName = name, | ||
ColumnName = r.Read() | ||
}; | ||
} | ||
|
||
if (token.IsEqualNoCase("foreign key")) | ||
{ | ||
var columns = ArrayParser.Parse(r); | ||
var reference = ReferenceParser.Parse(r); | ||
return new ForeignKeyConstraint() | ||
{ | ||
ConstraintName = name, | ||
ColumnNames = columns, | ||
Reference = reference | ||
}; | ||
} | ||
|
||
throw new NotSupportedException(); | ||
} | ||
} |
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,23 @@ | ||
using Carbunql.Analysis.Parser; | ||
using Carbunql.Definitions; | ||
|
||
namespace Carbunql.Analysis; | ||
|
||
public static class ReferenceParser | ||
{ | ||
public static ReferenceDefinition Parse(string text) | ||
{ | ||
var r = new SqlTokenReader(text); | ||
var q = Parse(r); | ||
return q; | ||
} | ||
|
||
public static ReferenceDefinition Parse(ITokenReader r) | ||
{ | ||
var token = r.Read("references"); | ||
var table = r.Read(); | ||
var columns = ArrayParser.Parse(r); | ||
|
||
return new ReferenceDefinition(table, columns); | ||
} | ||
} |
Oops, something went wrong.