Skip to content

Commit 985812b

Browse files
committed
some fixes for ambiguous column references
1 parent 55b4643 commit 985812b

File tree

6 files changed

+151
-11
lines changed

6 files changed

+151
-11
lines changed

JankSQL/Expressions/ResultSetValueAccessor.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
namespace JankSQL.Expressions
22
{
33
/// <summary>
4-
/// Wraps a row set and accepts a row index so an individual row
4+
/// Wraps a ResultSet and accepts a row index so an individual row
55
/// can be accessed by Expression.Evaluate().
66
/// </summary>
77
internal class ResultSetValueAccessor : IRowValueAccessor
@@ -19,7 +19,7 @@ public ExpressionOperand GetValue(FullColumnName fcn)
1919
{
2020
int idx = resultSet.ColumnIndex(fcn);
2121
if (idx == -1)
22-
throw new ExecutionException($"Invalid column name {fcn}; valid names are {string.Join(",", resultSet.GetColumnNames())}");
22+
throw new ExecutionException($"Invalid column name {fcn}; valid names are {string.Join(", ", resultSet.GetColumnNames())}");
2323

2424
Tuple thisRow = resultSet.Row(rowIndex);
2525
ExpressionOperand val = thisRow[idx];

JankSQL/Expressions/TemporaryRowValueAccessor.cs

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
namespace JankSQL.Expressions
1+
using System.Xml.Linq;
2+
3+
namespace JankSQL.Expressions
24
{
35
/// <summary>
46
/// wraps a discrete row and a list of column names to be used by
@@ -17,28 +19,43 @@ internal TemporaryRowValueAccessor(Tuple rowData, IEnumerable<FullColumnName> na
1719

1820
ExpressionOperand IRowValueAccessor.GetValue(FullColumnName fcn)
1921
{
22+
int ret = -1;
2023
for (int i = 0; i < names.Length; i++)
2124
{
2225
if (names[i].Equals(fcn))
23-
return rowData[i];
26+
{
27+
if (ret != -1)
28+
throw new ExecutionException($"column name {fcn} is ambiguous because it matches both {names[ret]} and {names[i]}");
29+
ret = i;
30+
}
2431
}
2532

33+
if (ret != -1)
34+
return rowData[ret];
35+
2636
throw new ExecutionException($"column {fcn} not found in TemporaryRowValueAccessor; available are {string.Join(",", (object[])names)}");
2737
}
2838

2939
void IRowValueAccessor.SetValue(FullColumnName fcn, ExpressionOperand op)
3040
{
41+
int ret = -1;
3142
for (int i = 0; i < names.Length; i++)
3243
{
3344
if (names[i].Equals(fcn))
3445
{
35-
rowData[i] = op;
36-
return;
46+
if (ret != -1)
47+
throw new ExecutionException($"column name {fcn} is ambiguous because it matches both {names[ret]} and {names[i]}");
48+
ret = i;
3749
}
3850
}
3951

52+
if (ret != - 1)
53+
{
54+
rowData[ret] = op;
55+
return;
56+
}
57+
4058
throw new ExecutionException($"column {fcn} not found in TemporaryRowValueAccessor; available are {string.Join(",", (object[])names)}");
4159
}
42-
4360
}
4461
}

JankSQL/ResultSet.cs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
namespace JankSQL
22
{
33
using System.Collections.Immutable;
4+
using System.Xml;
45

56
public class ResultSet
67
{
@@ -33,7 +34,18 @@ internal bool IsEOF
3334

3435
public int ColumnIndex(FullColumnName name)
3536
{
36-
return Array.IndexOf(columnNames, name);
37+
int ret = -1;
38+
for (int i = 0; i < columnNames.Length; i++)
39+
{
40+
if (columnNames[i].Equals(name))
41+
{
42+
if (ret != -1)
43+
throw new ExecutionException($"column name {name} is ambiguous because it matches both {columnNames[ret]} and {columnNames[i]}");
44+
ret = i;
45+
}
46+
}
47+
48+
return ret;
3749
}
3850

3951
public Tuple Row(int index)

Tests/AggregateTests.cs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ abstract public class AggregateTests
1515
public void TestMinMaxGroupByOutput()
1616
{
1717
var ec = Parser.ParseSQLFileFromString("SELECT is_even, MIN(number_name), MAX(number_name) FROM ten GROUP BY is_even");
18+
JankAssert.SuccessfulParse(ec);
1819

1920
ExecuteResult result = ec.ExecuteSingle(engine);
2021
JankAssert.RowsetExistsWithShape(result, 3, 2);
@@ -50,6 +51,7 @@ public void TestMinMaxGroupByOutput()
5051
public void TestMinMaxGroupByOutputNoRows()
5152
{
5253
var ec = Parser.ParseSQLFileFromString("SELECT is_even, MIN(number_name), MAX(number_name) FROM ten WHERE 1 = 0 GROUP BY is_even");
54+
JankAssert.SuccessfulParse(ec);
5355

5456
ExecuteResult result = ec.ExecuteSingle(engine);
5557
JankAssert.RowsetExistsWithShape(result, 3, 0);
@@ -60,6 +62,7 @@ public void TestMinMaxGroupByOutputNoRows()
6062
public void TestMinMaxGroupByNoOutput()
6163
{
6264
var ec = Parser.ParseSQLFileFromString("SELECT MIN(number_name), MAX(number_name) FROM ten GROUP BY is_even");
65+
JankAssert.SuccessfulParse(ec);
6366

6467
ExecuteResult result = ec.ExecuteSingle(engine);
6568
JankAssert.RowsetExistsWithShape(result, 2, 2);
@@ -90,6 +93,7 @@ public void TestMinMaxGroupByNoOutput()
9093
public void TestMinMaxGroupByNoOutputNoRows()
9194
{
9295
var ec = Parser.ParseSQLFileFromString("SELECT MIN(number_name), MAX(number_name) FROM ten WHERE 1 = 0 GROUP BY is_even");
96+
JankAssert.SuccessfulParse(ec);
9397

9498
ExecuteResult result = ec.ExecuteSingle(engine);
9599
JankAssert.RowsetExistsWithShape(result, 2, 0);
@@ -101,6 +105,7 @@ public void TestMinMaxGroupByNoOutputNoRows()
101105
public void TestSimpleSum()
102106
{
103107
var ec = Parser.ParseSQLFileFromString("SELECT SUM(number_id) FROM ten");
108+
JankAssert.SuccessfulParse(ec);
104109

105110
ExecuteResult result = ec.ExecuteSingle(engine);
106111
JankAssert.RowsetExistsWithShape(result, 1, 1);
@@ -113,6 +118,7 @@ public void TestSimpleSum()
113118
public void TestSimpleSumNoRows()
114119
{
115120
var ec = Parser.ParseSQLFileFromString("SELECT SUM(number_id) FROM ten WHERE 1 = 0;");
121+
JankAssert.SuccessfulParse(ec);
116122

117123
ExecuteResult result = ec.ExecuteSingle(engine);
118124
JankAssert.RowsetExistsWithShape(result, 1, 1);
@@ -125,6 +131,7 @@ public void TestSimpleSumNoRows()
125131
public void TestSimpleSumCount()
126132
{
127133
var ec = Parser.ParseSQLFileFromString("SELECT SUM(number_id), COUNT(number_id) FROM kiloLeft");
134+
JankAssert.SuccessfulParse(ec);
128135

129136
ExecuteResult result = ec.ExecuteSingle(engine);
130137
JankAssert.RowsetExistsWithShape(result, 2, 1);
@@ -138,6 +145,7 @@ public void TestSimpleSumCount()
138145
public void TestSumCountNoRows()
139146
{
140147
var ec = Parser.ParseSQLFileFromString("SELECT SUM(number_id), COUNT(number_id) FROM ten WHERE 1 = 0");
148+
JankAssert.SuccessfulParse(ec);
141149

142150
ExecuteResult result = ec.ExecuteSingle(engine);
143151
JankAssert.RowsetExistsWithShape(result, 2, 1);
@@ -152,6 +160,7 @@ public void TestSumCountNoRows()
152160
public void TestMinMax()
153161
{
154162
var ec = Parser.ParseSQLFileFromString("SELECT MIN(number_id), MAX(number_id) FROM ten ");
163+
JankAssert.SuccessfulParse(ec);
155164

156165
ExecuteResult result = ec.ExecuteSingle(engine);
157166
JankAssert.RowsetExistsWithShape(result, 2, 1);
@@ -166,6 +175,7 @@ public void TestMinMax()
166175
public void TestMinMaxFiltered()
167176
{
168177
var ec = Parser.ParseSQLFileFromString("SELECT MIN(number_id), MAX(number_id) FROM ten WHERE is_even = 1");
178+
JankAssert.SuccessfulParse(ec);
169179

170180
ExecuteResult result = ec.ExecuteSingle(engine);
171181
JankAssert.RowsetExistsWithShape(result, 2, 1);
@@ -179,6 +189,7 @@ public void TestMinMaxFiltered()
179189
public void TestMinMaxNoRows()
180190
{
181191
var ec = Parser.ParseSQLFileFromString("SELECT MIN(number_id), MAX(number_id) FROM ten WHERE 1 = 0");
192+
JankAssert.SuccessfulParse(ec);
182193

183194
ExecuteResult result = ec.ExecuteSingle(engine);
184195
JankAssert.RowsetExistsWithShape(result, 2, 1);
@@ -192,6 +203,7 @@ public void TestMinMaxNoRows()
192203
public void TestOneExpressionSumCount()
193204
{
194205
var ec = Parser.ParseSQLFileFromString("SELECT 23 * SUM(number_id), COUNT(number_id) FROM ten");
206+
JankAssert.SuccessfulParse(ec);
195207

196208
ExecuteResult result = ec.ExecuteSingle(engine);
197209
JankAssert.RowsetExistsWithShape(result, 2, 1);
@@ -205,6 +217,7 @@ public void TestOneExpressionSumCount()
205217
public void TestOneExpressionSumCountNoRows()
206218
{
207219
var ec = Parser.ParseSQLFileFromString("SELECT 23 * SUM(number_id), COUNT(number_id) FROM ten WHERE 1 = 0");
220+
JankAssert.SuccessfulParse(ec);
208221

209222
ExecuteResult result = ec.ExecuteSingle(engine);
210223
JankAssert.RowsetExistsWithShape(result, 2, 1);
@@ -218,6 +231,7 @@ public void TestOneExpressionSumCountNoRows()
218231
public void TestTwoExpressionSumCount()
219232
{
220233
var ec = Parser.ParseSQLFileFromString("SELECT 10* SUM(number_id), COUNT(number_id) * 100 FROM ten");
234+
JankAssert.SuccessfulParse(ec);
221235

222236
ExecuteResult result = ec.ExecuteSingle(engine);
223237
JankAssert.RowsetExistsWithShape(result, 2, 1);
@@ -232,6 +246,7 @@ public void TestTwoExpressionSumCount()
232246
public void TestTwoSumExpressionCountExpression()
233247
{
234248
var ec = Parser.ParseSQLFileFromString("SELECT SUM(number_id * 10), COUNT(number_id * 100) FROM ten");
249+
JankAssert.SuccessfulParse(ec);
235250

236251
ExecuteResult result = ec.ExecuteSingle(engine);
237252
JankAssert.RowsetExistsWithShape(result, 2, 1);
@@ -245,6 +260,7 @@ public void TestTwoSumExpressionCountExpression()
245260
public void TestTwoSumGroupByOutputGrouped()
246261
{
247262
var ec = Parser.ParseSQLFileFromString("SELECT is_even, SUM(number_id * 10), COUNT(number_id * 100) FROM ten GROUP BY is_even");
263+
JankAssert.SuccessfulParse(ec);
248264

249265
ExecuteResult result = ec.ExecuteSingle(engine);
250266
JankAssert.RowsetExistsWithShape(result, 3, 2);
@@ -280,6 +296,7 @@ public void TestTwoSumGroupByOutputGrouped()
280296
public void TestIntegerSimpleAverage()
281297
{
282298
var ec = Parser.ParseSQLFileFromString("SELECT AVG(number_id) FROM ten");
299+
JankAssert.SuccessfulParse(ec);
283300

284301
ExecuteResult result = ec.ExecuteSingle(engine);
285302
JankAssert.RowsetExistsWithShape(result, 1, 1);
@@ -294,6 +311,7 @@ public void TestIntegerSimpleAverage()
294311
public void TestIntegerSimpleAverageNoRows()
295312
{
296313
var ec = Parser.ParseSQLFileFromString("SELECT AVG(number_id) FROM ten WHERE 1 = 0");
314+
JankAssert.SuccessfulParse(ec);
297315

298316
ExecuteResult result = ec.ExecuteSingle(engine);
299317
JankAssert.RowsetExistsWithShape(result, 1, 1);
@@ -306,6 +324,7 @@ public void TestIntegerSimpleAverageNoRows()
306324
public void TestDecimalSimpleAverage()
307325
{
308326
var ec = Parser.ParseSQLFileFromString("SELECT AVG(population) FROM myTable;");
327+
JankAssert.SuccessfulParse(ec);
309328

310329
ExecuteResult result = ec.ExecuteSingle(engine);
311330
JankAssert.RowsetExistsWithShape(result, 1, 1);
@@ -318,6 +337,7 @@ public void TestDecimalSimpleAverage()
318337
public void TestDecimalSimpleAverageNoRows()
319338
{
320339
var ec = Parser.ParseSQLFileFromString("SELECT AVG(population) FROM myTable WHERE 1=0;");
340+
JankAssert.SuccessfulParse(ec);
321341

322342
ExecuteResult result = ec.ExecuteSingle(engine);
323343
JankAssert.RowsetExistsWithShape(result, 1, 1);
@@ -331,6 +351,7 @@ public void TestDecimalSimpleAverageNoRows()
331351
public void TestDecimalSimpleAverageNull()
332352
{
333353
var ec = Parser.ParseSQLFileFromString("SELECT AVG(population + NULL) FROM myTable;");
354+
JankAssert.SuccessfulParse(ec);
334355

335356
ExecuteResult result = ec.ExecuteSingle(engine);
336357
JankAssert.RowsetExistsWithShape(result, 1, 1);
@@ -344,6 +365,7 @@ public void TestDecimalSimpleAverageNull()
344365
public void TestDecimalSimpleSumNull()
345366
{
346367
var ec = Parser.ParseSQLFileFromString("SELECT SUM(population + NULL) FROM myTable;");
368+
JankAssert.SuccessfulParse(ec);
347369

348370
ExecuteResult result = ec.ExecuteSingle(engine);
349371
JankAssert.RowsetExistsWithShape(result, 1, 1);
@@ -356,6 +378,7 @@ public void TestDecimalSimpleSumNull()
356378
public void TestDecimalSimpleCountNull()
357379
{
358380
var ec = Parser.ParseSQLFileFromString("SELECT COUNT(population + NULL) FROM myTable;");
381+
JankAssert.SuccessfulParse(ec);
359382

360383
ExecuteResult result = ec.ExecuteSingle(engine);
361384
JankAssert.RowsetExistsWithShape(result, 1, 1);
@@ -368,6 +391,7 @@ public void TestDecimalSimpleCountNull()
368391
public void TestIntegerCastAverage()
369392
{
370393
var ec = Parser.ParseSQLFileFromString("SELECT AVG(CAST(number_id AS DECIMAL)) FROM ten");
394+
JankAssert.SuccessfulParse(ec);
371395

372396
ExecuteResult result = ec.ExecuteSingle(engine);
373397
JankAssert.RowsetExistsWithShape(result, 1, 1);
@@ -382,6 +406,7 @@ public void TestIntegerCastAverage()
382406
public void TestIntegerCastAverageNoRows()
383407
{
384408
var ec = Parser.ParseSQLFileFromString("SELECT AVG(CAST(number_id AS DECIMAL)) FROM ten WHERE 1 = 0");
409+
JankAssert.SuccessfulParse(ec);
385410

386411
ExecuteResult result = ec.ExecuteSingle(engine);
387412
JankAssert.RowsetExistsWithShape(result, 1, 1);
@@ -394,6 +419,7 @@ public void TestIntegerCastAverageNoRows()
394419
public void TestNotCoveredGroupingSelect()
395420
{
396421
var ec = Parser.ParseSQLFileFromString("SELECT number_name, MIN(number_name), MAX(number_name) FROM ten GROUP BY is_even");
422+
JankAssert.SuccessfulParse(ec);
397423

398424
ExecuteResult result = ec.ExecuteSingle(engine);
399425
JankAssert.FailureWithMessage(result);

0 commit comments

Comments
 (0)