├── .gitignore ├── LICENSE ├── README.md ├── README.zh-cn.md ├── index.js ├── package.json ├── preview.png ├── preview.zh-cn.png └── ux ├── DatabaseStack.htm ├── DatabaseStack.json └── dndTree.js /.gitignore: -------------------------------------------------------------------------------- 1 | ################# 2 | ## Eclipse 3 | ################# 4 | 5 | *.pydevproject 6 | .project 7 | .metadata 8 | bin/ 9 | tmp/ 10 | *.tmp 11 | *.bak 12 | *.swp 13 | *~.nib 14 | local.properties 15 | .classpath 16 | .settings/ 17 | .loadpath 18 | 19 | # External tool builders 20 | .externalToolBuilders/ 21 | 22 | # Locally stored "Eclipse launch configurations" 23 | *.launch 24 | 25 | # CDT-specific 26 | .cproject 27 | 28 | # PDT-specific 29 | .buildpath 30 | 31 | 32 | ################# 33 | ## Visual Studio 34 | ################# 35 | 36 | ## Ignore Visual Studio temporary files, build results, and 37 | ## files generated by popular Visual Studio add-ons. 38 | 39 | # User-specific files 40 | *.suo 41 | *.user 42 | *.sln.docstates 43 | 44 | # Build results 45 | 46 | [Dd]ebug/ 47 | [Rr]elease/ 48 | x64/ 49 | build/ 50 | [Bb]in/ 51 | [Oo]bj/ 52 | 53 | # MSTest test Results 54 | [Tt]est[Rr]esult*/ 55 | [Bb]uild[Ll]og.* 56 | 57 | *_i.c 58 | *_p.c 59 | *.ilk 60 | *.meta 61 | *.obj 62 | *.pch 63 | *.pdb 64 | *.pgc 65 | *.pgd 66 | *.rsp 67 | *.sbr 68 | *.tlb 69 | *.tli 70 | *.tlh 71 | *.tmp 72 | *.tmp_proj 73 | *.log 74 | *.vspscc 75 | *.vssscc 76 | .builds 77 | *.pidb 78 | *.log 79 | *.scc 80 | 81 | # Visual C++ cache files 82 | ipch/ 83 | *.aps 84 | *.ncb 85 | *.opensdf 86 | *.sdf 87 | *.cachefile 88 | 89 | # Visual Studio profiler 90 | *.psess 91 | *.vsp 92 | *.vspx 93 | 94 | # Guidance Automation Toolkit 95 | *.gpState 96 | 97 | # ReSharper is a .NET coding add-in 98 | _ReSharper*/ 99 | *.[Rr]e[Ss]harper 100 | 101 | # TeamCity is a build add-in 102 | _TeamCity* 103 | 104 | # DotCover is a Code Coverage Tool 105 | *.dotCover 106 | 107 | # NCrunch 108 | *.ncrunch* 109 | .*crunch*.local.xml 110 | 111 | # Installshield output folder 112 | [Ee]xpress/ 113 | 114 | # DocProject is a documentation generator add-in 115 | DocProject/buildhelp/ 116 | DocProject/Help/*.HxT 117 | DocProject/Help/*.HxC 118 | DocProject/Help/*.hhc 119 | DocProject/Help/*.hhk 120 | DocProject/Help/*.hhp 121 | DocProject/Help/Html2 122 | DocProject/Help/html 123 | 124 | # Click-Once directory 125 | publish/ 126 | 127 | # Publish Web Output 128 | *.Publish.xml 129 | *.pubxml 130 | *.publishproj 131 | 132 | # NuGet Packages Directory 133 | ## TODO: If you have NuGet Package Restore enabled, uncomment the next line 134 | #packages/ 135 | 136 | # Windows Azure Build Output 137 | csx 138 | *.build.csdef 139 | 140 | # Windows Store app package directory 141 | AppPackages/ 142 | 143 | # Others 144 | sql/ 145 | *.Cache 146 | ClientBin/ 147 | [Ss]tyle[Cc]op.* 148 | ~$* 149 | *~ 150 | *.dbmdl 151 | *.[Pp]ublish.xml 152 | *.pfx 153 | *.publishsettings 154 | 155 | # RIA/Silverlight projects 156 | Generated_Code/ 157 | 158 | # Backup & report files from converting an old project file to a newer 159 | # Visual Studio version. Backup files are not needed, because we have git ;-) 160 | _UpgradeReport_Files/ 161 | Backup*/ 162 | UpgradeLog*.XML 163 | UpgradeLog*.htm 164 | 165 | # SQL Server files 166 | App_Data/*.mdf 167 | App_Data/*.ldf 168 | 169 | ############# 170 | ## Windows detritus 171 | ############# 172 | 173 | # Windows image file caches 174 | Thumbs.db 175 | ehthumbs.db 176 | 177 | # Folder config file 178 | Desktop.ini 179 | 180 | # Recycle Bin used on file shares 181 | $RECYCLE.BIN/ 182 | 183 | # Mac crap 184 | .DS_Store 185 | 186 | 187 | ############# 188 | ## Python 189 | ############# 190 | 191 | *.py[cod] 192 | 193 | # Packages 194 | *.egg 195 | *.egg-info 196 | dist/ 197 | build/ 198 | eggs/ 199 | parts/ 200 | var/ 201 | sdist/ 202 | develop-eggs/ 203 | .installed.cfg 204 | 205 | # Installer logs 206 | pip-log.txt 207 | 208 | # Unit test / coverage reports 209 | .coverage 210 | .tox 211 | 212 | #Translations 213 | *.mo 214 | 215 | #Mr Developer 216 | .mr.developer.cfg 217 | 218 | node_modules/ 219 | 220 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | 203 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SQL Monitor 2 | Want to manages sql server performance? Check out SQL Monitor, it can monitor sql server processes and jobs, analyze performance, analyse system, object version control, view executing sql query, kill process / job, object explorer, database shrink/log truncate/backup/detach/attach etc.: 3 | 4 | https://github.com/unruledboy/SQLMonitor 5 | 6 | 7 | # Overflow Stack 8 | The overflow stack family (Web Front End Stack, Database Stack, .NET Stack etc.): 9 | http://overflowstack.github.io 10 | 11 | # Localization 12 | 中文: 13 | https://github.com/unruledboy/DatabaseStack/blob/master/README.zh-cn.md 14 | 15 | # DatabaseStack 16 | database technology stack, including MS SQL Server, Azure etc. 17 | 18 | ![Image of The Database Stack](https://raw.githubusercontent.com/unruledboy/DatabaseStack/master/preview.png) 19 | 20 | # What and why? 21 | Have you ever wondered: 22 | * what technologies database server really includes? 23 | * how many do I possess? 24 | 25 | 26 | I could not find a really comprehensive diagram that shows the database technology stack, so I come up with my own version. 27 | 28 | There might be issues here and there, like the category, the individual ones, but the beautity is you can modify it as you want. 29 | 30 | 31 | 32 | # The Database Stack 33 | 34 | You can have a graphical preview here (use mouse to move / zoom): 35 | 36 | https://rawgit.com/unruledboy/DatabaseStack/master/ux/DatabaseStack.htm 37 | 38 | 39 | 40 | - Database 41 | - RDBMS 42 | - Simple 43 | - [dBase ;-)](https://en.wikipedia.org/wiki/DBase) 44 | - Foxbase ;-) 45 | - [FoxPro ;-)](https://en.wikipedia.org/wiki/FoxPro) 46 | - [Visual FoxPro ;-)](https://msdn.microsoft.com/en-us/vfoxpro/bb190225.aspx) 47 | - [Access](https://products.office.com/en-us/access) 48 | - [Sqlite](https://www.sqlite.org/) 49 | - Basics 50 | - [Edgar F. Codd](https://en.wikipedia.org/wiki/Edgar_F._Codd) 51 | - [Object/relational mapping (O/RM)](https://en.wikipedia.org/wiki/Object-relational_mapping) 52 | - [Normalisation](https://en.wikipedia.org/wiki/Database_normalization) 53 | - Normal Form 54 | - First Normal Form (1NF) 55 | - Second Normal Form (2NF) 56 | - Third Normal Form (3NF) 57 | - [Transaction](https://en.wikipedia.org/wiki/Database_transaction) 58 | - [ACID](https://en.wikipedia.org/wiki/ACID) 59 | - Atomicity 60 | - Consistency 61 | - Isolation 62 | - Durability 63 | - [MS SQL Server](http://www.microsoft.com/en-us/server-cloud/products/sql-server/) 64 | - SQL OS 65 | - Memory Management 66 | - Buffer Pool 67 | - Deadlock detection 68 | - Exception handling 69 | - Schedulers 70 | - InterOp 71 | - Storage Engine 72 | - Transaction Services 73 | - File Manager 74 | - Data File 75 | - Extents 76 | - Pages 77 | - Log File 78 | - Write Ahead Log (WAL) 79 | - Dirty Pages 80 | - Lazy Writer 81 | - Checkpoint 82 | - Log Sequence Number (LSN) 83 | - Relational Engine 84 | - Query Processing 85 | - Parser 86 | - Optimizer 87 | - Stat 88 | - Hinting 89 | - Plan 90 | - Compilation 91 | - Caching 92 | - Recompilation 93 | - SQL Manager 94 | - Database Manager 95 | - Query Executor 96 | - Memory Management 97 | - Thread and Task Management 98 | - Buffer Management 99 | - Distributed Query Processing 100 | - Communication 101 | - SQL Server Network Interface (SNI) 102 | - Tabular Data Stream (TDS) 103 | - Protocols 104 | - TCP/IP 105 | - Named pipes 106 | - Shared memory 107 | - Virtual Interface Adapter (VIA, discontinued from 2012) 108 | - Web Services 109 | - Core Concepts 110 | - Instance 111 | - Default 112 | - Named 113 | - Alias 114 | - Port 115 | - Default: 1433 116 | - Dynamic 117 | - Transaction 118 | - ACID 119 | - Atomic 120 | - Consistent 121 | - Isolated 122 | - Durable 123 | - Types 124 | - Implicit 125 | - single UPDATE/DELETE 126 | - Explicit 127 | - BEGIN/COMMIT/ROLLBACK 128 | - Checkpoint 129 | - [Isolation Levels (low to high)](https://technet.microsoft.com/en-us/library/ms189122(v=sql.105).aspx) 130 | - Read uncommitted 131 | - dirty read 132 | - same as NOLOCK hint 133 | - Read committed (default) 134 | - READ_COMMITTED_SNAPSHOT 135 | - ON 136 | - repeatable read 137 | - OFF (default) 138 | - Nonrepeatable read, phantom 139 | - Repeatable read 140 | - Snapshot 141 | - Database ALLOW_SNAPSHOT_ISOLATION ON 142 | - 2005+ 143 | - Serializable 144 | - Concurrency 145 | - Lock 146 | - Optimistic 147 | - Pessimistic 148 | - Exclusive 149 | - Shared 150 | - Wait 151 | - Latch 152 | - Deadlock 153 | - Kill 154 | - sync/async 155 | - Blocking 156 | - Row versioning 157 | - Core Objects 158 | - Database 159 | - Recovery Models 160 | - Purpose 161 | - Backup transaction log 162 | - Affect backup types 163 | - Affect replication types 164 | - Models 165 | - Simple 166 | - Not point-in-time recovery 167 | - Minimum space 168 | - Full (default) 169 | - Point-in-time recovery 170 | - Large space 171 | - Bulk logged 172 | - Point-in-time recovery 173 | - No bulk operation logged 174 | - Save space 175 | - Compatibility Levels 176 | - Version Number 177 | - Effectively SQL Server version number 178 | - @@VERSION 179 | - 130: SQL Server 2016 180 | - 120: SQL Server 2014 181 | - 110: SQL Server 2012 182 | - 100: SQL Server 2008 183 | - 90: SQL Server 2005 184 | - 80: SQL Server 2000 185 | - Encryption 186 | - Copy 187 | - Table 188 | - Standard 189 | - Partition 190 | - Compression 191 | - Table Variable 192 | - Temp Table 193 | - Local 194 | - Global 195 | - FileTable 196 | - View 197 | - Standard 198 | - Indexed 199 | - Partitioned 200 | - Stored Procedure (SP) 201 | - Function (FN) 202 | - Table-valued Function 203 | - Scalar-valued Function 204 | - Data Type 205 | - Types 206 | - System Type 207 | - User-defined Type (UDT) 208 | - Conversion 209 | - Precedence 210 | - Synonym 211 | - Precision/Scale/Length 212 | - XML 213 | - JSON 214 | - Spatial (CLR) 215 | - Index 216 | - Index Types 217 | - Clustered Index 218 | - Non-clustered Index 219 | - Index Setting 220 | - Include 221 | - Filter 222 | - Index Management 223 | - Rebuild 224 | - Reorganise 225 | - Disable 226 | - Enable 227 | - Drop 228 | - Column 229 | - columnstore 230 | - Suitable for Data warehouse 231 | - NTFS FileStream 232 | - Schema 233 | - Trigger 234 | - Table Trigger 235 | - BEFORE 236 | - FOR/AFTER 237 | - INSTEAD OF 238 | - Constraint 239 | - Key 240 | - Default 241 | - Synonym 242 | - Sequence 243 | - Variable 244 | - Local Variable (@) 245 | - Global Variable (@@) 246 | - Common Table Expression (CTE) 247 | - Cursor 248 | - Collation 249 | - Login 250 | - User 251 | - Rule 252 | - Server role 253 | - Endpoint 254 | - Job 255 | - Job Agent 256 | - Job Activity Monitor 257 | - Alert 258 | - Operator 259 | - SQL Job 260 | - Step 261 | - Schedule 262 | - Notification 263 | - SQL CLR (.NET CLR) 264 | - Assembly 265 | - Managed Code Types 266 | - Function 267 | - Stored Procedure 268 | - Trigger 269 | - UDF 270 | - UDA 271 | - UDT 272 | - Security Levels 273 | - Linked Server 274 | - Service Broker 275 | - Basics 276 | - Transactional message queue 277 | - Objects 278 | - Message 279 | - Contract 280 | - Queue 281 | - Service 282 | - Dialog 283 | - Conversation 284 | - Standard 285 | - ANSI 92 286 | - Languages 287 | - Query Language 288 | - T-SQL (Transact-SQL) 289 | - MDX (MultiDimensional eXpressions) 290 | - Data Manipulation Language (DML) 291 | - CRUD 292 | - Create (INSERT) 293 | - Retrieve (SELECT) 294 | - Update (UPDATE) 295 | - Delete (DELETE) 296 | - MERGE 297 | - TEXT 298 | - UPDATETEXT 299 | - WRITETEXT 300 | - READTEXT 301 | - BULK INSERT 302 | - EXECUTE 303 | - Data Definition Language (DDL) 304 | - CREATE 305 | - ALTER 306 | - DROP 307 | - TRUNCATE 308 | - RESTORE 309 | - RECONFIGURE 310 | - Data Control Language (DCL) 311 | - GRANT 312 | - REVOKE 313 | - Transaction Control Language (TCL) 314 | - BEGIN TRANSACTION 315 | - COMMIT 316 | - ROLLBACK 317 | - SAVE TRANSACTION 318 | - System Databases 319 | - master (dbs, logins, configs) 320 | - tempdb (temp tables / sps) 321 | - msdb (jobs/alerts/backups) 322 | - model (template for new db) 323 | - resource (invisible, system objects) 324 | - File 325 | - primary (MDF) 326 | - secondary (NDF) 327 | - log (LDF) 328 | - File/Filegroup 329 | - Auto Grow 330 | - Runtime 331 | - Process 332 | - Worker 333 | - Connection 334 | - Request 335 | - Stall 336 | - Stats 337 | - Query Store 338 | - Cache 339 | - aging 340 | - Catalog Views 341 | - Dynamic Management Views (DMV) 342 | - Execution count 343 | - Execution io/cpu/perf 344 | - Full Text Search (FTS) 345 | - Integrated Full Text Search (iFTS) 346 | - Trace flags 347 | - Replication 348 | - Log Shipping 349 | - Publish/Subscribe 350 | - Transactional 351 | - Merge 352 | - Snapshot 353 | - Mirroring (deprecated from 2012) 354 | - Core 355 | - Principal 356 | - Witness 357 | - Database Mirroring Monitor 358 | - AlwaysOn 359 | - Clustering 360 | - Core 361 | - Shared Disk Array 362 | - Quorum 363 | - Failover 364 | - Active/Active 365 | - Active/Passive 366 | - Snapshot 367 | - Versions 368 | - SQL Server 2005 369 | - SSIS 370 | - SSRS 371 | - SSAS 372 | - Common Language Runtime (CLR) 373 | - XML 374 | - Data Service (SOAP) 375 | - Service Broker 376 | - Common Table Expression (CTE) 377 | - Dynamic Management View (DMV) 378 | - Database Mirroring (SP1) 379 | - TRY/CATCH 380 | - SQL Server 2008 381 | - Always On 382 | - FILESTREAM 383 | - Integrated Full-Text Search (iFTS) 384 | - Spatial Types 385 | - GEOMETRY 386 | - GEOGRAPHY 387 | - Transparent Data Encryption (TDE) 388 | - IntelliSense 389 | - SSRS Charting (acquired Dundas charts) 390 | - SQL Server 2012 391 | - Sequence 392 | - THROW 393 | - SQL Server 2014 394 | - In-memory Table 395 | - Clustered Columnstore Index 396 | - SQL Server 2016 397 | - Columnstore Index 398 | - In-memory OLTP 399 | - JSON 400 | - Query Store 401 | - Temporal Tables 402 | - Polybase (connector to BigData) 403 | - Always Encrypted 404 | - Editions 405 | - Express 406 | - BI 407 | - Web 408 | - Standard 409 | - Enterprise 410 | - Datacenter 411 | - Local DB 412 | - Management 413 | - SQL Server Management Studio (SSMS) 414 | - SQL Server Command Line Util (sqlcmd) 415 | - [SQL Monitor ;-)](https://github.com/unruledboy/SQLMonitor) 416 | - Maintenance 417 | - Maintenance Plan 418 | - Logs 419 | - Database Mail 420 | - Database 421 | - Backup/Restore 422 | - Mode 423 | - Full 424 | - Differential 425 | - Transaction log 426 | - Online/Offline 427 | - Attach/Dettach 428 | - Shrink 429 | - Import/Export 430 | - DBCC 431 | - Bulk Copy (bcp command line) 432 | - Resource governor 433 | - Facets 434 | - Business Intelligence (BI) 435 | - SQL Server Integration Service (SSIS) 436 | - Extract-Transform-Load (ETL) 437 | - SQL Server Reporting Service (SSRS) 438 | - SQL Server Analysis Service (SSAS) 439 | - OLAP 440 | - Troubleshoot 441 | - Dedicated Administrator Connection (DAC) 442 | - ADMIN:INSTANCE 443 | - SQL Browser service must be running 444 | - SQL Server Profiler 445 | - Activity Monitor 446 | - Error 447 | - Severity Levels 448 | - Error Log 449 | - sys.xp_readerrorlog 450 | - Performance 451 | - Seek 452 | - Scan 453 | - Fragmentation 454 | - Partitioning 455 | - Database Engine Tuning Advisor 456 | - Services 457 | - SQL Server 458 | - SQL Server Browser 459 | - SQL Server Agent 460 | - Connectivity 461 | - ADO.NET 462 | - ODBC 463 | - JDBC 464 | - Security 465 | - Access Control 466 | - SQL Inject 467 | - Backup 468 | - Testing 469 | - [tSQLt](http://tsqlt.org/) 470 | - [Oracle](https://www.oracle.com/database/) 471 | - [MySQL](https://www.mysql.com/) 472 | - [PostgreSQL](http://www.postgresql.org/) 473 | - [Informix](http://www.ibm.com/software/data/informix) 474 | - [DB2](http://www.ibm.com/software/data/db2) 475 | - Cloud 476 | - [Azure](https://azure.microsoft.com) 477 | - Database 478 | - Redis Cache 479 | - Storage 480 | - Blobs 481 | - Tables 482 | - Queues 483 | - Files and Disks 484 | - StorSimple 485 | - SQL Data Warehouse 486 | - [NoSQL](https://en.wikipedia.org/wiki/NoSQL) 487 | - Concepts 488 | - XML/JSON based 489 | - Eventually Consistency 490 | - Limitation 491 | - [CAPS/Brewer's theorem](https://en.wikipedia.org/wiki/CAP_theorem) 492 | - Consistency 493 | - Availability 494 | - Partition tolerance 495 | - Lack of join 496 | - Lack of true ACID 497 | - Types 498 | - Column 499 | - [Cassandra](http://cassandra.apache.org/) 500 | - [HBase](http://hbase.apache.org/) 501 | - Key/Value 502 | - [CouchDB](http://couchdb.apache.org/) 503 | - [AWS Dynamo](https://aws.amazon.com/dynamodb/) 504 | - [MemcacheDB](http://memcachedb.org/) 505 | - [Redis](http://redis.io/) 506 | - Document 507 | - [Apache CouchDB](http://couchdb.apache.org/) 508 | - [Couchbase](http://www.couchbase.com/) 509 | - [Azure DocumentDB](http://azure.microsoft.com/en-us/services/documentdb/) 510 | - [MongoDB](https://www.mongodb.org/) 511 | - Graph 512 | - [Neo4J](http://neo4j.com/) 513 | - Object 514 | - [ObjectStore](http://www.objectstore.com/) 515 | 516 | 517 | -------------------------------------------------------------------------------- /README.zh-cn.md: -------------------------------------------------------------------------------- 1 | # SQL Monitor 2 | 想优化SQL Server的功能吗?看看SQL Monitor吧!它可以管理SQL Server进程和作业、分析系统、版本控制、建议性能改进等。 3 | 4 | https://github.com/unruledboy/SQLMonitor 5 | 6 | 7 | # 爆栈 8 | 系统开发技术栈、Web前端开发技术栈、数据库技术栈、.NET技术栈! 9 | http://overflowstack.github.io 10 | 11 | 12 | # 本地化 13 | English: 14 | https://github.com/unruledboy/DatabaseStack/ 15 | 16 | 中文博客: 17 | http://www.cnblogs.com/unruledboy/p/DatabaseStack.html 18 | 19 | # 数据库技术栈 20 | 比较全面的数据库技术栈,包括MS SQL Server、Azure等。 21 | 22 | ![Image of The Database Stack](preview.zh-cn.png) 23 | 24 | # 为什么? 25 | 大家是否想过: 26 | * 数据库开发究竟包含哪些技术呢? 27 | * 我所掌握的技术这个子集,在数据库技术大系这个超集里面占的比例是多少呢? 28 | * 我究竟还没有掌握多少数据库技术呢? 29 | * 面试的时候会考哪些技术呢? 30 | 31 | 那么,数据库开发是否也应该有这样的技术栈概览图呢?搜索了很久,没有找到一个符合我要求的“较为全面”地表述数据库技术大系的图表。所以我们自行设计了这个数据库技术栈。 32 | 33 | 这个图表里的分类未必准确,相关技术也难免会有遗漏,欢迎大家指点以便不断改进。 34 | 35 | 数据库技术实在太繁多限于篇幅,这里没有罗列一些技术。 36 | 37 | 您可以点击下面链接查看交互式预览图(用鼠标移动/缩放/点击节点打开相关网站): 38 | 39 | https://rawgit.com/unruledboy/DatabaseStack/master/ux/DatabaseStack.htm?locale=zh-cn 40 | 41 | 42 | 43 | - 数据库 44 | - 关系型数据库系统 45 | - 简单 46 | - [dBase ;-)](https://en.wikipedia.org/wiki/DBase) 47 | - Foxbase ;-) 48 | - [FoxPro ;-)](https://en.wikipedia.org/wiki/FoxPro) 49 | - [Visual FoxPro ;-)](https://msdn.microsoft.com/en-us/vfoxpro/bb190225.aspx) 50 | - [Access](https://products.office.com/en-us/access) 51 | - [Sqlite](https://www.sqlite.org/) 52 | - 基本知识 53 | - [Edgar F. Codd](https://en.wikipedia.org/wiki/Edgar_F._Codd) 54 | - [对象关系映射 (O/RM)](https://en.wikipedia.org/wiki/Object-relational_mapping) 55 | - [数据库规范化](https://en.wikipedia.org/wiki/Database_normalization) 56 | - 范式 57 | - 第一范式 (1NF) 58 | - 第二范式 (1NF) 59 | - 第三范式 (1NF) 60 | - [事务](https://en.wikipedia.org/wiki/Database_transaction) 61 | - [ACID](https://en.wikipedia.org/wiki/ACID) 62 | - 原子性 63 | - 一致性 64 | - 隔离性/独立性 65 | - 持久性 66 | - [MS SQL Server](http://www.microsoft.com/en-us/server-cloud/products/sql-server/) 67 | - SQL OS 68 | - 内存管理 69 | - 缓存池 70 | - 死锁检测 71 | - 异常处理 72 | - 调度器 73 | - 交互 74 | - 存储引擎 75 | - 事务服务 76 | - 文件管理 77 | - 数据文件 78 | - Extents 79 | - Pages 80 | - 日志文件 81 | - Write Ahead Log (WAL) 82 | - 脏页 83 | - Lazy Writer 84 | - Checkpoint 85 | - Log Sequence Number (LSN) 86 | - 关系引擎 87 | - Query Processing 88 | - 解析器 89 | - 优化器 90 | - Stat 91 | - Hinting 92 | - Plan 93 | - Compilation 94 | - Caching 95 | - Recompilation 96 | - SQL Manager 97 | - Database Manager 98 | - Query Executor 99 | - Memory Management 100 | - Thread and Task Management 101 | - Buffer Management 102 | - Distributed Query Processing 103 | - 通讯 104 | - SQL Server Network Interface (SNI) 105 | - Tabular Data Stream (TDS) 106 | - Protocols 107 | - TCP/IP 108 | - Named pipes 109 | - Shared memory 110 | - Virtual Interface Adapter (VIA, discontinued from 2012) 111 | - Web Services 112 | - 概念 113 | - 实例 114 | - 默认 115 | - 命名 116 | - 别名 117 | - 端口 118 | - 默认: 1433 119 | - 动态 120 | - 事务 121 | - ACID 122 | - Atomic 123 | - Consistent 124 | - Isolated 125 | - Durable 126 | - 类型 127 | - 隐式 128 | - 单个 UPDATE/DELETE 129 | - 显式 130 | - BEGIN/COMMIT/ROLLBACK 131 | - Checkpoint 132 | - [隔离级别 (从低到高)](https://technet.microsoft.com/en-us/library/ms189122(v=sql.105).aspx) 133 | - Read uncommitted 134 | - 脏读 135 | - 和NOLOCK一样 136 | - Read committed (默认) 137 | - READ_COMMITTED_SNAPSHOT 138 | - ON 139 | - 可重复的读取 140 | - OFF (默认) 141 | - 不可重复的读取 142 | - Repeatable read 143 | - Snapshot 144 | - Database ALLOW_SNAPSHOT_ISOLATION ON 145 | - 2005+ 146 | - Serializable 147 | - 并发性 148 | - Lock 149 | - 乐观锁 150 | - 悲观锁 151 | - 排他 152 | - 共享 153 | - Wait 154 | - Latch 155 | - 死锁 156 | - Kill 157 | - sync/async 158 | - Blocking 159 | - 行版本 160 | - 对象 161 | - 数据库 162 | - 恢复模式 163 | - 作用 164 | - 备份事务日志 165 | - 影响备份类型 166 | - 影响复制类型 167 | - Models 168 | - 简单 169 | - Not point-in-time recovery 170 | - Minimum space 171 | - 完整 (默认) 172 | - Point-in-time recovery 173 | - Large space 174 | - 大容量日志恢复 175 | - Point-in-time recovery 176 | - No bulk operation logged 177 | - Save space 178 | - 兼容级别 179 | - 版本 180 | - 实际上就是SQL Server的版本 181 | - @@VERSION 182 | - 130: SQL Server 2016 183 | - 120: SQL Server 2014 184 | - 110: SQL Server 2012 185 | - 100: SQL Server 2008 186 | - 90: SQL Server 2005 187 | - 80: SQL Server 2000 188 | - 加密 189 | - 复制 190 | - 表 191 | - 标准 192 | - 分区 193 | - 压缩 194 | - 表变量 195 | - 临时表 196 | - 本地 197 | - 全局 198 | - FileTable 199 | - 视图 200 | - 标准 201 | - 索引 202 | - 分区 203 | - 存储过程 (SP) 204 | - 函数 (FN) 205 | - Table-valued Function 206 | - Scalar-valued Function 207 | - 数据类型 208 | - 类型 209 | - 系统类型 210 | - 用户定义类型 (UDT) 211 | - 转换 212 | - 优先级 213 | - 同义词 214 | - Precision/Scale/Length 215 | - XML 216 | - JSON 217 | - Spatial (CLR) 218 | - 索引 219 | - 索引类型 220 | - 聚集索引 221 | - 非聚集索引 222 | - 索引设置 223 | - Include 224 | - Filter 225 | - 索引管理 226 | - Rebuild 227 | - Reorganise 228 | - Disable 229 | - Enable 230 | - Drop 231 | - 列 232 | - columnstore 233 | - 适合数据仓库 234 | - NTFS FileStream 235 | - Schema 236 | - 触发器 237 | - 表触发器 238 | - BEFORE 239 | - FOR/AFTER 240 | - INSTEAD OF 241 | - Constraint 242 | - Key 243 | - Default 244 | - Synonym 245 | - 序列 246 | - 变量 247 | - 本地变量 (@) 248 | - 全局变量 (@@) 249 | - Common Table Expression (CTE) 250 | - Cursor 251 | - Collation 252 | - Login 253 | - User 254 | - Rule 255 | - Server role 256 | - Endpoint 257 | - 作业 258 | - Job Agent 259 | - Job Activity Monitor 260 | - Alert 261 | - Operator 262 | - SQL Job 263 | - Step 264 | - Schedule 265 | - Notification 266 | - SQL CLR (.NET CLR) 267 | - Assembly 268 | - Managed Code Types 269 | - Function 270 | - Stored Procedure 271 | - Trigger 272 | - UDF 273 | - UDA 274 | - UDT 275 | - Security Levels 276 | - Linked Server 277 | - Service Broker 278 | - 基本知识 279 | - Transactional message queue 280 | - 对象 281 | - Message 282 | - Contract 283 | - Queue 284 | - Service 285 | - Dialog 286 | - Conversation 287 | - 标准 288 | - ANSI 92 289 | - 语言 290 | - 查询语言 291 | - T-SQL (Transact-SQL) 292 | - MDX (MultiDimensional eXpressions) 293 | - 数据操作语言 (DML) 294 | - CRUD 295 | - Create (INSERT) 296 | - Retrieve (SELECT) 297 | - Update (UPDATE) 298 | - Delete (DELETE) 299 | - MERGE 300 | - TEXT 301 | - UPDATETEXT 302 | - WRITETEXT 303 | - READTEXT 304 | - BULK INSERT 305 | - EXECUTE 306 | - 数据定义语言 (DDL) 307 | - CREATE 308 | - ALTER 309 | - DROP 310 | - TRUNCATE 311 | - RESTORE 312 | - RECONFIGURE 313 | - 数据控制语言 (DCL) 314 | - GRANT 315 | - REVOKE 316 | - 事务控制语言 (TCL) 317 | - BEGIN TRANSACTION 318 | - COMMIT 319 | - ROLLBACK 320 | - SAVE TRANSACTION 321 | - 系统数据库 322 | - master (dbs, logins, configs) 323 | - tempdb (temp tables / sps) 324 | - msdb (jobs/alerts/backups) 325 | - model (template for new db) 326 | - resource (invisible, system objects) 327 | - 文件 328 | - primary (MDF) 329 | - secondary (NDF) 330 | - log (LDF) 331 | - File/Filegroup 332 | - Auto Grow 333 | - 运行时 334 | - Process 335 | - Worker 336 | - Connection 337 | - Request 338 | - Stall 339 | - Stats 340 | - Query Store 341 | - Cache 342 | - aging 343 | - Catalog Views 344 | - Dynamic Management Views (DMV) 345 | - Execution count 346 | - Execution io/cpu/perf 347 | - Full Text Search (FTS) 348 | - Integrated Full Text Search (iFTS) 349 | - Trace flags 350 | - 复制 351 | - Log Shipping 352 | - Publish/Subscribe 353 | - Transactional 354 | - Merge 355 | - Snapshot 356 | - Mirroring (deprecated from 2012) 357 | - Core 358 | - Principal 359 | - Witness 360 | - Database Mirroring Monitor 361 | - AlwaysOn 362 | - Clustering 363 | - Core 364 | - Shared Disk Array 365 | - Quorum 366 | - Failover 367 | - Active/Active 368 | - Active/Passive 369 | - Snapshot 370 | - 版本号 371 | - SQL Server 2005 372 | - SSIS 373 | - SSRS 374 | - SSAS 375 | - Common Language Runtime (CLR) 376 | - XML 377 | - Data Service (SOAP) 378 | - Service Broker 379 | - Common Table Expression (CTE) 380 | - Dynamic Management View (DMV) 381 | - Database Mirroring (SP1) 382 | - TRY/CATCH 383 | - SQL Server 2008 384 | - Always On 385 | - FILESTREAM 386 | - Integrated Full-Text Search (iFTS) 387 | - Spatial Types 388 | - GEOMETRY 389 | - GEOGRAPHY 390 | - Transparent Data Encryption (TDE) 391 | - IntelliSense 392 | - SSRS Charting (acquired Dundas charts) 393 | - SQL Server 2012 394 | - Sequence 395 | - THROW 396 | - SQL Server 2014 397 | - In-memory Table 398 | - Clustered Columnstore Index 399 | - SQL Server 2016 400 | - Columnstore Index 401 | - In-memory OLTP 402 | - JSON 403 | - Query Store 404 | - Temporal Tables 405 | - Polybase (connector to BigData) 406 | - Always Encrypted 407 | - 产品版本 408 | - Express 409 | - BI 410 | - Web 411 | - Standard 412 | - Enterprise 413 | - Datacenter 414 | - Local DB 415 | - 管理 416 | - SQL Server Management Studio (SSMS) 417 | - SQL Server Command Line Util (sqlcmd) 418 | - [SQL Monitor ;-)](https://github.com/unruledboy/SQLMonitor) 419 | - 维护 420 | - Maintenance Plan 421 | - Logs 422 | - Database Mail 423 | - Database 424 | - Backup/Restore 425 | - Mode 426 | - Full 427 | - Differential 428 | - Transaction log 429 | - Online/Offline 430 | - Attach/Dettach 431 | - Shrink 432 | - Import/Export 433 | - DBCC 434 | - Bulk Copy (bcp command line) 435 | - Resource governor 436 | - Facets 437 | - 商业智能 (BI) 438 | - SQL Server Integration Service (SSIS) 439 | - Extract-Transform-Load (ETL) 440 | - SQL Server Reporting Service (SSRS) 441 | - SQL Server Analysis Service (SSAS) 442 | - OLAP 443 | - 调试 444 | - Dedicated Administrator Connection (DAC) 445 | - ADMIN:INSTANCE 446 | - SQL Browser service must be running 447 | - SQL Server Profiler 448 | - Activity Monitor 449 | - Error 450 | - Severity Levels 451 | - Error Log 452 | - sys.xp_readerrorlog 453 | - 性能 454 | - Seek 455 | - Scan 456 | - Fragmentation 457 | - Partitioning 458 | - Database Engine Tuning Advisor 459 | - 服务 460 | - SQL Server 461 | - SQL Server Browser 462 | - SQL Server Agent 463 | - 连接 464 | - ADO.NET 465 | - ODBC 466 | - JDBC 467 | - 安全 468 | - Access Control 469 | - SQL Inject 470 | - Backup 471 | - 测试 472 | - [tSQLt](http://tsqlt.org/) 473 | - [Oracle](https://www.oracle.com/database/) 474 | - [MySQL](https://www.mysql.com/) 475 | - [PostgreSQL](http://www.postgresql.org/) 476 | - [Informix](http://www.ibm.com/software/data/informix) 477 | - [DB2](http://www.ibm.com/software/data/db2) 478 | - 云 479 | - [Azure](https://azure.microsoft.com) 480 | - Database 481 | - Redis Cache 482 | - Storage 483 | - Blobs 484 | - Tables 485 | - Queues 486 | - Files and Disks 487 | - StorSimple 488 | - SQL Data Warehouse 489 | - [NoSQL](https://en.wikipedia.org/wiki/NoSQL) 490 | - 概念 491 | - 基于XML/JSON 492 | - 最终一致性 493 | - 限制 494 | - [CAPS/Brewer理论](https://en.wikipedia.org/wiki/CAP_theorem) 495 | - 一致性 496 | - 可用性 497 | - 网络分区容忍性 498 | - 缺乏关联 499 | - 缺乏真正的ACID 500 | - 类型 501 | - 列 502 | - [Cassandra](http://cassandra.apache.org/) 503 | - [HBase](http://hbase.apache.org/) 504 | - 键值 505 | - [CouchDB](http://couchdb.apache.org/) 506 | - [AWS Dynamo](https://aws.amazon.com/dynamodb/) 507 | - [MemcacheDB](http://memcachedb.org/) 508 | - [Redis](http://redis.io/) 509 | - 文档 510 | - [Apache CouchDB](http://couchdb.apache.org/) 511 | - [Couchbase](http://www.couchbase.com/) 512 | - [Azure DocumentDB](http://azure.microsoft.com/en-us/services/documentdb/) 513 | - [MongoDB](https://www.mongodb.org/) 514 | - 图形关系 515 | - [Neo4J](http://neo4j.com/) 516 | - 对象 517 | - [ObjectStore](http://www.objectstore.com/) 518 | 519 | 520 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Builder 3 | * @author zsx 4 | */ 5 | var express = require('express'); 6 | var path = require('path'); 7 | var Promise = require("bluebird"); 8 | var request = require("request"); 9 | var async = require("async"); 10 | var fs = Promise.promisifyAll(require('fs')); 11 | 12 | var app = new express(); 13 | var queueReady = ["server"]; 14 | 15 | var pageWidth = 3700; // Magic number! 16 | var pageHeight = 5100; 17 | 18 | var config = { 19 | port: 3000, 20 | update_existed_stargazers: false, 21 | locale: process.env.locale || '', 22 | rawLocale: process.env.locale || '' 23 | } 24 | var httpServer = "http://127.0.0.1:" + config.port + "/"; 25 | 26 | if (config.locale) 27 | config.locale = '.' + config.locale; 28 | 29 | String.prototype.repeat = function(count) { 30 | return new Array(count + 1).join(this); 31 | } 32 | 33 | /** 34 | * Use to build a promise for some fucking async api. 35 | * @param object object 36 | **/ 37 | var promisify = function promisify(object) { 38 | for (var key in object) { 39 | (function(key, asyncKey) { 40 | object[asyncKey] = function() { 41 | var resolver = Promise.defer(); 42 | var len = arguments.length; 43 | var argu = new Array(len + 1); 44 | for (var i = 0; i < len; i++) { // I think a Array.from is more convenient. 45 | argu[i] = arguments[i]; 46 | } 47 | argu[len] = function() { 48 | resolver.resolve.apply(resolver, arguments); // Callback arguments 49 | }; 50 | object[key].apply(object, argu); 51 | return resolver.promise; 52 | } 53 | })(key, key + "Async"); 54 | } 55 | } 56 | 57 | /** 58 | * Recursion to generate readme 59 | * @param object object 60 | * @param string language 61 | * @param int deep 62 | * @return string 63 | */ 64 | var buildReadme = function buildReadme(object, language, deep) { 65 | var deeper = deep + 1; 66 | var deepString = "\t".repeat(deep) + "- "; 67 | var ret = []; 68 | var lang = typeof object.languages == "undefined" ? object.name : object.languages[language]; 69 | lang = lang || object.name; 70 | 71 | ret.push((function(deepString, name, url, github) { 72 | var haveUrl = !!url; 73 | var haveGitHub = !!github; 74 | return deepString + (haveUrl ? "[" : "") + name + (haveUrl ? "](" + url + ")" : "") + (haveGitHub ? " [\[GitHub\]](" + github + ")" : ""); 75 | })(deepString, lang, object.url, object.github)); 76 | if (object.children) { 77 | object.children.map(function(value, index) { 78 | ret.push(buildReadme(value, language, deeper)); 79 | }); 80 | } 81 | return ret.join("\n"); 82 | } 83 | 84 | var actions = { 85 | /** 86 | * Update the stargazers of the GitHub repo 87 | * Be careful! There have the rate limit! 88 | * @see https://developer.github.com/v3/#increasing-the-unauthenticated-rate-limit-for-oauth-applications 89 | * @return Promise 90 | */ 91 | updatestargazers: function updatestargazers() { 92 | return new Promise(function(resolve, reject) { 93 | var originalData = JSON.parse(fs.readFileSync('./ux/DatabaseStack.json', "utf-8")); // Require will lock the file. 94 | var getGitHubApi = function(github) { 95 | var githubArray = github.split("/"); 96 | // I want a sprintf T_T 97 | return "https://api.github.com/repos/" + githubArray[3] + "/" + githubArray[4]; 98 | }; 99 | var q = async.queue(function(object, callback) { 100 | if (!object.github || (!config.update_existed_stargazers && object.stargazers)) { 101 | callback(false); 102 | return; 103 | } 104 | var githubUrl = getGitHubApi(object.github); 105 | console.log("Getting " + githubUrl); 106 | request({ 107 | url: githubUrl, 108 | headers: { 109 | "User-Agent": "https://github.com/unruledboy/DatabaseStack" // GitHub required user-agent 110 | } 111 | }, function(err, res, body) { 112 | if (!err && res.statusCode == 200) { 113 | var json = JSON.parse(body); 114 | if (json === null) { 115 | callback(false); 116 | return; 117 | } 118 | object.stargazers = json.stargazers_count; 119 | callback(true); 120 | } else { 121 | if (res.statusCode == 403) { // Out of API limit! 122 | console.error("Out of GitHub API limit!"); 123 | console.error("The limit will be reset when " + new Date(res.headers['x-ratelimit-reset'] * 1000)); 124 | q.kill(); 125 | reject("Out of GitHub API limit!"); 126 | } 127 | callback(false); 128 | } 129 | }); 130 | 131 | }, 5); 132 | var addQueue = function addQueue(object) { 133 | q.push(object, function(err) { 134 | if (err) console.log(object.name + " = " + object.stargazers); 135 | }); 136 | if (object.children) { 137 | object.children.forEach(function(val) { 138 | addQueue(val); 139 | }); 140 | } 141 | }; 142 | addQueue(originalData); 143 | q.push({ // For some reason, the ``drain`` will not be called. 144 | noRequest: true 145 | }, function() { 146 | fs.writeFileAsync('./ux/DatabaseStack.json', JSON.stringify(originalData), "utf-8").then(function() { 147 | resolve(); 148 | }); 149 | }); 150 | return q; 151 | }) 152 | }, 153 | /** 154 | * For running phantomjs to take a screenshot for the webpage 155 | * @return Promise 156 | */ 157 | phantomjs: function phantomjs() { 158 | var json = require('./ux/DatabaseStack.json'); 159 | var phantom = require('phantom'); 160 | promisify(phantom); 161 | // What the fucking API 162 | var resolver = Promise.defer(); 163 | var buildByLanguage = function(language) { 164 | var displayLanguage = language == "" ? "en" : language; 165 | var ph; 166 | var page; 167 | return phantom.createAsync().then(function(phantom) { 168 | ph = phantom; 169 | promisify(ph); 170 | console.log("Created Phantomjs for " + displayLanguage); 171 | return ph.createPageAsync(); 172 | }).then(function(pg) { 173 | page = pg; 174 | promisify(pg); 175 | return page.setAsync('viewportSize', { 176 | width: pageWidth, 177 | height: pageHeight 178 | }); 179 | }).then(function() { 180 | console.log("Set viewportSize"); 181 | console.log("Opening " + httpServer + "?locale=" + language + " for " + displayLanguage); 182 | return page.openAsync(httpServer + "?locale=" + language); 183 | }).then(function(status) { 184 | console.log("Rendered HTML, the image will be saved after 2 seconds."); 185 | if (status == "success") { 186 | return Promise.delay(2000); 187 | } else { 188 | throw status; 189 | } 190 | }).then(function() { 191 | return page.renderAsync(path.join(__dirname, 'preview' + (language == "" ? "" : ".") + language + '.png')); 192 | }).then(function() { 193 | console.log("The image(" + displayLanguage + ") saved successfully!"); 194 | page.close(); 195 | ph.exit(); 196 | }); 197 | }; 198 | resolver.promise.then(buildByLanguage("")); 199 | for (var item in json.languages) { 200 | resolver.promise.then(buildByLanguage(item)); 201 | } 202 | return resolver.promise; 203 | }, 204 | 205 | /** 206 | * To rebuild the README.md 207 | * @return Promise 208 | */ 209 | readme: function readme() { 210 | var json = require('./ux/DatabaseStack.json'); 211 | var resolver = Promise.defer(); 212 | var buildByLanguage = function(language) { 213 | return Promise.resolve().then(function() { 214 | return fs.readFileAsync('./README' + (language == "" ? "" : ".") + language + '.md', "utf-8"); 215 | }).then(function(fileContent) { 216 | var ret = buildReadme(json, language, 0); 217 | fileContent = fileContent.replace(/<\!--BUILD_START-->[\d\D]+?<\!--BUILD_END-->/, "{%BuildStart%}") 218 | return fs.writeFileAsync('./README' + (language == "" ? "" : ".") + language + '.md', fileContent.replace("{%BuildStart%}", "\n\n" + ret + "\n\n", "utf-8")); 219 | }).then(function() { 220 | console.log('Readme' + (language == "" ? "" : ":") + language + ' built successfully!'); 221 | }) 222 | }; 223 | resolver.promise.then(buildByLanguage("")); 224 | for (var item in json.languages) { 225 | resolver.promise.then(buildByLanguage(item)); 226 | } 227 | return resolver.promise; 228 | }, 229 | /** 230 | * To start an express server 231 | * @return Promise 232 | */ 233 | server: function server() { 234 | return new Promise(function(resolver, reject) { 235 | return app 236 | .set('port', config.port) 237 | .set('view engine', 'html') 238 | .use(express.static(path.join(__dirname, '/ux'))) 239 | .use('/', function(req, res) { 240 | res.redirect('/DatabaseStack.htm?locale=' + req.query.locale); 241 | }) 242 | .listen(config.port, function() { 243 | console.info('Express started on: http://127.0.0.1:' + config.port); 244 | resolver(app); 245 | }); 246 | }); 247 | } 248 | }; 249 | 250 | var queue = [actions.server()]; 251 | process.argv.forEach(function(val) { 252 | if (val in actions) { 253 | console.info("Task: " + val); 254 | queue.push(actions[val]()); 255 | } else if (val[0] == "-" && val.indexOf("=") >= 0) { 256 | var obj = val.split("="); 257 | var name = obj[0].split("--")[1]; 258 | var value = obj[1]; 259 | config[name] = value; 260 | } 261 | }); 262 | 263 | var promise = Promise.all(queue); 264 | if (queue.length > 1) { // for somebody who only want to start the server. 265 | console.log("You can press Ctrl+C to exit if tasks finished.") 266 | promise.then(function() { 267 | console.log("OK!"); 268 | process.exit(0); 269 | }); 270 | } 271 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "DatabaseStack", 3 | "version": "2.0.0", 4 | "description": "Generate a image for database stack.", 5 | "main": "index.js", 6 | "scripts": { 7 | "build": "node index phantomjs readme", 8 | "start": "node index" 9 | }, 10 | "repository": { 11 | "type": "git", 12 | "url": "https://github.com/unruledboy/DatabaseStack.git" 13 | }, 14 | "keywords": [ 15 | "Database", 16 | "SQL Server", 17 | "Stack" 18 | ], 19 | "author": [ 20 | "unruledboy ", 21 | "zsx " 22 | ], 23 | "license": "ISC", 24 | "bugs": { 25 | "url": "https://github.com/unruledboy/DatabaseStack/issues" 26 | }, 27 | "homepage": "https://github.com/unruledboy/DatabaseStack", 28 | "dependencies": { 29 | "bluebird": "^2.9.34", 30 | "express": "^4.13.3", 31 | "phantom": "^0.7.2" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unruledboy/DatabaseStack/e1f68841db570d896c387bd60d5b69ea6c83b3d8/preview.png -------------------------------------------------------------------------------- /preview.zh-cn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unruledboy/DatabaseStack/e1f68841db570d896c387bd60d5b69ea6c83b3d8/preview.zh-cn.png -------------------------------------------------------------------------------- /ux/DatabaseStack.htm: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | Database Stack 7 | 8 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 |
93 |
94 | 97 | 100 |
101 |
102 |
103 | 104 | 105 | 106 | -------------------------------------------------------------------------------- /ux/DatabaseStack.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Database", 3 | "languages": { 4 | "zh-cn": "数据库" 5 | }, 6 | "children": [ 7 | { 8 | "name": "RDBMS", 9 | "languages": { 10 | "zh-cn": "关系型数据库系统" 11 | }, 12 | "children": [ 13 | { 14 | "name": "Simple", 15 | "languages": { 16 | "zh-cn": "简单" 17 | }, 18 | "children": [ 19 | { 20 | "name": "dBase ;-)", 21 | "url": "https://en.wikipedia.org/wiki/DBase" 22 | }, 23 | { "name": "Foxbase ;-)" }, 24 | { 25 | "name": "FoxPro ;-)", 26 | "url": "https://en.wikipedia.org/wiki/FoxPro" 27 | }, 28 | { 29 | "name": "Visual FoxPro ;-)", 30 | "url": "https://msdn.microsoft.com/en-us/vfoxpro/bb190225.aspx" 31 | }, 32 | { 33 | "name": "Access", 34 | "url": "https://products.office.com/en-us/access" 35 | }, 36 | { 37 | "name": "Sqlite", 38 | "url": "https://www.sqlite.org/" 39 | } 40 | ] 41 | }, 42 | { 43 | "name": "Basics", 44 | "languages": { 45 | "zh-cn": "基本知识" 46 | }, 47 | "children": [ 48 | { 49 | "name": "Edgar F. Codd", 50 | "url": "https://en.wikipedia.org/wiki/Edgar_F._Codd" 51 | }, 52 | { 53 | "name": "Object/relational mapping (O/RM)", 54 | "languages": { 55 | "zh-cn": "对象关系映射 (O/RM)" 56 | }, 57 | "url": "https://en.wikipedia.org/wiki/Object-relational_mapping" 58 | }, 59 | { 60 | "name": "Normalisation", 61 | "languages": { 62 | "zh-cn": "数据库规范化" 63 | }, 64 | "url": "https://en.wikipedia.org/wiki/Database_normalization", 65 | "children": [ 66 | { 67 | "name": "Normal Form", 68 | "languages": { 69 | "zh-cn": "范式" 70 | }, 71 | "children": [ 72 | { 73 | "name": "First Normal Form (1NF)", 74 | "languages": { 75 | "zh-cn": "第一范式 (1NF)" 76 | } 77 | }, 78 | { 79 | "name": "Second Normal Form (2NF)", 80 | "languages": { 81 | "zh-cn": "第二范式 (1NF)" 82 | } 83 | }, 84 | { 85 | "name": "Third Normal Form (3NF)", 86 | "languages": { 87 | "zh-cn": "第三范式 (1NF)" 88 | } 89 | } 90 | ] 91 | } 92 | ] 93 | }, 94 | { 95 | "name": "Transaction", 96 | "languages": { 97 | "zh-cn": "事务" 98 | }, 99 | "url": "https://en.wikipedia.org/wiki/Database_transaction", 100 | "children": [ 101 | { 102 | "name": "ACID", 103 | "url": "https://en.wikipedia.org/wiki/ACID", 104 | "children": [ 105 | { 106 | "name": "Atomicity", 107 | "languages": { 108 | "zh-cn": "原子性" 109 | } 110 | }, 111 | { 112 | "name": "Consistency", 113 | "languages": { 114 | "zh-cn": "一致性" 115 | } 116 | }, 117 | { 118 | "name": "Isolation", 119 | "languages": { 120 | "zh-cn": "隔离性/独立性" 121 | } 122 | }, 123 | { 124 | "name": "Durability", 125 | "languages": { 126 | "zh-cn": "持久性" 127 | } 128 | } 129 | ] 130 | } 131 | ] 132 | } 133 | ] 134 | }, 135 | { 136 | "name": "MS SQL Server", 137 | "url": "http://www.microsoft.com/en-us/server-cloud/products/sql-server/", 138 | "children": [ 139 | { 140 | "name": "SQL OS", 141 | "children": [ 142 | { 143 | "name": "Memory Management", 144 | "languages": { 145 | "zh-cn": "内存管理" 146 | } 147 | }, 148 | { 149 | "name": "Buffer Pool", 150 | "languages": { 151 | "zh-cn": "缓存池" 152 | } 153 | }, 154 | { 155 | "name": "Deadlock detection", 156 | "languages": { 157 | "zh-cn": "死锁检测" 158 | } 159 | }, 160 | { 161 | "name": "Exception handling", 162 | "languages": { 163 | "zh-cn": "异常处理" 164 | } 165 | }, 166 | { 167 | "name": "Schedulers", 168 | "languages": { 169 | "zh-cn": "调度器" 170 | } 171 | }, 172 | { 173 | "name": "InterOp", 174 | "languages": { 175 | "zh-cn": "交互" 176 | } 177 | } 178 | ] 179 | }, 180 | { 181 | "name": "Storage Engine", 182 | "languages": { 183 | "zh-cn": "存储引擎" 184 | }, 185 | "children": [ 186 | { 187 | "name": "Transaction Services", 188 | "languages": { 189 | "zh-cn": "事务服务" 190 | } 191 | }, 192 | { 193 | "name": "File Manager", 194 | "languages": { 195 | "zh-cn": "文件管理" 196 | } 197 | }, 198 | { 199 | "name": "Data File", 200 | "languages": { 201 | "zh-cn": "数据文件" 202 | } 203 | }, 204 | { "name": "Extents" }, 205 | { "name": "Pages" }, 206 | { 207 | "name": "Log File", 208 | "languages": { 209 | "zh-cn": "日志文件" 210 | }, 211 | "children": [ 212 | { "name": "Write Ahead Log (WAL)" }, 213 | { 214 | "name": "Dirty Pages", 215 | "languages": { 216 | "zh-cn": "脏页" 217 | } 218 | }, 219 | { "name": "Lazy Writer" }, 220 | { "name": "Checkpoint" }, 221 | { "name": "Log Sequence Number (LSN)" } 222 | ] 223 | } 224 | ] 225 | }, 226 | { 227 | "name": "Relational Engine", 228 | "languages": { 229 | "zh-cn": "关系引擎" 230 | }, 231 | "children": [ 232 | { 233 | "name": "Query Processing", 234 | "languages": { 235 | "zh-cn": "" 236 | }, 237 | "children": [ 238 | { 239 | "name": "Parser", 240 | "languages": { 241 | "zh-cn": "解析器" 242 | } 243 | }, 244 | { 245 | "name": "Optimizer", 246 | "languages": { 247 | "zh-cn": "优化器" 248 | }, 249 | "children": [ 250 | { "name": "Stat" }, 251 | { "name": "Hinting" }, 252 | { 253 | "name": "Plan", 254 | "children": [ 255 | { "name": "Compilation" }, 256 | { "name": "Caching" }, 257 | { "name": "Recompilation" } 258 | ] 259 | } 260 | ] 261 | }, 262 | { "name": "SQL Manager" }, 263 | { "name": "Database Manager" }, 264 | { "name": "Query Executor" } 265 | ] 266 | }, 267 | { "name": "Memory Management" }, 268 | { "name": "Thread and Task Management" }, 269 | { "name": "Buffer Management" }, 270 | { "name": "Distributed Query Processing" } 271 | ] 272 | }, 273 | { 274 | "name": "Communication", 275 | "languages": { 276 | "zh-cn": "通讯" 277 | }, 278 | "children": [ 279 | { "name": "SQL Server Network Interface (SNI)" }, 280 | { "name": "Tabular Data Stream (TDS)" }, 281 | { 282 | "name": "Protocols", 283 | "children": [ 284 | { "name": "TCP/IP" }, 285 | { "name": "Named pipes" }, 286 | { "name": "Shared memory" }, 287 | { "name": "Virtual Interface Adapter (VIA, discontinued from 2012)" }, 288 | { "name": "Web Services" } 289 | ] 290 | } 291 | ] 292 | }, 293 | { 294 | "name": "Core Concepts", 295 | "languages": { 296 | "zh-cn": "概念" 297 | }, 298 | "children": [ 299 | { 300 | "name": "Instance", 301 | "languages": { 302 | "zh-cn": "实例" 303 | }, 304 | "children": [ 305 | { 306 | "name": "Default", 307 | "languages": { 308 | "zh-cn": "默认" 309 | } 310 | }, 311 | { 312 | "name": "Named", 313 | "languages": { 314 | "zh-cn": "命名" 315 | } 316 | }, 317 | { 318 | "name": "Alias", 319 | "languages": { 320 | "zh-cn": "别名" 321 | } 322 | } 323 | ] 324 | }, 325 | { 326 | "name": "Port", 327 | "languages": { 328 | "zh-cn": "端口" 329 | }, 330 | "children": [ 331 | { 332 | "name": "Default: 1433", 333 | "languages": { 334 | "zh-cn": "默认: 1433" 335 | } 336 | }, 337 | { 338 | "name": "Dynamic", 339 | "languages": { 340 | "zh-cn": "动态" 341 | } 342 | } 343 | ] 344 | }, 345 | { 346 | "name": "Transaction", 347 | "languages": { 348 | "zh-cn": "事务" 349 | }, 350 | "children": [ 351 | { 352 | "name": "ACID", 353 | "children": [ 354 | { 355 | "name": "Atomic" 356 | }, 357 | { 358 | "name": "Consistent" 359 | }, 360 | { 361 | "name": "Isolated" 362 | }, 363 | { 364 | "name": "Durable" 365 | } 366 | ] 367 | }, 368 | { 369 | "name": "Types", 370 | "languages": { 371 | "zh-cn": "类型" 372 | }, 373 | "children": [ 374 | { 375 | "name": "Implicit", 376 | "languages": { 377 | "zh-cn": "隐式" 378 | }, 379 | "children": [ 380 | { 381 | "name": "single UPDATE/DELETE", 382 | "languages": { 383 | "zh-cn": "单个 UPDATE/DELETE" 384 | } 385 | } 386 | ] 387 | }, 388 | { 389 | "name": "Explicit", 390 | "languages": { 391 | "zh-cn": "显式" 392 | }, 393 | "children": [ 394 | { "name": "BEGIN/COMMIT/ROLLBACK" } 395 | ] 396 | } 397 | ] 398 | }, 399 | { "name": "Checkpoint" }, 400 | { 401 | "name": "Isolation Levels (low to high)", 402 | "languages": { 403 | "zh-cn": "隔离级别 (从低到高)" 404 | }, 405 | "url": "https://technet.microsoft.com/en-us/library/ms189122(v=sql.105).aspx", 406 | "children": [ 407 | { 408 | "name": "Read uncommitted", 409 | "children": [ 410 | { 411 | "name": "dirty read", 412 | "languages": { 413 | "zh-cn": "脏读" 414 | } 415 | }, 416 | { 417 | "name": "same as NOLOCK hint", 418 | "languages": { 419 | "zh-cn": "和NOLOCK一样" 420 | } 421 | } 422 | ] 423 | }, 424 | { 425 | "name": "Read committed (default)", 426 | "languages": { 427 | "zh-cn": "Read committed (默认)" 428 | }, 429 | "children": [ 430 | { 431 | "name": "READ_COMMITTED_SNAPSHOT", 432 | "children": [ 433 | { 434 | "name": "ON", 435 | "children": [ 436 | { 437 | "name": "repeatable read", 438 | "languages": { 439 | "zh-cn": "可重复的读取" 440 | } 441 | } 442 | ] 443 | }, 444 | { 445 | "name": "OFF (default)", 446 | "languages": { 447 | "zh-cn": "OFF (默认)" 448 | }, 449 | "children": [ 450 | { 451 | "name": "Nonrepeatable read, phantom", 452 | "languages": { 453 | "zh-cn": "不可重复的读取" 454 | } 455 | } 456 | ] 457 | } 458 | ] 459 | } 460 | ] 461 | }, 462 | { 463 | "name": "Repeatable read" 464 | }, 465 | { 466 | "name": "Snapshot", 467 | "children": [ 468 | { "name": "Database ALLOW_SNAPSHOT_ISOLATION ON" }, 469 | { "name": "2005+" } 470 | ] 471 | }, 472 | { 473 | "name": "Serializable" 474 | } 475 | ] 476 | } 477 | ] 478 | }, 479 | { 480 | "name": "Concurrency", 481 | "languages": { 482 | "zh-cn": "并发性" 483 | }, 484 | "children": [ 485 | { 486 | "name": "Lock", 487 | "languages": { 488 | "zh-cn": "" 489 | }, 490 | "children": [ 491 | { 492 | "name": "Optimistic", 493 | "languages": { 494 | "zh-cn": "乐观锁" 495 | } 496 | }, 497 | { 498 | "name": "Pessimistic", 499 | "languages": { 500 | "zh-cn": "悲观锁" 501 | } 502 | }, 503 | { 504 | "name": "Exclusive", 505 | "languages": { 506 | "zh-cn": "排他" 507 | } 508 | }, 509 | { 510 | "name": "Shared", 511 | "languages": { 512 | "zh-cn": "共享" 513 | } 514 | } 515 | ] 516 | }, 517 | { "name": "Wait" }, 518 | { "name": "Latch" }, 519 | { 520 | "name": "Deadlock", 521 | "languages": { 522 | "zh-cn": "死锁" 523 | }, 524 | "children": [ 525 | { "name": "Kill" } 526 | ] 527 | }, 528 | { "name": "sync/async" }, 529 | { "name": "Blocking" }, 530 | { 531 | "name": "Row versioning", 532 | "languages": { 533 | "zh-cn": "行版本" 534 | } 535 | } 536 | ] 537 | } 538 | ] 539 | }, 540 | { 541 | "name": "Core Objects", 542 | "languages": { 543 | "zh-cn": "对象" 544 | }, 545 | "children": [ 546 | { 547 | "name": "Database", 548 | "languages": { 549 | "zh-cn": "数据库" 550 | }, 551 | "children": [ 552 | { 553 | "name": "Recovery Models", 554 | "languages": { 555 | "zh-cn": "恢复模式" 556 | }, 557 | "children": [ 558 | { 559 | "name": "Purpose", 560 | "languages": { 561 | "zh-cn": "作用" 562 | }, 563 | "children": [ 564 | { 565 | "name": "Backup transaction log", 566 | "languages": { 567 | "zh-cn": "备份事务日志" 568 | } 569 | }, 570 | { 571 | "name": "Affect backup types", 572 | "languages": { 573 | "zh-cn": "影响备份类型" 574 | } 575 | }, 576 | { 577 | "name": "Affect replication types", 578 | "languages": { 579 | "zh-cn": "影响复制类型" 580 | } 581 | } 582 | ] 583 | }, 584 | { 585 | "name": "Models", 586 | "languages": { 587 | "zh-cn": "" 588 | }, 589 | "children": [ 590 | { 591 | "name": "Simple", 592 | "languages": { 593 | "zh-cn": "简单" 594 | }, 595 | "children": [ 596 | { 597 | "name": "Not point-in-time recovery" 598 | }, 599 | { 600 | "name": "Minimum space" 601 | } 602 | ] 603 | }, 604 | { 605 | "name": "Full (default)", 606 | "languages": { 607 | "zh-cn": "完整 (默认)" 608 | }, 609 | "children": [ 610 | { 611 | "name": "Point-in-time recovery" 612 | }, 613 | { 614 | "name": "Large space" 615 | } 616 | ] 617 | }, 618 | { 619 | "name": "Bulk logged", 620 | "languages": { 621 | "zh-cn": "大容量日志恢复" 622 | }, 623 | "children": [ 624 | { 625 | "name": "Point-in-time recovery" 626 | }, 627 | { 628 | "name": "No bulk operation logged" 629 | }, 630 | { 631 | "name": "Save space" 632 | } 633 | ] 634 | } 635 | ] 636 | } 637 | ] 638 | }, 639 | { 640 | "name": "Compatibility Levels", 641 | "languages": { 642 | "zh-cn": "兼容级别" 643 | }, 644 | "children": [ 645 | { 646 | "name": "Version Number", 647 | "languages": { 648 | "zh-cn": "版本" 649 | }, 650 | "children": [ 651 | { 652 | "name": "Effectively SQL Server version number", 653 | "languages": { 654 | "zh-cn": "实际上就是SQL Server的版本" 655 | } 656 | }, 657 | { "name": "@@VERSION" } 658 | ] 659 | }, 660 | { "name": "130: SQL Server 2016" }, 661 | { "name": "120: SQL Server 2014" }, 662 | { "name": "110: SQL Server 2012" }, 663 | { "name": "100: SQL Server 2008" }, 664 | { "name": "90: SQL Server 2005" }, 665 | { "name": "80: SQL Server 2000" } 666 | ] 667 | }, 668 | { 669 | "name": "Encryption", 670 | "languages": { 671 | "zh-cn": "加密" 672 | } 673 | }, 674 | { 675 | "name": "Copy", 676 | "languages": { 677 | "zh-cn": "复制" 678 | } 679 | } 680 | ] 681 | }, 682 | { 683 | "name": "Table", 684 | "languages": { 685 | "zh-cn": "表" 686 | }, 687 | "children": [ 688 | { 689 | "name": "Standard", 690 | "languages": { 691 | "zh-cn": "标准" 692 | }, 693 | "children": [ 694 | { 695 | "name": "Partition", 696 | "languages": { 697 | "zh-cn": "分区" 698 | } 699 | }, 700 | { 701 | "name": "Compression", 702 | "languages": { 703 | "zh-cn": "压缩" 704 | } 705 | } 706 | ] 707 | }, 708 | { 709 | "name": "Table Variable", 710 | "languages": { 711 | "zh-cn": "表变量" 712 | } 713 | }, 714 | { 715 | "name": "Temp Table", 716 | "languages": { 717 | "zh-cn": "临时表" 718 | }, 719 | "children": [ 720 | { 721 | "name": "Local", 722 | "languages": { 723 | "zh-cn": "本地" 724 | } 725 | }, 726 | { 727 | "name": "Global", 728 | "languages": { 729 | "zh-cn": "全局" 730 | } 731 | } 732 | ] 733 | }, 734 | { 735 | "name": "FileTable" 736 | } 737 | ] 738 | }, 739 | { 740 | "name": "View", 741 | "languages": { 742 | "zh-cn": "视图" 743 | }, 744 | "children": [ 745 | { 746 | "name": "Standard", 747 | "languages": { 748 | "zh-cn": "标准" 749 | } 750 | }, 751 | { 752 | "name": "Indexed", 753 | "languages": { 754 | "zh-cn": "索引" 755 | } 756 | }, 757 | { 758 | "name": "Partitioned", 759 | "languages": { 760 | "zh-cn": "分区" 761 | } 762 | } 763 | ] 764 | }, 765 | { 766 | "name": "Stored Procedure (SP)", 767 | "languages": { 768 | "zh-cn": "存储过程 (SP)" 769 | } 770 | }, 771 | { 772 | "name": "Function (FN)", 773 | "languages": { 774 | "zh-cn": "函数 (FN)" 775 | }, 776 | "children": [ 777 | { "name": "Table-valued Function" }, 778 | { "name": "Scalar-valued Function" } 779 | ] 780 | }, 781 | { 782 | "name": "Data Type", 783 | "languages": { 784 | "zh-cn": "数据类型" 785 | }, 786 | "children": [ 787 | { 788 | "name": "Types", 789 | "languages": { 790 | "zh-cn": "类型" 791 | }, 792 | "children": [ 793 | { 794 | "name": "System Type", 795 | "languages": { 796 | "zh-cn": "系统类型" 797 | } 798 | }, 799 | { 800 | "name": "User-defined Type (UDT)", 801 | "languages": { 802 | "zh-cn": "用户定义类型 (UDT)" 803 | } 804 | } 805 | ] 806 | }, 807 | { 808 | "name": "Conversion", 809 | "languages": { 810 | "zh-cn": "转换" 811 | } 812 | }, 813 | { 814 | "name": "Precedence", 815 | "languages": { 816 | "zh-cn": "优先级" 817 | } 818 | }, 819 | { 820 | "name": "Synonym", 821 | "languages": { 822 | "zh-cn": "同义词" 823 | } 824 | }, 825 | { "name": "Precision/Scale/Length" }, 826 | { "name": "XML" }, 827 | { "name": "JSON" }, 828 | { "name": "Spatial (CLR)" } 829 | ] 830 | }, 831 | { 832 | "name": "Index", 833 | "languages": { 834 | "zh-cn": "索引" 835 | }, 836 | "children": [ 837 | { 838 | "name": "Index Types", 839 | "languages": { 840 | "zh-cn": "索引类型" 841 | }, 842 | "children": [ 843 | { 844 | "name": "Clustered Index", 845 | "languages": { 846 | "zh-cn": "聚集索引" 847 | } 848 | }, 849 | { 850 | "name": "Non-clustered Index", 851 | "languages": { 852 | "zh-cn": "非聚集索引" 853 | } 854 | } 855 | ] 856 | }, 857 | { 858 | "name": "Index Setting", 859 | "languages": { 860 | "zh-cn": "索引设置" 861 | }, 862 | "children": [ 863 | { "name": "Include" }, 864 | { "name": "Filter" } 865 | ] 866 | }, 867 | { 868 | "name": "Index Management", 869 | "languages": { 870 | "zh-cn": "索引管理" 871 | }, 872 | "children": [ 873 | { "name": "Rebuild" }, 874 | { "name": "Reorganise" }, 875 | { "name": "Disable" }, 876 | { "name": "Enable" }, 877 | { "name": "Drop" } 878 | ] 879 | } 880 | ] 881 | }, 882 | { 883 | "name": "Column", 884 | "languages": { 885 | "zh-cn": "列" 886 | }, 887 | "children": [ 888 | { 889 | "name": "columnstore", 890 | "languages": { 891 | "zh-cn": "" 892 | }, 893 | "children": [ 894 | { 895 | "name": "Suitable for Data warehouse", 896 | "languages": { 897 | "zh-cn": "适合数据仓库" 898 | } 899 | } 900 | ] 901 | }, 902 | { "name": "NTFS FileStream" } 903 | ] 904 | }, 905 | { "name": "Schema" }, 906 | { 907 | "name": "Trigger", 908 | "languages": { 909 | "zh-cn": "触发器" 910 | }, 911 | "children": [ 912 | { 913 | "name": "Table Trigger", 914 | "languages": { 915 | "zh-cn": "表触发器" 916 | }, 917 | "children": [ 918 | { "name": "BEFORE" }, 919 | { "name": "FOR/AFTER" }, 920 | { "name": "INSTEAD OF" } 921 | ] 922 | } 923 | ] 924 | }, 925 | { "name": "Constraint" }, 926 | { "name": "Key" }, 927 | { "name": "Default" }, 928 | { 929 | "name": "Synonym" 930 | }, 931 | { 932 | "name": "Sequence", 933 | "languages": { 934 | "zh-cn": "序列" 935 | } 936 | }, 937 | { 938 | "name": "Variable", 939 | "languages": { 940 | "zh-cn": "变量" 941 | }, 942 | "children": [ 943 | { 944 | "name": "Local Variable (@)", 945 | "languages": { 946 | "zh-cn": "本地变量 (@)" 947 | } 948 | }, 949 | { 950 | "name": "Global Variable (@@)", 951 | "languages": { 952 | "zh-cn": "全局变量 (@@)" 953 | } 954 | } 955 | ] 956 | }, 957 | { "name": "Common Table Expression (CTE)" }, 958 | { "name": "Cursor" }, 959 | { "name": "Collation" }, 960 | { "name": "Login" }, 961 | { "name": "User" }, 962 | { "name": "Rule" }, 963 | { "name": "Server role" }, 964 | { "name": "Endpoint" }, 965 | { 966 | "name": "Job", 967 | "languages": { 968 | "zh-cn": "作业" 969 | }, 970 | "children": [ 971 | { "name": "Job Agent" }, 972 | { "name": "Job Activity Monitor" }, 973 | { "name": "Alert" }, 974 | { "name": "Operator" }, 975 | { 976 | "name": "SQL Job", 977 | "children": [ 978 | { "name": "Step" }, 979 | { "name": "Schedule" }, 980 | { "name": "Notification" } 981 | ] 982 | } 983 | ] 984 | }, 985 | { 986 | "name": "SQL CLR (.NET CLR)", 987 | "children": [ 988 | { "name": "Assembly" }, 989 | { 990 | "name": "Managed Code Types", 991 | "children": [ 992 | { "name": "Function" }, 993 | { "name": "Stored Procedure" }, 994 | { "name": "Trigger" }, 995 | { "name": "UDF" }, 996 | { "name": "UDA" }, 997 | { "name": "UDT" } 998 | ] 999 | }, 1000 | { "name": "Security Levels" } 1001 | ] 1002 | }, 1003 | { "name": "Linked Server" }, 1004 | { 1005 | "name": "Service Broker", 1006 | "children": [ 1007 | { 1008 | "name": "Basics", 1009 | "languages": { 1010 | "zh-cn": "基本知识" 1011 | }, 1012 | "children": [ 1013 | { "name": "Transactional message queue" } 1014 | ] 1015 | }, 1016 | { 1017 | "name": "Objects", 1018 | "languages": { 1019 | "zh-cn": "对象" 1020 | }, 1021 | "children": [ 1022 | { "name": "Message" }, 1023 | { "name": "Contract" }, 1024 | { "name": "Queue" }, 1025 | { "name": "Service" }, 1026 | { "name": "Dialog" }, 1027 | { "name": "Conversation" } 1028 | ] 1029 | } 1030 | ] 1031 | } 1032 | ] 1033 | }, 1034 | { 1035 | "name": "Standard", 1036 | "languages": { 1037 | "zh-cn": "标准" 1038 | }, 1039 | "children": [ 1040 | { 1041 | "name": "ANSI 92" 1042 | } 1043 | ] 1044 | }, 1045 | { 1046 | "name": "Languages", 1047 | "languages": { 1048 | "zh-cn": "语言" 1049 | }, 1050 | "children": [ 1051 | { 1052 | "name": "Query Language", 1053 | "languages": { 1054 | "zh-cn": "查询语言" 1055 | }, 1056 | "children": [ 1057 | { "name": "T-SQL (Transact-SQL)" }, 1058 | { "name": "MDX (MultiDimensional eXpressions)" } 1059 | ] 1060 | }, 1061 | { 1062 | "name": "Data Manipulation Language (DML)", 1063 | "languages": { 1064 | "zh-cn": "数据操作语言 (DML)" 1065 | }, 1066 | "children": [ 1067 | { 1068 | "name": "CRUD", 1069 | "children": [ 1070 | { "name": "Create (INSERT)" }, 1071 | { "name": "Retrieve (SELECT)" }, 1072 | { "name": "Update (UPDATE)" }, 1073 | { "name": "Delete (DELETE)" } 1074 | ] 1075 | }, 1076 | { "name": "MERGE" }, 1077 | { 1078 | "name": "TEXT", 1079 | "children": [ 1080 | { "name": "UPDATETEXT" }, 1081 | { "name": "WRITETEXT" }, 1082 | { "name": "READTEXT" } 1083 | ] 1084 | }, 1085 | { "name": "BULK INSERT" }, 1086 | { "name": "EXECUTE" } 1087 | ] 1088 | }, 1089 | { 1090 | "name": "Data Definition Language (DDL)", 1091 | "languages": { 1092 | "zh-cn": "数据定义语言 (DDL)" 1093 | }, 1094 | "children": [ 1095 | { "name": "CREATE" }, 1096 | { "name": "ALTER" }, 1097 | { "name": "DROP" }, 1098 | { "name": "TRUNCATE" }, 1099 | { "name": "RESTORE" }, 1100 | { "name": "RECONFIGURE" } 1101 | ] 1102 | }, 1103 | { 1104 | "name": "Data Control Language (DCL)", 1105 | "languages": { 1106 | "zh-cn": "数据控制语言 (DCL)" 1107 | }, 1108 | "children": [ 1109 | { "name": "GRANT" }, 1110 | { "name": "REVOKE" } 1111 | ] 1112 | }, 1113 | { 1114 | "name": "Transaction Control Language (TCL)", 1115 | "languages": { 1116 | "zh-cn": "事务控制语言 (TCL)" 1117 | }, 1118 | "children": [ 1119 | { "name": "BEGIN TRANSACTION" }, 1120 | { "name": "COMMIT" }, 1121 | { "name": "ROLLBACK" }, 1122 | { "name": "SAVE TRANSACTION" } 1123 | ] 1124 | } 1125 | ] 1126 | }, 1127 | { 1128 | "name": "System Databases", 1129 | "languages": { 1130 | "zh-cn": "系统数据库" 1131 | }, 1132 | "children": [ 1133 | { "name": "master (dbs, logins, configs)" }, 1134 | { "name": "tempdb (temp tables / sps)" }, 1135 | { "name": "msdb (jobs/alerts/backups)" }, 1136 | { "name": "model (template for new db)" }, 1137 | { "name": "resource (invisible, system objects)" } 1138 | ] 1139 | }, 1140 | { 1141 | "name": "File", 1142 | "languages": { 1143 | "zh-cn": "文件" 1144 | }, 1145 | "children": [ 1146 | { "name": "primary (MDF)" }, 1147 | { "name": "secondary (NDF)" }, 1148 | { "name": "log (LDF)" }, 1149 | { "name": "File/Filegroup" }, 1150 | { "name": "Auto Grow" } 1151 | ] 1152 | }, 1153 | { 1154 | "name": "Runtime", 1155 | "languages": { 1156 | "zh-cn": "运行时" 1157 | }, 1158 | "children": [ 1159 | { "name": "Process" }, 1160 | { "name": "Worker" }, 1161 | { "name": "Connection" }, 1162 | { "name": "Request" }, 1163 | { "name": "Stall" }, 1164 | { "name": "Stats" }, 1165 | { "name": "Query Store" }, 1166 | { 1167 | "name": "Cache", 1168 | "children": [ 1169 | { "name": "aging" } 1170 | ] 1171 | }, 1172 | { "name": "Catalog Views" }, 1173 | { 1174 | "name": "Dynamic Management Views (DMV)", 1175 | "children": [ 1176 | { "name": "Execution count" }, 1177 | { "name": "Execution io/cpu/perf" } 1178 | ] 1179 | }, 1180 | { 1181 | "name": "Full Text Search (FTS)", 1182 | "children": [ 1183 | { "name": "Integrated Full Text Search (iFTS)" } 1184 | ] 1185 | }, 1186 | { "name": "Trace flags" } 1187 | ] 1188 | }, 1189 | { 1190 | "name": "Replication", 1191 | "languages": { 1192 | "zh-cn": "复制" 1193 | }, 1194 | "children": [ 1195 | { "name": "Log Shipping" }, 1196 | { 1197 | "name": "Publish/Subscribe", 1198 | "children": [ 1199 | { "name": "Transactional" }, 1200 | { "name": "Merge" }, 1201 | { "name": "Snapshot" } 1202 | ] 1203 | }, 1204 | { 1205 | "name": "Mirroring (deprecated from 2012)", 1206 | "children": [ 1207 | { 1208 | "name": "Core", 1209 | "children": [ 1210 | { "name": "Principal" }, 1211 | { "name": "Witness" } 1212 | ] 1213 | }, 1214 | { "name": "Database Mirroring Monitor" } 1215 | ] 1216 | }, 1217 | { "name": "AlwaysOn" }, 1218 | { 1219 | "name": "Clustering", 1220 | "children": [ 1221 | { 1222 | "name": "Core", 1223 | "children": [ 1224 | { "name": "Shared Disk Array" }, 1225 | { "name": "Quorum" } 1226 | ] 1227 | }, 1228 | { 1229 | "name": "Failover", 1230 | "children": [ 1231 | { "name": "Active/Active" }, 1232 | { "name": "Active/Passive" } 1233 | ] 1234 | } 1235 | ] 1236 | }, 1237 | { "name": "Snapshot" } 1238 | ] 1239 | }, 1240 | { 1241 | "name": "Versions", 1242 | "languages": { 1243 | "zh-cn": "版本号" 1244 | }, 1245 | "children": [ 1246 | { 1247 | "name": "SQL Server 2005", 1248 | "children": [ 1249 | { "name": "SSIS" }, 1250 | { "name": "SSRS" }, 1251 | { "name": "SSAS" }, 1252 | { "name": "Common Language Runtime (CLR)" }, 1253 | { "name": "XML" }, 1254 | { "name": "Data Service (SOAP)" }, 1255 | { "name": "Service Broker" }, 1256 | { "name": "Common Table Expression (CTE)" }, 1257 | { "name": "Dynamic Management View (DMV)" }, 1258 | { "name": "Database Mirroring (SP1)" }, 1259 | { "name": "TRY/CATCH" } 1260 | ] 1261 | }, 1262 | { 1263 | "name": "SQL Server 2008", 1264 | "children": [ 1265 | { "name": "Always On" }, 1266 | { "name": "FILESTREAM" }, 1267 | { "name": "Integrated Full-Text Search (iFTS)" }, 1268 | { 1269 | "name": "Spatial Types", 1270 | "children": [ 1271 | { "name": "GEOMETRY" }, 1272 | { "name": "GEOGRAPHY" } 1273 | ] 1274 | }, 1275 | { "name": "Transparent Data Encryption (TDE)" }, 1276 | { "name": "IntelliSense" }, 1277 | { "name": "SSRS Charting (acquired Dundas charts)" } 1278 | ] 1279 | }, 1280 | { 1281 | "name": "SQL Server 2012", 1282 | "children": [ 1283 | { "name": "Sequence" }, 1284 | { "name": "THROW" } 1285 | ] 1286 | }, 1287 | { 1288 | "name": "SQL Server 2014", 1289 | "children": [ 1290 | { "name": "In-memory Table" }, 1291 | { "name": "Clustered Columnstore Index" } 1292 | ] 1293 | }, 1294 | { 1295 | "name": "SQL Server 2016", 1296 | "children": [ 1297 | { "name": "Columnstore Index" }, 1298 | { "name": "In-memory OLTP" }, 1299 | { "name": "JSON" }, 1300 | { "name": "Query Store" }, 1301 | { "name": "Temporal Tables" }, 1302 | { "name": "Polybase (connector to BigData)" }, 1303 | { "name": "Always Encrypted" } 1304 | ] 1305 | } 1306 | ] 1307 | }, 1308 | { 1309 | "name": "Editions", 1310 | "languages": { 1311 | "zh-cn": "产品版本" 1312 | }, 1313 | "children": [ 1314 | { "name": "Express" }, 1315 | { "name": "BI" }, 1316 | { "name": "Web" }, 1317 | { "name": "Standard" }, 1318 | { "name": "Enterprise" }, 1319 | { "name": "Datacenter" }, 1320 | { "name": "Local DB" } 1321 | ] 1322 | }, 1323 | { 1324 | "name": "Management", 1325 | "languages": { 1326 | "zh-cn": "管理" 1327 | }, 1328 | "children": [ 1329 | { "name": "SQL Server Management Studio (SSMS)" }, 1330 | { "name": "SQL Operations Studio" }, 1331 | { "name": "SQL Server Command Line Util (sqlcmd)" }, 1332 | { 1333 | "name": "SQL Monitor ;-)", 1334 | "url": "https://github.com/unruledboy/SQLMonitor" 1335 | } 1336 | ] 1337 | }, 1338 | { 1339 | "name": "Maintenance", 1340 | "languages": { 1341 | "zh-cn": "维护" 1342 | }, 1343 | "children": [ 1344 | { "name": "Maintenance Plan" }, 1345 | { "name": "Logs" }, 1346 | { "name": "Database Mail" }, 1347 | { 1348 | "name": "Database", 1349 | "children": [ 1350 | { 1351 | "name": "Backup/Restore", 1352 | "children": [ 1353 | { 1354 | "name": "Mode", 1355 | "children": [ 1356 | { "name": "Full" }, 1357 | { "name": "Differential" }, 1358 | { "name": "Transaction log" } 1359 | ] 1360 | } 1361 | ] 1362 | }, 1363 | { "name": "Online/Offline" }, 1364 | { "name": "Attach/Dettach" }, 1365 | { "name": "Shrink" } 1366 | ] 1367 | }, 1368 | { "name": "Import/Export" }, 1369 | { "name": "DBCC" }, 1370 | { "name": "Bulk Copy (bcp command line)" }, 1371 | { "name": "Resource governor" }, 1372 | { "name": "Facets" } 1373 | ] 1374 | }, 1375 | { 1376 | "name": "Business Intelligence (BI)", 1377 | "languages": { 1378 | "zh-cn": "商业智能 (BI)" 1379 | }, 1380 | "children": [ 1381 | { 1382 | "name": "SQL Server Integration Service (SSIS)", 1383 | "children": [ 1384 | { "name": "Extract-Transform-Load (ETL)" } 1385 | ] 1386 | }, 1387 | { "name": "SQL Server Reporting Service (SSRS)" }, 1388 | { 1389 | "name": "SQL Server Analysis Service (SSAS)", 1390 | "children": [ 1391 | { "name": "OLAP" } 1392 | ] 1393 | } 1394 | ] 1395 | }, 1396 | { 1397 | "name": "Troubleshoot", 1398 | "languages": { 1399 | "zh-cn": "调试" 1400 | }, 1401 | "children": [ 1402 | { 1403 | "name": "Dedicated Administrator Connection (DAC)", 1404 | "children": [ 1405 | { "name": "ADMIN:INSTANCE" }, 1406 | { "name": "SQL Browser service must be running" } 1407 | ] 1408 | }, 1409 | { "name": "SQL Server Profiler" }, 1410 | { "name": "Activity Monitor" }, 1411 | { 1412 | "name": "Error", 1413 | "children": [ 1414 | { "name": "Severity Levels" }, 1415 | { "name": "Error Log" }, 1416 | { "name": "sys.xp_readerrorlog" } 1417 | ] 1418 | } 1419 | ] 1420 | }, 1421 | { 1422 | "name": "Performance", 1423 | "languages": { 1424 | "zh-cn": "性能" 1425 | }, 1426 | "children": [ 1427 | { "name": "Seek" }, 1428 | { "name": "Scan" }, 1429 | { "name": "Fragmentation" }, 1430 | { "name": "Partitioning" }, 1431 | { "name": "Database Engine Tuning Advisor" } 1432 | ] 1433 | }, 1434 | { 1435 | "name": "Services", 1436 | "languages": { 1437 | "zh-cn": "服务" 1438 | }, 1439 | "children": [ 1440 | { "name": "SQL Server" }, 1441 | { "name": "SQL Server Browser" }, 1442 | { "name": "SQL Server Agent" } 1443 | ] 1444 | }, 1445 | { 1446 | "name": "Connectivity", 1447 | "languages": { 1448 | "zh-cn": "连接" 1449 | }, 1450 | "children": [ 1451 | { "name": "ADO.NET" }, 1452 | { "name": "ODBC" }, 1453 | { "name": "JDBC" } 1454 | ] 1455 | }, 1456 | { 1457 | "name": "Security", 1458 | "languages": { 1459 | "zh-cn": "安全" 1460 | }, 1461 | "children": [ 1462 | { "name": "Access Control" }, 1463 | { "name": "SQL Inject" }, 1464 | { "name": "Backup" } 1465 | ] 1466 | }, 1467 | { 1468 | "name": "Testing", 1469 | "languages": { 1470 | "zh-cn": "测试" 1471 | }, 1472 | "children": [ 1473 | { 1474 | "name": "tSQLt", 1475 | "url": "http://tsqlt.org/" 1476 | } 1477 | ] 1478 | } 1479 | ] 1480 | }, 1481 | { 1482 | "name": "Oracle", 1483 | "url": "https://www.oracle.com/database/" 1484 | }, 1485 | { 1486 | "name": "MySQL", 1487 | "url": "https://www.mysql.com/" 1488 | }, 1489 | { 1490 | "name": "PostgreSQL", 1491 | "url": "http://www.postgresql.org/" 1492 | }, 1493 | { 1494 | "name": "Informix", 1495 | "url": "http://www.ibm.com/software/data/informix" 1496 | }, 1497 | { 1498 | "name": "DB2", 1499 | "url": "http://www.ibm.com/software/data/db2" 1500 | } 1501 | ] 1502 | }, 1503 | { 1504 | "name": "Cloud", 1505 | "languages": { 1506 | "zh-cn": "云" 1507 | }, 1508 | "children": [ 1509 | { 1510 | "name": "Azure", 1511 | "url": "https://azure.microsoft.com", 1512 | "children": [ 1513 | { "name": "Database" }, 1514 | { "name": "Redis Cache" }, 1515 | { 1516 | "name": "Storage", 1517 | "children": [ 1518 | { "name": "Blobs" }, 1519 | { "name": "Tables" }, 1520 | { "name": "Queues" }, 1521 | { "name": "Files and Disks" } 1522 | ] 1523 | }, 1524 | { "name": "StorSimple" }, 1525 | { "name": "SQL Data Warehouse" } 1526 | ] 1527 | } 1528 | ] 1529 | }, 1530 | { 1531 | "name": "NoSQL", 1532 | "url": "https://en.wikipedia.org/wiki/NoSQL", 1533 | "children": [ 1534 | { 1535 | "name": "Concepts", 1536 | "languages": { 1537 | "zh-cn": "概念" 1538 | }, 1539 | "children": [ 1540 | { 1541 | "name": "XML/JSON based", 1542 | "languages": { 1543 | "zh-cn": "基于XML/JSON" 1544 | } 1545 | }, 1546 | { 1547 | "name": "Eventually Consistency", 1548 | "languages": { 1549 | "zh-cn": "最终一致性" 1550 | } 1551 | } 1552 | ] 1553 | }, 1554 | { 1555 | "name": "Limitation", 1556 | "languages": { 1557 | "zh-cn": "限制" 1558 | }, 1559 | "children": [ 1560 | { 1561 | "name": "CAPS/Brewer's theorem", 1562 | "languages": { 1563 | "zh-cn": "CAPS/Brewer理论" 1564 | }, 1565 | "url": "https://en.wikipedia.org/wiki/CAP_theorem", 1566 | "children": [ 1567 | { 1568 | "name": "Consistency", 1569 | "languages": { 1570 | "zh-cn": "一致性" 1571 | } 1572 | }, 1573 | { 1574 | "name": "Availability", 1575 | "languages": { 1576 | "zh-cn": "可用性" 1577 | } 1578 | }, 1579 | { 1580 | "name": "Partition tolerance", 1581 | "languages": { 1582 | "zh-cn": "网络分区容忍性" 1583 | } 1584 | } 1585 | ] 1586 | }, 1587 | { 1588 | "name": "Lack of join", 1589 | "languages": { 1590 | "zh-cn": "缺乏关联" 1591 | } 1592 | }, 1593 | { 1594 | "name": "Lack of true ACID", 1595 | "languages": { 1596 | "zh-cn": "缺乏真正的ACID" 1597 | } 1598 | } 1599 | ] 1600 | }, 1601 | { 1602 | "name": "Types", 1603 | "languages": { 1604 | "zh-cn": "类型" 1605 | }, 1606 | "children": [ 1607 | { 1608 | "name": "Column", 1609 | "languages": { 1610 | "zh-cn": "列" 1611 | }, 1612 | "children": [ 1613 | { 1614 | "name": "Cassandra", 1615 | "url": "http://cassandra.apache.org/" 1616 | }, 1617 | { 1618 | "name": "HBase", 1619 | "url": "http://hbase.apache.org/" 1620 | } 1621 | ] 1622 | }, 1623 | { 1624 | "name": "Key/Value", 1625 | "languages": { 1626 | "zh-cn": "键值" 1627 | }, 1628 | "children": [ 1629 | { 1630 | "name": "CouchDB", 1631 | "url": "http://couchdb.apache.org/" 1632 | }, 1633 | { 1634 | "name": "AWS Dynamo", 1635 | "url": "https://aws.amazon.com/dynamodb/" 1636 | }, 1637 | { 1638 | "name": "MemcacheDB", 1639 | "url": "http://memcachedb.org/" 1640 | }, 1641 | { 1642 | "name": "Redis", 1643 | "url": "http://redis.io/" 1644 | } 1645 | ] 1646 | }, 1647 | { 1648 | "name": "Document", 1649 | "languages": { 1650 | "zh-cn": "文档" 1651 | }, 1652 | "children": [ 1653 | { 1654 | "name": "Apache CouchDB", 1655 | "url": "http://couchdb.apache.org/" 1656 | }, 1657 | { 1658 | "name": "Couchbase", 1659 | "url": "http://www.couchbase.com/" 1660 | }, 1661 | { 1662 | "name": "Azure DocumentDB", 1663 | "url": "http://azure.microsoft.com/en-us/services/documentdb/" 1664 | }, 1665 | { 1666 | "name": "MongoDB", 1667 | "url": "https://www.mongodb.org/" 1668 | } 1669 | ] 1670 | }, 1671 | { 1672 | "name": "Graph", 1673 | "languages": { 1674 | "zh-cn": "图形关系" 1675 | }, 1676 | "children": [ 1677 | { 1678 | "name": "Neo4J", 1679 | "url": "http://neo4j.com/" 1680 | } 1681 | ] 1682 | }, 1683 | { 1684 | "name": "Object", 1685 | "languages": { 1686 | "zh-cn": "对象" 1687 | }, 1688 | "children": [ 1689 | { 1690 | "name": "ObjectStore", 1691 | "url": "http://www.objectstore.com/" 1692 | } 1693 | ] 1694 | } 1695 | ] 1696 | } 1697 | ] 1698 | } 1699 | ] 1700 | } 1701 | -------------------------------------------------------------------------------- /ux/dndTree.js: -------------------------------------------------------------------------------- 1 |  2 | (function() { 3 | var isPhantom = /PhantomJS/ig.test(navigator.userAgent); 4 | var locale = location.search.split("locale=").pop().split("&").shift(); 5 | 6 | var parseName = function(object) { 7 | if (!object.languages) return object.name; 8 | return object.languages[locale] || object.name; 9 | } 10 | 11 | // Get JSON data 12 | var treeJSON = d3.json('DatabaseStack.json', function(error, treeData) { 13 | 14 | // Calculate total nodes, max label length 15 | var totalNodes = 0; 16 | var maxLabelLength = []; 17 | // variables for drag/drop 18 | var selectedNode = null; 19 | var draggingNode = null; 20 | // panning variables 21 | var panSpeed = 200; 22 | var panBoundary = 20; // Within 20px from edges will pan when dragging. 23 | // Misc. variables 24 | var i = 0; 25 | var duration = 750; 26 | var root; 27 | 28 | // size of the diagram 29 | var viewerWidth = $(document).width(); 30 | var viewerHeight = $(document).height(); 31 | 32 | var tree = d3.layout.tree() 33 | .size([viewerHeight, viewerWidth]); 34 | 35 | // define a d3 diagonal projection for use by the node paths later on. 36 | var diagonal = d3.svg.diagonal() 37 | .projection(function(d) { 38 | return [d.y, d.x]; 39 | }); 40 | 41 | // A recursive helper function for performing some setup by walking through all nodes 42 | 43 | function visit(parent, visitFn, childrenFn, depth) { 44 | if (!parent) return; 45 | 46 | visitFn(parent, depth); 47 | 48 | var children = childrenFn(parent); 49 | if (children) { 50 | var count = children.length; 51 | var d = depth + 1; 52 | for (var i = 0; i < count; i++) { 53 | visit(children[i], visitFn, childrenFn, d); 54 | } 55 | } 56 | } 57 | 58 | // Call visit function to establish maxLabelLength 59 | visit(treeData, function(d, depth) { 60 | totalNodes++; 61 | if (maxLabelLength[depth] == undefined) 62 | maxLabelLength[depth] = 0; 63 | maxLabelLength[depth] = Math.max(parseName(d).length, maxLabelLength[depth]); 64 | }, function(d) { 65 | return d.children && d.children.length > 0 ? d.children : null; 66 | }, 0); 67 | 68 | 69 | // sort the tree according to the node names 70 | 71 | function sortTree() { 72 | tree.sort(function(a, b) { 73 | return parseName(b).toLowerCase() < parseName(a).toLowerCase() ? 1 : -1; 74 | }); 75 | } 76 | // Sort the tree initially incase the JSON isn't in a sorted order. 77 | //sortTree(); 78 | 79 | // TODO: Pan function, can be better implemented. 80 | 81 | function pan(domNode, direction) { 82 | var speed = panSpeed; 83 | if (panTimer) { 84 | clearTimeout(panTimer); 85 | translateCoords = d3.transform(svgGroup.attr("transform")); 86 | if (direction == 'left' || direction == 'right') { 87 | translateX = direction == 'left' ? translateCoords.translate[0] + speed : translateCoords.translate[0] - speed; 88 | translateY = translateCoords.translate[1]; 89 | } else if (direction == 'up' || direction == 'down') { 90 | translateX = translateCoords.translate[0]; 91 | translateY = direction == 'up' ? translateCoords.translate[1] + speed : translateCoords.translate[1] - speed; 92 | } 93 | scaleX = translateCoords.scale[0]; 94 | scaleY = translateCoords.scale[1]; 95 | scale = zoomListener.scale(); 96 | svgGroup.transition().attr("transform", "translate(" + translateX + "," + translateY + ")scale(" + scale + ")"); 97 | d3.select(domNode).select('g.node').attr("transform", "translate(" + translateX + "," + translateY + ")"); 98 | zoomListener.scale(zoomListener.scale()); 99 | zoomListener.translate([translateX, translateY]); 100 | panTimer = setTimeout(function() { 101 | pan(domNode, speed, direction); 102 | }, 50); 103 | } 104 | } 105 | 106 | // Define the zoom function for the zoomable tree 107 | 108 | function zoom() { 109 | svgGroup.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")"); 110 | } 111 | 112 | 113 | // define the zoomListener which calls the zoom function on the "zoom" event constrained within the scaleExtents 114 | var zoomListener = d3.behavior.zoom().scaleExtent([0.1, 3]).on("zoom", zoom); 115 | 116 | function initiateDrag(d, domNode) { 117 | draggingNode = d; 118 | d3.select(domNode).select('.ghostCircle').attr('pointer-events', 'none'); 119 | d3.selectAll('.ghostCircle').attr('class', 'ghostCircle show'); 120 | d3.select(domNode).attr('class', 'node activeDrag'); 121 | 122 | svgGroup.selectAll("g.node").sort(function(a, b) { // select the parent and sort the path's 123 | if (a.id != draggingNode.id) return 1; // a is not the hovered element, send "a" to the back 124 | else return -1; // a is the hovered element, bring "a" to the front 125 | }); 126 | // if nodes has children, remove the links and nodes 127 | if (nodes.length > 1) { 128 | // remove link paths 129 | links = tree.links(nodes); 130 | nodePaths = svgGroup.selectAll("path.link") 131 | .data(links, function(d) { 132 | return d.target.id; 133 | }).remove(); 134 | // remove child nodes 135 | nodesExit = svgGroup.selectAll("g.node") 136 | .data(nodes, function(d) { 137 | return d.id; 138 | }).filter(function(d, i) { 139 | if (d.id == draggingNode.id) { 140 | return false; 141 | } 142 | return true; 143 | }).remove(); 144 | } 145 | 146 | // remove parent link 147 | parentLink = tree.links(tree.nodes(draggingNode.parent)); 148 | svgGroup.selectAll('path.link').filter(function(d, i) { 149 | if (d.target.id == draggingNode.id) { 150 | return true; 151 | } 152 | return false; 153 | }).remove(); 154 | 155 | dragStarted = null; 156 | } 157 | 158 | // define the baseSvg, attaching a class for styling and the zoomListener 159 | var baseSvg = d3.select("#tree-container").append("svg:svg") 160 | .attr("width", viewerWidth) 161 | .attr("height", viewerHeight) 162 | .attr("class", "overlay") 163 | .call(zoomListener) 164 | 165 | 166 | // Define the drag listeners for drag/drop behaviour of nodes. 167 | dragListener = d3.behavior.drag() 168 | .on("dragstart", function(d) { 169 | if (d == root) { 170 | return; 171 | } 172 | dragStarted = true; 173 | nodes = tree.nodes(d); 174 | d3.event.sourceEvent.stopPropagation(); 175 | // it's important that we suppress the mouseover event on the node being dragged. Otherwise it will absorb the mouseover event and the underlying node will not detect it d3.select(this).attr('pointer-events', 'none'); 176 | }) 177 | .on("drag", function(d) { 178 | if (d == root) { 179 | return; 180 | } 181 | if (dragStarted) { 182 | domNode = this; 183 | initiateDrag(d, domNode); 184 | } 185 | 186 | // get coords of mouseEvent relative to svg container to allow for panning 187 | relCoords = d3.mouse($('svg').get(0)); 188 | if (relCoords[0] < panBoundary) { 189 | panTimer = true; 190 | pan(this, 'left'); 191 | } else if (relCoords[0] > ($('svg').width() - panBoundary)) { 192 | 193 | panTimer = true; 194 | pan(this, 'right'); 195 | } else if (relCoords[1] < panBoundary) { 196 | panTimer = true; 197 | pan(this, 'up'); 198 | } else if (relCoords[1] > ($('svg').height() - panBoundary)) { 199 | panTimer = true; 200 | pan(this, 'down'); 201 | } else { 202 | try { 203 | clearTimeout(panTimer); 204 | } catch (e) { 205 | 206 | } 207 | } 208 | 209 | d.x0 += d3.event.dy; 210 | d.y0 += d3.event.dx; 211 | var node = d3.select(this); 212 | node.attr("transform", "translate(" + d.y0 + "," + d.x0 + ")"); 213 | updateTempConnector(); 214 | }).on("dragend", function(d) { 215 | if (d == root) { 216 | return; 217 | } 218 | domNode = this; 219 | if (selectedNode) { 220 | // now remove the element from the parent, and insert it into the new elements children 221 | var index = draggingNode.parent.children.indexOf(draggingNode); 222 | if (index > -1) { 223 | draggingNode.parent.children.splice(index, 1); 224 | } 225 | if (typeof selectedNode.children !== 'undefined' || typeof selectedNode._children !== 'undefined') { 226 | if (typeof selectedNode.children !== 'undefined') { 227 | selectedNode.children.push(draggingNode); 228 | } else { 229 | selectedNode._children.push(draggingNode); 230 | } 231 | } else { 232 | selectedNode.children = []; 233 | selectedNode.children.push(draggingNode); 234 | } 235 | // Make sure that the node being added to is expanded so user can see added node is correctly moved 236 | expand(selectedNode); 237 | sortTree(); 238 | endDrag(); 239 | } else { 240 | endDrag(); 241 | } 242 | }); 243 | 244 | function endDrag() { 245 | selectedNode = null; 246 | d3.selectAll('.ghostCircle').attr('class', 'ghostCircle'); 247 | d3.select(domNode).attr('class', 'node'); 248 | // now restore the mouseover event or we won't be able to drag a 2nd time 249 | d3.select(domNode).select('.ghostCircle').attr('pointer-events', ''); 250 | updateTempConnector(); 251 | if (draggingNode !== null) { 252 | update(root); 253 | centerNode(draggingNode); 254 | draggingNode = null; 255 | } 256 | } 257 | 258 | // Helper functions for collapsing and expanding nodes. 259 | 260 | function collapse(d) { 261 | if (d.children) { 262 | d._children = d.children; 263 | d._children.forEach(collapse); 264 | d.children = null; 265 | } 266 | } 267 | 268 | function expand(d) { 269 | if (d._children) { 270 | d.children = d._children; 271 | d.children.forEach(expand); 272 | d._children = null; 273 | } 274 | } 275 | 276 | var overCircle = function(d) { 277 | selectedNode = d; 278 | updateTempConnector(); 279 | }; 280 | var outCircle = function(d) { 281 | selectedNode = null; 282 | updateTempConnector(); 283 | }; 284 | 285 | // Function to update the temporary connector indicating dragging affiliation 286 | var updateTempConnector = function() { 287 | var data = []; 288 | if (draggingNode !== null && selectedNode !== null) { 289 | // have to flip the source coordinates since we did this for the existing connectors on the original tree 290 | data = [{ 291 | source: { 292 | x: selectedNode.y0, 293 | y: selectedNode.x0 294 | }, 295 | target: { 296 | x: draggingNode.y0, 297 | y: draggingNode.x0 298 | } 299 | }]; 300 | } 301 | var link = svgGroup.selectAll(".templink").data(data); 302 | 303 | link.enter().append("path") 304 | .attr("class", "templink") 305 | .attr("d", d3.svg.diagonal()) 306 | .attr('pointer-events', 'none'); 307 | 308 | link.attr("d", d3.svg.diagonal()); 309 | 310 | link.exit().remove(); 311 | }; 312 | 313 | // Function to center node when clicked/dropped so node doesn't get lost when collapsing/moving with large amount of children. 314 | 315 | function centerNode(source) { 316 | scale = zoomListener.scale(); 317 | 318 | x = -source.y0; 319 | y = -source.x0; 320 | x = x * scale + viewerWidth / 2; 321 | y = y * scale + viewerHeight / 2; 322 | d3.select('g').transition() 323 | .duration(duration) 324 | .attr("transform", "translate(" + x + "," + y + ")scale(" + scale + ")"); 325 | zoomListener.scale(scale); 326 | zoomListener.translate([x, y]); 327 | } 328 | 329 | function leftNode(source) { 330 | scale = zoomListener.scale(); 331 | 332 | x = 100 * scale; 333 | y = source.y0 * scale; 334 | console.log(x); 335 | 336 | d3.select('g').transition() 337 | .duration(duration) 338 | .attr("transform", "translate(" + x + "," + y + ")scale(" + scale + ")"); 339 | zoomListener.scale(scale); 340 | zoomListener.translate([x, y]); 341 | } 342 | 343 | // Toggle children function 344 | 345 | function toggleChildren(d) { 346 | if (d.children) { 347 | d._children = d.children; 348 | d.children = null; 349 | } else if (d._children) { 350 | d.children = d._children; 351 | d._children = null; 352 | } 353 | return d; 354 | } 355 | 356 | // Toggle children on click. 357 | 358 | function click(d) { 359 | if (d3.event.defaultPrevented) return; // click suppressed 360 | d = toggleChildren(d); 361 | update(d); 362 | centerNode(d); 363 | } 364 | 365 | function update(source) { 366 | // Compute the new height, function counts total children of root node and sets tree height accordingly. 367 | // This prevents the layout looking squashed when new nodes are made visible or looking sparse when nodes are removed 368 | // This makes the layout more consistent. 369 | var levelWidth = [1]; 370 | var childCount = function(level, n) { 371 | 372 | if (n.children && n.children.length > 0) { 373 | if (levelWidth.length <= level + 1) levelWidth.push(0); 374 | 375 | levelWidth[level + 1] += n.children.length; 376 | n.children.forEach(function(d) { 377 | childCount(level + 1, d); 378 | }); 379 | } 380 | }; 381 | childCount(0, root); 382 | var newHeight = d3.max(levelWidth) * 25; // 25 pixels per line 383 | tree = tree.size([newHeight, viewerWidth]); 384 | 385 | // Compute the new tree layout. 386 | var nodes = tree.nodes(root).reverse(), 387 | links = tree.links(nodes); 388 | 389 | // Set widths between levels based on maxLabelLength. 390 | nodes.forEach(function(d) { 391 | var labelLength = 0; 392 | for (var j = 0; j <= d.depth; j++) { 393 | labelLength += maxLabelLength[j]; 394 | } 395 | d.y = labelLength * 10; //maxLabelLength * 10px 396 | // alternatively to keep a fixed scale one can set a fixed depth per level 397 | // Normalize for fixed-depth by commenting out below line 398 | // d.y = (d.depth * 500); //500px per level. 399 | }); 400 | 401 | // Update the nodes… 402 | node = svgGroup.selectAll("g.node") 403 | .data(nodes, function(d) { 404 | return d.id || (d.id = ++i); 405 | }); 406 | 407 | // Enter any new nodes at the parent's previous position. 408 | var nodeEnter = node.enter().append("g") 409 | .call(dragListener) 410 | .attr("class", "node") 411 | .attr("transform", function(d) { 412 | return "translate(" + source.y0 + "," + source.x0 + ")"; 413 | }) 414 | .on('click', click) 415 | .append("a") 416 | .attr("xlink:href", function(d) { 417 | return d.url || d.github; 418 | }) 419 | .attr("target", "_blank"); 420 | 421 | nodeEnter.append("circle") 422 | .attr('class', 'nodeCircle') 423 | .attr("r", 0) 424 | .style("fill", function(d) { 425 | return d._children ? "lightsteelblue" : "#fff"; 426 | }); 427 | 428 | nodeEnter.append("text") 429 | .attr("x", function(d) { 430 | return d.children || d._children ? -10 : 10; 431 | }) 432 | .attr("dy", ".35em") 433 | .attr('class', 'nodeText') 434 | .attr("text-anchor", function(d) { 435 | return d.children || d._children ? "end" : "start"; 436 | }) 437 | .text(function(d) { 438 | return parseName(d); 439 | }) 440 | .style("fill-opacity", 0); 441 | 442 | // phantom node to give us mouseover in a radius around it 443 | nodeEnter.append("circle") 444 | .attr('class', 'ghostCircle') 445 | .attr("r", 30) 446 | .attr("opacity", 0.2) // change this to zero to hide the target area 447 | .style("fill", "red") 448 | .attr('pointer-events', 'mouseover') 449 | .on("mouseover", function(node) { 450 | overCircle(node); 451 | }) 452 | .on("mouseout", function(node) { 453 | outCircle(node); 454 | }); 455 | 456 | // Update the text to reflect whether node has children or not. 457 | node.select('text') 458 | .attr("x", function(d) { 459 | return d.children || d._children ? -10 : 10; 460 | }) 461 | .attr("text-anchor", function(d) { 462 | return d.children || d._children ? "end" : "start"; 463 | }) 464 | .text(function(d) { 465 | return parseName(d); 466 | }); 467 | 468 | // Change the circle fill depending on whether it has children and is collapsed 469 | node.select("circle.nodeCircle") 470 | .attr("r", 4.5) 471 | .style("fill", function(d) { 472 | return d._children ? "lightsteelblue" : "#fff"; 473 | }); 474 | 475 | // Transition nodes to their new position. 476 | var nodeUpdate = node.transition() 477 | .duration(duration) 478 | .attr("transform", function(d) { 479 | return "translate(" + d.y + "," + d.x + ")"; 480 | }); 481 | 482 | // Fade the text in 483 | nodeUpdate.select("text") 484 | .style("fill-opacity", 1); 485 | 486 | // Transition exiting nodes to the parent's new position. 487 | var nodeExit = node.exit().transition() 488 | .duration(duration) 489 | .attr("transform", function(d) { 490 | return "translate(" + source.y + "," + source.x + ")"; 491 | }) 492 | .remove(); 493 | 494 | nodeExit.select("circle") 495 | .attr("r", 0); 496 | 497 | nodeExit.select("text") 498 | .style("fill-opacity", 0); 499 | 500 | // Update the links… 501 | var link = svgGroup.selectAll("path.link") 502 | .data(links, function(d) { 503 | return d.target.id; 504 | }); 505 | 506 | // Enter any new links at the parent's previous position. 507 | link.enter().insert("path", "g") 508 | .attr("class", "link") 509 | .attr("d", function(d) { 510 | var o = { 511 | x: source.x0, 512 | y: source.y0 513 | }; 514 | return diagonal({ 515 | source: o, 516 | target: o 517 | }); 518 | }); 519 | 520 | // Transition links to their new position. 521 | link.transition() 522 | .duration(duration) 523 | .attr("d", diagonal); 524 | 525 | // Transition exiting nodes to the parent's new position. 526 | link.exit().transition() 527 | .duration(duration) 528 | .attr("d", function(d) { 529 | var o = { 530 | x: source.x, 531 | y: source.y 532 | }; 533 | return diagonal({ 534 | source: o, 535 | target: o 536 | }); 537 | }) 538 | .remove(); 539 | 540 | // Stash the old positions for transition. 541 | nodes.forEach(function(d) { 542 | d.x0 = d.x; 543 | d.y0 = d.y; 544 | }); 545 | } 546 | 547 | // Append a group which holds all nodes and which the zoom Listener can act upon. 548 | var svgGroup = baseSvg.append("g"); 549 | 550 | // Define the root 551 | root = treeData; 552 | root.x0 = viewerHeight / 2; 553 | root.y0 = 0; 554 | update(root); 555 | 556 | // Layout the tree initially and center on the root node. 557 | if (isPhantom) { 558 | zoomListener.scale(1.25); 559 | leftNode(root); 560 | } else { 561 | zoomListener.scale(0.25); 562 | centerNode(root); 563 | } 564 | 565 | // 566 | }); 567 | 568 | })(); 569 | --------------------------------------------------------------------------------