Skip to content

Commit ece9389

Browse files
committed
settup binding to detect errors earlier
1 parent 9c42e99 commit ece9389

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+772
-209
lines changed

Diff for: .editorconfig

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
[*]
2+
# VSSPELL: Spell checker settings for all files
3+
vsspell_section_id = f3072efff769410d89867fda3123d044
4+
vsspell_ignored_words_f3072efff769410d89867fda3123d044 = Accessor|Subselect|Rowset|Equi
5+

Diff for: JankSQL.sln

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Parsing", "Parsing\Parsing.
99
EndProject
1010
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{07F69422-E71F-4541-825E-60461DC4F723}"
1111
ProjectSection(SolutionItems) = preProject
12+
.editorconfig = .editorconfig
1213
.gitignore = .gitignore
1314
README.md = README.md
1415
EndProjectSection

Diff for: JankSQL/BindResult.cs

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
using System;
2+
namespace JankSQL
3+
{
4+
public class BindResult
5+
{
6+
public BindResult()
7+
{
8+
this.BindStatus = BindStatus.NOT_BOUND;
9+
}
10+
11+
public BindResult(BindStatus bs)
12+
{
13+
this.BindStatus = bs;
14+
}
15+
16+
public BindResult(BindStatus bs, string errorMessage)
17+
{
18+
this.BindStatus = bs;
19+
this.ErrorMessage = errorMessage;
20+
}
21+
22+
public BindStatus BindStatus { get; set; }
23+
24+
public string? ErrorMessage { get; set; }
25+
26+
public bool IsSuccessful => (BindStatus == BindStatus.SUCCESSFUL) || (BindStatus == BindStatus.SUCCESSFUL);
27+
28+
public override string ToString()
29+
{
30+
if (BindStatus == BindStatus.FAILED || BindStatus == BindStatus.SUCCESSFUL_WITH_MESSAGE)
31+
return $"{BindStatus} ({ErrorMessage})";
32+
33+
return $"{BindStatus}";
34+
}
35+
36+
internal static BindResult Success()
37+
{
38+
BindResult bindResult = new BindResult(BindStatus.SUCCESSFUL);
39+
return bindResult;
40+
}
41+
42+
internal static BindResult Failed(string errorMessage)
43+
{
44+
BindResult bindResult = new BindResult(BindStatus.FAILED, errorMessage);
45+
return bindResult;
46+
}
47+
48+
}
49+
}

Diff for: JankSQL/BindStatus.cs

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
namespace JankSQL
2+
{
3+
public enum BindStatus
4+
{
5+
NOT_BOUND,
6+
SUCCESSFUL,
7+
SUCCESSFUL_WITH_MESSAGE,
8+
FAILED,
9+
}
10+
}

Diff for: JankSQL/Contexts/CommitContext.cs

+5
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,11 @@ public void Dump()
1515
Console.WriteLine("CommitContext");
1616
}
1717

18+
public BindResult Bind(Engines.IEngine engine, IList<FullColumnName> outerColumnNames, IDictionary<string, ExpressionOperand> bindValues)
19+
{
20+
return BindResult.Success();
21+
}
22+
1823
public ExecuteResult Execute(IEngine engine, IRowValueAccessor? accessor, Dictionary<string, ExpressionOperand> bindValues)
1924
{
2025
engine.Commit();

Diff for: JankSQL/Contexts/CreateIndexContext.cs

+6
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,12 @@ public object Clone()
2828
return clone;
2929
}
3030

31+
public BindResult Bind(Engines.IEngine engine, IList<FullColumnName> outerColumnNames, IDictionary<string, ExpressionOperand> bindValues)
32+
{
33+
Console.WriteLine("WARNING: Bind() not implemented for CreateIndexContext");
34+
return new(BindStatus.SUCCESSFUL);
35+
}
36+
3137
public ExecuteResult Execute(IEngine engine, IRowValueAccessor? accessor, Dictionary<string, ExpressionOperand> bindValues)
3238
{
3339
engine.CreateIndex(TableName, IndexName, IsUnique, columnInfo);

Diff for: JankSQL/Contexts/CreateTableContext.cs

+6
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,12 @@ public object Clone()
3333
return context;
3434
}
3535

36+
public BindResult Bind(Engines.IEngine engine, IList<FullColumnName> outerColumnNames, IDictionary<string, ExpressionOperand> bindValues)
37+
{
38+
Console.WriteLine("WARNING: Bind() not implemented for CreateTableContext");
39+
return new(BindStatus.SUCCESSFUL);
40+
}
41+
3642
public ExecuteResult Execute(IEngine engine, IRowValueAccessor? accessor, Dictionary<string, ExpressionOperand> bindValues)
3743
{
3844
engine.CreateTable(tableName, columnNames.ToImmutableList(), columnTypes.ToImmutableList());

Diff for: JankSQL/Contexts/DeleteContext.cs

+13-10
Original file line numberDiff line numberDiff line change
@@ -7,36 +7,39 @@
77
internal class DeleteContext : IExecutableContext
88
{
99
private readonly FullTableName tableName;
10-
private Expression? predicateExpression;
1110

1211
internal DeleteContext(FullTableName tableName)
1312
{
1413
this.tableName = tableName;
1514
}
1615

17-
internal Expression? PredicateExpression
18-
{
19-
get { return predicateExpression; }
20-
set { predicateExpression = value; }
21-
}
16+
internal Expression? PredicateExpression { get; set; }
2217

2318
public object Clone()
2419
{
2520
DeleteContext clone = new (tableName);
26-
clone.predicateExpression = predicateExpression != null ? (Expression?)predicateExpression.Clone() : null;
21+
clone.PredicateExpression = PredicateExpression != null ? (Expression?)PredicateExpression.Clone() : null;
2722
return clone;
2823
}
2924

3025
public void Dump()
3126
{
3227
Console.WriteLine($"DELETE FROM {tableName}");
3328

34-
if (predicateExpression == null)
29+
if (PredicateExpression == null)
3530
Console.WriteLine(" no predicate");
3631
else
37-
Console.WriteLine($" {predicateExpression}");
32+
Console.WriteLine($" {PredicateExpression}");
3833
}
3934

35+
public BindResult Bind(Engines.IEngine engine, IList<FullColumnName> outerColumnNames, IDictionary<string, ExpressionOperand> bindValues)
36+
{
37+
Console.WriteLine("WARNING: Bind() not implemented for DeleteContext");
38+
return new(BindStatus.SUCCESSFUL);
39+
}
40+
41+
42+
4043
public ExecuteResult Execute(IEngine engine, IRowValueAccessor? outerAccessor, Dictionary<string, ExpressionOperand> bindValues)
4144
{
4245
Engines.IEngineTable? tableSource = engine.GetEngineTable(tableName);
@@ -49,7 +52,7 @@ public ExecuteResult Execute(IEngine engine, IRowValueAccessor? outerAccessor, D
4952
{
5053
// found the source table, so load it
5154
TableSource source = new (tableSource);
52-
Delete delete = new (tableSource, source, predicateExpression);
55+
Delete delete = new (tableSource, source, PredicateExpression);
5356

5457
while (true)
5558
{

Diff for: JankSQL/Contexts/DropTableContext.cs

+7
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,13 @@ public void Dump()
1717
Console.WriteLine($"Drop table {tableName}");
1818
}
1919

20+
public BindResult Bind(Engines.IEngine engine, IList<FullColumnName> outerColumnNames, IDictionary<string, ExpressionOperand> bindValues)
21+
{
22+
Console.WriteLine("WARNING: Bind() not implemented for DropTableContext");
23+
return new(BindStatus.SUCCESSFUL);
24+
}
25+
26+
2027
public ExecuteResult Execute(IEngine engine, IRowValueAccessor? accessor, Dictionary<string, ExpressionOperand> bindValues)
2128
{
2229
engine.DropTable(tableName);

Diff for: JankSQL/Contexts/ExecutionContext.cs

+31-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,15 @@
11
namespace JankSQL.Contexts
22
{
3+
/// <summary>
4+
/// An ExecutionContext provide as a context (state) for executing a set of SQL statements.
5+
/// This container holds the set of statements and provides methods for executing exactly one
6+
/// or all of the statements. ExecuteResult values are returned for each executed statement.
7+
/// </summary>
38
public class ExecutionContext
49
{
10+
/// <summary>
11+
/// The list of executed statements.
12+
/// </summary>
513
public List<IExecutableContext> ExecuteContexts { get; set; } = new();
614

715
public void Dump()
@@ -10,6 +18,12 @@ public void Dump()
1018
context.Dump();
1119
}
1220

21+
/// <summary>
22+
/// Execute all statement and return an array of ExecuteResult values about their success.
23+
/// </summary>
24+
/// <param name="engine">IEngine to be used for execution.</param>
25+
/// <param name="bindValues">Dictionary of bind values to provide for the executed statements.</param>
26+
/// <returns></returns>
1327
public ExecuteResult[] Execute(Engines.IEngine engine, Dictionary<string, ExpressionOperand> bindValues)
1428
{
1529
var clonedContexts = new List<IExecutableContext>();
@@ -21,8 +35,14 @@ public ExecuteResult[] Execute(Engines.IEngine engine, Dictionary<string, Expres
2135
{
2236
try
2337
{
24-
ExecuteResult result = context.Execute(engine, null, bindValues);
25-
results.Add(result);
38+
BindResult br = context.Bind(engine, Array.Empty<FullColumnName>(), bindValues);
39+
if (!br.IsSuccessful)
40+
results.Add(ExecuteResult.FailureWithError(br.ErrorMessage));
41+
else
42+
{
43+
ExecuteResult result = context.Execute(engine, null, bindValues);
44+
results.Add(result);
45+
}
2646
}
2747
catch (ExecutionException ex)
2848
{
@@ -35,13 +55,22 @@ public ExecuteResult[] Execute(Engines.IEngine engine, Dictionary<string, Expres
3555
return results.ToArray();
3656
}
3757

58+
/// <summary>
59+
/// Execute a single statement and return an ExecuteResult value about the result.
60+
/// </summary>
61+
/// <param name="engine">IEngine to be used for execution.</param>
62+
/// <param name="bindValues">Dictionary of bind values to provide for the executed statement.</param>
63+
/// <returns></returns>
3864
public ExecuteResult ExecuteSingle(Engines.IEngine engine, Dictionary<string, ExpressionOperand> bindValues)
3965
{
4066
if (ExecuteContexts.Count != 1)
4167
return ExecuteResult.FailureWithError("ExecuteSingle() called on multiple-context batch");
4268
else
4369
{
4470
IExecutableContext clonedContext = (IExecutableContext)ExecuteContexts[0].Clone();
71+
BindResult br = clonedContext.Bind(engine, Array.Empty<FullColumnName>(), bindValues);
72+
if (!br.IsSuccessful)
73+
return ExecuteResult.FailureWithError(br.ErrorMessage);
4574
return clonedContext.Execute(engine, null, bindValues);
4675
}
4776
}

Diff for: JankSQL/Contexts/IExecutableContext.cs

+3
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ public interface IExecutableContext : ICloneable
2424
/// <returns>An ExecuteResult indicating the outcome.</returns>
2525
ExecuteResult Execute(Engines.IEngine engine, IRowValueAccessor? accessor, Dictionary<string, ExpressionOperand> bindValues);
2626

27+
28+
BindResult Bind(Engines.IEngine engine, IList<FullColumnName> outerColumnNames, IDictionary<string, ExpressionOperand> bindValues);
29+
2730
/// <summary>
2831
/// Dump information about this executable context. This call will effectively show
2932
/// an "execution plan".

Diff for: JankSQL/Contexts/InsertContext.cs

+7
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,13 @@ public object Clone()
3636
return clone;
3737
}
3838

39+
public BindResult Bind(Engines.IEngine engine, IList<FullColumnName> outerColumnNames, IDictionary<string, ExpressionOperand> bindValues)
40+
{
41+
Console.WriteLine("WARNING: Bind() not implemented for InsertContext");
42+
return new(BindStatus.SUCCESSFUL);
43+
}
44+
45+
3946
public ExecuteResult Execute(Engines.IEngine engine, IRowValueAccessor? accessor, Dictionary<string, ExpressionOperand> bindValues)
4047
{
4148
if (constructors == null)

Diff for: JankSQL/Contexts/RollbackContext.cs

+6
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,12 @@ public void Dump()
1515
Console.WriteLine("ROLLBACK");
1616
}
1717

18+
public BindResult Bind(Engines.IEngine engine, IList<FullColumnName> outerColumnNames, IDictionary<string, ExpressionOperand> bindValues)
19+
{
20+
Console.WriteLine("WARNING: Bind() not implemented for RollbackContext");
21+
return new(BindStatus.SUCCESSFUL);
22+
}
23+
1824
public ExecuteResult Execute(IEngine engine, IRowValueAccessor? accessor, Dictionary<string, ExpressionOperand> bindValues)
1925
{
2026
engine.Rollback();

0 commit comments

Comments
 (0)