// https://docs.microsoft.com/en-us/sql/t-sql/statements/create-procedure-transact-sql public static IReadOnlyDictionary <string, SqlParamInfo> ParseProcedure(string sql) { if (string.IsNullOrWhiteSpace(sql)) { return(_empty); } // Tokenize var tokens = SqlTokenizer.Tokenize(sql, true); using (var tokenizer = tokens.GetEnumerator()) { var more = tokenizer.MoveNext(); if (!more) { return(_empty); } // CREATE if (!ParseLiteral(tokenizer, "CREATE")) { return(_empty); } // PROC | PROCEDURE if (!ParseLiteral(tokenizer, "PROC", "PROCEDURE")) { return(_empty); } // [Name] or "Name" if (!ParseModuleName(tokenizer, out var schema, out var name)) { return(_empty); } // ( var parenthesized = ParseSymbol(tokenizer, '('); var parms = new Dictionary <string, SqlParamInfo>(); while (true) { // Exit loop if end of parameter block // ) if (parenthesized && ParseSymbol(tokenizer, ')')) { break; } // AS, WITH or FOR if (ParseLiteral(tokenizer, "AS", "WITH", "FOR")) { break; } // Read next parameter // @param if (!ParseParamName(tokenizer, out var pname)) { return(_empty); } // AS ParseLiteral(tokenizer, "AS"); // Foo.DECIMAL(1,2) if (!ParseTypeName(tokenizer, out var tschema, out var tname)) { return(_empty); } // VARYING ParseLiteral(tokenizer, "VARYING"); // = <default> var hasDefault = ParseDefault(tokenizer, out var isNullable); // OUT | OUTPUT var dir = ParameterDirection.Input; if (ParseLiteral(tokenizer, "OUT", "OUTPUT")) { dir = ParameterDirection.InputOutput; } // READONLY var isReadOnly = ParseLiteral(tokenizer, "READONLY"); // Done var parm = new SqlParamInfo(isNullable, hasDefault, isReadOnly, dir); parms.Add(pname, parm); // , ParseSymbol(tokenizer, ','); } return(parms); } }
// https://docs.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql public static IReadOnlyDictionary <string, SqlParamInfo> ParseFunction(string sql) { if (string.IsNullOrWhiteSpace(sql)) { return(_empty); } // Tokenize var tokens = SqlTokenizer.Tokenize(sql, true); using (var tokenizer = tokens.GetEnumerator()) { var more = tokenizer.MoveNext(); if (!more) { return(_empty); } // CREATE if (!ParseLiteral(tokenizer, "CREATE")) { return(_empty); } // FUNCTION if (!ParseLiteral(tokenizer, "FUNCTION")) { return(_empty); } // [Name] or "Name" if (!ParseModuleName(tokenizer, out var schema, out var name)) { return(_empty); } // ( if (!ParseSymbol(tokenizer, '(')) { return(_empty); } var parms = new Dictionary <string, SqlParamInfo>(StringComparer.Ordinal); while (true) { // Exit loop if end of parameter block // ) if (ParseSymbol(tokenizer, ')')) { break; } // RETURNS if (ParseLiteral(tokenizer, "RETURNS")) { break; } // Read next parameter // @param if (!ParseParamName(tokenizer, out var pname)) { return(_empty); } // AS ParseLiteral(tokenizer, "AS"); // Foo.DECIMAL(1,2) if (!ParseTypeName(tokenizer, out var tschema, out var tname)) { return(_empty); } // = default var hasDefault = ParseDefault(tokenizer, out var isNullable); // READONLY var isReadOnly = ParseLiteral(tokenizer, "READONLY"); // Done var parm = new SqlParamInfo(isNullable, hasDefault, isReadOnly, ParameterDirection.Input); parms.Add(pname, parm); // , ParseSymbol(tokenizer, ','); } return(parms); } }