Skip to content

Commit

Permalink
Merge pull request #335 from mk3008/332-supports-parsing-of-create-in…
Browse files Browse the repository at this point in the history
…dex-statement

332 supports parsing of create index statement
  • Loading branch information
mk3008 authored Feb 18, 2024
2 parents 6e882d1 + 09234d4 commit 73b5f09
Show file tree
Hide file tree
Showing 14 changed files with 408 additions and 38 deletions.
98 changes: 98 additions & 0 deletions src/Carbunql/Analysis/CreateIndexQueryParser.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
using Carbunql.Analysis.Parser;
using Carbunql.Clauses;
using Carbunql.Extensions;
using System.Xml.Linq;

namespace Carbunql.Analysis;

public static class CreateIndexQueryParser
{
public static CreateIndexQuery 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;
}

public static CreateIndexQuery Parse(ITokenReader r)
{
var t = ParseAsCreateIndexCommand(r);
t.OnClause = ParseAsOnClause(r);

if (r.Peek().IsEqualNoCase("where"))
{
t.WhereClause = WhereClauseParser.Parse(r);
}
return t;
}

private static CreateIndexQuery ParseAsCreateIndexCommand(ITokenReader r)
{
var isUnique = false;
var token = r.Read();
if (token.IsEqualNoCase("create unique index"))
{
isUnique = true;
}
else if (token.IsEqualNoCase("create index"))
{
isUnique = false;
}
else
{
throw new NotSupportedException($"Token:{token}");
}

var indexName = string.Empty;
if (!r.Peek().IsEqualNoCase("on"))
{
indexName = r.Read();
}

return new CreateIndexQuery { IsUnique = isUnique, IndexName = indexName };
}

private static IndexOnClause ParseAsOnClause(ITokenReader r)
{
r.Read("on");
var table = ParseAsTableName(r);
var clause = new IndexOnClause(table.schema, table.name);

r.Read("(");
do
{
r.ReadOrDefault(",");
var c = SortableItemParser.Parse(r);
clause.Add(c);
} while (r.Peek() == ",");
r.Read(")");

return clause;
}

private static (string schema, string name) ParseAsTableName(ITokenReader r)
{
var token = r.Read();

var schema = string.Empty;
string? name;
if (r.Peek() == ".")
{
r.Read(".");
schema = token;
name = r.Read();
}
else
{
name = token;
}

return (schema, name);
}
}
5 changes: 3 additions & 2 deletions src/Carbunql/Analysis/CreateTableQueryParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ public static CreateTableQuery Parse(ITokenReader r)
}
else if (token == "(")
{
t.DefinitionClause ??= new();
r.Read("(");
do
{
Expand All @@ -42,12 +43,12 @@ public static CreateTableQuery Parse(ITokenReader r)
if (token.IsEqualNoCase(ConstraintTokens))
{
var c = ConstraintParser.Parse(r);
t.Constraints.Add(c);
t.DefinitionClause.Add(c);
}
else
{
var c = ColumnDefinitionParser.Parse(r);
t.Columns.Add(c);
t.DefinitionClause.Add(c);
}
} while (r.Peek() == ",");
r.Read(")");
Expand Down
2 changes: 2 additions & 0 deletions src/Carbunql/Analysis/Parser/WhereClauseParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ public static WhereClause Parse(string text)

public static WhereClause Parse(ITokenReader r)
{
r.ReadOrDefault("where");

var val = ValueParser.Parse(r);
var where = new WhereClause(val);
return where;
Expand Down
18 changes: 16 additions & 2 deletions src/Carbunql/Analysis/TokenReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -148,9 +148,23 @@ public virtual string Read()
sb.Append(" " + Reader.Read("table"));
return sb.ToString();
}
else

if (Reader.TryRead("table", out var table))
{
sb.Append(" " + Reader.Read("table"));
sb.Append(" " + table);
return sb.ToString();
}

if (Reader.TryRead("unique", out var unique))
{
sb.Append(" " + unique);
sb.Append(" " + Reader.Read("index"));
return sb.ToString();
}

if (Reader.TryRead("index", out var index))
{
sb.Append(" " + index);
return sb.ToString();
}
}
Expand Down
57 changes: 57 additions & 0 deletions src/Carbunql/Clauses/IndexOnClause.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
using Carbunql.Tables;

namespace Carbunql.Clauses;

public class IndexOnClause : QueryCommandCollection<SortableItem>
{
public IndexOnClause(string table)
{
Table = table;
}

public IndexOnClause(string schema, string table)
{
Schema = schema;
Table = table;
}

public string? Schema { get; init; } = null;

public string Table { get; init; }

public string TableFullName => (string.IsNullOrEmpty(Schema)) ? Table : Schema + "." + Table;

public override IEnumerable<Token> GetTokens(Token? parent)
{
if (!Items.Any()) yield break;

var clause = Token.Reserved(this, parent, "on");
yield return clause;
yield return new Token(this, parent, TableFullName);

yield return Token.ReservedBracketStart(this, parent);
foreach (var item in base.GetTokens(clause)) yield return item;
yield return Token.ReservedBracketEnd(this, parent);
}

public IEnumerable<SelectQuery> GetInternalQueries()
{
yield break;
}

public IEnumerable<PhysicalTable> GetPhysicalTables()
{
yield break;
}

public IEnumerable<CommonTable> GetCommonTables()
{
yield break;
}


public override IEnumerable<QueryParameter> GetParameters()
{
yield break;
}
}
41 changes: 41 additions & 0 deletions src/Carbunql/Clauses/TableDefinitionClause.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
using Carbunql.Definitions;
using Carbunql.Tables;

namespace Carbunql.Clauses;

public class TableDefinitionClause : QueryCommandCollection<ITableDefinition>
{
public override IEnumerable<Token> GetTokens(Token? parent)
{
if (!Items.Any()) yield break;

var bracket = Token.ReservedBracketStart(this, parent);
yield return bracket;
foreach (var item in base.GetTokens(bracket))
{
yield return item;
}
yield return Token.ReservedBracketEnd(this, parent);
}

public IEnumerable<SelectQuery> GetInternalQueries()
{
yield break;
}

public IEnumerable<PhysicalTable> GetPhysicalTables()
{
yield break;
}

public IEnumerable<CommonTable> GetCommonTables()
{
yield break;
}


public override IEnumerable<QueryParameter> GetParameters()
{
yield break;
}
}
79 changes: 79 additions & 0 deletions src/Carbunql/CreateIndexQuery.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
using Carbunql.Building;
using Carbunql.Clauses;
using Carbunql.Tables;
using MessagePack;

namespace Carbunql;

public class CreateIndexQuery : IQueryCommandable, ICommentable
{
public bool IsUnique { get; set; } = false;

public string? IndexName { get; init; } = null;

public IndexOnClause? OnClause { get; set; }

public WhereClause? WhereClause { get; set; } = null;

[IgnoreMember]
public CommentClause? CommentClause { get; set; }

public IEnumerable<SelectQuery> GetInternalQueries()
{
yield break;
}

public IEnumerable<PhysicalTable> GetPhysicalTables()
{
yield break;
}

public virtual IEnumerable<QueryParameter> GetParameters()
{
yield break;
}

private Token GetCreateIndexToken(Token? parent)
{
if (IsUnique)
{
return Token.Reserved(this, parent, "create unique index");
}
return Token.Reserved(this, parent, "create index");
}

public IEnumerable<Token> GetTokens(Token? parent)
{
//if (Query == null) throw new NullReferenceException(nameof(Query));

if (CommentClause != null) foreach (var item in CommentClause.GetTokens(parent)) yield return item;

var ct = GetCreateIndexToken(parent);
yield return ct;
if (!string.IsNullOrEmpty(IndexName))
{
yield return new Token(this, parent, IndexName);
}

if (OnClause != null)
{
foreach (var item in OnClause.GetTokens(parent))
{
yield return item;
}
}

if (WhereClause != null)
{
foreach (var item in WhereClause.GetTokens(parent))
{
yield return item;
}
}
}

public IEnumerable<CommonTable> GetCommonTables()
{
yield break;
}
}
Loading

0 comments on commit 73b5f09

Please sign in to comment.