Skip to content

Commit 8abbd6b

Browse files
committed
Fields from "main" table not in SELECT no longer returned by INNER JOINs that require them.
* For example, `SELECT field1, field2, table2.field1 FROM table1 INNER JOIN table2 ON table1.t2Id = table2.id` will no longer return `table1.t2Id`. * It does, however, still return `table2.id`, which I'll take a look at next (and potentially not increment the version). * The method used here is particularly bullheaded, spaghetti-ish, and inane: Added section to `_parseSelectStatement` in CommandParts that for fields in JOIN that belong to the "main" table. `_getColumnsToReturn` sees which of those are already in the SELECT and removes them from the CommandParts' lstrMainTableJoinONLYFields It also adds any columns not in the SELECT, but ignores any fuzzy name ramifications throughout. SelectCommand's executeStatement then adds a step to its POST-PROCESS INNER JOINS section, where it removes any columns from the main table in the JOIN but not in the SELECT, from the DataTable before returning it. So it *is* pulling the join fields back before taking them out. Not exceptionally well tested. Will try to set more up when I take out fields from joined tables as well.
1 parent d467d47 commit 8abbd6b

File tree

5 files changed

+80
-7
lines changed

5 files changed

+80
-7
lines changed

BinaryReaderPlay/Main.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ public class MainClass
2020
// Right now, on Windows, that's "C:\\Users\\YourUserName\\Documents\\MooresDbPlay"
2121
//public static readonly string cstrDbDir = Utils.cstrHomeDir + Path.DirectorySeparatorChar + "MooresDbPlay";
2222
public static bool bDebug = false;
23-
public static string buildData = "20150410"; // not always incremented with each build.
24-
public static string version = "0.0.4.2";
23+
public static string buildData = "20150513"; // not always incremented with each build.
24+
public static string version = "0.0.4.3";
2525

2626
public static void logIt(string strMsg)
2727
{

BinaryReaderPlay/org/rufwork/mooresDb/infrastructure/commands/Processors/CommandParts.cs

Lines changed: 51 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using org.rufwork.mooresDb.infrastructure.contexts;
77
using org.rufwork.mooresDb.infrastructure.tableParts;
88
using org.rufwork.extensions;
9+
using org.rufwork.mooresDb.exceptions;
910

1011
namespace org.rufwork.mooresDb.infrastructure.commands.Processors
1112
{
@@ -27,6 +28,7 @@ public class CommandParts
2728

2829
public Column[] acolInSelect;
2930
public Queue<string> qstrAllColumnNames = new Queue<string>();
31+
public List<string> lstrMainTableJoinONLYFields = new List<string>(); // Sir Not Well Named in this Film.
3032
public Dictionary<string, string> dictUpdateColVals = new Dictionary<string, string>();
3133
public Dictionary<string, string> dictFuzzyToColNameMappings = new Dictionary<string, string>();
3234
public Dictionary<string, string> dictRawNamesToASNames = new Dictionary<string, string>();
@@ -133,7 +135,7 @@ private void _parseSelectStatement(string strSql)
133135
this.strFrom = strSql.Substring(intIndexOf, intTail - intIndexOf);
134136

135137
// Look for inner join.
136-
// TODO: Another reserved word that we don't really want a table to be named ("join").
138+
// TODO: Another reserved word that we don't really want a table to be named: ("join").
137139
this.strInnerJoinKludge = "";
138140
if (this.strFrom.IndexOf(" join ", StringComparison.CurrentCultureIgnoreCase) > -1)
139141
{
@@ -143,8 +145,22 @@ private void _parseSelectStatement(string strSql)
143145
this.strInnerJoinKludge = this.strFrom.Substring(intInnerJoin);
144146
this.strFrom = this.strFrom.Substring(0, intInnerJoin);
145147

146-
// TODO: Check the WHERE clause to see if anything belongs to the JOIN.
147-
//do that ^^^
148+
// Keep track of the join fields so we can intelligently select but
149+
// not display them if they are/aren't in the SELECT.
150+
// Let's start with the bullheaded way.
151+
string strMainTableName = this.strFrom.Substring(4).Trim();
152+
string[] innerKludgeTokenized = this.strInnerJoinKludge.Split();
153+
foreach (string toke in innerKludgeTokenized)
154+
{
155+
if (toke.ToUpper().StartsWith(strMainTableName.ToUpper()))
156+
{
157+
this.lstrMainTableJoinONLYFields.Add(toke.ReplaceCaseInsensitiveFind(strMainTableName + ".", ""));
158+
}
159+
}
160+
}
161+
else
162+
{
163+
throw new SyntaxException("Statement includes `join` keyword. Currently, only inner joins are supported.");
148164
}
149165
}
150166

@@ -163,7 +179,38 @@ private void _parseSelectStatement(string strSql)
163179
private void _getColumnsToReturn()
164180
{
165181
Queue<Column> qCols = new Queue<Column>();
166-
string[] astrCmdTokens = this.strSelect.StringToNonWhitespaceTokens2().Skip(1).ToArray(); // Skip 1 to ignore SELECT.
182+
List<string> lstrCmdTokens = this.strSelect.StringToNonWhitespaceTokens2().Skip(1).ToList(); // Skip 1 to ignore SELECT.
183+
184+
if (!string.IsNullOrEmpty(this.strInnerJoinKludge))
185+
{
186+
// TODO: Clean this kludge to get in INNER JOIN fields into datatable
187+
// while selecting, but to remove these once we're done before
188+
// returning the DataTable.
189+
// NOTE: I'm not taking into account fuzzily matching names, in part
190+
// because I'm planning to remove that painful feature.
191+
if (lstrCmdTokens.Contains("*"))
192+
{
193+
// If we're selecting everything from the main table,
194+
// no additional columns are needed.
195+
this.lstrMainTableJoinONLYFields = new List<string>();
196+
}
197+
else
198+
{
199+
foreach (string strMainTableCol in lstrCmdTokens.Where(s => !s.Contains(".") && !s.Contains("*")))
200+
{
201+
if (this.lstrMainTableJoinONLYFields.Contains(strMainTableCol))
202+
{
203+
this.lstrMainTableJoinONLYFields.Remove(strMainTableCol);
204+
}
205+
}
206+
}
207+
208+
foreach (string strJoinColName in this.lstrMainTableJoinONLYFields)
209+
{
210+
lstrCmdTokens.Add(strJoinColName);
211+
}
212+
} // end kludge for grafting main table join fields not explicitly in SELECT list.
213+
string[] astrCmdTokens = lstrCmdTokens.ToArray();
167214

168215
for (int i = 0; i < astrCmdTokens.Length; i++)
169216
{

BinaryReaderPlay/org/rufwork/mooresDb/infrastructure/commands/SelectCommand.cs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,11 +65,15 @@ public DataTable executeStatement(string strSql)
6565

6666
WhereProcessor.ProcessRows(ref dtReturn, _table, selectParts);
6767

68+
69+
//=====================================================================
70+
// POST-PROCESS INNER JOINS
6871
// (Joins are only in selects, so this isn't part of WhereProcessing.)
6972
//
7073
// To take account of joins, we basically need to create a SelectParts
7174
// per inner join. So we need to create a WHERE from the table we
7275
// just selected and then send those values down to a new _selectRows.
76+
//=====================================================================
7377
if (selectParts.strInnerJoinKludge.Length > 0)
7478
{
7579
if (selectParts.qInnerJoinFields.Count < 1)
@@ -96,12 +100,27 @@ public DataTable executeStatement(string strSql)
96100
{
97101
dtReturn.Columns[astrFromSelect[i]].SetOrdinal(i);
98102
}
103+
104+
// TODO: There are better ways to do this.
105+
// TODO: Figure out if this handles all fuzzy name translations
106+
// earlier in the SELECT process.
107+
if (selectParts.lstrMainTableJoinONLYFields.Count() > 0)
108+
{
109+
foreach (string colName in selectParts.lstrMainTableJoinONLYFields)
110+
{
111+
dtReturn.Columns.Remove(colName);
112+
}
113+
}
99114
}
100115
catch (Exception e)
101116
{
102117
throw new SyntaxException("Problem reordering columns in inner join -- " + e.ToString());
103118
}
104119
}
120+
//=====================================================================
121+
// EO POST-PROCESS INNER JOINS
122+
//=====================================================================
123+
105124

106125
// strOrderBy has had all whitespace shortened to one space, so we can get away with the hardcoded 9.
107126
if (null != selectParts.strOrderBy && selectParts.strOrderBy.Length > 9)

ISQL/org/rufwork/mooresDb/clients/Isql.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ INNER JOIN rest
198198

199199
if (objResult is DataTable)
200200
{
201-
Console.WriteLine(InfrastructureUtils.dataTableToString((DataTable)objResult, intWindowWidth));
201+
Console.WriteLine(InfrastructureUtils.dataTableToString((DataTable)objResult, intWindowWidth-1));
202202
}
203203
else if (objResult is string)
204204
{

ReleaseNotes.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
#Release notes:
22
<br>
33

4+
##0.0.4.3 - 20150513
5+
6+
* Fields from "main" table not explicitly mentioned in the SELECT are no longer returned by INNER JOINs that require them.
7+
* For example, `SELECT field1, field2, table2.field1 FROM table1 INNER JOIN table2 ON table1.t2Id = table2.id` will no longer return `table1.t2Id`.
8+
* It does, however, still return `table2.id`, which I'll take a look at next (and potentially not increment the version).
9+
* The method used here is particularly bullheaded, spaghetti-ish, and inane.
10+
411
##0.0.4.2 - 20150410
512

613
* `AS` support for *columns only* added.

0 commit comments

Comments
 (0)