public static SqlTableDefinition GetTableDefinition(this Sqlite3SchemaRow schema) { Dictionary <Sqlite3SchemaRow, SqlTableDefinition> definitionCache = schema.Database.GetProperty(SqlCacheKey, () => new Dictionary <Sqlite3SchemaRow, SqlTableDefinition>()); if (!definitionCache.TryGetValue(schema, out SqlTableDefinition definition)) { if (!SqlParser.TryParse(schema.Sql, out definition)) { definitionCache[schema] = null; } else { definitionCache[schema] = definition; } } if (definition == null) { throw new Exception(); } SqlTableDefinition def = definition; return(def); }
public static bool TryGetValueByName(this Sqlite3Row row, string columnName, out object value) { value = null; SqlTableDefinition tableDefinition = row.Table.GetTableDefinition(); if (!tableDefinition.TryGetColumn(columnName, out SqlTableColumn column)) { return(false); } if (row.ColumnData.Length <= column.Ordinal) { return(false); } // Special case for row-id if (tableDefinition.RowIdColumn != null && columnName.Equals(tableDefinition.RowIdColumn.Name, StringComparison.OrdinalIgnoreCase)) { // Return the row-id value = row.RowId; return(true); } value = row.ColumnData[column.Ordinal]; return(true); }
public static bool TryParse(string sql, out SqlTableDefinition tableDefinition) { tableDefinition = null; // Parse out the SQL into series of column creation statements Result <TokenList <SqlToken> > tokens = SqlTokenizer.Tokenizer.TryTokenize(sql); if (!tokens.HasValue) { return(false); } if (!TryParseTokenList(tokens.Value, out SqlNode node)) { return(false); } // Check if this is a create table if (!node.Is(0, "CREATE") || !node.Is(1, "TABLE") || !node.Is(2, SqlToken.String) || !node.IsGroup(3)) { return(false); } SqlTableDefinition def = new SqlTableDefinition(node.GetString(2)); SqlNode columns = node.GetGroup(3); int primaryKeyComponents = 0; SqlTableColumn primaryKeyColumn = null; for (int columnIndex = 0; columnIndex < columns.Children.Count; columnIndex++) { SqlNode columnSet = columns.Children[columnIndex]; if (!columnSet.Children.Any() || !columnSet.Children.First().Is(SqlToken.String)) { continue; } string firstToken = columnSet.Children.First().GetString(); bool isConstraint = SqlKeywords.NonColumnKeywords.Contains(firstToken); string name; if (isConstraint) { if (columnSet.Is(0, "PRIMARY") && columnSet.Is(1, "KEY") && columnSet.IsGroup(2)) { SqlNode pkColumns = columnSet.GetGroup(2); foreach (SqlNode pkColumn in pkColumns.Children) { if (pkColumn.Is(SqlToken.String)) { name = pkColumn.GetString(); } else if (pkColumn.Is(0, SqlToken.String)) { name = pkColumn.GetString(0); } else { return(false); } if (!def.TryGetColumn(name, out SqlTableColumn columnObject)) { continue; } columnObject.IsPartOfPrimaryKey = true; primaryKeyComponents++; primaryKeyColumn = columnObject; } } continue; } name = columnSet.GetString(0); string[] typeStrings = columnSet.Children.Skip(1).Where(s => s.Is(SqlToken.String)) .Select(s => s.GetString()).ToArray(); // Defaults Type identifiedType = typeof(byte[]); string[] identifiedTypeStrings = typeStrings; foreach ((string[] words, Type type)candidate in SqlKeywords.TypeKeywords) { if (!typeStrings.Take(candidate.words.Length).SequenceEqual(candidate.words)) { continue; } identifiedType = candidate.type; identifiedTypeStrings = candidate.words; break; } SqlTableColumn sqlTableColumn = new SqlTableColumn(columnIndex, name, string.Join(" ", identifiedTypeStrings), identifiedType); def.AddColumn(sqlTableColumn); // Is this a primary key? if (typeStrings.Contains("PRIMARY", StringComparer.OrdinalIgnoreCase) && typeStrings.Contains("KEY", StringComparer.OrdinalIgnoreCase)) { sqlTableColumn.IsPartOfPrimaryKey = true; primaryKeyComponents++; primaryKeyColumn = sqlTableColumn; } } // Identify row-id substitutes if (primaryKeyComponents == 1 && primaryKeyColumn.DetectedType == typeof(long)) { def.ConfigureRowIdColumn(primaryKeyColumn); } tableDefinition = def; return(true); }