/// <summary> /// Parses the tokens into structured trigger definition. /// </summary> /// <param name="tokens">A collection of tokens from the trigger definition.</param> /// <returns>Parsed data for a <c>CREATE TRIGGER</c> definition.</returns> /// <exception cref="ArgumentNullException"><paramref name="tokens"/> is empty.</exception> public ParsedTriggerData ParseTokens(TokenList <SqliteToken> tokens) { if (tokens == default || tokens.Empty()) { throw new ArgumentNullException(nameof(tokens)); } var timing = TriggerQueryTiming.After; var evt = TriggerEvent.None; var triggerDef = SqliteTokenParsers.TriggerDefinition(tokens); if (triggerDef.HasValue) { timing = triggerDef.Value.timing; evt = triggerDef.Value.evt; } return(new ParsedTriggerData(timing, evt)); }
/// <summary> /// Parses the tokens into structured table definition. /// </summary> /// <param name="definition">The textual definition of the <c>CREATE TABLE</c> statement.</param> /// <param name="tokens">A collection of tokens from the table definition.</param> /// <returns>Parsed data for a <c>CREATE TABLE</c> definition.</returns> /// <exception cref="ArgumentNullException"><paramref name="tokens"/> is empty.</exception> public ParsedTableData ParseTokens(string definition, TokenList <SqliteToken> tokens) { if (definition.IsNullOrWhiteSpace()) { throw new ArgumentNullException(nameof(definition)); } if (tokens == default || tokens.Empty()) { throw new ArgumentNullException(nameof(tokens)); } var next = tokens.ConsumeToken(); var createTablePrefix = SqliteTokenParsers.CreateTablePrefix(next.Location); if (!createTablePrefix.HasValue) { throw new ArgumentException("Token list does not start with a CREATE TABLE statement.", nameof(tokens)); } next = createTablePrefix.Remainder.ConsumeToken(); var ifNotExists = SqliteTokenParsers.IfNotExistsClause(next.Location); if (ifNotExists.HasValue) { next = ifNotExists.Remainder.ConsumeToken(); } var tableName = SqliteTokenParsers.QualifiedName(next.Location); if (!tableName.HasValue) { throw new ArgumentException("Unable to determine the name of the table being parsed.", nameof(tokens)); } next = tableName.Remainder.ConsumeToken(); var isSelectBasedTable = !next.HasValue || next.Value.Kind != SqliteToken.LParen; // skipping because we cannot parse extra information from a select-based table if (isSelectBasedTable) { return(ParsedTableData.Empty(definition)); } next = next.Remainder.ConsumeToken(); // consume LParen var tableMembers = SqliteTokenParsers.TableMembers(next.Location); if (!tableMembers.HasValue) { var errMessage = "Unable to parse columns and/or constraints from the table definition. Error: " + tableMembers.ErrorMessage; throw new ArgumentException(errMessage, nameof(tokens)); } var columns = new List <Column>(); var primaryKey = Option <PrimaryKey> .None; var uniqueKeys = new List <UniqueKey>(); var foreignKeys = new List <ForeignKey>(); var checks = new List <Check>(); var parsedColumns = tableMembers.Value.SelectMany(m => m.Columns); var parsedConstraints = tableMembers.Value.SelectMany(m => m.Constraints); foreach (var parsedColumn in parsedColumns) { var column = new Column( parsedColumn.Name, parsedColumn.TypeDefinition, parsedColumn.Nullable, parsedColumn.IsAutoIncrement, parsedColumn.Collation, parsedColumn.DefaultValue, parsedColumn.GeneratedColumnDefinition, parsedColumn.GeneratedColumnType ); columns.Add(column); if (primaryKey.IsNone && parsedColumn.PrimaryKey.IsSome) { primaryKey = parsedColumn.PrimaryKey; } parsedColumn.UniqueKey.IfSome(uk => uniqueKeys.Add(uk)); foreignKeys.AddRange(parsedColumn.ForeignKeys); checks.AddRange(parsedColumn.Checks); } foreach (var parsedConstraint in parsedConstraints) { switch (parsedConstraint.ConstraintType) { case TableConstraint.TableConstraintType.PrimaryKey: if (parsedConstraint is TableConstraint.PrimaryKey pk) { primaryKey = new PrimaryKey(pk.Name, pk.Columns); } break; case TableConstraint.TableConstraintType.UniqueKey: if (parsedConstraint is TableConstraint.UniqueKey uk) { uniqueKeys.Add(new UniqueKey(uk.Name, uk.Columns)); } break; case TableConstraint.TableConstraintType.ForeignKey: if (parsedConstraint is TableConstraint.ForeignKey fk) { foreignKeys.Add(new ForeignKey(fk.Name, fk.Columns, fk.ParentTable, fk.ParentColumnNames)); } break; case TableConstraint.TableConstraintType.Check: if (parsedConstraint is TableConstraint.Check ck) { checks.Add(new Check(ck.Name, ck.Definition)); } break; } } return(new ParsedTableData( definition, columns, primaryKey, uniqueKeys, foreignKeys, checks )); }