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