public static void ProcessFile(string path, QfConfigModel outerConfig) { var conductor = new Conductor().BuildUp(); conductor.ProcessOneQuery(path, outerConfig); Console.WriteLine("Processed file '{0}'.", path); }
/// <summary> /// Returns the QueryFirst config for a given query file. Values specified directly in /// the query's qfconfig.json file will override values specified in the project and install qfconfig.json files. /// /// If the config specifies a QfDefaultConnection but no QfDefaultConnectionProviderName, "System.Data.SqlClient" /// will be used. /// </summary> /// <param name="filePath"></param> /// <param name="queryText"></param> /// <returns></returns> public State Go(State state, QfConfigModel outerConfig) { // read the config file if there is one. var queryConfig = ConfigFileReader.GetQueryConfig(state._1SourceQueryFullPath) ?? new QfConfigModel(); // to do perhaps. Do we want to make this work again? //// if the query defines a QfDefaultConnection, use it. //var match = Regex.Match(state._2InitialQueryText, "^--QfDefaultConnection(=|:)(?<cstr>[^\r\n]*)", RegexOptions.Multiline); //if (match.Success) //{ // queryConfig.DefaultConnection = match.Groups["cstr"].Value; // var matchProviderName = Regex.Match(state._2InitialQueryText, "^--QfDefaultConnectionProviderName(=|:)(?<pn>[^\r\n]*)", RegexOptions.Multiline); // if (matchProviderName.Success) // { // queryConfig.Provider = matchProviderName.Groups["pn"].Value; // } // else // { // queryConfig.Provider = "System.Data.SqlClient"; // } //} state._3Config = ConfigBuilder.Resolve2Configs(outerConfig, queryConfig); return(state); }
public QfConfigModel Resolve2Configs(QfConfigModel overridden, QfConfigModel overides) { if (overridden == null) { return(overides); } QfConfigModel returnVal = new QfConfigModel { DefaultConnection = overides.DefaultConnection ?? overridden.DefaultConnection, Provider = overides.Provider ?? overridden.Provider, HelperAssemblies = new List <string>(), Generators = overides.Generators ?? overridden.Generators, MakeSelfTest = overides.MakeSelfTest ?? overridden.MakeSelfTest, Namespace = overides.Namespace ?? overridden.Namespace, ResultClassName = overides.ResultClassName ?? overridden.ResultClassName, ResultInterfaceName = overides.ResultInterfaceName ?? overridden.ResultInterfaceName }; // helper assemblies. Unlike other config, these cumulate. if (overides.HelperAssemblies != null) { returnVal.HelperAssemblies.AddRange(overides.HelperAssemblies); } if (overridden.HelperAssemblies != null) { returnVal.HelperAssemblies.AddRange(overridden.HelperAssemblies); } return(returnVal); }
private QfConfigModel SetDefaultProvider(QfConfigModel config) { // Sql server is the default IF connection string is provided. if (!string.IsNullOrEmpty(config.DefaultConnection) && string.IsNullOrEmpty(config.Provider)) { config.Provider = "System.Data.SqlClient"; } return(config); }
/// <summary> /// Now we can connect the editor window, we need to recover the connection string when we open a query. /// This method is called on open and on save. /// </summary> /// <param name="sourcePath"></param> /// <param name="state"></param> internal void ProcessUpToStep4(string sourcePath, QfConfigModel outerConfig, ref State state) { // todo: if a .sql is not in the project, this throws null exception. What should it do? new _1ProcessQueryPath().Go(state, sourcePath); // copy namespace of generated partial class from user partial class new _2ReadQuery().Go(state); var _3 = new _3ResolveConfig().BuildUp(); _3.Go(state, outerConfig); }
// Process all files in the directory passed in, recurse on any directories // that are found, and process the files they contain. public static void ProcessDirectory(string targetDirectory, QfConfigModel outerConfig) { // Process the list of files found in the directory. string[] fileEntries = Directory.GetFiles(targetDirectory, "*.sql"); foreach (string fileName in fileEntries) { ProcessFile(fileName, outerConfig); } // Recurse into subdirectories of this directory. string[] subdirectoryEntries = Directory.GetDirectories(targetDirectory); foreach (string subdirectory in subdirectoryEntries) { ProcessDirectory(subdirectory, outerConfig); } }
public QfConfigModel GetQueryConfig(string queryFilename) { QfConfigModel query; try { string queryConfigFileContents; if (File.Exists(queryFilename.Replace(".sql", ".qfconfig.json"))) { queryConfigFileContents = File.ReadAllText(queryFilename.Replace(".sql", ".qfconfig.json")); query = JsonConvert.DeserializeObject <QfConfigModel>(queryConfigFileContents); } else { query = new QfConfigModel(); } SetDefaultProvider(query); return(query); } catch (Exception ex) { throw new Exception($"Error deserializing {queryFilename.Replace(".sql", ".qfconfig.json")}. Is there anything funny in there?", ex); } }
/// <summary> /// Defines the command line switches. See /// https://github.com/xamarin/XamarinComponents/tree/master/XPlat/Mono.Options /// </summary> /// <param name="args">The command line args to parse</param> /// <returns></returns> static StartupOptions DefineAndParseOptions(string[] args) { var returnVal = new StartupOptions(); var commandLineConfig = new QfConfigModel(); // these variables will be set when the command line is parsed // these are the available options, note that they set the variables commandLineConfig.Generators = new List <Generator>(); int verbosity = 0; var shouldShowHelp = false; var options = new OptionSet { { "c|qfDefaultConnection=", "Connection string for query generation, overrides config files.", c => commandLineConfig.DefaultConnection = c }, { "m|makeSelfTest", "Make integration test for query. Requires xunit. Overrides config files.", m => commandLineConfig.MakeSelfTest = m != null }, { "g|generator=", "Generator(s) to use. Will replace generators specified in config files", g => commandLineConfig.Generators.Add(new Generator { Name = g }) }, { "w|watch", "Watch for changes in the file or directory", w => returnVal.Watch = w != null }, { "k|keepOpen", "Wait for a keystroke before exiting the console.", k => keepOpen = k != null }, { "h|help", "show this message and exit", h => shouldShowHelp = h != null }, { "n|new=", "create a new QueryFirst query with the specified name.", n => returnVal.NewQueryName = n }, { "j|newConfig", "create qfconfig.json in the current directory", nc => returnVal.CreateConfig = nc != null }, { "r|newRuntimeConnection", "create QfRuntimeConnection.cs in the current directory", nc => returnVal.CreateRuntimeConnection = nc != null }, }; // now parse the options... List <string> extra; try { // parse the command line extra = options.Parse(args); if (extra != null && extra.Count > 0 && !string.IsNullOrEmpty(extra[0])) { returnVal.SourcePath = extra[0]; } else { // by default, process the current directory returnVal.SourcePath = Environment.CurrentDirectory; } } catch (OptionException e) { // output some error message Console.Write("QueryFirst: "); Console.WriteLine(e.Message); Console.WriteLine("Try `QueryFirst --help' for more information."); return(null); } finally { // clean up if none... if (commandLineConfig.Generators.Count == 0) { commandLineConfig.Generators = null; } } if (shouldShowHelp) { options.WriteOptionDescriptions(Console.Out); returnVal.DidShowHelp = true; } returnVal.StartupConfig = commandLineConfig; return(returnVal); }
public void ProcessOneQuery(string sourcePath, QfConfigModel outerConfig) { try { _state = new State(); ProcessUpToStep4(sourcePath, outerConfig, ref _state); // We have the config, we can instantiate our provider... if (_tiny.CanResolve <IProvider>(_state._3Config.Provider)) { _provider = _tiny.Resolve <IProvider>(_state._3Config.Provider); } else { QfConsole.WriteLine(@"After resolving the config, we have no provider\n"); } if (string.IsNullOrEmpty(_state._3Config.DefaultConnection)) { QfConsole.WriteLine(@"No design time connection string. You need to create qfconfig.json beside or above your query or put --QfDefaultConnection=myConnectionString somewhere in your query file. See the Readme section at https://marketplace.visualstudio.com/items?itemName=bbsimonbb.QueryFirst "); return; // nothing to be done } if (!_tiny.CanResolve <IProvider>(_state._3Config.Provider)) { QfConsole.WriteLine(string.Format( @"No Implementation of IProvider for providerName {0}. The query {1} may not run and the wrapper has not been regenerated.\n", _state._3Config.Provider, _state._1BaseName )); return; } // assign some names new _4ExtractNamesFromUserPartialClass().Go(_state); // Scaffold inserts and updates _tiny.Resolve <_5ScaffoldUpdateOrInsert>().Go(ref _state); if (_state._2InitialQueryText != _state._5QueryAfterScaffolding) { } // Execute query try { new _6FindUndeclaredParameters(_provider).Go(ref _state, out string outputMessage); // if message returned, write it to output. if (!string.IsNullOrEmpty(outputMessage)) { QfConsole.WriteLine(outputMessage); } // if undeclared params were found, modify the original .sql if (!string.IsNullOrEmpty(_state._6NewParamDeclarations)) { QfTextFileWriter.WriteFile(new QfTextFile() { Filename = _state._1SourceQueryFullPath, FileContents = _state._6QueryWithParamsAdded }); } new _7RunQueryAndGetResultSchema(new AdoSchemaFetcher(), _provider).Go(ref _state); new _8ParseOrFindDeclaredParams(_provider).Go(ref _state); } catch (Exception ex) { StringBuilder bldr = new StringBuilder(); bldr.AppendLine("Error running query."); bldr.AppendLine(); bldr.AppendLine("/*The last attempt to run this query failed with the following error. This class is no longer synced with the query"); bldr.AppendLine("You can compile the class by deleting this error information, but it will likely generate runtime errors."); bldr.AppendLine("-----------------------------------------------------------"); bldr.AppendLine(ex.Message); bldr.AppendLine("-----------------------------------------------------------"); bldr.AppendLine(ex.StackTrace); bldr.AppendLine("*/"); File.AppendAllText(_state._1GeneratedClassFullFilename, bldr.ToString()); throw; } // dump state for reproducing issues #if DEBUG using (var ms = new MemoryStream()) { var ser = new DataContractJsonSerializer(typeof(State)); ser.WriteObject(ms, _state); byte[] json = ms.ToArray(); ms.Close(); File.WriteAllText(_state._1CurrDir + "qfDumpState.json", Encoding.UTF8.GetString(json, 0, json.Length)); } #endif var code = new CSharpFrameworkGenerator().Generate(_state); //File.WriteAllText(ctx.GeneratedClassFullFilename, Code.ToString()); QfTextFileWriter.WriteFile(code); QfConsole.WriteLine("QueryFirst generated wrapper class for " + _state._1BaseName + ".sql" + Environment.NewLine); } catch (Exception ex) { QfConsole.WriteLine(ex.TellMeEverything()); } }