├── .editorconfig ├── .gitattributes ├── .gitignore ├── License.md ├── README.md ├── References ├── EPPlus.XML ├── EPPlus.dll ├── ICSharpCode.AvalonEdit.dll ├── ICSharpCode.AvalonEdit.xml ├── Microsoft.WindowsAPICodePack.Shell.dll ├── Microsoft.WindowsAPICodePack.dll ├── MoonPdfLib.dll ├── MouseKeyboardActivityMonitor.dll ├── Newtonsoft.Json.dll ├── Newtonsoft.Json.xml ├── Oci │ └── ODAC121024Xcopy_32bit.zip ├── Oracle.ManagedDataAccess.dll ├── Oracle.ManagedDataAccessDTC.dll ├── Oracle.ManagedDataAccessIOP.dll ├── Test │ ├── Nito.AsyncEx.Enlightenment.dll │ ├── Nito.AsyncEx.Enlightenment.xml │ ├── Nito.AsyncEx.dll │ ├── Nito.AsyncEx.xml │ ├── Shouldly.dll │ ├── nunit.framework.dll │ └── nunit.framework.xml ├── Xceed.Wpf.Toolkit.dll ├── Xceed.Wpf.Toolkit.xml ├── libmupdf.dll ├── protobuf-net.dll └── protobuf-net.xml ├── SQLPad.nuspec ├── Screenshots ├── CodeComplete1.png ├── CodeComplete2.png ├── CodeComplete3.png ├── ColumnTooltip.png ├── DatabaseMonitor1.png ├── DatabaseOutput.png ├── ExecutionStatistics.png ├── ExpandAsterisk.png ├── FunctionOverloads.png ├── Overview1.png ├── Overview2.png ├── Overview3.png ├── Overview4.png ├── StatementExecutionHistory.png ├── TableTooltip.png └── TraceEvents.png ├── SqlPad.Oracle.Database.Test ├── App.config ├── ConsoleTraceListenerTestFixture.cs ├── OracleConfiguration.xml ├── OracleDatabaseModelTest.cs ├── OracleDebuggerSessionTest.cs ├── Properties │ └── AssemblyInfo.cs └── SqlPad.Oracle.Database.Test.csproj ├── SqlPad.Oracle.Test ├── Commands │ ├── CommandTest.cs │ ├── FindUsagesCommandTest.cs │ ├── OracleTestCommandSettingsProviderFactory.cs │ └── TestCommandSettings.cs ├── ConsoleTraceListenerTestFixture.cs ├── MiscellaneousTest.cs ├── OracleCodeCompletionProviderTest.cs ├── OracleContextActionProviderTest.cs ├── OracleFoldingSectionProviderTest.cs ├── OracleMultiNodeEditorDataProviderTest.cs ├── OracleNavigationServiceTest.cs ├── OraclePlSqlStatementSemanticModelTest.cs ├── OraclePlSqlStatementValidatorTest.cs ├── OracleSnippetProviderTest.cs ├── OracleSqlParserTest.cs ├── OracleStatementFormatterTest.cs ├── OracleStatementSemanticModelTest.cs ├── OracleStatementValidatorTest.cs ├── OracleTestConnectionAdapter.cs ├── OracleTestDatabaseModel.cs ├── OracleTestInfrastructureFactory.cs ├── OracleTestObjectScriptExtractor.cs ├── OracleTokenReaderTest.cs ├── OracleToolTipProviderTest.cs ├── Properties │ └── AssemblyInfo.cs ├── SqlPad.Oracle.Test.csproj ├── StatementGrammarNodeTest.cs ├── TestFiles │ ├── SqlStatements1.sql │ └── TestSnippet.xml └── TestFixture.cs ├── SqlPad.Oracle ├── CodeCompletionSearchHelper.cs ├── CodeGenerationItems │ ├── CreateFunction.xml │ ├── CreatePackage.xml │ ├── CreatePackageBody.xml │ └── CreateProcedure.xml ├── Commands │ ├── AddAliasCommand.cs │ ├── AddCreateTableAsCommand.cs │ ├── AddExpressionToClauseCommandBase.cs │ ├── AddInsertIntoColumnListCommand.cs │ ├── AddMissingColumnCommand.cs │ ├── AddToGroupByCommand.cs │ ├── AddToOrderByCommand.cs │ ├── BindVariableLiteralConversionCommand.cs │ ├── CleanRedundantSymbolCommand.cs │ ├── ConfigureNamedParameterCommand.cs │ ├── ConvertOrderByNumberColumnReferencesCommand.cs │ ├── CreateScriptCommand.cs │ ├── ExpandAsteriskCommand.cs │ ├── ExpandViewCommand.cs │ ├── ExtractPackageInterfaceCommand.cs │ ├── FindUsagesCommand.cs │ ├── GenerateCustomTypeCSharpWrapperClassCommand.cs │ ├── LiteralBindVariableConversionCommand.cs │ ├── ModifyCaseCommand.cs │ ├── MoveContentCommand.cs │ ├── OracleCommandBase.cs │ ├── OracleCommandFactory.cs │ ├── PropagateColumnCommand.cs │ ├── ResolveAmbiguousColumnCommand.cs │ ├── SafeDeleteCommand.cs │ ├── SplitStringCommand.cs │ ├── SqlTextBuilder.cs │ ├── ToggleFullyQualifiedReferencesCommand.cs │ ├── ToggleQuotedNotationCommand.cs │ ├── UnnestInlineViewCommand.cs │ ├── UnquoteCommand.cs │ ├── WrapAsCommonTableExpressionCommand.cs │ └── WrapAsInlineViewCommand.cs ├── CustomTypeCSharpWrapperClassGenerator.cs ├── DataDictionary │ ├── OracleColumn.cs │ ├── OracleConstraint.cs │ ├── OracleDataDictionary.cs │ ├── OracleDataType.cs │ ├── OracleDatabaseLink.cs │ ├── OracleObject.cs │ ├── OracleObjectFactory.cs │ ├── OracleObjectIdentifier.cs │ ├── OracleProgramIdentifier.cs │ ├── OracleProgramMetadata.cs │ └── OracleReferenceBuilder.cs ├── DatabaseConnection │ ├── OracleClobValue.cs │ ├── OracleConnectionAdapter.cs │ ├── OracleConnectionAdapterBase.cs │ ├── OracleCustomTypeGenerator.cs │ ├── OracleDataAccessExtensions.cs │ ├── OracleDataDictionaryMapper.cs │ ├── OracleDatabaseCommands.cs │ ├── OracleDatabaseModel.cs │ ├── OracleDatabaseModelBase.cs │ ├── OracleDebugger.cs │ └── OracleObjectScriptExtractor.cs ├── DebugTrace │ ├── OracleTraceEvent.cs │ ├── OracleTraceIdentifier.cs │ ├── OracleTraceViewer.xaml │ ├── OracleTraceViewer.xaml.cs │ └── OracleTransientKernelProfile.cs ├── Documentation.Extensions.cs ├── Documentation.cs ├── Documentation.xsd ├── ExecutionPlan │ ├── ExecutionPlanItem.cs │ ├── ExecutionPlanItemCollection.cs │ ├── ExecutionPlanTreeView.xaml │ ├── ExecutionPlanTreeView.xaml.cs │ ├── ExecutionPlanViewer.xaml │ ├── ExecutionPlanViewer.xaml.cs │ └── ExecutionStatisticsPlanItemCollection.cs ├── GenerateXsdClasses.cmd ├── ModelDataProviders │ ├── CursorExecutionStatisticsDataProvider.cs │ ├── ExplainPlanDataProvider.cs │ ├── IModelDataProvider.cs │ ├── ModelDataProvider.cs │ ├── PartitionDataProvider.cs │ ├── SessionExecutionStatisticsDataProvider.cs │ ├── SqlMonitorDataProvider.cs │ └── UserDataProvider.cs ├── OracleBindVariable.cs ├── OracleCodeCompletionItem.cs ├── OracleCodeCompletionProvider.cs ├── OracleCodeCompletionType.cs ├── OracleCommandSettingsProviderFactory.cs ├── OracleConditionValidator.cs ├── OracleConfiguration.Extensions.cs ├── OracleConfiguration.cs ├── OracleConfiguration.xml ├── OracleConfiguration.xsd ├── OracleContextActionProvider.cs ├── OracleDataExportConverter.cs ├── OracleDatabaseMonitor.cs ├── OracleDocumentation.xml ├── OracleExtensions.cs ├── OracleFoldingSectionProvider.cs ├── OracleGrammarDescription.cs ├── OracleGrammarDescription.tt ├── OracleHelpProvider.cs ├── OracleIdentifierValidationRule.cs ├── OracleInfrastructureFactory.cs ├── OracleMultiNodeEditorDataProvider.cs ├── OracleNavigationService.cs ├── OracleProgramMatcher.cs ├── OracleSemanticErrorType.cs ├── OracleSessionDetailViewer.xaml ├── OracleSessionDetailViewer.xaml.cs ├── OracleSnippetProvider.cs ├── OracleSqlGrammar.Extension.cs ├── OracleSqlGrammar.cs ├── OracleSqlGrammar.xml ├── OracleSqlGrammar.xsd ├── OracleSqlParser.cs ├── OracleStatement.cs ├── OracleStatementFormatter.cs ├── OracleStatementValidator.cs ├── OracleToken.cs ├── OracleTokenReader.cs ├── OracleValueAggregator.cs ├── Properties │ └── AssemblyInfo.cs ├── Scripts │ └── CreateExplainPlanTable.sql ├── SemanticModel │ ├── OracleColumnBuilderVisitor.cs │ ├── OracleColumnReference.cs │ ├── OracleDataObjectReference.cs │ ├── OracleDataTypeReference.cs │ ├── OracleInsertTarget.cs │ ├── OracleJoinDescription.cs │ ├── OracleLiteral.cs │ ├── OraclePivotTableReference.cs │ ├── OraclePlSqlProgram.cs │ ├── OraclePlSqlStatementSemanticModel.cs │ ├── OracleProgramReference.cs │ ├── OracleQueryBlock.cs │ ├── OracleReference.cs │ ├── OracleReferenceContainer.cs │ ├── OracleReferenceDataSource.cs │ ├── OracleSelectListColumn.cs │ ├── OracleSequenceReference.cs │ ├── OracleSpecialTableReference.cs │ ├── OracleSqlModelReference.cs │ ├── OracleStatementSemanticModel.cs │ ├── OracleStatementSemanticModelFactory.cs │ ├── OracleTableCollectionReference.cs │ ├── QueryBlockType.cs │ ├── ReferenceType.cs │ └── StatementPlacement.cs ├── SessionActivityIndicator.xaml ├── SessionActivityIndicator.xaml.cs ├── SessionIdentifier.cs ├── Snippets │ ├── SnippetGatherTableStats.xml │ ├── SnippetInsert.xml │ ├── SnippetObjects.xml │ ├── SnippetSelect.xml │ ├── SnippetSelectCount.xml │ └── SnippetTables.xml ├── SqlPad.Oracle.csproj ├── Themes │ ├── Common.xaml │ ├── Generic.xaml │ └── ToolTipDataGrid.xaml └── ToolTips │ ├── CircularProgresBarConverters.cs │ ├── ConstraintList.xaml │ ├── ConstraintList.xaml.cs │ ├── IndexList.xaml │ ├── IndexList.xaml.cs │ ├── OracleToolTipBuilderVisitor.cs │ ├── OracleToolTipProvider.cs │ ├── PartitionDetailsModel.cs │ ├── PartitionList.xaml │ ├── PartitionList.xaml.cs │ ├── PopupBase.cs │ ├── ProfileDetails.xaml │ ├── ProfileDetails.xaml.cs │ ├── TablespaceDetails.xaml │ ├── TablespaceDetails.xaml.cs │ ├── ToolTipAsterisk.xaml │ ├── ToolTipAsterisk.xaml.cs │ ├── ToolTipColumn.xaml │ ├── ToolTipColumn.xaml.cs │ ├── ToolTipDatabaseLink.xaml │ ├── ToolTipDatabaseLink.xaml.cs │ ├── ToolTipMaterializedView.xaml │ ├── ToolTipMaterializedView.xaml.cs │ ├── ToolTipObject.xaml │ ├── ToolTipObject.xaml.cs │ ├── ToolTipPartition.xaml │ ├── ToolTipPartition.xaml.cs │ ├── ToolTipProgram.xaml │ ├── ToolTipProgram.xaml.cs │ ├── ToolTipSchema.xaml │ ├── ToolTipSchema.xaml.cs │ ├── ToolTipSequence.xaml │ ├── ToolTipSequence.xaml.cs │ ├── ToolTipTable.xaml │ ├── ToolTipTable.xaml.cs │ ├── ToolTipView.xaml │ ├── ToolTipView.xaml.cs │ ├── ToolTipViewColumn.xaml │ └── ToolTipViewColumn.xaml.cs ├── SqlPad.Test ├── App.config ├── ConsoleTraceListenerTestFixture.cs ├── EditorNavigationServiceTest.cs ├── EditorTest.cs ├── MiscellaneousTest.cs ├── MultiNodeEditorTest.cs ├── Properties │ └── AssemblyInfo.cs ├── SqlPad.Test.csproj ├── TemporaryDirectoryTestFixture.cs ├── TestFixture.cs ├── VisualComponentTest.cs ├── VisualTestRunner.cs └── WorkDocumentTest.cs ├── SqlPad.sln └── SqlPad ├── ActiveSnippet.cs ├── App.config ├── App.xaml ├── App.xaml.cs ├── Archive.ico ├── AssemblyBuildInfo.cs ├── BinaryDataHelper.cs ├── BindVariableModel.cs ├── Bookmarks └── IconMargin.cs ├── CSharpQueryClassGenerator.cs ├── CellValueConverter.cs ├── Chart.ico ├── ClipboardManager.cs ├── ColumnHeader.cs ├── CommandSettingsModel.cs ├── Commands ├── CommandExecutionHandler.cs ├── ContextActionTextEditorCommand.cs ├── DiagnosticCommands.cs ├── GenericCommandHandler.cs ├── GenericCommands.cs ├── ICommandFactory.cs └── ICommandSettings.cs ├── CompilationErrorArgs.cs ├── CompletionData.cs ├── ComplexTypeViewer.xaml ├── ComplexTypeViewer.xaml.cs ├── Configuration.Extensions.cs ├── Configuration.cs ├── Configuration.xml ├── Configuration.xsd ├── ConfigurationProvider.cs ├── DataExport ├── CsvDataExporter.cs ├── DataExportContextBase.cs ├── DataExportHelper.cs ├── ExcelDataExporter.cs ├── HtmlDataExporter.cs ├── IDataExporter.cs ├── JsonDataExporter.cs ├── MarkDownDataExporter.cs ├── SqlInsertDataExporter.cs ├── SqlUpdateDataExporter.cs ├── TsvDataExporter.cs └── XmlDataExporter.cs ├── DataGridHelper.cs ├── DataGridResultViewer.xaml ├── DataGridResultViewer.xaml.cs ├── DataSpaceConverter.cs ├── DatabaseProviderConfiguration.cs ├── DebuggerViewer.xaml ├── DebuggerViewer.xaml.cs ├── DocumentPage.DependencyProperties.cs ├── DocumentPage.xaml ├── DocumentPage.xaml.cs ├── DragDrop ├── DragDropHelper.cs ├── DraggedAdorner.cs └── InsertionAdorner.cs ├── EditDialog.xaml ├── EditDialog.xaml.cs ├── EditableTabHeaderControl.cs ├── EditorNavigationService.cs ├── EmptyIcon.ico ├── Extensions.cs ├── FileResultViewer.xaml ├── FileResultViewer.xaml.cs ├── FindReplace ├── Adapters.cs ├── FindReplace.cs ├── FindReplaceDialog.xaml ├── FindReplaceDialog.xaml.cs ├── IEditor.cs ├── TextSearchHelper.cs ├── next.png └── prev.png ├── FoldingSection.cs ├── GenerateXsdClasses.cmd ├── ICodeCompletionProvider.cs ├── ICodeSnippetProvider.cs ├── IConnectionAdapter.cs ├── IContextActionProvider.cs ├── IDatabaseModel.cs ├── IDebuggerSession.cs ├── IHelpProvider.cs ├── IInfrastructureFactory.cs ├── ILargeTextValue.cs ├── ISqlParser.cs ├── IStatementFormatter.cs ├── IStatementValidator.cs ├── IToken.cs ├── ITokenReader.cs ├── IToolTipProvider.cs ├── IValidationModel.cs ├── InfrastructureConfigurationSection.cs ├── JavaScriptSyntaxHighlight.xshd ├── LargeValueEditor.xaml ├── LargeValueEditor.xaml.cs ├── MainWindow.xaml ├── MainWindow.xaml.cs ├── MarginSetter.cs ├── Messages.cs ├── MetadataCache.cs ├── ModelBase.cs ├── ModificationNotification └── ModificationNotificationMargin.cs ├── MultiNodeEditor.cs ├── Namespaces.cs ├── NodeType.cs ├── OutputViewer.DependencyProperties.cs ├── OutputViewer.xaml ├── OutputViewer.xaml.cs ├── ParseResult.cs ├── ParseStatus.cs ├── PasswordDialog.xaml ├── PasswordDialog.xaml.cs ├── ProgramOverloadList.xaml ├── ProgramOverloadList.xaml.cs ├── Properties ├── AssemblyInfo.cs ├── Resources.Designer.cs ├── Resources.resx ├── Settings.Designer.cs └── Settings.settings ├── Resources.cs ├── ResultInfo.cs ├── ResultSetDataGridTemplateSelector.cs ├── ScrollingTextBox.cs ├── SearchTextBox.cs ├── Snippet.cs ├── Snippet.xsd ├── Snippets.cs ├── SourcePosition.cs ├── SqlDocumentColorizingTransformer.cs ├── SqlDocumentRepository.cs ├── SqlEditor.xaml ├── SqlEditor.xaml.cs ├── SqlEditorBackgroundRenderer.cs ├── SqlFoldingStrategy.cs ├── SqlPad.csproj ├── SqlPad.ico ├── SqlPadTextBox.cs ├── SqlTextEditor.cs ├── StatementBase.cs ├── StatementCollection.cs ├── StatementCommentNode.cs ├── StatementExecutionHistory.xaml ├── StatementExecutionHistory.xaml.cs ├── StatementExecutionModel.cs ├── StatementGrammarNode.cs ├── StatementNode.cs ├── StatusInfoModel.cs ├── TextHelper.cs ├── TextSegment.cs ├── TraceLog.cs ├── WindowClipboardHistory.xaml ├── WindowClipboardHistory.xaml.cs ├── WindowDatabaseMonitor.xaml ├── WindowDatabaseMonitor.xaml.cs ├── WindowOperationMonitor.xaml ├── WindowOperationMonitor.xaml.cs ├── WindowTraceLog.xaml ├── WindowTraceLog.xaml.cs ├── WorkDocument.cs ├── WorkDocumentCollection.cs └── WpfExtensions.cs /.editorconfig: -------------------------------------------------------------------------------- 1 | ; Top-most EditorConfig file 2 | root = true 3 | 4 | [*.cs] 5 | indent_style = tab 6 | indent_size = 4 7 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | *.sln merge=union 7 | *.csproj merge=union 8 | *.vbproj merge=union 9 | *.fsproj merge=union 10 | *.dbproj merge=union 11 | 12 | # Standard to msysgit 13 | *.doc diff=astextplain 14 | *.DOC diff=astextplain 15 | *.docx diff=astextplain 16 | *.DOCX diff=astextplain 17 | *.dot diff=astextplain 18 | *.DOT diff=astextplain 19 | *.pdf diff=astextplain 20 | *.PDF diff=astextplain 21 | *.rtf diff=astextplain 22 | *.RTF diff=astextplain 23 | -------------------------------------------------------------------------------- /License.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2017 Jan Hucka 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. -------------------------------------------------------------------------------- /References/EPPlus.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Husqvik/SQLPad/c858b567aa01be4d5920cd9f9fc05c65c939a584/References/EPPlus.dll -------------------------------------------------------------------------------- /References/ICSharpCode.AvalonEdit.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Husqvik/SQLPad/c858b567aa01be4d5920cd9f9fc05c65c939a584/References/ICSharpCode.AvalonEdit.dll -------------------------------------------------------------------------------- /References/Microsoft.WindowsAPICodePack.Shell.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Husqvik/SQLPad/c858b567aa01be4d5920cd9f9fc05c65c939a584/References/Microsoft.WindowsAPICodePack.Shell.dll -------------------------------------------------------------------------------- /References/Microsoft.WindowsAPICodePack.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Husqvik/SQLPad/c858b567aa01be4d5920cd9f9fc05c65c939a584/References/Microsoft.WindowsAPICodePack.dll -------------------------------------------------------------------------------- /References/MoonPdfLib.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Husqvik/SQLPad/c858b567aa01be4d5920cd9f9fc05c65c939a584/References/MoonPdfLib.dll -------------------------------------------------------------------------------- /References/MouseKeyboardActivityMonitor.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Husqvik/SQLPad/c858b567aa01be4d5920cd9f9fc05c65c939a584/References/MouseKeyboardActivityMonitor.dll -------------------------------------------------------------------------------- /References/Newtonsoft.Json.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Husqvik/SQLPad/c858b567aa01be4d5920cd9f9fc05c65c939a584/References/Newtonsoft.Json.dll -------------------------------------------------------------------------------- /References/Oci/ODAC121024Xcopy_32bit.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Husqvik/SQLPad/c858b567aa01be4d5920cd9f9fc05c65c939a584/References/Oci/ODAC121024Xcopy_32bit.zip -------------------------------------------------------------------------------- /References/Oracle.ManagedDataAccess.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Husqvik/SQLPad/c858b567aa01be4d5920cd9f9fc05c65c939a584/References/Oracle.ManagedDataAccess.dll -------------------------------------------------------------------------------- /References/Oracle.ManagedDataAccessDTC.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Husqvik/SQLPad/c858b567aa01be4d5920cd9f9fc05c65c939a584/References/Oracle.ManagedDataAccessDTC.dll -------------------------------------------------------------------------------- /References/Oracle.ManagedDataAccessIOP.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Husqvik/SQLPad/c858b567aa01be4d5920cd9f9fc05c65c939a584/References/Oracle.ManagedDataAccessIOP.dll -------------------------------------------------------------------------------- /References/Test/Nito.AsyncEx.Enlightenment.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Husqvik/SQLPad/c858b567aa01be4d5920cd9f9fc05c65c939a584/References/Test/Nito.AsyncEx.Enlightenment.dll -------------------------------------------------------------------------------- /References/Test/Nito.AsyncEx.Enlightenment.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Nito.AsyncEx.Enlightenment 5 | 6 | 7 | 8 | 9 | Verifies platform enlightenment. 10 | 11 | 12 | 13 | 14 | Returns a value indicating whether the correct platform enlightenment provider has been loaded. 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /References/Test/Nito.AsyncEx.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Husqvik/SQLPad/c858b567aa01be4d5920cd9f9fc05c65c939a584/References/Test/Nito.AsyncEx.dll -------------------------------------------------------------------------------- /References/Test/Shouldly.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Husqvik/SQLPad/c858b567aa01be4d5920cd9f9fc05c65c939a584/References/Test/Shouldly.dll -------------------------------------------------------------------------------- /References/Test/nunit.framework.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Husqvik/SQLPad/c858b567aa01be4d5920cd9f9fc05c65c939a584/References/Test/nunit.framework.dll -------------------------------------------------------------------------------- /References/Xceed.Wpf.Toolkit.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Husqvik/SQLPad/c858b567aa01be4d5920cd9f9fc05c65c939a584/References/Xceed.Wpf.Toolkit.dll -------------------------------------------------------------------------------- /References/libmupdf.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Husqvik/SQLPad/c858b567aa01be4d5920cd9f9fc05c65c939a584/References/libmupdf.dll -------------------------------------------------------------------------------- /References/protobuf-net.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Husqvik/SQLPad/c858b567aa01be4d5920cd9f9fc05c65c939a584/References/protobuf-net.dll -------------------------------------------------------------------------------- /Screenshots/CodeComplete1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Husqvik/SQLPad/c858b567aa01be4d5920cd9f9fc05c65c939a584/Screenshots/CodeComplete1.png -------------------------------------------------------------------------------- /Screenshots/CodeComplete2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Husqvik/SQLPad/c858b567aa01be4d5920cd9f9fc05c65c939a584/Screenshots/CodeComplete2.png -------------------------------------------------------------------------------- /Screenshots/CodeComplete3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Husqvik/SQLPad/c858b567aa01be4d5920cd9f9fc05c65c939a584/Screenshots/CodeComplete3.png -------------------------------------------------------------------------------- /Screenshots/ColumnTooltip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Husqvik/SQLPad/c858b567aa01be4d5920cd9f9fc05c65c939a584/Screenshots/ColumnTooltip.png -------------------------------------------------------------------------------- /Screenshots/DatabaseMonitor1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Husqvik/SQLPad/c858b567aa01be4d5920cd9f9fc05c65c939a584/Screenshots/DatabaseMonitor1.png -------------------------------------------------------------------------------- /Screenshots/DatabaseOutput.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Husqvik/SQLPad/c858b567aa01be4d5920cd9f9fc05c65c939a584/Screenshots/DatabaseOutput.png -------------------------------------------------------------------------------- /Screenshots/ExecutionStatistics.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Husqvik/SQLPad/c858b567aa01be4d5920cd9f9fc05c65c939a584/Screenshots/ExecutionStatistics.png -------------------------------------------------------------------------------- /Screenshots/ExpandAsterisk.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Husqvik/SQLPad/c858b567aa01be4d5920cd9f9fc05c65c939a584/Screenshots/ExpandAsterisk.png -------------------------------------------------------------------------------- /Screenshots/FunctionOverloads.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Husqvik/SQLPad/c858b567aa01be4d5920cd9f9fc05c65c939a584/Screenshots/FunctionOverloads.png -------------------------------------------------------------------------------- /Screenshots/Overview1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Husqvik/SQLPad/c858b567aa01be4d5920cd9f9fc05c65c939a584/Screenshots/Overview1.png -------------------------------------------------------------------------------- /Screenshots/Overview2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Husqvik/SQLPad/c858b567aa01be4d5920cd9f9fc05c65c939a584/Screenshots/Overview2.png -------------------------------------------------------------------------------- /Screenshots/Overview3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Husqvik/SQLPad/c858b567aa01be4d5920cd9f9fc05c65c939a584/Screenshots/Overview3.png -------------------------------------------------------------------------------- /Screenshots/Overview4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Husqvik/SQLPad/c858b567aa01be4d5920cd9f9fc05c65c939a584/Screenshots/Overview4.png -------------------------------------------------------------------------------- /Screenshots/StatementExecutionHistory.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Husqvik/SQLPad/c858b567aa01be4d5920cd9f9fc05c65c939a584/Screenshots/StatementExecutionHistory.png -------------------------------------------------------------------------------- /Screenshots/TableTooltip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Husqvik/SQLPad/c858b567aa01be4d5920cd9f9fc05c65c939a584/Screenshots/TableTooltip.png -------------------------------------------------------------------------------- /Screenshots/TraceEvents.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Husqvik/SQLPad/c858b567aa01be4d5920cd9f9fc05c65c939a584/Screenshots/TraceEvents.png -------------------------------------------------------------------------------- /SqlPad.Oracle.Database.Test/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /SqlPad.Oracle.Database.Test/ConsoleTraceListenerTestFixture.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics; 2 | using NUnit.Framework; 3 | 4 | namespace SqlPad.Oracle.Database.Test 5 | { 6 | [SetUpFixture] 7 | public class ConsoleTraceListenerTestFixture 8 | { 9 | [OneTimeSetUp] 10 | public void SetUp() 11 | { 12 | Trace.Listeners.Add(new ConsoleTraceListener()); 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /SqlPad.Oracle.Database.Test/OracleConfiguration.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | C:\Oracle\product\12.1.0\dbhome_1\BIN\tkprof.exe 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /SqlPad.Oracle.Database.Test/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // General Information about an assembly is controlled through the following 5 | // set of attributes. Change these attribute values to modify the information 6 | // associated with an assembly. 7 | [assembly: AssemblyTitle("SqlPad.Oracle.Database.Test")] 8 | [assembly: AssemblyDescription("")] 9 | [assembly: AssemblyConfiguration("")] 10 | [assembly: AssemblyCompany("")] 11 | [assembly: AssemblyProduct("SqlPad.Oracle.Database.Test")] 12 | [assembly: AssemblyCopyright("Copyright © 2016")] 13 | [assembly: AssemblyTrademark("")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | // Setting ComVisible to false makes the types in this assembly not visible 17 | // to COM components. If you need to access a type in this assembly from 18 | // COM, set the ComVisible attribute to true on that type. 19 | [assembly: ComVisible(false)] 20 | 21 | // The following GUID is for the ID of the typelib if this project is exposed to COM 22 | [assembly: Guid("5517bbaf-6f68-4c3f-aefc-b3670adba9a9")] 23 | 24 | // Version information for an assembly consists of the following four values: 25 | // 26 | // Major Version 27 | // Minor Version 28 | // Build Number 29 | // Revision 30 | // 31 | // You can specify all the values or you can default the Build and Revision Numbers 32 | // by using the '*' as shown below: 33 | // [assembly: AssemblyVersion("1.0.*")] 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] 36 | -------------------------------------------------------------------------------- /SqlPad.Oracle.Test/Commands/OracleTestCommandSettingsProviderFactory.cs: -------------------------------------------------------------------------------- 1 | using SqlPad.Commands; 2 | 3 | namespace SqlPad.Oracle.Test.Commands 4 | { 5 | internal class OracleTestCommandSettingsProviderFactory : ICommandSettingsProviderFactory 6 | { 7 | public ICommandSettingsProvider CreateCommandSettingsProvider(CommandSettingsModel settings) 8 | { 9 | return new TestCommandSettings(settings); 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /SqlPad.Oracle.Test/Commands/TestCommandSettings.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SqlPad.Commands; 3 | 4 | namespace SqlPad.Oracle.Test.Commands 5 | { 6 | internal class TestCommandSettings : ICommandSettingsProvider 7 | { 8 | private readonly bool _isValueValid; 9 | 10 | public TestCommandSettings(CommandSettingsModel settingsModel, bool isValueValid = true) 11 | { 12 | Settings = settingsModel; 13 | _isValueValid = isValueValid; 14 | } 15 | 16 | public EventHandler GetSettingsCalled; 17 | 18 | public bool GetSettings() 19 | { 20 | GetSettingsCalled?.Invoke(this, EventArgs.Empty); 21 | 22 | return _isValueValid; 23 | } 24 | 25 | public CommandSettingsModel Settings { get; } 26 | } 27 | } -------------------------------------------------------------------------------- /SqlPad.Oracle.Test/ConsoleTraceListenerTestFixture.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics; 2 | using NUnit.Framework; 3 | 4 | namespace SqlPad.Oracle.Test 5 | { 6 | [SetUpFixture] 7 | public class ConsoleTraceListenerTestFixture 8 | { 9 | [OneTimeSetUp] 10 | public void SetUp() 11 | { 12 | Trace.Listeners.Add(new ConsoleTraceListener()); 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /SqlPad.Oracle.Test/OracleSnippetProviderTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Linq; 4 | using NUnit.Framework; 5 | using Shouldly; 6 | using SqlPad.Test; 7 | 8 | namespace SqlPad.Oracle.Test 9 | { 10 | [TestFixture] 11 | public class OracleSnippetProviderTest : TemporaryDirectoryTestFixture 12 | { 13 | private static readonly OracleSnippetProvider SnippetProvider = new OracleSnippetProvider(); 14 | 15 | [SetUp] 16 | public void SetUpSnippets() 17 | { 18 | ConfigurationProvider.SetSnippetsFolder(TempDirectoryName); 19 | ConfigurationProvider.SetCodeGenerationItemFolder(TempDirectoryName); 20 | 21 | var sourceDirectoryName = Path.Combine(Path.GetDirectoryName(new Uri(GetType().Assembly.CodeBase).LocalPath), "TestFiles"); 22 | 23 | const string fileNameTestSnippet = "TestSnippet.xml"; 24 | const string fileNameSelectSnippet = "SnippetSelect.xml"; 25 | File.Copy(Path.Combine(sourceDirectoryName, fileNameTestSnippet), Path.Combine(TempDirectoryName, fileNameTestSnippet), true); 26 | File.Copy(Path.Combine(sourceDirectoryName, fileNameSelectSnippet), Path.Combine(TempDirectoryName, fileNameSelectSnippet), true); 27 | } 28 | 29 | [Test] 30 | public void TestSnippetSuggestionWithinStatementWhileTyping() 31 | { 32 | const string statementText = "SELECT DUMMY FROM\r\nD\r\nDUAL"; 33 | var snippets = SnippetProvider.GetSnippets(statementText, 21, TestFixture.DatabaseModel).ToArray(); 34 | snippets.Length.ShouldBe(0); 35 | } 36 | 37 | [Test] 38 | public void TestSnippetSuggestionAfterSemicolon() 39 | { 40 | const string statementText = ";SEL"; 41 | var snippets = SnippetProvider.GetSnippets(statementText, 4, TestFixture.DatabaseModel).ToArray(); 42 | snippets.Length.ShouldBe(1); 43 | } 44 | 45 | [Test] 46 | public void TestSnippetSuggestionAfterCommonTableExpression() 47 | { 48 | const string statementText = "WITH cte AS (SELECT * FROM DUAL) se"; 49 | var snippets = SnippetProvider.GetSnippets(statementText, 35, TestFixture.DatabaseModel).ToArray(); 50 | snippets.Length.ShouldBe(1); 51 | } 52 | 53 | [Test] 54 | public void TestSnippetWithoutParameterAndAllowedTerminals() 55 | { 56 | var snippets = SnippetProvider.GetSnippets("TES", 3, TestFixture.DatabaseModel).ToArray(); 57 | snippets.Length.ShouldBe(1); 58 | snippets[0].Name.ShouldBe("Test"); 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /SqlPad.Oracle.Test/OracleTestInfrastructureFactory.cs: -------------------------------------------------------------------------------- 1 | using System.Configuration; 2 | 3 | namespace SqlPad.Oracle.Test 4 | { 5 | public class OracleTestInfrastructureFactory : OracleInfrastructureFactory, IInfrastructureFactory 6 | { 7 | public new IDatabaseModel CreateDatabaseModel(ConnectionStringSettings connectionString, string identifier) 8 | { 9 | return OracleTestDatabaseModel.Instance; 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /SqlPad.Oracle.Test/OracleTestObjectScriptExtractor.cs: -------------------------------------------------------------------------------- 1 | using System.Threading; 2 | using System.Threading.Tasks; 3 | using SqlPad.Oracle.DatabaseConnection; 4 | using SqlPad.Oracle.DataDictionary; 5 | 6 | namespace SqlPad.Oracle.Test 7 | { 8 | public class OracleTestObjectScriptExtractor : IOracleObjectScriptExtractor 9 | { 10 | internal const string SelectionTableCreateScript = 11 | @"CREATE TABLE ""HUSQVIK"".""SELECTION"" 12 | (""SELECTION_ID"" NUMBER, 13 | ""CURRENTSTARTED"" NUMBER, 14 | ""CURRENTCOMPLETES"" NUMBER, 15 | ""STATUS"" NUMBER, 16 | ""RESPONDENTBUCKET_ID"" NUMBER, 17 | ""PROJECT_ID"" NUMBER, 18 | ""NAME"" VARCHAR2(100) 19 | ) SEGMENT CREATION IMMEDIATE 20 | PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 21 | NOCOMPRESS LOGGING 22 | STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 23 | PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 24 | BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT) 25 | TABLESPACE ""TBS_HQ_PDB"""; 26 | 27 | internal const string TablespaceCreateScript = 28 | @"CREATE BIGFILE TABLESPACE ""TBS_HQ_PDB"" DATAFILE 29 | 'E:\ORACLE\ORADATA\HQ12C\HQ_PDB\TBS_HQ_PDB.DBF' SIZE 4294967296 30 | AUTOEXTEND ON NEXT 536870912 MAXSIZE 33554431M 31 | LOGGING ONLINE PERMANENT BLOCKSIZE 8192 32 | EXTENT MANAGEMENT LOCAL AUTOALLOCATE DEFAULT 33 | NOCOMPRESS SEGMENT SPACE MANAGEMENT AUTO 34 | ALTER DATABASE DATAFILE 35 | 'E:\ORACLE\ORADATA\HQ12C\HQ_PDB\TBS_HQ_PDB.DBF' RESIZE 15032385536"; 36 | 37 | public Task ExtractSchemaObjectScriptAsync(OracleObject schemaObject, CancellationToken cancellationToken) 38 | { 39 | return Task.FromResult(SelectionTableCreateScript); 40 | } 41 | 42 | public Task ExtractNonSchemaObjectScriptAsync(string objectName, string objectType, CancellationToken cancellationToken) 43 | { 44 | return Task.FromResult(TablespaceCreateScript); 45 | } 46 | 47 | public Task ExtractViewTextAsync(OracleObjectIdentifier viewIdentifier, CancellationToken cancellationToken) 48 | { 49 | return Task.FromResult("SELECT dummy FROM dual"); 50 | } 51 | } 52 | } -------------------------------------------------------------------------------- /SqlPad.Oracle.Test/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // General Information about an assembly is controlled through the following 5 | // set of attributes. Change these attribute values to modify the information 6 | // associated with an assembly. 7 | [assembly: AssemblyTitle("SqlPad.Oracle.Test")] 8 | [assembly: AssemblyDescription("")] 9 | [assembly: AssemblyConfiguration("")] 10 | [assembly: AssemblyCompany("")] 11 | [assembly: AssemblyProduct("SqlPad.Oracle.Test")] 12 | [assembly: AssemblyCopyright("Copyright © 2016")] 13 | [assembly: AssemblyTrademark("")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | // Setting ComVisible to false makes the types in this assembly not visible 17 | // to COM components. If you need to access a type in this assembly from 18 | // COM, set the ComVisible attribute to true on that type. 19 | [assembly: ComVisible(false)] 20 | 21 | // The following GUID is for the ID of the typelib if this project is exposed to COM 22 | [assembly: Guid("b174dac5-9bec-4767-a27e-3765e0059c6c")] 23 | 24 | // Version information for an assembly consists of the following four values: 25 | // 26 | // Major Version 27 | // Minor Version 28 | // Build Number 29 | // Revision 30 | // 31 | // You can specify all the values or you can default the Build and Revision Numbers 32 | // by using the '*' as shown below: 33 | // [assembly: AssemblyVersion("1.0.*")] 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] 36 | -------------------------------------------------------------------------------- /SqlPad.Oracle.Test/StatementGrammarNodeTest.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using NUnit.Framework; 3 | using Shouldly; 4 | using NonTerminals = SqlPad.Oracle.OracleGrammarDescription.NonTerminals; 5 | using Terminals = SqlPad.Oracle.OracleGrammarDescription.Terminals; 6 | 7 | namespace SqlPad.Oracle.Test 8 | { 9 | [TestFixture] 10 | public class StatementGrammarNodeTest 11 | { 12 | private StatementGrammarNode _rootNode; 13 | 14 | [SetUp] 15 | public void SetUp() 16 | { 17 | const string sqlText = "WITH XXX AS (SELECT 3 COL FROM DUAL CTE_OUTER_ALIAS_1) SELECT VP1 COL1, (SELECT 1 FROM XXX SC_ALIAS_1) SCALARSUBQUERY FROM (WITH YYY AS (SELECT 1 FROM SYS.DUAL CTE_INNER_ALIAS_1), ZZZ AS (SELECT 2 FROM DUAL CTE_INNER_ALIAS_2), FFF AS (SELECT 4 FROM XXX CTE_INNER_ALIAS_3) SELECT COL + 1 VP1 FROM (SELECT COL FROM XXX TABLE_ALIAS_1, DUAL TABLE_ALIAS_2) TABLE_ALIAS_3) SUBQUERY"; 18 | var result = OracleSqlParser.Instance.Parse(sqlText); 19 | 20 | result.Count.ShouldBe(1); 21 | 22 | var oracleStatement = result.Single(); 23 | oracleStatement.ParseStatus.ShouldBe(ParseStatus.Success); 24 | 25 | _rootNode = oracleStatement.RootNode; 26 | } 27 | 28 | [Test] 29 | public void TestGetPathFilterDescendants() 30 | { 31 | var rootNestedQuery = _rootNode[0, 0, 0]; 32 | var commonTableExpressions = rootNestedQuery.GetPathFilterDescendants(n => n.Id != NonTerminals.NestedQuery, NonTerminals.CommonTableExpression).ToArray(); 33 | commonTableExpressions.Length.ShouldBe(1); 34 | 35 | commonTableExpressions = _rootNode.GetDescendants(NonTerminals.CommonTableExpression).ToArray(); 36 | commonTableExpressions.Length.ShouldBe(4); 37 | } 38 | 39 | [Test] 40 | public void TestStatementCollectionGetNodeAtPositionAtSemicolonBetweenStatements() 41 | { 42 | var statements = OracleSqlParser.Instance.Parse("SELECT * FROM DUAL;SELECT * FROM DUAL"); 43 | var node = statements.GetNodeAtPosition(18); 44 | node.Id.ShouldBe(Terminals.ObjectIdentifier); 45 | 46 | node = statements.GetNodeAtPosition(19); 47 | node.Id.ShouldBe(Terminals.Select); 48 | } 49 | } 50 | } -------------------------------------------------------------------------------- /SqlPad.Oracle.Test/TestFiles/TestSnippet.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /SqlPad.Oracle.Test/TestFixture.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using SqlPad.Oracle.DatabaseConnection; 4 | 5 | namespace SqlPad.Oracle.Test 6 | { 7 | public class TestFixture 8 | { 9 | public static readonly OracleDatabaseModelBase DatabaseModel = OracleTestDatabaseModel.Instance; 10 | 11 | public static SqlDocumentRepository CreateDocumentRepository() 12 | { 13 | return new SqlDocumentRepository(OracleSqlParser.Instance, new OracleStatementValidator(), DatabaseModel); 14 | } 15 | } 16 | 17 | public static class TestExtensions 18 | { 19 | public static StatementBase Validate(this StatementBase statement) 20 | { 21 | if (statement.RootNode == null || statement.RootNode.TerminalCount <= 1) 22 | return statement; 23 | 24 | var sortedTerminals = statement.AllTerminals.OrderBy(t => t.SourcePosition.IndexStart).ToArray(); 25 | var terminal = sortedTerminals[0]; 26 | var allTerminals = statement.AllTerminals.ToArray(); 27 | 28 | for (var i = 1; i < sortedTerminals.Length; i++) 29 | { 30 | var followingTerminal = sortedTerminals[i]; 31 | if (terminal.SourcePosition.IndexEnd >= followingTerminal.SourcePosition.IndexStart) 32 | throw new InvalidOperationException($"Terminals '{terminal.Id}' and '{followingTerminal.Id}' within the statement are overlapping. "); 33 | 34 | if (followingTerminal != allTerminals[i]) 35 | throw new InvalidOperationException($"Terminals within the statement are in invalid order (index {i}). "); 36 | 37 | terminal = followingTerminal; 38 | } 39 | 40 | return statement; 41 | } 42 | } 43 | } -------------------------------------------------------------------------------- /SqlPad.Oracle/CodeGenerationItems/CreateFunction.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 10 | CREATE FUNCTION 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /SqlPad.Oracle/CodeGenerationItems/CreatePackage.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 9 | CREATE PACKAGE 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /SqlPad.Oracle/CodeGenerationItems/CreatePackageBody.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 13 | CREATE PACKAGE 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /SqlPad.Oracle/CodeGenerationItems/CreateProcedure.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 10 | CREATE PROCEDURE 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /SqlPad.Oracle/Commands/AddToGroupByCommand.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using SqlPad.Commands; 4 | using NonTerminals = SqlPad.Oracle.OracleGrammarDescription.NonTerminals; 5 | 6 | namespace SqlPad.Oracle.Commands 7 | { 8 | internal class AddToGroupByCommand : AddExpressionToClauseCommandBase 9 | { 10 | public const string Title = "Add to GROUP BY clause"; 11 | 12 | private AddToGroupByCommand(ActionExecutionContext executionContext) 13 | : base(executionContext) 14 | { 15 | } 16 | 17 | protected override TextSegment ResolveAddedTextSegment() 18 | { 19 | var groupByClause = CurrentQueryBlock.RootNode[NonTerminals.GroupByClause]; 20 | if (groupByClause == null) 21 | { 22 | var targetNode = 23 | CurrentQueryBlock.RootNode[NonTerminals.HierarchicalQueryClause] 24 | ?? CurrentQueryBlock.RootNode[NonTerminals.WhereClause] 25 | ?? CurrentQueryBlock.FromClause; 26 | 27 | if (targetNode?.LastTerminalNode != null) 28 | { 29 | return 30 | new TextSegment 31 | { 32 | IndextStart = targetNode.LastTerminalNode.SourcePosition.IndexEnd + 1, 33 | Length = 0, 34 | Text = $" GROUP BY {ExpressionText}" 35 | }; 36 | } 37 | 38 | return TextSegment.Empty; 39 | } 40 | 41 | var groupingExpressions = 42 | groupByClause.GetPathFilterDescendants(n => !n.Id.In(NonTerminals.GroupingSetsClause, NonTerminals.RollupCubeClause, NonTerminals.NestedQuery, NonTerminals.HavingClause), NonTerminals.GroupingClause) 43 | .Where(n => n.ChildNodes.Count > 0 && String.Equals(n.ChildNodes[0].Id, NonTerminals.Expression)); 44 | 45 | StatementGrammarNode lastGroupingExpression = null; 46 | foreach (var groupingExpression in groupingExpressions) 47 | { 48 | if (TerminalCollectionEqual(groupingExpression.Terminals, SelectedTerminals)) 49 | { 50 | return TextSegment.Empty; 51 | } 52 | 53 | lastGroupingExpression = groupingExpression; 54 | } 55 | 56 | var commaPrefix = lastGroupingExpression == null ? String.Empty : ", "; 57 | return 58 | new TextSegment 59 | { 60 | IndextStart = (lastGroupingExpression?.SourcePosition.IndexEnd ?? groupByClause.SourcePosition.IndexEnd) + 1, 61 | Length = 0, 62 | Text = $"{commaPrefix}{ExpressionText}" 63 | }; 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /SqlPad.Oracle/Commands/AddToOrderByCommand.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using SqlPad.Commands; 4 | 5 | namespace SqlPad.Oracle.Commands 6 | { 7 | internal class AddToOrderByCommand : AddExpressionToClauseCommandBase 8 | { 9 | public const string Title = "Add to ORDER BY clause"; 10 | 11 | private AddToOrderByCommand(ActionExecutionContext executionContext) 12 | : base(executionContext) 13 | { 14 | } 15 | 16 | protected override TextSegment ResolveAddedTextSegment() 17 | { 18 | var subqueryNode = CurrentQueryBlock.RootNode.GetAncestor(OracleGrammarDescription.NonTerminals.Subquery); 19 | var orderByClause = subqueryNode[OracleGrammarDescription.NonTerminals.OrderByClause]; 20 | if (orderByClause == null) 21 | { 22 | var targetNode = subqueryNode[OracleGrammarDescription.NonTerminals.OptionalParenthesisEnclosedConcatenatedQueryBlock]; 23 | return 24 | new TextSegment 25 | { 26 | IndextStart = targetNode.LastTerminalNode.SourcePosition.IndexEnd + 1, 27 | Length = 0, 28 | Text = $" ORDER BY {ExpressionText}" 29 | }; 30 | } 31 | 32 | var orderExpressions = 33 | orderByClause.GetPathFilterDescendants(n => !n.Id.In(OracleGrammarDescription.NonTerminals.NestedQuery), OracleGrammarDescription.NonTerminals.OrderExpression) 34 | .Where(n => n.ChildNodes.Count > 0); 35 | 36 | StatementGrammarNode lastOrderExpression = null; 37 | foreach (var orderExpression in orderExpressions) 38 | { 39 | if (TerminalCollectionEqual(orderExpression.Terminals, SelectedTerminals)) 40 | { 41 | return TextSegment.Empty; 42 | } 43 | 44 | lastOrderExpression = orderExpression; 45 | } 46 | 47 | var commaPrefix = lastOrderExpression == null ? String.Empty : ", "; 48 | return 49 | new TextSegment 50 | { 51 | IndextStart = (lastOrderExpression?.SourcePosition.IndexEnd ?? orderByClause.SourcePosition.IndexEnd) + 1, 52 | Length = 0, 53 | Text = $"{commaPrefix}{ExpressionText}" 54 | }; 55 | } 56 | } 57 | } -------------------------------------------------------------------------------- /SqlPad.Oracle/Commands/CleanRedundantSymbolCommand.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using SqlPad.Commands; 5 | using Terminals = SqlPad.Oracle.OracleGrammarDescription.Terminals; 6 | 7 | namespace SqlPad.Oracle.Commands 8 | { 9 | internal class CleanRedundantSymbolCommand : OracleCommandBase 10 | { 11 | public const string Title = "Clean redundant symbols"; 12 | 13 | private IReadOnlyCollection _terminalGroupsToRemove; 14 | 15 | private CleanRedundantSymbolCommand(ActionExecutionContext executionContext) 16 | : base(executionContext) 17 | { 18 | } 19 | 20 | protected override CommandCanExecuteResult CanExecute() 21 | { 22 | var prerequisitesMet = 23 | ExecutionContext.SelectionLength == 0 && CurrentNode != null && 24 | SemanticModel.RedundantSymbolGroups.Any(); 25 | 26 | if (!prerequisitesMet) 27 | { 28 | return false; 29 | } 30 | 31 | var terminalGroupsToRemove = (IEnumerable)SemanticModel.RedundantSymbolGroups; 32 | 33 | var doGlobalClean = CurrentNode.Id.In(Terminals.Select, Terminals.Update, Terminals.Insert, Terminals.Delete, Terminals.Merge); 34 | if (doGlobalClean) 35 | { 36 | if (CurrentQueryBlock != null) 37 | { 38 | terminalGroupsToRemove = terminalGroupsToRemove.Where(g => g.Any(n => n.HasAncestor(CurrentQueryBlock.RootNode) || (CurrentQueryBlock.OrderByClause != null && n.HasAncestor(CurrentQueryBlock.OrderByClause)))); 39 | } 40 | } 41 | else 42 | { 43 | terminalGroupsToRemove = terminalGroupsToRemove.Where(g => g.Contains(CurrentNode)); 44 | } 45 | 46 | _terminalGroupsToRemove = terminalGroupsToRemove.ToArray(); 47 | 48 | return _terminalGroupsToRemove.Count > 0; 49 | } 50 | 51 | protected override void Execute() 52 | { 53 | var removedTerminals = _terminalGroupsToRemove.SelectMany(g => g); 54 | var removedSegments = removedTerminals 55 | .Select(n => 56 | new TextSegment 57 | { 58 | IndextStart = n.SourcePosition.IndexStart, 59 | Length = n.SourcePosition.Length, 60 | Text = String.Empty 61 | }); 62 | 63 | ExecutionContext.SegmentsToReplace.AddRange(removedSegments); 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /SqlPad.Oracle/Commands/ExpandViewCommand.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading; 3 | using System.Threading.Tasks; 4 | using SqlPad.Commands; 5 | using SqlPad.Oracle.DataDictionary; 6 | using SqlPad.Oracle.SemanticModel; 7 | 8 | namespace SqlPad.Oracle.Commands 9 | { 10 | internal class ExpandViewCommand : OracleCommandBase 11 | { 12 | private OracleView _view; 13 | private OracleDataObjectReference _objectReference; 14 | public const string Title = "Expand"; 15 | 16 | private ExpandViewCommand(ActionExecutionContext executionContext) 17 | : base(executionContext) 18 | { 19 | } 20 | 21 | protected override CommandCanExecuteResult CanExecute() 22 | { 23 | if (CurrentNode == null) 24 | { 25 | return false; 26 | } 27 | 28 | _objectReference = SemanticModel.GetReference(CurrentNode); 29 | _view = _objectReference?.SchemaObject.GetTargetSchemaObject() as OracleView; 30 | return _view != null; 31 | } 32 | 33 | protected override void Execute() 34 | { 35 | ExecuteAsync(CancellationToken.None).Wait(); 36 | } 37 | 38 | protected override async Task ExecuteAsync(CancellationToken cancellationToken) 39 | { 40 | var viewText = await SemanticModel.DatabaseModel.ObjectScriptExtractor.ExtractViewTextAsync(_view.FullyQualifiedName, cancellationToken); 41 | if (String.IsNullOrEmpty(viewText)) 42 | { 43 | return; 44 | } 45 | 46 | var segment = 47 | new TextSegment 48 | { 49 | IndextStart = _objectReference.RootNode.SourcePosition.IndexStart, 50 | Text = $"({viewText}) " 51 | }; 52 | 53 | ExecutionContext.SegmentsToReplace.Add(segment); 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /SqlPad.Oracle/Commands/ExtractPackageInterfaceCommand.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Text; 4 | using SqlPad.Commands; 5 | using SqlPad.Oracle.SemanticModel; 6 | using NonTerminals = SqlPad.Oracle.OracleGrammarDescription.NonTerminals; 7 | 8 | namespace SqlPad.Oracle.Commands 9 | { 10 | internal class ExtractPackageInterfaceCommand : OracleCommandBase 11 | { 12 | private OraclePlSqlProgram _program; 13 | public const string Title = "Extract interface"; 14 | 15 | private readonly OraclePlSqlStatementSemanticModel _plSqlModel; 16 | 17 | private ExtractPackageInterfaceCommand(ActionExecutionContext executionContext) 18 | : base(executionContext) 19 | { 20 | _plSqlModel = SemanticModel as OraclePlSqlStatementSemanticModel; 21 | } 22 | 23 | protected override CommandCanExecuteResult CanExecute() 24 | { 25 | if (CurrentNode == null || _plSqlModel == null) 26 | { 27 | return false; 28 | } 29 | 30 | _program = _plSqlModel.Programs.SingleOrDefault(p => p.RootNode.SourcePosition.Contains(CurrentNode.SourcePosition)); 31 | if (_program == null) 32 | { 33 | return false; 34 | } 35 | 36 | return 37 | _program.Type == PlSqlProgramType.PackageProgram && String.Equals(_program.RootNode.Id, NonTerminals.CreatePackageBody) && 38 | CurrentNode.HasAncestor(_program.RootNode[NonTerminals.SchemaObject]); 39 | } 40 | 41 | protected override void Execute() 42 | { 43 | var interfaceBuilder = new StringBuilder(); 44 | interfaceBuilder.AppendLine(); 45 | interfaceBuilder.AppendLine(); 46 | 47 | var packageName = _program.ObjectIdentifier.ToFormattedString(); 48 | interfaceBuilder.AppendLine($"CREATE OR REPLACE PACKAGE {packageName} AS"); 49 | 50 | foreach (var subProgram in _program.SubPrograms) 51 | { 52 | var signatureNode = subProgram.RootNode[0]; 53 | if (!signatureNode.Id.In(NonTerminals.ProcedureHeading, NonTerminals.FunctionHeading)) 54 | continue; 55 | 56 | interfaceBuilder.AppendLine($"\t{signatureNode.GetText(_plSqlModel.StatementText)};"); 57 | } 58 | 59 | interfaceBuilder.AppendLine($"END {packageName};"); 60 | 61 | var segment = 62 | new TextSegment 63 | { 64 | IndextStart = _program.RootNode.SourcePosition.IndexEnd + 1, 65 | Text = interfaceBuilder.ToString() 66 | }; 67 | 68 | ExecutionContext.SegmentsToReplace.Add(segment); 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /SqlPad.Oracle/Commands/GenerateCustomTypeCSharpWrapperClassCommand.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Text; 4 | using System.Windows; 5 | using SqlPad.Commands; 6 | using SqlPad.Oracle.DataDictionary; 7 | using SqlPad.Oracle.SemanticModel; 8 | using Terminals = SqlPad.Oracle.OracleGrammarDescription.Terminals; 9 | 10 | namespace SqlPad.Oracle.Commands 11 | { 12 | internal class GenerateCustomTypeCSharpWrapperClassCommand : OracleCommandBase 13 | { 14 | public const string Title = "Generate C# class"; 15 | 16 | private OracleTypeBase _oracleObjectType; 17 | 18 | private GenerateCustomTypeCSharpWrapperClassCommand(ActionExecutionContext executionContext) 19 | : base(executionContext) 20 | { 21 | } 22 | 23 | protected override CommandCanExecuteResult CanExecute() 24 | { 25 | if (!String.Equals(CurrentNode?.Id, Terminals.Identifier)) 26 | { 27 | return false; 28 | } 29 | 30 | var semanticModel = (OracleStatementSemanticModel)ExecutionContext.DocumentRepository.ValidationModels[CurrentNode.Statement].SemanticModel; 31 | _oracleObjectType = (OracleTypeBase)semanticModel.GetTypeReference(CurrentNode)?.SchemaObject.GetTargetSchemaObject(); 32 | 33 | return _oracleObjectType != null && _oracleObjectType.FullyQualifiedName != OracleDataType.XmlType.FullyQualifiedName; 34 | } 35 | 36 | protected override void Execute() 37 | { 38 | var builder = new StringBuilder(); 39 | using (var writer = new StringWriter(builder)) 40 | { 41 | CustomTypeCSharpWrapperClassGenerator.Generate(_oracleObjectType, writer); 42 | } 43 | 44 | Clipboard.SetText(builder.ToString()); 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /SqlPad.Oracle/Commands/SplitStringCommand.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using SqlPad.Commands; 4 | using Terminals = SqlPad.Oracle.OracleGrammarDescription.Terminals; 5 | 6 | namespace SqlPad.Oracle.Commands 7 | { 8 | internal class SplitStringCommand : OracleCommandBase 9 | { 10 | public const string Title = "Split string"; 11 | 12 | private const char SingleQuoteCharacter = '\''; 13 | 14 | private int _trimIndex; 15 | private bool _isQuotedString; 16 | private int _positionInString; 17 | 18 | private string LiteralValue => CurrentNode.Token.Value; 19 | 20 | private SplitStringCommand(ActionExecutionContext executionContext) 21 | : base(executionContext) 22 | { 23 | } 24 | 25 | protected override CommandCanExecuteResult CanExecute() 26 | { 27 | var isAtStringLiteral = CurrentNode != null && String.Equals(CurrentNode.Id, Terminals.StringLiteral); 28 | if (!isAtStringLiteral) 29 | { 30 | return false; 31 | } 32 | 33 | _trimIndex = OracleExtensions.GetTrimIndex(LiteralValue, out _isQuotedString, out var quoteInitializer); 34 | var endOffset = _isQuotedString ? 1 : 0; 35 | _positionInString = ExecutionContext.CaretOffset - CurrentNode.SourcePosition.IndexStart; 36 | 37 | if (IsAfterOddApostrophe()) 38 | { 39 | _positionInString++; 40 | } 41 | 42 | return _positionInString >= _trimIndex && _positionInString < LiteralValue.Length - endOffset; 43 | } 44 | 45 | private bool IsAfterOddApostrophe() 46 | { 47 | if (_isQuotedString || LiteralValue[_positionInString] != SingleQuoteCharacter) 48 | { 49 | return false; 50 | } 51 | 52 | return LiteralValue.Substring(0, _positionInString) 53 | .Reverse() 54 | .TakeWhile(c => c == SingleQuoteCharacter) 55 | .Count() % 2 == 1; 56 | } 57 | 58 | protected override void Execute() 59 | { 60 | var stringInitializer = _isQuotedString ? LiteralValue.Substring(0, _trimIndex) : "'"; 61 | var stringFinalizer = _isQuotedString ? LiteralValue.Substring(LiteralValue.Length - 2, 2) : "'"; 62 | 63 | var firstPart = LiteralValue.Substring(0, _positionInString); 64 | var secondPart = LiteralValue.Substring(_positionInString); 65 | 66 | ExecutionContext.SegmentsToReplace.Add( 67 | new TextSegment 68 | { 69 | IndextStart = CurrentNode.SourcePosition.IndexStart, 70 | Length = CurrentNode.SourcePosition.Length, 71 | Text = $"{firstPart}{stringFinalizer} || || {stringInitializer}{secondPart}" 72 | }); 73 | 74 | ExecutionContext.CaretOffset = CurrentNode.SourcePosition.IndexStart + firstPart.Length + stringFinalizer.Length + 4; 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /SqlPad.Oracle/Commands/SqlTextBuilder.cs: -------------------------------------------------------------------------------- 1 | using System.Text; 2 | 3 | namespace SqlPad.Oracle.Commands 4 | { 5 | public class SqlTextBuilder 6 | { 7 | private static readonly OracleConfigurationFormatterFormatOptions FormatOptions = OracleConfiguration.Configuration.Formatter.FormatOptions; 8 | 9 | private readonly StringBuilder _builder = new StringBuilder(); 10 | 11 | public override string ToString() 12 | { 13 | return _builder.ToString(); 14 | } 15 | 16 | public void AppendIdentifier(string value) 17 | { 18 | AppendFormat(value, FormatOptions.Identifier); 19 | } 20 | 21 | public void AppendAlias(string value) 22 | { 23 | AppendFormat(value, FormatOptions.Alias); 24 | } 25 | 26 | public void AppendKeyword(string value) 27 | { 28 | AppendFormat(value, FormatOptions.Keyword); 29 | } 30 | 31 | public void AppendReservedWord(string value) 32 | { 33 | AppendFormat(value, FormatOptions.ReservedWord); 34 | } 35 | 36 | public void AppendText(string value) 37 | { 38 | _builder.Append(value); 39 | } 40 | 41 | public void AppendLine() 42 | { 43 | _builder.AppendLine(); 44 | } 45 | 46 | private void AppendFormat(string value, FormatOption formatOption) 47 | { 48 | var formattedValue = OracleStatementFormatter.FormatTerminalValue(value, formatOption); 49 | _builder.Append(formattedValue); 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /SqlPad.Oracle/Commands/ToggleQuotedNotationCommand.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using SqlPad.Commands; 5 | using Terminals = SqlPad.Oracle.OracleGrammarDescription.Terminals; 6 | 7 | namespace SqlPad.Oracle.Commands 8 | { 9 | internal class ToggleQuotedNotationCommand : OracleCommandBase 10 | { 11 | public const string Title = "Toggle quoted notation"; 12 | 13 | private StatementGrammarNode _sourceNode; 14 | 15 | private ToggleQuotedNotationCommand(ActionExecutionContext executionContext) 16 | : base(executionContext) 17 | { 18 | } 19 | 20 | protected override CommandCanExecuteResult CanExecute() 21 | { 22 | if (CurrentNode == null || CurrentNode != CurrentNode.Statement.RootNode.FirstTerminalNode) 23 | { 24 | return false; 25 | } 26 | 27 | _sourceNode = CurrentQueryBlock != null && String.Equals(CurrentNode.Id, Terminals.Select) 28 | ? CurrentQueryBlock.RootNode 29 | : CurrentNode.Statement.RootNode; 30 | 31 | return GetReplacedSegments().Any(); 32 | } 33 | 34 | protected override void Execute() 35 | { 36 | ExecutionContext.SegmentsToReplace.AddRange(GetReplacedSegments()); 37 | } 38 | 39 | private IEnumerable GetReplacedSegments() 40 | { 41 | bool? enableQuotes = null; 42 | foreach (var identifier in _sourceNode.Terminals.Where(t => t.Id.IsIdentifierOrAlias() && t.Token.Value.ToQuotedIdentifier() != t.Token.Value.ToSimpleIdentifier() && !t.Token.Value.CollidesWithReservedWord())) 43 | { 44 | if (!enableQuotes.HasValue) 45 | { 46 | enableQuotes = !identifier.Token.Value.IsQuoted(); 47 | } 48 | 49 | if ((enableQuotes.Value && identifier.Token.Value.IsQuoted()) || 50 | !enableQuotes.Value && !identifier.Token.Value.IsQuoted()) 51 | continue; 52 | 53 | var replacedLength = enableQuotes.Value ? 0 : 1; 54 | var newText = enableQuotes.Value ? "\"" : String.Empty; 55 | 56 | yield return new TextSegment 57 | { 58 | IndextStart = identifier.SourcePosition.IndexStart, 59 | Length = replacedLength, 60 | Text = newText 61 | }; 62 | 63 | yield return new TextSegment 64 | { 65 | IndextStart = identifier.SourcePosition.IndexEnd + 1 - replacedLength, 66 | Length = replacedLength, 67 | Text = newText 68 | }; 69 | } 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /SqlPad.Oracle/DataDictionary/OracleColumn.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics; 2 | 3 | namespace SqlPad.Oracle.DataDictionary 4 | { 5 | [DebuggerDisplay("OracleColumn (Name={Name}; Type={FullTypeName}; Nullable={Nullable})")] 6 | public class OracleColumn 7 | { 8 | private const string ColumnNameColumnValue = "\"COLUMN_VALUE\""; 9 | 10 | public OracleColumn(bool isPseudocolumn = false) 11 | { 12 | IsPseudocolumn = isPseudocolumn; 13 | } 14 | 15 | public OracleDataType DataType { get; set; } 16 | 17 | public string Name { get; set; } 18 | 19 | public string FullTypeName => OracleDataType.ResolveFullTypeName(DataType, CharacterSize); 20 | 21 | public int? CharacterSize { get; set; } 22 | 23 | public bool Nullable { get; set; } 24 | 25 | public bool Virtual { get; set; } 26 | 27 | public bool? UserGenerated { get; set; } 28 | 29 | public bool Hidden { get; set; } 30 | 31 | public string DefaultValue { get; set; } 32 | 33 | public bool IsPseudocolumn { get; private set; } 34 | 35 | public OracleColumn Clone() 36 | { 37 | return 38 | new OracleColumn 39 | { 40 | DataType = DataType, 41 | Name = Name, 42 | CharacterSize = CharacterSize, 43 | Nullable = Nullable, 44 | Hidden = Hidden 45 | }; 46 | } 47 | 48 | public static OracleColumn BuildColumnValueColumn(OracleDataType columnType) 49 | { 50 | return 51 | new OracleColumn 52 | { 53 | Name = ColumnNameColumnValue, 54 | DataType = columnType, 55 | Nullable = true 56 | }; 57 | } 58 | } 59 | 60 | public enum DataUnit 61 | { 62 | NotApplicable, 63 | Byte, 64 | Character 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /SqlPad.Oracle/DataDictionary/OracleConstraint.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Diagnostics; 3 | 4 | namespace SqlPad.Oracle.DataDictionary 5 | { 6 | public abstract class OracleConstraint : OracleObject 7 | { 8 | public abstract ConstraintType ConstraintType { get; } 9 | 10 | public OracleSchemaObject OwnerObject { get; set; } 11 | 12 | public IList Columns { get; set; } 13 | 14 | public bool IsEnabled { get; set; } 15 | 16 | public bool IsDeferrable { get; set; } 17 | 18 | public bool IsValidated { get; set; } 19 | 20 | public bool IsRelied { get; set; } 21 | 22 | public override string Type { get; } = OracleObjectType.Constraint; 23 | } 24 | 25 | [DebuggerDisplay("OraclePrimaryKeyConstraint (Name={FullyQualifiedName.Name}; IsEnabled={IsEnabled}; IsDeferrable={IsDeferrable}; IsValidated={IsValidated}; IsRelied={IsRelied})")] 26 | public class OraclePrimaryKeyConstraint : OracleUniqueConstraint 27 | { 28 | public override ConstraintType ConstraintType => ConstraintType.PrimaryKey; 29 | } 30 | 31 | [DebuggerDisplay("OracleUniqueConstraint (Name={FullyQualifiedName.Name}; IsEnabled={IsEnabled}; IsDeferrable={IsDeferrable}; IsValidated={IsValidated}; IsRelied={IsRelied})")] 32 | public class OracleUniqueConstraint : OracleConstraint 33 | { 34 | public override ConstraintType ConstraintType => ConstraintType.Unique; 35 | } 36 | 37 | [DebuggerDisplay("OracleCheckConstraint (Name={FullyQualifiedName.Name}; IsEnabled={IsEnabled}; IsDeferrable={IsDeferrable}; IsValidated={IsValidated}; IsRelied={IsRelied})")] 38 | public class OracleCheckConstraint : OracleConstraint 39 | { 40 | public override ConstraintType ConstraintType => ConstraintType.Check; 41 | } 42 | 43 | [DebuggerDisplay("OracleForeignKeyConstraint (Name={FullyQualifiedName.Name}; IsEnabled={IsEnabled}; IsDeferrable={IsDeferrable}; IsValidated={IsValidated}; IsRelied={IsRelied})")] 44 | public class OracleReferenceConstraint : OracleConstraint 45 | { 46 | public OracleSchemaObject TargetObject { get; set; } 47 | 48 | public OracleUniqueConstraint ReferenceConstraint { get; set; } 49 | 50 | public DeleteRule DeleteRule { get; set; } 51 | 52 | public override ConstraintType ConstraintType => ConstraintType.ForeignKey; 53 | } 54 | 55 | public enum ConstraintType 56 | { 57 | PrimaryKey, 58 | Unique, 59 | Check, 60 | ForeignKey, 61 | } 62 | 63 | public enum DeleteRule 64 | { 65 | None, 66 | SetNull, 67 | Cascade 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /SqlPad.Oracle/DataDictionary/OracleDatabaseLink.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | 4 | namespace SqlPad.Oracle.DataDictionary 5 | { 6 | [DebuggerDisplay("OracleDatabaseLink (Name={FullyQualifiedName.Name}; Host={Host}; UserName={UserName}; Created={Created})")] 7 | public class OracleDatabaseLink : OracleObject 8 | { 9 | public string UserName { get; set; } 10 | 11 | public string Host { get; set; } 12 | 13 | public DateTime Created { get; set; } 14 | 15 | public override string Type { get; } = OracleObjectType.DatabaseLink; 16 | } 17 | } -------------------------------------------------------------------------------- /SqlPad.Oracle/DataDictionary/OracleObjectFactory.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace SqlPad.Oracle.DataDictionary 4 | { 5 | internal static class OracleObjectFactory 6 | { 7 | public static OracleSchemaObject CreateSchemaObjectMetadata(string objectType, string owner, string name, bool isValid, DateTime created, DateTime lastDdl, bool isTemporary) 8 | { 9 | var schemaObject = CreateObjectMetadata(objectType); 10 | schemaObject.FullyQualifiedName = OracleObjectIdentifier.Create(owner, name); 11 | schemaObject.IsValid = isValid; 12 | schemaObject.Created = created; 13 | schemaObject.LastDdl = lastDdl; 14 | schemaObject.IsTemporary = isTemporary; 15 | 16 | return schemaObject; 17 | } 18 | 19 | public static OracleConstraint CreateConstraint(string constraintType, string owner, string name, bool isEnabled, bool isValidated, bool isDeferrable, bool isRelied) 20 | { 21 | var constraint = CreateConstraint(constraintType); 22 | constraint.FullyQualifiedName = OracleObjectIdentifier.Create(owner, name); 23 | constraint.IsEnabled = isEnabled; 24 | constraint.IsValidated = isValidated; 25 | constraint.IsDeferrable = isDeferrable; 26 | constraint.IsRelied = isRelied; 27 | 28 | return constraint; 29 | } 30 | 31 | private static OracleConstraint CreateConstraint(string constraintType) 32 | { 33 | switch (constraintType) 34 | { 35 | case "P": 36 | return new OraclePrimaryKeyConstraint(); 37 | case "U": 38 | return new OracleUniqueConstraint(); 39 | case "R": 40 | return new OracleReferenceConstraint(); 41 | case "C": 42 | return new OracleCheckConstraint(); 43 | default: 44 | throw new InvalidOperationException($"Constraint type '{constraintType}' not supported. "); 45 | } 46 | } 47 | 48 | private static OracleSchemaObject CreateObjectMetadata(string objectType) 49 | { 50 | switch (objectType) 51 | { 52 | case OracleObjectType.Table: 53 | return new OracleTable(); 54 | case OracleObjectType.View: 55 | return new OracleView(); 56 | case OracleObjectType.Synonym: 57 | return new OracleSynonym(); 58 | case OracleObjectType.Function: 59 | return new OracleFunction(); 60 | case OracleObjectType.Procedure: 61 | return new OracleProcedure(); 62 | case OracleObjectType.Sequence: 63 | return new OracleSequence(); 64 | case OracleObjectType.Package: 65 | return new OraclePackage(); 66 | case OracleObjectType.Directory: 67 | return new OracleDirectory(); 68 | default: 69 | throw new InvalidOperationException($"Object type '{objectType}' not supported. "); 70 | } 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /SqlPad.Oracle/DatabaseConnection/OracleConnectionAdapterBase.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Threading; 3 | using System.Threading.Tasks; 4 | using SqlPad.Oracle.ExecutionPlan; 5 | using SqlPad.Oracle.DebugTrace; 6 | 7 | namespace SqlPad.Oracle.DatabaseConnection 8 | { 9 | public abstract class OracleConnectionAdapterBase : IConnectionAdapter 10 | { 11 | public abstract IDatabaseModel DatabaseModel { get; } 12 | 13 | public abstract IDebuggerSession DebuggerSession { get; } 14 | 15 | public virtual void Dispose() { } 16 | 17 | public abstract bool CanFetch(ResultInfo resultInfo); 18 | 19 | public abstract bool IsExecuting { get; } 20 | 21 | public abstract bool EnableDatabaseOutput { get; set; } 22 | 23 | public abstract string Identifier { get; set; } 24 | 25 | public abstract Task ExecuteStatementAsync(StatementBatchExecutionModel executionModel, CancellationToken cancellationToken); 26 | 27 | public abstract Task ExecuteChildStatementAsync(StatementExecutionModel executionModel, CancellationToken cancellationToken); 28 | 29 | public abstract Task RefreshResult(StatementExecutionResult result, CancellationToken cancellationToken); 30 | 31 | public abstract Task> GetExecutionStatisticsAsync(CancellationToken cancellationToken); 32 | 33 | public abstract Task> FetchRecordsAsync(ResultInfo resultInfo, int rowCount, CancellationToken cancellationToken); 34 | 35 | public abstract bool HasActiveTransaction { get; } 36 | 37 | public abstract string TransanctionIdentifier { get; } 38 | 39 | public abstract Task CommitTransaction(); 40 | 41 | public abstract Task RollbackTransaction(); 42 | 43 | public abstract Task ExplainPlanAsync(StatementExecutionModel executionModel, CancellationToken cancellationToken); 44 | 45 | public abstract Task GetCursorExecutionStatisticsAsync(CancellationToken cancellationToken); 46 | 47 | public abstract Task ActivateTraceEvents(IEnumerable traceEvents, string traceIdentifier, CancellationToken cancellationToken); 48 | 49 | public abstract Task StopTraceEvents(CancellationToken cancellationToken); 50 | 51 | public abstract string TraceFileName { get; } 52 | 53 | public abstract SessionIdentifier? SessionIdentifier { get; } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /SqlPad.Oracle/DatabaseConnection/OracleObjectScriptExtractor.cs: -------------------------------------------------------------------------------- 1 | using System.Threading; 2 | using System.Threading.Tasks; 3 | using SqlPad.Oracle.DataDictionary; 4 | using SqlPad.Oracle.ModelDataProviders; 5 | 6 | namespace SqlPad.Oracle.DatabaseConnection 7 | { 8 | public interface IOracleObjectScriptExtractor 9 | { 10 | Task ExtractSchemaObjectScriptAsync(OracleObject schemaObject, CancellationToken cancellationToken); 11 | 12 | Task ExtractNonSchemaObjectScriptAsync(string objectName, string objectType, CancellationToken cancellationToken); 13 | 14 | Task ExtractViewTextAsync(OracleObjectIdentifier viewIdentifier, CancellationToken cancellationToken); 15 | } 16 | 17 | public class OracleObjectScriptExtractor : IOracleObjectScriptExtractor 18 | { 19 | private readonly OracleDatabaseModelBase _databaseModel; 20 | 21 | public OracleObjectScriptExtractor(OracleDatabaseModelBase databaseModel) 22 | { 23 | _databaseModel = databaseModel; 24 | } 25 | 26 | public async Task ExtractSchemaObjectScriptAsync(OracleObject schemaObject, CancellationToken cancellationToken) 27 | { 28 | var scriptDataProvider = new ObjectScriptDataProvider(schemaObject); 29 | await UpdateDataModel(cancellationToken, scriptDataProvider); 30 | return scriptDataProvider.ScriptText; 31 | } 32 | 33 | public async Task ExtractNonSchemaObjectScriptAsync(string objectName, string objectType, CancellationToken cancellationToken) 34 | { 35 | var scriptDataProvider = new ObjectScriptDataProvider(objectName, objectType); 36 | await UpdateDataModel(cancellationToken, scriptDataProvider); 37 | return scriptDataProvider.ScriptText; 38 | } 39 | 40 | public async Task ExtractViewTextAsync(OracleObjectIdentifier viewIdentifier, CancellationToken cancellationToken) 41 | { 42 | var dataModel = new ViewDetailModel(); 43 | var viewDetailsDataProvider = new ViewDetailDataProvider(dataModel, viewIdentifier, _databaseModel.Version); 44 | await UpdateDataModel(cancellationToken, viewDetailsDataProvider); 45 | return dataModel.Text; 46 | } 47 | 48 | private async Task UpdateDataModel(CancellationToken cancellationToken, IModelDataProvider scriptDataProvider) 49 | { 50 | var connectionString = OracleConnectionStringRepository.GetBackgroundConnectionString(_databaseModel.ConnectionString.ConnectionString); 51 | await OracleDatabaseModel.UpdateModelAsync(connectionString, _databaseModel.CurrentSchema, false, cancellationToken, scriptDataProvider); 52 | } 53 | } 54 | } -------------------------------------------------------------------------------- /SqlPad.Oracle/DebugTrace/OracleTraceIdentifier.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace SqlPad.Oracle.DebugTrace 4 | { 5 | public static class OracleTraceIdentifier 6 | { 7 | public static string Normalize(string traceIdentifier) 8 | { 9 | return String.IsNullOrEmpty(traceIdentifier) ? "''''" : $"\"{traceIdentifier.Replace('"', '_').Replace("'", "''")}\""; 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /SqlPad.Oracle/Documentation.Extensions.cs: -------------------------------------------------------------------------------- 1 | using System.Xml.Serialization; 2 | 3 | namespace SqlPad.Oracle 4 | { 5 | public partial class DocumentationPackageSubProgram 6 | { 7 | [XmlIgnore] 8 | public DocumentationPackage PackageDocumentation { get; internal set; } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /SqlPad.Oracle/ExecutionPlan/ExecutionStatisticsPlanItemCollection.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | 4 | namespace SqlPad.Oracle.ExecutionPlan 5 | { 6 | public class ExecutionStatisticsPlanItemCollection : ExecutionPlanItemCollectionBase 7 | { 8 | public string PlanText { get; set; } 9 | } 10 | 11 | [DebuggerDisplay("ExecutionStatisticsPlanItem (Id={Id}; Operation={Operation}; Depth={Depth}; IsLeaf={IsLeaf}; ExecutionOrder={ExecutionOrder})")] 12 | public class ExecutionStatisticsPlanItem : ExecutionPlanItem 13 | { 14 | public DateTime Timestamp { get; set; } 15 | 16 | public int Executions { get; set; } 17 | 18 | public int? LastStarts { get; set; } 19 | 20 | public int? TotalStarts { get; set; } 21 | 22 | public long? LastOutputRows { get; set; } 23 | 24 | public long? TotalOutputRows { get; set; } 25 | 26 | public long? LastConsistentReadBufferGets { get; set; } 27 | 28 | public long? TotalConsistentReadBufferGets { get; set; } 29 | 30 | public long? LastCurrentReadBufferGets { get; set; } 31 | 32 | public long? TotalCurrentReadBufferGets { get; set; } 33 | 34 | public long? LastDiskReads { get; set; } 35 | 36 | public long? TotalDiskReads { get; set; } 37 | 38 | public long? LastDiskWrites { get; set; } 39 | 40 | public long? TotalDiskWrites { get; set; } 41 | 42 | public TimeSpan? LastElapsedTime { get; set; } 43 | 44 | public TimeSpan? TotalElapsedTime { get; set; } 45 | 46 | public string WorkAreaSizingPolicy { get; set; } 47 | 48 | public long? EstimatedOptimalSizeBytes { get; set; } 49 | 50 | public long? EstimatedOnePassSizeBytes { get; set; } 51 | 52 | public long? LastMemoryUsedBytes { get; set; } 53 | 54 | public string LastExecutionMethod { get; set; } 55 | 56 | public int? LastParallelDegree { get; set; } 57 | 58 | public int? TotalWorkAreaExecutions { get; set; } 59 | 60 | public int? OptimalWorkAreaExecutions { get; set; } 61 | 62 | public int? OnePassWorkAreaExecutions { get; set; } 63 | 64 | public int? MultiPassWorkAreaExecutions { get; set; } 65 | 66 | public TimeSpan? ActiveWorkAreaTime { get; set; } 67 | 68 | public long? MaxTemporarySizeBytes { get; set; } 69 | 70 | public long? LastTemporarySizeBytes { get; set; } 71 | } 72 | } -------------------------------------------------------------------------------- /SqlPad.Oracle/GenerateXsdClasses.cmd: -------------------------------------------------------------------------------- 1 | xsd OracleSqlGrammar.xsd /c /n:SqlPad.Oracle 2 | xsd OracleConfiguration.xsd /c /n:SqlPad.Oracle 3 | xsd Documentation.xsd /c /n:SqlPad.Oracle -------------------------------------------------------------------------------- /SqlPad.Oracle/ModelDataProviders/IModelDataProvider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading; 3 | using System.Threading.Tasks; 4 | #if ORACLE_MANAGED_DATA_ACCESS_CLIENT 5 | using Oracle.ManagedDataAccess.Client; 6 | #else 7 | using Oracle.DataAccess.Client; 8 | #endif 9 | 10 | namespace SqlPad.Oracle.ModelDataProviders 11 | { 12 | internal interface IModelDataProvider 13 | { 14 | void InitializeCommand(OracleCommand command); 15 | 16 | Task MapReaderData(OracleDataReader reader, CancellationToken cancellationToken); 17 | 18 | void MapScalarValue(object value); 19 | 20 | bool HasScalarResult { get; } 21 | 22 | bool IsValid { get; } 23 | } 24 | 25 | internal abstract class ModelDataProvider : IModelDataProvider 26 | { 27 | protected TModel DataModel { get; private set; } 28 | 29 | protected ModelDataProvider(TModel dataModel) 30 | { 31 | DataModel = dataModel; 32 | } 33 | 34 | public abstract void InitializeCommand(OracleCommand command); 35 | 36 | public virtual Task MapReaderData(OracleDataReader reader, CancellationToken cancellationToken) 37 | { 38 | throw new NotSupportedException("Override this method if you want to map data from the reader. "); 39 | } 40 | 41 | public virtual bool HasScalarResult => false; 42 | 43 | public virtual bool IsValid => true; 44 | 45 | public virtual void MapScalarValue(object value) 46 | { 47 | throw new NotSupportedException("Override this method to get scalar value from a query. "); 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /SqlPad.Oracle/ModelDataProviders/UserDataProvider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading; 3 | using System.Threading.Tasks; 4 | using SqlPad.Oracle.DatabaseConnection; 5 | using SqlPad.Oracle.ToolTips; 6 | #if ORACLE_MANAGED_DATA_ACCESS_CLIENT 7 | using Oracle.ManagedDataAccess.Client; 8 | #else 9 | using Oracle.DataAccess.Client; 10 | #endif 11 | 12 | namespace SqlPad.Oracle.ModelDataProviders 13 | { 14 | internal class UserDataProvider : ModelDataProvider 15 | { 16 | public UserDataProvider(OracleSchemaModel dataModel) 17 | : base(dataModel) 18 | { 19 | } 20 | 21 | public override void InitializeCommand(OracleCommand command) 22 | { 23 | command.CommandText = OracleDatabaseCommands.SelectUserAdditionalData; 24 | command.AddSimpleParameter("USERNAME", DataModel.Schema.Name.Trim('"')); 25 | } 26 | 27 | public override async Task MapReaderData(OracleDataReader reader, CancellationToken cancellationToken) 28 | { 29 | if (!await reader.ReadAsynchronous(cancellationToken)) 30 | { 31 | return; 32 | } 33 | 34 | DataModel.AccountStatus = (string)reader["ACCOUNT_STATUS"]; 35 | DataModel.LockDate = OracleReaderValueConvert.ToDateTime(reader["LOCK_DATE"]); 36 | DataModel.ExpiryDate = OracleReaderValueConvert.ToDateTime(reader["EXPIRY_DATE"]); 37 | DataModel.DefaultTablespace = (string)reader["DEFAULT_TABLESPACE"]; 38 | DataModel.TemporaryTablespace = (string)reader["TEMPORARY_TABLESPACE"]; 39 | DataModel.Profile = (string)reader["PROFILE"]; 40 | DataModel.EditionsEnabled = String.Equals((string)reader["EDITIONS_ENABLED"], "Y"); 41 | DataModel.AuthenticationType = (string)reader["AUTHENTICATION_TYPE"]; 42 | DataModel.LastLogin = OracleReaderValueConvert.ToDateTime(reader["LAST_LOGIN"]); 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /SqlPad.Oracle/OracleBindVariable.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Collections.ObjectModel; 4 | using TerminalValues = SqlPad.Oracle.OracleGrammarDescription.TerminalValues; 5 | 6 | namespace SqlPad.Oracle 7 | { 8 | public static class OracleBindVariable 9 | { 10 | public const string DataTypeUnicodeClob = "NCLOB"; 11 | public const string DataTypeRefCursor = "REF CURSOR"; 12 | 13 | public static readonly ReadOnlyDictionary DataTypes = 14 | new ReadOnlyDictionary( 15 | new Dictionary 16 | { 17 | { TerminalValues.Char, new BindVariableType(TerminalValues.Char, typeof(string), false) }, 18 | { TerminalValues.Clob, new BindVariableType(TerminalValues.Clob, typeof(string), true) }, 19 | { TerminalValues.Date, new BindVariableType(TerminalValues.Date, typeof(DateTime), false) }, 20 | { TerminalValues.Timestamp, new BindVariableType(TerminalValues.Timestamp, typeof(DateTime), false) }, 21 | { TerminalValues.NChar, new BindVariableType(TerminalValues.NChar, typeof(string), false) }, 22 | { DataTypeUnicodeClob, new BindVariableType(DataTypeUnicodeClob, typeof(string), true) }, 23 | { TerminalValues.Number, new BindVariableType(TerminalValues.Number, typeof(string), false) }, 24 | { TerminalValues.NVarchar2, new BindVariableType(TerminalValues.NVarchar2, typeof(string), false) }, 25 | { TerminalValues.Varchar2, new BindVariableType(TerminalValues.Varchar2, typeof(string), false) }, 26 | { DataTypeRefCursor, new BindVariableType(DataTypeRefCursor, typeof(string), false) }, 27 | { TerminalValues.Raw, new BindVariableType(TerminalValues.Raw, typeof(string), true) }, 28 | { TerminalValues.Blob, new BindVariableType(TerminalValues.Blob, typeof(string), true) } 29 | }); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /SqlPad.Oracle/OracleCommandSettingsProviderFactory.cs: -------------------------------------------------------------------------------- 1 | using SqlPad.Commands; 2 | 3 | namespace SqlPad.Oracle 4 | { 5 | public class OracleCommandSettingsProviderFactory : ICommandSettingsProviderFactory 6 | { 7 | public ICommandSettingsProvider CreateCommandSettingsProvider(CommandSettingsModel settings) 8 | { 9 | return new EditDialog(settings); 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /SqlPad.Oracle/OracleConfiguration.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | ALTER SESSION SET optimizer_dynamic_sampling = 0 plsql_debug = true; 5 | 6 | BEGIN 7 | utl_http.set_body_charset('UTF8'); 8 | utl_http.set_wallet(path => 'file:C:/oracle/wallet'); 9 | END; 10 | 11 | C:\Oracle\product\12.1.0\dbhome_1\BIN\tkprof.exe 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /SqlPad.Oracle/OracleDataExportConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | using TerminalValues = SqlPad.Oracle.OracleGrammarDescription.TerminalValues; 4 | 5 | namespace SqlPad.Oracle 6 | { 7 | public class OracleDataExportConverter : IDataExportConverter 8 | { 9 | public string ToSqlValue(object value) 10 | { 11 | var stringValue = value.ToString(); 12 | if (String.IsNullOrEmpty(stringValue)) 13 | { 14 | return TerminalValues.Null; 15 | } 16 | 17 | var vendorValue = value as IValue; 18 | return vendorValue != null 19 | ? vendorValue.ToSqlLiteral() 20 | : value is Int16 || value is Int32 || value is Int64 21 | ? stringValue 22 | : $"'{stringValue.Replace("'", "''")}'"; 23 | } 24 | 25 | public string ToColumnName(string columnHeader) 26 | { 27 | if (columnHeader.Length > 30) 28 | { 29 | columnHeader = columnHeader.Substring(0, 30); 30 | } 31 | 32 | return 33 | columnHeader.RequiresQuotes() 34 | ? $"\"{columnHeader.Replace('"', ' ')}\"" 35 | : columnHeader; 36 | } 37 | 38 | public string ToXml(object value) 39 | { 40 | var vendorValue = value as IValue; 41 | return vendorValue != null 42 | ? vendorValue.ToXml() 43 | : value.ToString().ToXmlCompliant(); 44 | } 45 | 46 | public string ToJson(object value) 47 | { 48 | var stringValue = value.ToString(); 49 | var vendorValue = value as IValue; 50 | return vendorValue != null 51 | ? vendorValue.ToJson() 52 | : value is Int16 || value is Int32 || value is Int64 53 | ? stringValue 54 | : $"\"{stringValue.Replace("\"", "\\\"")}\""; 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /SqlPad.Oracle/OracleIdentifierValidationRule.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using System.Windows.Controls; 4 | 5 | namespace SqlPad.Oracle 6 | { 7 | public class OracleIdentifierValidationRule : ValidationRule 8 | { 9 | public override ValidationResult Validate(object value, CultureInfo cultureInfo) 10 | { 11 | var identifier = (string)value; 12 | return new ValidationResult(AllowEmpty && String.IsNullOrEmpty(identifier) || OracleSqlParser.IsValidIdentifier(identifier), "Identifier contains characters that are not allowed, starts with a number, has more than 30 characters or matches a reserved word. "); 13 | } 14 | 15 | public bool AllowEmpty { get; set; } 16 | } 17 | 18 | public class OracleBindVariableIdentifierValidationRule : ValidationRule 19 | { 20 | private readonly Version _databaseVersion; 21 | 22 | public OracleBindVariableIdentifierValidationRule(Version databaseVersion) 23 | { 24 | _databaseVersion = databaseVersion; 25 | } 26 | 27 | public override ValidationResult Validate(object value, CultureInfo cultureInfo) 28 | { 29 | return new ValidationResult(OracleStatementValidator.IsValidBindVariableIdentifier((string)value, _databaseVersion), "Bind variable identifier contains characters that are not allowed, has more than 30 characters, matches a reserved word or is a number value not between 0 and 65535. "); 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /SqlPad.Oracle/OracleSqlGrammar.Extension.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using System.Text.RegularExpressions; 4 | 5 | namespace SqlPad.Oracle 6 | { 7 | [DebuggerDisplay("SqlGrammarStartSymbol (Id={" + nameof(Id) + "})")] 8 | public partial class SqlGrammarStartSymbol 9 | { 10 | 11 | } 12 | 13 | [DebuggerDisplay("SqlGrammarRuleSequence (Elements={Items.Length}, Comment={Comment})")] 14 | public partial class SqlGrammarRuleSequence 15 | { 16 | } 17 | 18 | [DebuggerDisplay("SqlGrammarTerminal (Id={Id}, Value={Value}, RegexValue={RegexValue})")] 19 | public partial class SqlGrammarTerminal 20 | { 21 | internal void Initialize() 22 | { 23 | if (!String.IsNullOrEmpty(RegexValue)) 24 | { 25 | RegexMatcher = new Regex(RegexValue, RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.CultureInvariant); 26 | } 27 | } 28 | 29 | internal Regex RegexMatcher { get; private set; } 30 | 31 | internal bool IsFixed => RegexMatcher == null; 32 | } 33 | 34 | [DebuggerDisplay("SqlGrammarRuleSequenceTerminal (Id={Id}, IsOptional={IsOptional})")] 35 | public partial class SqlGrammarRuleSequenceTerminal : ISqlGrammarRuleSequenceItem 36 | { 37 | public bool IsRequired => !isOptionalFieldSpecified || (isOptionalFieldSpecified && !IsOptional); 38 | 39 | public NodeType Type => NodeType.Terminal; 40 | 41 | public SqlGrammarRuleSequence ParentSequence { get; set; } 42 | 43 | public int SequenceIndex { get; set; } 44 | 45 | public SqlGrammarTerminal Terminal; 46 | } 47 | 48 | [DebuggerDisplay("SqlGrammarRuleSequenceNonTerminal (Id={Id}, IsOptional={IsOptional})")] 49 | public partial class SqlGrammarRuleSequenceNonTerminal : ISqlGrammarRuleSequenceItem 50 | { 51 | public bool IsRequired => !isOptionalFieldSpecified || (isOptionalFieldSpecified && !IsOptional); 52 | 53 | public NodeType Type => NodeType.NonTerminal; 54 | 55 | public SqlGrammarRuleSequence ParentSequence { get; set; } 56 | 57 | public int SequenceIndex { get; set; } 58 | 59 | public SqlGrammarRule TargetRule; 60 | } 61 | 62 | public interface ISqlGrammarRuleSequenceItem 63 | { 64 | NodeType Type { get; } 65 | 66 | string Id { get; } 67 | 68 | bool IsRequired { get; } 69 | 70 | SqlGrammarRuleSequence ParentSequence { get; } 71 | 72 | int SequenceIndex { get; } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /SqlPad.Oracle/OracleToken.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics; 2 | 3 | namespace SqlPad.Oracle 4 | { 5 | [DebuggerDisplay("OracleToken (Value={Value}, Index={Index})")] 6 | public struct OracleToken : IToken 7 | { 8 | public static OracleToken Empty = new OracleToken(); 9 | public readonly CommentType CommentType; 10 | public readonly int Index; 11 | public readonly string Value; 12 | public readonly string UpperInvariantValue; 13 | 14 | public OracleToken(string value, int index, CommentType commentType = CommentType.None) 15 | { 16 | UpperInvariantValue = value.ToUpperInvariant(); 17 | Value = value; 18 | Index = index; 19 | CommentType = commentType; 20 | } 21 | 22 | string IToken.Value => Value; 23 | 24 | int IToken.Index => Index; 25 | 26 | CommentType IToken.CommentType => CommentType; 27 | } 28 | } -------------------------------------------------------------------------------- /SqlPad.Oracle/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | using System.Windows; 5 | using SqlPad; 6 | 7 | // General Information about an assembly is controlled through the following 8 | // set of attributes. Change these attribute values to modify the information 9 | // associated with an assembly. 10 | [assembly: AssemblyTitle("SQL Pad for Oracle")] 11 | [assembly: AssemblyDescription("")] 12 | [assembly: AssemblyConfiguration("")] 13 | [assembly: AssemblyCompany("")] 14 | [assembly: AssemblyProduct("SqlPad.Oracle")] 15 | [assembly: AssemblyCopyright("Copyright © 2016")] 16 | [assembly: AssemblyTrademark("")] 17 | [assembly: AssemblyCulture("")] 18 | 19 | // Setting ComVisible to false makes the types in this assembly not visible 20 | // to COM components. If you need to access a type in this assembly from 21 | // COM, set the ComVisible attribute to true on that type. 22 | [assembly: ComVisible(false)] 23 | 24 | [assembly: InternalsVisibleTo("SqlPad.Oracle.Test")] 25 | [assembly: InternalsVisibleTo("SqlPad.Oracle.Database.Test")] 26 | 27 | // The following GUID is for the ID of the typelib if this project is exposed to COM 28 | [assembly: Guid("8d6c6950-3d58-4806-b550-3dcd66579ef4")] 29 | 30 | // Version information for an assembly consists of the following four values: 31 | // 32 | // Major Version 33 | // Minor Version 34 | // Build Number 35 | // Revision 36 | // 37 | // You can specify all the values or you can default the Build and Revision Numbers 38 | // by using the '*' as shown below: 39 | // [assembly: AssemblyVersion("1.0.*")] 40 | [assembly: AssemblyVersion("0.4.0.489")] 41 | [assembly: AssemblyFileVersion("0.4.0.489")] 42 | [assembly: AssemblyBuildInfo("d7ddc296", "2019-05-12 11:07:36")] 43 | [assembly: ThemeInfo(ResourceDictionaryLocation.None, ResourceDictionaryLocation.SourceAssembly)] -------------------------------------------------------------------------------- /SqlPad.Oracle/Scripts/CreateExplainPlanTable.sql: -------------------------------------------------------------------------------- 1 | CREATE GLOBAL TEMPORARY TABLE EXPLAIN_PLAN 2 | ( 3 | STATEMENT_ID VARCHAR2(30), 4 | PLAN_ID NUMBER, 5 | TIMESTAMP DATE, 6 | REMARKS VARCHAR2(4000), 7 | OPERATION VARCHAR2(30), 8 | OPTIONS VARCHAR2(255), 9 | OBJECT_NODE VARCHAR2(128), 10 | OBJECT_OWNER VARCHAR2(30), 11 | OBJECT_NAME VARCHAR2(30), 12 | OBJECT_ALIAS VARCHAR2(65), 13 | OBJECT_INSTANCE INTEGER, 14 | OBJECT_TYPE VARCHAR2(30), 15 | OPTIMIZER VARCHAR2(255), 16 | SEARCH_COLUMNS NUMBER, 17 | ID INTEGER, 18 | PARENT_ID INTEGER, 19 | DEPTH INTEGER, 20 | POSITION INTEGER, 21 | COST INTEGER, 22 | CARDINALITY INTEGER, 23 | BYTES INTEGER, 24 | OTHER_TAG VARCHAR2(255), 25 | PARTITION_START VARCHAR2(255), 26 | PARTITION_STOP VARCHAR2(255), 27 | PARTITION_ID INTEGER, 28 | OTHER LONG, 29 | DISTRIBUTION VARCHAR2(30), 30 | CPU_COST INTEGER, 31 | IO_COST INTEGER, 32 | TEMP_SPACE INTEGER, 33 | ACCESS_PREDICATES VARCHAR2(4000), 34 | FILTER_PREDICATES VARCHAR2(4000), 35 | PROJECTION VARCHAR2(4000), 36 | TIME INTEGER, 37 | QBLOCK_NAME VARCHAR2(30), 38 | OTHER_XML CLOB 39 | ) 40 | ON COMMIT PRESERVE ROWS; 41 | 42 | CREATE OR REPLACE PUBLIC SYNONYM EXPLAIN_PLAN FOR EXPLAIN_PLAN; 43 | -------------------------------------------------------------------------------- /SqlPad.Oracle/SemanticModel/OracleColumnReference.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.Linq; 5 | using SqlPad.Oracle.DataDictionary; 6 | 7 | namespace SqlPad.Oracle.SemanticModel 8 | { 9 | [DebuggerDisplay("OracleColumnReference (Owner={OwnerNode == null ? null : OwnerNode.Token.Value}; Object={ObjectNode == null ? null : ObjectNode.Token.Value}; Column={ColumnNode.Token.Value}; Placement={Placement}; HasExplicitDefinition={HasExplicitDefinition})")] 10 | public class OracleColumnReference : OracleReference 11 | { 12 | private StatementGrammarNode _columnNode; 13 | private string _normalizedName; 14 | 15 | public OracleColumnReference(OracleReferenceContainer referenceContainer) 16 | { 17 | ColumnNodeObjectReferences = new HashSet(); 18 | ColumnNodeColumnReferences = new List(); 19 | Container = referenceContainer; 20 | } 21 | 22 | public override string Name => _columnNode.Token.Value; 23 | 24 | public override string NormalizedName => _normalizedName; 25 | 26 | public bool ReferencesAllColumns => String.Equals(_columnNode.Token.Value, "*"); 27 | 28 | public StatementGrammarNode OldOuterJoinOperatorNode { get; set; } 29 | 30 | public StatementGrammarNode ColumnNode 31 | { 32 | get { return _columnNode; } 33 | set 34 | { 35 | if (_columnNode == value) 36 | { 37 | return; 38 | } 39 | 40 | _columnNode = value; 41 | _normalizedName = _columnNode?.Token.Value.ToQuotedIdentifier(); 42 | } 43 | } 44 | 45 | public ICollection ColumnNodeObjectReferences { get; } 46 | 47 | public ICollection ColumnNodeColumnReferences { get; set; } 48 | 49 | public OracleColumn ColumnDescription { get; set; } 50 | 51 | public bool IsCorrelated { get; set; } 52 | 53 | public OracleObjectWithColumnsReference ValidObjectReference 54 | { 55 | get 56 | { 57 | if (ColumnNodeObjectReferences.Count == 1) 58 | return ColumnNodeObjectReferences.First(); 59 | 60 | return ObjectNodeObjectReferences.Count == 1 61 | ? ObjectNodeObjectReferences.First() 62 | : null; 63 | } 64 | } 65 | 66 | protected override IEnumerable GetAdditionalIdentifierTerminals() 67 | { 68 | if (_columnNode != null) 69 | { 70 | yield return _columnNode; 71 | } 72 | } 73 | 74 | public override void Accept(IOracleReferenceVisitor visitor) 75 | { 76 | visitor.VisitColumnReference(this); 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /SqlPad.Oracle/SemanticModel/OracleDataTypeReference.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using SqlPad.Oracle.DataDictionary; 5 | 6 | namespace SqlPad.Oracle.SemanticModel 7 | { 8 | [DebuggerDisplay("OracleDataTypeReference (Owner={OwnerNode == null ? null : OwnerNode.Token.Value}; Name={ObjectNode.Token.Value}; SchemaObject={SchemaObject})")] 9 | public class OracleDataTypeReference : OracleReference 10 | { 11 | public override string Name => throw new NotSupportedException(); 12 | 13 | public OracleDataType ResolvedDataType { get; set; } 14 | 15 | public StatementGrammarNode PrecisionNode { get; set; } 16 | 17 | public StatementGrammarNode ScaleNode { get; set; } 18 | 19 | public StatementGrammarNode LengthNode { get; set; } 20 | 21 | public ICollection PlSqlTypes { get; } = new List(); 22 | 23 | public override void Accept(IOracleReferenceVisitor visitor) 24 | { 25 | visitor.VisitDataTypeReference(this); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /SqlPad.Oracle/SemanticModel/OracleInsertTarget.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | 4 | namespace SqlPad.Oracle.SemanticModel 5 | { 6 | public class OracleInsertTarget : OracleReferenceContainer 7 | { 8 | public OracleInsertTarget(OracleStatementSemanticModel semanticModel) : base(semanticModel) 9 | { 10 | } 11 | 12 | public StatementGrammarNode RootNode { get; set; } 13 | 14 | public StatementGrammarNode TargetNode { get; set; } 15 | 16 | public StatementGrammarNode ColumnListNode { get; set; } 17 | 18 | public StatementGrammarNode ValueList { get; set; } 19 | 20 | public IReadOnlyList ValueExpressions { get; set; } 21 | 22 | public IReadOnlyDictionary Columns { get; set; } 23 | 24 | public OracleQueryBlock RowSource { get; set; } 25 | 26 | public OracleDataObjectReference DataObjectReference => ObjectReferences.Count == 1 ? ObjectReferences.First() : null; 27 | } 28 | } -------------------------------------------------------------------------------- /SqlPad.Oracle/SemanticModel/OracleJoinDescription.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace SqlPad.Oracle.SemanticModel 4 | { 5 | public class OracleJoinDescription 6 | { 7 | public OracleDataObjectReference MasterObjectReference { get; set; } 8 | 9 | public StatementGrammarNode MasterPartitionClause { get; set; } 10 | 11 | public OracleDataObjectReference SlaveObjectReference { get; set; } 12 | 13 | public StatementGrammarNode SlavePartitionClause { get; set; } 14 | 15 | public ICollection Columns { get; set; } 16 | 17 | public JoinType Type { get; set; } 18 | 19 | public JoinDefinition Definition { get; set; } 20 | } 21 | 22 | public enum JoinType 23 | { 24 | Inner, 25 | Left, 26 | Right, 27 | Full 28 | } 29 | 30 | public enum JoinDefinition 31 | { 32 | Explicit, 33 | Natural 34 | } 35 | } -------------------------------------------------------------------------------- /SqlPad.Oracle/SemanticModel/OracleLiteral.cs: -------------------------------------------------------------------------------- 1 | namespace SqlPad.Oracle.SemanticModel 2 | { 3 | public enum LiteralType 4 | { 5 | Unknown, 6 | Date, 7 | IntervalYearToMonth, 8 | IntervalDayToSecond, 9 | Timestamp, 10 | Number, 11 | SinglePrecision, 12 | DoublePrecision, 13 | Char 14 | } 15 | 16 | public struct OracleLiteral 17 | { 18 | public LiteralType Type; 19 | 20 | public StatementGrammarNode Terminal; 21 | 22 | public bool IsMultibyte 23 | { 24 | get 25 | { 26 | if (Terminal == null || Terminal.Id != OracleGrammarDescription.Terminals.StringLiteral) 27 | { 28 | return false; 29 | } 30 | 31 | return Terminal.Token.Value[0] == 'n' || Terminal.Token.Value[0] == 'N'; 32 | } 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /SqlPad.Oracle/SemanticModel/OracleProgramReference.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using SqlPad.Oracle.DataDictionary; 5 | 6 | namespace SqlPad.Oracle.SemanticModel 7 | { 8 | [DebuggerDisplay("OracleProgramReference (Owner={OwnerNode == null ? null : OwnerNode.Token.Value}; Object={ObjectNode == null ? null : ObjectNode.Token.Value}; Program={ProgramIdentifierNode.Token.Value}; Metadata={Metadata})")] 9 | public class OracleProgramReference : OracleProgramReferenceBase 10 | { 11 | public override string Name => ProgramIdentifierNode.Token.Value; 12 | 13 | public StatementGrammarNode ProgramIdentifierNode { get; set; } 14 | 15 | public StatementGrammarNode AnalyticClauseNode { get; set; } 16 | 17 | public override OracleProgramMetadata Metadata { get; set; } 18 | 19 | protected override IEnumerable GetAdditionalIdentifierTerminals() 20 | { 21 | if (ProgramIdentifierNode != null) 22 | { 23 | yield return ProgramIdentifierNode; 24 | } 25 | } 26 | 27 | public override void Accept(IOracleReferenceVisitor visitor) 28 | { 29 | visitor.VisitProgramReference(this); 30 | } 31 | } 32 | 33 | [DebuggerDisplay("OracleTypeReference (Owner={OwnerNode == null ? null : OwnerNode.Token.Value}; Type={ObjectNode.Token.Value}; Metadata={Metadata})")] 34 | public class OracleTypeReference : OracleProgramReferenceBase 35 | { 36 | public override string Name => ObjectNode.Token.Value; 37 | 38 | public override OracleProgramMetadata Metadata 39 | { 40 | get { return ((OracleTypeBase)SchemaObject.GetTargetSchemaObject()).GetConstructorMetadata(); } 41 | set { throw new NotSupportedException("Metadata cannot be set. It is inferred from type attributes"); } 42 | } 43 | 44 | public override void Accept(IOracleReferenceVisitor visitor) 45 | { 46 | visitor.VisitTypeReference(this); 47 | } 48 | } 49 | 50 | public abstract class OracleProgramReferenceBase : OracleReference 51 | { 52 | public StatementGrammarNode ParameterListNode { get; set; } 53 | 54 | public IReadOnlyList ParameterReferences { get; set; } 55 | 56 | public abstract OracleProgramMetadata Metadata { get; set; } 57 | } 58 | 59 | public class ProgramParameterReference 60 | { 61 | public static readonly ProgramParameterReference[] EmptyArray = new ProgramParameterReference[0]; 62 | 63 | public StatementGrammarNode ParameterNode { get; set; } 64 | 65 | public StatementGrammarNode ValueNode { get; set; } 66 | 67 | public StatementGrammarNode OptionalIdentifierTerminal { get; set; } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /SqlPad.Oracle/SemanticModel/OracleSequenceReference.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Diagnostics; 3 | using SqlPad.Oracle.DataDictionary; 4 | 5 | namespace SqlPad.Oracle.SemanticModel 6 | { 7 | [DebuggerDisplay("OracleSequenceReference (Owner={OwnerNode == null ? null : OwnerNode.Token.Value}; Sequence={ObjectNode.Token.Value})")] 8 | public class OracleSequenceReference : OracleObjectWithColumnsReference 9 | { 10 | private static readonly OracleColumn[] EmptyArray = new OracleColumn[0]; 11 | 12 | public override string Name => ObjectNode.Token.Value; 13 | 14 | public override ReferenceType Type => ReferenceType.SchemaObject; 15 | 16 | public override void Accept(IOracleReferenceVisitor visitor) 17 | { 18 | visitor.VisitSequenceReference(this); 19 | } 20 | 21 | protected override IReadOnlyList BuildColumns() 22 | { 23 | return EmptyArray; 24 | } 25 | 26 | protected override IReadOnlyList BuildPseudocolumns() 27 | { 28 | return ((OracleSequence)SchemaObject).Columns; 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /SqlPad.Oracle/SemanticModel/OracleSpecialTableReference.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Diagnostics; 3 | using System.Linq; 4 | using SqlPad.Oracle.DataDictionary; 5 | 6 | namespace SqlPad.Oracle.SemanticModel 7 | { 8 | [DebuggerDisplay("OracleSpecialTableReference (Alias={Name})")] 9 | public class OracleSpecialTableReference : OracleDataObjectReference 10 | { 11 | public StatementGrammarNode ColumnsClause { get; } 12 | 13 | public OracleSpecialTableReference(OracleReferenceContainer referenceContainer, ReferenceType referenceType, IEnumerable columns, StatementGrammarNode columnsClause) 14 | : base(referenceType) 15 | { 16 | referenceContainer.ObjectReferences.Add(this); 17 | Container = referenceContainer; 18 | ColumnDefinitions = columns.ToArray(); 19 | ColumnsClause = columnsClause; 20 | } 21 | 22 | public IReadOnlyList ColumnDefinitions { get; } 23 | 24 | public override string Name => AliasNode?.Token.Value; 25 | 26 | protected override OracleObjectIdentifier BuildFullyQualifiedObjectName() 27 | { 28 | return OracleObjectIdentifier.Create(null, Name); 29 | } 30 | 31 | protected override IReadOnlyList BuildColumns() 32 | { 33 | return ColumnDefinitions.Select(c => c.ColumnDescription).ToArray(); 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /SqlPad.Oracle/SemanticModel/OracleStatementSemanticModelFactory.cs: -------------------------------------------------------------------------------- 1 | using System.Threading; 2 | using System.Threading.Tasks; 3 | using SqlPad.Oracle.DatabaseConnection; 4 | 5 | namespace SqlPad.Oracle.SemanticModel 6 | { 7 | public static class OracleStatementSemanticModelFactory 8 | { 9 | public static OracleStatementSemanticModel Build(string statementText, OracleStatement statement, OracleDatabaseModelBase databaseModel) 10 | { 11 | return BuildInternal(statementText, statement, databaseModel, CancellationToken.None); 12 | } 13 | 14 | private static OracleStatementSemanticModel BuildInternal(string statementText, OracleStatement statement, OracleDatabaseModelBase databaseModel, CancellationToken cancellationToken) 15 | { 16 | var semanticModel = statement != null && statement.IsPlSql 17 | ? new OraclePlSqlStatementSemanticModel(statementText, statement, databaseModel) 18 | : new OracleStatementSemanticModel(statementText, statement, databaseModel); 19 | return semanticModel.Build(cancellationToken); 20 | } 21 | 22 | public static Task BuildAsync(string statementText, OracleStatement statement, OracleDatabaseModelBase databaseModel, CancellationToken cancellationToken) 23 | { 24 | return Task.Run(() => BuildInternal(statementText, statement, databaseModel, cancellationToken), cancellationToken); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /SqlPad.Oracle/SemanticModel/OracleTableCollectionReference.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Diagnostics; 3 | using SqlPad.Oracle.DataDictionary; 4 | 5 | namespace SqlPad.Oracle.SemanticModel 6 | { 7 | [DebuggerDisplay("OracleTableCollectionReference (OwnerNode={OwnerNode == null ? null : OwnerNode.Token.Value}; ObjectNode={ObjectNode == null ? null : ObjectNode.Token.Value})")] 8 | public class OracleTableCollectionReference : OracleDataObjectReference 9 | { 10 | private OracleReference _rowSourceReference; 11 | 12 | public OracleReference RowSourceReference 13 | { 14 | get { return _rowSourceReference; } 15 | set 16 | { 17 | _rowSourceReference = value; 18 | OwnerNode = _rowSourceReference.OwnerNode; 19 | ObjectNode = _rowSourceReference.ObjectNode; 20 | Owner = _rowSourceReference.Owner; 21 | } 22 | } 23 | 24 | public override string Name => AliasNode?.Token.Value; 25 | 26 | public override IEnumerable IncludeInnerReferences 27 | { 28 | get 29 | { 30 | yield return this; 31 | 32 | var columnSourceReference = _rowSourceReference as OracleColumnReference; 33 | if (columnSourceReference?.ValidObjectReference is OracleDataObjectReference innerObjectReferences) 34 | { 35 | yield return innerObjectReferences; 36 | } 37 | } 38 | } 39 | 40 | public OracleTableCollectionReference(OracleReferenceContainer referenceContainer) : base(ReferenceType.TableCollection) 41 | { 42 | referenceContainer.ObjectReferences.Add(this); 43 | Container = referenceContainer; 44 | Placement = StatementPlacement.TableReference; 45 | } 46 | 47 | protected override OracleObjectIdentifier BuildFullyQualifiedObjectName() 48 | { 49 | return OracleObjectIdentifier.Create(null, Name); 50 | } 51 | 52 | public override void Accept(IOracleReferenceVisitor visitor) 53 | { 54 | visitor.VisitTableCollectionReference(this); 55 | } 56 | 57 | protected override IReadOnlyList BuildColumns() 58 | { 59 | var columnBuilderVisitor = new OracleColumnBuilderVisitor(); 60 | _rowSourceReference?.Accept(columnBuilderVisitor); 61 | 62 | return columnBuilderVisitor.Columns; 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /SqlPad.Oracle/SemanticModel/QueryBlockType.cs: -------------------------------------------------------------------------------- 1 | namespace SqlPad.Oracle.SemanticModel 2 | { 3 | public enum QueryBlockType 4 | { 5 | Normal, 6 | CursorParameter, 7 | CommonTableExpression, 8 | ScalarSubquery 9 | } 10 | } -------------------------------------------------------------------------------- /SqlPad.Oracle/SemanticModel/ReferenceType.cs: -------------------------------------------------------------------------------- 1 | namespace SqlPad.Oracle.SemanticModel 2 | { 3 | public enum ReferenceType 4 | { 5 | SchemaObject, 6 | CommonTableExpression, 7 | InlineView, 8 | TableCollection, 9 | XmlTable, 10 | JsonTable, 11 | SqlModel, 12 | PivotTable, 13 | HierarchicalClause 14 | } 15 | } -------------------------------------------------------------------------------- /SqlPad.Oracle/SemanticModel/StatementPlacement.cs: -------------------------------------------------------------------------------- 1 | namespace SqlPad.Oracle.SemanticModel 2 | { 3 | public enum StatementPlacement 4 | { 5 | None, 6 | ValuesClause, 7 | SelectList, 8 | TableReference, 9 | PivotClause, 10 | Where, 11 | GroupBy, 12 | Having, 13 | Join, 14 | OrderBy, 15 | Model, 16 | ConnectBy, 17 | RecursiveSearchOrCycleClause 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /SqlPad.Oracle/SessionIdentifier.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics; 2 | 3 | namespace SqlPad.Oracle 4 | { 5 | [DebuggerDisplay("SessionIdentifier (Instance={Instance}; SessionId={SessionId})")] 6 | public struct SessionIdentifier 7 | { 8 | public int Instance { get; } 9 | 10 | public int SessionId { get; } 11 | 12 | public SessionIdentifier(int instance, int sessionId) 13 | { 14 | Instance = instance; 15 | SessionId = sessionId; 16 | } 17 | 18 | public bool Equals(SessionIdentifier other) 19 | { 20 | return Instance == other.Instance && SessionId == other.SessionId; 21 | } 22 | 23 | public override bool Equals(object obj) 24 | { 25 | if (ReferenceEquals(null, obj)) 26 | { 27 | return false; 28 | } 29 | 30 | return obj is SessionIdentifier && Equals((SessionIdentifier)obj); 31 | } 32 | 33 | public override int GetHashCode() 34 | { 35 | unchecked 36 | { 37 | return (Instance * 397) ^ SessionId; 38 | } 39 | } 40 | 41 | public static bool operator ==(SessionIdentifier left, SessionIdentifier right) 42 | { 43 | return left.Equals(right); 44 | } 45 | 46 | public static bool operator !=(SessionIdentifier left, SessionIdentifier right) 47 | { 48 | return !left.Equals(right); 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /SqlPad.Oracle/Snippets/SnippetGatherTableStats.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | {0}, tabname => '{1}'); END;]]> 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /SqlPad.Oracle/Snippets/SnippetInsert.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | VALUES ()]]> 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /SqlPad.Oracle/Snippets/SnippetObjects.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /SqlPad.Oracle/Snippets/SnippetSelect.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /SqlPad.Oracle/Snippets/SnippetSelectCount.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /SqlPad.Oracle/Snippets/SnippetTables.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /SqlPad.Oracle/Themes/Common.xaml: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 24 | 25 | -------------------------------------------------------------------------------- /SqlPad.Oracle/Themes/ToolTipDataGrid.xaml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 15 | 16 | 21 | 22 | 25 | 26 | 31 | 32 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /SqlPad.Oracle/ToolTips/ConstraintList.xaml: -------------------------------------------------------------------------------- 1 |  10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /SqlPad.Oracle/ToolTips/ConstraintList.xaml.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.ComponentModel; 3 | using System.Windows; 4 | 5 | namespace SqlPad.Oracle.ToolTips 6 | { 7 | public partial class ConstraintList 8 | { 9 | public ConstraintList() 10 | { 11 | InitializeComponent(); 12 | } 13 | 14 | public static readonly DependencyProperty ConstraintsProperty = DependencyProperty.Register("Constraints", typeof(IEnumerable), typeof(ConstraintList), new FrameworkPropertyMetadata(PropertyChangedCallbackHandler)); 15 | 16 | [Bindable(true)] 17 | public IEnumerable Constraints 18 | { 19 | get { return (IEnumerable)GetValue(ConstraintsProperty); } 20 | set { SetValue(ConstraintsProperty, value); } 21 | } 22 | 23 | private static void PropertyChangedCallbackHandler(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs args) 24 | { 25 | var constraintList = (ConstraintList)dependencyObject; 26 | constraintList.DataGrid.ItemsSource = (IEnumerable)args.NewValue; 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /SqlPad.Oracle/ToolTips/IndexList.xaml.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.ComponentModel; 3 | using System.Windows; 4 | 5 | namespace SqlPad.Oracle.ToolTips 6 | { 7 | public partial class IndexList 8 | { 9 | public IndexList() 10 | { 11 | InitializeComponent(); 12 | } 13 | 14 | public static readonly DependencyProperty IndexesProperty = DependencyProperty.Register("Indexes", typeof(IEnumerable), typeof(IndexList), new FrameworkPropertyMetadata(PropertyChangedCallbackHandler)); 15 | 16 | [Bindable(true)] 17 | public IEnumerable Indexes 18 | { 19 | get { return (IEnumerable)GetValue(IndexesProperty); } 20 | set { SetValue(IndexesProperty, value); } 21 | } 22 | 23 | private static void PropertyChangedCallbackHandler(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs args) 24 | { 25 | var indexList = (IndexList)dependencyObject; 26 | indexList.DataGrid.ItemsSource = (IEnumerable)args.NewValue; 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /SqlPad.Oracle/ToolTips/PartitionList.xaml.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using System.Windows; 3 | 4 | namespace SqlPad.Oracle.ToolTips 5 | { 6 | public partial class PartitionList 7 | { 8 | public PartitionList() 9 | { 10 | InitializeComponent(); 11 | } 12 | 13 | public static readonly DependencyProperty TableDetailsProperty = DependencyProperty.Register("TableDetails", typeof(TableDetailsModel), typeof(PartitionList), new FrameworkPropertyMetadata(TableDetailsPropertyChangedCallbackHandler)); 14 | 15 | [Bindable(true)] 16 | public TableDetailsModel TableDetails 17 | { 18 | get { return (TableDetailsModel)GetValue(TableDetailsProperty); } 19 | set { SetValue(TableDetailsProperty, value); } 20 | } 21 | 22 | private static void TableDetailsPropertyChangedCallbackHandler(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs args) 23 | { 24 | var partitionList = (PartitionList)dependencyObject; 25 | partitionList.DataContext = args.NewValue; 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /SqlPad.Oracle/ToolTips/ToolTipAsterisk.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Windows; 5 | using System.Windows.Controls; 6 | 7 | namespace SqlPad.Oracle.ToolTips 8 | { 9 | public partial class ToolTipAsterisk : IToolTip 10 | { 11 | public event EventHandler Pin; 12 | 13 | public Control Control => this; 14 | 15 | public FrameworkElement InnerContent => this; 16 | 17 | public ToolTipAsterisk() 18 | { 19 | InitializeComponent(); 20 | } 21 | 22 | public IEnumerable Columns 23 | { 24 | get 25 | { 26 | var sourceModels = (IEnumerable)ItemsControl.ItemsSource; 27 | return sourceModels.Where(m => !m.IsSeparator); 28 | } 29 | set 30 | { 31 | var columnViewModels = new List(); 32 | 33 | OracleColumnModel previousModel = null; 34 | foreach (var model in value) 35 | { 36 | if (previousModel != null && previousModel.RowSourceName != model.RowSourceName) 37 | { 38 | columnViewModels.Add(OracleColumnViewModel.CreateSeparator()); 39 | } 40 | 41 | columnViewModels.Add(OracleColumnViewModel.FromDataModel(model)); 42 | 43 | previousModel = model; 44 | } 45 | 46 | ItemsControl.ItemsSource = columnViewModels; 47 | } 48 | } 49 | } 50 | 51 | public class OracleColumnModel 52 | { 53 | public int ColumnIndex { get; set; } 54 | 55 | public string Name { get; set; } 56 | 57 | public string FullTypeName { get; set; } 58 | 59 | public bool? Nullable { get; set; } 60 | 61 | public string RowSourceName { get; set; } 62 | } 63 | 64 | internal class OracleColumnViewModel : OracleColumnModel 65 | { 66 | public bool IsSeparator { get; private set; } 67 | 68 | public static OracleColumnViewModel CreateSeparator() 69 | { 70 | return new OracleColumnViewModel { IsSeparator = true }; 71 | } 72 | 73 | public static OracleColumnViewModel FromDataModel(OracleColumnModel model) 74 | { 75 | return 76 | new OracleColumnViewModel 77 | { 78 | ColumnIndex = model.ColumnIndex, 79 | FullTypeName = model.FullTypeName, 80 | Nullable = model.Nullable, 81 | Name = model.Name.ToSimpleIdentifier(), 82 | RowSourceName = model.RowSourceName 83 | }; 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /SqlPad.Oracle/ToolTips/ToolTipDatabaseLink.xaml: -------------------------------------------------------------------------------- 1 |  12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /SqlPad.Oracle/ToolTips/ToolTipDatabaseLink.xaml.cs: -------------------------------------------------------------------------------- 1 | using System.Threading; 2 | using System.Threading.Tasks; 3 | using SqlPad.Oracle.DataDictionary; 4 | 5 | namespace SqlPad.Oracle.ToolTips 6 | { 7 | public partial class ToolTipDatabaseLink 8 | { 9 | public ToolTipDatabaseLink(OracleDatabaseLink databaseLink) 10 | { 11 | InitializeComponent(); 12 | 13 | DataContext = databaseLink; 14 | } 15 | 16 | protected override Task ExtractDdlAsync(CancellationToken cancellationToken) 17 | { 18 | return ScriptExtractor.ExtractSchemaObjectScriptAsync((OracleDatabaseLink)DataContext, cancellationToken); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /SqlPad.Oracle/ToolTips/ToolTipMaterializedView.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using System.Threading; 4 | using System.Threading.Tasks; 5 | using SqlPad.Oracle.DataDictionary; 6 | 7 | namespace SqlPad.Oracle.ToolTips 8 | { 9 | public partial class ToolTipMaterializedView 10 | { 11 | public ToolTipMaterializedView() 12 | { 13 | InitializeComponent(); 14 | } 15 | 16 | protected override Task ExtractDdlAsync(CancellationToken cancellationToken) 17 | { 18 | return ScriptExtractor.ExtractSchemaObjectScriptAsync(((MaterializedViewDetailsModel)DataContext).MaterializedView, cancellationToken); 19 | } 20 | } 21 | 22 | public class MaterializedViewDetailsModel : TableDetailsModel 23 | { 24 | public OracleMaterializedView MaterializedView 25 | { 26 | get { return (OracleMaterializedView)Table; } 27 | set { Table = value; } 28 | } 29 | 30 | public string MaterializedViewTitle { get; set; } 31 | } 32 | 33 | internal class MaterializedViewPropertyConverter : ValueConverterBase 34 | { 35 | public override object Convert(object value, Type targetType, object parameter, CultureInfo culture) 36 | { 37 | if (value is MaterializedViewRefreshMode) 38 | { 39 | return (MaterializedViewRefreshMode)value == MaterializedViewRefreshMode.OnDemand ? "On demand" : "On commit"; 40 | } 41 | 42 | var stringValue = (string)value; 43 | return CultureInfo.InvariantCulture.TextInfo.ToTitleCase(stringValue.ToLowerInvariant()); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /SqlPad.Oracle/ToolTips/ToolTipObject.xaml: -------------------------------------------------------------------------------- 1 |  9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /SqlPad.Oracle/ToolTips/ToolTipObject.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows; 3 | using System.Windows.Controls; 4 | 5 | namespace SqlPad.Oracle.ToolTips 6 | { 7 | public partial class ToolTipObject : IToolTip 8 | { 9 | public event EventHandler Pin; 10 | 11 | public ToolTipObject() 12 | { 13 | InitializeComponent(); 14 | } 15 | 16 | public Control Control => this; 17 | 18 | public FrameworkElement InnerContent => this; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /SqlPad.Oracle/ToolTips/ToolTipPartition.xaml.cs: -------------------------------------------------------------------------------- 1 | namespace SqlPad.Oracle.ToolTips 2 | { 3 | public partial class ToolTipPartition 4 | { 5 | public ToolTipPartition(PartitionDetailsModelBase dataModel) 6 | { 7 | InitializeComponent(); 8 | 9 | DataContext = dataModel; 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /SqlPad.Oracle/ToolTips/ToolTipSequence.xaml.cs: -------------------------------------------------------------------------------- 1 | using System.Threading; 2 | using System.Threading.Tasks; 3 | using SqlPad.Oracle.DataDictionary; 4 | 5 | namespace SqlPad.Oracle.ToolTips 6 | { 7 | public partial class ToolTipSequence 8 | { 9 | public ToolTipSequence(string title, OracleSequence sequence) 10 | { 11 | InitializeComponent(); 12 | 13 | LabelTitle.Text = title; 14 | 15 | DataContext = sequence; 16 | } 17 | 18 | protected override Task ExtractDdlAsync(CancellationToken cancellationToken) 19 | { 20 | return ScriptExtractor.ExtractSchemaObjectScriptAsync((OracleSequence)DataContext, cancellationToken); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /SqlPad.Oracle/ToolTips/ToolTipView.xaml: -------------------------------------------------------------------------------- 1 |  10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /SqlPad.Oracle/ToolTips/ToolTipView.xaml.cs: -------------------------------------------------------------------------------- 1 | using System.Threading; 2 | using System.Threading.Tasks; 3 | using SqlPad.Oracle.DataDictionary; 4 | 5 | namespace SqlPad.Oracle.ToolTips 6 | { 7 | public partial class ToolTipView 8 | { 9 | public ToolTipView() 10 | { 11 | InitializeComponent(); 12 | } 13 | 14 | protected override Task ExtractDdlAsync(CancellationToken cancellationToken) 15 | { 16 | return ScriptExtractor.ExtractSchemaObjectScriptAsync(((ObjectDetailsModel)DataContext).Object, cancellationToken); 17 | } 18 | } 19 | 20 | public class ObjectDetailsModel : ModelWithConstraints, IModelWithComment 21 | { 22 | private string _comment; 23 | 24 | public OracleObject Object { get; set; } 25 | 26 | public string Title { get; set; } 27 | 28 | public string Comment 29 | { 30 | get { return _comment; } 31 | set { UpdateValueAndRaisePropertyChanged(ref _comment, value); } 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /SqlPad.Oracle/ToolTips/ToolTipViewColumn.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows; 3 | using System.Windows.Controls; 4 | 5 | namespace SqlPad.Oracle.ToolTips 6 | { 7 | public partial class ToolTipViewColumn : IToolTip 8 | { 9 | public event EventHandler Pin; 10 | 11 | public ToolTipViewColumn(ColumnDetailsModel dataModel) 12 | { 13 | InitializeComponent(); 14 | 15 | DataContext = dataModel; 16 | } 17 | 18 | public Control Control => this; 19 | 20 | public FrameworkElement InnerContent => this; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /SqlPad.Test/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /SqlPad.Test/ConsoleTraceListenerTestFixture.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics; 2 | using NUnit.Framework; 3 | 4 | namespace SqlPad.Test 5 | { 6 | [SetUpFixture] 7 | public class ConsoleTraceListenerTestFixture 8 | { 9 | [OneTimeSetUp] 10 | public void SetUp() 11 | { 12 | Trace.Listeners.Add(new ConsoleTraceListener()); 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /SqlPad.Test/EditorNavigationServiceTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using NUnit.Framework; 3 | using Shouldly; 4 | 5 | namespace SqlPad.Test 6 | { 7 | [TestFixture] 8 | public class EditorNavigationServiceTest 9 | { 10 | [SetUp] 11 | public void SetUp() 12 | { 13 | EditorNavigationService.Initialize(); 14 | } 15 | 16 | [Test, STAThread] 17 | public void TestInitializedEditorNavigationService() 18 | { 19 | EditorNavigationService.IsEnabled.ShouldBeTrue(); 20 | EditorNavigationService.GetNextEdit().ShouldBeNull(); 21 | Should.Throw(() => EditorNavigationService.GetPreviousEdit()); 22 | } 23 | 24 | [Test, STAThread] 25 | public void TestRegisterDocumentCursorPosition() 26 | { 27 | var workingDocument = new WorkDocument(); 28 | const int originalPosition = 10; 29 | const int position2 = 99; 30 | const int lastPosition = 43; 31 | EditorNavigationService.RegisterDocumentCursorPosition(workingDocument, originalPosition); 32 | EditorNavigationService.RegisterDocumentCursorPosition(workingDocument, position2); 33 | EditorNavigationService.RegisterDocumentCursorPosition(workingDocument, lastPosition); 34 | EditorNavigationService.GetNextEdit().ShouldBeNull(); 35 | var previousEdit = EditorNavigationService.GetPreviousEdit(); 36 | previousEdit.ShouldNotBeNull(); 37 | previousEdit.Document.ShouldBe(workingDocument); 38 | previousEdit.CursorPosition.ShouldBe(position2); 39 | previousEdit = EditorNavigationService.GetPreviousEdit(); 40 | previousEdit.ShouldNotBeNull(); 41 | previousEdit.Document.ShouldBe(workingDocument); 42 | previousEdit.CursorPosition.ShouldBe(originalPosition); 43 | previousEdit = EditorNavigationService.GetPreviousEdit(); 44 | previousEdit.ShouldNotBeNull(); 45 | previousEdit.Document.ShouldBe(workingDocument); 46 | previousEdit.CursorPosition.ShouldBe(originalPosition); 47 | 48 | var nextEdit = EditorNavigationService.GetNextEdit(); 49 | nextEdit.ShouldNotBeNull(); 50 | nextEdit.Document.ShouldBe(workingDocument); 51 | nextEdit.CursorPosition.ShouldBe(position2); 52 | nextEdit = EditorNavigationService.GetNextEdit(); 53 | nextEdit.ShouldNotBeNull(); 54 | nextEdit.Document.ShouldBe(workingDocument); 55 | nextEdit.CursorPosition.ShouldBe(lastPosition); 56 | EditorNavigationService.GetNextEdit().ShouldBeNull(); 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /SqlPad.Test/EditorTest.cs: -------------------------------------------------------------------------------- 1 | using System.Threading; 2 | using NUnit.Framework; 3 | using Shouldly; 4 | using SqlPad.Commands; 5 | 6 | namespace SqlPad.Test 7 | { 8 | [TestFixture] 9 | public class EditorTest 10 | { 11 | private SqlTextEditor _editor; 12 | 13 | [SetUp] 14 | public void SetUp() 15 | { 16 | _editor = new SqlTextEditor(); 17 | } 18 | 19 | [Test, Apartment(ApartmentState.STA)] 20 | public void SetLineDuplicationAtLineBeginning() 21 | { 22 | _editor.Text = "SELECT * FROM SELECTION;"; 23 | GenericCommandHandler.DuplicateText(_editor.TextArea, null); 24 | 25 | _editor.Text.ShouldBe("SELECT * FROM SELECTION;\nSELECT * FROM SELECTION;"); 26 | _editor.CaretOffset.ShouldBe(25); 27 | } 28 | 29 | [Test, Apartment(ApartmentState.STA)] 30 | public void SetLineDuplicationAtLineEnd() 31 | { 32 | _editor.Text = "SELECT * FROM SELECTION;"; 33 | _editor.CaretOffset = 24; 34 | GenericCommandHandler.DuplicateText(_editor.TextArea, null); 35 | 36 | _editor.Text.ShouldBe("SELECT * FROM SELECTION;\nSELECT * FROM SELECTION;"); 37 | _editor.CaretOffset.ShouldBe(49); 38 | } 39 | 40 | [Test, Apartment(ApartmentState.STA)] 41 | public void SetSelectionDuplicate() 42 | { 43 | _editor.Text = "SELECT * FROM SELECTION;"; 44 | _editor.CaretOffset = 13; 45 | _editor.SelectionLength = 10; 46 | _editor.SelectedText.ShouldBe(" SELECTION"); 47 | GenericCommandHandler.DuplicateText(_editor.TextArea, null); 48 | 49 | _editor.Text.ShouldBe("SELECT * FROM SELECTION SELECTION;"); 50 | _editor.CaretOffset.ShouldBe(33); 51 | } 52 | 53 | [Test, Apartment(ApartmentState.STA)] 54 | public void TestBlockComments() 55 | { 56 | _editor.Text = "SELECT * FROM SELECTION;\nSELECT * FROM RESPONDENTBUCKET"; 57 | _editor.CaretOffset = 13; 58 | _editor.SelectionLength = 35; 59 | 60 | GenericCommandHandler.HandleBlockComments(_editor.TextArea, null); 61 | 62 | _editor.Text.ShouldBe("SELECT * FROM/* SELECTION;\nSELECT * FROM RESPONDEN*/TBUCKET"); 63 | _editor.CaretOffset.ShouldBe(50); 64 | _editor.SelectionLength.ShouldBe(0); 65 | } 66 | 67 | [Test, Apartment(ApartmentState.STA)] 68 | public void TestLineComments() 69 | { 70 | _editor.Text = "SELECT * FROM SELECTION;\nSELECT * FROM RESPONDENTBUCKET"; 71 | _editor.CaretOffset = 13; 72 | _editor.SelectionLength = 35; 73 | 74 | GenericCommandHandler.HandleLineComments(_editor.TextArea, null); 75 | 76 | _editor.Text.ShouldBe("--SELECT * FROM SELECTION;\n--SELECT * FROM RESPONDENTBUCKET"); 77 | _editor.CaretOffset.ShouldBe(52); 78 | _editor.SelectionLength.ShouldBe(0); 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /SqlPad.Test/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // General Information about an assembly is controlled through the following 5 | // set of attributes. Change these attribute values to modify the information 6 | // associated with an assembly. 7 | [assembly: AssemblyTitle("SqlPad.Test")] 8 | [assembly: AssemblyDescription("")] 9 | [assembly: AssemblyConfiguration("")] 10 | [assembly: AssemblyCompany("")] 11 | [assembly: AssemblyProduct("SqlPad.Test")] 12 | [assembly: AssemblyCopyright("Copyright © 2016")] 13 | [assembly: AssemblyTrademark("")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | // Setting ComVisible to false makes the types in this assembly not visible 17 | // to COM components. If you need to access a type in this assembly from 18 | // COM, set the ComVisible attribute to true on that type. 19 | [assembly: ComVisible(false)] 20 | 21 | // The following GUID is for the ID of the typelib if this project is exposed to COM 22 | [assembly: Guid("3da8b989-03bb-4493-90af-995d38d9ba1e")] 23 | 24 | // Version information for an assembly consists of the following four values: 25 | // 26 | // Major Version 27 | // Minor Version 28 | // Build Number 29 | // Revision 30 | // 31 | // You can specify all the values or you can default the Build and Revision Numbers 32 | // by using the '*' as shown below: 33 | // [assembly: AssemblyVersion("1.0.*")] 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] 36 | -------------------------------------------------------------------------------- /SqlPad.Test/TemporaryDirectoryTestFixture.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics; 2 | using System.IO; 3 | using NUnit.Framework; 4 | 5 | namespace SqlPad.Test 6 | { 7 | public abstract class TemporaryDirectoryTestFixture 8 | { 9 | protected string TempDirectoryName; 10 | 11 | [SetUp] 12 | public void SetUp() 13 | { 14 | TempDirectoryName = TestFixture.SetupTestDirectory(); 15 | ConfigurationProvider.SetUserDataFolder(TempDirectoryName); 16 | } 17 | 18 | [TearDown] 19 | public void TearDown() 20 | { 21 | WorkDocumentCollection.ReleaseConfigurationLock(); 22 | Directory.Delete(TempDirectoryName, true); 23 | Trace.WriteLine($"Test temp directory '{TempDirectoryName}' has been deleted. "); 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /SqlPad.Test/TestFixture.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using System.IO; 4 | 5 | namespace SqlPad.Test 6 | { 7 | public static class TestFixture 8 | { 9 | public static string SetupTestDirectory() 10 | { 11 | var tempDirectoryName = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString("N")); 12 | Directory.CreateDirectory(tempDirectoryName); 13 | Trace.WriteLine($"Test temp directory '{tempDirectoryName}' has been created. "); 14 | return tempDirectoryName; 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /SqlPad/Archive.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Husqvik/SQLPad/c858b567aa01be4d5920cd9f9fc05c65c939a584/SqlPad/Archive.ico -------------------------------------------------------------------------------- /SqlPad/AssemblyBuildInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | 4 | namespace SqlPad 5 | { 6 | [AttributeUsage(AttributeTargets.Assembly)] 7 | public class AssemblyBuildInfo : Attribute 8 | { 9 | public const string TimestampMask = "yyyy-MM-dd HH:mm:ss"; 10 | 11 | public AssemblyBuildInfo(string lastGitCommitHash, string timestampString) 12 | { 13 | VersionTimestampString = timestampString; 14 | VersionTimestamp = DateTime.ParseExact(timestampString, TimestampMask, CultureInfo.InvariantCulture); 15 | LastGitCommitHash = lastGitCommitHash; 16 | } 17 | 18 | public DateTime VersionTimestamp { get; private set; } 19 | 20 | public string VersionTimestampString { get; private set; } 21 | 22 | public string LastGitCommitHash { get; private set; } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /SqlPad/BindVariableModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace SqlPad 5 | { 6 | public class BindVariableModel : ModelBase 7 | { 8 | public BindVariableModel(BindVariableConfiguration bindVariable) 9 | { 10 | BindVariable = bindVariable; 11 | } 12 | 13 | public BindVariableConfiguration BindVariable { get; } 14 | 15 | public bool IsFilePath 16 | { 17 | get { return BindVariable.IsFilePath; } 18 | set { BindVariable.IsFilePath = value; } 19 | } 20 | 21 | public string Name => BindVariable.Name; 22 | 23 | public ICollection DataTypes => BindVariable.DataTypes.Values; 24 | 25 | public object Value 26 | { 27 | get { return BindVariable.Value; } 28 | set 29 | { 30 | if (BindVariable.Value == value) 31 | { 32 | return; 33 | } 34 | 35 | BindVariable.Value = value; 36 | RaisePropertyChanged(nameof(Value)); 37 | } 38 | } 39 | 40 | public Type InputType => BindVariable.DataTypes[BindVariable.DataType].InputType; 41 | 42 | public BindVariableType DataType 43 | { 44 | get { return BindVariable.DataTypes[BindVariable.DataType]; } 45 | set 46 | { 47 | if (BindVariable.DataType == value.Name) 48 | { 49 | return; 50 | } 51 | 52 | var previousInputType = BindVariable.DataTypes[value.Name].InputType; 53 | 54 | BindVariable.DataType = value.Name; 55 | 56 | if (previousInputType != InputType) 57 | { 58 | Value = null; 59 | RaisePropertyChanged(nameof(InputType)); 60 | } 61 | 62 | RaisePropertyChanged(nameof(DataType)); 63 | } 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /SqlPad/Chart.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Husqvik/SQLPad/c858b567aa01be4d5920cd9f9fc05c65c939a584/SqlPad/Chart.ico -------------------------------------------------------------------------------- /SqlPad/ClipboardManager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | using System.Windows; 4 | using System.Windows.Interop; 5 | 6 | namespace SqlPad 7 | { 8 | public class ClipboardManager 9 | { 10 | private static readonly ClipboardManager Instance = new ClipboardManager(); 11 | private static readonly IntPtr WndProcSuccess = IntPtr.Zero; 12 | 13 | public static event EventHandler ClipboardChanged; 14 | 15 | private ClipboardManager() 16 | { 17 | } 18 | 19 | public static void RegisterWindow(Window window) 20 | { 21 | var source = PresentationSource.FromVisual(window) as HwndSource; 22 | if (source == null) 23 | { 24 | throw new ArgumentException("Window must be initialized first. ", nameof(window)); 25 | } 26 | 27 | source.AddHook(Instance.WndProc); 28 | 29 | var windowHandle = new WindowInteropHelper(window).Handle; 30 | 31 | NativeMethods.AddClipboardFormatListener(windowHandle); 32 | } 33 | 34 | public static bool TryGetClipboardText(out string text) 35 | { 36 | text = null; 37 | 38 | try 39 | { 40 | text = Clipboard.GetText(); 41 | return !String.IsNullOrEmpty(text); 42 | } 43 | catch (COMException) { } 44 | catch (OutOfMemoryException) { } 45 | 46 | return false; 47 | } 48 | 49 | private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) 50 | { 51 | if (msg == NativeMethods.ClipboardUpdate) 52 | { 53 | ClipboardChanged?.Invoke(this, EventArgs.Empty); 54 | handled = true; 55 | } 56 | 57 | return WndProcSuccess; 58 | } 59 | 60 | private static class NativeMethods 61 | { 62 | public const int ClipboardUpdate = 0x031D; 63 | 64 | [DllImport("user32.dll", SetLastError = true)] 65 | [return: MarshalAs(UnmanagedType.Bool)] 66 | public static extern bool AddClipboardFormatListener(IntPtr hwnd); 67 | } 68 | } 69 | } -------------------------------------------------------------------------------- /SqlPad/ColumnHeader.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Windows.Data; 4 | 5 | namespace SqlPad 6 | { 7 | public class ColumnHeader 8 | { 9 | public int ColumnIndex { get; set; } 10 | 11 | public string Name { get; set; } 12 | 13 | public string DatabaseDataType { get; set; } 14 | 15 | public Type DataType { get; set; } 16 | 17 | public IValueConverter CustomConverter { get; set; } 18 | 19 | public IReadOnlyCollection ParentReferenceDataSources { get; set; } 20 | 21 | public bool IsNumeric => DataType.In(typeof(Decimal), typeof(Int16), typeof(Int32), typeof(Int64), typeof(Byte), typeof(Single), typeof(Double)); 22 | 23 | public override string ToString() 24 | { 25 | return Name; 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /SqlPad/CommandSettingsModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.Windows.Controls; 5 | 6 | namespace SqlPad 7 | { 8 | public class CommandSettingsModel : ModelBase 9 | { 10 | private string _value = String.Empty; 11 | 12 | public Func UseDefaultSettings { get; set; } 13 | 14 | public string Title { get; set; } = String.Empty; 15 | 16 | public string Heading { get; set; } = String.Empty; 17 | 18 | public string Description { get; set; } = String.Empty; 19 | 20 | public bool IsTextInputVisible { get; set; } = true; 21 | 22 | public string Value 23 | { 24 | get { return _value; } 25 | set { UpdateValueAndRaisePropertyChanged(ref _value, value); } 26 | } 27 | 28 | public IDictionary BooleanOptions { get; } = new Dictionary(); 29 | 30 | public ValidationRule ValidationRule { get; set; } 31 | 32 | public void AddBooleanOption(BooleanOption option) 33 | { 34 | BooleanOptions.Add(option.OptionIdentifier, option); 35 | } 36 | } 37 | 38 | [DebuggerDisplay("BooleanOption(OptionIdentifier={OptionIdentifier}; Value={Value})")] 39 | public class BooleanOption : ModelBase 40 | { 41 | private bool _value; 42 | 43 | public BooleanOption() 44 | { 45 | IsEnabled = true; 46 | } 47 | 48 | public bool Value 49 | { 50 | get { return _value; } 51 | set { UpdateValueAndRaisePropertyChanged(ref _value, value); } 52 | } 53 | 54 | public string OptionIdentifier { get; set; } 55 | 56 | public object DescriptionContent { get; set; } 57 | 58 | public object Tag { get; set; } 59 | 60 | public bool IsEnabled { get; set; } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /SqlPad/Commands/DiagnosticCommands.cs: -------------------------------------------------------------------------------- 1 | using System.Windows.Input; 2 | using ICSharpCode.AvalonEdit; 3 | 4 | namespace SqlPad.Commands 5 | { 6 | internal static class DiagnosticCommands 7 | { 8 | public static RoutedCommand ShowTokenCommand = new RoutedCommand("ShowTokens", typeof(TextEditor), new InputGestureCollection { new KeyGesture(Key.T, ModifierKeys.Control | ModifierKeys.Alt | ModifierKeys.Shift) }); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /SqlPad/Commands/ICommandFactory.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace SqlPad.Commands 4 | { 5 | public interface ICommandFactory 6 | { 7 | ICollection CommandHandlers { get; } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /SqlPad/Commands/ICommandSettings.cs: -------------------------------------------------------------------------------- 1 | namespace SqlPad.Commands 2 | { 3 | public interface ICommandSettingsProvider 4 | { 5 | bool GetSettings(); 6 | 7 | CommandSettingsModel Settings { get; } 8 | } 9 | 10 | public interface ICommandSettingsProviderFactory 11 | { 12 | ICommandSettingsProvider CreateCommandSettingsProvider(CommandSettingsModel settings); 13 | } 14 | } -------------------------------------------------------------------------------- /SqlPad/CompilationErrorArgs.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace SqlPad 4 | { 5 | public class CompilationErrorArgs : EventArgs 6 | { 7 | public CompilationError CompilationError { get; private set; } 8 | 9 | public CompilationErrorArgs(CompilationError compilationError) 10 | { 11 | CompilationError = compilationError ?? throw new ArgumentNullException(nameof(compilationError)); 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /SqlPad/ComplexTypeViewer.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.Windows; 4 | using System.Windows.Controls; 5 | 6 | namespace SqlPad 7 | { 8 | public partial class ComplexTypeViewer 9 | { 10 | public static readonly DependencyProperty ComplexTypeProperty = DependencyProperty.Register(nameof(ComplexType), typeof(IComplexType), typeof(ComplexTypeViewer), new FrameworkPropertyMetadata()); 11 | 12 | internal EventHandler ResultGridBeginningEditCancelTextInputHandler => App.DataGridBeginningEditCancelTextInputHandlerImplementation; 13 | 14 | public ComplexTypeViewer() 15 | { 16 | InitializeComponent(); 17 | } 18 | 19 | [Bindable(true)] 20 | public IComplexType ComplexType 21 | { 22 | get { return (IComplexType)GetValue(ComplexTypeProperty); } 23 | set { SetValue(ComplexTypeProperty, value); } 24 | } 25 | 26 | private void ComplexTypeViewerGridSortingHandler(object sender, DataGridSortingEventArgs e) 27 | { 28 | if (!Equals(e.Column, AttributeNameColumn)) 29 | { 30 | e.Handled = true; 31 | } 32 | } 33 | } 34 | 35 | /*internal class CustomTypeDataTemplateSelector : DataTemplateSelector 36 | { 37 | public bool IsEditing { get; set; } 38 | 39 | public override DataTemplate SelectTemplate(object item, DependencyObject container) 40 | { 41 | var collectionValue = item as ICollectionValue; 42 | var complexType = item as IComplexType; 43 | 44 | var complexTypeViewer = WpfExtensions.FindParentVisual(container); 45 | var templateName = String.Format("PrimitiveValueType{0}Template", IsEditing ? "Editing" : null); 46 | 47 | return (DataTemplate)complexTypeViewer.Resources[templateName]; 48 | } 49 | }*/ 50 | } 51 | -------------------------------------------------------------------------------- /SqlPad/Configuration.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /SqlPad/Configuration.xsd: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /SqlPad/DataExport/DataExportHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Windows.Controls; 6 | 7 | namespace SqlPad.DataExport 8 | { 9 | internal static class DataExportHelper 10 | { 11 | public static IReadOnlyList GetOrderedExportableColumns(DataGrid dataGrid) 12 | { 13 | return 14 | dataGrid.Columns 15 | .OrderBy(c => c.DisplayIndex) 16 | .Select(c => c.Header as ColumnHeader) 17 | .Where(h => h != null) 18 | .ToArray(); 19 | } 20 | 21 | public static TextWriter InitializeWriter(string fileName, Stream stream) 22 | { 23 | return String.IsNullOrEmpty(fileName) ? new StreamWriter(stream) : File.CreateText(fileName); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /SqlPad/DataExport/IDataExporter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Threading; 4 | using System.Threading.Tasks; 5 | 6 | namespace SqlPad.DataExport 7 | { 8 | public interface IDataExporter 9 | { 10 | string Name { get; } 11 | 12 | string FileNameFilter { get; } 13 | 14 | string FileExtension { get; } 15 | 16 | bool HasAppendSupport { get; } 17 | 18 | Task StartExportAsync(ExportOptions options, IReadOnlyList columns, IDataExportConverter dataExportConverter, CancellationToken cancellationToken); 19 | } 20 | 21 | public interface IDataExportContext : IDisposable 22 | { 23 | long CurrentRowIndex { get; } 24 | 25 | Task AppendRowsAsync(IEnumerable rows); 26 | 27 | Task FinalizeAsync(); 28 | 29 | void SetProgress(long totalRowCount, IProgress progress); 30 | } 31 | 32 | public class ExportOptions 33 | { 34 | public static readonly ExportOptions ToClipboard = new ExportOptions(null, null); 35 | 36 | public string FileName { get; } 37 | 38 | public string ExportName { get; } 39 | 40 | public bool IntoClipboard => this == ToClipboard; 41 | 42 | private ExportOptions(string fileName, string exportName) 43 | { 44 | FileName = fileName; 45 | ExportName = exportName; 46 | } 47 | 48 | public static ExportOptions ToFile(string fileName, string exportName) 49 | { 50 | return new ExportOptions(fileName, exportName); 51 | } 52 | } 53 | 54 | public class DataExporters 55 | { 56 | public static readonly IDataExporter Csv = new CsvDataExporter(); 57 | public static readonly IDataExporter Tsv = new TsvDataExporter(); 58 | public static readonly IDataExporter Excel = new ExcelDataExporter(); 59 | public static readonly IDataExporter Html = new HtmlDataExporter(); 60 | public static readonly IDataExporter Json = new JsonDataExporter(); 61 | public static readonly IDataExporter Markdown = new MarkdownDataExporter(); 62 | public static readonly IDataExporter SqlInsert = new SqlInsertDataExporter(); 63 | public static readonly IDataExporter SqlUpdate = new SqlUpdateDataExporter(); 64 | public static readonly IDataExporter Xml = new XmlDataExporter(); 65 | 66 | public static readonly IDataExporter[] All = 67 | { 68 | Csv, 69 | Tsv, 70 | Excel, 71 | Html, 72 | Json, 73 | Markdown, 74 | SqlInsert, 75 | SqlUpdate, 76 | Xml 77 | }; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /SqlPad/DataExport/SqlInsertDataExporter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace SqlPad.DataExport 7 | { 8 | internal class SqlInsertDataExporter : SqlBaseDataExporter 9 | { 10 | public override string Name { get; } = "SQL insert"; 11 | 12 | protected override DataExportContextBase CreateExportContext(ExportOptions exportOptions, IReadOnlyList columns, IDataExportConverter dataExportConverter) 13 | { 14 | return new SqlInsertExportContext(exportOptions, columns, dataExportConverter); 15 | } 16 | } 17 | 18 | internal class SqlInsertExportContext : SqlDataExportContextBase 19 | { 20 | public SqlInsertExportContext(ExportOptions exportOptions, IReadOnlyList columns, IDataExportConverter dataExportConverter) 21 | : base(exportOptions, columns, dataExportConverter) 22 | { 23 | } 24 | 25 | protected override string BuildSqlCommandTemplate(IEnumerable columnHeaders) 26 | { 27 | var headerArray = columnHeaders.ToArray(); 28 | var sqlTemplateBuilder = new StringBuilder("INSERT INTO MY_TABLE (", 32768); 29 | sqlTemplateBuilder.Append(String.Join(", ", headerArray)); 30 | sqlTemplateBuilder.Append(") VALUES ("); 31 | sqlTemplateBuilder.Append(String.Join(", ", headerArray.Select((c, i) => $"{{{i}}}"))); 32 | sqlTemplateBuilder.Append(");"); 33 | 34 | return sqlTemplateBuilder.ToString(); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /SqlPad/DataExport/TsvDataExporter.cs: -------------------------------------------------------------------------------- 1 | namespace SqlPad.DataExport 2 | { 3 | public class TsvDataExporter : CsvDataExporter 4 | { 5 | public override string Name { get; } = "Tab separated value"; 6 | 7 | public override string FileNameFilter { get; } = "TSV files (*.tsv)|*.tsv|All files (*.*)|*"; 8 | 9 | public override string FileExtension { get; } = "tsv"; 10 | 11 | protected override string Separator { get; } = "\t"; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /SqlPad/DataSpaceConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | 4 | namespace SqlPad 5 | { 6 | public class DataSpaceConverter : ValueConverterBase 7 | { 8 | public static readonly DataSpaceConverter Instance = new DataSpaceConverter(); 9 | 10 | public override object Convert(object value, Type targetType, object parameter, CultureInfo culture) => 11 | value == null 12 | ? parameter?.ToString() ?? ValueNotAvailable 13 | : PrettyPrint(System.Convert.ToDecimal(value)); 14 | 15 | public static string PrettyPrint(decimal bytes) => PrettyPrint(bytes, CultureInfo.CurrentCulture); 16 | 17 | public static string PrettyPrint(decimal bytes, CultureInfo culture) 18 | { 19 | if (bytes < 1024) 20 | { 21 | return $"{bytes.ToString(culture)} B"; 22 | } 23 | 24 | if (bytes < 1048576) 25 | { 26 | return $"{Math.Round(bytes / 1024).ToString(culture)} kB"; 27 | } 28 | 29 | if (bytes < 1073741824) 30 | { 31 | return $"{Math.Round(bytes / 1048576, 1).ToString(culture)} MB"; 32 | } 33 | 34 | if (bytes < 1099511627776) 35 | { 36 | return $"{Math.Round(bytes / 1073741824, 2).ToString(culture)} GB"; 37 | } 38 | 39 | if (bytes < 1125899906842624) 40 | { 41 | return $"{Math.Round(bytes / 1099511627776, 2).ToString(culture)} TB"; 42 | } 43 | 44 | if (bytes < 1152921504606846976) 45 | { 46 | return $"{Math.Round(bytes / 1125899906842624, 2).ToString(culture)} PB"; 47 | } 48 | 49 | if (bytes < 1180591620717411303424m) 50 | { 51 | return $"{Math.Round(bytes / 1152921504606846976, 2).ToString(culture)} EB"; 52 | } 53 | 54 | if (bytes < 1208925819614629174706176m) 55 | { 56 | return $"{Math.Round(bytes / 1180591620717411303424m, 2).ToString(culture)} ZB"; 57 | } 58 | 59 | return $"{Math.Round(bytes / 1208925819614629174706176m, 2).ToString(culture)} YB"; 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /SqlPad/DragDrop/DraggedAdorner.cs: -------------------------------------------------------------------------------- 1 | using System.Windows.Documents; 2 | using System.Windows.Controls; 3 | using System.Windows; 4 | using System.Windows.Media; 5 | 6 | namespace SqlPad.DragDrop 7 | { 8 | public class DraggedAdorner : Adorner 9 | { 10 | private readonly ContentPresenter _contentPresenter; 11 | private readonly AdornerLayer _adornerLayer; 12 | private double _left; 13 | private double _top; 14 | 15 | public DraggedAdorner(object dragDropData, DataTemplate dragDropTemplate, UIElement adornedElement, AdornerLayer adornerLayer) 16 | : base(adornedElement) 17 | { 18 | _adornerLayer = adornerLayer; 19 | 20 | _contentPresenter = 21 | new ContentPresenter 22 | { 23 | Content = dragDropData, 24 | ContentTemplate = dragDropTemplate, 25 | Opacity = 0.7 26 | }; 27 | 28 | _adornerLayer.Add(this); 29 | } 30 | 31 | public void SetPosition(double left, double top) 32 | { 33 | _left = left - 1; 34 | _top = top + 13; 35 | 36 | _adornerLayer?.Update(AdornedElement); 37 | } 38 | 39 | protected override Size MeasureOverride(Size constraint) 40 | { 41 | _contentPresenter.Measure(constraint); 42 | return _contentPresenter.DesiredSize; 43 | } 44 | 45 | protected override Size ArrangeOverride(Size finalSize) 46 | { 47 | _contentPresenter.Arrange(new Rect(finalSize)); 48 | return finalSize; 49 | } 50 | 51 | protected override Visual GetVisualChild(int index) 52 | { 53 | return _contentPresenter; 54 | } 55 | 56 | protected override int VisualChildrenCount { get; } = 1; 57 | 58 | public override GeneralTransform GetDesiredTransform(GeneralTransform transform) 59 | { 60 | var result = new GeneralTransformGroup(); 61 | result.Children.Add(base.GetDesiredTransform(transform)); 62 | result.Children.Add(new TranslateTransform(_left, _top)); 63 | 64 | return result; 65 | } 66 | 67 | public void Detach() 68 | { 69 | _adornerLayer.Remove(this); 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /SqlPad/EditDialog.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows; 3 | using System.Windows.Controls; 4 | using System.Windows.Data; 5 | using System.Windows.Input; 6 | using SqlPad.Commands; 7 | 8 | namespace SqlPad 9 | { 10 | public partial class EditDialog : ICommandSettingsProvider 11 | { 12 | public EditDialog(CommandSettingsModel settings) 13 | { 14 | InitializeComponent(); 15 | 16 | Settings = settings ?? throw new ArgumentNullException(nameof(settings)); 17 | } 18 | 19 | private void CloseClickHandler(object sender, RoutedEventArgs e) 20 | { 21 | DialogResult = true; 22 | Close(); 23 | } 24 | 25 | private void LoadedHandler(object sender, RoutedEventArgs e) 26 | { 27 | DataContext = Settings; 28 | 29 | if (Settings.ValidationRule != null) 30 | { 31 | BindingOperations.GetBinding(TextValue, TextBox.TextProperty).ValidationRules.Add(Settings.ValidationRule); 32 | BindingOperations.GetBindingExpression(TextValue, TextBox.TextProperty).UpdateSource(); 33 | } 34 | 35 | TextValue.Focus(); 36 | TextValue.SelectAll(); 37 | } 38 | 39 | public bool GetSettings() 40 | { 41 | if (Settings.UseDefaultSettings != null && Settings.UseDefaultSettings()) 42 | return true; 43 | 44 | var result = ShowDialog(); 45 | return result.HasValue && result.Value; 46 | } 47 | 48 | public CommandSettingsModel Settings { get; } 49 | 50 | private void SelectItemCommandExecutedHandler(object sender, ExecutedRoutedEventArgs e) 51 | { 52 | bool? newValue = null; 53 | foreach (BooleanOption option in ((ListView)sender).SelectedItems) 54 | { 55 | if (!newValue.HasValue) 56 | { 57 | newValue = !option.Value; 58 | } 59 | 60 | option.Value = newValue.Value; 61 | } 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /SqlPad/EmptyIcon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Husqvik/SQLPad/c858b567aa01be4d5920cd9f9fc05c65c939a584/SqlPad/EmptyIcon.ico -------------------------------------------------------------------------------- /SqlPad/FindReplace/Adapters.cs: -------------------------------------------------------------------------------- 1 | using ICSharpCode.AvalonEdit; 2 | using System.Globalization; 3 | using System; 4 | using System.Windows.Controls; 5 | 6 | namespace SqlPad.FindReplace 7 | { 8 | public class TextEditorAdapter : IEditor 9 | { 10 | public TextEditorAdapter(TextEditor editor) 11 | { 12 | _editor = editor; 13 | } 14 | 15 | public Control Control => _editor; 16 | 17 | private readonly TextEditor _editor; 18 | 19 | public string Text => _editor.Text; 20 | 21 | public int SelectionStart => _editor.SelectionStart; 22 | 23 | public int SelectionLength => _editor.SelectionLength; 24 | 25 | public string SelectedText => _editor.SelectedText; 26 | 27 | public void BeginChange() 28 | { 29 | _editor.BeginChange(); 30 | } 31 | 32 | public void EndChange() 33 | { 34 | _editor.EndChange(); 35 | } 36 | 37 | public void Select(int start, int length) 38 | { 39 | _editor.Select(start, length); 40 | var location = _editor.Document.GetLocation(start); 41 | _editor.ScrollTo(location.Line, location.Column); 42 | } 43 | 44 | public void Replace(int start, int length, string replaceWith) 45 | { 46 | _editor.Document.Replace(start, length, replaceWith); 47 | } 48 | 49 | } 50 | 51 | public class EditorConverter : ValueConverterBase 52 | { 53 | public override object Convert(object value, Type targetType, object parameter, CultureInfo culture) 54 | { 55 | return new TextEditorAdapter((TextEditor)value); 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /SqlPad/FindReplace/FindReplaceDialog.xaml.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | using System.Windows.Input; 3 | 4 | namespace SqlPad.FindReplace 5 | { 6 | public partial class FindReplaceDialog 7 | { 8 | readonly FindReplaceManager _findReplaceManager; 9 | 10 | public FindReplaceDialog(FindReplaceManager findReplaceManager) 11 | { 12 | DataContext = _findReplaceManager = findReplaceManager; 13 | InitializeComponent(); 14 | } 15 | 16 | private void FindNextClick(object sender, RoutedEventArgs e) 17 | { 18 | _findReplaceManager.FindNext(); 19 | } 20 | 21 | private void ReplaceClick(object sender, RoutedEventArgs e) 22 | { 23 | _findReplaceManager.Replace(); 24 | } 25 | 26 | private void ReplaceAllClick(object sender, RoutedEventArgs e) 27 | { 28 | _findReplaceManager.ReplaceAll(); 29 | } 30 | 31 | private void KeyDownHandler(object sender, KeyEventArgs e) 32 | { 33 | if (e.Key == Key.Escape) 34 | Close(); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /SqlPad/FindReplace/IEditor.cs: -------------------------------------------------------------------------------- 1 | namespace SqlPad.FindReplace 2 | { 3 | public interface IEditor 4 | { 5 | string Text { get; } 6 | 7 | int SelectionStart { get; } 8 | 9 | int SelectionLength { get; } 10 | 11 | string SelectedText { get; } 12 | 13 | /// 14 | /// Selects the specified portion of Text and scrolls that part into view. 15 | /// 16 | /// 17 | /// 18 | void Select(int start, int length); 19 | 20 | void Replace(int start, int length, string replaceWith); 21 | 22 | /// 23 | /// This method is called before a replace all operation. 24 | /// 25 | void BeginChange(); 26 | 27 | /// 28 | /// This method is called after a replace all operation. 29 | /// 30 | void EndChange(); 31 | } 32 | } -------------------------------------------------------------------------------- /SqlPad/FindReplace/TextSearchHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text.RegularExpressions; 5 | 6 | namespace SqlPad.FindReplace 7 | { 8 | public static class TextSearchHelper 9 | { 10 | private static readonly char[] SearchPhraseSeparators = { ' ' }; 11 | 12 | public static string[] GetSearchedWords(string searchPhrase) 13 | { 14 | return searchPhrase.ToUpperInvariant().Split(SearchPhraseSeparators, StringSplitOptions.RemoveEmptyEntries); 15 | } 16 | 17 | public static string GetRegexPattern(string searchPhrase) 18 | { 19 | return GetRegexPattern(GetSearchedWords(searchPhrase)); 20 | } 21 | 22 | public static string GetRegexPattern(IEnumerable searchedWords) 23 | { 24 | var regexPatterns = searchedWords.Select(w => $"({Regex.Escape(w)})"); 25 | return String.Join("|", regexPatterns); 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /SqlPad/FindReplace/next.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Husqvik/SQLPad/c858b567aa01be4d5920cd9f9fc05c65c939a584/SqlPad/FindReplace/next.png -------------------------------------------------------------------------------- /SqlPad/FindReplace/prev.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Husqvik/SQLPad/c858b567aa01be4d5920cd9f9fc05c65c939a584/SqlPad/FindReplace/prev.png -------------------------------------------------------------------------------- /SqlPad/FoldingSection.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics; 2 | 3 | namespace SqlPad 4 | { 5 | [DebuggerDisplay("FoldingSection (Placeholder={Placeholder}; Range={FoldingStart + \"-\" + FoldingEnd})")] 6 | public class FoldingSection 7 | { 8 | public int FoldingStart { get; set; } 9 | 10 | public int FoldingEnd { get; set; } 11 | 12 | public string Placeholder { get; set; } 13 | 14 | public bool IsNested { get; set; } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /SqlPad/GenerateXsdClasses.cmd: -------------------------------------------------------------------------------- 1 | xsd Snippet.xsd /c /n:SqlPad 2 | xsd Configuration.xsd /c /n:SqlPad -------------------------------------------------------------------------------- /SqlPad/ICodeCompletionProvider.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace SqlPad 4 | { 5 | public interface ICodeCompletionProvider 6 | { 7 | IReadOnlyCollection ResolveProgramOverloads(SqlDocumentRepository documentRepository, int cursorPosition); 8 | 9 | IReadOnlyCollection ResolveItems(SqlDocumentRepository sqlDocumentRepository, IDatabaseModel databaseModel, int cursorPosition, bool forcedInvokation); 10 | } 11 | 12 | public class ProgramOverloadDescription 13 | { 14 | public string Name { get; set; } 15 | 16 | public IReadOnlyList Parameters { get; set; } 17 | 18 | public int CurrentParameterIndex { get; set; } 19 | 20 | public string ReturnedDatatype { get; set; } 21 | } 22 | 23 | public interface ICodeCompletionItem 24 | { 25 | string Category { get; } 26 | 27 | string Label { get; } 28 | 29 | StatementGrammarNode StatementNode { get; } 30 | 31 | int Priority { get; } 32 | 33 | int CategoryPriority { get; } 34 | 35 | int InsertOffset { get; } 36 | 37 | int CaretOffset { get; } 38 | 39 | string Text { get; } 40 | 41 | string Description { get; } 42 | } 43 | } -------------------------------------------------------------------------------- /SqlPad/ICodeSnippetProvider.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace SqlPad 4 | { 5 | public interface ICodeSnippetProvider 6 | { 7 | IEnumerable GetSnippets(SqlDocumentRepository sqlDocumentRepository, string statementText, int cursorPosition); 8 | 9 | IEnumerable GetCodeGenerationItems(SqlDocumentRepository sqlDocumentRepository); 10 | } 11 | 12 | public interface ICodeSnippet 13 | { 14 | string Name { get; } 15 | 16 | string Description { get; } 17 | 18 | string BaseText { get; } 19 | 20 | IReadOnlyList Parameters { get; } 21 | 22 | SourcePosition SourceToReplace { get; } 23 | } 24 | 25 | public interface ICodeSnippetParameter 26 | { 27 | string Name { get; } 28 | 29 | int Index { get; } 30 | 31 | string DefaultValue { get; } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /SqlPad/IConnectionAdapter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Threading; 4 | using System.Threading.Tasks; 5 | 6 | namespace SqlPad 7 | { 8 | public interface IConnectionAdapter : IDisposable 9 | { 10 | IDatabaseModel DatabaseModel { get; } 11 | 12 | IDebuggerSession DebuggerSession { get; } 13 | 14 | bool CanFetch(ResultInfo resultInfo); 15 | 16 | bool IsExecuting { get; } 17 | 18 | bool EnableDatabaseOutput { get; set; } 19 | 20 | string Identifier { get; set; } 21 | 22 | Task ExecuteStatementAsync(StatementBatchExecutionModel executionModel, CancellationToken cancellationToken); 23 | 24 | Task ExecuteChildStatementAsync(StatementExecutionModel executionModel, CancellationToken cancellationToken); 25 | 26 | Task RefreshResult(StatementExecutionResult result, CancellationToken cancellationToken); 27 | 28 | Task> GetExecutionStatisticsAsync(CancellationToken cancellationToken); 29 | 30 | Task> FetchRecordsAsync(ResultInfo resultInfo, int rowCount, CancellationToken cancellationToken); 31 | 32 | bool HasActiveTransaction { get; } 33 | 34 | string TransanctionIdentifier { get; } 35 | 36 | Task CommitTransaction(); 37 | 38 | Task RollbackTransaction(); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /SqlPad/IContextActionProvider.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Diagnostics; 3 | using SqlPad.Commands; 4 | 5 | namespace SqlPad 6 | { 7 | public interface IContextActionProvider 8 | { 9 | ICollection GetContextActions(SqlDocumentRepository sqlDocumentRepository, ActionExecutionContext executionContext); 10 | 11 | ICollection GetAvailableRefactorings(SqlDocumentRepository sqlDocumentRepository, ActionExecutionContext executionContext); 12 | } 13 | 14 | [DebuggerDisplay("ContextAction (Name={Name})")] 15 | public class ContextAction 16 | { 17 | public ContextAction(string name, CommandExecutionHandler executionHandler, ActionExecutionContext executionContext, bool isLongOperation = false) 18 | { 19 | Name = name; 20 | ExecutionHandler = executionHandler; 21 | ExecutionContext = executionContext; 22 | IsLongOperation = isLongOperation; 23 | } 24 | 25 | public string Name { get; } 26 | 27 | public bool IsLongOperation { get; private set; } 28 | 29 | public CommandExecutionHandler ExecutionHandler { get; private set; } 30 | 31 | public ActionExecutionContext ExecutionContext { get; private set; } 32 | } 33 | } -------------------------------------------------------------------------------- /SqlPad/IDebuggerSession.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Threading; 4 | using System.Threading.Tasks; 5 | 6 | namespace SqlPad 7 | { 8 | public interface IDebuggerSession 9 | { 10 | int? ActiveLine { get; } 11 | 12 | bool BreakOnExceptions { get; set; } 13 | 14 | event EventHandler Attached; 15 | 16 | event EventHandler Detached; 17 | 18 | IReadOnlyList StackTrace { get; } 19 | 20 | DatabaseExceptionInformation CurrentException { get; } 21 | 22 | Task Start(CancellationToken cancellationToken); 23 | 24 | Task Continue(CancellationToken cancellationToken); 25 | 26 | Task StepOver(CancellationToken cancellationToken); 27 | 28 | Task StepInto(CancellationToken cancellationToken); 29 | 30 | Task StepOut(CancellationToken cancellationToken); 31 | 32 | Task Abort(CancellationToken cancellationToken); 33 | 34 | Task GetValue(WatchItem watchItem, CancellationToken cancellationToken); 35 | 36 | Task SetValue(WatchItem watchItem, CancellationToken cancellationToken); 37 | 38 | Task SetBreakpoint(object programInfo, int line, CancellationToken cancellationToken); 39 | 40 | Task DeleteBreakpoint(object breakpointIdentifier, CancellationToken cancellationToken); 41 | 42 | Task EnableBreakpoint(object breakpointIdentifier, CancellationToken cancellationToken); 43 | 44 | Task DisableBreakpoint(object breakpointIdentifier, CancellationToken cancellationToken); 45 | } 46 | 47 | public class DebugProgramItem 48 | { 49 | public string Header { get; set; } 50 | 51 | public string ProgramText { get; set; } 52 | 53 | public int Line { get; set; } 54 | 55 | public object ProgramIdentifier { get; set; } 56 | } 57 | 58 | public struct BreakpointActionResult 59 | { 60 | public object BreakpointIdentifier; 61 | 62 | public bool IsSuccessful; 63 | } 64 | 65 | public class DatabaseExceptionInformation 66 | { 67 | public int ErrorCode { get; set; } 68 | 69 | public string ErrorMessage { get; set; } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /SqlPad/IHelpProvider.cs: -------------------------------------------------------------------------------- 1 | using SqlPad.Commands; 2 | 3 | namespace SqlPad 4 | { 5 | public interface IHelpProvider 6 | { 7 | void ShowHelp(ActionExecutionContext executionContext); 8 | } 9 | } -------------------------------------------------------------------------------- /SqlPad/ILargeTextValue.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.Text; 5 | 6 | namespace SqlPad 7 | { 8 | public interface IValue 9 | { 10 | bool IsNull { get; } 11 | 12 | string ToSqlLiteral(); 13 | 14 | string ToXml(); 15 | 16 | string ToJson(); 17 | 18 | object RawValue { get; } 19 | } 20 | 21 | public interface ILargeValue : IValue 22 | { 23 | string DataTypeName { get; } 24 | 25 | bool IsEditable { get; } 26 | 27 | long Length { get; } 28 | 29 | void Prefetch(); 30 | } 31 | 32 | public interface ILargeTextValue: ILargeValue 33 | { 34 | string Preview { get; } 35 | 36 | string Value { get; } 37 | 38 | void GetChunk(StringBuilder stringBuilder, int offset, int length); 39 | } 40 | 41 | public interface ILargeBinaryValue : ILargeValue 42 | { 43 | byte[] Value { get; } 44 | 45 | byte[] GetChunk(int bytes); 46 | } 47 | 48 | public interface ICollectionValue : ILargeValue 49 | { 50 | IList Records { get; } 51 | 52 | ColumnHeader ColumnHeader { get; } 53 | } 54 | 55 | public interface IComplexType : ILargeValue 56 | { 57 | IReadOnlyList Attributes { get; } 58 | } 59 | 60 | [DebuggerDisplay("CustomTypeAttributeValue (ColumnName={ColumnHeader.Name}; Value={Value})")] 61 | public struct CustomTypeAttributeValue 62 | { 63 | public ColumnHeader ColumnHeader { get; set; } 64 | 65 | public object Value { get; set; } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /SqlPad/ISqlParser.cs: -------------------------------------------------------------------------------- 1 | using System.Threading; 2 | using System.Threading.Tasks; 3 | 4 | namespace SqlPad 5 | { 6 | public interface ISqlParser 7 | { 8 | StatementCollection Parse(string sqlText); 9 | 10 | Task ParseAsync(string sqlText, CancellationToken cancellationToken); 11 | 12 | bool IsLiteral(string terminalId); 13 | 14 | bool IsAlias(string terminalId); 15 | 16 | bool CanAddPairCharacter(string tokenValue, char character); 17 | } 18 | } -------------------------------------------------------------------------------- /SqlPad/IStatementFormatter.cs: -------------------------------------------------------------------------------- 1 | using SqlPad.Commands; 2 | 3 | namespace SqlPad 4 | { 5 | public interface IStatementFormatter 6 | { 7 | CommandExecutionHandler ExecutionHandler { get; } 8 | CommandExecutionHandler SingleLineExecutionHandler { get; } 9 | CommandExecutionHandler NormalizeHandler { get; } 10 | } 11 | } -------------------------------------------------------------------------------- /SqlPad/IStatementValidator.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Collections.ObjectModel; 3 | using System.Linq; 4 | using System.Threading; 5 | using System.Threading.Tasks; 6 | 7 | namespace SqlPad 8 | { 9 | public interface IStatementValidator 10 | { 11 | IStatementSemanticModel BuildSemanticModel(string statementText, StatementBase statementBase, IDatabaseModel databaseModel); 12 | 13 | Task BuildSemanticModelAsync(string statementText, StatementBase statementBase, IDatabaseModel databaseModel, CancellationToken cancellationToken); 14 | 15 | IValidationModel BuildValidationModel(IStatementSemanticModel semanticModel); 16 | 17 | Task> ApplyReferenceConstraintsAsync(StatementExecutionResult executionResult, IDatabaseModel databaseModel, CancellationToken cancellationToken); 18 | } 19 | 20 | public interface IStatementSemanticModel 21 | { 22 | IDatabaseModel DatabaseModel { get; } 23 | StatementBase Statement { get; } 24 | string StatementText { get; } 25 | bool HasDatabaseModel { get; } 26 | ICollection RedundantSymbolGroups { get; } 27 | } 28 | 29 | public class RedundantTerminalGroup : ReadOnlyCollection 30 | { 31 | public RedundantTerminalGroup(IEnumerable items, RedundancyType redundancyType) 32 | : base(items.ToArray()) 33 | { 34 | RedundancyType = redundancyType; 35 | } 36 | 37 | public RedundancyType RedundancyType { get; private set; } 38 | } 39 | 40 | public enum RedundancyType 41 | { 42 | Qualifier, 43 | UnusedColumn, 44 | RedundantColumnAlias, 45 | RedundantObjectAlias, 46 | UnusedQueryBlock 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /SqlPad/IToken.cs: -------------------------------------------------------------------------------- 1 | namespace SqlPad 2 | { 3 | public interface IToken 4 | { 5 | string Value { get; } 6 | 7 | int Index { get; } 8 | 9 | CommentType CommentType { get; } 10 | } 11 | 12 | public enum CommentType 13 | { 14 | None, 15 | Line, 16 | Block 17 | } 18 | } -------------------------------------------------------------------------------- /SqlPad/ITokenReader.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace SqlPad 4 | { 5 | public interface ITokenReader 6 | { 7 | IEnumerable GetTokens(bool includeCommentBlocks = false); 8 | } 9 | } -------------------------------------------------------------------------------- /SqlPad/IToolTipProvider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows; 3 | using System.Windows.Controls; 4 | 5 | namespace SqlPad 6 | { 7 | public interface IToolTipProvider 8 | { 9 | IToolTip GetToolTip(SqlDocumentRepository sqlDocumentRepository, int cursorPosition); 10 | } 11 | 12 | public interface IToolTip 13 | { 14 | Control Control { get; } 15 | 16 | FrameworkElement InnerContent { get; } 17 | 18 | event EventHandler Pin; 19 | } 20 | } -------------------------------------------------------------------------------- /SqlPad/IValidationModel.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace SqlPad 4 | { 5 | public interface IValidationModel 6 | { 7 | StatementBase Statement { get; } 8 | 9 | IStatementSemanticModel SemanticModel { get; } 10 | 11 | IDictionary ObjectNodeValidity { get; } 12 | 13 | IDictionary ColumnNodeValidity { get; } 14 | 15 | IDictionary ProgramNodeValidity { get; } 16 | 17 | IDictionary IdentifierNodeValidity { get; } 18 | 19 | IEnumerable Errors { get; } 20 | 21 | IEnumerable SemanticErrors { get; } 22 | 23 | IEnumerable Suggestions { get; } 24 | } 25 | 26 | public interface INodeValidationData 27 | { 28 | StatementGrammarNode Node { get; } 29 | 30 | string SuggestionType { get; } 31 | 32 | string SemanticErrorType { get; } 33 | 34 | bool IsRecognized { get; } 35 | 36 | ICollection ObjectNames { get; } 37 | 38 | string ToolTipText { get; } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /SqlPad/MarginSetter.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using System.Windows; 3 | using System.Windows.Controls; 4 | 5 | namespace SqlPad 6 | { 7 | public class MarginSetter 8 | { 9 | public static Thickness GetMargin(DependencyObject obj) 10 | { 11 | return (Thickness)obj.GetValue(MarginProperty); 12 | } 13 | 14 | public static void SetMargin(DependencyObject obj, Thickness value) 15 | { 16 | obj.SetValue(MarginProperty, value); 17 | } 18 | 19 | // Using a DependencyProperty as the backing store for Margin. This enables animation, styling, binding, etc... 20 | public static readonly DependencyProperty MarginProperty = 21 | DependencyProperty.RegisterAttached("Margin", typeof(Thickness), typeof(MarginSetter), new UIPropertyMetadata(new Thickness(), MarginChangedCallback)); 22 | 23 | public static void MarginChangedCallback(object sender, DependencyPropertyChangedEventArgs e) 24 | { 25 | // Make sure this is put on a panel 26 | var panel = sender as Panel; 27 | 28 | if (panel == null) 29 | return; 30 | 31 | panel.Loaded += PanelLoadedHandler; 32 | } 33 | 34 | private static void PanelLoadedHandler(object sender, RoutedEventArgs e) 35 | { 36 | var panel = (Panel)sender; 37 | 38 | // Go over the children and set margin for them: 39 | foreach (var frameworkElement in panel.Children.OfType()) 40 | { 41 | frameworkElement.Margin = GetMargin(panel); 42 | } 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /SqlPad/Messages.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows; 3 | 4 | namespace SqlPad 5 | { 6 | public static class Messages 7 | { 8 | public static string GetExceptionErrorMessage(Exception exception) 9 | { 10 | return String.IsNullOrEmpty(exception.Message) ? "" : exception.Message; 11 | } 12 | 13 | public static MessageBoxResult ShowInformation(string message, string caption = "Information", Window owner = null) 14 | { 15 | return ShowMessage(message, caption, MessageBoxImage.Information, owner); 16 | } 17 | 18 | public static MessageBoxResult ShowError(string errorMessage, string caption = "Error", Window owner = null) 19 | { 20 | return ShowMessage(errorMessage, caption, MessageBoxImage.Error, owner); 21 | } 22 | 23 | private static MessageBoxResult ShowMessage(string message, string caption, MessageBoxImage image, Window owner) 24 | { 25 | if (owner == null) 26 | { 27 | owner = App.MainWindow; 28 | } 29 | 30 | return MessageBox.Show(owner, message, caption, MessageBoxButton.OK, image); 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /SqlPad/ModelBase.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using System.Runtime.CompilerServices; 3 | 4 | namespace SqlPad 5 | { 6 | public class ModelBase : INotifyPropertyChanged, INotifyPropertyChanging 7 | { 8 | public event PropertyChangingEventHandler PropertyChanging; 9 | 10 | public event PropertyChangedEventHandler PropertyChanged; 11 | 12 | protected bool UpdateValueAndRaisePropertyChanged(ref T value, T newValue, [CallerMemberName] string propertyName = null) 13 | { 14 | if (Equals(value, newValue)) 15 | return false; 16 | 17 | if (PropertyChanging != null) 18 | { 19 | var args = new PropertyChangingEventArgs(propertyName); 20 | PropertyChanging(this, args); 21 | } 22 | 23 | value = newValue; 24 | 25 | RaisePropertyChanged(propertyName); 26 | 27 | return true; 28 | } 29 | 30 | protected void RaisePropertyChanged(params string[] propertyNames) 31 | { 32 | foreach (var propertyName in propertyNames) 33 | { 34 | PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); 35 | } 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /SqlPad/Namespaces.cs: -------------------------------------------------------------------------------- 1 | namespace SqlPad 2 | { 3 | public static class Namespaces 4 | { 5 | public const string SqlPadBaseNamespace = "http://husqvik.com/SqlPad/2014/02"; 6 | } 7 | } -------------------------------------------------------------------------------- /SqlPad/NodeType.cs: -------------------------------------------------------------------------------- 1 | namespace SqlPad 2 | { 3 | public enum NodeType 4 | { 5 | Terminal, 6 | NonTerminal 7 | } 8 | } -------------------------------------------------------------------------------- /SqlPad/ParseResult.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Diagnostics; 3 | 4 | namespace SqlPad 5 | { 6 | [DebuggerDisplay("ParseResult (Status={Status}{Nodes == null ? \"\" : \", Nodes=\" + System.Linq.Enumerable.Count(Nodes), nq})")] 7 | public struct ParseResult 8 | { 9 | public ParseStatus Status; 10 | 11 | public string NodeId; 12 | 13 | public IList Nodes; 14 | 15 | public IList BestCandidates; 16 | 17 | public int TerminalCount; 18 | 19 | public int BestCandidateTerminalCount; 20 | } 21 | } -------------------------------------------------------------------------------- /SqlPad/ParseStatus.cs: -------------------------------------------------------------------------------- 1 | namespace SqlPad 2 | { 3 | public enum ParseStatus 4 | { 5 | Success, 6 | SequenceNotFound 7 | } 8 | } -------------------------------------------------------------------------------- /SqlPad/PasswordDialog.xaml: -------------------------------------------------------------------------------- 1 |  8 | 9 | 10 | 11 | 12 | 15 | 16 | 17 | 18 |