public PredicateStep ParsePredicates(string query) { var predicates = new List <string>(); List <string> queryParts = SplitOnSeparatorsExceptQuotesAndParantheses(query, new char[] { ' ', '\r', '\n' }); var whereClauseIndex = queryParts.IndexOf("where"); int?operatorIndex = null; if (whereClauseIndex != -1) { string firstPredicate = queryParts[whereClauseIndex + 0] + " " + queryParts[whereClauseIndex + 1] + " " + queryParts[whereClauseIndex + 2] + " " + queryParts[whereClauseIndex + 3]; predicates.Add(firstPredicate); operatorIndex = whereClauseIndex + 4; HashSet <string> andOrOps = new HashSet <string> { "or", "and" }; while (operatorIndex < queryParts.Count() && andOrOps.Contains(queryParts[(int)operatorIndex].ToLower())) { string currentPredicate = queryParts[(int)operatorIndex + 0] + " " + queryParts[(int)operatorIndex + 1] + " " + queryParts[(int)operatorIndex + 2] + " " + queryParts[(int)operatorIndex + 3]; predicates.Add(currentPredicate); operatorIndex += 4; } } PredicateStep predicateStep = new PredicateStep { Predicates = predicates, HasPredicates = true, OperatorIndex = operatorIndex, QueryParts = queryParts }; return(predicateStep); }
public List <List <IComparable> > RunQuery(string query) { var tableName = _selectParser.GetTableName(query); var tableDef = _schemaFetcher.GetTableDefinition(tableName); List <SelectColumnDto> columns = _selectParser.GetColumns(query); IEnumerable <SelectColumnDto> selects = tableDef.ColumnDefinitions .Select(x => new SelectColumnDto(x)).OrderBy(x => x.Index).ToList(); foreach (var select in selects) { if (columns.Select(x => x.ColumnName).Contains(select.ColumnName) || columns.First().ColumnName == "*") { select.IsInSelect = true; SelectColumnDto firstMatchingColumn = columns.FirstOrDefault(x => x.ColumnName == select.ColumnName); if (firstMatchingColumn != null) { select.AggregateFunction = firstMatchingColumn.AggregateFunction; } } } PredicateStep predicateStep = _selectParser.ParsePredicates(query); predicateStep = _selectParser.GetPredicateTrailers(predicateStep, query); var predicateOperations = _predicateParser.BuildPredicateOperations(tableDef, predicateStep.Predicates); var readTransaction = new ReadTransaction { TableDefinition = tableDef, Selects = selects, PredicateOperations = predicateOperations }; var rows = _lockManager.ProcessReadTransaction(readTransaction).Rows; if (predicateStep.PredicateTrailer != null && predicateStep.PredicateTrailer.Any()) { rows = ApplyGroupByOperation(selects, predicateStep, rows); rows = ProcessPostPredicateOrderBy(selects, predicateStep, rows); } return(rows); }
public PredicateStep GetPredicateTrailers(PredicateStep predicateStep, string query) { int startTrailingPredicate = predicateStep.OperatorIndex == null? IndexOfTableName(query, GetTableName(query)) + 1 : (int)predicateStep.OperatorIndex; List <string> predicateTrailersUnparsed = string.Join(' ', predicateStep.QueryParts.GetRange(startTrailingPredicate, predicateStep.QueryParts.Count() - startTrailingPredicate)) .ToLower() .Split(new[] { " ", ",", "by" }, StringSplitOptions.RemoveEmptyEntries) .Where(x => !string.IsNullOrEmpty(x)).ToList(); predicateStep.PredicateTrailer = ParsePredicateTrailers(predicateTrailersUnparsed); return(predicateStep); }
private List <List <IComparable> > ApplyGroupByOperation(IEnumerable <SelectColumnDto> selects, PredicateStep predicateStep, List <List <IComparable> > rows) { Func <IComparable, List <List <IComparable> >, IEnumerable <KeyValuePair <int, Func <List <IComparable>, IComparable> > >, List <IComparable> > processGrouping = ReturnGroupedList; //first, group by var groupByClause = predicateStep.PredicateTrailer.Where(x => x.Contains("group")).FirstOrDefault(); if (groupByClause == null) { return(rows); } var groupParts = groupByClause.Split(' '); if (groupParts.Count() > 2) { throw new Exception(ErrorMessages.One_Column_Max_In_Group_By); } string groupingColumn = groupParts[1].ToLower(); selects = selects.Where(x => x.IsInSelect); int groupColumnIndex = selects.Select(x => x.ColumnName.ToLower()).ToList().IndexOf(groupingColumn); var columnIndexToAggregateFunction = selects.Select((x, i) => new KeyValuePair <int, Func <List <IComparable>, IComparable> >(i, x.AggregateFunction)).ToList(); var groupings = rows.GroupBy(x => x[groupColumnIndex]); var aggregatedRows = new List <List <IComparable> >(); foreach (var grouping in groupings) { List <List <IComparable> > groupingValues = grouping.Select(x => x).ToList(); List <IComparable> groupedRow = ReturnGroupedList(grouping.Key, groupingValues, columnIndexToAggregateFunction); aggregatedRows.Add(groupedRow); } return(aggregatedRows); }
private List <List <IComparable> > ProcessPostPredicateOrderBy(IEnumerable <SelectColumnDto> selects, PredicateStep predicateStep, List <List <IComparable> > rows) { //first, group by var orderByClause = predicateStep.PredicateTrailer.FirstOrDefault(x => x.Contains("order")); if (orderByClause == null) { return(rows); } var orderParts = orderByClause.Split(' '); //storing an inenumerable in a temporary list and then adding the "then by" //clause does not work. changes to an ienumerable are not guaranteed to persist switch (orderParts.Count()) { case 2: var select = selects.Where(x => x.ColumnName == orderParts[1]).FirstOrDefault(); rows = rows.OrderBy(x => x[select.Index]).ToList(); break; case 3: var selectCase2 = selects.Where(x => x.ColumnName == orderParts[1]).FirstOrDefault(); var selectCase2_2 = selects.Where(x => x.ColumnName == orderParts[2]).FirstOrDefault(); rows = rows.OrderBy(x => x[selectCase2.Index]).ThenBy(x => x[selectCase2_2.Index]).ToList(); break; case 4: var selectCase3 = selects.Where(x => x.ColumnName == orderParts[1]).FirstOrDefault(); var selectCase3_2 = selects.Where(x => x.ColumnName == orderParts[2]).FirstOrDefault(); var selectCase3_3 = selects.Where(x => x.ColumnName == orderParts[3]).FirstOrDefault(); rows = rows.OrderBy(x => x[selectCase3.Index]).ThenBy(x => x[selectCase3_2.Index]). ThenBy(x => x[selectCase3_3.Index]).ToList(); break; default: throw new Exception(ErrorMessages.Three_Column_Max_In_Order_By); } return(rows); }
private object RunUpdateStatement(string sql) { List <KeyValuePair <string, string> > columnToValue = _updateParser.GetUpdates(sql); var tableName = _updateParser.GetTableName(sql); var tableDef = _schemaFetcher.GetTableDefinition(tableName); PredicateStep predicateStep = _updateParser.ParsePredicates(sql); var predicateOperations = _predicateParser.BuildPredicateOperations(tableDef, predicateStep.Predicates); var selects = tableDef.ColumnDefinitions .Select(x => new SelectColumnDto(x)).OrderBy(x => x.Index).ToList(); selects.ForEach(x => x.IsInSelect = true); var readTransaction = new ReadTransaction { TableDefinition = tableDef, Selects = selects, PredicateOperations = predicateOperations }; var selectData = _lockManager.ProcessReadTransaction(readTransaction); var columnDefs = new List <ColumnDefinition>(); foreach (var col in columnToValue) { var colDef = tableDef.ColumnDefinitions.Where(x => x.ColumnName.ToLower() == col.Key).Single(); columnDefs.Add(colDef); } Dictionary <int, IComparable> indexToValue = new Dictionary <int, IComparable>(); foreach (var columnNameToValue in columnToValue) { var colDef = tableDef.ColumnDefinitions.Single(x => x.ColumnName.ToLower() == columnNameToValue.Key); indexToValue[colDef.Index] = _stringParser.ConvertToType(columnNameToValue.Value, colDef.Type); } foreach (var colDef in columnDefs) { foreach (var row in selectData.Rows) { row[colDef.Index] = indexToValue[colDef.Index]; } } //each row is updated as its own transaction - not ideal for update - not atomic for (int i = 0; i < selectData.Rows.Count; i++) { var writeTransaction = new WriteTransaction { Data = selectData.Rows[i].ToArray(), TableDefinition = tableDef, AddressToWriteTo = selectData.RowLocations[i], Query = sql, UpdateObjectCount = false }; _lockManager.ProcessWriteTransaction(writeTransaction); } return(new object()); }