Skip to content

Commit c17a1f5

Browse files
committed
Eliminates secondary table JOIN-only fields from returned DataTable.
Issue: If there's a SELECT * and the raw name of the column isn't what's used in the JOIN, it'll bust. So if we have `Table1` with `Field1` with a raw name of `Fie` and we try... SELECT * FROM Table1 INNER JOIN Table2 ON Table1.Field1 = Table2.Id ... it'll error out. You instead have to use... SELECT * FROM Table1 INNER JOIN Table2 ON Table1.Fie = Table2.Id ... which is awkward. I think I can fix that reasonably easily for the main table, but it'll be a little more difficult -- or at least potentially horribly inefficient -- for secondary tables. I think.
1 parent 354519d commit c17a1f5

File tree

3 files changed

+57
-20
lines changed

3 files changed

+57
-20
lines changed

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

Lines changed: 52 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ public class CommandParts
2828

2929
public Column[] acolInSelect;
3030
public Queue<string> qstrAllColumnNames = new Queue<string>();
31-
public List<string> lstrMainTableJoinONLYFields = new List<string>(); // Sir Not Well Named in this Film.
31+
public List<string> lstrJoinONLYFields = new List<string>(); // Sir Still Not Paricularly Well Named in this Film.
3232
public Dictionary<string, string> dictUpdateColVals = new Dictionary<string, string>();
3333
public Dictionary<string, string> dictFuzzyToColNameMappings = new Dictionary<string, string>();
3434
public Dictionary<string, string> dictRawNamesToASNames = new Dictionary<string, string>();
@@ -148,13 +148,35 @@ private void _parseSelectStatement(string strSql)
148148
// Keep track of the join fields so we can intelligently select but
149149
// not display them if they are/aren't in the SELECT.
150150
// Let's start with the bullheaded way.
151+
152+
// The most natural place to find fields used to join "secondary
153+
// tables" (any table after the first in the FROM list) would
154+
// actually be in _processInnerJoin in SelectCommand, but this is
155+
// already spaghettied enough. So let's dupe some logic and do it
156+
// here.
157+
// TODO: Consider deciphering lists of tables and fields in a
158+
// refactored CommandParts and removing that from SelectCommand, etc.
151159
string strMainTableName = this.strFrom.Substring(4).Trim();
152-
string[] innerKludgeTokenized = this.strInnerJoinKludge.Split();
153-
foreach (string toke in innerKludgeTokenized)
160+
string[] innerKludgeTokenized = this.strInnerJoinKludge.StringToNonWhitespaceTokens2();
161+
Queue<string> qSecondaryTableNames = new Queue<string>();
162+
163+
for (int i=0; i<innerKludgeTokenized.Length; i++)
154164
{
165+
string toke = innerKludgeTokenized[i];
155166
if (toke.ToUpper().StartsWith(strMainTableName.ToUpper()))
156167
{
157-
this.lstrMainTableJoinONLYFields.Add(toke.ReplaceCaseInsensitiveFind(strMainTableName + ".", ""));
168+
this.lstrJoinONLYFields.Add(toke.ReplaceCaseInsensitiveFind(strMainTableName + ".", ""));
169+
}
170+
else if (qSecondaryTableNames.Any(s => toke.ToUpper().StartsWith(s.ToUpper() + "."))) // TODO: this kinda suggests "." can't be in a table or column name either. Don't think we're checking that.
171+
{
172+
this.lstrJoinONLYFields.Add(toke);
173+
}
174+
175+
// TODO: This makes JOIN a pretty hard keyword. I think that's safe, though.
176+
// If you want a table named JOIN, it'll have to be in brackets, right?
177+
if (toke.Equals("JOIN", StringComparison.CurrentCultureIgnoreCase))
178+
{
179+
qSecondaryTableNames.Enqueue(innerKludgeTokenized[i + 1]);
158180
}
159181
}
160182
}
@@ -188,24 +210,39 @@ private void _getColumnsToReturn()
188210
// returning the DataTable.
189211
// NOTE: I'm not taking into account fuzzily matching names, in part
190212
// 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
213+
foreach (string strSelectCols in lstrCmdTokens)
198214
{
199-
foreach (string strMainTableCol in lstrCmdTokens.Where(s => !s.Contains(".") && !s.Contains("*")))
215+
if (strSelectCols.Equals("*"))
200216
{
201-
if (this.lstrMainTableJoinONLYFields.Contains(strMainTableCol))
217+
if (1 == lstrJoinONLYFields.Count())
218+
{
219+
// If we're selecting * from everything, then there are no
220+
// join-only fields/columns.
221+
this.lstrJoinONLYFields = new List<string>();
222+
}
223+
else
202224
{
203-
this.lstrMainTableJoinONLYFields.Remove(strMainTableCol);
225+
// Else we're selecting everything from the main table.
226+
this.lstrJoinONLYFields.RemoveAll(s => !s.Contains("."));
204227
}
205228
}
229+
else if (strSelectCols.Contains("*"))
230+
{
231+
// Find what table we're removing jive from, then find all cols
232+
// that start with that prefix.
233+
// TODO: Double check if we every drop requirement to prefix join
234+
// columns with table names, though I don't think we will.
235+
// TODO: This all goes to heck when we alias JOIN table names. Idiot.
236+
string str2ndaryTable = strSelectCols.ReplaceCaseInsensitiveFind(".*", "");
237+
this.lstrJoinONLYFields.RemoveAll(s => s.StartsWith(str2ndaryTable + "."));
238+
}
239+
else if (this.lstrJoinONLYFields.Contains(strSelectCols))
240+
{
241+
this.lstrJoinONLYFields.Remove(strSelectCols);
242+
}
206243
}
207244

208-
foreach (string strJoinColName in this.lstrMainTableJoinONLYFields)
245+
foreach (string strJoinColName in this.lstrJoinONLYFields)
209246
{
210247
lstrCmdTokens.Add(strJoinColName);
211248
}

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,9 +104,9 @@ public DataTable executeStatement(string strSql)
104104
// TODO: There are better ways to do this.
105105
// TODO: Figure out if this handles all fuzzy name translations
106106
// earlier in the SELECT process.
107-
if (selectParts.lstrMainTableJoinONLYFields.Count() > 0)
107+
if (selectParts.lstrJoinONLYFields.Count() > 0)
108108
{
109-
foreach (string colName in selectParts.lstrMainTableJoinONLYFields)
109+
foreach (string colName in selectParts.lstrJoinONLYFields)
110110
{
111111
dtReturn.Columns.Remove(colName);
112112
}

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
// ======================== EO LICENSE ===============================
1212

1313

14-
### VERSION 0.0.4.2: Nothing is guaranteed to work. NOTHING. Use at your own risk.
14+
### VERSION 0.0.4.3: Nothing is guaranteed to work. NOTHING. Use at your own risk.
1515

1616
###Usage
1717

@@ -41,9 +41,9 @@ Step 2: Use the code below *at your own risk*.
4141
###Mac OS X Notes
4242
SqlDb# as a library works fine on Xamarin.Mac or MonoMac.
4343

44-
**The Isql project**, however, does not echo content entered into a `Console.Read` or `.ReadLine()`, so you can't, for example, see what you're typing in as your SQL statement. I've [filed a bug](https://bugzilla.xamarin.com/show_bug.cgi?id=22262) with Xamarin, but it hasn't gotten much attention. That's somewhat understandable; I haven't been able to make a test case simpler than SqlDb#'s Isql project that exhibits this behavior.
44+
**The Isql project**, when run on OS X, however, does not echo content entered into a `Console.Read` or `.ReadLine()`, so you can't, for example, see what you're typing in as your SQL statement. I've [filed a bug](https://bugzilla.xamarin.com/show_bug.cgi?id=22262) with Xamarin, but it hasn't gotten much attention. That's somewhat understandable; I haven't been able to make a test case simpler than SqlDb#'s Isql project that exhibits this behavior.
4545

46-
To avoid this echo issue when *developing SqlDb#* (not developing *against* or using; again, the library works fine) using MonoMac or Xamarin.Mac, please use the `MacUI` branch (which contains a native UI ISQL client), merge latest from the `master` branch, set `SqlDbSharpMacUI` as your startup project, and use that interface to run queries during development.
46+
To avoid this echo issue when *developing SqlDb#* (not developing *against* or using; again, the library works fine afaict) using MonoMac or Xamarin.Mac, please use the `MacUI` branch (which contains a native UI ISQL client), merge latest from the `master` branch, set `SqlDbSharpMacUI` as your startup project, and use that interface to run queries during development.
4747

4848
<img src="http://rufwork.com/code/SqlDbSharp/MacIsql.png"><br>
4949

0 commit comments

Comments
 (0)