Example #1
0
        public static void ProcessFile(string path, QfConfigModel outerConfig)
        {
            var conductor = new Conductor().BuildUp();

            conductor.ProcessOneQuery(path, outerConfig);
            Console.WriteLine("Processed file '{0}'.", path);
        }
Example #2
0
        /// <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);
        }
Example #3
0
        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);
 }
Example #5
0
        /// <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);
        }
Example #6
0
        // 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);
            }
        }
Example #8
0
        /// <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);
        }
Example #9
0
        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());
            }
        }