commit
3afa4c82ef
@ -0,0 +1,11 @@
|
|||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
end_of_line = crlf
|
||||||
|
insert_final_newline = true
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
|
||||||
|
# 4 space indentation
|
||||||
|
[*.cs]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 4
|
||||||
@ -0,0 +1,6 @@
|
|||||||
|
# Set the default behavior, in case people don't have core.autocrlf set.
|
||||||
|
* text=auto
|
||||||
|
|
||||||
|
# Declare files that will always have CRLF line endings on checkout.
|
||||||
|
# required for unit tests to pass on any platform
|
||||||
|
*.sql text eol=crlf
|
||||||
@ -0,0 +1,352 @@
|
|||||||
|
|
||||||
|
# Created by https://www.gitignore.io/api/csharp
|
||||||
|
# Edit at https://www.gitignore.io/?templates=csharp
|
||||||
|
|
||||||
|
### Csharp ###
|
||||||
|
## Ignore Visual Studio temporary files, build results, and
|
||||||
|
## files generated by popular Visual Studio add-ons.
|
||||||
|
##
|
||||||
|
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
|
||||||
|
|
||||||
|
# User-specific files
|
||||||
|
*.rsuser
|
||||||
|
*.suo
|
||||||
|
*.user
|
||||||
|
*.userosscache
|
||||||
|
*.sln.docstates
|
||||||
|
.vs
|
||||||
|
|
||||||
|
# User-specific files (MonoDevelop/Xamarin Studio)
|
||||||
|
*.userprefs
|
||||||
|
|
||||||
|
# Mono auto generated files
|
||||||
|
mono_crash.*
|
||||||
|
|
||||||
|
# Build results
|
||||||
|
[Dd]ebug/
|
||||||
|
[Dd]ebugPublic/
|
||||||
|
[Rr]elease/
|
||||||
|
[Rr]eleases/
|
||||||
|
x64/
|
||||||
|
x86/
|
||||||
|
[Aa][Rr][Mm]/
|
||||||
|
[Aa][Rr][Mm]64/
|
||||||
|
bld/
|
||||||
|
[Bb]in/
|
||||||
|
[Oo]bj/
|
||||||
|
[Ll]og/
|
||||||
|
|
||||||
|
# Visual Studio 2015/2017 cache/options directory
|
||||||
|
.vs/
|
||||||
|
# Uncomment if you have tasks that create the project's static files in wwwroot
|
||||||
|
#wwwroot/
|
||||||
|
|
||||||
|
# Visual Studio 2017 auto generated files
|
||||||
|
Generated\ Files/
|
||||||
|
|
||||||
|
# MSTest test Results
|
||||||
|
[Tt]est[Rr]esult*/
|
||||||
|
[Bb]uild[Ll]og.*
|
||||||
|
|
||||||
|
# NUNIT
|
||||||
|
*.VisualState.xml
|
||||||
|
TestResult.xml
|
||||||
|
|
||||||
|
# Build Results of an ATL Project
|
||||||
|
[Dd]ebugPS/
|
||||||
|
[Rr]eleasePS/
|
||||||
|
dlldata.c
|
||||||
|
|
||||||
|
# Benchmark Results
|
||||||
|
BenchmarkDotNet.Artifacts/
|
||||||
|
|
||||||
|
# .NET Core
|
||||||
|
project.lock.json
|
||||||
|
project.fragment.lock.json
|
||||||
|
artifacts/
|
||||||
|
|
||||||
|
# StyleCop
|
||||||
|
StyleCopReport.xml
|
||||||
|
|
||||||
|
# Files built by Visual Studio
|
||||||
|
*_i.c
|
||||||
|
*_p.c
|
||||||
|
*_h.h
|
||||||
|
*.ilk
|
||||||
|
*.meta
|
||||||
|
*.obj
|
||||||
|
*.iobj
|
||||||
|
*.pch
|
||||||
|
*.pdb
|
||||||
|
*.ipdb
|
||||||
|
*.pgc
|
||||||
|
*.pgd
|
||||||
|
*.rsp
|
||||||
|
*.sbr
|
||||||
|
*.tlb
|
||||||
|
*.tli
|
||||||
|
*.tlh
|
||||||
|
*.tmp
|
||||||
|
*.tmp_proj
|
||||||
|
*_wpftmp.csproj
|
||||||
|
*.log
|
||||||
|
*.vspscc
|
||||||
|
*.vssscc
|
||||||
|
.builds
|
||||||
|
*.pidb
|
||||||
|
*.svclog
|
||||||
|
*.scc
|
||||||
|
|
||||||
|
# Chutzpah Test files
|
||||||
|
_Chutzpah*
|
||||||
|
|
||||||
|
# Visual C++ cache files
|
||||||
|
ipch/
|
||||||
|
*.aps
|
||||||
|
*.ncb
|
||||||
|
*.opendb
|
||||||
|
*.opensdf
|
||||||
|
*.sdf
|
||||||
|
*.cachefile
|
||||||
|
*.VC.db
|
||||||
|
*.VC.VC.opendb
|
||||||
|
|
||||||
|
# Visual Studio profiler
|
||||||
|
*.psess
|
||||||
|
*.vsp
|
||||||
|
*.vspx
|
||||||
|
*.sap
|
||||||
|
|
||||||
|
# Visual Studio Trace Files
|
||||||
|
*.e2e
|
||||||
|
|
||||||
|
# TFS 2012 Local Workspace
|
||||||
|
$tf/
|
||||||
|
|
||||||
|
# Guidance Automation Toolkit
|
||||||
|
*.gpState
|
||||||
|
|
||||||
|
# ReSharper is a .NET coding add-in
|
||||||
|
_ReSharper*/
|
||||||
|
*.[Rr]e[Ss]harper
|
||||||
|
*.DotSettings.user
|
||||||
|
|
||||||
|
# JustCode is a .NET coding add-in
|
||||||
|
.JustCode
|
||||||
|
|
||||||
|
# TeamCity is a build add-in
|
||||||
|
_TeamCity*
|
||||||
|
|
||||||
|
# DotCover is a Code Coverage Tool
|
||||||
|
*.dotCover
|
||||||
|
|
||||||
|
# AxoCover is a Code Coverage Tool
|
||||||
|
.axoCover/*
|
||||||
|
!.axoCover/settings.json
|
||||||
|
|
||||||
|
# Visual Studio code coverage results
|
||||||
|
*.coverage
|
||||||
|
*.coveragexml
|
||||||
|
|
||||||
|
# NCrunch
|
||||||
|
_NCrunch_*
|
||||||
|
.*crunch*.local.xml
|
||||||
|
nCrunchTemp_*
|
||||||
|
|
||||||
|
# MightyMoose
|
||||||
|
*.mm.*
|
||||||
|
AutoTest.Net/
|
||||||
|
|
||||||
|
# Web workbench (sass)
|
||||||
|
.sass-cache/
|
||||||
|
|
||||||
|
# Installshield output folder
|
||||||
|
[Ee]xpress/
|
||||||
|
|
||||||
|
# DocProject is a documentation generator add-in
|
||||||
|
DocProject/buildhelp/
|
||||||
|
DocProject/Help/*.HxT
|
||||||
|
DocProject/Help/*.HxC
|
||||||
|
DocProject/Help/*.hhc
|
||||||
|
DocProject/Help/*.hhk
|
||||||
|
DocProject/Help/*.hhp
|
||||||
|
DocProject/Help/Html2
|
||||||
|
DocProject/Help/html
|
||||||
|
|
||||||
|
# Click-Once directory
|
||||||
|
publish/
|
||||||
|
|
||||||
|
# Publish Web Output
|
||||||
|
*.[Pp]ublish.xml
|
||||||
|
*.azurePubxml
|
||||||
|
# Note: Comment the next line if you want to checkin your web deploy settings,
|
||||||
|
# but database connection strings (with potential passwords) will be unencrypted
|
||||||
|
*.pubxml
|
||||||
|
*.publishproj
|
||||||
|
|
||||||
|
# Microsoft Azure Web App publish settings. Comment the next line if you want to
|
||||||
|
# checkin your Azure Web App publish settings, but sensitive information contained
|
||||||
|
# in these scripts will be unencrypted
|
||||||
|
PublishScripts/
|
||||||
|
|
||||||
|
# NuGet Packages
|
||||||
|
*.nupkg
|
||||||
|
# The packages folder can be ignored because of Package Restore
|
||||||
|
**/[Pp]ackages/*
|
||||||
|
# except build/, which is used as an MSBuild target.
|
||||||
|
!**/[Pp]ackages/build/
|
||||||
|
# Uncomment if necessary however generally it will be regenerated when needed
|
||||||
|
#!**/[Pp]ackages/repositories.config
|
||||||
|
# NuGet v3's project.json files produces more ignorable files
|
||||||
|
*.nuget.props
|
||||||
|
*.nuget.targets
|
||||||
|
|
||||||
|
# Microsoft Azure Build Output
|
||||||
|
csx/
|
||||||
|
*.build.csdef
|
||||||
|
|
||||||
|
# Microsoft Azure Emulator
|
||||||
|
ecf/
|
||||||
|
rcf/
|
||||||
|
|
||||||
|
# Windows Store app package directories and files
|
||||||
|
AppPackages/
|
||||||
|
BundleArtifacts/
|
||||||
|
Package.StoreAssociation.xml
|
||||||
|
_pkginfo.txt
|
||||||
|
*.appx
|
||||||
|
*.appxbundle
|
||||||
|
*.appxupload
|
||||||
|
|
||||||
|
# Visual Studio cache files
|
||||||
|
# files ending in .cache can be ignored
|
||||||
|
*.[Cc]ache
|
||||||
|
# but keep track of directories ending in .cache
|
||||||
|
!?*.[Cc]ache/
|
||||||
|
|
||||||
|
# Others
|
||||||
|
ClientBin/
|
||||||
|
~$*
|
||||||
|
*~
|
||||||
|
*.dbmdl
|
||||||
|
*.dbproj.schemaview
|
||||||
|
*.jfm
|
||||||
|
*.pfx
|
||||||
|
*.publishsettings
|
||||||
|
orleans.codegen.cs
|
||||||
|
|
||||||
|
# Including strong name files can present a security risk
|
||||||
|
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
|
||||||
|
#*.snk
|
||||||
|
|
||||||
|
# Since there are multiple workflows, uncomment next line to ignore bower_components
|
||||||
|
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
|
||||||
|
#bower_components/
|
||||||
|
|
||||||
|
# RIA/Silverlight projects
|
||||||
|
Generated_Code/
|
||||||
|
|
||||||
|
# Backup & report files from converting an old project file
|
||||||
|
# to a newer Visual Studio version. Backup files are not needed,
|
||||||
|
# because we have git ;-)
|
||||||
|
_UpgradeReport_Files/
|
||||||
|
Backup*/
|
||||||
|
UpgradeLog*.XML
|
||||||
|
UpgradeLog*.htm
|
||||||
|
ServiceFabricBackup/
|
||||||
|
*.rptproj.bak
|
||||||
|
|
||||||
|
# SQL Server files
|
||||||
|
*.mdf
|
||||||
|
*.ldf
|
||||||
|
*.ndf
|
||||||
|
|
||||||
|
# Business Intelligence projects
|
||||||
|
*.rdl.data
|
||||||
|
*.bim.layout
|
||||||
|
*.bim_*.settings
|
||||||
|
*.rptproj.rsuser
|
||||||
|
*- Backup*.rdl
|
||||||
|
|
||||||
|
# Microsoft Fakes
|
||||||
|
FakesAssemblies/
|
||||||
|
|
||||||
|
# GhostDoc plugin setting file
|
||||||
|
*.GhostDoc.xml
|
||||||
|
|
||||||
|
# Node.js Tools for Visual Studio
|
||||||
|
.ntvs_analysis.dat
|
||||||
|
node_modules/
|
||||||
|
|
||||||
|
# Visual Studio 6 build log
|
||||||
|
*.plg
|
||||||
|
|
||||||
|
# Visual Studio 6 workspace options file
|
||||||
|
*.opt
|
||||||
|
|
||||||
|
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
|
||||||
|
*.vbw
|
||||||
|
|
||||||
|
# Visual Studio LightSwitch build output
|
||||||
|
**/*.HTMLClient/GeneratedArtifacts
|
||||||
|
**/*.DesktopClient/GeneratedArtifacts
|
||||||
|
**/*.DesktopClient/ModelManifest.xml
|
||||||
|
**/*.Server/GeneratedArtifacts
|
||||||
|
**/*.Server/ModelManifest.xml
|
||||||
|
_Pvt_Extensions
|
||||||
|
|
||||||
|
# Paket dependency manager
|
||||||
|
.paket/paket.exe
|
||||||
|
paket-files/
|
||||||
|
|
||||||
|
# FAKE - F# Make
|
||||||
|
.fake/
|
||||||
|
|
||||||
|
# CodeRush personal settings
|
||||||
|
.cr/personal
|
||||||
|
|
||||||
|
# Python Tools for Visual Studio (PTVS)
|
||||||
|
__pycache__/
|
||||||
|
*.pyc
|
||||||
|
|
||||||
|
# Cake - Uncomment if you are using it
|
||||||
|
# tools/**
|
||||||
|
# !tools/packages.config
|
||||||
|
|
||||||
|
# Tabs Studio
|
||||||
|
*.tss
|
||||||
|
|
||||||
|
# Telerik's JustMock configuration file
|
||||||
|
*.jmconfig
|
||||||
|
|
||||||
|
# BizTalk build output
|
||||||
|
*.btp.cs
|
||||||
|
*.btm.cs
|
||||||
|
*.odx.cs
|
||||||
|
*.xsd.cs
|
||||||
|
|
||||||
|
# OpenCover UI analysis results
|
||||||
|
OpenCover/
|
||||||
|
|
||||||
|
# Azure Stream Analytics local run output
|
||||||
|
ASALocalRun/
|
||||||
|
|
||||||
|
# MSBuild Binary and Structured Log
|
||||||
|
*.binlog
|
||||||
|
|
||||||
|
# NVidia Nsight GPU debugger configuration file
|
||||||
|
*.nvuser
|
||||||
|
|
||||||
|
# MFractors (Xamarin productivity tool) working folder
|
||||||
|
.mfractor/
|
||||||
|
|
||||||
|
# Local History for Visual Studio
|
||||||
|
.localhistory/
|
||||||
|
|
||||||
|
# BeatPulse healthcheck temp database
|
||||||
|
healthchecksdb
|
||||||
|
|
||||||
|
# Backup folder for Package Reference Convert tool in Visual Studio 2017
|
||||||
|
MigrationBackup/
|
||||||
|
|
||||||
|
# End of https://www.gitignore.io/api/csharp
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
rem cd %1
|
||||||
|
git init
|
||||||
|
git remote add origin http://192.168.111.85:30000/shu/OpenDBDiff.git
|
||||||
|
git add .
|
||||||
|
git commit -m "Initial commit"
|
||||||
|
git push -u origin master
|
||||||
|
pause
|
||||||
@ -0,0 +1,339 @@
|
|||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
Version 2, June 1991
|
||||||
|
|
||||||
|
Copyright (C) 1989, 1991 Free Software Foundation, Inc., <http://fsf.org/>
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
Preamble
|
||||||
|
|
||||||
|
The licenses for most software are designed to take away your
|
||||||
|
freedom to share and change it. By contrast, the GNU General Public
|
||||||
|
License is intended to guarantee your freedom to share and change free
|
||||||
|
software--to make sure the software is free for all its users. This
|
||||||
|
General Public License applies to most of the Free Software
|
||||||
|
Foundation's software and to any other program whose authors commit to
|
||||||
|
using it. (Some other Free Software Foundation software is covered by
|
||||||
|
the GNU Lesser General Public License instead.) You can apply it to
|
||||||
|
your programs, too.
|
||||||
|
|
||||||
|
When we speak of free software, we are referring to freedom, not
|
||||||
|
price. Our General Public Licenses are designed to make sure that you
|
||||||
|
have the freedom to distribute copies of free software (and charge for
|
||||||
|
this service if you wish), that you receive source code or can get it
|
||||||
|
if you want it, that you can change the software or use pieces of it
|
||||||
|
in new free programs; and that you know you can do these things.
|
||||||
|
|
||||||
|
To protect your rights, we need to make restrictions that forbid
|
||||||
|
anyone to deny you these rights or to ask you to surrender the rights.
|
||||||
|
These restrictions translate to certain responsibilities for you if you
|
||||||
|
distribute copies of the software, or if you modify it.
|
||||||
|
|
||||||
|
For example, if you distribute copies of such a program, whether
|
||||||
|
gratis or for a fee, you must give the recipients all the rights that
|
||||||
|
you have. You must make sure that they, too, receive or can get the
|
||||||
|
source code. And you must show them these terms so they know their
|
||||||
|
rights.
|
||||||
|
|
||||||
|
We protect your rights with two steps: (1) copyright the software, and
|
||||||
|
(2) offer you this license which gives you legal permission to copy,
|
||||||
|
distribute and/or modify the software.
|
||||||
|
|
||||||
|
Also, for each author's protection and ours, we want to make certain
|
||||||
|
that everyone understands that there is no warranty for this free
|
||||||
|
software. If the software is modified by someone else and passed on, we
|
||||||
|
want its recipients to know that what they have is not the original, so
|
||||||
|
that any problems introduced by others will not reflect on the original
|
||||||
|
authors' reputations.
|
||||||
|
|
||||||
|
Finally, any free program is threatened constantly by software
|
||||||
|
patents. We wish to avoid the danger that redistributors of a free
|
||||||
|
program will individually obtain patent licenses, in effect making the
|
||||||
|
program proprietary. To prevent this, we have made it clear that any
|
||||||
|
patent must be licensed for everyone's free use or not licensed at all.
|
||||||
|
|
||||||
|
The precise terms and conditions for copying, distribution and
|
||||||
|
modification follow.
|
||||||
|
|
||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||||
|
|
||||||
|
0. This License applies to any program or other work which contains
|
||||||
|
a notice placed by the copyright holder saying it may be distributed
|
||||||
|
under the terms of this General Public License. The "Program", below,
|
||||||
|
refers to any such program or work, and a "work based on the Program"
|
||||||
|
means either the Program or any derivative work under copyright law:
|
||||||
|
that is to say, a work containing the Program or a portion of it,
|
||||||
|
either verbatim or with modifications and/or translated into another
|
||||||
|
language. (Hereinafter, translation is included without limitation in
|
||||||
|
the term "modification".) Each licensee is addressed as "you".
|
||||||
|
|
||||||
|
Activities other than copying, distribution and modification are not
|
||||||
|
covered by this License; they are outside its scope. The act of
|
||||||
|
running the Program is not restricted, and the output from the Program
|
||||||
|
is covered only if its contents constitute a work based on the
|
||||||
|
Program (independent of having been made by running the Program).
|
||||||
|
Whether that is true depends on what the Program does.
|
||||||
|
|
||||||
|
1. You may copy and distribute verbatim copies of the Program's
|
||||||
|
source code as you receive it, in any medium, provided that you
|
||||||
|
conspicuously and appropriately publish on each copy an appropriate
|
||||||
|
copyright notice and disclaimer of warranty; keep intact all the
|
||||||
|
notices that refer to this License and to the absence of any warranty;
|
||||||
|
and give any other recipients of the Program a copy of this License
|
||||||
|
along with the Program.
|
||||||
|
|
||||||
|
You may charge a fee for the physical act of transferring a copy, and
|
||||||
|
you may at your option offer warranty protection in exchange for a fee.
|
||||||
|
|
||||||
|
2. You may modify your copy or copies of the Program or any portion
|
||||||
|
of it, thus forming a work based on the Program, and copy and
|
||||||
|
distribute such modifications or work under the terms of Section 1
|
||||||
|
above, provided that you also meet all of these conditions:
|
||||||
|
|
||||||
|
a) You must cause the modified files to carry prominent notices
|
||||||
|
stating that you changed the files and the date of any change.
|
||||||
|
|
||||||
|
b) You must cause any work that you distribute or publish, that in
|
||||||
|
whole or in part contains or is derived from the Program or any
|
||||||
|
part thereof, to be licensed as a whole at no charge to all third
|
||||||
|
parties under the terms of this License.
|
||||||
|
|
||||||
|
c) If the modified program normally reads commands interactively
|
||||||
|
when run, you must cause it, when started running for such
|
||||||
|
interactive use in the most ordinary way, to print or display an
|
||||||
|
announcement including an appropriate copyright notice and a
|
||||||
|
notice that there is no warranty (or else, saying that you provide
|
||||||
|
a warranty) and that users may redistribute the program under
|
||||||
|
these conditions, and telling the user how to view a copy of this
|
||||||
|
License. (Exception: if the Program itself is interactive but
|
||||||
|
does not normally print such an announcement, your work based on
|
||||||
|
the Program is not required to print an announcement.)
|
||||||
|
|
||||||
|
These requirements apply to the modified work as a whole. If
|
||||||
|
identifiable sections of that work are not derived from the Program,
|
||||||
|
and can be reasonably considered independent and separate works in
|
||||||
|
themselves, then this License, and its terms, do not apply to those
|
||||||
|
sections when you distribute them as separate works. But when you
|
||||||
|
distribute the same sections as part of a whole which is a work based
|
||||||
|
on the Program, the distribution of the whole must be on the terms of
|
||||||
|
this License, whose permissions for other licensees extend to the
|
||||||
|
entire whole, and thus to each and every part regardless of who wrote it.
|
||||||
|
|
||||||
|
Thus, it is not the intent of this section to claim rights or contest
|
||||||
|
your rights to work written entirely by you; rather, the intent is to
|
||||||
|
exercise the right to control the distribution of derivative or
|
||||||
|
collective works based on the Program.
|
||||||
|
|
||||||
|
In addition, mere aggregation of another work not based on the Program
|
||||||
|
with the Program (or with a work based on the Program) on a volume of
|
||||||
|
a storage or distribution medium does not bring the other work under
|
||||||
|
the scope of this License.
|
||||||
|
|
||||||
|
3. You may copy and distribute the Program (or a work based on it,
|
||||||
|
under Section 2) in object code or executable form under the terms of
|
||||||
|
Sections 1 and 2 above provided that you also do one of the following:
|
||||||
|
|
||||||
|
a) Accompany it with the complete corresponding machine-readable
|
||||||
|
source code, which must be distributed under the terms of Sections
|
||||||
|
1 and 2 above on a medium customarily used for software interchange; or,
|
||||||
|
|
||||||
|
b) Accompany it with a written offer, valid for at least three
|
||||||
|
years, to give any third party, for a charge no more than your
|
||||||
|
cost of physically performing source distribution, a complete
|
||||||
|
machine-readable copy of the corresponding source code, to be
|
||||||
|
distributed under the terms of Sections 1 and 2 above on a medium
|
||||||
|
customarily used for software interchange; or,
|
||||||
|
|
||||||
|
c) Accompany it with the information you received as to the offer
|
||||||
|
to distribute corresponding source code. (This alternative is
|
||||||
|
allowed only for noncommercial distribution and only if you
|
||||||
|
received the program in object code or executable form with such
|
||||||
|
an offer, in accord with Subsection b above.)
|
||||||
|
|
||||||
|
The source code for a work means the preferred form of the work for
|
||||||
|
making modifications to it. For an executable work, complete source
|
||||||
|
code means all the source code for all modules it contains, plus any
|
||||||
|
associated interface definition files, plus the scripts used to
|
||||||
|
control compilation and installation of the executable. However, as a
|
||||||
|
special exception, the source code distributed need not include
|
||||||
|
anything that is normally distributed (in either source or binary
|
||||||
|
form) with the major components (compiler, kernel, and so on) of the
|
||||||
|
operating system on which the executable runs, unless that component
|
||||||
|
itself accompanies the executable.
|
||||||
|
|
||||||
|
If distribution of executable or object code is made by offering
|
||||||
|
access to copy from a designated place, then offering equivalent
|
||||||
|
access to copy the source code from the same place counts as
|
||||||
|
distribution of the source code, even though third parties are not
|
||||||
|
compelled to copy the source along with the object code.
|
||||||
|
|
||||||
|
4. You may not copy, modify, sublicense, or distribute the Program
|
||||||
|
except as expressly provided under this License. Any attempt
|
||||||
|
otherwise to copy, modify, sublicense or distribute the Program is
|
||||||
|
void, and will automatically terminate your rights under this License.
|
||||||
|
However, parties who have received copies, or rights, from you under
|
||||||
|
this License will not have their licenses terminated so long as such
|
||||||
|
parties remain in full compliance.
|
||||||
|
|
||||||
|
5. You are not required to accept this License, since you have not
|
||||||
|
signed it. However, nothing else grants you permission to modify or
|
||||||
|
distribute the Program or its derivative works. These actions are
|
||||||
|
prohibited by law if you do not accept this License. Therefore, by
|
||||||
|
modifying or distributing the Program (or any work based on the
|
||||||
|
Program), you indicate your acceptance of this License to do so, and
|
||||||
|
all its terms and conditions for copying, distributing or modifying
|
||||||
|
the Program or works based on it.
|
||||||
|
|
||||||
|
6. Each time you redistribute the Program (or any work based on the
|
||||||
|
Program), the recipient automatically receives a license from the
|
||||||
|
original licensor to copy, distribute or modify the Program subject to
|
||||||
|
these terms and conditions. You may not impose any further
|
||||||
|
restrictions on the recipients' exercise of the rights granted herein.
|
||||||
|
You are not responsible for enforcing compliance by third parties to
|
||||||
|
this License.
|
||||||
|
|
||||||
|
7. If, as a consequence of a court judgment or allegation of patent
|
||||||
|
infringement or for any other reason (not limited to patent issues),
|
||||||
|
conditions are imposed on you (whether by court order, agreement or
|
||||||
|
otherwise) that contradict the conditions of this License, they do not
|
||||||
|
excuse you from the conditions of this License. If you cannot
|
||||||
|
distribute so as to satisfy simultaneously your obligations under this
|
||||||
|
License and any other pertinent obligations, then as a consequence you
|
||||||
|
may not distribute the Program at all. For example, if a patent
|
||||||
|
license would not permit royalty-free redistribution of the Program by
|
||||||
|
all those who receive copies directly or indirectly through you, then
|
||||||
|
the only way you could satisfy both it and this License would be to
|
||||||
|
refrain entirely from distribution of the Program.
|
||||||
|
|
||||||
|
If any portion of this section is held invalid or unenforceable under
|
||||||
|
any particular circumstance, the balance of the section is intended to
|
||||||
|
apply and the section as a whole is intended to apply in other
|
||||||
|
circumstances.
|
||||||
|
|
||||||
|
It is not the purpose of this section to induce you to infringe any
|
||||||
|
patents or other property right claims or to contest validity of any
|
||||||
|
such claims; this section has the sole purpose of protecting the
|
||||||
|
integrity of the free software distribution system, which is
|
||||||
|
implemented by public license practices. Many people have made
|
||||||
|
generous contributions to the wide range of software distributed
|
||||||
|
through that system in reliance on consistent application of that
|
||||||
|
system; it is up to the author/donor to decide if he or she is willing
|
||||||
|
to distribute software through any other system and a licensee cannot
|
||||||
|
impose that choice.
|
||||||
|
|
||||||
|
This section is intended to make thoroughly clear what is believed to
|
||||||
|
be a consequence of the rest of this License.
|
||||||
|
|
||||||
|
8. If the distribution and/or use of the Program is restricted in
|
||||||
|
certain countries either by patents or by copyrighted interfaces, the
|
||||||
|
original copyright holder who places the Program under this License
|
||||||
|
may add an explicit geographical distribution limitation excluding
|
||||||
|
those countries, so that distribution is permitted only in or among
|
||||||
|
countries not thus excluded. In such case, this License incorporates
|
||||||
|
the limitation as if written in the body of this License.
|
||||||
|
|
||||||
|
9. The Free Software Foundation may publish revised and/or new versions
|
||||||
|
of the General Public License from time to time. Such new versions will
|
||||||
|
be similar in spirit to the present version, but may differ in detail to
|
||||||
|
address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the Program
|
||||||
|
specifies a version number of this License which applies to it and "any
|
||||||
|
later version", you have the option of following the terms and conditions
|
||||||
|
either of that version or of any later version published by the Free
|
||||||
|
Software Foundation. If the Program does not specify a version number of
|
||||||
|
this License, you may choose any version ever published by the Free Software
|
||||||
|
Foundation.
|
||||||
|
|
||||||
|
10. If you wish to incorporate parts of the Program into other free
|
||||||
|
programs whose distribution conditions are different, write to the author
|
||||||
|
to ask for permission. For software which is copyrighted by the Free
|
||||||
|
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||||
|
make exceptions for this. Our decision will be guided by the two goals
|
||||||
|
of preserving the free status of all derivatives of our free software and
|
||||||
|
of promoting the sharing and reuse of software generally.
|
||||||
|
|
||||||
|
NO WARRANTY
|
||||||
|
|
||||||
|
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||||
|
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||||
|
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||||
|
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||||
|
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||||
|
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||||
|
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||||
|
REPAIR OR CORRECTION.
|
||||||
|
|
||||||
|
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||||
|
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||||
|
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||||
|
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||||
|
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||||
|
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||||
|
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||||
|
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGES.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
How to Apply These Terms to Your New Programs
|
||||||
|
|
||||||
|
If you develop a new program, and you want it to be of the greatest
|
||||||
|
possible use to the public, the best way to achieve this is to make it
|
||||||
|
free software which everyone can redistribute and change under these terms.
|
||||||
|
|
||||||
|
To do so, attach the following notices to the program. It is safest
|
||||||
|
to attach them to the start of each source file to most effectively
|
||||||
|
convey the exclusion of warranty; and each file should have at least
|
||||||
|
the "copyright" line and a pointer to where the full notice is found.
|
||||||
|
|
||||||
|
{description}
|
||||||
|
Copyright (C) {year} {fullname}
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License along
|
||||||
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
|
||||||
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
|
If the program is interactive, make it output a short notice like this
|
||||||
|
when it starts in an interactive mode:
|
||||||
|
|
||||||
|
Gnomovision version 69, Copyright (C) year name of author
|
||||||
|
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||||
|
This is free software, and you are welcome to redistribute it
|
||||||
|
under certain conditions; type `show c' for details.
|
||||||
|
|
||||||
|
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||||
|
parts of the General Public License. Of course, the commands you use may
|
||||||
|
be called something other than `show w' and `show c'; they could even be
|
||||||
|
mouse-clicks or menu items--whatever suits your program.
|
||||||
|
|
||||||
|
You should also get your employer (if you work as a programmer) or your
|
||||||
|
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||||
|
necessary. Here is a sample; alter the names:
|
||||||
|
|
||||||
|
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||||
|
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||||
|
|
||||||
|
{signature of Ty Coon}, 1 April 1989
|
||||||
|
Ty Coon, President of Vice
|
||||||
|
|
||||||
|
This General Public License does not permit incorporating your program into
|
||||||
|
proprietary programs. If your program is a subroutine library, you may
|
||||||
|
consider it more useful to permit linking proprietary applications with the
|
||||||
|
library. If this is what you want to do, use the GNU Lesser General
|
||||||
|
Public License instead of this License.
|
||||||
@ -0,0 +1,33 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace OpenDBDiff.Abstractions.Schema.Attributes
|
||||||
|
{
|
||||||
|
[AttributeUsage(AttributeTargets.Property, AllowMultiple = true)]
|
||||||
|
public sealed class SchemaNodeAttribute : Attribute
|
||||||
|
{
|
||||||
|
public SchemaNodeAttribute(string name)
|
||||||
|
{
|
||||||
|
this.Name = name;
|
||||||
|
this.Image = "Folder";
|
||||||
|
}
|
||||||
|
|
||||||
|
public SchemaNodeAttribute(string name, string image)
|
||||||
|
{
|
||||||
|
this.Name = name;
|
||||||
|
this.Image = image;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SchemaNodeAttribute(string name, string image, Boolean isFullName)
|
||||||
|
{
|
||||||
|
this.Name = name;
|
||||||
|
this.Image = image;
|
||||||
|
this.IsFullName = isFullName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Name { get; private set; }
|
||||||
|
|
||||||
|
public string Image { get; private set; }
|
||||||
|
|
||||||
|
public Boolean IsFullName { get; private set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,17 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace OpenDBDiff.Abstractions.Schema.Events
|
||||||
|
{
|
||||||
|
public class ProgressEventArgs : EventArgs
|
||||||
|
{
|
||||||
|
public string Message { get; set; }
|
||||||
|
|
||||||
|
public ProgressEventArgs(string message, int progress)
|
||||||
|
{
|
||||||
|
this.Progress = progress;
|
||||||
|
this.Message = message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Progress { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,14 @@
|
|||||||
|
namespace OpenDBDiff.Abstractions.Schema.Events
|
||||||
|
{
|
||||||
|
public class ProgressEventHandler
|
||||||
|
{
|
||||||
|
public delegate void ProgressHandler(ProgressEventArgs e);
|
||||||
|
|
||||||
|
public static event ProgressHandler OnProgress;
|
||||||
|
|
||||||
|
public static void RaiseOnChange(ProgressEventArgs e)
|
||||||
|
{
|
||||||
|
if (OnProgress != null) OnProgress(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,31 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace OpenDBDiff.Abstractions.Schema.Model
|
||||||
|
{
|
||||||
|
public interface ISchemaBase
|
||||||
|
{
|
||||||
|
ISchemaBase Clone(ISchemaBase parent);
|
||||||
|
int DependenciesCount { get; }
|
||||||
|
string FullName { get; }
|
||||||
|
int Id { get; set; }
|
||||||
|
Boolean HasState(ObjectStatus statusFind);
|
||||||
|
string Name { get; set; }
|
||||||
|
string Owner { get; set; }
|
||||||
|
ISchemaBase Parent { get; set; }
|
||||||
|
ObjectStatus Status { get; set; }
|
||||||
|
Boolean IsSystem { get; set; }
|
||||||
|
ObjectType ObjectType { get; set; }
|
||||||
|
Boolean GetWasInsertInDiffList(ScriptAction action);
|
||||||
|
void SetWasInsertInDiffList(ScriptAction action);
|
||||||
|
void ResetWasInsertInDiffList();
|
||||||
|
string ToSqlDrop();
|
||||||
|
string ToSqlAdd();
|
||||||
|
string ToSql();
|
||||||
|
SQLScriptList ToSqlDiff(System.Collections.Generic.ICollection<ISchemaBase> schemas);
|
||||||
|
SQLScript Create();
|
||||||
|
SQLScript Drop();
|
||||||
|
int CompareFullNameTo(string name, string myName);
|
||||||
|
Boolean IsCodeType { get; }
|
||||||
|
IDatabase RootParent { get; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,286 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
|
namespace OpenDBDiff.Abstractions.Schema.Model
|
||||||
|
{
|
||||||
|
[DebuggerDisplay("Id: {Id} - Name: {Name} - Status: {status}")]
|
||||||
|
public abstract class SchemaBase : ISchemaBase
|
||||||
|
{
|
||||||
|
private ObjectStatus status;
|
||||||
|
private ISchemaBase parent;
|
||||||
|
private string nameCharacterOpen;
|
||||||
|
private string nameCharacterClose;
|
||||||
|
private Hashtable wasInsertInDiffList;
|
||||||
|
private IDatabase rootParent = null;
|
||||||
|
|
||||||
|
protected SchemaBase(string nameCharacterOpen, string nameCharacterClose, ObjectType objectType)
|
||||||
|
{
|
||||||
|
this.Guid = System.Guid.NewGuid().ToString();
|
||||||
|
this.ObjectType = objectType;
|
||||||
|
this.status = ObjectStatus.Original;
|
||||||
|
this.nameCharacterClose = nameCharacterClose;
|
||||||
|
this.nameCharacterOpen = nameCharacterOpen;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*protected object Clone(object vObj, ISchemaBase parentObject)
|
||||||
|
{
|
||||||
|
if (vObj.GetType().IsValueType || vObj.GetType() == Type.GetType("System.String"))
|
||||||
|
return vObj;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
object newObject = Activator.CreateInstance(vObj.GetType(), new object[] {parentObject });
|
||||||
|
foreach (PropertyInfo Item in newObject.GetType().GetProperties())
|
||||||
|
{
|
||||||
|
if (Item.GetType().GetInterface("ICloneable") != null)
|
||||||
|
{
|
||||||
|
ICloneable IClone = (ICloneable)Item.GetValue(vObj, null);
|
||||||
|
Item.SetValue(newObject, IClone.Clone(), null);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Item.SetValue(newObject, Clone(Item.GetValue(vObj, null),parentObject), null);
|
||||||
|
}
|
||||||
|
foreach (FieldInfo Item in newObject.GetType().GetFields())
|
||||||
|
{
|
||||||
|
if (Item.GetType().GetInterface("ICloneable") != null)
|
||||||
|
{
|
||||||
|
ICloneable IClone = (ICloneable)Item.GetValue(vObj);
|
||||||
|
Item.SetValue(newObject, IClone.Clone());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Item.SetValue(newObject, Clone(Item.GetValue(vObj),parentObject));
|
||||||
|
}
|
||||||
|
return newObject;
|
||||||
|
}
|
||||||
|
} */
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Instance's parent object
|
||||||
|
/// </summary>
|
||||||
|
public ISchemaBase Parent
|
||||||
|
{
|
||||||
|
get { return parent; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
rootParent = null;
|
||||||
|
parent = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public IDatabase RootParent
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (rootParent != null) return rootParent;
|
||||||
|
if (this.Parent != null)
|
||||||
|
{
|
||||||
|
if (this.Parent.Parent != null)
|
||||||
|
if (this.Parent.Parent.Parent != null)
|
||||||
|
rootParent = (IDatabase)this.Parent.Parent.Parent;
|
||||||
|
else
|
||||||
|
rootParent = (IDatabase)this.Parent.Parent;
|
||||||
|
else
|
||||||
|
rootParent = (IDatabase)this.Parent;
|
||||||
|
}
|
||||||
|
else if (this is IDatabase)
|
||||||
|
{
|
||||||
|
rootParent = (IDatabase)this;
|
||||||
|
}
|
||||||
|
return rootParent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int CompareFullNameTo(string name, string myName)
|
||||||
|
{
|
||||||
|
if (!RootParent.IsCaseSensitive)
|
||||||
|
return myName.ToUpper().CompareTo(name.ToUpper());
|
||||||
|
else
|
||||||
|
return myName.CompareTo(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// SQL Code for the database object
|
||||||
|
/// </summary>
|
||||||
|
public abstract string ToSql();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// SQL Code for drop the database object
|
||||||
|
/// </summary>
|
||||||
|
public abstract string ToSqlDrop();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// SQL Code for add the database object
|
||||||
|
/// </summary>
|
||||||
|
public abstract string ToSqlAdd();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Deep clone the object
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="parent">Parent of the object</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public virtual ISchemaBase Clone(ISchemaBase parent)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the list of SQL Scripts to execute to sync for the specified schemas
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>
|
||||||
|
/// A list (<see cref="SQLScriptList"/>) of scripts to run to sync
|
||||||
|
/// </returns>
|
||||||
|
public virtual SQLScriptList ToSqlDiff(ICollection<ISchemaBase> schemas)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual SQLScript Create()
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual SQLScript Drop()
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns if the obecet was already inserted in the list of scripts with differencies
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="action">The action to check in the list</param>
|
||||||
|
/// <returns>True if is already inserted. False if it wasn't</returns>
|
||||||
|
public Boolean GetWasInsertInDiffList(ScriptAction action)
|
||||||
|
{
|
||||||
|
if (wasInsertInDiffList != null)
|
||||||
|
return (wasInsertInDiffList.ContainsKey(action));
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets the object as inserted in the list of differences script
|
||||||
|
/// </summary>
|
||||||
|
public void SetWasInsertInDiffList(ScriptAction action)
|
||||||
|
{
|
||||||
|
if (wasInsertInDiffList == null) wasInsertInDiffList = new Hashtable();
|
||||||
|
if (!wasInsertInDiffList.ContainsKey(action))
|
||||||
|
wasInsertInDiffList.Add(action, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ResetWasInsertInDiffList()
|
||||||
|
{
|
||||||
|
this.wasInsertInDiffList = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Unique GUID identifying the object
|
||||||
|
/// </summary>
|
||||||
|
public string Guid { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Object type. <seealso cref="ObjectType"/>
|
||||||
|
/// </summary>
|
||||||
|
public ObjectType ObjectType { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ID del objeto.
|
||||||
|
/// </summary>
|
||||||
|
public int Id { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Nombre completo del objeto, incluyendo el owner.
|
||||||
|
/// </summary>
|
||||||
|
public virtual string FullName
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (String.IsNullOrEmpty(Owner))
|
||||||
|
return nameCharacterOpen + Name + nameCharacterClose;
|
||||||
|
else
|
||||||
|
return nameCharacterOpen + Owner + nameCharacterClose + "." + nameCharacterOpen + Name + nameCharacterClose;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Username of the owner of the object
|
||||||
|
/// </summary>
|
||||||
|
public string Owner { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Nombre of the object
|
||||||
|
/// </summary>
|
||||||
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Determine if the database object if a System object or not
|
||||||
|
/// </summary>
|
||||||
|
public Boolean IsSystem { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the status of the object. By default is set to <see cref="ObjectStatus.Original"/>. When setting a value, it also affects to the <see cref="Parent"/> status.
|
||||||
|
/// </summary>
|
||||||
|
public virtual ObjectStatus Status
|
||||||
|
{
|
||||||
|
get { return status; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (status != ObjectStatus.Rebuild && status != ObjectStatus.RebuildDependencies)
|
||||||
|
status = value;
|
||||||
|
|
||||||
|
if (Parent == null) return;
|
||||||
|
|
||||||
|
// Si el estado de la tabla era el original, lo cambia, sino deja el actual estado.
|
||||||
|
// If the state of the table was the original, it changes it, but leaves the current state. (Google translated)
|
||||||
|
if (Parent.Status == ObjectStatus.Original
|
||||||
|
|| value == ObjectStatus.Rebuild
|
||||||
|
|| value == ObjectStatus.RebuildDependencies)
|
||||||
|
{
|
||||||
|
switch (value)
|
||||||
|
{
|
||||||
|
case ObjectStatus.RebuildDependencies:
|
||||||
|
case ObjectStatus.Rebuild:
|
||||||
|
Parent.Status = value;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ObjectStatus.Original:
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
Parent.Status = ObjectStatus.Alter;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean HasState(ObjectStatus statusFind)
|
||||||
|
{
|
||||||
|
return ((this.Status & statusFind) == statusFind);
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual Boolean IsCodeType
|
||||||
|
{
|
||||||
|
get { return false; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual int DependenciesCount
|
||||||
|
{
|
||||||
|
get { return 0; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual bool HasDependencies
|
||||||
|
{
|
||||||
|
get { return DependenciesCount > 0; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get if the SQL commands for the collection must build in one single statement
|
||||||
|
/// or one statmente for each item of the collection.
|
||||||
|
/// </summary>
|
||||||
|
public virtual Boolean MustBuildSqlInLine
|
||||||
|
{
|
||||||
|
get { return false; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,146 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace OpenDBDiff.Abstractions.Schema.Model
|
||||||
|
{
|
||||||
|
public class SchemaList<T, P> : List<T>, ISchemaList<T, P>
|
||||||
|
where T : ISchemaBase
|
||||||
|
where P : ISchemaBase
|
||||||
|
{
|
||||||
|
private Dictionary<string, int> nameMap = new Dictionary<string, int>();
|
||||||
|
private SearchSchemaBase allObjects = null;
|
||||||
|
private bool IsCaseSensitive = false;
|
||||||
|
|
||||||
|
public SchemaList(P parent, SearchSchemaBase allObjects)
|
||||||
|
{
|
||||||
|
this.Parent = parent;
|
||||||
|
this.allObjects = allObjects;
|
||||||
|
this.Comparion = StringComparison.CurrentCultureIgnoreCase;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SchemaList<T, P> Clone(P parentObject)
|
||||||
|
{
|
||||||
|
SchemaList<T, P> options = new SchemaList<T, P>(parentObject, allObjects);
|
||||||
|
this.ForEach(item =>
|
||||||
|
{
|
||||||
|
object cloned = item.Clone(parentObject);
|
||||||
|
|
||||||
|
//Not everything implements the clone methd, so make sure we got some actual cloned data before adding it back to the list
|
||||||
|
if (cloned != null)
|
||||||
|
options.Add((T)cloned);
|
||||||
|
});
|
||||||
|
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected StringComparison Comparion { get; private set; }
|
||||||
|
|
||||||
|
public SchemaList(P parent)
|
||||||
|
{
|
||||||
|
this.Parent = parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public new void Add(T item)
|
||||||
|
{
|
||||||
|
var db = this.Parent.RootParent;
|
||||||
|
if (!db.Options.Filters.IsItemIncluded(item))
|
||||||
|
return;
|
||||||
|
|
||||||
|
base.Add(item);
|
||||||
|
if (allObjects != null)
|
||||||
|
allObjects.Add(item);
|
||||||
|
|
||||||
|
string name = item.FullName;
|
||||||
|
IsCaseSensitive = item.RootParent.IsCaseSensitive;
|
||||||
|
if (!IsCaseSensitive)
|
||||||
|
name = name.ToUpper();
|
||||||
|
|
||||||
|
if (!nameMap.ContainsKey(name))
|
||||||
|
nameMap.Add(name, base.Count - 1);
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Devuelve el objecto Padre perteneciente a la coleccion.
|
||||||
|
/// </summary>
|
||||||
|
public P Parent { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Devuelve el objeto correspondiente a un ID especifico.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="id">ID del objecto a buscar</param>
|
||||||
|
/// <returns>Si no encontro nada, devuelve null, de lo contrario, el objeto</returns>
|
||||||
|
public T Find(int id)
|
||||||
|
{
|
||||||
|
return Find(Item => Item.Id == id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indica si el nombre del objecto existe en la coleccion de objectos del mismo tipo.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="table">
|
||||||
|
/// Nombre del objecto a buscar.
|
||||||
|
/// </param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public Boolean Contains(string name)
|
||||||
|
{
|
||||||
|
if (IsCaseSensitive)
|
||||||
|
return nameMap.ContainsKey(name);
|
||||||
|
else
|
||||||
|
return nameMap.ContainsKey(name.ToUpper());
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual T this[string name]
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (IsCaseSensitive)
|
||||||
|
return this[nameMap[name]];
|
||||||
|
else
|
||||||
|
return this[nameMap[name.ToUpper()]];
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return default(T);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (IsCaseSensitive)
|
||||||
|
base[nameMap[name]] = value;
|
||||||
|
else
|
||||||
|
base[nameMap[name.ToUpper()]] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual SQLScriptList ToSqlDiff()
|
||||||
|
{
|
||||||
|
return ToSqlDiff(new List<ISchemaBase>());
|
||||||
|
}
|
||||||
|
public virtual SQLScriptList ToSqlDiff(ICollection<ISchemaBase> schemas)
|
||||||
|
{
|
||||||
|
SQLScriptList listDiff = new SQLScriptList();
|
||||||
|
foreach (var item in this.Where(item => (schemas.Count() == 0 || schemas.FirstOrDefault(sch => sch.Id == item.Id || (sch.Parent != null && sch.Parent.Id == item.Id)) != default(ISchemaBase))))
|
||||||
|
{
|
||||||
|
item.ResetWasInsertInDiffList();
|
||||||
|
var childrenSchemas = schemas.Where(s => s.Parent != null && s.Parent.Id == item.Id).ToList();
|
||||||
|
listDiff.AddRange(item.ToSqlDiff(childrenSchemas).WarnMissingScript(item));
|
||||||
|
}
|
||||||
|
return listDiff;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public virtual string ToSql()
|
||||||
|
{
|
||||||
|
return string.Join
|
||||||
|
(
|
||||||
|
"\r\n",
|
||||||
|
this
|
||||||
|
.Where(item => !item.HasState(ObjectStatus.Drop))
|
||||||
|
.Select(item => item.ToSql())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,72 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace OpenDBDiff.Abstractions.Schema
|
||||||
|
{
|
||||||
|
public class SQLScript : IComparable<SQLScript>
|
||||||
|
{
|
||||||
|
public SQLScript(int deepvalue, string sqlScript, int dependenciesCount, ScriptAction action)
|
||||||
|
{
|
||||||
|
SQL = sqlScript;
|
||||||
|
Dependencies = dependenciesCount;
|
||||||
|
Status = action;
|
||||||
|
Deep = deepvalue;
|
||||||
|
//childs = new SQLScriptList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public SQLScript(string sqlScript, int dependenciesCount, ScriptAction action)
|
||||||
|
{
|
||||||
|
SQL = sqlScript;
|
||||||
|
Dependencies = dependenciesCount;
|
||||||
|
Status = action;
|
||||||
|
//childs = new SQLScriptList();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*public SQLScriptList Childs
|
||||||
|
{
|
||||||
|
get { return childs; }
|
||||||
|
set { childs = value; }
|
||||||
|
}*/
|
||||||
|
|
||||||
|
public int Deep { get; set; }
|
||||||
|
|
||||||
|
public ScriptAction Status { get; set; }
|
||||||
|
|
||||||
|
public int Dependencies { get; set; }
|
||||||
|
|
||||||
|
public string SQL { get; set; }
|
||||||
|
|
||||||
|
public bool IsDropAction
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return ((Status == ScriptAction.DropView) || (Status == ScriptAction.DropFunction) || (Status == ScriptAction.DropStoredProcedure));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsAddAction
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return ((Status == ScriptAction.AddView) || (Status == ScriptAction.AddFunction) || (Status == ScriptAction.AddStoredProcedure));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int CompareTo(SQLScript other)
|
||||||
|
{
|
||||||
|
if (this.Deep == other.Deep)
|
||||||
|
{
|
||||||
|
if (this.Status == other.Status)
|
||||||
|
{
|
||||||
|
if (this.Status == ScriptAction.DropTable || this.Status == ScriptAction.DropConstraint || this.Status == ScriptAction.DropTrigger)
|
||||||
|
return other.Dependencies.CompareTo(this.Dependencies);
|
||||||
|
else
|
||||||
|
return this.Dependencies.CompareTo(other.Dependencies);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return this.Status.CompareTo(other.Status);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return this.Deep.CompareTo(other.Deep);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,135 @@
|
|||||||
|
using OpenDBDiff.Abstractions.Schema.Model;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace OpenDBDiff.Abstractions.Schema
|
||||||
|
{
|
||||||
|
public class SQLScriptList
|
||||||
|
{
|
||||||
|
private List<SQLScript> list;
|
||||||
|
|
||||||
|
public void Sort()
|
||||||
|
{
|
||||||
|
if (list != null) list.Sort();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Add(SQLScript item, int deep)
|
||||||
|
{
|
||||||
|
if (list == null) list = new List<SQLScript>();
|
||||||
|
if (item != null)
|
||||||
|
{
|
||||||
|
item.Deep = deep;
|
||||||
|
list.Add(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Add(SQLScript item)
|
||||||
|
{
|
||||||
|
if (list == null) list = new List<SQLScript>();
|
||||||
|
if (item != null) list.Add(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Add(string SQL, int dependencies, ScriptAction type)
|
||||||
|
{
|
||||||
|
if (list == null) list = new List<SQLScript>();
|
||||||
|
list.Add(new SQLScript(SQL, dependencies, type));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddRange(SQLScriptList items)
|
||||||
|
{
|
||||||
|
for (int j = 0; j < items.Count; j++)
|
||||||
|
{
|
||||||
|
if (list == null) list = new List<SQLScript>();
|
||||||
|
list.Add(items[j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Count
|
||||||
|
{
|
||||||
|
get { return (list == null) ? 0 : list.Count; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public SQLScript this[int index]
|
||||||
|
{
|
||||||
|
get { return list[index]; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/*private string ToSqlDown(SQLScript item)
|
||||||
|
{
|
||||||
|
string sql = "";
|
||||||
|
for (int i = 0; i < item.Childs.Count; i++)
|
||||||
|
{
|
||||||
|
for (int k = 0; k < item.Childs[i].Childs.Count; k++)
|
||||||
|
{
|
||||||
|
for (int h = 0; h < item.Childs[i].Childs[k].Childs.Count; h++)
|
||||||
|
{
|
||||||
|
for (int l = 0; l < item.Childs[i].Childs[k].Childs[h].Childs.Count; l++)
|
||||||
|
{
|
||||||
|
for (int m = 0; m < item.Childs[i].Childs[k].Childs[h].Childs[l].Childs.Count; m++)
|
||||||
|
{
|
||||||
|
sql += item.Childs[i].Childs[k].Childs[h].Childs[l].Childs[m].SQL;
|
||||||
|
}
|
||||||
|
sql += item.Childs[i].Childs[k].Childs[h].Childs[l].SQL;
|
||||||
|
}
|
||||||
|
sql += item.Childs[i].Childs[k].Childs[h].SQL;
|
||||||
|
}
|
||||||
|
sql += item.Childs[i].Childs[k].SQL;
|
||||||
|
}
|
||||||
|
sql += item.Childs[i].SQL;
|
||||||
|
}
|
||||||
|
sql += item.SQL;
|
||||||
|
return sql;
|
||||||
|
}*/
|
||||||
|
|
||||||
|
public string ToSQL()
|
||||||
|
{
|
||||||
|
StringBuilder sql = new StringBuilder();
|
||||||
|
this.Sort(); /*Ordena la lista antes de generar el script*/
|
||||||
|
if (list != null)
|
||||||
|
{
|
||||||
|
for (int j = 0; j < list.Count; j++)
|
||||||
|
{
|
||||||
|
//if ((list[j].IsDropAction) || (!list[j].IsAddAction))
|
||||||
|
sql.Append(list[j].SQL); //ToSqlDown(list[j]);
|
||||||
|
}
|
||||||
|
/*for (int j = list.Count-1; j >= 0; j--)
|
||||||
|
{
|
||||||
|
if (list[j].IsAddAction)
|
||||||
|
sql.Append(list[j].SQL);
|
||||||
|
}*/
|
||||||
|
|
||||||
|
}
|
||||||
|
return sql.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public SQLScriptList FindAlter()
|
||||||
|
{
|
||||||
|
SQLScriptList alter = new SQLScriptList();
|
||||||
|
list.ForEach(item => { if ((item.Status == ScriptAction.AlterView) || (item.Status == ScriptAction.AlterFunction) || (item.Status == ScriptAction.AlterProcedure)) alter.Add(item); });
|
||||||
|
return alter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class SQLScriptListExtensionMethod
|
||||||
|
{
|
||||||
|
public static SQLScriptList WarnMissingScript(this SQLScriptList scriptList, ISchemaBase scriptSource)
|
||||||
|
{
|
||||||
|
if (scriptList == null || scriptSource == null || scriptSource.Status == ObjectStatus.Original)
|
||||||
|
{
|
||||||
|
return scriptList;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < scriptList.Count; ++i)
|
||||||
|
{
|
||||||
|
if (!String.IsNullOrEmpty(scriptList[i].SQL))
|
||||||
|
{
|
||||||
|
return scriptList;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
scriptList.Add(String.Format("\r\n--\r\n-- DIFF-ERROR 0x{0:x8}.{1:d3}: Missing {2} script for {3} '{4}'\r\n--\r\n\r\n", (int)scriptSource.Status, (int)scriptSource.ObjectType, scriptSource.Status, scriptSource.ObjectType, scriptSource.Name), 0, ScriptAction.None);
|
||||||
|
return scriptList;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,231 @@
|
|||||||
|
using System;
|
||||||
|
using System.ComponentModel;
|
||||||
|
|
||||||
|
namespace OpenDBDiff.Abstractions.Schema
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Original = The object has no modifications.
|
||||||
|
/// Create = The object must be created.
|
||||||
|
/// Drop = The object must be deleted.
|
||||||
|
/// Alter = The object has modifications.
|
||||||
|
/// AlterRebuild = The object has modifications, but a DROP and ADD must be done too.
|
||||||
|
/// AlterProperties = The object has modifications in its properties, but not in its structure.
|
||||||
|
/// </summary>
|
||||||
|
[Flags]
|
||||||
|
public enum ObjectStatus
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The object is unaltered
|
||||||
|
/// </summary>
|
||||||
|
Original = 0,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The object was altered
|
||||||
|
/// </summary>
|
||||||
|
Alter = 2,
|
||||||
|
|
||||||
|
AlterBody = 4,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The object was altered but requires a rebuild
|
||||||
|
/// </summary>
|
||||||
|
Rebuild = 8,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The object has properties altered, but not in it's structure
|
||||||
|
/// </summary>
|
||||||
|
RebuildDependencies = 16,
|
||||||
|
|
||||||
|
Update = 32,
|
||||||
|
Create = 64,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The object should be dropped
|
||||||
|
/// </summary>
|
||||||
|
Drop = 128,
|
||||||
|
|
||||||
|
Disabled = 256,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The owner of the object changed
|
||||||
|
/// </summary>
|
||||||
|
ChangeOwner = 512,
|
||||||
|
|
||||||
|
DropOlder = 1024,
|
||||||
|
Bind = 2048,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The permission set of the object changed
|
||||||
|
/// </summary>
|
||||||
|
PermissionSet = 4096,
|
||||||
|
|
||||||
|
AlterWhitespace = 8192
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum ScriptAction
|
||||||
|
{
|
||||||
|
None = 0,
|
||||||
|
UseDatabase = 1,
|
||||||
|
AddFileGroup = 2,
|
||||||
|
AddFile = 3,
|
||||||
|
AlterFile = 4,
|
||||||
|
AlterFileGroup = 5,
|
||||||
|
UnbindRuleColumn = 6,
|
||||||
|
UnbindRuleType = 7,
|
||||||
|
DropRule = 8,
|
||||||
|
AddRule = 9,
|
||||||
|
|
||||||
|
DropFullTextIndex = 10,
|
||||||
|
DropConstraintFK = 11,
|
||||||
|
DropConstraint = 12,
|
||||||
|
DropConstraintPK = 13,
|
||||||
|
DropSynonyms = 14,
|
||||||
|
DropStoredProcedure = 15,
|
||||||
|
DropTrigger = 16,
|
||||||
|
DropView = 17,
|
||||||
|
DropFunction = 17,
|
||||||
|
DropIndex = 18,
|
||||||
|
DropTable = 20,
|
||||||
|
AlterColumnFormula = 21,
|
||||||
|
AlterColumn = 22,
|
||||||
|
AddRole = 23,
|
||||||
|
AddUser = 24,
|
||||||
|
AddSchema = 25,
|
||||||
|
AddDefault = 26,
|
||||||
|
AddAssembly = 27,
|
||||||
|
AddAssemblyFile = 28,
|
||||||
|
AddUserDataType = 29,
|
||||||
|
AddTableType = 30,
|
||||||
|
AlterPartitionFunction = 31,
|
||||||
|
AddPartitionFunction = 32,
|
||||||
|
AddPartitionScheme = 33,
|
||||||
|
AddFullText = 34,
|
||||||
|
AddXMLSchema = 35,
|
||||||
|
AlterAssembly = 36,
|
||||||
|
UpdateTable = 37,
|
||||||
|
AlterTable = 38,
|
||||||
|
AlterIndex = 39,
|
||||||
|
AlterFullTextIndex = 40,
|
||||||
|
AddTable = 41,
|
||||||
|
RebuildTable = 42,
|
||||||
|
AlterColumnRestore = 43,
|
||||||
|
AlterColumnFormulaRestore = 44,
|
||||||
|
AlterFunction = 45,
|
||||||
|
AlterView = 46,
|
||||||
|
AlterProcedure = 47,
|
||||||
|
AddIndex = 48,
|
||||||
|
AddFunction = 49,
|
||||||
|
AddView = 49, /*AddFunction and AddView must have the same number!!!*/
|
||||||
|
AddTrigger = 50,
|
||||||
|
AddConstraint = 51,
|
||||||
|
AddConstraintPK = 52,
|
||||||
|
AddConstraintFK = 53,
|
||||||
|
AlterConstraint = 54,
|
||||||
|
AddFullTextIndex = 55,
|
||||||
|
EnabledTrigger = 56,
|
||||||
|
AddSynonyms = 57,
|
||||||
|
AddStoredProcedure = 58,
|
||||||
|
DropOptions = 59,
|
||||||
|
AddOptions = 60,
|
||||||
|
|
||||||
|
AlterTableChangeTracking = 61,
|
||||||
|
|
||||||
|
DropFullText = 62,
|
||||||
|
DropTableType = 63,
|
||||||
|
DropUserDataType = 64,
|
||||||
|
DropXMLSchema = 65,
|
||||||
|
DropAssemblyUserDataType = 66,
|
||||||
|
DropAssemblyFile = 67,
|
||||||
|
DropAssembly = 68,
|
||||||
|
DropDefault = 69,
|
||||||
|
|
||||||
|
DropPartitionScheme = 70,
|
||||||
|
DropPartitionFunction = 71,
|
||||||
|
|
||||||
|
DropSchema = 72,
|
||||||
|
DropUser = 73,
|
||||||
|
DropRole = 74,
|
||||||
|
DropFile = 75,
|
||||||
|
DropFileGroup = 76,
|
||||||
|
AddExtendedProperty = 77,
|
||||||
|
DropExtendedProperty = 78
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum ObjectType
|
||||||
|
{
|
||||||
|
None = 0,
|
||||||
|
Table = 1,
|
||||||
|
Column = 2,
|
||||||
|
Trigger = 3,
|
||||||
|
Constraint = 4,
|
||||||
|
|
||||||
|
[Description("Constraint Column")]
|
||||||
|
ConstraintColumn = 5,
|
||||||
|
|
||||||
|
Index = 6,
|
||||||
|
|
||||||
|
[Description("Index Column")]
|
||||||
|
IndexColumn = 7,
|
||||||
|
|
||||||
|
[Description("User Data Type")]
|
||||||
|
UserDataType = 8,
|
||||||
|
|
||||||
|
[Description("XML Schema")]
|
||||||
|
XMLSchema = 9,
|
||||||
|
|
||||||
|
View = 10,
|
||||||
|
Function = 11,
|
||||||
|
|
||||||
|
[Description("Stored Procedure")]
|
||||||
|
StoredProcedure = 12,
|
||||||
|
|
||||||
|
[Description("Table Option")]
|
||||||
|
TableOption = 13,
|
||||||
|
|
||||||
|
Database = 14,
|
||||||
|
Schema = 15,
|
||||||
|
|
||||||
|
[Description("File Group")]
|
||||||
|
FileGroup = 16,
|
||||||
|
|
||||||
|
File = 17,
|
||||||
|
Default = 18,
|
||||||
|
Rule = 19,
|
||||||
|
Synonym = 20,
|
||||||
|
Assembly = 21,
|
||||||
|
User = 22,
|
||||||
|
Role = 23,
|
||||||
|
|
||||||
|
[Description("Full Text")]
|
||||||
|
FullText = 24,
|
||||||
|
|
||||||
|
[Description("Assembly File")]
|
||||||
|
AssemblyFile = 25,
|
||||||
|
|
||||||
|
[Description("CLR Stored Procedure")]
|
||||||
|
CLRStoredProcedure = 26,
|
||||||
|
|
||||||
|
[Description("CLR Trigger")]
|
||||||
|
CLRTrigger = 27,
|
||||||
|
|
||||||
|
[Description("CLR Function")]
|
||||||
|
CLRFunction = 28,
|
||||||
|
|
||||||
|
[Description("Extended Property")]
|
||||||
|
ExtendedProperty = 30,
|
||||||
|
|
||||||
|
Partition = 31,
|
||||||
|
|
||||||
|
[Description("Partition Function")]
|
||||||
|
PartitionFunction = 32,
|
||||||
|
|
||||||
|
[Description("Partition Scheme")]
|
||||||
|
PartitionScheme = 33,
|
||||||
|
|
||||||
|
[Description("Table Type")]
|
||||||
|
TableType = 34,
|
||||||
|
|
||||||
|
[Description("Full Text Index")]
|
||||||
|
FullTextIndex = 35
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,24 @@
|
|||||||
|
using System;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace OpenDBDiff.Abstractions.Ui
|
||||||
|
{
|
||||||
|
public interface IFront : ICloneable
|
||||||
|
{
|
||||||
|
Point Location { get; set; }
|
||||||
|
string Name { get; set; }
|
||||||
|
Size Size { get; set; }
|
||||||
|
int TabIndex { get; set; }
|
||||||
|
bool Visible { get; set; }
|
||||||
|
DockStyle Dock { get; set; }
|
||||||
|
Boolean TestConnection();
|
||||||
|
string ConnectionString { get; set; }
|
||||||
|
string ErrorConnection { get; }
|
||||||
|
string DatabaseName { get; }
|
||||||
|
string Text { get; set; }
|
||||||
|
AnchorStyles Anchor { get; set; }
|
||||||
|
Control Control { get; }
|
||||||
|
void SetSettingsFrom(IFront other);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
<configuration>
|
||||||
|
<appSettings>
|
||||||
|
<add key="OpenDBDiff.NewIssueUri" value="https://github.com/OpenDBDiff/OpenDBDiff/issues/new" />
|
||||||
|
</appSettings>
|
||||||
|
</configuration>
|
||||||
@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<packages>
|
||||||
|
<package id="CommandLineParser" version="2.8.0" targetFramework="net452" />
|
||||||
|
</packages>
|
||||||
@ -0,0 +1,23 @@
|
|||||||
|
using System;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace OpenDBDiff.Front
|
||||||
|
{
|
||||||
|
public interface IFront
|
||||||
|
{
|
||||||
|
Point Location { get; set; }
|
||||||
|
string Name { get; set; }
|
||||||
|
Size Size { get; set; }
|
||||||
|
int TabIndex { get; set; }
|
||||||
|
bool Visible { get; set; }
|
||||||
|
DockStyle Dock { get; set; }
|
||||||
|
Boolean TestConnection();
|
||||||
|
string ConnectionString { get; set; }
|
||||||
|
string ErrorConnection { get; }
|
||||||
|
string DatabaseName { get; }
|
||||||
|
string Text { get; set; }
|
||||||
|
AnchorStyles Anchor { get; set; }
|
||||||
|
Control Control { get; }
|
||||||
|
}
|
||||||
|
}
|
||||||
Binary file not shown.
@ -0,0 +1,58 @@
|
|||||||
|
using OpenDBDiff.Schema.Model;
|
||||||
|
using OpenDBDiff.Schema.SQLServer.Generates.Model;
|
||||||
|
|
||||||
|
namespace OpenDBDiff.Schema.SQLServer.Generates.Compare
|
||||||
|
{
|
||||||
|
internal class CompareAssemblies : CompareBase<Assembly>
|
||||||
|
{
|
||||||
|
protected override void DoUpdate<Root>(SchemaList<Assembly, Root> originFields, Assembly node)
|
||||||
|
{
|
||||||
|
if (!node.Compare(originFields[node.FullName]))
|
||||||
|
{
|
||||||
|
Assembly newNode = (Assembly)node.Clone(originFields.Parent);
|
||||||
|
newNode.Status = ObjectStatus.Alter;
|
||||||
|
|
||||||
|
if (node.Text.Equals(originFields[node.FullName].Text))
|
||||||
|
{
|
||||||
|
if (!node.PermissionSet.Equals(originFields[node.FullName].PermissionSet))
|
||||||
|
newNode.Status += (int)ObjectStatus.PermissionSet;
|
||||||
|
if (!node.Owner.Equals(originFields[node.FullName].Owner))
|
||||||
|
newNode.Status += (int)ObjectStatus.ChangeOwner;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
newNode.Status = ObjectStatus.Rebuild;
|
||||||
|
|
||||||
|
originFields[node.FullName].Files.ForEach(item =>
|
||||||
|
{
|
||||||
|
if (!newNode.Files.Contains(item.FullName))
|
||||||
|
newNode.Files.Add(new AssemblyFile(newNode, item, ObjectStatus.Drop));
|
||||||
|
else
|
||||||
|
item.Status = ObjectStatus.Alter;
|
||||||
|
});
|
||||||
|
newNode.Files.ForEach(item =>
|
||||||
|
{
|
||||||
|
if (!originFields[node.FullName].Files.Contains(item.FullName))
|
||||||
|
{
|
||||||
|
item.Status = ObjectStatus.Create;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
CompareExtendedProperties(originFields[node.FullName], newNode);
|
||||||
|
originFields[node.FullName] = newNode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void DoNew<Root>(SchemaList<Assembly, Root> originFields, Assembly node)
|
||||||
|
{
|
||||||
|
bool pass = true;
|
||||||
|
Assembly newNode = (Assembly)node.Clone(originFields.Parent);
|
||||||
|
if ((((Database)newNode.RootParent).Info.Version == DatabaseInfo.SQLServerVersion.SQLServer2005)
|
||||||
|
&& (((Database)node.RootParent).Info.Version == DatabaseInfo.SQLServerVersion.SQLServer2008))
|
||||||
|
pass = node.FullName.Equals("Microsoft.SqlServer.Types");
|
||||||
|
if (pass)
|
||||||
|
{
|
||||||
|
newNode.Status = ObjectStatus.Create;
|
||||||
|
originFields.Add(newNode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,91 @@
|
|||||||
|
using System;
|
||||||
|
using OpenDBDiff.Schema.Model;
|
||||||
|
using OpenDBDiff.Schema.SQLServer.Generates.Model;
|
||||||
|
|
||||||
|
namespace OpenDBDiff.Schema.SQLServer.Generates.Compare
|
||||||
|
{
|
||||||
|
public class CompareColumns
|
||||||
|
{
|
||||||
|
public void GenerateDifferences<T>(Columns<T> originFields, Columns<T> destinationFields) where T : ISchemaBase
|
||||||
|
{
|
||||||
|
int restPosition = 0;
|
||||||
|
int sumPosition = 0;
|
||||||
|
|
||||||
|
foreach (Column node in originFields)
|
||||||
|
{
|
||||||
|
if (!destinationFields.Contains(node.FullName))
|
||||||
|
{
|
||||||
|
node.Status = ObjectStatus.Drop;
|
||||||
|
restPosition++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
originFields[node.FullName].Position -= restPosition;
|
||||||
|
}
|
||||||
|
foreach (Column node in destinationFields)
|
||||||
|
{
|
||||||
|
if (!originFields.Contains(node.FullName))
|
||||||
|
{
|
||||||
|
Column newNode = node.Clone(originFields.Parent);
|
||||||
|
if ((newNode.Position == 1) || ((newNode.DefaultConstraint == null) && (!newNode.IsNullable) && (!newNode.IsComputed) && (!newNode.IsIdentity) && (!newNode.IsIdentityForReplication)))
|
||||||
|
{
|
||||||
|
newNode.Status = ObjectStatus.Create;
|
||||||
|
newNode.Parent.Status = ObjectStatus.Rebuild;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
newNode.Status = ObjectStatus.Create;
|
||||||
|
sumPosition++;
|
||||||
|
originFields.Add(newNode);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Column originField = originFields[node.FullName];
|
||||||
|
/*ColumnConstraint oldDefault = null;
|
||||||
|
if (originField.DefaultConstraint != null)
|
||||||
|
oldDefault = originField.DefaultConstraint.Clone(originField);*/
|
||||||
|
Boolean IsColumnEqual = Column.Compare(originField, node);
|
||||||
|
if ((!IsColumnEqual) || (originField.Position != node.Position))
|
||||||
|
{
|
||||||
|
if (Column.CompareIdentity(originField, node))
|
||||||
|
{
|
||||||
|
|
||||||
|
if (node.HasToRebuildOnlyConstraint)
|
||||||
|
{
|
||||||
|
node.Status = ObjectStatus.Alter;
|
||||||
|
if ((originField.IsNullable) && (!node.IsNullable))
|
||||||
|
node.Status += (int)ObjectStatus.Update;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (node.HasToRebuild(originField.Position + sumPosition, originField.Type, originField.IsFileStream))
|
||||||
|
node.Status = ObjectStatus.Rebuild;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!IsColumnEqual)
|
||||||
|
{
|
||||||
|
node.Status = ObjectStatus.Alter;
|
||||||
|
if ((originField.IsNullable) && (!node.IsNullable))
|
||||||
|
node.Status += (int)ObjectStatus.Update;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (node.Status != ObjectStatus.Rebuild)
|
||||||
|
{
|
||||||
|
if (!Column.CompareRule(originField, node))
|
||||||
|
{
|
||||||
|
node.Status += (int)ObjectStatus.Bind;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
node.Status = ObjectStatus.Rebuild;
|
||||||
|
}
|
||||||
|
originFields[node.FullName] = node.Clone(originFields.Parent);
|
||||||
|
}
|
||||||
|
originFields[node.FullName].DefaultConstraint = CompareColumnsConstraints.GenerateDifferences(originField, node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@ -0,0 +1,72 @@
|
|||||||
|
using OpenDBDiff.Schema.SQLServer.Generates.Model;
|
||||||
|
|
||||||
|
namespace OpenDBDiff.Schema.SQLServer.Generates.Compare
|
||||||
|
{
|
||||||
|
internal class CompareColumnsConstraints : CompareBase<ColumnConstraint>
|
||||||
|
{
|
||||||
|
public static ColumnConstraint GenerateDifferences(Column originFields, Column destinationFields)
|
||||||
|
{
|
||||||
|
if ((originFields.DefaultConstraint == null) && (destinationFields.DefaultConstraint != null))
|
||||||
|
{
|
||||||
|
originFields.DefaultConstraint = destinationFields.DefaultConstraint.Clone(originFields);
|
||||||
|
originFields.DefaultConstraint.Status = ObjectStatus.Create;
|
||||||
|
originFields.DefaultConstraint.Parent.Status = ObjectStatus.Original;
|
||||||
|
originFields.DefaultConstraint.Parent.Parent.Status = ObjectStatus.Alter;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ((originFields.DefaultConstraint != null) && (destinationFields.DefaultConstraint != null))
|
||||||
|
{
|
||||||
|
if (!ColumnConstraint.Compare(originFields.DefaultConstraint, destinationFields.DefaultConstraint))
|
||||||
|
{
|
||||||
|
originFields.DefaultConstraint = destinationFields.DefaultConstraint.Clone(originFields);
|
||||||
|
//Indico que hay un ALTER TABLE, pero sobre la columna, no seteo ningun estado.
|
||||||
|
originFields.DefaultConstraint.Status = ObjectStatus.Alter;
|
||||||
|
originFields.DefaultConstraint.Parent.Status = ObjectStatus.Original;
|
||||||
|
originFields.DefaultConstraint.Parent.Parent.Status = ObjectStatus.Alter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if ((originFields.DefaultConstraint != null) && (destinationFields.DefaultConstraint == null))
|
||||||
|
{
|
||||||
|
originFields.DefaultConstraint.Status = ObjectStatus.Drop;
|
||||||
|
originFields.DefaultConstraint.Parent.Status = ObjectStatus.Original;
|
||||||
|
originFields.DefaultConstraint.Parent.Parent.Status = ObjectStatus.Alter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*foreach (ColumnConstraint node in destinationFields)
|
||||||
|
{
|
||||||
|
if (!originFields.Exists(node.FullName))
|
||||||
|
{
|
||||||
|
node.Status = ObjectStatusType.CreateStatus;
|
||||||
|
originFields.Parent.Status = ObjectStatusType.OriginalStatus;
|
||||||
|
originFields.Parent.Parent.Status = ObjectStatusType.AlterStatus;
|
||||||
|
originFields.Add(node);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!ColumnConstraint.Compare(originFields[node.FullName], node))
|
||||||
|
{
|
||||||
|
ColumnConstraint newNode = node.Clone(originFields.Parent);
|
||||||
|
//Indico que hay un ALTER TABLE, pero sobre la columna, no seteo ningun estado.
|
||||||
|
newNode.Status = ObjectStatusType.AlterStatus;
|
||||||
|
newNode.Parent.Status = ObjectStatusType.OriginalStatus;
|
||||||
|
newNode.Parent.Parent.Status = ObjectStatusType.AlterStatus;
|
||||||
|
originFields[node.FullName] = newNode;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MarkDrop(originFields, destinationFields, node =>
|
||||||
|
{
|
||||||
|
node.Status = ObjectStatusType.DropStatus;
|
||||||
|
originFields.Parent.Status = ObjectStatusType.OriginalStatus;
|
||||||
|
originFields.Parent.Parent.Status = ObjectStatusType.AlterStatus;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
*/
|
||||||
|
return originFields.DefaultConstraint;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,40 @@
|
|||||||
|
using OpenDBDiff.Schema.Model;
|
||||||
|
using OpenDBDiff.Schema.SQLServer.Generates.Model;
|
||||||
|
|
||||||
|
namespace OpenDBDiff.Schema.SQLServer.Generates.Compare
|
||||||
|
{
|
||||||
|
internal class CompareConstraints : CompareBase<Constraint>
|
||||||
|
{
|
||||||
|
protected override void DoUpdate<Root>(SchemaList<Constraint, Root> originFields, Constraint node)
|
||||||
|
{
|
||||||
|
Constraint origin = originFields[node.FullName];
|
||||||
|
if (!Constraint.Compare(origin, node))
|
||||||
|
{
|
||||||
|
Constraint newNode = (Constraint)node.Clone(originFields.Parent);
|
||||||
|
if (node.IsDisabled == origin.IsDisabled)
|
||||||
|
{
|
||||||
|
newNode.Status = ObjectStatus.Alter;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
newNode.Status = ObjectStatus.Alter + (int)ObjectStatus.Disabled;
|
||||||
|
originFields[node.FullName] = newNode;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (node.IsDisabled != origin.IsDisabled)
|
||||||
|
{
|
||||||
|
Constraint newNode = (Constraint)node.Clone(originFields.Parent);
|
||||||
|
newNode.Status = ObjectStatus.Disabled;
|
||||||
|
originFields[node.FullName] = newNode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void DoNew<Root>(SchemaList<Constraint, Root> originFields, Constraint node)
|
||||||
|
{
|
||||||
|
Constraint newNode = (Constraint)node.Clone(originFields.Parent);
|
||||||
|
newNode.Status = ObjectStatus.Create;
|
||||||
|
originFields.Add(newNode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,54 @@
|
|||||||
|
using OpenDBDiff.Schema.Misc;
|
||||||
|
using OpenDBDiff.Schema.SQLServer.Generates.Model;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace OpenDBDiff.Schema.SQLServer.Generates.Compare
|
||||||
|
{
|
||||||
|
internal static class CompareDatabase
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Generates the differences to migrate a schema from origin to destination
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="origin">The Origin schema is the schema before our generated actions are applied.</param>
|
||||||
|
/// <param name="destination">The Destination schema is the schema after our actions are applied.</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
/// <exception cref="SchemaException"></exception>
|
||||||
|
public static Database GenerateDifferences(Database origin, Database destination)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Database data = origin;
|
||||||
|
(new CompareTables()).GenerateDifferences<Database>(origin.Tables, destination.Tables);
|
||||||
|
(new CompareAssemblies()).GenerateDifferences<Database>(origin.Assemblies, destination.Assemblies);
|
||||||
|
(new CompareUserDataTypes()).GenerateDifferences<Database>(origin.UserTypes, destination.UserTypes);
|
||||||
|
(new CompareXMLSchemas()).GenerateDifferences<Database>(origin.XmlSchemas, destination.XmlSchemas);
|
||||||
|
(new CompareSchemas()).GenerateDifferences<Database>(origin.Schemas, destination.Schemas);
|
||||||
|
(new CompareFileGroups()).GenerateDifferences<Database>(origin.FileGroups, destination.FileGroups);
|
||||||
|
(new CompareRules()).GenerateDifferences<Database>(origin.Rules, destination.Rules);
|
||||||
|
(new CompareDDLTriggers()).GenerateDifferences<Database>(origin.DDLTriggers, destination.DDLTriggers);
|
||||||
|
(new CompareSynonyms()).GenerateDifferences<Database>(origin.Synonyms, destination.Synonyms);
|
||||||
|
(new CompareUsers()).GenerateDifferences<Database>(origin.Users, destination.Users);
|
||||||
|
(new CompareStoredProcedures()).GenerateDifferences<Database>(origin.Procedures, destination.Procedures);
|
||||||
|
(new CompareCLRStoredProcedure()).GenerateDifferences<Database>(origin.CLRProcedures, destination.CLRProcedures);
|
||||||
|
(new CompareCLRFunction()).GenerateDifferences<Database>(origin.CLRFunctions, destination.CLRFunctions);
|
||||||
|
(new CompareViews()).GenerateDifferences<Database>(origin.Views, destination.Views);
|
||||||
|
(new CompareFunctions()).GenerateDifferences<Database>(origin.Functions, destination.Functions);
|
||||||
|
(new CompareRoles()).GenerateDifferences<Database>(origin.Roles, destination.Roles);
|
||||||
|
(new ComparePartitionFunction()).GenerateDifferences<Database>(origin.PartitionFunctions, destination.PartitionFunctions);
|
||||||
|
(new ComparePartitionSchemes()).GenerateDifferences<Database>(origin.PartitionSchemes, destination.PartitionSchemes);
|
||||||
|
(new CompareTableType()).GenerateDifferences<Database>(origin.TablesTypes, destination.TablesTypes);
|
||||||
|
(new CompareFullText()).GenerateDifferences<Database>(origin.FullText, destination.FullText);
|
||||||
|
data.SourceInfo = destination.Info;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
catch (SchemaException)
|
||||||
|
{
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
throw new SchemaException(ex.Message, ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,44 @@
|
|||||||
|
using OpenDBDiff.Schema.Model;
|
||||||
|
using OpenDBDiff.Schema.SQLServer.Generates.Model;
|
||||||
|
|
||||||
|
namespace OpenDBDiff.Schema.SQLServer.Generates.Compare
|
||||||
|
{
|
||||||
|
internal class CompareFileGroups : CompareBase<FileGroup>
|
||||||
|
{
|
||||||
|
protected override void DoNew<Root>(SchemaList<FileGroup, Root> originFields, FileGroup node)
|
||||||
|
{
|
||||||
|
FileGroup newNode = (FileGroup)node.Clone(originFields.Parent);
|
||||||
|
newNode.Status = ObjectStatus.Create;
|
||||||
|
/*If the Logical File Name exists in another filegroup,
|
||||||
|
* we must change the new Logical File Name.
|
||||||
|
*/
|
||||||
|
originFields.ForEach(file =>
|
||||||
|
{
|
||||||
|
if (file.Status != ObjectStatus.Drop)
|
||||||
|
{
|
||||||
|
file.Files.ForEach(group =>
|
||||||
|
{
|
||||||
|
newNode.Files.ForEach(ngroup =>
|
||||||
|
{
|
||||||
|
if (group.CompareFullNameTo(group.FullName, ngroup.FullName) == 0)
|
||||||
|
{
|
||||||
|
newNode.Files[ngroup.FullName].Name = group.Name + "_2";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
originFields.Add(newNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void DoUpdate<Root>(SchemaList<FileGroup, Root> originFields, FileGroup node)
|
||||||
|
{
|
||||||
|
if (!FileGroup.Compare(node, originFields[node.FullName]))
|
||||||
|
{
|
||||||
|
FileGroup newNode = (FileGroup)node.Clone(originFields.Parent);
|
||||||
|
newNode.Status = ObjectStatus.Alter;
|
||||||
|
originFields[node.FullName] = newNode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,30 @@
|
|||||||
|
using OpenDBDiff.Schema.Model;
|
||||||
|
using OpenDBDiff.Schema.SQLServer.Generates.Model;
|
||||||
|
|
||||||
|
namespace OpenDBDiff.Schema.SQLServer.Generates.Compare
|
||||||
|
{
|
||||||
|
internal class CompareIndexes : CompareBase<Index>
|
||||||
|
{
|
||||||
|
protected override void DoNew<Root>(SchemaList<Index, Root> originFields, Index node)
|
||||||
|
{
|
||||||
|
Index newNode = (Index)node.Clone(originFields.Parent);
|
||||||
|
newNode.Status = ObjectStatus.Create;
|
||||||
|
originFields.Add(newNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void DoUpdate<Root>(SchemaList<Index, Root> originFields, Index node)
|
||||||
|
{
|
||||||
|
if (!Index.Compare(node, originFields[node.FullName]))
|
||||||
|
{
|
||||||
|
Index newNode = (Index)node.Clone(originFields.Parent);
|
||||||
|
if (!Index.CompareExceptIsDisabled(node, originFields[node.FullName]))
|
||||||
|
{
|
||||||
|
newNode.Status = ObjectStatus.Alter;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
newNode.Status = ObjectStatus.Disabled;
|
||||||
|
originFields[node.FullName] = newNode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,25 @@
|
|||||||
|
using OpenDBDiff.Schema.Model;
|
||||||
|
using OpenDBDiff.Schema.SQLServer.Generates.Model;
|
||||||
|
|
||||||
|
namespace OpenDBDiff.Schema.SQLServer.Generates.Compare
|
||||||
|
{
|
||||||
|
internal class CompareRules : CompareBase<Rule>
|
||||||
|
{
|
||||||
|
protected override void DoUpdate<Root>(SchemaList<Rule, Root> originFields, Rule node)
|
||||||
|
{
|
||||||
|
if (!node.Compare(originFields[node.FullName]))
|
||||||
|
{
|
||||||
|
Rule newNode = node.Clone(originFields.Parent);
|
||||||
|
newNode.Status = ObjectStatus.Alter;
|
||||||
|
originFields[node.FullName] = newNode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void DoNew<Root>(SchemaList<Rule, Root> originFields, Rule node)
|
||||||
|
{
|
||||||
|
Rule newNode = node.Clone(originFields.Parent);
|
||||||
|
newNode.Status = ObjectStatus.Create;
|
||||||
|
originFields.Add(newNode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
namespace OpenDBDiff.Schema.SQLServer.Generates.Compare
|
||||||
|
{
|
||||||
|
internal class CompareSchemas : CompareBase<Model.Schema>
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,27 @@
|
|||||||
|
using OpenDBDiff.Schema.Model;
|
||||||
|
using OpenDBDiff.Schema.SQLServer.Generates.Model;
|
||||||
|
|
||||||
|
namespace OpenDBDiff.Schema.SQLServer.Generates.Compare
|
||||||
|
{
|
||||||
|
internal class CompareStoredProcedures : CompareBase<StoredProcedure>
|
||||||
|
{
|
||||||
|
protected override void DoUpdate<Root>(SchemaList<StoredProcedure, Root> originFields, StoredProcedure node)
|
||||||
|
{
|
||||||
|
if (!node.Compare(originFields[node.FullName]))
|
||||||
|
{
|
||||||
|
StoredProcedure newNode = node; //.Clone(originFields.Parent);
|
||||||
|
|
||||||
|
if (node.CompareExceptWhitespace(originFields[node.FullName]))
|
||||||
|
{
|
||||||
|
newNode.Status = ObjectStatus.AlterWhitespace;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
newNode.Status = ObjectStatus.Alter;
|
||||||
|
}
|
||||||
|
|
||||||
|
originFields[node.FullName] = newNode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,18 @@
|
|||||||
|
using OpenDBDiff.Schema.Model;
|
||||||
|
using OpenDBDiff.Schema.SQLServer.Generates.Model;
|
||||||
|
|
||||||
|
namespace OpenDBDiff.Schema.SQLServer.Generates.Compare
|
||||||
|
{
|
||||||
|
internal class CompareSynonyms : CompareBase<Synonym>
|
||||||
|
{
|
||||||
|
protected override void DoUpdate<Root>(SchemaList<Synonym, Root> originFields, Synonym node)
|
||||||
|
{
|
||||||
|
if (!Synonym.Compare(node, originFields[node.FullName]))
|
||||||
|
{
|
||||||
|
Synonym newNode = node; //.Clone(originFields.Parent);
|
||||||
|
newNode.Status = ObjectStatus.Alter;
|
||||||
|
originFields[node.FullName] = newNode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,92 @@
|
|||||||
|
using OpenDBDiff.Schema.Model;
|
||||||
|
using OpenDBDiff.Schema.SQLServer.Generates.Model;
|
||||||
|
|
||||||
|
namespace OpenDBDiff.Schema.SQLServer.Generates.Compare
|
||||||
|
{
|
||||||
|
internal class CompareTables : CompareBase<Table>
|
||||||
|
{
|
||||||
|
protected override void DoUpdate<Root>(SchemaList<Table, Root> originFields, Table node)
|
||||||
|
{
|
||||||
|
if (node.Status != ObjectStatus.Drop)
|
||||||
|
{
|
||||||
|
Table tablaOriginal = originFields[node.FullName];
|
||||||
|
tablaOriginal.OriginalTable = (Table)originFields[node.FullName].Clone((Database)tablaOriginal.Parent);
|
||||||
|
(new CompareColumns()).GenerateDifferences<Table>(tablaOriginal.Columns, node.Columns);
|
||||||
|
(new CompareConstraints()).GenerateDifferences<Table>(tablaOriginal.Constraints, node.Constraints);
|
||||||
|
(new CompareIndexes()).GenerateDifferences<Table>(tablaOriginal.Indexes, node.Indexes);
|
||||||
|
(new CompareTablesOptions()).GenerateDifferences<Table>(tablaOriginal.Options, node.Options);
|
||||||
|
(new CompareTriggers()).GenerateDifferences<Table>(tablaOriginal.Triggers, node.Triggers);
|
||||||
|
(new CompareCLRTriggers()).GenerateDifferences<Table>(tablaOriginal.CLRTriggers, node.CLRTriggers);
|
||||||
|
(new CompareFullTextIndex()).GenerateDifferences<Table>(tablaOriginal.FullTextIndex, node.FullTextIndex);
|
||||||
|
if (!Table.CompareFileGroup(tablaOriginal, node))
|
||||||
|
{
|
||||||
|
tablaOriginal.FileGroup = node.FileGroup;
|
||||||
|
/*Esto solo aplica a las tablas heap, el resto hace el campo en el filegroup del indice clustered*/
|
||||||
|
if (!tablaOriginal.HasClusteredIndex)
|
||||||
|
tablaOriginal.Status = ObjectStatus.Rebuild;
|
||||||
|
}
|
||||||
|
if (!Table.CompareFileGroupText(tablaOriginal, node))
|
||||||
|
{
|
||||||
|
tablaOriginal.FileGroupText = node.FileGroupText;
|
||||||
|
tablaOriginal.Status = ObjectStatus.Rebuild;
|
||||||
|
}
|
||||||
|
if (node.HasChangeTracking != tablaOriginal.HasChangeTracking)
|
||||||
|
{
|
||||||
|
tablaOriginal.HasChangeTracking = node.HasChangeTracking;
|
||||||
|
tablaOriginal.HasChangeTrackingTrackColumn = node.HasChangeTrackingTrackColumn;
|
||||||
|
tablaOriginal.Status += (int)ObjectStatus.Disabled;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Compara las colecciones de tablas de dos bases diferentes y marca el estado de los objetos
|
||||||
|
/// dependiendo si existen o si deben borrarse.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="originTables"></param>
|
||||||
|
/// Tablas originales, donde se guardaran los estados de las tablas.
|
||||||
|
/// <param name="destinationTables">
|
||||||
|
/// Tablas comparativas, que se usa para comparar con la base original.
|
||||||
|
/// </param>
|
||||||
|
/*public static void GenerateDifferences(SchemaList<Table, Database> originTables, SchemaList<Table, Database> destinationTables)
|
||||||
|
{
|
||||||
|
MarkDrop(originTables, destinationTables);
|
||||||
|
|
||||||
|
foreach (Table node in destinationTables)
|
||||||
|
{
|
||||||
|
if (!originTables.Exists(node.FullName))
|
||||||
|
{
|
||||||
|
node.Status = ObjectStatusType.CreateStatus;
|
||||||
|
node.Parent = originTables.Parent;
|
||||||
|
originTables.Add(node);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (node.Status != ObjectStatusType.DropStatus)
|
||||||
|
{
|
||||||
|
Table tablaOriginal = originTables[node.FullName];
|
||||||
|
tablaOriginal.OriginalTable = (Table)originTables[node.FullName].Clone((Database)tablaOriginal.Parent);
|
||||||
|
CompareColumns.GenerateDifferences<Table>(tablaOriginal.Columns, node.Columns);
|
||||||
|
CompareConstraints.GenerateDifferences<Table>(tablaOriginal.Constraints, node.Constraints);
|
||||||
|
CompareIndexes.GenerateDifferences(tablaOriginal.Indexes, node.Indexes);
|
||||||
|
CompareTablesOptions.GenerateDifferences(tablaOriginal.Options, node.Options);
|
||||||
|
(new CompareTriggers()).GenerateDifferences<Table>(tablaOriginal.Triggers, node.Triggers);
|
||||||
|
(new CompareCLRTriggers()).GenerateDifferences<Table>(tablaOriginal.CLRTriggers, node.CLRTriggers);
|
||||||
|
if (!Table.CompareFileGroup(tablaOriginal, node))
|
||||||
|
{
|
||||||
|
tablaOriginal.FileGroup = node.FileGroup;
|
||||||
|
//Esto solo aplica a las tablas heap, el resto hace el campo en el filegroup del indice clustered
|
||||||
|
if (!tablaOriginal.HasClusteredIndex)
|
||||||
|
tablaOriginal.Status = ObjectStatusType.RebuildStatus;
|
||||||
|
}
|
||||||
|
if (!Table.CompareFileGroupText(tablaOriginal, node))
|
||||||
|
{
|
||||||
|
tablaOriginal.FileGroupText = node.FileGroupText;
|
||||||
|
tablaOriginal.Status = ObjectStatusType.RebuildStatus;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,25 @@
|
|||||||
|
using OpenDBDiff.Schema.Model;
|
||||||
|
using OpenDBDiff.Schema.SQLServer.Generates.Model;
|
||||||
|
|
||||||
|
namespace OpenDBDiff.Schema.SQLServer.Generates.Compare
|
||||||
|
{
|
||||||
|
internal class CompareTablesOptions : CompareBase<TableOption>
|
||||||
|
{
|
||||||
|
protected override void DoNew<Root>(SchemaList<TableOption, Root> originFields, TableOption node)
|
||||||
|
{
|
||||||
|
TableOption newNode = (TableOption)node.Clone(originFields.Parent);
|
||||||
|
newNode.Status = ObjectStatus.Create;
|
||||||
|
originFields.Add(newNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void DoUpdate<Root>(SchemaList<TableOption, Root> originFields, TableOption node)
|
||||||
|
{
|
||||||
|
if (!TableOption.Compare(node, originFields[node.FullName]))
|
||||||
|
{
|
||||||
|
TableOption newNode = (TableOption)node.Clone(originFields.Parent);
|
||||||
|
newNode.Status = ObjectStatus.Alter;
|
||||||
|
originFields[node.FullName] = newNode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,28 @@
|
|||||||
|
using OpenDBDiff.Schema.Model;
|
||||||
|
using OpenDBDiff.Schema.SQLServer.Generates.Model;
|
||||||
|
|
||||||
|
namespace OpenDBDiff.Schema.SQLServer.Generates.Compare
|
||||||
|
{
|
||||||
|
internal class CompareTriggers : CompareBase<Trigger>
|
||||||
|
{
|
||||||
|
protected override void DoNew<Root>(SchemaList<Trigger, Root> originFields, Trigger node)
|
||||||
|
{
|
||||||
|
Trigger newNode = (Trigger)node.Clone(originFields.Parent);
|
||||||
|
newNode.Status = ObjectStatus.Create;
|
||||||
|
originFields.Add(newNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void DoUpdate<Root>(SchemaList<Trigger, Root> originFields, Trigger node)
|
||||||
|
{
|
||||||
|
if (!node.Compare(originFields[node.FullName]))
|
||||||
|
{
|
||||||
|
Trigger newNode = (Trigger)node.Clone(originFields.Parent);
|
||||||
|
if (!newNode.Text.Equals(originFields[node.FullName].Text))
|
||||||
|
newNode.Status = ObjectStatus.Alter;
|
||||||
|
if (node.IsDisabled != originFields[node.FullName].IsDisabled)
|
||||||
|
newNode.Status = newNode.Status + (int)ObjectStatus.Disabled;
|
||||||
|
originFields[node.FullName] = newNode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,51 @@
|
|||||||
|
using System;
|
||||||
|
using OpenDBDiff.Schema.Model;
|
||||||
|
using OpenDBDiff.Schema.SQLServer.Generates.Model;
|
||||||
|
|
||||||
|
namespace OpenDBDiff.Schema.SQLServer.Generates.Compare
|
||||||
|
{
|
||||||
|
internal class CompareUserDataTypes : CompareBase<UserDataType>
|
||||||
|
{
|
||||||
|
protected override void DoNew<Root>(SchemaList<UserDataType, Root> originFields, UserDataType node)
|
||||||
|
{
|
||||||
|
UserDataType newNode = (UserDataType)node.Clone(originFields.Parent);
|
||||||
|
newNode.Status = ObjectStatus.Create;
|
||||||
|
Boolean HasAssembly = originFields.Exists(item => item.AssemblyFullName.Equals(node.AssemblyFullName) && item.IsAssembly);
|
||||||
|
if (HasAssembly)
|
||||||
|
newNode.Status += (int)ObjectStatus.DropOlder;
|
||||||
|
originFields.Add(newNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void DoUpdate<Root>(SchemaList<UserDataType, Root> originFields, UserDataType node)
|
||||||
|
{
|
||||||
|
if (!node.Compare(originFields[node.FullName]))
|
||||||
|
{
|
||||||
|
UserDataType newNode = (UserDataType)node.Clone(originFields.Parent);
|
||||||
|
newNode.Dependencies.AddRange(originFields[node.FullName].Dependencies);
|
||||||
|
|
||||||
|
if (!UserDataType.CompareDefault(node, originFields[node.FullName]))
|
||||||
|
{
|
||||||
|
if (!String.IsNullOrEmpty(node.Default.Name))
|
||||||
|
newNode.Default.Status = ObjectStatus.Create;
|
||||||
|
else
|
||||||
|
newNode.Default.Status = ObjectStatus.Drop;
|
||||||
|
newNode.Status = ObjectStatus.Alter;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!UserDataType.CompareRule(node, originFields[node.FullName]))
|
||||||
|
{
|
||||||
|
if (!String.IsNullOrEmpty(node.Rule.Name))
|
||||||
|
newNode.Rule.Status = ObjectStatus.Create;
|
||||||
|
else
|
||||||
|
newNode.Rule.Status = ObjectStatus.Drop;
|
||||||
|
newNode.Status = ObjectStatus.Alter;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
newNode.Status = ObjectStatus.Rebuild;
|
||||||
|
}
|
||||||
|
originFields[node.FullName] = newNode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,52 @@
|
|||||||
|
using OpenDBDiff.Schema.Model;
|
||||||
|
using OpenDBDiff.Schema.SQLServer.Generates.Model;
|
||||||
|
|
||||||
|
namespace OpenDBDiff.Schema.SQLServer.Generates.Compare
|
||||||
|
{
|
||||||
|
internal class CompareViews : CompareBase<View>
|
||||||
|
{
|
||||||
|
protected override void DoUpdate<Root>(SchemaList<View, Root> originFields, View node)
|
||||||
|
{
|
||||||
|
View original = originFields[node.FullName];
|
||||||
|
if (!node.Compare(original))
|
||||||
|
{
|
||||||
|
View newNode = (View)node.Clone(originFields.Parent);
|
||||||
|
newNode.DependenciesOut.AddRange(original.DependenciesOut);
|
||||||
|
newNode.DependenciesIn.AddRange(original.DependenciesIn);
|
||||||
|
|
||||||
|
newNode.Status = ObjectStatus.Alter;
|
||||||
|
newNode.Indexes = original.Indexes;
|
||||||
|
newNode.Triggers = original.Triggers;
|
||||||
|
|
||||||
|
if (newNode.IsSchemaBinding)
|
||||||
|
newNode.Status += (int)ObjectStatus.RebuildDependencies;
|
||||||
|
if (newNode.HasToRebuild)
|
||||||
|
newNode.Status += (int)ObjectStatus.Rebuild;
|
||||||
|
else
|
||||||
|
newNode.Status += (int)ObjectStatus.AlterBody;
|
||||||
|
|
||||||
|
originFields[node.FullName] = newNode;
|
||||||
|
original = newNode;
|
||||||
|
}
|
||||||
|
(new CompareIndexes()).GenerateDifferences<View>(original.Indexes, node.Indexes);
|
||||||
|
(new CompareTriggers()).GenerateDifferences<View>(original.Triggers, node.Triggers);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void DoNew<Root>(SchemaList<View, Root> originFields, View node)
|
||||||
|
{
|
||||||
|
View newNode = (View)node.Clone(originFields.Parent);
|
||||||
|
newNode.Status = ObjectStatus.Create;
|
||||||
|
originFields.Add(newNode);
|
||||||
|
newNode.DependenciesIn.ForEach(dep =>
|
||||||
|
{
|
||||||
|
ISchemaBase item = ((Database)((ISchemaBase)originFields.Parent)).Find(dep);
|
||||||
|
if (item != null)
|
||||||
|
{
|
||||||
|
if (item.IsCodeType)
|
||||||
|
((ICode)item).DependenciesOut.Add(newNode.FullName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,18 @@
|
|||||||
|
using OpenDBDiff.Schema.Model;
|
||||||
|
using OpenDBDiff.Schema.SQLServer.Generates.Model;
|
||||||
|
|
||||||
|
namespace OpenDBDiff.Schema.SQLServer.Generates.Compare
|
||||||
|
{
|
||||||
|
internal class CompareXMLSchemas : CompareBase<XMLSchema>
|
||||||
|
{
|
||||||
|
protected override void DoUpdate<Root>(SchemaList<XMLSchema, Root> originFields, XMLSchema node)
|
||||||
|
{
|
||||||
|
if (!node.Compare(originFields[node.FullName]))
|
||||||
|
{
|
||||||
|
XMLSchema newNode = node.Clone(originFields.Parent);
|
||||||
|
newNode.Status = ObjectStatus.Alter;
|
||||||
|
originFields[node.FullName] = newNode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,191 @@
|
|||||||
|
using OpenDBDiff.Schema.Errors;
|
||||||
|
using OpenDBDiff.Schema.Events;
|
||||||
|
using OpenDBDiff.Schema.Misc;
|
||||||
|
using OpenDBDiff.Schema.SQLServer.Generates.Compare;
|
||||||
|
using OpenDBDiff.Schema.SQLServer.Generates.Generates.Util;
|
||||||
|
using OpenDBDiff.Schema.SQLServer.Generates.Model;
|
||||||
|
using OpenDBDiff.Schema.SQLServer.Generates.Options;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Data.SqlClient;
|
||||||
|
|
||||||
|
namespace OpenDBDiff.Schema.SQLServer.Generates.Generates
|
||||||
|
{
|
||||||
|
public class Generate
|
||||||
|
{
|
||||||
|
private readonly List<MessageLog> messages;
|
||||||
|
private ProgressEventArgs currentlyReading;
|
||||||
|
|
||||||
|
public Generate()
|
||||||
|
{
|
||||||
|
messages = new List<MessageLog>();
|
||||||
|
OnReading += Generate_OnReading;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int MaxValue
|
||||||
|
{
|
||||||
|
get { return Constants.READING_MAX; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public string ConnectionString { get; set; }
|
||||||
|
|
||||||
|
private string Name
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
string name;
|
||||||
|
using (var conn = new SqlConnection(ConnectionString))
|
||||||
|
{
|
||||||
|
name = conn.Database;
|
||||||
|
}
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public SqlOption Options { get; set; }
|
||||||
|
|
||||||
|
private event ProgressEventHandler.ProgressHandler OnReading;
|
||||||
|
|
||||||
|
public event ProgressEventHandler.ProgressHandler OnProgress;
|
||||||
|
|
||||||
|
private void Generate_OnReading(ProgressEventArgs e)
|
||||||
|
{
|
||||||
|
if (OnProgress != null) OnProgress(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RaiseOnReading(ProgressEventArgs e)
|
||||||
|
{
|
||||||
|
this.currentlyReading = e;
|
||||||
|
if (OnReading != null) OnReading(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RaiseOnReadingOne(object name)
|
||||||
|
{
|
||||||
|
if (name != null && this.OnReading != null && this.currentlyReading != null)
|
||||||
|
{
|
||||||
|
var eOne = new ProgressEventArgs(this.currentlyReading.Message, this.currentlyReading.Progress);
|
||||||
|
eOne.Message = eOne.Message.Replace("...", String.Format(": [{0}]", name));
|
||||||
|
this.OnReading(eOne);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Genera el schema de la base de datos seleccionada y devuelve un objeto Database.
|
||||||
|
/// </summary>
|
||||||
|
public Database Process()
|
||||||
|
{
|
||||||
|
string error = "";
|
||||||
|
var databaseSchema = new Database();
|
||||||
|
|
||||||
|
//tables.OnTableProgress += new Progress.ProgressHandler(tables_OnTableProgress);
|
||||||
|
databaseSchema.Options = Options;
|
||||||
|
databaseSchema.Name = Name;
|
||||||
|
databaseSchema.Info = (new GenerateDatabase(ConnectionString, Options)).Get(databaseSchema);
|
||||||
|
/*Thread t1 = new Thread(delegate()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{*/
|
||||||
|
(new GenerateRules(this)).Fill(databaseSchema, ConnectionString);
|
||||||
|
(new GenerateTables(this)).Fill(databaseSchema, ConnectionString, messages);
|
||||||
|
(new GenerateViews(this)).Fill(databaseSchema, ConnectionString, messages);
|
||||||
|
|
||||||
|
if (Options.Ignore.FilterIndex)
|
||||||
|
{
|
||||||
|
(new GenerateIndex(this)).Fill(databaseSchema, ConnectionString);
|
||||||
|
(new GenerateFullTextIndex(this)).Fill(databaseSchema, ConnectionString);
|
||||||
|
}
|
||||||
|
(new GenerateUserDataTypes(this)).Fill(databaseSchema, ConnectionString, messages);
|
||||||
|
(new GenerateXMLSchemas(this)).Fill(databaseSchema, ConnectionString);
|
||||||
|
(new GenerateSchemas(this)).Fill(databaseSchema, ConnectionString);
|
||||||
|
/*}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
error = ex.StackTrace;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Thread t2 = new Thread(delegate()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{*/
|
||||||
|
|
||||||
|
//not supported in azure yet
|
||||||
|
if (databaseSchema.Info.Version != DatabaseInfo.SQLServerVersion.SQLServerAzure10)
|
||||||
|
{
|
||||||
|
(new GeneratePartitionFunctions(this)).Fill(databaseSchema, ConnectionString);
|
||||||
|
(new GeneratePartitionScheme(this)).Fill(databaseSchema, ConnectionString);
|
||||||
|
(new GenerateFileGroups(this)).Fill(databaseSchema, ConnectionString);
|
||||||
|
}
|
||||||
|
|
||||||
|
(new GenerateDDLTriggers(this)).Fill(databaseSchema, ConnectionString);
|
||||||
|
(new GenerateSynonyms(this)).Fill(databaseSchema, ConnectionString);
|
||||||
|
|
||||||
|
//not supported in azure yet
|
||||||
|
if (databaseSchema.Info.Version != DatabaseInfo.SQLServerVersion.SQLServerAzure10)
|
||||||
|
{
|
||||||
|
(new GenerateAssemblies(this)).Fill(databaseSchema, ConnectionString);
|
||||||
|
(new GenerateFullText(this)).Fill(databaseSchema, ConnectionString);
|
||||||
|
}
|
||||||
|
/*}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
error = ex.StackTrace;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Thread t3 = new Thread(delegate()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{*/
|
||||||
|
(new GenerateStoredProcedures(this)).Fill(databaseSchema, ConnectionString);
|
||||||
|
(new GenerateFunctions(this)).Fill(databaseSchema, ConnectionString);
|
||||||
|
(new GenerateTriggers(this)).Fill(databaseSchema, ConnectionString, messages);
|
||||||
|
(new GenerateTextObjects(this)).Fill(databaseSchema, ConnectionString);
|
||||||
|
(new GenerateUsers(this)).Fill(databaseSchema, ConnectionString);
|
||||||
|
/*}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
error = ex.StackTrace;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
t1.Start();
|
||||||
|
t2.Start();
|
||||||
|
t3.Start();
|
||||||
|
t1.Join();
|
||||||
|
t2.Join();
|
||||||
|
t3.Join();*/
|
||||||
|
if (String.IsNullOrEmpty(error))
|
||||||
|
{
|
||||||
|
/*Las propiedades extendidas deben ir despues de haber capturado el resto de los objetos de la base*/
|
||||||
|
(new GenerateExtendedProperties(this)).Fill(databaseSchema, ConnectionString, messages);
|
||||||
|
databaseSchema.BuildDependency();
|
||||||
|
return databaseSchema;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
throw new SchemaException(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void tables_OnTableProgress(object sender, ProgressEventArgs e)
|
||||||
|
{
|
||||||
|
ProgressEventHandler.RaiseOnChange(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Static because Compare method is static; static events are not my favorite
|
||||||
|
public static event ProgressEventHandler.ProgressHandler OnCompareProgress;
|
||||||
|
|
||||||
|
internal static void RaiseOnCompareProgress(string formatString, params object[] formatParams)
|
||||||
|
{
|
||||||
|
OnCompareProgress?.Invoke(new ProgressEventArgs(String.Format(formatString, formatParams), -1));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Generates the differences to migrate a schema from origin to destination
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="origin">The Origin schema is the schema before our generated actions are applied.</param>
|
||||||
|
/// <param name="destination">The Destination schema is the schema after our actions are applied.</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static Database Compare(Database origin, Database destination)
|
||||||
|
{
|
||||||
|
Database merge = CompareDatabase.GenerateDifferences(origin, destination);
|
||||||
|
return merge;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,103 @@
|
|||||||
|
using System;
|
||||||
|
using System.Data.SqlClient;
|
||||||
|
using OpenDBDiff.Schema.SQLServer.Generates.Generates.Util;
|
||||||
|
using OpenDBDiff.Schema.SQLServer.Generates.Model;
|
||||||
|
|
||||||
|
namespace OpenDBDiff.Schema.SQLServer.Generates.Generates
|
||||||
|
{
|
||||||
|
public class GenerateAssemblies
|
||||||
|
{
|
||||||
|
private Generate root;
|
||||||
|
|
||||||
|
public GenerateAssemblies(Generate root)
|
||||||
|
{
|
||||||
|
this.root = root;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string GetSQLFiles()
|
||||||
|
{
|
||||||
|
return SQLQueries.SQLQueryFactory.Get("GetAssemblyFiles");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string GetSQL()
|
||||||
|
{
|
||||||
|
return SQLQueries.SQLQueryFactory.Get("GetAssemblies");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string ToHex(byte[] stream)
|
||||||
|
{
|
||||||
|
return ByteToHexEncoder.ByteArrayToHex(stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void FillFiles(Database database, string connectionString)
|
||||||
|
{
|
||||||
|
if (database.Options.Ignore.FilterAssemblies)
|
||||||
|
{
|
||||||
|
using (SqlConnection conn = new SqlConnection(connectionString))
|
||||||
|
{
|
||||||
|
using (SqlCommand command = new SqlCommand(GetSQLFiles(), conn))
|
||||||
|
{
|
||||||
|
conn.Open();
|
||||||
|
command.CommandTimeout = 0;
|
||||||
|
using (SqlDataReader reader = command.ExecuteReader())
|
||||||
|
{
|
||||||
|
while (reader.Read())
|
||||||
|
{
|
||||||
|
if (((int)reader["FileId"]) != 1)
|
||||||
|
{
|
||||||
|
Assembly assem = database.Assemblies[reader["Name"].ToString()];
|
||||||
|
AssemblyFile file = new AssemblyFile(assem, reader["FileName"].ToString(), ToHex((byte[])reader["FileContent"]));
|
||||||
|
assem.Files.Add(file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public void Fill(Database database, string connectionString)
|
||||||
|
{
|
||||||
|
int lastViewId = 0;
|
||||||
|
if (database.Options.Ignore.FilterAssemblies)
|
||||||
|
{
|
||||||
|
using (SqlConnection conn = new SqlConnection(connectionString))
|
||||||
|
{
|
||||||
|
using (SqlCommand command = new SqlCommand(GetSQL(), conn))
|
||||||
|
{
|
||||||
|
conn.Open();
|
||||||
|
command.CommandTimeout = 0;
|
||||||
|
using (SqlDataReader reader = command.ExecuteReader())
|
||||||
|
{
|
||||||
|
Assembly item = null;
|
||||||
|
while (reader.Read())
|
||||||
|
{
|
||||||
|
if (lastViewId != (int)reader["assembly_id"])
|
||||||
|
{
|
||||||
|
item = new Assembly(database)
|
||||||
|
{
|
||||||
|
Id = (int)reader["assembly_id"],
|
||||||
|
Name = reader["Name"].ToString(),
|
||||||
|
Owner = reader["Owner"].ToString(),
|
||||||
|
CLRName = reader["clr_name"].ToString(),
|
||||||
|
PermissionSet = reader["permission_set_desc"].ToString(),
|
||||||
|
Text = ToHex((byte[])reader["content"]),
|
||||||
|
Visible = (bool)reader["is_visible"]
|
||||||
|
};
|
||||||
|
lastViewId = item.Id;
|
||||||
|
database.Assemblies.Add(item);
|
||||||
|
}
|
||||||
|
if (!String.IsNullOrEmpty(reader["Dependency"].ToString()))
|
||||||
|
item.DependenciesOut.Add(reader["Dependency"].ToString());
|
||||||
|
if (!String.IsNullOrEmpty(reader["ObjectDependency"].ToString()))
|
||||||
|
item.DependenciesOut.Add(reader["ObjectDependency"].ToString());
|
||||||
|
if (!String.IsNullOrEmpty(reader["UDTName"].ToString()))
|
||||||
|
item.DependenciesOut.Add(reader["UDTName"].ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FillFiles(database, connectionString);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,303 @@
|
|||||||
|
using System;
|
||||||
|
using System.Data.SqlClient;
|
||||||
|
using System.Text;
|
||||||
|
using OpenDBDiff.Schema.Events;
|
||||||
|
using OpenDBDiff.Schema.Model;
|
||||||
|
using OpenDBDiff.Schema.SQLServer.Generates.Generates.SQLCommands;
|
||||||
|
using OpenDBDiff.Schema.SQLServer.Generates.Generates.Util;
|
||||||
|
using OpenDBDiff.Schema.SQLServer.Generates.Model;
|
||||||
|
|
||||||
|
namespace OpenDBDiff.Schema.SQLServer.Generates.Generates
|
||||||
|
{
|
||||||
|
public class GenerateConstraint
|
||||||
|
{
|
||||||
|
private Generate root;
|
||||||
|
|
||||||
|
public GenerateConstraint(Generate root)
|
||||||
|
{
|
||||||
|
this.root = root;
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Check Functions...
|
||||||
|
public void FillCheck(Database database, string connectionString)
|
||||||
|
{
|
||||||
|
int parentId = 0;
|
||||||
|
ISchemaBase table = null;
|
||||||
|
|
||||||
|
using (SqlConnection conn = new SqlConnection(connectionString))
|
||||||
|
{
|
||||||
|
using (SqlCommand command = new SqlCommand(ConstraintSQLCommand.GetCheck(database.Info.Version), conn))
|
||||||
|
{
|
||||||
|
root.RaiseOnReading(new ProgressEventArgs("Reading constraint...", Constants.READING_CONSTRAINTS));
|
||||||
|
conn.Open();
|
||||||
|
command.CommandTimeout = 0;
|
||||||
|
using (SqlDataReader reader = command.ExecuteReader())
|
||||||
|
{
|
||||||
|
Constraint item = null;
|
||||||
|
while (reader.Read())
|
||||||
|
{
|
||||||
|
root.RaiseOnReadingOne(reader["Name"]);
|
||||||
|
if (parentId != (int)reader["parent_object_id"])
|
||||||
|
{
|
||||||
|
parentId = (int)reader["parent_object_id"];
|
||||||
|
if (reader["ObjectType"].ToString().Trim().Equals("U"))
|
||||||
|
table = database.Tables.Find(parentId);
|
||||||
|
else
|
||||||
|
table = database.TablesTypes.Find(parentId);
|
||||||
|
}
|
||||||
|
if (table != null)
|
||||||
|
{
|
||||||
|
item = new Constraint(table);
|
||||||
|
item.Id = (int)reader["id"];
|
||||||
|
item.Name = reader["Name"].ToString();
|
||||||
|
item.Type = Constraint.ConstraintType.Check;
|
||||||
|
item.Definition = reader["Definition"].ToString();
|
||||||
|
item.WithNoCheck = (bool)reader["WithCheck"];
|
||||||
|
item.IsDisabled = (bool)reader["is_disabled"];
|
||||||
|
item.Owner = reader["Owner"].ToString();
|
||||||
|
if (database.Options.Ignore.FilterNotForReplication)
|
||||||
|
item.NotForReplication = (bool)reader["is_not_for_replication"];
|
||||||
|
if (reader["ObjectType"].ToString().Trim().Equals("U"))
|
||||||
|
((Table)table).Constraints.Add(item);
|
||||||
|
else
|
||||||
|
((TableType)table).Constraints.Add(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region ForeignKey Functions...
|
||||||
|
|
||||||
|
private static string GetSQLForeignKey()
|
||||||
|
{
|
||||||
|
return SQLQueries.SQLQueryFactory.Get("GetForeignKeys");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void FillForeignKey(Database database, string connectionString)
|
||||||
|
{
|
||||||
|
int lastid = 0;
|
||||||
|
int parentId = 0;
|
||||||
|
Table table = null;
|
||||||
|
|
||||||
|
using (SqlConnection conn = new SqlConnection(connectionString))
|
||||||
|
{
|
||||||
|
using (SqlCommand command = new SqlCommand(GetSQLForeignKey(), conn))
|
||||||
|
{
|
||||||
|
conn.Open();
|
||||||
|
command.CommandTimeout = 0;
|
||||||
|
using (SqlDataReader reader = command.ExecuteReader())
|
||||||
|
{
|
||||||
|
Constraint con = null;
|
||||||
|
while (reader.Read())
|
||||||
|
{
|
||||||
|
if (parentId != (int)reader["parent_object_id"])
|
||||||
|
{
|
||||||
|
parentId = (int)reader["parent_object_id"];
|
||||||
|
table = database.Tables.Find(parentId);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (table != null)
|
||||||
|
{
|
||||||
|
if (lastid != (int)reader["object_id"])
|
||||||
|
{
|
||||||
|
con = new Constraint(table);
|
||||||
|
con.Id = (int)reader["object_id"];
|
||||||
|
con.Name = reader["Name"].ToString();
|
||||||
|
con.Type = Constraint.ConstraintType.ForeignKey;
|
||||||
|
con.WithNoCheck = (bool)reader["is_not_trusted"];
|
||||||
|
con.RelationalTableFullName = "[" + reader["ReferenceOwner"].ToString() + "].[" + reader["TableRelationalName"].ToString() + "]";
|
||||||
|
con.RelationalTableId = (int)reader["TableRelationalId"];
|
||||||
|
con.Owner = reader["Owner"].ToString();
|
||||||
|
con.IsDisabled = (bool)reader["is_disabled"];
|
||||||
|
con.OnDeleteCascade = (byte)reader["delete_referential_action"];
|
||||||
|
con.OnUpdateCascade = (byte)reader["update_referential_action"];
|
||||||
|
if (database.Options.Ignore.FilterNotForReplication)
|
||||||
|
con.NotForReplication = (bool)reader["is_not_for_replication"];
|
||||||
|
lastid = (int)reader["object_id"];
|
||||||
|
table.Constraints.Add(con);
|
||||||
|
}
|
||||||
|
ConstraintColumn ccon = new ConstraintColumn(con);
|
||||||
|
ccon.Name = reader["ColumnName"].ToString();
|
||||||
|
ccon.ColumnRelationalName = reader["ColumnRelationalName"].ToString();
|
||||||
|
ccon.ColumnRelationalId = (int)reader["ColumnRelationalId"];
|
||||||
|
ccon.Id = (int)reader["ColumnId"];
|
||||||
|
ccon.KeyOrder = con.Columns.Count;
|
||||||
|
ccon.ColumnRelationalDataTypeId = (int)reader["user_type_id"];
|
||||||
|
//table.DependenciesCount++;
|
||||||
|
con.Columns.Add(ccon);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region UniqueKey Functions...
|
||||||
|
private static void FillUniqueKey(Database database, string connectionString)
|
||||||
|
{
|
||||||
|
int lastId = 0;
|
||||||
|
int parentId = 0;
|
||||||
|
bool change = false;
|
||||||
|
ISchemaBase table = null;
|
||||||
|
|
||||||
|
using (SqlConnection conn = new SqlConnection(connectionString))
|
||||||
|
{
|
||||||
|
using (SqlCommand command = new SqlCommand(ConstraintSQLCommand.GetUniqueKey(database.Info.Version, database.Info.Edition), conn))
|
||||||
|
{
|
||||||
|
conn.Open();
|
||||||
|
command.CommandTimeout = 0;
|
||||||
|
using (SqlDataReader reader = command.ExecuteReader())
|
||||||
|
{
|
||||||
|
Constraint con = null;
|
||||||
|
while (reader.Read())
|
||||||
|
{
|
||||||
|
if (parentId != (int)reader["ID"])
|
||||||
|
{
|
||||||
|
parentId = (int)reader["ID"];
|
||||||
|
if (reader["ObjectType"].ToString().Trim().Equals("U"))
|
||||||
|
table = database.Tables.Find(parentId);
|
||||||
|
else
|
||||||
|
table = database.TablesTypes.Find(parentId);
|
||||||
|
change = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
change = false;
|
||||||
|
|
||||||
|
if (table != null)
|
||||||
|
{
|
||||||
|
if ((lastId != (int)reader["Index_id"]) || (change))
|
||||||
|
{
|
||||||
|
con = new Constraint(table);
|
||||||
|
con.Name = reader["Name"].ToString();
|
||||||
|
con.Owner = (string)reader["Owner"];
|
||||||
|
con.Id = (int)reader["Index_id"];
|
||||||
|
con.Type = Constraint.ConstraintType.Unique;
|
||||||
|
con.Index.Id = (int)reader["Index_id"];
|
||||||
|
con.Index.AllowPageLocks = (bool)reader["allow_page_locks"];
|
||||||
|
con.Index.AllowRowLocks = (bool)reader["allow_row_locks"];
|
||||||
|
con.Index.FillFactor = (byte)reader["fill_factor"];
|
||||||
|
con.Index.IgnoreDupKey = (bool)reader["ignore_dup_key"];
|
||||||
|
con.Index.IsAutoStatistics = (bool)reader["ignore_dup_key"];
|
||||||
|
con.Index.IsDisabled = (bool)reader["is_disabled"];
|
||||||
|
con.Index.IsPadded = (bool)reader["is_padded"];
|
||||||
|
con.Index.IsPrimaryKey = false;
|
||||||
|
con.Index.IsUniqueKey = true;
|
||||||
|
con.Index.Type = (Index.IndexTypeEnum)(byte)reader["type"];
|
||||||
|
con.Index.Name = con.Name;
|
||||||
|
if (database.Options.Ignore.FilterTableFileGroup)
|
||||||
|
con.Index.FileGroup = reader["FileGroup"].ToString();
|
||||||
|
lastId = (int)reader["Index_id"];
|
||||||
|
if (reader["ObjectType"].ToString().Trim().Equals("U"))
|
||||||
|
((Table)table).Constraints.Add(con);
|
||||||
|
else
|
||||||
|
((TableType)table).Constraints.Add(con);
|
||||||
|
}
|
||||||
|
ConstraintColumn ccon = new ConstraintColumn(con);
|
||||||
|
ccon.Name = reader["ColumnName"].ToString();
|
||||||
|
ccon.IsIncluded = (bool)reader["is_included_column"];
|
||||||
|
ccon.Order = (bool)reader["is_descending_key"];
|
||||||
|
ccon.Id = (int)reader["column_id"];
|
||||||
|
ccon.DataTypeId = (int)reader["user_type_id"];
|
||||||
|
con.Columns.Add(ccon);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region PrimaryKey Functions...
|
||||||
|
private static void FillPrimaryKey(Database database, string connectionString)
|
||||||
|
{
|
||||||
|
int lastId = 0;
|
||||||
|
int parentId = 0;
|
||||||
|
bool change = false;
|
||||||
|
ISchemaBase table = null;
|
||||||
|
|
||||||
|
using (SqlConnection conn = new SqlConnection(connectionString))
|
||||||
|
{
|
||||||
|
using (SqlCommand command = new SqlCommand(ConstraintSQLCommand.GetPrimaryKey(database.Info.Version, null), conn))
|
||||||
|
{
|
||||||
|
conn.Open();
|
||||||
|
command.CommandTimeout = 0;
|
||||||
|
using (SqlDataReader reader = command.ExecuteReader())
|
||||||
|
{
|
||||||
|
Constraint con = null;
|
||||||
|
while (reader.Read())
|
||||||
|
{
|
||||||
|
if (parentId != (int)reader["ID"])
|
||||||
|
{
|
||||||
|
parentId = (int)reader["ID"];
|
||||||
|
if (reader["ObjectType"].ToString().Trim().Equals("U"))
|
||||||
|
table = database.Tables.Find(parentId);
|
||||||
|
else
|
||||||
|
table = database.TablesTypes.Find(parentId);
|
||||||
|
change = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
change = false;
|
||||||
|
|
||||||
|
if (table != null)
|
||||||
|
{
|
||||||
|
if ((lastId != (int)reader["Index_id"]) || (change))
|
||||||
|
{
|
||||||
|
con = new Constraint(table);
|
||||||
|
con.Id = (int)reader["Index_id"];
|
||||||
|
con.Name = (string)reader["Name"];
|
||||||
|
con.Owner = (string)reader["Owner"];
|
||||||
|
con.Type = Constraint.ConstraintType.PrimaryKey;
|
||||||
|
con.Index.Id = (int)reader["Index_id"];
|
||||||
|
con.Index.AllowPageLocks = (bool)reader["allow_page_locks"];
|
||||||
|
con.Index.AllowRowLocks = (bool)reader["allow_row_locks"];
|
||||||
|
con.Index.FillFactor = (byte)reader["fill_factor"];
|
||||||
|
con.Index.IgnoreDupKey = (bool)reader["ignore_dup_key"];
|
||||||
|
con.Index.IsAutoStatistics = (bool)reader["ignore_dup_key"];
|
||||||
|
con.Index.IsDisabled = (bool)reader["is_disabled"];
|
||||||
|
con.Index.IsPadded = (bool)reader["is_padded"];
|
||||||
|
con.Index.IsPrimaryKey = true;
|
||||||
|
con.Index.IsUniqueKey = false;
|
||||||
|
con.Index.Type = (Index.IndexTypeEnum)(byte)reader["type"];
|
||||||
|
con.Index.Name = con.Name;
|
||||||
|
if (database.Options.Ignore.FilterTableFileGroup)
|
||||||
|
con.Index.FileGroup = reader["FileGroup"].ToString();
|
||||||
|
lastId = (int)reader["Index_id"];
|
||||||
|
if (reader["ObjectType"].ToString().Trim().Equals("U"))
|
||||||
|
((Table)table).Constraints.Add(con);
|
||||||
|
else
|
||||||
|
((TableType)table).Constraints.Add(con);
|
||||||
|
}
|
||||||
|
ConstraintColumn ccon = new ConstraintColumn(con);
|
||||||
|
ccon.Name = (string)reader["ColumnName"];
|
||||||
|
ccon.IsIncluded = (bool)reader["is_included_column"];
|
||||||
|
ccon.Order = (bool)reader["is_descending_key"];
|
||||||
|
ccon.KeyOrder = (byte)reader["key_ordinal"];
|
||||||
|
ccon.Id = (int)reader["column_id"];
|
||||||
|
ccon.DataTypeId = (int)reader["user_type_id"];
|
||||||
|
con.Columns.Add(ccon);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
public void Fill(Database database, string connectionString)
|
||||||
|
{
|
||||||
|
if (database.Options.Ignore.FilterConstraintPK)
|
||||||
|
FillPrimaryKey(database, connectionString);
|
||||||
|
if (database.Options.Ignore.FilterConstraintFK)
|
||||||
|
FillForeignKey(database, connectionString);
|
||||||
|
if (database.Options.Ignore.FilterConstraintUK)
|
||||||
|
FillUniqueKey(database, connectionString);
|
||||||
|
if (database.Options.Ignore.FilterConstraintCheck)
|
||||||
|
FillCheck(database, connectionString);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,50 @@
|
|||||||
|
using System.Data.SqlClient;
|
||||||
|
using OpenDBDiff.Schema.SQLServer.Generates.Model;
|
||||||
|
|
||||||
|
namespace OpenDBDiff.Schema.SQLServer.Generates.Generates
|
||||||
|
{
|
||||||
|
public class GenerateDDLTriggers
|
||||||
|
{
|
||||||
|
private Generate root;
|
||||||
|
|
||||||
|
public GenerateDDLTriggers(Generate root)
|
||||||
|
{
|
||||||
|
this.root = root;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string GetSQL()
|
||||||
|
{
|
||||||
|
return SQLQueries.SQLQueryFactory.Get("GetDDLTriggers");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Fill(Database database, string connectionString)
|
||||||
|
{
|
||||||
|
if (database.Options.Ignore.FilterDDLTriggers)
|
||||||
|
{
|
||||||
|
using (SqlConnection conn = new SqlConnection(connectionString))
|
||||||
|
{
|
||||||
|
conn.Open();
|
||||||
|
using (SqlCommand command = new SqlCommand(GetSQL(), conn))
|
||||||
|
{
|
||||||
|
command.CommandTimeout = 0;
|
||||||
|
using (SqlDataReader reader = command.ExecuteReader())
|
||||||
|
{
|
||||||
|
while (reader.Read())
|
||||||
|
{
|
||||||
|
Trigger trigger = new Trigger(database);
|
||||||
|
trigger.Text = reader["Text"].ToString();
|
||||||
|
trigger.Name = reader["Name"].ToString();
|
||||||
|
trigger.InsteadOf = (bool)reader["is_instead_of_trigger"];
|
||||||
|
trigger.IsDisabled = (bool)reader["is_disabled"];
|
||||||
|
trigger.IsDDLTrigger = true;
|
||||||
|
trigger.NotForReplication = (bool)reader["is_not_for_replication"];
|
||||||
|
trigger.Owner = "";
|
||||||
|
database.DDLTriggers.Add(trigger);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,97 @@
|
|||||||
|
using System;
|
||||||
|
using System.Data.SqlClient;
|
||||||
|
using System.Globalization;
|
||||||
|
using OpenDBDiff.Schema.Misc;
|
||||||
|
using OpenDBDiff.Schema.SQLServer.Generates.Generates.SQLCommands;
|
||||||
|
using OpenDBDiff.Schema.SQLServer.Generates.Model;
|
||||||
|
using OpenDBDiff.Schema.SQLServer.Generates.Options;
|
||||||
|
#if DEBUG
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace OpenDBDiff.Schema.SQLServer.Generates.Generates
|
||||||
|
{
|
||||||
|
public class GenerateDatabase
|
||||||
|
{
|
||||||
|
private string connectioString;
|
||||||
|
private SqlOption objectFilter;
|
||||||
|
|
||||||
|
public bool UseDefaultVersionOnVersionParseError { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor de la clase.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="connectioString">Connection string de la base</param>
|
||||||
|
public GenerateDatabase(string connectioString, SqlOption filter)
|
||||||
|
{
|
||||||
|
this.connectioString = connectioString;
|
||||||
|
this.objectFilter = filter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DatabaseInfo Get(Database database)
|
||||||
|
{
|
||||||
|
DatabaseInfo item = new DatabaseInfo();
|
||||||
|
using (SqlConnection conn = new SqlConnection(connectioString))
|
||||||
|
{
|
||||||
|
using (SqlCommand command = new SqlCommand(DatabaseSQLCommand.GetVersion(database), conn))
|
||||||
|
{
|
||||||
|
conn.Open();
|
||||||
|
|
||||||
|
item.Server = conn.DataSource;
|
||||||
|
item.Database = conn.Database;
|
||||||
|
|
||||||
|
using (SqlDataReader reader = command.ExecuteReader())
|
||||||
|
{
|
||||||
|
if (reader.Read())
|
||||||
|
{
|
||||||
|
string versionValue = reader["Version"] as string;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// used to use the decimal as well when Azure was 10.25
|
||||||
|
var version = new Version(versionValue);
|
||||||
|
item.VersionNumber = float.Parse(String.Format("{0}.{1}", version.Major, version.Minor), CultureInfo.InvariantCulture);
|
||||||
|
|
||||||
|
if (reader.FieldCount > 1 && !reader.IsDBNull(1))
|
||||||
|
{
|
||||||
|
int edition;
|
||||||
|
if (int.TryParse(reader[1].ToString(), out edition)
|
||||||
|
&& Enum.IsDefined(typeof(DatabaseInfo.SQLServerEdition), edition))
|
||||||
|
{
|
||||||
|
item.SetEdition((DatabaseInfo.SQLServerEdition)edition);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (Exception notAGoodIdeaToCatchAllErrors)
|
||||||
|
{
|
||||||
|
var exception = new SchemaException(
|
||||||
|
String.Format("Error parsing ProductVersion. ({0})", versionValue ?? "[null]")
|
||||||
|
, notAGoodIdeaToCatchAllErrors);
|
||||||
|
|
||||||
|
if (!UseDefaultVersionOnVersionParseError)
|
||||||
|
{
|
||||||
|
throw exception;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
using (SqlCommand command = new SqlCommand(DatabaseSQLCommand.Get(item.Version, item.Edition, database), conn))
|
||||||
|
{
|
||||||
|
using (SqlDataReader reader = command.ExecuteReader())
|
||||||
|
{
|
||||||
|
if (reader.Read())
|
||||||
|
{
|
||||||
|
item.Collation = reader["Collation"].ToString();
|
||||||
|
item.HasFullTextEnabled = ((int)reader["IsFulltextEnabled"]) == 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,92 @@
|
|||||||
|
using System.Data.SqlClient;
|
||||||
|
using OpenDBDiff.Schema.SQLServer.Generates.Model;
|
||||||
|
|
||||||
|
namespace OpenDBDiff.Schema.SQLServer.Generates.Generates
|
||||||
|
{
|
||||||
|
public class GenerateFileGroups
|
||||||
|
{
|
||||||
|
private Generate root;
|
||||||
|
|
||||||
|
public GenerateFileGroups(Generate root)
|
||||||
|
{
|
||||||
|
this.root = root;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string GetSQLFile(FileGroup filegroup)
|
||||||
|
{
|
||||||
|
string query = SQLQueries.SQLQueryFactory.Get("GetDatabaseFile");
|
||||||
|
|
||||||
|
return query.Replace("{ID}", filegroup.Id.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string GetSQL()
|
||||||
|
{
|
||||||
|
return SQLQueries.SQLQueryFactory.Get("GetFileGroups");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void FillFiles(FileGroup filegroup, string connectionString)
|
||||||
|
{
|
||||||
|
using (SqlConnection conn = new SqlConnection(connectionString))
|
||||||
|
{
|
||||||
|
using (SqlCommand command = new SqlCommand(GetSQLFile(filegroup), conn))
|
||||||
|
{
|
||||||
|
conn.Open();
|
||||||
|
using (SqlDataReader reader = command.ExecuteReader())
|
||||||
|
{
|
||||||
|
while (reader.Read())
|
||||||
|
{
|
||||||
|
FileGroupFile item = new FileGroupFile(filegroup);
|
||||||
|
item.Id = (int)reader["file_id"];
|
||||||
|
item.Name = reader["name"].ToString();
|
||||||
|
item.Owner = "";
|
||||||
|
item.Growth = (int)reader["growth"];
|
||||||
|
item.IsPercentGrowth = (bool)reader["is_percent_growth"];
|
||||||
|
item.IsSparse = (bool)reader["is_sparse"];
|
||||||
|
item.MaxSize = (int)reader["max_size"];
|
||||||
|
item.PhysicalName = reader["physical_name"].ToString();
|
||||||
|
item.Size = (int)reader["size"];
|
||||||
|
item.Type = (byte)reader["type"];
|
||||||
|
filegroup.Files.Add(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Fill(Database database, string connectionString)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (database.Options.Ignore.FilterTableFileGroup)
|
||||||
|
{
|
||||||
|
using (SqlConnection conn = new SqlConnection(connectionString))
|
||||||
|
{
|
||||||
|
using (SqlCommand command = new SqlCommand(GetSQL(), conn))
|
||||||
|
{
|
||||||
|
conn.Open();
|
||||||
|
using (SqlDataReader reader = command.ExecuteReader())
|
||||||
|
{
|
||||||
|
while (reader.Read())
|
||||||
|
{
|
||||||
|
FileGroup item = new FileGroup(database);
|
||||||
|
item.Id = (int)reader["ID"];
|
||||||
|
item.Name = reader["name"].ToString();
|
||||||
|
item.Owner = "";
|
||||||
|
item.IsDefaultFileGroup = (bool)reader["is_default"];
|
||||||
|
item.IsReadOnly = (bool)reader["is_read_only"];
|
||||||
|
item.IsFileStream = reader["type"].Equals("FD");
|
||||||
|
FillFiles(item, connectionString);
|
||||||
|
database.FileGroups.Add(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,105 @@
|
|||||||
|
using System.Data.SqlClient;
|
||||||
|
using OpenDBDiff.Schema.Events;
|
||||||
|
using OpenDBDiff.Schema.Model;
|
||||||
|
using OpenDBDiff.Schema.SQLServer.Generates.Generates.SQLCommands;
|
||||||
|
using OpenDBDiff.Schema.SQLServer.Generates.Generates.Util;
|
||||||
|
using OpenDBDiff.Schema.SQLServer.Generates.Model;
|
||||||
|
|
||||||
|
namespace OpenDBDiff.Schema.SQLServer.Generates.Generates
|
||||||
|
{
|
||||||
|
public class GenerateIndex
|
||||||
|
{
|
||||||
|
private Generate root;
|
||||||
|
|
||||||
|
public GenerateIndex(Generate root)
|
||||||
|
{
|
||||||
|
this.root = root;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Fill(Database database, string connectionString)
|
||||||
|
{
|
||||||
|
int indexid = 0;
|
||||||
|
int parentId = 0;
|
||||||
|
bool change = false;
|
||||||
|
string type;
|
||||||
|
ISchemaBase parent = null;
|
||||||
|
root.RaiseOnReading(new ProgressEventArgs("Reading Index...", Constants.READING_INDEXES));
|
||||||
|
using (SqlConnection conn = new SqlConnection(connectionString))
|
||||||
|
{
|
||||||
|
using (SqlCommand command = new SqlCommand(IndexSQLCommand.Get(database.Info.Version, database.Info.Edition), conn))
|
||||||
|
{
|
||||||
|
conn.Open();
|
||||||
|
command.CommandTimeout = 0;
|
||||||
|
using (SqlDataReader reader = command.ExecuteReader())
|
||||||
|
{
|
||||||
|
Index item = null;
|
||||||
|
while (reader.Read())
|
||||||
|
{
|
||||||
|
root.RaiseOnReadingOne(reader["Name"]);
|
||||||
|
type = reader["ObjectType"].ToString().Trim();
|
||||||
|
if (parentId != (int)reader["object_id"])
|
||||||
|
{
|
||||||
|
parentId = (int)reader["object_id"];
|
||||||
|
if (type.Equals("V"))
|
||||||
|
parent = database.Views.Find(parentId);
|
||||||
|
else
|
||||||
|
parent = database.Tables.Find(parentId);
|
||||||
|
change = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
change = false;
|
||||||
|
|
||||||
|
if (parent != null)
|
||||||
|
{
|
||||||
|
if (indexid != (int)reader["index_id"] || change)
|
||||||
|
{
|
||||||
|
item = new Index(parent);
|
||||||
|
item.Name = reader["Name"].ToString();
|
||||||
|
item.Owner = parent.Owner;
|
||||||
|
item.Type = (Index.IndexTypeEnum)(byte)reader["type"];
|
||||||
|
item.Id = (int)reader["index_id"];
|
||||||
|
item.IgnoreDupKey = (bool)reader["ignore_dup_key"];
|
||||||
|
item.IsAutoStatistics = (bool)reader["NoAutomaticRecomputation"];
|
||||||
|
item.IsDisabled = (bool)reader["is_disabled"];
|
||||||
|
item.IsPrimaryKey = (bool)reader["is_primary_key"];
|
||||||
|
item.IsUniqueKey = (bool)reader["is_unique"];
|
||||||
|
if (database.Options.Ignore.FilterIndexRowLock)
|
||||||
|
{
|
||||||
|
item.AllowPageLocks = (bool)reader["allow_page_locks"];
|
||||||
|
item.AllowRowLocks = (bool)reader["allow_row_locks"];
|
||||||
|
}
|
||||||
|
if (database.Options.Ignore.FilterIndexFillFactor)
|
||||||
|
{
|
||||||
|
item.FillFactor = (byte)reader["fill_factor"];
|
||||||
|
item.IsPadded = (bool)reader["is_padded"];
|
||||||
|
}
|
||||||
|
if ((database.Options.Ignore.FilterTableFileGroup) && (item.Type != Index.IndexTypeEnum.XML))
|
||||||
|
item.FileGroup = reader["FileGroup"].ToString();
|
||||||
|
|
||||||
|
if ((database.Info.Version == DatabaseInfo.SQLServerVersion.SQLServer2008) && (database.Options.Ignore.FilterIndexFilter))
|
||||||
|
{
|
||||||
|
item.FilterDefintion = reader["FilterDefinition"].ToString();
|
||||||
|
}
|
||||||
|
indexid = (int)reader["index_id"];
|
||||||
|
if (type.Equals("V"))
|
||||||
|
((View)parent).Indexes.Add(item);
|
||||||
|
else
|
||||||
|
((Table)parent).Indexes.Add(item);
|
||||||
|
}
|
||||||
|
IndexColumn ccon = new IndexColumn(item.Parent);
|
||||||
|
ccon.Name = reader["ColumnName"].ToString();
|
||||||
|
ccon.IsIncluded = (bool)reader["is_included_column"];
|
||||||
|
ccon.Order = (bool)reader["is_descending_key"];
|
||||||
|
ccon.Id = (int)reader["column_id"];
|
||||||
|
ccon.KeyOrder = (byte)reader["key_ordinal"];
|
||||||
|
ccon.DataTypeId = (int)reader["user_type_id"];
|
||||||
|
if ((!ccon.IsIncluded) || (ccon.IsIncluded && database.Options.Ignore.FilterIndexIncludeColumns))
|
||||||
|
item.Columns.Add(ccon);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,46 @@
|
|||||||
|
using System.Data.SqlClient;
|
||||||
|
using OpenDBDiff.Schema.SQLServer.Generates.Model;
|
||||||
|
|
||||||
|
namespace OpenDBDiff.Schema.SQLServer.Generates.Generates
|
||||||
|
{
|
||||||
|
public class GenerateRules
|
||||||
|
{
|
||||||
|
private Generate root;
|
||||||
|
|
||||||
|
public GenerateRules(Generate root)
|
||||||
|
{
|
||||||
|
this.root = root;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string GetSQL()
|
||||||
|
{
|
||||||
|
return SQLQueries.SQLQueryFactory.Get("GetRules");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Fill(Database database, string connectionString)
|
||||||
|
{
|
||||||
|
if (database.Options.Ignore.FilterRules)
|
||||||
|
{
|
||||||
|
using (SqlConnection conn = new SqlConnection(connectionString))
|
||||||
|
{
|
||||||
|
using (SqlCommand command = new SqlCommand(GetSQL(), conn))
|
||||||
|
{
|
||||||
|
conn.Open();
|
||||||
|
using (SqlDataReader reader = command.ExecuteReader())
|
||||||
|
{
|
||||||
|
while (reader.Read())
|
||||||
|
{
|
||||||
|
Rule item = new Rule(database);
|
||||||
|
item.Id = (int)reader["object_id"];
|
||||||
|
item.Name = reader["Name"].ToString();
|
||||||
|
item.Owner = reader["Owner"].ToString();
|
||||||
|
item.Text = reader["Definition"].ToString();
|
||||||
|
database.Rules.Add(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,46 @@
|
|||||||
|
using System.Data.SqlClient;
|
||||||
|
using OpenDBDiff.Schema.SQLServer.Generates.Model;
|
||||||
|
|
||||||
|
namespace OpenDBDiff.Schema.SQLServer.Generates.Generates
|
||||||
|
{
|
||||||
|
public class GenerateSchemas
|
||||||
|
{
|
||||||
|
private Generate root;
|
||||||
|
|
||||||
|
public GenerateSchemas(Generate root)
|
||||||
|
{
|
||||||
|
this.root = root;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string GetSQL()
|
||||||
|
{
|
||||||
|
return SQLQueries.SQLQueryFactory.Get("GetSchemas");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Fill(Database database, string connectioString)
|
||||||
|
{
|
||||||
|
if (database.Options.Ignore.FilterSchema)
|
||||||
|
{
|
||||||
|
using (SqlConnection conn = new SqlConnection(connectioString))
|
||||||
|
{
|
||||||
|
using (SqlCommand command = new SqlCommand(GetSQL(), conn))
|
||||||
|
{
|
||||||
|
conn.Open();
|
||||||
|
command.CommandTimeout = 0;
|
||||||
|
using (SqlDataReader reader = command.ExecuteReader())
|
||||||
|
{
|
||||||
|
while (reader.Read())
|
||||||
|
{
|
||||||
|
Model.Schema item = new Model.Schema(database);
|
||||||
|
item.Id = (int)reader["schema_id"];
|
||||||
|
item.Name = reader["name"].ToString();
|
||||||
|
item.Owner = reader["owner"].ToString();
|
||||||
|
database.Schemas.Add(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,145 @@
|
|||||||
|
using OpenDBDiff.Schema.Events;
|
||||||
|
using OpenDBDiff.Schema.SQLServer.Generates.Generates.Util;
|
||||||
|
using OpenDBDiff.Schema.SQLServer.Generates.Model;
|
||||||
|
using System.Data.SqlClient;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace OpenDBDiff.Schema.SQLServer.Generates.Generates
|
||||||
|
{
|
||||||
|
public class GenerateStoredProcedures
|
||||||
|
{
|
||||||
|
private static int NameIndex = -1;
|
||||||
|
private static int object_idIndex = -1;
|
||||||
|
private static int ownerIndex = -1;
|
||||||
|
private static int typeIndex = -1;
|
||||||
|
|
||||||
|
private Generate root;
|
||||||
|
|
||||||
|
public GenerateStoredProcedures(Generate root)
|
||||||
|
{
|
||||||
|
this.root = root;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void InitIndex(SqlDataReader reader)
|
||||||
|
{
|
||||||
|
if (NameIndex == -1)
|
||||||
|
{
|
||||||
|
object_idIndex = reader.GetOrdinal("object_id");
|
||||||
|
NameIndex = reader.GetOrdinal("Name");
|
||||||
|
ownerIndex = reader.GetOrdinal("owner");
|
||||||
|
typeIndex = reader.GetOrdinal("type");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string GetSQLParameters()
|
||||||
|
{
|
||||||
|
return SQLQueries.SQLQueryFactory.Get("GetParameters");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string GetSQL(DatabaseInfo.SQLServerVersion version)
|
||||||
|
{
|
||||||
|
if (version == DatabaseInfo.SQLServerVersion.SQLServerAzure10)
|
||||||
|
{
|
||||||
|
return SQLQueries.SQLQueryFactory.Get("GetProcedures", DatabaseInfo.SQLServerVersion.SQLServerAzure10);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return SQLQueries.SQLQueryFactory.Get("GetProcedures");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void FillParameters(Database database, string connectionString)
|
||||||
|
{
|
||||||
|
using (SqlConnection conn = new SqlConnection(connectionString))
|
||||||
|
{
|
||||||
|
using (SqlCommand command = new SqlCommand(GetSQLParameters(), conn))
|
||||||
|
{
|
||||||
|
conn.Open();
|
||||||
|
command.CommandTimeout = 0;
|
||||||
|
using (SqlDataReader reader = command.ExecuteReader())
|
||||||
|
{
|
||||||
|
while (reader.Read())
|
||||||
|
{
|
||||||
|
var objectName = reader["ObjectName"].ToString();
|
||||||
|
|
||||||
|
if (database.CLRProcedures.Contains(objectName))
|
||||||
|
{
|
||||||
|
Parameter param = new Parameter();
|
||||||
|
param.Name = reader["Name"].ToString();
|
||||||
|
param.Type = reader["TypeName"].ToString();
|
||||||
|
param.Size = (short)reader["max_length"];
|
||||||
|
param.Scale = (byte)reader["scale"];
|
||||||
|
param.Precision = (byte)reader["precision"];
|
||||||
|
param.Output = (bool)reader["is_output"];
|
||||||
|
if (param.Type.Equals("nchar") || param.Type.Equals("nvarchar"))
|
||||||
|
{
|
||||||
|
if (param.Size != -1)
|
||||||
|
param.Size = param.Size / 2;
|
||||||
|
}
|
||||||
|
database.CLRProcedures[objectName].Parameters.Add(param);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Fill(Database database, string connectionString)
|
||||||
|
{
|
||||||
|
if ((database.Options.Ignore.FilterStoredProcedure) || (database.Options.Ignore.FilterCLRStoredProcedure))
|
||||||
|
{
|
||||||
|
root.RaiseOnReading(new ProgressEventArgs("Reading stored procedures...", Constants.READING_PROCEDURES));
|
||||||
|
using (SqlConnection conn = new SqlConnection(connectionString))
|
||||||
|
{
|
||||||
|
using (SqlCommand command = new SqlCommand(GetSQL(database.Info.Version), conn))
|
||||||
|
{
|
||||||
|
conn.Open();
|
||||||
|
command.CommandTimeout = 0;
|
||||||
|
using (SqlDataReader reader = command.ExecuteReader())
|
||||||
|
{
|
||||||
|
while (reader.Read())
|
||||||
|
{
|
||||||
|
InitIndex(reader);
|
||||||
|
root.RaiseOnReadingOne(reader[NameIndex]);
|
||||||
|
|
||||||
|
var objectType = reader[typeIndex].ToString().Trim();
|
||||||
|
switch (objectType)
|
||||||
|
{
|
||||||
|
case "P":
|
||||||
|
if (database.Options.Ignore.FilterStoredProcedure)
|
||||||
|
{
|
||||||
|
StoredProcedure item = new StoredProcedure(database);
|
||||||
|
item.Id = (int)reader[object_idIndex];
|
||||||
|
item.Name = (string)reader[NameIndex];
|
||||||
|
item.Owner = (string)reader[ownerIndex];
|
||||||
|
database.Procedures.Add(item);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "PC":
|
||||||
|
if (database.Options.Ignore.FilterCLRStoredProcedure)
|
||||||
|
{
|
||||||
|
CLRStoredProcedure item = new CLRStoredProcedure(database);
|
||||||
|
item.Id = (int)reader[object_idIndex];
|
||||||
|
item.Name = reader[NameIndex].ToString();
|
||||||
|
item.Owner = reader[ownerIndex].ToString();
|
||||||
|
item.IsAssembly = true;
|
||||||
|
item.AssemblyId = (int)reader["assembly_id"];
|
||||||
|
item.AssemblyName = reader["assembly_name"].ToString();
|
||||||
|
item.AssemblyClass = reader["assembly_class"].ToString();
|
||||||
|
item.AssemblyExecuteAs = reader["ExecuteAs"].ToString();
|
||||||
|
item.AssemblyMethod = reader["assembly_method"].ToString();
|
||||||
|
database.CLRProcedures.Add(item);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (database.CLRProcedures.Any())
|
||||||
|
FillParameters(database, connectionString);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,47 @@
|
|||||||
|
using System.Data.SqlClient;
|
||||||
|
using OpenDBDiff.Schema.SQLServer.Generates.Model;
|
||||||
|
|
||||||
|
namespace OpenDBDiff.Schema.SQLServer.Generates.Generates
|
||||||
|
{
|
||||||
|
public class GenerateSynonyms
|
||||||
|
{
|
||||||
|
private Generate root;
|
||||||
|
|
||||||
|
public GenerateSynonyms(Generate root)
|
||||||
|
{
|
||||||
|
this.root = root;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string GetSQL()
|
||||||
|
{
|
||||||
|
return SQLQueries.SQLQueryFactory.Get("GetSynonyms");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Fill(Database database, string connectionString)
|
||||||
|
{
|
||||||
|
if (database.Options.Ignore.FilterSynonyms)
|
||||||
|
{
|
||||||
|
using (SqlConnection conn = new SqlConnection(connectionString))
|
||||||
|
{
|
||||||
|
using (SqlCommand command = new SqlCommand(GetSQL(), conn))
|
||||||
|
{
|
||||||
|
conn.Open();
|
||||||
|
command.CommandTimeout = 0;
|
||||||
|
using (SqlDataReader reader = command.ExecuteReader())
|
||||||
|
{
|
||||||
|
while (reader.Read())
|
||||||
|
{
|
||||||
|
Synonym item = new Synonym(database);
|
||||||
|
item.Id = (int)reader["object_id"];
|
||||||
|
item.Name = reader["Name"].ToString();
|
||||||
|
item.Owner = reader["Owner"].ToString();
|
||||||
|
item.Value = reader["base_object_name"].ToString();
|
||||||
|
database.Synonyms.Add(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,313 @@
|
|||||||
|
using OpenDBDiff.Schema.Errors;
|
||||||
|
using OpenDBDiff.Schema.Events;
|
||||||
|
using OpenDBDiff.Schema.Model;
|
||||||
|
using OpenDBDiff.Schema.SQLServer.Generates.Generates.SQLCommands;
|
||||||
|
using OpenDBDiff.Schema.SQLServer.Generates.Generates.Util;
|
||||||
|
using OpenDBDiff.Schema.SQLServer.Generates.Model;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Data;
|
||||||
|
using System.Data.SqlClient;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Linq;
|
||||||
|
using Constraint = OpenDBDiff.Schema.SQLServer.Generates.Model.Constraint;
|
||||||
|
|
||||||
|
namespace OpenDBDiff.Schema.SQLServer.Generates.Generates
|
||||||
|
{
|
||||||
|
public class GenerateTables
|
||||||
|
{
|
||||||
|
private int colIDIndex = -1;
|
||||||
|
private int colNameIndex = -1;
|
||||||
|
private int colFormulaIndex = -1;
|
||||||
|
private int colIsPersistedIndex = -1;
|
||||||
|
private int colIsComputedIndex = -1;
|
||||||
|
private int colNullableIndex = -1;
|
||||||
|
private int colXmlSchemaIndex = -1;
|
||||||
|
private int colIs_xml_documentIndex = -1;
|
||||||
|
private int colPrecisionIndex = -1;
|
||||||
|
private int colScaleIndex = -1;
|
||||||
|
private int colDataUserTypeIdIndex = -1;
|
||||||
|
private int colIsUserDefinedTypeIndex = -1;
|
||||||
|
private int colSizeIndex = -1;
|
||||||
|
private int colHasIndexIndex = -1;
|
||||||
|
private int colHasComputedFormulaIndex = -1;
|
||||||
|
private int colIsRowGuidIndex = -1;
|
||||||
|
private int colTypeIndex = -1;
|
||||||
|
private int colOwnerType = -1;
|
||||||
|
private int colis_sparseIndex = -1;
|
||||||
|
private int colIs_FileStream = -1;
|
||||||
|
private int colDefaultIdIndex = -1;
|
||||||
|
private int colDefaultNameIndex = -1;
|
||||||
|
private int colDefaultDefinitionIndex = -1;
|
||||||
|
private int colrule_object_idIndex = -1;
|
||||||
|
private int colIsIdentityReplIndex = -1;
|
||||||
|
private int colCollationIndex = -1;
|
||||||
|
private int colIsIdentityIndex = -1;
|
||||||
|
private int colIdentSeedIndex = -1;
|
||||||
|
private int colIdentIncrementIndex = -1;
|
||||||
|
private int TableIdIndex = -1;
|
||||||
|
private int TableNameIndex = -1;
|
||||||
|
private int TableOwnerIndex = -1;
|
||||||
|
private int TableHasChangeTracking = -1;
|
||||||
|
private int TableHasChangeTrackingTrackColumn = -1;
|
||||||
|
private int TableLockEscalation = -1;
|
||||||
|
private int Text_In_Row_limitIndex = -1;
|
||||||
|
private int HasClusteredIndexIndex = -1;
|
||||||
|
private int large_value_types_out_of_rowIndex = -1;
|
||||||
|
private int HasVarDecimalIndex = -1;
|
||||||
|
private int FileGroupIndex = -1;
|
||||||
|
private int FileGroupTextIndex = -1;
|
||||||
|
private int FileGroupStreamIndex = -1;
|
||||||
|
|
||||||
|
private Generate root;
|
||||||
|
|
||||||
|
public GenerateTables(Generate root)
|
||||||
|
{
|
||||||
|
this.root = root;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void InitTableIndex(Database database, IDataRecord reader)
|
||||||
|
{
|
||||||
|
if (reader == null) throw new ArgumentNullException("reader");
|
||||||
|
if (TableIdIndex == -1)
|
||||||
|
{
|
||||||
|
TableIdIndex = reader.GetOrdinal("TableId");
|
||||||
|
TableNameIndex = reader.GetOrdinal("TableName");
|
||||||
|
TableOwnerIndex = reader.GetOrdinal("TableOwner");
|
||||||
|
Text_In_Row_limitIndex = reader.GetOrdinal("Text_In_Row_limit");
|
||||||
|
HasClusteredIndexIndex = reader.GetOrdinal("HasClusteredIndex");
|
||||||
|
large_value_types_out_of_rowIndex = reader.GetOrdinal("large_value_types_out_of_row");
|
||||||
|
HasVarDecimalIndex = reader.GetOrdinal("HasVarDecimal");
|
||||||
|
FileGroupIndex = reader.GetOrdinal("FileGroup");
|
||||||
|
FileGroupTextIndex = reader.GetOrdinal("FileGroupText");
|
||||||
|
if (database.Info.Version == DatabaseInfo.SQLServerVersion.SQLServer2008)
|
||||||
|
{
|
||||||
|
FileGroupStreamIndex = reader.GetOrdinal("FileGroupStream");
|
||||||
|
TableHasChangeTracking = reader.GetOrdinal("HasChangeTracking");
|
||||||
|
TableHasChangeTrackingTrackColumn = reader.GetOrdinal("HasChangeTrackingTrackColumn");
|
||||||
|
TableLockEscalation = reader.GetOrdinal("lock_escalation_desc");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void InitColIndex(Database database, IDataRecord reader)
|
||||||
|
{
|
||||||
|
if (reader == null) throw new ArgumentNullException("reader");
|
||||||
|
if (colNameIndex == -1)
|
||||||
|
{
|
||||||
|
colIDIndex = reader.GetOrdinal("ID");
|
||||||
|
colNameIndex = reader.GetOrdinal("Name");
|
||||||
|
colFormulaIndex = reader.GetOrdinal("Formula");
|
||||||
|
colIsPersistedIndex = reader.GetOrdinal("FormulaPersisted");
|
||||||
|
colIsComputedIndex = reader.GetOrdinal("IsComputed");
|
||||||
|
colNullableIndex = reader.GetOrdinal("IsNullable");
|
||||||
|
colOwnerType = reader.GetOrdinal("OwnerType");
|
||||||
|
colXmlSchemaIndex = reader.GetOrdinal("XmlSchema");
|
||||||
|
colIs_xml_documentIndex = reader.GetOrdinal("Is_xml_document");
|
||||||
|
colPrecisionIndex = reader.GetOrdinal("Precision");
|
||||||
|
colScaleIndex = reader.GetOrdinal("Scale");
|
||||||
|
colDataUserTypeIdIndex = reader.GetOrdinal("user_type_id");
|
||||||
|
colIsUserDefinedTypeIndex = reader.GetOrdinal("is_user_defined");
|
||||||
|
colSizeIndex = reader.GetOrdinal("Size");
|
||||||
|
colHasIndexIndex = reader.GetOrdinal("HasIndex");
|
||||||
|
colHasComputedFormulaIndex = reader.GetOrdinal("HasComputedFormula");
|
||||||
|
colIsRowGuidIndex = reader.GetOrdinal("IsRowGuid");
|
||||||
|
colTypeIndex = reader.GetOrdinal("Type");
|
||||||
|
colDefaultIdIndex = reader.GetOrdinal("DefaultId");
|
||||||
|
colDefaultNameIndex = reader.GetOrdinal("DefaultName");
|
||||||
|
colDefaultDefinitionIndex = reader.GetOrdinal("DefaultDefinition");
|
||||||
|
colrule_object_idIndex = reader.GetOrdinal("rule_object_id");
|
||||||
|
colIsIdentityReplIndex = reader.GetOrdinal("IsIdentityRepl");
|
||||||
|
colCollationIndex = reader.GetOrdinal("Collation");
|
||||||
|
colIsIdentityIndex = reader.GetOrdinal("IsIdentity");
|
||||||
|
colIdentSeedIndex = reader.GetOrdinal("IdentSeed");
|
||||||
|
colIdentIncrementIndex = reader.GetOrdinal("IdentIncrement");
|
||||||
|
if (database.Info.Version == DatabaseInfo.SQLServerVersion.SQLServer2008)
|
||||||
|
{
|
||||||
|
colis_sparseIndex = reader.GetOrdinal("is_sparse");
|
||||||
|
colIs_FileStream = reader.GetOrdinal("is_filestream");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void FillColumn<T>(ITable<T> table, SqlDataReader reader) where T : ISchemaBase
|
||||||
|
{
|
||||||
|
Database database = (Database)table.Parent;
|
||||||
|
|
||||||
|
InitColIndex(database, reader);
|
||||||
|
Column col = new Column((ISchemaBase)table);
|
||||||
|
col.Id = (int)reader[colIDIndex];
|
||||||
|
if (database.Options.Ignore.FilterColumnOrder)
|
||||||
|
col.Position = table.Columns.Count + 1;
|
||||||
|
|
||||||
|
if (database.Options.Ignore.FilterColumnCollation)
|
||||||
|
col.Collation = (string)reader[colCollationIndex];
|
||||||
|
|
||||||
|
if (database.Options.Ignore.FilterColumnIdentity)
|
||||||
|
{
|
||||||
|
col.IsIdentity = (bool)reader[colIsIdentityIndex];
|
||||||
|
if ((col.IsIdentity) || (col.IsIdentityForReplication))
|
||||||
|
{
|
||||||
|
if (!reader.IsDBNull(colIdentSeedIndex))
|
||||||
|
col.IdentitySeed = (long)(decimal)reader[colIdentSeedIndex];
|
||||||
|
else
|
||||||
|
col.IdentitySeed = 1;
|
||||||
|
|
||||||
|
if (!reader.IsDBNull(colIdentIncrementIndex))
|
||||||
|
col.IdentityIncrement = (int)(decimal)reader[colIdentIncrementIndex];
|
||||||
|
else
|
||||||
|
col.IdentityIncrement = 1;
|
||||||
|
}
|
||||||
|
if (database.Options.Ignore.FilterNotForReplication)
|
||||||
|
col.IsIdentityForReplication = ((int)reader[colIsIdentityReplIndex] == 1);
|
||||||
|
}
|
||||||
|
col.Name = (string)reader[colNameIndex];
|
||||||
|
col.Owner = table.Owner;
|
||||||
|
col.ComputedFormula = (string)reader[colFormulaIndex];
|
||||||
|
col.IsPersisted = (bool)reader[colIsPersistedIndex];
|
||||||
|
col.IsComputed = (bool)reader[colIsComputedIndex];
|
||||||
|
col.IsNullable = (bool)reader[colNullableIndex];
|
||||||
|
col.XmlSchema = reader[colXmlSchemaIndex].ToString();
|
||||||
|
col.IsXmlDocument = (bool)reader[colIs_xml_documentIndex];
|
||||||
|
col.Precision = (byte)reader[colPrecisionIndex];
|
||||||
|
col.Scale = (byte)reader[colScaleIndex];
|
||||||
|
col.DataUserTypeId = (int)reader[colDataUserTypeIdIndex];
|
||||||
|
col.IsUserDefinedType = (bool)reader[colIsUserDefinedTypeIndex];
|
||||||
|
if (!String.IsNullOrEmpty(reader[colSizeIndex].ToString()))
|
||||||
|
col.Size = (short)reader[colSizeIndex];
|
||||||
|
col.HasIndexDependencies = ((int)reader[colHasIndexIndex] == 1);
|
||||||
|
col.HasComputedDependencies = ((int)reader[colHasComputedFormulaIndex] == 1);
|
||||||
|
col.IsRowGuid = (bool)reader[colIsRowGuidIndex];
|
||||||
|
if (col.IsUserDefinedType)
|
||||||
|
col.Type = "[" + (string)reader[colOwnerType] + "].[" + (string)reader[colTypeIndex] + "]";
|
||||||
|
else
|
||||||
|
col.Type = (string)reader[colTypeIndex];
|
||||||
|
if (((Database)table.Parent).Info.Version == DatabaseInfo.SQLServerVersion.SQLServer2008)
|
||||||
|
{
|
||||||
|
col.IsSparse = (bool)reader[colis_sparseIndex];
|
||||||
|
col.IsFileStream = (bool)reader[colIs_FileStream];
|
||||||
|
}
|
||||||
|
if ((int)reader[colDefaultIdIndex] != 0)
|
||||||
|
{
|
||||||
|
col.DefaultConstraint = new ColumnConstraint(col)
|
||||||
|
{
|
||||||
|
Id = (int)reader[colDefaultIdIndex],
|
||||||
|
Owner = table.Owner,
|
||||||
|
Name = (string)reader[colDefaultNameIndex],
|
||||||
|
Type = Constraint.ConstraintType.Default,
|
||||||
|
Definition = (string)reader[colDefaultDefinitionIndex]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if ((int)reader[colrule_object_idIndex] != 0)
|
||||||
|
col.Rule = ((Database)table.Parent).Rules.Find((int)reader[colrule_object_idIndex]);
|
||||||
|
table.Columns.Add(col);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Fill(Database database, string connectionString, List<MessageLog> messages)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
root.RaiseOnReading(new ProgressEventArgs("Reading tables...", Constants.READING_TABLES));
|
||||||
|
FillTables(database, connectionString);
|
||||||
|
if (database.Tables.Any() || database.TablesTypes.Any())
|
||||||
|
{
|
||||||
|
if (database.Options.Ignore.FilterConstraint)
|
||||||
|
(new GenerateConstraint(root)).Fill(database, connectionString);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
messages.Add(new MessageLog(ex.Message, ex.StackTrace, MessageLog.LogType.Error));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void FillTables(Database database, string connectionString)
|
||||||
|
{
|
||||||
|
int textInRow;
|
||||||
|
Boolean largeValues;
|
||||||
|
Boolean varDecimal;
|
||||||
|
int lastObjectId = 0;
|
||||||
|
bool isTable = true;
|
||||||
|
ISchemaBase item = null;
|
||||||
|
|
||||||
|
using (SqlConnection conn = new SqlConnection(connectionString))
|
||||||
|
{
|
||||||
|
using (SqlCommand command = new SqlCommand(TableSQLCommand.GetTableDetail(database.Info.Version, database.Info.Edition), conn))
|
||||||
|
{
|
||||||
|
conn.Open();
|
||||||
|
command.CommandTimeout = 0;
|
||||||
|
using (SqlDataReader reader = command.ExecuteReader())
|
||||||
|
{
|
||||||
|
while (reader.Read())
|
||||||
|
{
|
||||||
|
InitTableIndex(database, reader);
|
||||||
|
root.RaiseOnReadingOne(reader[TableNameIndex]);
|
||||||
|
if (lastObjectId != (int)reader[TableIdIndex])
|
||||||
|
{
|
||||||
|
lastObjectId = (int)reader[TableIdIndex];
|
||||||
|
isTable = reader["ObjectType"].ToString().Trim().Equals("U");
|
||||||
|
if (isTable)
|
||||||
|
{
|
||||||
|
item = new Table(database);
|
||||||
|
item.Id = (int)reader[TableIdIndex];
|
||||||
|
item.Name = (string)reader[TableNameIndex];
|
||||||
|
item.Owner = (string)reader[TableOwnerIndex];
|
||||||
|
((Table)item).HasClusteredIndex = (int)reader[HasClusteredIndexIndex] == 1;
|
||||||
|
textInRow = (int)reader[Text_In_Row_limitIndex];
|
||||||
|
largeValues = (Boolean)reader[large_value_types_out_of_rowIndex];
|
||||||
|
varDecimal = ((int)reader[HasVarDecimalIndex]) == 1;
|
||||||
|
if (database.Options.Ignore.FilterTableFileGroup)
|
||||||
|
{
|
||||||
|
((Table)item).FileGroup = (string)reader[FileGroupIndex];
|
||||||
|
((Table)item).FileGroupText = (string)reader[FileGroupTextIndex];
|
||||||
|
if (database.Info.Version == DatabaseInfo.SQLServerVersion.SQLServer2008)
|
||||||
|
{
|
||||||
|
if (database.Options.Ignore.FilterTableChangeTracking)
|
||||||
|
{
|
||||||
|
((Table)item).FileGroupStream = (string)reader[FileGroupStreamIndex];
|
||||||
|
((Table)item).HasChangeTracking = ((int)reader[TableHasChangeTracking]) == 1;
|
||||||
|
((Table)item).HasChangeTrackingTrackColumn = ((int)reader[TableHasChangeTrackingTrackColumn]) == 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (database.Options.Ignore.FilterTableOption)
|
||||||
|
{
|
||||||
|
if (textInRow > 0) ((Table)item).Options.Add(new TableOption("TextInRow", textInRow.ToString(CultureInfo.InvariantCulture), item));
|
||||||
|
if (largeValues) ((Table)item).Options.Add(new TableOption("LargeValues", "1", item));
|
||||||
|
if (varDecimal) ((Table)item).Options.Add(new TableOption("VarDecimal", "1", item));
|
||||||
|
}
|
||||||
|
if ((database.Options.Ignore.FilterTableLockEscalation) && (database.Info.Version == DatabaseInfo.SQLServerVersion.SQLServer2008))
|
||||||
|
((Table)item).Options.Add(new TableOption("LockEscalation", (string)reader[TableLockEscalation], item));
|
||||||
|
else
|
||||||
|
((Table)item).Options.Add(new TableOption("LockEscalation", "TABLE", item));
|
||||||
|
database.Tables.Add((Table)item);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
item = new TableType(database)
|
||||||
|
{
|
||||||
|
Id = (int)reader[TableIdIndex],
|
||||||
|
Name = (string)reader[TableNameIndex],
|
||||||
|
Owner = (string)reader[TableOwnerIndex]
|
||||||
|
};
|
||||||
|
database.TablesTypes.Add((TableType)item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isTable)
|
||||||
|
{
|
||||||
|
if (database.Options.Ignore.FilterTable)
|
||||||
|
FillColumn((ITable<Table>)item, reader);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (database.Options.Ignore.FilterUserDataType)
|
||||||
|
FillColumn((ITable<TableType>)item, reader);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//tables.ToSQL();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,114 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Data.SqlClient;
|
||||||
|
using OpenDBDiff.Schema.Errors;
|
||||||
|
using OpenDBDiff.Schema.Events;
|
||||||
|
using OpenDBDiff.Schema.Model;
|
||||||
|
using OpenDBDiff.Schema.SQLServer.Generates.Generates.Util;
|
||||||
|
using OpenDBDiff.Schema.SQLServer.Generates.Model;
|
||||||
|
using OpenDBDiff.Schema.SQLServer.Generates.Options;
|
||||||
|
|
||||||
|
namespace OpenDBDiff.Schema.SQLServer.Generates.Generates
|
||||||
|
{
|
||||||
|
public class GenerateTriggers
|
||||||
|
{
|
||||||
|
private Generate root;
|
||||||
|
|
||||||
|
public GenerateTriggers(Generate root)
|
||||||
|
{
|
||||||
|
this.root = root;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string GetSQL(DatabaseInfo.SQLServerVersion version, SqlOption options)
|
||||||
|
{
|
||||||
|
if (version == DatabaseInfo.SQLServerVersion.SQLServerAzure10)
|
||||||
|
{
|
||||||
|
return SQLQueries.SQLQueryFactory.Get("GetTriggers", version);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return SQLQueries.SQLQueryFactory.Get("GetTriggers");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Fill(Database database, string connectionString, List<MessageLog> messages)
|
||||||
|
{
|
||||||
|
int parentId = 0;
|
||||||
|
ISchemaBase parent = null;
|
||||||
|
string type;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (database.Options.Ignore.FilterTrigger)
|
||||||
|
{
|
||||||
|
root.RaiseOnReading(new ProgressEventArgs("Reading Triggers...", Constants.READING_TRIGGERS));
|
||||||
|
using (SqlConnection conn = new SqlConnection(connectionString))
|
||||||
|
{
|
||||||
|
using (SqlCommand command = new SqlCommand(GetSQL(database.Info.Version, database.Options), conn))
|
||||||
|
{
|
||||||
|
conn.Open();
|
||||||
|
command.CommandTimeout = 0;
|
||||||
|
using (SqlDataReader reader = command.ExecuteReader())
|
||||||
|
{
|
||||||
|
while (reader.Read())
|
||||||
|
{
|
||||||
|
root.RaiseOnReadingOne(reader["Name"]);
|
||||||
|
type = reader["ObjectType"].ToString().Trim();
|
||||||
|
if (parentId != (int)reader["parent_id"])
|
||||||
|
{
|
||||||
|
parentId = (int)reader["parent_id"];
|
||||||
|
if (type.Equals("V"))
|
||||||
|
parent = database.Views.Find(parentId);
|
||||||
|
else
|
||||||
|
parent = database.Tables.Find(parentId);
|
||||||
|
}
|
||||||
|
if (reader["type"].Equals("TR"))
|
||||||
|
{
|
||||||
|
Trigger item = new Trigger(parent);
|
||||||
|
item.Id = (int)reader["object_id"];
|
||||||
|
item.Name = reader["Name"].ToString();
|
||||||
|
item.InsteadOf = (bool)reader["is_instead_of_trigger"];
|
||||||
|
item.IsDisabled = (bool)reader["is_disabled"];
|
||||||
|
item.IsDDLTrigger = false;
|
||||||
|
item.Owner = reader["Owner"].ToString();
|
||||||
|
if (database.Options.Ignore.FilterNotForReplication)
|
||||||
|
item.NotForReplication = (bool)reader["is_not_for_replication"];
|
||||||
|
if (type.Equals("V"))
|
||||||
|
((View)parent).Triggers.Add(item);
|
||||||
|
else
|
||||||
|
((Table)parent).Triggers.Add(item);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CLRTrigger item = new CLRTrigger(parent);
|
||||||
|
item.Id = (int)reader["object_id"];
|
||||||
|
item.Name = reader["Name"].ToString();
|
||||||
|
item.IsDelete = (bool)reader["IsDelete"];
|
||||||
|
item.IsUpdate = (bool)reader["IsUpdate"];
|
||||||
|
item.IsInsert = (bool)reader["IsInsert"];
|
||||||
|
item.Owner = reader["Owner"].ToString();
|
||||||
|
item.IsAssembly = true;
|
||||||
|
item.AssemblyId = (int)reader["assembly_id"];
|
||||||
|
item.AssemblyName = reader["assembly_name"].ToString();
|
||||||
|
item.AssemblyClass = reader["assembly_class"].ToString();
|
||||||
|
item.AssemblyExecuteAs = reader["ExecuteAs"].ToString();
|
||||||
|
item.AssemblyMethod = reader["assembly_method"].ToString();
|
||||||
|
if (type.Equals("V"))
|
||||||
|
((View)parent).CLRTriggers.Add(item);
|
||||||
|
else
|
||||||
|
((Table)parent).CLRTriggers.Add(item);
|
||||||
|
/*if (!database.Options.Ignore.FilterIgnoreNotForReplication)
|
||||||
|
trigger.NotForReplication = (bool)reader["is_not_for_replication"];*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
messages.Add(new MessageLog(ex.Message, ex.StackTrace, MessageLog.LogType.Error));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,106 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Data.SqlClient;
|
||||||
|
using OpenDBDiff.Schema.Errors;
|
||||||
|
using OpenDBDiff.Schema.Events;
|
||||||
|
using OpenDBDiff.Schema.Model;
|
||||||
|
using OpenDBDiff.Schema.SQLServer.Generates.Generates.SQLCommands;
|
||||||
|
using OpenDBDiff.Schema.SQLServer.Generates.Generates.Util;
|
||||||
|
using OpenDBDiff.Schema.SQLServer.Generates.Model;
|
||||||
|
|
||||||
|
namespace OpenDBDiff.Schema.SQLServer.Generates.Generates
|
||||||
|
{
|
||||||
|
public class GenerateUserDataTypes
|
||||||
|
{
|
||||||
|
private readonly Generate root;
|
||||||
|
|
||||||
|
public GenerateUserDataTypes(Generate root)
|
||||||
|
{
|
||||||
|
this.root = root;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string GetSQLColumnsDependencies()
|
||||||
|
{
|
||||||
|
return SQLQueries.SQLQueryFactory.Get("GetSQLColumnsDependencies");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void FillColumnsDependencies(SchemaList<UserDataType, Database> types, string connectionString)
|
||||||
|
{
|
||||||
|
if (types == null) throw new ArgumentNullException("types");
|
||||||
|
using (SqlConnection conn = new SqlConnection(connectionString))
|
||||||
|
{
|
||||||
|
using (SqlCommand command = new SqlCommand(GetSQLColumnsDependencies(), conn))
|
||||||
|
{
|
||||||
|
conn.Open();
|
||||||
|
command.CommandTimeout = 0;
|
||||||
|
using (SqlDataReader reader = command.ExecuteReader())
|
||||||
|
{
|
||||||
|
while (reader.Read())
|
||||||
|
{
|
||||||
|
types[reader["TypeName"].ToString()].Dependencies.Add(new ObjectDependency(reader["TableName"].ToString(), reader["ColumnName"].ToString(), ConvertType.GetObjectType(reader["Type"].ToString())));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Fill(Database database, string connectionString, List<MessageLog> messages)
|
||||||
|
{
|
||||||
|
//not supported in azure yet http://msdn.microsoft.com/en-us/library/ee336233.aspx
|
||||||
|
if (database.Info.Version == DatabaseInfo.SQLServerVersion.SQLServerAzure10) return;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (database.Options.Ignore.FilterUserDataType)
|
||||||
|
{
|
||||||
|
root.RaiseOnReading(new ProgressEventArgs("Reading UDT...", Constants.READING_UDT));
|
||||||
|
using (SqlConnection conn = new SqlConnection(connectionString))
|
||||||
|
{
|
||||||
|
using (SqlCommand command = new SqlCommand(UserDataTypeCommand.Get(database.Info.Version, database.Info.Edition), conn))
|
||||||
|
{
|
||||||
|
conn.Open();
|
||||||
|
command.CommandTimeout = 0;
|
||||||
|
using (SqlDataReader reader = command.ExecuteReader())
|
||||||
|
{
|
||||||
|
while (reader.Read())
|
||||||
|
{
|
||||||
|
root.RaiseOnReadingOne(reader["Name"]);
|
||||||
|
UserDataType item = new UserDataType(database);
|
||||||
|
item.Id = (int)reader["tid"];
|
||||||
|
item.AllowNull = (bool)reader["is_nullable"];
|
||||||
|
item.Size = (short)reader["max_length"];
|
||||||
|
item.Name = reader["Name"].ToString();
|
||||||
|
item.Owner = reader["owner"].ToString();
|
||||||
|
item.Precision = int.Parse(reader["precision"].ToString());
|
||||||
|
item.Scale = int.Parse(reader["scale"].ToString());
|
||||||
|
if (!String.IsNullOrEmpty(reader["defaultname"].ToString()))
|
||||||
|
{
|
||||||
|
item.Default.Name = reader["defaultname"].ToString();
|
||||||
|
item.Default.Owner = reader["defaultowner"].ToString();
|
||||||
|
}
|
||||||
|
if (!String.IsNullOrEmpty(reader["rulename"].ToString()))
|
||||||
|
{
|
||||||
|
item.Rule.Name = reader["rulename"].ToString();
|
||||||
|
item.Rule.Owner = reader["ruleowner"].ToString();
|
||||||
|
}
|
||||||
|
item.Type = reader["basetypename"].ToString();
|
||||||
|
item.IsAssembly = (bool)reader["is_assembly_type"];
|
||||||
|
item.AssemblyId = (int)reader["assembly_id"];
|
||||||
|
item.AssemblyName = reader["assembly_name"].ToString();
|
||||||
|
item.AssemblyClass = reader["assembly_class"].ToString();
|
||||||
|
database.UserTypes.Add(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (database.Options.Ignore.FilterTable)
|
||||||
|
FillColumnsDependencies(database.UserTypes, connectionString);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
messages.Add(new MessageLog(ex.Message, ex.StackTrace, MessageLog.LogType.Error));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,77 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Data.SqlClient;
|
||||||
|
using OpenDBDiff.Schema.Errors;
|
||||||
|
using OpenDBDiff.Schema.Events;
|
||||||
|
using OpenDBDiff.Schema.SQLServer.Generates.Generates.SQLCommands;
|
||||||
|
using OpenDBDiff.Schema.SQLServer.Generates.Generates.Util;
|
||||||
|
using OpenDBDiff.Schema.SQLServer.Generates.Model;
|
||||||
|
|
||||||
|
namespace OpenDBDiff.Schema.SQLServer.Generates.Generates
|
||||||
|
{
|
||||||
|
public class GenerateViews
|
||||||
|
{
|
||||||
|
private Generate root;
|
||||||
|
|
||||||
|
public GenerateViews(Generate root)
|
||||||
|
{
|
||||||
|
this.root = root;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Fill(Database database, string connectionString, List<MessageLog> messages)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
root.RaiseOnReading(new ProgressEventArgs("Reading views...", Constants.READING_VIEWS));
|
||||||
|
if (database.Options.Ignore.FilterView)
|
||||||
|
{
|
||||||
|
FillView(database, connectionString);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
messages.Add(new MessageLog(ex.Message, ex.StackTrace, MessageLog.LogType.Error));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void FillView(Database database, string connectionString)
|
||||||
|
{
|
||||||
|
int lastViewId = 0;
|
||||||
|
using (SqlConnection conn = new SqlConnection(connectionString))
|
||||||
|
{
|
||||||
|
using (SqlCommand command = new SqlCommand(ViewSQLCommand.GetView(database.Info.Version, database.Info.Edition), conn))
|
||||||
|
{
|
||||||
|
conn.Open();
|
||||||
|
command.CommandTimeout = 0;
|
||||||
|
using (SqlDataReader reader = command.ExecuteReader())
|
||||||
|
{
|
||||||
|
View item = null;
|
||||||
|
while (reader.Read())
|
||||||
|
{
|
||||||
|
root.RaiseOnReadingOne(reader["name"]);
|
||||||
|
if (lastViewId != (int)reader["object_id"])
|
||||||
|
{
|
||||||
|
item = new View(database);
|
||||||
|
item.Id = (int)reader["object_id"];
|
||||||
|
item.Name = reader["name"].ToString();
|
||||||
|
item.Owner = reader["owner"].ToString();
|
||||||
|
item.IsSchemaBinding = reader["IsSchemaBound"].ToString().Equals("1");
|
||||||
|
database.Views.Add(item);
|
||||||
|
lastViewId = item.Id;
|
||||||
|
}
|
||||||
|
if (item.IsSchemaBinding)
|
||||||
|
{
|
||||||
|
if (!reader.IsDBNull(reader.GetOrdinal("referenced_major_id")))
|
||||||
|
database.Dependencies.Add(database, (int)reader["referenced_major_id"], item);
|
||||||
|
if (!String.IsNullOrEmpty(reader["TableName"].ToString()))
|
||||||
|
item.DependenciesIn.Add(reader["TableName"].ToString());
|
||||||
|
if (!String.IsNullOrEmpty(reader["DependOut"].ToString()))
|
||||||
|
item.DependenciesOut.Add(reader["DependOut"].ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,85 @@
|
|||||||
|
using System.Data.SqlClient;
|
||||||
|
using System.Text;
|
||||||
|
using OpenDBDiff.Schema.Events;
|
||||||
|
using OpenDBDiff.Schema.Model;
|
||||||
|
using OpenDBDiff.Schema.SQLServer.Generates.Generates.Util;
|
||||||
|
using OpenDBDiff.Schema.SQLServer.Generates.Model;
|
||||||
|
|
||||||
|
namespace OpenDBDiff.Schema.SQLServer.Generates.Generates
|
||||||
|
{
|
||||||
|
public class GenerateXMLSchemas
|
||||||
|
{
|
||||||
|
private Generate root;
|
||||||
|
|
||||||
|
public GenerateXMLSchemas(Generate root)
|
||||||
|
{
|
||||||
|
this.root = root;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string GetSQLColumnsDependencies()
|
||||||
|
{
|
||||||
|
return SQLQueries.SQLQueryFactory.Get("GetXMLSchemaCollections");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string GetSQLXMLSchema()
|
||||||
|
{
|
||||||
|
return SQLQueries.SQLQueryFactory.Get("GetSQLXMLSchema");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void FillColumnsDependencies(SchemaList<XMLSchema, Database> items, string connectionString)
|
||||||
|
{
|
||||||
|
using (SqlConnection conn = new SqlConnection(connectionString))
|
||||||
|
{
|
||||||
|
using (SqlCommand command = new SqlCommand(GetSQLColumnsDependencies(), conn))
|
||||||
|
{
|
||||||
|
conn.Open();
|
||||||
|
command.CommandTimeout = 0;
|
||||||
|
using (SqlDataReader reader = command.ExecuteReader())
|
||||||
|
{
|
||||||
|
while (reader.Read())
|
||||||
|
{
|
||||||
|
items[reader["XMLName"].ToString()].Dependencies.Add(new ObjectDependency(reader["TableName"].ToString(), reader["ColumnName"].ToString(), ConvertType.GetObjectType(reader["Type"].ToString())));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Fill(Database database, string connectionString)
|
||||||
|
{
|
||||||
|
//TODO XML_SCHEMA_NAMESPACE function not supported in Azure, is there a workaround?
|
||||||
|
//not supported in azure yet
|
||||||
|
if (database.Info.Version == DatabaseInfo.SQLServerVersion.SQLServerAzure10) return;
|
||||||
|
|
||||||
|
|
||||||
|
if (database.Options.Ignore.FilterXMLSchema)
|
||||||
|
{
|
||||||
|
root.RaiseOnReading(new ProgressEventArgs("Reading XML Schema...", Constants.READING_XMLSCHEMAS));
|
||||||
|
using (SqlConnection conn = new SqlConnection(connectionString))
|
||||||
|
{
|
||||||
|
using (SqlCommand command = new SqlCommand(GetSQLXMLSchema(), conn))
|
||||||
|
{
|
||||||
|
conn.Open();
|
||||||
|
command.CommandTimeout = 0;
|
||||||
|
using (SqlDataReader reader = command.ExecuteReader())
|
||||||
|
{
|
||||||
|
while (reader.Read())
|
||||||
|
{
|
||||||
|
root.RaiseOnReadingOne(reader["name"]);
|
||||||
|
XMLSchema item = new XMLSchema(database);
|
||||||
|
item.Id = (int)reader["ID"];
|
||||||
|
item.Name = reader["name"].ToString();
|
||||||
|
item.Owner = reader["owner"].ToString();
|
||||||
|
item.Text = reader["Text"].ToString();
|
||||||
|
database.XmlSchemas.Add(item);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (database.Options.Ignore.FilterTable)
|
||||||
|
FillColumnsDependencies(database.XmlSchemas, connectionString);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue