├── .gitattributes
├── .gitignore
├── Checks
├── App.config
├── Checks.csproj
├── Program.cs
└── Properties
│ └── AssemblyInfo.cs
├── InstallerScriptGenerator
├── App.config
├── BO
│ ├── InstallerScriptableClrMethod.cs
│ ├── InstallerScriptableItem.cs
│ ├── InstallerScriptableSqlAssembly.cs
│ ├── InstallerScriptableSqlFunction.cs
│ ├── InstallerScriptableSqlProcedure.cs
│ └── SqlParameter.cs
├── InstallerScriptGenerator.csproj
├── Program.cs
├── Properties
│ └── AssemblyInfo.cs
├── TemplateParser.cs
└── Utils
│ └── ClrSqlTermsConverter.cs
├── README.md
├── RediSQLCache.sln
├── RedisSqlCache
├── Common
│ └── DateTimeUtils.cs
├── Deployment
│ ├── BasicUsageSamples.sql
│ ├── Install.Sql
│ ├── LICENSE.txt
│ ├── Readme.txt
│ └── Uninstall.sql
├── Properties
│ └── AssemblyInfo.cs
├── RediSql.csproj
├── RedisSharp
│ └── RedisSharp.cs
├── Scripts
│ ├── DeploymentScriptsGenerator.ps1
│ ├── InstallerTemplate.txt
│ ├── SanityTest.sql
│ ├── UninstallTemplate.txt
│ └── Usage.sql
├── SqlClrComponents
│ ├── Common
│ │ └── RedisConnection.cs
│ ├── Enums.cs
│ ├── RedisqlGlobalServerFunctions.cs
│ ├── RedisqlKeysManipulationFunctions.cs
│ ├── RedisqlLists.cs
│ ├── RedisqlRowsets.cs
│ └── RedisqlStringValuesFunctions.cs
└── TSQLCode
│ ├── GetSetStoredRowset.sql
│ ├── GetStoredRowset.sql
│ └── XmlToRowset.sql
├── ScriptGenerator
├── InstallerScriptGenerator.exe
├── InstallerScriptGenerator.exe.config
├── InstallerScriptGenerator.vshost.exe
├── InstallerScriptGenerator.vshost.exe.config
├── InstallerScriptGenerator.vshost.exe.manifest
└── SqlClrDeclarations.dll
└── SqlClrDeclarations
├── Attributes
├── ExportedFunctionAttribute.cs
├── SqlInstallerScriptGeneratorExportedAttributeBase.cs
├── SqlInstallerScriptGeneratorExportedProcedure.cs
└── SqlParameterAttribute.cs
├── Properties
└── AssemblyInfo.cs
└── SqlClrDeclarations.csproj
/.gitattributes:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Set default behavior to automatically normalize line endings.
3 | ###############################################################################
4 | * text=auto
5 |
6 | ###############################################################################
7 | # Set default behavior for command prompt diff.
8 | #
9 | # This is need for earlier builds of msysgit that does not have it on by
10 | # default for csharp files.
11 | # Note: This is only used by command line
12 | ###############################################################################
13 | #*.cs diff=csharp
14 |
15 | ###############################################################################
16 | # Set the merge driver for project and solution files
17 | #
18 | # Merging from the command prompt will add diff markers to the files if there
19 | # are conflicts (Merging from VS is not affected by the settings below, in VS
20 | # the diff markers are never inserted). Diff markers may cause the following
21 | # file extensions to fail to load in VS. An alternative would be to treat
22 | # these files as binary and thus will always conflict and require user
23 | # intervention with every merge. To do so, just uncomment the entries below
24 | ###############################################################################
25 | #*.sln merge=binary
26 | #*.csproj merge=binary
27 | #*.vbproj merge=binary
28 | #*.vcxproj merge=binary
29 | #*.vcproj merge=binary
30 | #*.dbproj merge=binary
31 | #*.fsproj merge=binary
32 | #*.lsproj merge=binary
33 | #*.wixproj merge=binary
34 | #*.modelproj merge=binary
35 | #*.sqlproj merge=binary
36 | #*.wwaproj merge=binary
37 |
38 | ###############################################################################
39 | # behavior for image files
40 | #
41 | # image files are treated as binary by default.
42 | ###############################################################################
43 | #*.jpg binary
44 | #*.png binary
45 | #*.gif binary
46 |
47 | ###############################################################################
48 | # diff behavior for common document formats
49 | #
50 | # Convert binary document formats to text before diffing them. This feature
51 | # is only available from the command line. Turn it on by uncommenting the
52 | # entries below.
53 | ###############################################################################
54 | #*.doc diff=astextplain
55 | #*.DOC diff=astextplain
56 | #*.docx diff=astextplain
57 | #*.DOCX diff=astextplain
58 | #*.dot diff=astextplain
59 | #*.DOT diff=astextplain
60 | #*.pdf diff=astextplain
61 | #*.PDF diff=astextplain
62 | #*.rtf diff=astextplain
63 | #*.RTF diff=astextplain
64 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 |
4 | # User-specific files
5 | *.suo
6 | *.user
7 | *.userosscache
8 | *.sln.docstates
9 |
10 | # User-specific files (MonoDevelop/Xamarin Studio)
11 | *.userprefs
12 |
13 | # Build results
14 | [Dd]ebug/
15 | [Dd]ebugPublic/
16 | [Rr]elease/
17 | [Rr]eleases/
18 | x64/
19 | x86/
20 | build/
21 | bld/
22 | [Bb]in/
23 | [Oo]bj/
24 |
25 | # Visual Studio 2015 cache/options directory
26 | .vs/
27 |
28 | # MSTest test Results
29 | [Tt]est[Rr]esult*/
30 | [Bb]uild[Ll]og.*
31 |
32 | # NUNIT
33 | *.VisualState.xml
34 | TestResult.xml
35 |
36 | # Build Results of an ATL Project
37 | [Dd]ebugPS/
38 | [Rr]eleasePS/
39 | dlldata.c
40 |
41 | # DNX
42 | project.lock.json
43 | artifacts/
44 |
45 | *_i.c
46 | *_p.c
47 | *_i.h
48 | *.ilk
49 | *.meta
50 | *.obj
51 | *.pch
52 | *.pdb
53 | *.pgc
54 | *.pgd
55 | *.rsp
56 | *.sbr
57 | *.tlb
58 | *.tli
59 | *.tlh
60 | *.tmp
61 | *.tmp_proj
62 | *.log
63 | *.vspscc
64 | *.vssscc
65 | .builds
66 | *.pidb
67 | *.svclog
68 | *.scc
69 |
70 | # Chutzpah Test files
71 | _Chutzpah*
72 |
73 | # Visual C++ cache files
74 | ipch/
75 | *.aps
76 | *.ncb
77 | *.opensdf
78 | *.sdf
79 | *.cachefile
80 |
81 | # Visual Studio profiler
82 | *.psess
83 | *.vsp
84 | *.vspx
85 |
86 | # TFS 2012 Local Workspace
87 | $tf/
88 |
89 | # Guidance Automation Toolkit
90 | *.gpState
91 |
92 | # ReSharper is a .NET coding add-in
93 | _ReSharper*/
94 | *.[Rr]e[Ss]harper
95 | *.DotSettings.user
96 |
97 | # JustCode is a .NET coding add-in
98 | .JustCode
99 |
100 | # TeamCity is a build add-in
101 | _TeamCity*
102 |
103 | # DotCover is a Code Coverage Tool
104 | *.dotCover
105 |
106 | # NCrunch
107 | _NCrunch_*
108 | .*crunch*.local.xml
109 |
110 | # MightyMoose
111 | *.mm.*
112 | AutoTest.Net/
113 |
114 | # Web workbench (sass)
115 | .sass-cache/
116 |
117 | # Installshield output folder
118 | [Ee]xpress/
119 |
120 | # DocProject is a documentation generator add-in
121 | DocProject/buildhelp/
122 | DocProject/Help/*.HxT
123 | DocProject/Help/*.HxC
124 | DocProject/Help/*.hhc
125 | DocProject/Help/*.hhk
126 | DocProject/Help/*.hhp
127 | DocProject/Help/Html2
128 | DocProject/Help/html
129 |
130 | # Click-Once directory
131 | publish/
132 |
133 | # Publish Web Output
134 | *.[Pp]ublish.xml
135 | *.azurePubxml
136 | ## TODO: Comment the next line if you want to checkin your
137 | ## web deploy settings but do note that will include unencrypted
138 | ## passwords
139 | #*.pubxml
140 |
141 | *.publishproj
142 |
143 | # NuGet Packages
144 | *.nupkg
145 | # The packages folder can be ignored because of Package Restore
146 | **/packages/*
147 | # except build/, which is used as an MSBuild target.
148 | !**/packages/build/
149 | # Uncomment if necessary however generally it will be regenerated when needed
150 | #!**/packages/repositories.config
151 |
152 | # Windows Azure Build Output
153 | csx/
154 | *.build.csdef
155 |
156 | # Windows Store app package directory
157 | AppPackages/
158 |
159 | # Visual Studio cache files
160 | # files ending in .cache can be ignored
161 | *.[Cc]ache
162 | # but keep track of directories ending in .cache
163 | !*.[Cc]ache/
164 |
165 | # Others
166 | ClientBin/
167 | [Ss]tyle[Cc]op.*
168 | ~$*
169 | *~
170 | *.dbmdl
171 | *.dbproj.schemaview
172 | *.pfx
173 | *.publishsettings
174 | node_modules/
175 | orleans.codegen.cs
176 |
177 | # RIA/Silverlight projects
178 | Generated_Code/
179 |
180 | # Backup & report files from converting an old project file
181 | # to a newer Visual Studio version. Backup files are not needed,
182 | # because we have git ;-)
183 | _UpgradeReport_Files/
184 | Backup*/
185 | UpgradeLog*.XML
186 | UpgradeLog*.htm
187 |
188 | # SQL Server files
189 | *.mdf
190 | *.ldf
191 |
192 | # Business Intelligence projects
193 | *.rdl.data
194 | *.bim.layout
195 | *.bim_*.settings
196 |
197 | # Microsoft Fakes
198 | FakesAssemblies/
199 |
200 | # Node.js Tools for Visual Studio
201 | .ntvs_analysis.dat
202 |
203 | # Visual Studio 6 build log
204 | *.plg
205 |
206 | # Visual Studio 6 workspace options file
207 | *.opt
208 |
209 | # LightSwitch generated files
210 | GeneratedArtifacts/
211 | _Pvt_Extensions/
212 | ModelManifest.xml
213 |
--------------------------------------------------------------------------------
/Checks/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/Checks/Checks.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {A726DF9E-E4F2-470E-8E4D-B8A760D80653}
8 | Exe
9 | Properties
10 | Checks
11 | Checks
12 | v4.6
13 | 512
14 | true
15 |
16 |
17 | AnyCPU
18 | true
19 | full
20 | false
21 | bin\Debug\
22 | DEBUG;TRACE
23 | prompt
24 | 4
25 |
26 |
27 | AnyCPU
28 | pdbonly
29 | true
30 | bin\Release\
31 | TRACE
32 | prompt
33 | 4
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 | {666fe4b7-0a6b-44df-b179-c394234e33de}
55 | RediSql
56 |
57 |
58 |
59 |
66 |
--------------------------------------------------------------------------------
/Checks/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using RediSql.SqlClrComponents;
7 |
8 | namespace Checks
9 | {
10 | class Program
11 | {
12 | static void Main(string[] args)
13 | {
14 | var a = RedisqlLists.GetListItems("localhost", 6379, null, null, "Sdgsdg", 0 , -1);
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/Checks/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("Checks")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("Checks")]
13 | [assembly: AssemblyCopyright("Copyright © 2015")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("a726df9e-e4f2-470e-8e4d-b8a760d80653")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/InstallerScriptGenerator/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/InstallerScriptGenerator/BO/InstallerScriptableClrMethod.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Reflection;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 |
8 | namespace InstallerScriptGenerator.BO
9 | {
10 | internal abstract class InstallerScriptableClrMethod : InstallerScriptableItem
11 | {
12 | protected Type ContainedType { get; set; }
13 | protected MethodInfo Method { get; set; }
14 | internal InstallerScriptableClrMethod(string name, string schemaName, InstallerScriptableSqlAssembly sqlAssembly, Type containedType, MethodInfo method)
15 | {
16 | Name = name;
17 | SchemaName = schemaName;
18 | ContainedType = containedType;
19 | Method = method;
20 | SqlAssembly = sqlAssembly;
21 | }
22 |
23 |
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/InstallerScriptGenerator/BO/InstallerScriptableItem.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Reflection;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using SqlClrDeclarations.Attributes;
8 |
9 | namespace InstallerScriptGenerator.BO
10 | {
11 | internal abstract class InstallerScriptableItem
12 | {
13 | internal string SchemaName { get; set; }
14 | internal string Name { get; set; }
15 | public InstallerScriptableSqlAssembly SqlAssembly { get; set; }
16 |
17 | internal abstract string GenerateInstallScript();
18 | internal abstract string GenerateUninstallScript();
19 |
20 | internal static InstallerScriptableItem GetScreiptableItem(
21 | SqlInstallerScriptGeneratorExportedAttributeBase attributeInfo, InstallerScriptableSqlAssembly sqlAssembly,
22 | MemberInfo declaredItem)
23 | {
24 | InstallerScriptableItem item = null;
25 | if (attributeInfo is SqlInstallerScriptGeneratorExportedFunction && declaredItem is MethodInfo)
26 | {
27 | item = new InstallerScriptableSqlFunction(attributeInfo.Name, attributeInfo.SchemaName, sqlAssembly,
28 | (MethodInfo)declaredItem);
29 | }
30 | if (attributeInfo is SqlInstallerScriptGeneratorExportedProcedure && declaredItem is MethodInfo)
31 | {
32 | item = new InstallerScriptableSqlProcedure(attributeInfo.Name, attributeInfo.SchemaName, sqlAssembly,
33 | (MethodInfo)declaredItem);
34 | }
35 | if (item == null)
36 | throw new ArgumentOutOfRangeException(nameof(attributeInfo), "unexpected type of attribute");
37 | return item;
38 | }
39 | }
40 | }
--------------------------------------------------------------------------------
/InstallerScriptGenerator/BO/InstallerScriptableSqlAssembly.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Reflection;
6 | using System.Text;
7 | using System.Threading.Tasks;
8 | using SqlClrDeclarations.Attributes;
9 |
10 | namespace InstallerScriptGenerator.BO
11 | {
12 | internal class InstallerScriptableSqlAssembly : InstallerScriptableItem
13 | {
14 | internal Assembly Assembly { get; set; }
15 | internal string Path { get; set; }
16 |
17 | public InstallerScriptableSqlAssembly(Assembly assembly)
18 | {
19 | var assemblyAttribute = assembly.GetCustomAttribute();
20 | Name = assemblyAttribute.Title;
21 | Path = assembly.Location;
22 | Assembly = assembly;
23 | }
24 |
25 | internal override string GenerateInstallScript()
26 | {
27 | string template = @"
28 | CREATE ASSEMBLY [$$$name$$$]
29 | AUTHORIZATION [dbo]
30 | FROM 0x$$$bits$$$
31 | WITH PERMISSION_SET = UNSAFE
32 | ";
33 | return template.Replace("$$$bits$$$", BitConverter.ToString(File.ReadAllBytes(Path)).Replace("-", string.Empty)).Replace("$$$name$$$", Name);
34 | }
35 |
36 | internal override string GenerateUninstallScript()
37 | {
38 | return $"DROP ASSEMBLY [{Name}]";
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/InstallerScriptGenerator/BO/InstallerScriptableSqlFunction.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Reflection;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using Microsoft.SqlServer.Server;
8 | using SqlClrDeclarations.Attributes;
9 |
10 | namespace InstallerScriptGenerator.BO
11 | {
12 | internal class InstallerScriptableSqlFunction : InstallerScriptableClrMethod
13 | {
14 | private readonly SqlInstallerScriptGeneratorExportedFunction _exportedFunctionAttribute;
15 | private readonly SqlFunctionAttribute _sqlFunctionAttribute;
16 | public InstallerScriptableSqlFunction(string name, string schemaName, InstallerScriptableSqlAssembly sqlSqlAssembly, MethodInfo method) : base(name, schemaName, sqlSqlAssembly, method.DeclaringType, method)
17 | {
18 | _exportedFunctionAttribute = method.GetCustomAttribute();
19 | _sqlFunctionAttribute = method.GetCustomAttribute();
20 | }
21 |
22 | internal override string GenerateInstallScript()
23 | {
24 | StringBuilder sb = new StringBuilder(@"
25 | GO
26 | CREATE FUNCTION $$$SchemaName$$$.$$$SqlFunctionName$$$($$$ParametersList$$$)
27 | RETURNS $$$SqlReturnValueType$$$
28 | AS EXTERNAL NAME[$$$SqlAssemblyName$$$].[$$$FullClrTypeName$$$].[$$$MethodName$$$]
29 | GO
30 | ");
31 | sb.Replace("$$$SchemaName$$$", SchemaName);
32 | sb.Replace("$$$SqlFunctionName$$$", Name);
33 | sb.Replace("$$$ParametersList$$$", SqlParameter.GenerateSqlParameterString(Method.GetParameters()));
34 | sb.Replace("$$$SqlReturnValueType$$$", GetSqlReturnValueType());
35 | sb.Replace("$$$SqlAssemblyName$$$", SqlAssembly.Name);
36 | sb.Replace("$$$FullClrTypeName$$$", ContainedType.FullName);
37 | sb.Replace("$$$MethodName$$$", Method.Name);
38 | return sb.ToString();
39 | }
40 |
41 | private string GetSqlReturnValueType()
42 | {
43 | if (!string.IsNullOrEmpty(_sqlFunctionAttribute.TableDefinition))
44 | return $"table({_sqlFunctionAttribute.TableDefinition})";
45 | if (!string.IsNullOrEmpty(_exportedFunctionAttribute.SqlReturnType))
46 | return _exportedFunctionAttribute.SqlReturnType;
47 | return Utils.ClrSqlTermsConverter.ConvertClrTypeToSqlTypeName(Method.ReturnType);
48 | }
49 |
50 |
51 |
52 | internal override string GenerateUninstallScript()
53 | {
54 | return $"DROP FUNCTION {SchemaName}.{Name}";
55 | }
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/InstallerScriptGenerator/BO/InstallerScriptableSqlProcedure.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Reflection;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using Microsoft.SqlServer.Server;
8 | using SqlClrDeclarations.Attributes;
9 |
10 | namespace InstallerScriptGenerator.BO
11 | {
12 | internal class InstallerScriptableSqlProcedure : InstallerScriptableClrMethod
13 | {
14 | private readonly SqlInstallerScriptGeneratorExportedProcedure _exportedProcedureAttribute;
15 | private readonly SqlProcedureAttribute _sqlProcedureAttribute;
16 | public InstallerScriptableSqlProcedure(string name, string schemaName, InstallerScriptableSqlAssembly sqlSqlAssembly, MethodInfo method) : base(name, schemaName, sqlSqlAssembly, method.DeclaringType, method)
17 | {
18 | _exportedProcedureAttribute = method.GetCustomAttribute();
19 | _sqlProcedureAttribute = method.GetCustomAttribute();
20 | }
21 |
22 | internal override string GenerateInstallScript()
23 | {
24 | StringBuilder sb = new StringBuilder(@"
25 | GO
26 | CREATE PROCEDURE $$$SchemaName$$$.$$$SqlProcedureName$$$($$$ParametersList$$$)
27 | AS EXTERNAL NAME[$$$SqlAssemblyName$$$].[$$$FullClrTypeName$$$].[$$$MethodName$$$]
28 | GO
29 | ");
30 | sb.Replace("$$$SchemaName$$$", SchemaName);
31 | sb.Replace("$$$SqlProcedureName$$$", Name);
32 | sb.Replace("$$$ParametersList$$$", SqlParameter.GenerateSqlParameterString(Method.GetParameters()));
33 | sb.Replace("$$$SqlAssemblyName$$$", SqlAssembly.Name);
34 | sb.Replace("$$$FullClrTypeName$$$", ContainedType.FullName);
35 | sb.Replace("$$$MethodName$$$", Method.Name);
36 | return sb.ToString();
37 | }
38 |
39 |
40 | internal override string GenerateUninstallScript()
41 | {
42 | return $"DROP PROCEDURE {SchemaName}.{Name}";
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/InstallerScriptGenerator/BO/SqlParameter.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Reflection;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using SqlClrDeclarations.Attributes;
8 |
9 | namespace InstallerScriptGenerator.BO
10 | {
11 | internal class SqlParameter
12 | {
13 | internal string Name { get; set; }
14 | internal object DefaultValue { get; set; }
15 |
16 | internal string SqlDefaultValue
17 | {
18 | get
19 | {
20 | if (DefaultValue == null) return null;
21 | if (DefaultValue == DBNull.Value) return "null";
22 | if (DefaultValue == typeof(DBNull)) return "null";
23 | if (SqlType == Utils.ClrSqlTermsConverter.ConvertClrTypeToSqlTypeName(typeof(string))) return "'" + DefaultValue + "'";
24 | return DefaultValue.ToString();
25 | }
26 | }
27 | internal string SqlType { get; set; }
28 | internal SqlParameter(ParameterInfo parameter)
29 | {
30 | if (parameter.IsDefined(typeof(SqlParameterAttribute)))
31 | {
32 | var attribute = (SqlParameterAttribute)parameter.GetCustomAttribute(typeof(SqlParameterAttribute));
33 | Name = !string.IsNullOrEmpty(attribute.Name) ? attribute.Name : parameter.Name;
34 | SqlType = !string.IsNullOrEmpty(attribute.SqlType)
35 | ? attribute.SqlType
36 | : Utils.ClrSqlTermsConverter.ConvertClrTypeToSqlTypeName(parameter.ParameterType);
37 | DefaultValue = attribute.DefaultValue;
38 | if (DefaultValue is bool)
39 | DefaultValue = (bool)attribute.DefaultValue ? 0 : 1;
40 |
41 | }
42 | else
43 | {
44 | DefaultValue = null;
45 | Name = parameter.Name;
46 | SqlType = Utils.ClrSqlTermsConverter.ConvertClrTypeToSqlTypeName(parameter.ParameterType);
47 | }
48 | }
49 |
50 | internal static string GenerateSqlParameterString(ParameterInfo[] parameters)
51 | {
52 | return string.Join(", ", parameters.Select(param =>
53 | {
54 | var paramInfo = new SqlParameter(param);
55 | string singleParam = $"@{paramInfo.Name} {paramInfo.SqlType}";
56 | if (paramInfo.SqlDefaultValue != null)
57 | singleParam += $"={paramInfo.SqlDefaultValue}";
58 | return singleParam;
59 | }));
60 | }
61 |
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/InstallerScriptGenerator/InstallerScriptGenerator.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {CABBBA96-75AF-4F10-96AB-72B814B5A97E}
8 | Exe
9 | Properties
10 | InstallerScriptGenerator
11 | InstallerScriptGenerator
12 | v4.6
13 | 512
14 | true
15 |
16 |
17 |
18 | AnyCPU
19 | true
20 | full
21 | false
22 | bin\Debug\
23 | DEBUG;TRACE
24 | prompt
25 | 4
26 | false
27 |
28 |
29 | AnyCPU
30 | pdbonly
31 | true
32 | ..\ScriptGenerator\
33 | TRACE
34 | prompt
35 | 4
36 | false
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 | {56c24720-8053-4cf5-8bf8-bae7dba78424}
66 | SqlClrDeclarations
67 |
68 |
69 |
70 |
77 |
--------------------------------------------------------------------------------
/InstallerScriptGenerator/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Reflection;
6 | using System.Text;
7 | using System.Threading.Tasks;
8 | using InstallerScriptGenerator.BO;
9 | using Microsoft.SqlServer.Server;
10 | using SqlClrDeclarations.Attributes;
11 | using SqlClrDeclarations.Attributes;
12 |
13 | namespace InstallerScriptGenerator
14 | {
15 | class Program
16 | {
17 | static void Main(string[] args)
18 | {
19 | string templateFile = args[0];
20 | string outputFilePath = args[1];
21 | TemplateParser parser = new TemplateParser(templateFile);
22 | string result = parser.ParseTemplate();
23 | File.WriteAllText(outputFilePath, result);
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/InstallerScriptGenerator/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("InstallerScriptGenerator")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("InstallerScriptGenerator")]
13 | [assembly: AssemblyCopyright("Copyright © 2015")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("cabbba96-75af-4f10-96ab-72b814b5a97e")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/InstallerScriptGenerator/TemplateParser.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Reflection;
6 | using System.Runtime.InteropServices;
7 | using System.Text;
8 | using System.Threading.Tasks;
9 | using InstallerScriptGenerator.BO;
10 | using SqlClrDeclarations.Attributes;
11 |
12 | namespace InstallerScriptGenerator
13 | {
14 | public class TemplateParser
15 | {
16 | private FileInfo _templateFile;
17 |
18 | public TemplateParser(string filePath)
19 | {
20 | _templateFile = new FileInfo(filePath);
21 | }
22 |
23 | public string ParseTemplate()
24 | {
25 | StringBuilder sb = new StringBuilder((int)_templateFile.Length);
26 | using (var reader = _templateFile.OpenText())
27 | {
28 | while (!reader.EndOfStream)
29 | {
30 | string line = reader.ReadLine();
31 | if (line == null) break;
32 | var installScriptMagic = "~~~InstallScript:~~~";
33 | var uninstallScriptMagic = "~~~UninstallScript:~~~";
34 | var includeFileMagic = "~~~IncludeFile:~~~";
35 | if (line.StartsWith(installScriptMagic))
36 | {
37 | string assemblyPath = line.Remove(0, installScriptMagic.Length);
38 | string installScript = GetInstallScriptText(assemblyPath);
39 | sb.AppendLine(installScript);
40 | }
41 | else if (line.StartsWith(uninstallScriptMagic))
42 | {
43 | string assemblyPath = line.Remove(0, uninstallScriptMagic.Length);
44 | string uninstallScript = GetUninstallScriptText(assemblyPath);
45 | sb.AppendLine(uninstallScript);
46 | }
47 | else if (line.StartsWith(includeFileMagic))
48 | {
49 | string filePath = line.Remove(0, includeFileMagic.Length);
50 | string fileToInclude = File.ReadAllText(filePath);
51 | sb.AppendLine(fileToInclude);
52 | }
53 | else
54 | {
55 | sb.AppendLine(line);
56 | }
57 | }
58 | }
59 | return sb.ToString();
60 | }
61 |
62 | private string GetUninstallScriptText(string assemeblyPath)
63 | {
64 | StringBuilder sb = new StringBuilder();
65 | var asm = Assembly.LoadFile(assemeblyPath);
66 |
67 | IterateScriptableItemsInsideAssembly(asm, item => sb.AppendLine(item.GenerateUninstallScript()));
68 | sb.AppendLine(new InstallerScriptableSqlAssembly(asm).GenerateUninstallScript());
69 | return sb.ToString();
70 | }
71 |
72 | private string GetInstallScriptText(string assemeblyPath)
73 | {
74 | StringBuilder sb = new StringBuilder();
75 | var asm = Assembly.LoadFile(assemeblyPath);
76 | sb.AppendLine(new InstallerScriptableSqlAssembly(asm).GenerateInstallScript());
77 | IterateScriptableItemsInsideAssembly(asm, item => sb.AppendLine(item.GenerateInstallScript()));
78 | return sb.ToString();
79 | }
80 |
81 | private void IterateScriptableItemsInsideAssembly(Assembly asm, Action action)
82 | {
83 | var sqlAssembly = new InstallerScriptableSqlAssembly(asm);
84 |
85 | foreach (var method in asm.GetTypes().SelectMany(k => k.GetMembers()).Where(k => k.GetCustomAttributes(false)
86 | .Any(l => l is SqlInstallerScriptGeneratorExportedAttributeBase))
87 | .OrderBy(k => k.Name))
88 | {
89 | var attribute = method.GetCustomAttribute();
90 | var scriptableItem = InstallerScriptableItem.GetScreiptableItem(attribute, sqlAssembly, method);
91 | action(scriptableItem);
92 |
93 | }
94 |
95 | }
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/InstallerScriptGenerator/Utils/ClrSqlTermsConverter.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace InstallerScriptGenerator.Utils
8 | {
9 | internal static class ClrSqlTermsConverter
10 | {
11 | internal static string ConvertClrTypeToSqlTypeName(Type t)
12 | {
13 | if (t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Nullable<>))
14 | t = t.GetGenericArguments()[0];
15 | if (t == typeof(int)) return "int";
16 | if (t == typeof(long)) return "bigint";
17 | if (t == typeof(short)) return "smallint";
18 | if (t == typeof(DateTime)) return "datetime2";
19 | if (t == typeof(TimeSpan)) return "time";
20 | if (t == typeof(string)) return "nvarchar(4000)";
21 | if (t == typeof(bool)) return "bit";
22 | throw new ArgumentOutOfRangeException("unknown type: " + t.FullName);
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # redisql
2 | RediSql is a Redis client for SQL Server (T-SQL)
3 | This is the repository, and can be very useful if you want to read RediSql's code.
4 |
5 | If you're looking for downloads, installation instructions etc. Plase refer to:
6 | http://redisql.ishahar.net
7 |
--------------------------------------------------------------------------------
/RediSQLCache.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 14
4 | VisualStudioVersion = 14.0.23107.0
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RediSql", "RedisSqlCache\RediSql.csproj", "{666FE4B7-0A6B-44DF-B179-C394234E33DE}"
7 | ProjectSection(ProjectDependencies) = postProject
8 | {CABBBA96-75AF-4F10-96AB-72B814B5A97E} = {CABBBA96-75AF-4F10-96AB-72B814B5A97E}
9 | EndProjectSection
10 | EndProject
11 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "InstallerScriptGenerator", "InstallerScriptGenerator\InstallerScriptGenerator.csproj", "{CABBBA96-75AF-4F10-96AB-72B814B5A97E}"
12 | EndProject
13 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SqlClrDeclarations", "SqlClrDeclarations\SqlClrDeclarations.csproj", "{56C24720-8053-4CF5-8BF8-BAE7DBA78424}"
14 | EndProject
15 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Checks", "Checks\Checks.csproj", "{A726DF9E-E4F2-470E-8E4D-B8A760D80653}"
16 | EndProject
17 | Global
18 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
19 | Debug|Any CPU = Debug|Any CPU
20 | Release|Any CPU = Release|Any CPU
21 | EndGlobalSection
22 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
23 | {666FE4B7-0A6B-44DF-B179-C394234E33DE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
24 | {666FE4B7-0A6B-44DF-B179-C394234E33DE}.Debug|Any CPU.Build.0 = Debug|Any CPU
25 | {666FE4B7-0A6B-44DF-B179-C394234E33DE}.Release|Any CPU.ActiveCfg = Release|Any CPU
26 | {666FE4B7-0A6B-44DF-B179-C394234E33DE}.Release|Any CPU.Build.0 = Release|Any CPU
27 | {CABBBA96-75AF-4F10-96AB-72B814B5A97E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
28 | {CABBBA96-75AF-4F10-96AB-72B814B5A97E}.Debug|Any CPU.Build.0 = Debug|Any CPU
29 | {CABBBA96-75AF-4F10-96AB-72B814B5A97E}.Release|Any CPU.ActiveCfg = Release|Any CPU
30 | {CABBBA96-75AF-4F10-96AB-72B814B5A97E}.Release|Any CPU.Build.0 = Release|Any CPU
31 | {56C24720-8053-4CF5-8BF8-BAE7DBA78424}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
32 | {56C24720-8053-4CF5-8BF8-BAE7DBA78424}.Debug|Any CPU.Build.0 = Debug|Any CPU
33 | {56C24720-8053-4CF5-8BF8-BAE7DBA78424}.Release|Any CPU.ActiveCfg = Release|Any CPU
34 | {56C24720-8053-4CF5-8BF8-BAE7DBA78424}.Release|Any CPU.Build.0 = Release|Any CPU
35 | {A726DF9E-E4F2-470E-8E4D-B8A760D80653}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
36 | {A726DF9E-E4F2-470E-8E4D-B8A760D80653}.Debug|Any CPU.Build.0 = Debug|Any CPU
37 | {A726DF9E-E4F2-470E-8E4D-B8A760D80653}.Release|Any CPU.ActiveCfg = Release|Any CPU
38 | {A726DF9E-E4F2-470E-8E4D-B8A760D80653}.Release|Any CPU.Build.0 = Release|Any CPU
39 | EndGlobalSection
40 | GlobalSection(SolutionProperties) = preSolution
41 | HideSolutionNode = FALSE
42 | EndGlobalSection
43 | EndGlobal
44 |
--------------------------------------------------------------------------------
/RedisSqlCache/Common/DateTimeUtils.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 |
5 | namespace RediSql.Common
6 | {
7 | public static class DateTimeUtils
8 | {
9 | private static readonly DateTime BaseLinuxTime = new DateTime(1970, 1, 1);
10 |
11 | public static double ToUnixTime(DateTime dt)
12 | {
13 | return (BaseLinuxTime - dt).TotalSeconds;
14 | }
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/RedisSqlCache/Deployment/BasicUsageSamples.sql:
--------------------------------------------------------------------------------
1 | -- This file includes some samples of using RediSql.
2 | -- For more samples, and full documentation, please visit http://redisql.ishahar.net
3 |
4 | --Get some server info
5 | SELECT * FROM [redisql].[GetServerInfo] (
6 | 'localhost' --Redis hosted locally
7 | ,default --default port
8 | ,default --no password
9 | ,default --dbid: 0
10 | )
11 | GO
12 |
13 | --Create string key without expiration
14 | EXEC [redisql].[SetStringValue]
15 | @host = N'localhost',
16 | @port = 6379,
17 | @key = 'SimpleStringKey',
18 | @value = N'sample_value'
19 |
20 | --We can check if the key exists now
21 | IF (SELECT [redisql].[IsKeyExists] ('localhost',default,default,default,'SimpleStringKey')) = 1
22 | BEGIN
23 | PRINT 'Key Exists!'
24 | END
25 |
26 | --We can add keys with expiration, in the following snippet - 10 minutes
27 | EXEC [redisql].[SetStringValue]
28 | @host = N'localhost',
29 | @port = 6379,
30 | @key = 'StringKeyWithTTL',
31 | @value = N'gv',
32 | @expiration = '00:10:00' --10 minutes expiration
33 |
34 | --Let's print the value of the key
35 | --if the key not exists we'll get NULL value
36 | SELECT [redisql].[GetStringValue] (
37 | 'localhost'
38 | ,default --default port
39 | ,default -- no password
40 | ,default -- dbid: 0
41 | ,'SimpleStringKey')
42 |
43 | --Delete 'SimpleStringKey' from Redis
44 | SELECT [redisql].[DeleteKey] (
45 | 'localhost'
46 | ,default --default port
47 | ,default -- no password
48 | ,default -- dbid: 0
49 | ,'SimpleStringKey')
50 |
51 |
52 | --If the key exists in Redis server, just return the value from the server (and extend expiration, if required).
53 | --If the key doesn't exists, store the key in Redis and return it.
54 | SELECT [redisql].[GetSetStringValue] (
55 | 'localhost'
56 | ,default --port
57 | ,default --pasword
58 | ,default --db
59 | ,'SampleStringKey5'
60 | ,'SampleValue'
61 | ,default --no expiration
62 | )
63 |
64 |
65 | --Get all keys from Redis.
66 | --not meant for production code, but mostly for debugging
67 | SELECT * FROM [redisql].[GetKeys] (
68 | 'localhost'
69 | ,default
70 | ,default
71 | ,default
72 | ,'*' -- get all keys, no filter
73 | )
74 |
75 | --Get all keys from Redis that contains "String" in the key name.
76 | --not meant for production code, but mostly for debugging
77 | SELECT * FROM [redisql].[GetKeys] (
78 | 'localhost'
79 | ,default
80 | ,default
81 | ,default
82 | ,'*String*'
83 | )
84 |
85 | --Commit all changes to Redis, by producing point-in-time snapshot
86 | --For further information about persistency in Redis please refer to:
87 | --http://redis.io/topics/persistence
88 | EXEC [redisql].[SaveChanges]
89 | @host = 'localhost'
90 |
91 | --store the result of the query in Redis
92 | EXEC [redisql].StoreQueryResultsData
93 | @host = N'localhost',
94 | @port = 6379,
95 | @key = 'RowsetKey1',
96 | @query = N'SELECT * FROM INFORMATION_SCHEMA.ROUTINES',
97 | @replaceExisting = 1
98 |
99 | --store the result of the query in Redis, but with 50 seconds expiration
100 | EXEC [redisql].StoreQueryResultsData
101 | @host = N'localhost',
102 | @port = 6379,
103 | @key = 'RowsetKey7',
104 | @query = N'SELECT * FROM INFORMATION_SCHEMA.ROUTINES',
105 | @replaceExisting = 1,
106 | @expiration = '00:00:50'
107 |
108 |
109 | --Get the results of the query we stored before
110 | --If key not exists, return null
111 | DECLARE @result int
112 | EXEC @result = [redisql].[GetStoredRowset]
113 | @host = N'localhost',
114 | @key ='RowsetKey1'
115 | PRINT @result --if result >= 0: there was a key that name, with rows, and result is the number of the rows stored.
116 | --if result == -1, key not exists
117 |
118 | --If the key exists in Redis, return the stored rowset
119 | --If the key doesn't exists, run the query, return the results and also store them in Redis
120 | DECLARE @result int
121 | EXEC @result= [redisql].GetSetStoredRowset
122 | @host = N'localhost',
123 | @port = 6379,
124 | @key = 'RowsetKey9',
125 | @query = N'SELECT * FROM INFORMATION_SCHEMA.ROUTINES'
126 |
127 | PRINT @result --if result >= 0: there was a key that name, with rows, and result is the number of the rows stored.
128 | --if result == -1, key not exists and the query executed against SQL Server
--------------------------------------------------------------------------------
/RedisSqlCache/Deployment/Install.Sql:
--------------------------------------------------------------------------------
1 | --RediSql - Redis client for T-SQL
2 | --For installation instructions and other information, please visit http://redisql.ishahar.net
3 |
4 | --REMEMBER: make sure you run this query on the correct database!
5 |
6 | DECLARE @dbName nvarchar(50) = '[check1]' --CHANGE HERE TO YOUR DB NAME
7 |
8 | EXEC('ALTER DATABASE ' + @dbname + ' SET TRUSTWORTHY ON')
9 |
10 |
11 | GO
12 | CREATE SCHEMA [redisql] AUTHORIZATION [dbo]
13 | GO
14 |
15 | CREATE ASSEMBLY [SqlClrDeclarations]
16 | AUTHORIZATION [dbo]
17 | FROM 0x4D5A90000300000004000000FFFF0000B800000000000000400000000000000000000000000000000000000000000000000000000000000000000000800000000E1FBA0E00B409CD21B8014CCD21546869732070726F6772616D2063616E6E6F742062652072756E20696E20444F53206D6F64652E0D0D0A2400000000000000504500004C010300920141560000000000000000E00022200B013000000E000000060000000000001E2C0000002000000040000000000010002000000002000004000000000000000400000000000000008000000002000000000000030040850000100000100000000010000010000000000000100000000000000000000000CB2B00004F00000000400000C803000000000000000000000000000000000000006000000C000000482B00001C0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000080000000000000000000000082000004800000000000000000000002E74657874000000240C000000200000000E000000020000000000000000000000000000200000602E72737263000000C8030000004000000004000000100000000000000000000000000000400000402E72656C6F6300000C0000000060000000020000001400000000000000000000000000004000004200000000000000000000000000000000FF2B0000000000004800000002000500D4200000740A000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001E027B010000042A2202037D010000042A5602280800000602032807000006020428050000062A1E027B020000042A2202037D020000042A1E027B030000042A2202037D030000042A1E02281100000A2A1E027B040000042A2202037D040000042A1E027B050000042A2202037D050000042A1E027B060000042A2202037D060000042A42534A4201000100000000000C00000076342E302E33303331390000000005006C00000030040000237E00009C0400007C04000023537472696E6773000000001809000004000000235553001C0900001000000023475549440000002C0900004801000023426C6F6200000000000000020000015715A0010900000000FA01330016000001000000140000000500000006000000100000000A000000110000002300000003000000060000000C000000010000000100000000006D030100000000000600A002010406000D0301040600BE01CF030F00210400000600E6018B0306006D028B0306004E028B030600F4028B030600C0028B030600D9028B030600FD018B030600D201E20306009801E203060031028B030600180253030600610484030600A601840306007D0101040600210384030600720484030000000001000000000001000100010010009D0330040C0001000100010010004C0130044D0002000400010010001F0130040C0004000900010010008A0230044D0004000A0001005E00290001002900290001001300290001007D002C000100130029000100450029005020000000008608FB002F00010058200000000086080D01100001006120000000008618C903330002007720000000008608AD002F0004007F20000000008608BC001000040088200000000086089B002F0005009020000000008608A400100005009920000000008618C903060006006120000000008618C90333000600A1200000000086082B0339000800A9200000000086083C033D000800B2200000000086089B002F000900BA20000000008608A40010000900C320000000008608E3002F000A00CB20000000008608EF0010000A009920000000008618C90306000B00000001004D0300000100D60000000200CB00000001004D03000001004D0300000100D60000000200CB00000001004D03000001004D03000001004D030900C90301001100C90306001900C9030A002900C90310003100C90310003900C90310004100C90310004900C90310005100C90310005900C90310006100C90315006900C90310007100C90310007900C90310008900C9031A009100C90306009900C90306002000830030012100830030012E000B004A002E00130053002E001B0072002E0023007B002E002B0093002E00330093002E003B0093002E0043007B002E004B0099002E00530093002E005B0093002E006300B1002E006B00DB002E007300E80040008300300141008300300143007B00350161008300300180008300300181008300300183007B003501A00083003001A10083003001A3007B003E01C00083003001C10083003001E00083003001400183003001600183003001800183003001A00183003001C00183003001E001830030010200010003000200050004000000110142000000C00042000000DE0042000000400346000000DE0042000000F300420002000100030001000200030002000400050001000500050002000600070001000700070002000A00090001000B00090002000C000B0001000D000B0002000E000D0001000F000D000480000001000000000000000000000000004E04000004000000000000000000000020000A00000000000000003C4D6F64756C653E006D73636F726C6962003C4E616D653E6B5F5F4261636B696E674669656C64003C536368656D614E616D653E6B5F5F4261636B696E674669656C64003C53716C547970653E6B5F5F4261636B696E674669656C64003C53716C52657475726E547970653E6B5F5F4261636B696E674669656C64003C44656661756C7456616C75653E6B5F5F4261636B696E674669656C64006765745F4E616D65007365745F4E616D65006765745F536368656D614E616D65007365745F536368656D614E616D6500736368656D614E616D650066756E6374696F6E4E616D65006765745F53716C54797065007365745F53716C54797065006765745F53716C52657475726E54797065007365745F53716C52657475726E547970650053716C496E7374616C6C657253637269707447656E657261746F724578706F7274656450726F6365647572650053716C496E7374616C6C657253637269707447656E657261746F724578706F727465644174747269627574654261736500436F6D70696C657247656E65726174656441747472696275746500477569644174747269627574650041747472696275746555736167654174747269627574650044656275676761626C6541747472696275746500436F6D56697369626C6541747472696275746500417373656D626C795469746C6541747472696275746500417373656D626C7954726164656D61726B417474726962757465005461726765744672616D65776F726B41747472696275746500417373656D626C7946696C6556657273696F6E41747472696275746500417373656D626C79436F6E66696775726174696F6E41747472696275746500417373656D626C794465736372697074696F6E4174747269627574650053716C506172616D6574657241747472696275746500436F6D70696C6174696F6E52656C61786174696F6E7341747472696275746500417373656D626C7950726F6475637441747472696275746500417373656D626C79436F7079726967687441747472696275746500417373656D626C79436F6D70616E794174747269627574650052756E74696D65436F6D7061746962696C697479417474726962757465006765745F44656661756C7456616C7565007365745F44656661756C7456616C75650076616C75650053797374656D2E52756E74696D652E56657273696F6E696E670053716C436C724465636C61726174696F6E732E646C6C0053797374656D0053797374656D2E5265666C656374696F6E0053716C496E7374616C6C657253637269707447656E657261746F724578706F7274656446756E6374696F6E002E63746F720053797374656D2E446961676E6F73746963730053797374656D2E52756E74696D652E496E7465726F7053657276696365730053797374656D2E52756E74696D652E436F6D70696C6572536572766963657300446562756767696E674D6F6465730053716C436C724465636C61726174696F6E732E417474726962757465730053716C436C724465636C61726174696F6E730041747472696275746554617267657473004F626A6563740000000000000000FF1810DC4E0B8B4D9CE1E63AF2E8B1CE00042001010803200001052001011111042001010E042001010205200101114108B77A5C561934E08902060E02061C0320000E052002010E0E0320001C042001011C0328000E0328001C0801000800000000001E01000100540216577261704E6F6E457863657074696F6E5468726F7773010801000200000000001701001253716C436C724465636C61726174696F6E73000005010000000017010012436F7079726967687420C2A920203230313500002901002435366332343732302D383035332D346366352D386266382D62616537646261373834323400000C010007312E302E302E3000004701001A2E4E45544672616D65776F726B2C56657273696F6E3D76342E300100540E144672616D65776F726B446973706C61794E616D65102E4E4554204672616D65776F726B20340401000000080100400000000000080100000800000000000000000092014156000000000200000067000000642B0000640D000052534453C76A21CD3E8DBE4F9C2BADE7D46D4BFF01000000433A5C50726F6A656374735C5265646953514C43616368655C53716C436C724465636C61726174696F6E735C6F626A5C52656C656173655C53716C436C724465636C61726174696F6E732E70646200F32B000000000000000000000D2C0000002000000000000000000000000000000000000000000000FF2B0000000000000000000000005F436F72446C6C4D61696E006D73636F7265652E646C6C000000000000FF25002000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001001000000018000080000000000000000000000000000001000100000030000080000000000000000000000000000001000000000048000000584000006C03000000000000000000006C0334000000560053005F00560045005200530049004F004E005F0049004E0046004F0000000000BD04EFFE00000100000001000000000000000100000000003F000000000000000400000002000000000000000000000000000000440000000100560061007200460069006C00650049006E0066006F00000000002400040000005400720061006E0073006C006100740069006F006E00000000000000B004CC020000010053007400720069006E006700460069006C00650049006E0066006F000000A802000001003000300030003000300034006200300000001A000100010043006F006D006D0065006E007400730000000000000022000100010043006F006D00700061006E0079004E0061006D00650000000000000000004E0013000100460069006C0065004400650073006300720069007000740069006F006E0000000000530071006C0043006C0072004400650063006C00610072006100740069006F006E00730000000000300008000100460069006C006500560065007200730069006F006E000000000031002E0030002E0030002E00300000004E001700010049006E007400650072006E0061006C004E0061006D0065000000530071006C0043006C0072004400650063006C00610072006100740069006F006E0073002E0064006C006C00000000004800120001004C006500670061006C0043006F007000790072006900670068007400000043006F0070007900720069006700680074002000A90020002000320030003100350000002A00010001004C006500670061006C00540072006100640065006D00610072006B00730000000000000000005600170001004F0072006900670069006E0061006C00460069006C0065006E0061006D0065000000530071006C0043006C0072004400650063006C00610072006100740069006F006E0073002E0064006C006C0000000000460013000100500072006F0064007500630074004E0061006D00650000000000530071006C0043006C0072004400650063006C00610072006100740069006F006E00730000000000340008000100500072006F006400750063007400560065007200730069006F006E00000031002E0030002E0030002E003000000038000800010041007300730065006D0062006C0079002000560065007200730069006F006E00000031002E0030002E0030002E0030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000C000000203C00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
18 | WITH PERMISSION_SET = UNSAFE
19 |
20 |
21 | GO
22 |
23 | CREATE ASSEMBLY [RediSql]
24 | AUTHORIZATION [dbo]
25 | FROM 0x4D5A90000300000004000000FFFF0000B800000000000000400000000000000000000000000000000000000000000000000000000000000000000000800000000E1FBA0E00B409CD21B8014CCD21546869732070726F6772616D2063616E6E6F742062652072756E20696E20444F53206D6F64652E0D0D0A2400000000000000504500004C010300C1A344560000000000000000E00022200B013000006E00000006000000000000BA8C00000020000000A000000000001000200000000200000400000000000000040000000000000000E000000002000000000000030040850000100000100000000010000010000000000000100000000000000000000000678C00004F00000000A00000680300000000000000000000000000000000000000C000000C000000F48B00001C0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000080000000000000000000000082000004800000000000000000000002E74657874000000C06C000000200000006E000000020000000000000000000000000000200000602E727372630000006803000000A000000004000000700000000000000000000000000000400000402E72656C6F6300000C00000000C00000000200000074000000000000000000000000000040000042000000000000000000000000000000009B8C000000000000480000000200050054430000A0480000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013300500400000000000000002188D3500000125161F0D9C25171F0A9C7D0A00000402281900000A032D0B7201000070731A00000A7A02032805000006020428070000060215280D0000062A36020320EB18000028010000062A4602720B00007020EB18000028010000062A1E027B030000042A2202037D030000042A1E027B040000042A2202037D040000042A1E027B050000042A2202037D050000042A1E027B060000042A2202037D060000042A1E027B070000042A2202037D070000042A1E027B080000042A2202037D080000042A1E027B090000042A9E02037D0900000402721F000070178D110000012516027B090000048C37000001A228280000062A220203281C0000062A2602030428140000062ABE032D0B722D000070731A00000A7A042D0B7235000070731A00000A7A0203281B00000A046F1C00000A28150000062A000000133007006000000000000000032D0B722D000070731A00000A7A042D0B7235000070731A00000A7A048E692000000040311072410000707235000070731D00000A7A02047263000070178D11000001251603A228230000062D0B726B000070731E00000A7A0228270000062ABE032D0B722D000070731A00000A7A042D0B7235000070731A00000A7A0203281B00000A046F1C00000A28170000062A133007005300000000000000032D0B722D000070731A00000A7A042D0B7235000070731A00000A7A048E692000000040311072410000707235000070731D00000A7A0204728F000070178D11000001251603A22829000006163002162A172A00133005005900000000000000032D0B729B000070731A00000A7A02037E25000004252D17267E24000004FE069E000006731F00000A2580250000047E26000004252D17267E24000004FE069F000006732000000A258026000004280100002B28190000062AAE032D0B729B000070731A00000A7A02036F2200000A280200002B036F2400000A280300002B281A0000062A000000133005001E01000001000011038E69048E692E0B72A5000070732500000A7A281B00000A72F50000706F1C00000A0A732600000A0B160C38B6000000281B00000A03089A6F1C00000A0D04089A1304281B00000A72FB000070098E698C3700000172F5000070282700000A6F1C00000A1305281B00000A03089A72F5000070282800000A6F1C00000A1306281B00000A72FB00007011048E698C3700000172F5000070282700000A6F1C00000A13070711051611058E696F2900000A0711061611068E696F2900000A0711071611078E696F2900000A0711041611048E696F2900000A070616068E696F2900000A0817580C08038E693F41FFFFFF02076F2A00000A72FF000070038E69185A17588C370000017203010070282700000A2824000006260228270000062A92032D0B722D000070731A00000A7A02721D010070178D11000001251603A2282D0000062A00133002002700000002000011032D0B722D000070731A00000A7A0203281B0000060A062C0C281B00000A066F2B00000A2A142A6602036F67000006036F73000006036F77000006281E0000062A000000133005006500000003000011032D0B722D000070731A00000A7A04282C00000A2D03192B01170A06058E69588D110000010B071603A205160706058E69282D00000A0617330D0272250100700728480000062A0717722F010070A2071804A202722501007007282A0000068D0400001B2A000000133007006000000000000000032D0B722D000070731A00000A7A042D0B7235000070731A00000A7A048E692000000040311072410000707235000070731D00000A7A0204723B010070178D11000001251603A228230000062D0B726B000070731E00000A7A02282E0000062A133004004000000002000011032D0B722D000070731A00000A7A042D0B7235000070731A00000A7A0203281B00000A046F1C00000A281F0000060A062C0C281B00000A066F2B00000A2A142A133002003200000004000011732E00000A0A2B13071F0D2E0E071F0A2E190607D16F2F00000A26027B020000046F3000000A250B1533DD066F3100000A2A000013300600A0000000000000000218171C733200000A7D01000004027B01000004176F3300000A027B0100000402280C0000066F3400000A027B010000040228040000060228060000066F3500000A027B010000046F3600000A2D13027B010000046F3700000A02147D010000042A02027B01000004733800000A2000400000733900000A7D0200000402280E0000062C1A027249010070178D11000001251602280E000006A228280000062A13300400E90000000500001172FF00007017058E695817580B1201283A00000A72F5000070283B00000A0A1C8D11000001251606A2251772FB000070A22518046F3C00000A8C37000001A2251972F5000070A2251A04A2251B72F5000070A2283D00000A0A050C160B2B5008079A6F3100000A0D281B00000A096F3E00000A13041C8D11000001251606A2251772FB000070A2251811048C37000001A2251972F5000070A2251A09A2251B72F5000070A2283D00000A0A0717580B07088E6932AA1A8D11000001251606A2251772FB000070A22518038E698C37000001A2251972F5000070A2283D00000A0A02030628240000062A0000001B3003007C00000006000011027B010000042D06022822000006027B010000042D02162A281B00000A046F1C00000A0A027253010070042826000006027B01000004066F3F00000A26032C1F027B01000004036F3F00000A26027B01000004027B0A0000046F3F00000A26DE1726027B010000046F3700000A02147D01000004160BDE02172A072A01100000000024003D6100171A0000011B3004001201000007000011027B010000042D06022822000006027B010000042D02162A72FF00007017048E69580C1202283A00000A72F5000070283B00000A0A1C8D11000001251606A2251772FB000070A22518036F3C00000A8C37000001A2251972F5000070A2251A03A2251B72F5000070A2283D00000A0A040D160C2B5309089A6F3100000A1304281B00000A11046F3E00000A13051C8D11000001251606A2251772FB000070A2251811058C37000001A2251972F5000070A2251A1104A2251B72F5000070A2283D00000A0A0817580C08098E6932A7281B00000A066F1C00000A0B027253010070062826000006027B01000004076F3F00000A26DE1826027B010000046F3700000A02147D01000004161306DE02172A11062A0000011000000000DA001BF500181A0000019A037257010070046F4000000A72F5000070725D0100706F4100000A283B00000A284200000A2A00133004006600000008000011027B020000046F3000000A0A0615330B726101007073990000067A0228210000060B02727B01007006D10C1202FE16450000016F3100000A07282800000A2826000006061F2D331D07727F0100706F4300000A2D03072B07071A6F4400000A73990000067A2A7202030428250000062D0B726B000070731E00000A7A0228270000062A0013300400A3000000090000110203040528230000062D0B726B000070731E00000A7A027B020000046F3000000A0A0615330B726101007073990000067A0228210000060B02727B01007006D10C1202FE16450000016F3100000A07282800000A2826000006061F2D331D07727F0100706F4300000A2D03072B07071A6F4400000A73990000067A061F3A330C071203284500000A2C02092A7289010070068C3700000107282700000A73990000067A0013300400A20000000900001102030428250000062D0B726B000070731E00000A7A027B020000046F3000000A0A0615330B726101007073990000067A0228210000060B02727B01007006D10C1202FE16450000016F3100000A07282800000A2826000006061F2D331D07727F0100706F4300000A2D03072B07071A6F4400000A73990000067A061F3A330C071203284500000A2C02092A7289010070068C3700000107282700000A73990000067A000013300400980000000800001102030428250000062D0B726B000070731E00000A7A027B020000046F3000000A0A0615330B726101007073990000067A0228210000060B02727B01007006D10C1202FE16450000016F3100000A07282800000A2826000006061F2D331D07727F0100706F4300000A2D03072B07071A6F4400000A73990000067A061F2B3302072A7289010070068C3700000107282700000A73990000067A7202030428250000062D0B726B000070731E00000A7A0228210000062A7202030428250000062D0B726B000070731E00000A7A02282E0000062A000013300500F60000000A0000110228210000060A02727B010070062826000006066F3C00000A2D0B72CF01007073990000067A06166F4600000A251F2D33230672F70100706F4300000A2D0906176F4400000A2B07061B6F4400000A73990000067A1F244089000000067203020070284700000A2C02142A06176F4400000A1201284500000A2C5F078D350000010C160D027B0200000408090709596F4800000A13041104172F0B720B02007073990000067A091104580D090732D5027B020000046F3000000A1F0D330F027B020000046F3000000A1F0A2E0B724902007073990000067A082A727102007073990000067A728F02007006282800000A73990000067A9E032D0B722D000070731A00000A7A0272B5020070178D11000001251603A2282A00000617FE012A9E032D0B722D000070731A00000A7A0272C3020070178D11000001251603A2282A00000617FE012A6E032D0B72CB020070731A00000A7A0272C302007003282A0000062A92032D0B722D000070731A00000A7A0272D5020070178D11000001251603A2282A0000062AB6032D0B722D000070731A00000A7A0272DF020070188D11000001251603A22517048C37000001A2282A0000062A92032D0B722D000070731A00000A7A0272ED020070178D11000001251603A2282A0000062AB6032D0B722D000070731A00000A7A0272F7020070188D11000001251603A22517048C37000001A2282A0000062A133006008B0000000B000011032D0B722D000070731A00000A7A027205030070178D11000001251603A2282B0000060A06720F030070284700000A2D43067219030070284700000A2D38067227030070284700000A2D2D06722F030070284700000A2D22067239030070284700000A2D17067243030070284700000A2D0C2B0C162A172A192A182A1B2A1A2A724D03007073990000067A4A027269030070168D11000001282B0000062A0000133006004000000000000000032D0B727D030070731A00000A7A042D0B7293030070731A00000A7A0272A9030070188D11000001251603A2251704A2282C000006166F4600000A1F2BFE012AC2032D0B722D000070731A00000A7A0272B7030070188D11000001251603A22517048C37000001A2282A00000617FE012AC2032D0B722D000070731A00000A7A0272C5030070188D11000001251603A22517048C37000001A2282A00000617FE012A92032D0B722D000070731A00000A7A0272D7030070178D11000001251603A2282A0000062A4A0272DF030070168D11000001282A0000062A4A0272ED030070168D1100000128280000062A4A0272F7030070168D1100000128280000062A1B300300710000000B000011027205040070168D110000012825000006260228210000060A02727B010070062826000006066F3C00000A2D0B72CF01007073990000067A0672F70100706F4300000A2D0906176F4400000A2B07061B6F4400000A73990000067A26027B010000046F3700000A02147D01000004DE002A0000000110000000001200495B00151C0000014A027217040070168D1100000128280000062A4A027229040070168D1100000128280000062A0000133003002D0000000C000011027239040070168D11000001282A0000060A210080B5F7F57F9F08734900000A066C284A00000A284B00000A2A00000013300500740000000D00001102724B040070168D11000001282D0000060A734C00000A0B281B00000A066F2B00000A178D4500000125161F0A9D6F4D00000A0C160D2B3408099A130411041F3A6F4E00000A13051105152E1B0711041611056F4F00000A1104110517586F4400000A6F5000000A0917580D09088E6932C6072A320272FF00007028450000062A92032D0B7255040070731A00000A7A027265040070178D11000001251603A228470000062AAA032D0B726F040070731A00000A7A038E2D0B726F040070732500000A7A0272790400700328480000062A00000013300500320000000E00001102030428480000060A068E698D3D0000010B160C2B140708281B00000A06089A6F2B00000AA20817580C08068E6932E6072A000013300400C60000000F00001102030428250000062D0B726B000070731E00000A7A027B020000046F3000000A0A0615330B726101007073990000067A0228210000060B02727B01007006D10C1202FE16450000016F3100000A07282800000A2826000006061F2D331D07727F0100706F4300000A2D03072B07071A6F4400000A73990000067A061F2A3330071203284500000A2C26098D0400001B13041613052B111104110502282E000006A211051758130511050932EA11042A7283040070068C3700000107282700000A73990000067AA20272C5040070198D11000001251603A22517048C37000001A22518058C37000001A228480000062A4E0203281B00000A046F1C00000A284B0000062A7A020472D3040070178D11000001251603A22823000006260228270000062A4E0203281B00000A046F1C00000A284D0000062A7A020472DF040070178D11000001251603A22823000006260228270000062A5A0272EB040070178D11000001251603A2282A0000062A9A0272F5040070188D11000001251603A22517048C37000001A228250000062602282E0000062A76027203050070178D11000001251603A228250000062602282E0000062A7602720D050070178D11000001251603A228250000062602282E0000062A6A02047217050070178D11000001251603A2282900000616FE022A4E0203281B00000A046F1C00000A28520000062A5A027221050070178D11000001251603A2282A0000062A6A0204722D050070178D11000001251603A2282900000616FE022A4E0203281B00000A046F1C00000A28550000062A5A027241050070178D11000001251603A228480000062A5A027253050070178D11000001251603A2282D0000062A5A02726B050070178D11000001251603A2282D0000062A6A02047275050070178D11000001251603A2282900000616FE022A4E0203281B00000A046F1C00000A285A0000062A5A032D06735100000A7A02727F0500700328480000062AAA03282C00000A2C0B728D050070731A00000A7A042D0B726F040070731A00000A7A02030428280000062A3602729505007003285D0000062A5A032D06735100000A7A0272AD0500700328480000062A360272BB05007003285D0000062A5A032D06735100000A7A0272D30500700328480000062A360272DF05007003285D0000062A7A020572F5050070188D11000001251603A2251704A2282900000616FE022A3A02176F6600000602285200000A2A1B300200110000000000000002166F66000006DE0702281000000ADC2A00000001100000020000000909000700000000BA032C2A027201060070168D11000001282500000626022827000006027B010000046F3700000A02147D010000042A1E027B0C0000042A2202037D0C0000042A1E027B0D0000042A2202037D0D0000042A1E027B0E0000042A2202037D0E0000042A1E027B0F0000042A2202037D0F0000042A1E027B100000042A2202037D100000042A1E027B110000042A2202037D110000042A1E027B120000042A2202037D120000042A1E027B130000042A2202037D130000042A0013300200AD00000010000011735300000A0A02286D0000062D0802286F0000062C3006720B0600706F5400000A260602286D0000068C370000016F5400000A260602286F0000068C370000016F5400000A2602286B0000062C0C0672170600706F5400000A26022871000006282C00000A2D190672230600706F5400000A26060228710000066F5400000A26022875000006282C00000A2D1906721D0100706F5400000A26060228750000066F5400000A26066F5500000A2A1E02281900000A2A0000001B30040025000000110000110203040528960000060A060E040E050E066F490000060BDE0A062C06066F5600000ADC072A0000000110000002000A000F19000A00000000133003001E0000000200001102740400001B0A03281B00000A066F2B00000A285700000A812C0000012A00001B3004002D000000120000110203040528960000060A281B00000A060E040E056F4F0000066F2B00000A0BDE0A062C06066F5600000ADC072A0000000110000002000A001721000A000000001B3004002B000000120000110203040528960000060A281B00000A060E046F500000066F2B00000A0BDE0A062C06066F5600000ADC072A000110000002000A00151F000A000000001B3004002B000000120000110203040528960000060A281B00000A060E046F510000066F2B00000A0BDE0A062C06066F5600000ADC072A000110000002000A00151F000A000000001B30040053000000130000110203040528960000060A0E062C0C060E040E056F4C0000062B0A060E040E056F4A0000060F07285800000A2C19060E040F07285900000A0B1201285A00000A696F3900000626DE0A062C06066F5600000ADC2A000110000002000A003E48000A000000001B30040021000000140000110203040528960000060A060E046F4E0000060BDE0A062C06066F5600000ADC072A0000000110000002000A000B15000A000000001B300400DF0000001500001173A00000060A06027D2700000406037D2800000406047D2900000406057D2A000004060E047D2B0000040E0528810000060B067B27000004067B28000004067B29000004067B2A00000428960000060C08067B2B0000046F2F0000062C1E0E072C0F08067B2B0000046F30000006262B0B7229060070731E00000A7A076F5B00000A1758735C00000A2528830000066F5D00000A25076F5E00000A06FE06A1000006735F00000A6F6000000A0F06285800000A2C1D08067B2B0000040F06285900000A0D1203285A00000A696F3900000626DE0A082C06086F5600000ADC2A00011000000200500084D4000A000000001B300400C800000016000011736100000A0A72B2060070736200000A0B076F6300000A06070228820000066F5D00000A0207736400000A0C086F6500000A0D2B6972E2060070286600000A736700000A13041613052B3C0911056F6800000A2D2C110472EC060070110517588C37000001286900000A286600000A0911056F6A00000A736B00000A6F6C00000A1105175813051105096F6D00000A32BA0611046F3100000A6F5D00000A096F6E00000A2D8FDE1E092C06096F5600000ADC082C06086F5600000ADC072C06076F5600000ADC062A012800000200330075A8000A0000000002002C0086B2000A0000000002001100ABBC000A000000001B300800D90000001700001172F006007002736400000A0A061A6F6F00000A066F7000000A722A070070036F7100000A267234070070286600000A736700000A0B066F6500000A0C2B72077254070070286600000A198D1100000125167262070070286600000A08726E0700706F7200000A737300000AA22517728C070070286600000A08728C0700706F7200000A737300000AA225187296070070286600000A0872A60700706F7200000A737300000AA2737400000A6F6C00000A086F6E00000A2D86DE0A082C06086F5600000ADC076F3100000A0DDE0A062C06066F5600000ADC092A000000011C000002003C007EBA000A0000000002000C00C1CD000A000000001A72C80700702A001B30040043000000130000110203040528960000060A060E040E056F140000060F06285800000A2C19060E040F06285900000A0B1201285A00000A696F3900000626DE0A062C06066F5600000ADC2A000110000002000A002E38000A000000001B3004004C000000180000110203040528960000060A060E040E056F160000060B072C240F06285800000A2C1B060E040F06285900000A0C1202285A00000A696F390000060DDE0E070DDE0A062C06066F5600000ADC092A0110000002000A003640000A000000001B3004004B000000190000110203040528960000060A060E040E056F200000060F06285800000A2C19060E040F06285900000A0B1201285A00000A696F3900000626252D03260E050CDE0A062C06066F5600000ADC082A000110000002000A00353F000A000000001B30040021000000120000110203040528960000060A060E046F1C0000060BDE0A062C06066F5600000ADC072A0000000110000002000A000B15000A000000001B300400210000001A0000110203040528960000060A060E046F2F0000060BDE0A062C06066F5600000ADC072A0000000110000002000A000B15000A000000001B300600E50000001B0000110203040528960000060A060E046F360000060B074506000000050000001A0000002F0000006C000000900000007E000000389D000000160C1202FE16040000026F3100000A0DDD98000000170C1202FE16040000026F3100000A0DDD83000000020304050E0416287B00000628830000061B6F7500000A2C12190C1202FE16040000026F3100000A0DDE58180C1202FE16040000026F3100000A0DDE461A0C1202FE16040000026F3100000A0DDE341A0C1202FE16040000026F3100000A0DDE221B0C1202FE16040000026F3100000A0DDE10737600000A7A062C06066F5600000ADC092A0000000110000002000A00CFD9000A000000001B300400230000001A0000110203040528960000060A060E040E056F380000060BDE0A062C06066F5600000ADC072A000110000002000A000D17000A000000001B300400290000001A0000110203040528960000060A060E040F05285A00000A696F390000060BDE0A062C06066F5600000ADC072A0000000110000002000A00131D000A000000001B300400290000001A0000110203040528960000060A060E040E052897000006696F3A0000060BDE0A062C06066F5600000ADC072A0000000110000002000A00131D000A000000001B300400370000001C0000110203040528960000060A060E046F3B0000060B07162F0B1202FE150900001B082B0607737700000A0CDE0A062C06066F5600000ADC082A000110000002000A00212B000A000000001B300400210000001A0000110203040528960000060A060E046F300000060BDE0A062C06066F5600000ADC072A0000000110000002000A000B15000A000000001B30040021000000110000110203040528960000060A060E046F450000060BDE0A062C06066F5600000ADC072A0000000110000002000A000B15000A000000004A0302743D000001285700000A812C0000012A001B3004001F000000110000110203040528960000060A066F430000060BDE0A062C06066F5600000ADC072A000110000002000A000913000A00000000133002002C0000001D00001102A50A00001B0A031200287800000A285700000A812C000001041200287900000A285700000A812C0000012A1B300400290000001E0000110203040528960000060A0E042C08066F3E000006DE12066F3D000006DE0A062C06066F5600000ADC2A0000000110000002000A00141E000A000000001B3004002E0000001E0000110203040528960000060A0F03287A00000A2C08066F41000006DE12066F40000006DE0A062C06066F5600000ADC2A00000110000002000A001923000A000000001B3004001F0000001F0000110203040528960000060A066F420000060BDE0A062C06066F5600000ADC072A000110000002000A000913000A00000000133002002A0000001E000011020373010000060A042C0706046F0F0000060F03287A00000A2C0D060F03287B00000A6F11000006062A00001330020014000000200000117E1B00000402287C00000A0A1200285A00000A2A4A20B20700001717737D00000A801B0000042A4E0272E4070070281E00000A0203289B0000062A1E027B230000042A2202037D230000042A2E739D00000680240000042A220F01287800000A2A4A281B00000A0F01287900000A6F1C00000A2A133008002F00000021000011027B27000004027B28000004027B29000004027B2A000004027B2B00000403171200FE150600001B06287E0000062A0042534A4201000100000000000C00000076342E302E33303331390000000005006C000000481E0000237E0000B41E0000FC12000023537472696E677300000000B03100000408000023555300B4390000100000002347554944000000C4390000DC0E000023426C6F620000000000000002000001571FA20B090A000000FA01330016000001000000520000000F0000002B000000A10000001A010000010000007D0000000F000000D100000021000000040000001500000026000000010000000A00000001000000060000000400000003000000000005090100000000000600A606D00C06002707D00C06006D05680C0F00F00C000006009505EE0906005C06EE0906002806EE0906000E07EE090600C606EE090600DF06EE090600C205EE0906008105B10C06005F05B10C06000B06EE090600DD05220806007906EE0906004D0F800906001A0480090A000A10B90E06003709E40006004405D00C0600B300820106005409E4000600FA0680090600D80BB6110A00E30AB90E0600F605680C0600930AE40006006A0480090600B400820106008C0980090600FB0A800906009D0080090600A400820106005311940D0E005B0A140D12004706400C12009503400C06000E04940D0E009006140D0600D704800906001309800906006000800912003C08FF0C0E00EF04140D1200AC05400C0600910980090600900082011200240A8D1012007E038D101200BC0B8D101600A310870B0600490780090600CD0A800906009700800906001908B6110600F30A80091A000F04970B06006B00820106008200820106006708800906005A09E40006002D1280090A009412B90E0A00C604B90E0A00B904B90E0A004609B90E0600260480090600A30B80090600D70080090600790080091200170A050B16003404870B1200AF0B050B1600210C870B12006803050B1200AD0409011200000A8D1012002C0C8D1016003905870B0600470B800906009F0A800900000000CE00000000000100010001001000590D000045000100010001001000020E000045000C00670001010000D404DB0E7D001400790081011000F40EDB0E45001B00790081011000CC0EDB0E45001B00800081011000E50DDB0E45001B00840081011000A70DDB0E45001B00880081011000C80DDB0E45001B00910080011000320A270B45001B00960081011000660D180B45001B00970002010000D40400007D001C00990002001000BB0A0000810023009900032110006E010000450024009C00030110000100000045002700A00001001110D00301006109D40301009402D80301007E02DB030100C702DB0301006202DB030100AA02DB030100C901D80301006201DB0301004301DE035180AA08E2030100F902D8030100F901E50301002A03E50301004602DB0301002A02DB030100E502D80301000E03D80301001502D80306060101DB0356809208E80356806708E80356805811E80356801810E80356800610E8035680B408E80331007E04EC0306060101DB035680A404F00356806708F00356805811F00356800610F0035680B408F00356807E0FF0030100E301D8033600CA00F40316001600F80316004900070406006F11D80306002711DB030600CB03D80306009D01170406009012D80350200000000086185B0C270101009C200000000086185B0C10000300AA200000000086185B0C06000400BC200000000086085D1116010400C420000000008108661110000400CD20000000008608101112010500D520000000008108191101000500DE20000000008608941112010600E620000000008608A51101000600EF20000000008608E61012010700F720000000008608F51001000700002100000000860874111201080008210000000086088411010008001121000000008608B103160109001921000000008608BE031000090022210000000086084C0112010A002A21000000008608530101000A00522100000000860869091F040B005B2100000000860872091A000C00652100000000860006101A000E0098210000000086000610240410000422000000008600FB002B0412003422000000008600FB00310414009422000000008600061038041600F9220000000086000610420417002823000000008600790F4D0418005224000000008600750F26001A00782400000000860064081F041B00AB24000000008600221156041C00C82400000000860022115E041D003C25000000008600031068042000A825000000008600031072012200F4250000000081009104160124003426000000008100540F06002400E026000000008100580370042400D827000000008100EE00790427007028000000008100720380042900A0290000000081009E081A002B00C829000000008100330E06002D003A2A0000000081002F0E87042D00582A0000000081006D108E042F00082B0000000081007F1097043200B82B0000000081004F089E0434005C2C00000000810060089E043600792C0000000081003401A5043800982C0000000081001501DB003A009A2D0000000086007C1283013A00C22D000000008600C90783013B00EA2D000000008600C907AD043C00062E000000008600B61055013D002B2E000000008600B610B3043E00592E000000008600AC10550140007E2E000000008600AC10B3044100AC2E000000008600EC07B9044300432F000000008600541216014400582F0000000086004D042B044400A42F000000008600DC04BF044600D52F0000000086003D0FBF0448000630000000008600BE0755014A002B30000000008608D00712014B003E30000000008600B90706004B005130000000008600A20706004B006430000000008600600B06004B00F430000000008600FC0806004B0007310000000086005A0106004B001C31000000008608B107C5044B005831000000008600690BCA044B00D831000000008608270FD3044B00E531000000008600300FD8044B000A32000000008600640FDE044C0038320000000086001512E6044D0078320000000086000112EE044F004A330000000086000404F70451007333000000008600B9081A0054008733000000008600B90824045600A633000000008600C2081A005800BA33000000008600C20824045A00D933000000008600E00855015C00F033000000008600D71100055D001734000000008600710B26005F003534000000008600790B260060005334000000008600EA0F310461006E34000000008600EA0F2B0463008234000000008600CB0F550165009934000000008600AD0F31046600B434000000008600AD0F2B046800C834000000008600BB0F07056A00DF34000000008600980F26006B00F634000000008600830F26006C000D35000000008600DC0F31046D002835000000008600DC0F2B046F003C350000000086007C0EDE04710053350000000081007B0C0E0572007E350000000086006B0E150574008C35000000008600A30EDE047500A3350000000086008B0E15057600B135000000008600570EDE047700C835000000008600410E15057800D635000000008600F30F1B057900F53500000000E601220506007C00043600000000C400E30706007C00343600000000C401220515007C006336000000008608331216017D006B360000000086083B1210007D007436000000008608FB072D017E007C360000000086080A0815007E008536000000008608A2122D017F008D36000000008608B61215007F0096360000000086084F10120180009E360000000086085E1001008000A736000000008608311012018100AF36000000008608401001008100B836000000008608E71116018200C036000000008608EE1110008200C9360000000086085E1216018300D1360000000086086D1210008300DA36000000008608690F16018400E236000000008608710F10008400EC360000000086004D0D2A028500A5370000000086185B0C06008500B037000000009600740D23058500F437000000009600F80B35058C002038000000009600C4113E058E006C38000000009600710B4D059400B438000000009600790B4D059900FC380000000096002C115B059E006C39000000009600DD087305A600AC390000000096001E018105AB00A83A00000000910036119905B300A43B0000000091001A09A305B400A83C0000000096087201AB05B600B03C0000000096006A07AF05B600103D000000009600010FC605BD00783D0000000096006707DD05C400E03D00000000960058074D05CB00203E0000000096001B0FF405D000603E000000009600D1044D05D500643F0000000096004D040206DA00A43F000000009600AB091106E000EC3F000000009600C1092206E6003440000000009600DA003206EC0088400000000096004A12F405F100C840000000009600300F4506F60008410000000096000F0C3505FB001C41000000009600690B5506FD005841000000009600E60B640601019041000000009600B90771060401D841000000009600CC087F0609012442000000009600B9018C060D016042000000009300420A9A06110198420000000096007304A8061501B842000000009118610CAE061601CB420000000086185B0C10001601DF42000000008608DC0316011701E742000000008108E50310001701F042000000009118610CAE061801A5370000000086185B0C06001801FC420000000083002000B206180105430000000083005300BD061901A5370000000086185B0C06001A0118430000000083002D0010001A01000001006F11000002002711000001006F11000001009C07000001009C07000001009C07000001009C07000001009C07000001009C07000001009C07000001009012000001009012000002009C07000001009012000002009C07000001009012000002009C07000001009012000002009C07000001009012000002009C07000001005C0F000001005C0F00000100380F00000200460D000001009012000001009012000001000E0E000001009012000002009F09000003000E0E000001009012000002009C07000001009012000002009C07000001004701000002004B0300000300540D00000100470100000200820B000001004B0300000200540D00000100C60100000200F303000001004B0300000200540D000001004701000002004B0300000300540D000001004B0300000200540D000001004B0300000200540D000001004B0300000200540D000001004B0300000200540D00000100901200000100901200000100540D000001009012000001009012000002000411000001009012000001009012000002000411000001009012000001005404000002005F0400000100901200000200A90C000001009012000002008C0400000100901200000100580B00000100380F000001004B0300000200540D000001004B0300000200540D000001009012000002000A11000003009103000001009012000002009C07000001009012000002009C07000001009012000002009C07000001009012000002009C0700000100901200000100901200000200E11100000100901200000100901200000100901200000200A80B00000100901200000200A80B00000100901200000100901200000200A80B00000100901200000200A80B00000100901200000100901200000100901200000100901200000200A80B00000100901200000200A80B00000100380F000001004B0300000200380F00000100380F00000100380F00000100380F00000100380F00000100380F00000100431200000200881200000300A80B000001007808000001009C07000001009C07000001009C07000001009C07000001009C07000001009C07000001009C07000001009C07000001006F1100000200271100000300CB03000004009D01000005009012000006000A11000007009103000001007B09020002009C07000001006F1100000200271100000300CB03000004009D0100000500901200000600E111000001006F1100000200271100000300CB03000004009D01000005009012000001006F1100000200271100000300CB03000004009D01000005009012000001006F1100000200271100000300CB03000004009D01000005009012000006009C07000007004F0300000800D409000001006F1100000200271100000300CB03000004009D01000005009012000001006F1100000200271100000300CB03000004009D0100000500901200000600DC1200000700D40900000800820800000100DC1200000100500A00000200DC12000001006F1100000200271100000300CB03000004009D01000005009012000006009C0700000700D409000001006F1100000200271100000300CB03000004009D01000005009012000006009C0700000700D409000001006F1100000200271100000300CB03000004009D01000005009012000006009C0700000700D409000001006F1100000200271100000300CB03000004009D01000005009012000001006F1100000200271100000300CB03000004009D01000005009012000001006F1100000200271100000300CB03000004009D01000005009012000001006F1100000200271100000300CB03000004009D01000005009012000006003A04000001006F1100000200271100000300CB03000004009D0100000500901200000600D409000001006F1100000200271100000300CB03000004009D0100000500901200000600D409000001006F1100000200271100000300CB03000004009D01000005009012000001006F1100000200271100000300CB03000004009D01000005009012000001006F1100000200271100000300CB03000004009D0100000500390C000001007B09020002004504000001006F1100000200271100000300CB03000004009D01000001007B09020002002E04020003009C07000001006F1100000200271100000300CB03000004009D0100000500A403000001006F1100000200271100000300CB03000004009D01000001006F1100000200271100000300CB03000004009D01000001006F1100000200271110100300CB03101004009D0100000100610F00000100EE03000001009C0700000100F60800000100C21100000100F8080200490009005B0C010011005B0C060019005B0C0A0029005B0C100031005B0C100039005B0C100041005B0C100049005B0C100051005B0C100059005B0C100061005B0C150069005B0C100071005B0C100079005B0C100081005B0C10008900E3070600A9005B0C0600C1005B0C0600D9005B0C100021015B0C1A0029015B0C060041015B0C060069015B0C1A0071015B0C060089005B0C0600B1015B0C1000C101C1002000C101320D2600C9015B0C1A0001015B0C10000C005B0C3A0014005B0C3A00D101CF124F001C00270F8900D1012B1293001C003B0DA500C9015B0C1000B9005B0C0600E901460FC600E901460FCD00F1013305D300B9002B12DB00C1016408E500E901EE12F100F901CA12F600C9005B0C0600C9008E030C01F1014507120189004608160199005B0C1A019900F51115009900841101009900540F27019900AB012D0199001C05060019025B0C3101A1005B0C3701B90146081601E901460F4801E901D2081201E901460F4F01C101D9105501990089036001E90187091601E901D403720121029A047801E901EB088301E9016E088801B9012A059401E901160EA401E901E212A901F101A201AF01E9005B0CBF0179019D0CC401E900870ACB012C005B0C0600E9012B10EC01E901F307F301E9016E08F8012C00A701FE01B1015B0C06003102DB071A0219015B0C06001901A701250219012B122A0291002205060061011F103702340086072D0134004E07550279018C0C5A023C00C01012013C005B0C01003C00A7017B023C00FB03810244005B0C3A003C00A20893023C005B0C060089015B0C100041029A09060091015B0CB4029101CA0BBC0249021F10C202A1015B0CC90251021109D002E901460FD50251029307DB02A1015B0CE0025902A701E8025102CA1012015102A2012D016102A904FA029101200E0103710279070703510269090F0381025B0CE002A1015B0C1403E9015F0D400391025B0C06004C005B0C7B0254003312550254004E076D034C0086072D014C004E075502E900DF098403E9005B0C8E030A002C00A90308005400B20308005800B70308005C00BC0308006000C10308006400C60308006800CB0308007400B20308007800B70308007C00BC0308008000C10308008400C60308008800CB0312004D04B20312005104B2032E000B00E8062E001300F1062E001B0010072E00230019072E002B0026072E00330026072E003B0026072E00430019072E004B002C072E00530026072E005B0026072E00630044072E006B006E072E0073007B0743007B00D00D61008B00B70380008B00B70381008B00B703A0008B00B703A1008B00B703C0008B00B703C1008B00B703E0008B00B703E1008B00B70300018B00B70301018B00B70320018B00B70340018B00B70360018B00B70380018B00B70381018B00B703A0018B00B703A1018B00B703C0018B00B703C1018B00B703C3018B00B703E0018B00B703E1018B00B703E3018B00B70301028B00B70321028B00B70341028B00B70361028B00B703E4039300B70361048B00B703C0049B00C307C4049300B70344059300B703C4059300B70324069300B70364069300B703A4069300B703E4069300B70324079300B70384079300B70384099300B703C4099300B703040A9300B703E00C8B00B703000D8B00B703200D8B00B703400D8B00B703600D8B00B703800D8B00B703A00D8B00B703C00D8B00B703E00D8B00B703000E8B00B703200E8B00B703240E9300B703400E8B00B703600E8B00B703640E9300B703800E8B00B703840E9300B703A00E8B00B703A40E9300B703C00E8B00B703C40E9300B703E40E9300B703040F9300B703200FA300CE07200FAB00E807600FA300DD08600FAB00FE08800FA300A209800FAB00FE08A00FA300BB09A00FAB00FE08C00FBB00D509C00FC300B703E00FA300EC09E00FAB00FE080010BB00070A0010C300B7038010BB002A0A8010C300B703A010A300460AA010AB00FE08C010A3006D0AC010AB00FE08C410B300DA0DE010A3008C0AE010AB00FE08E410B300F40D0011A300A80A0011AB00FE080411B300F40D2011A300C10A2011AB00FE084011A300D90A4011AB00FE084411B300640E6011A300F00A6011AB00FE086411B3007D0E8011A300130B8011AB00FE08A011A300330BA011AB00FE08C011A3004A0BC011AB00FE08E011A300610BE011AB00760BE411B300DA0D0412B300F40D2012A300680C2012AB00830C2412B300F40D6012BB008A0D6012C300B7038012BB00A30D8012C300B703A012A300B60DA012AB00FE08A412B300DA0DC412B300F40DE412B300F40D40138B00B7034413B300DA0D60138B00B7036413B300F40D8413B300F40DE413B300DA0D0414B300F40D2414B300F40D8414B300960EA414B300F40DE414B300DA0D0415B300F40D2415B300F40D8415B300DA0DA415B300F40DC415B300F40D2416B300F40D4416B300AC0EE416B300DA0D0417B300F40D2417B300F40D8417B300F40DC417B300DA0DE417B300F40D0418B300F40D6418B300F40DA418B300DA0DC418B300F40DE418B300F40D4419B300F40D8419B300DA0DA419B300F40DC419B300F40D241AB300DA0D441AB300F40D641AB300F40DC41AB300DA0DE41AB300F40D041BB300F40D641BB300DA0D841BB300F40DA41BB300F40D241CB300DA0D441CB300F40D641CB300F40DE41CB300DA0D041DB300F40D241DB300F40DA41DB300DA0DC41DB300F40DE41DB300F40D441EB300DA0D641EB300F40D841EB300F40DE41EB300DA0D041FB300F40D241FB300F40D441FB300C20EC41FB300DA0DE41FB300F40D0420B300F40DA420B300DA0DC420B300F40DE420B300F40D0421B300960E4421B300DA0D6421B300F40D8421B300F40DC421B300DA0DE421B300F40D0422B300F40DB400E000EB0006013F015A0166017D018D019B01B701BB01D50106020F021F022F023E0244025E0264029E02ED021D0327033003360348035B03720377037E0395030200010003000C00060014000D00150000006A11C90600001D11CD060000A911CD060000F910CD0600008811CD060000C203C90600005F01CD0600007609D1060000D407CD060000B507D6060000330FDB0600008C12C90600000E08E0060000BA12E00600006210CD0600004410CD060000F211C90600007112C9060000750FC90600007601E4060000E903C90602000400030001000500030002000600050001000700050002000800070001000900070002000A00090001000B00090002000C000B0001000D000B0002000E000D0001000F000D00020010000F00010011000F0002001200110001001300110002003C001300020042001500020044001700020067001900010068001900020069001B0001006A001B0002006B001D0001006C001D0002006D001F0001006E001F0002006F00210001007000210002007100230001007200230002007300250001007400250002007500270001007600270002008300290002009A002B0001009B002B000200CA0021002C00400081000301E5014C0274028C02540365030480000001000000000000000000000000002F090000040000000000000000000000A003650100000000040000000000000000000000A0038009000000000100000000000000000000000000810D00000000040000000000000000000000A003090100000000040000000000000000000000A003870B00000000040000000000000000000000A003E304000000000C0002000D0002000E0002000F000600430074004700A1004700AF000000003C3E635F5F446973706C6179436C617373305F30003C3E395F5F34325F30003C5365743E625F5F34325F30003C53746F72655175657279526573756C7473446174613E625F5F30003C3E395F5F34325F31003C5365743E625F5F34325F31004E756C6C61626C6560310049456E756D657261626C65603100416374696F6E60310049436F6C6C656374696F6E6031004C697374603100496E7433320046756E636032004B657956616C7565506169726032004944696374696F6E6172796032006765745F55544638003C3E39003C4D6F64756C653E004743004765744B657954544C0053797374656D2E494F0053656E644461746152455350005365744E580076616C75655F5F0053797374656D2E446174610052656164446174610053746F72655175657279526573756C7473446174610053656E644578706563744461746100656E645F64617461006765745F4462007365745F446200466C7573684462006462006D73636F726C6962003C3E63006765745F526F777365744D616769630053797374656D2E436F6C6C656374696F6E732E47656E657269630064624964005265616400416464006765745F436F6E6E6563746564004765744C6173745361766564006964003C50617373776F72643E6B5F5F4261636B696E674669656C64003C436F64653E6B5F5F4261636B696E674669656C64003C44657363656E64696E673E6B5F5F4261636B696E674669656C64003C4765743E6B5F5F4261636B696E674669656C64003C55707065724C696D69743E6B5F5F4261636B696E674669656C64003C4C6F7765724C696D69743E6B5F5F4261636B696E674669656C64003C5265747279436F756E743E6B5F5F4261636B696E674669656C64003C506F72743E6B5F5F4261636B696E674669656C64003C486F73743E6B5F5F4261636B696E674669656C64003C53656E6454696D656F75743E6B5F5F4261636B696E674669656C64003C526574727954696D656F75743E6B5F5F4261636B696E674669656C64003C42793E6B5F5F4261636B696E674669656C64003C4B65793E6B5F5F4261636B696E674669656C64003C53746F7265496E4B65793E6B5F5F4261636B696E674669656C64003C4C65786F67726170686963616C6C793E6B5F5F4261636B696E674669656C6400636D6400616464546F456E640053656E6444617461436F6D6D616E64004462436F6D6D616E640053656E64436F6D6D616E640053716C436F6D6D616E640053656E6400417070656E6400446174614163636573734B696E640069734261636B67726F756E64006765745F50617373776F7264007365745F50617373776F72640070617373776F7264005265706C616365006765745F436F6465007365745F436F646500636F6465006D6573736167650041646452616E6765004C69737452616E67650049456E756D657261626C650049446973706F7361626C6500436F6E736F6C65007469746C6500584E616D65006B65794E65774E616D65006B65794E616D650052656E616D65006F6C644B65796E616D65006E65774B65796E616D65004461746554696D6500546F556E697854696D6500426173654C696E757854696D650074696D6500526561644C696E650057726974654C696E65004E6F6E65007365745F436F6D6D616E64547970650050726F746F636F6C5479706500536F636B657454797065004765744B657954797065004578706972650053797374656D2E436F72650053716C496E7374616C6C657253637269707447656E657261746F724578706F7274656450726F63656475726500436C6F736500446973706F7365005472795061727365005772697465005841747472696275746500436F6D70696C657247656E65726174656441747472696275746500477569644174747269627574650044656275676761626C6541747472696275746500436F6D56697369626C6541747472696275746500417373656D626C795469746C654174747269627574650053716C50726F63656475726541747472696275746500417373656D626C7954726164656D61726B417474726962757465005461726765744672616D65776F726B41747472696275746500436F6E646974696F6E616C41747472696275746500417373656D626C7946696C6556657273696F6E41747472696275746500417373656D626C79436F6E66696775726174696F6E4174747269627574650053716C46756E6374696F6E41747472696275746500417373656D626C794465736372697074696F6E4174747269627574650044656661756C744D656D6265724174747269627574650053716C506172616D6574657241747472696275746500436F6D70696C6174696F6E52656C61786174696F6E7341747472696275746500417373656D626C7950726F6475637441747472696275746500417373656D626C79436F7079726967687441747472696275746500506172616D417272617941747472696275746500417373656D626C79436F6D70616E794174747269627574650052756E74696D65436F6D7061746962696C697479417474726962757465005265616442797465006765745F56616C756500476574537472696E6756616C756500476574536574537472696E6756616C7565004164645769746856616C7565006765745F48617356616C75650047657456616C75650076616C7565004261636B67726F756E6453617665006765745F4C617374536176650054696D65546F4C6976650052656D6F7665006765745F446253697A6500537570707265737346696E616C697A6500547970654F6600496E6465784F66006765745F44657363656E64696E67007365745F44657363656E64696E6700456E636F64696E670053797374656D2E52756E74696D652E56657273696F6E696E670053716C537472696E6700546F537472696E670053656E64457870656374537472696E670053656E64476574537472696E6700537562737472696E6700646973706F73696E67007265706C6163654578697374696E67004E6F744578697374696E67004C6F6700466F724561636800556E697845706F63680048617368004C656674507573680052696768745075736800466C757368006765745F4C656E677468004765744C6973744C656E6774680053746172747357697468006B0076616C00466C757368416C6C005265646953716C2E646C6C00497344424E756C6C00476574436F6C756D6E4D65746164617461586D6C005265646953716C00427566666572656453747265616D004E6574776F726B53747265616D004D656D6F727953747265616D006273747265616D006765745F4974656D007365745F4974656D006974656D0053797374656D005472696D00456E756D0054696D655370616E004F70656E0064657374696E6174696F6E0053657452656C617469766545787069726174696F6E00536574457861637445787069726174696F6E0065787069726174696F6E006F705F5375627472616374696F6E0053797374656D2E5265666C656374696F6E0053716C506172616D65746572436F6C6C656374696F6E004462436F6E6E656374696F6E0053716C436F6E6E656374696F6E005265646973436F6E6E656374696F6E00476574436F6E6E656374696F6E00636F6E6E656374696F6E0053716C496E7374616C6C657253637269707447656E657261746F724578706F7274656446756E6374696F6E006F705F4164646974696F6E00494F457863657074696F6E00417267756D656E744F75744F6652616E6765457863657074696F6E00526573706F6E7365457863657074696F6E00417267756D656E744E756C6C457863657074696F6E00536F636B6574457863657074696F6E00417267756D656E74457863657074696F6E0053797374656D2E446174612E436F6D6D6F6E005265646953716C2E436F6D6D6F6E005265646953716C2E53716C436C72436F6D706F6E656E74732E436F6D6D6F6E00537472696E67436F6D70617269736F6E007061747465726E0053687574646F776E00476574496E666F004C656674506F70005269676874506F7000726573700053797374656D2E586D6C2E4C696E710053797374656D2E4C696E710043686172006D656D626572004462446174615265616465720053716C44617461526561646572004578656375746552656164657200537472696E674275696C64657200476574496E666F5F526F7746696C6C6572004765744C6973744974656D735F526F7746696C6C6572004765744B6579735F526F7746696C6C65720058436F6E7461696E65720053716C506172616D657465720066696C746572004D6963726F736F66742E53716C5365727665722E536572766572002E63746F72002E6363746F720053797374656D2E446961676E6F73746963730053746F7265536574436F6D6D616E6473006765745F546F74616C5365636F6E64730046726F6D5365636F6E6473007365636F6E64730053797374656D2E52756E74696D652E496E7465726F7053657276696365730053797374656D2E52756E74696D652E436F6D70696C6572536572766963657300446562756767696E674D6F6465730053797374656D2E446174612E53716C54797065730053716C436C724465636C61726174696F6E732E41747472696275746573004765744279746573006765745F56616C7565730076616C75657300546F41726773006172677300526564697300457175616C73004461746554696D655574696C73004765744C6973744974656D730053716C436C724465636C61726174696F6E730053797374656D2E436F6C6C656374696F6E73005265646973716C4B6579734D616E6970756C6174696F6E46756E6374696F6E73005265646973716C476C6F62616C53657276657246756E6374696F6E73005265646973716C537472696E6756616C75657346756E6374696F6E7300536F72744F7074696F6E73006F7074696F6E73006765745F4368617273006765745F506172616D65746572730053656E64457870656374537563636573730053746F7265446966666572656E63654F665365747300476574446966666572656E63654F66536574730053746F7265556E696F6E4F665365747300476574556E696F6E4F66536574730053746F7265496E74657273656374696F6E4F665365747300476574496E74657273656374696F6E4F66536574730053797374656D2E4E65742E536F636B657473005265646973716C526F7773657473005265646953716C2E53716C436C72436F6D706F6E656E7473005265646973716C4C6973747300536574537472696E6756616C756549664E6F744578697374730049734B6579457869737473006765745F4B657973004765744B657973006B65797300457870697265417400436F6E636174004F626A65637400436F6E6E6563740064696374006474004D476574006765745F476574007365745F476574004D536574005A53657400506F7052616E646F6D4D656D6265724F665365740047657452616E646F6D4D656D6265724F665365740049734D656D6265724F66536574004765744D656D626572734F665365740043617264696E616C6974794F665365740052656D6F766546726F6D53657400416464546F536574004D6F76654D656D626572546F5365740047657453657400536F636B657400736F636B657400526F77736574006F705F496D706C696369740053706C6974006765745F55707065724C696D6974007365745F55707065724C696D6974006765745F4C6F7765724C696D6974007365745F4C6F7765724C696D69740053656E6444617461457870656374496E740053656E64457870656374496E740053797374656D2E446174612E53716C436C69656E740058456C656D656E740044656372656D656E7400496E6372656D656E74006765745F436F756E74006765745F4669656C64436F756E740047657442797465436F756E74006765745F5265747279436F756E74007365745F5265747279436F756E7400636F756E74007374617274006765745F506F7274007365745F506F727400536F727400706F727400416464546F4C69737400457865637574655175657279416E64476574526573756C744C6973740041727261794C697374006765745F486F7374007365745F486F737400686F7374006765745F53656E6454696D656F7574007365745F53656E6454696D656F7574006765745F526574727954696D656F7574007365745F526574727954696D656F75740053797374656D2E546578740076004765744C6973744974656D4174496E646578004C697374496E64657800696E646578006765745F4279007365745F4279007365745F4E6F44656C61790053656E644578706563744461746141727261790053656E64457870656374537472696E67417272617900546F4172726179006765745F4B6579007365745F4B6579007372634B65790044656C6574654B65790052616E646F6D4B6579006765745F53746F7265496E4B6579007365745F53746F7265496E4B657900436F6E7461696E734B657900646573744B6579006B6579004164647265737346616D696C79006765745F4C65786F67726170686963616C6C79007365745F4C65786F67726170686963616C6C7900436F707900546F44696374696F6E617279007175657279006F705F457175616C6974790049734E756C6C4F72456D70747900000968006F007300740000136C006F00630061006C0068006F0073007400000D530045004C0045004300540000076B0065007900000B760061006C00750065000021760061006C0075006500200065007800630065006500640073002000310047000007530045005400002355006E00610062006C006500200074006F00200063006F006E006E00650063007400000B5300450054004E00580000096400690063007400004F6B00650079007300200061006E0064002000760061006C0075006500730020006D007500730074002000680061007600650020007400680065002000730061006D0065002000730069007A00650000050D000A000003240000032A0000190D000A00240034000D000A004D005300450054000D000A000007470045005400000953004F0052005400000B530054004F0052004500000D470045005400530045005400000941005500540048000003430000053A0020000003200000194E006F0020006D006F0072006500200064006100740061000003530000094500520052002000004555006E006B006E006F0077006E0020007200650070006C00790020006F006E00200069006E0074006500670065007200200072006500710075006500730074003A00200000275A00650072006F0020006C0065006E00670074006800200072006500730070006F0073006500000B2D004500520052002000010724002D003100013D49006E00760061006C006900640020007400650072006D0069006E006100740069006F006E0020006D00690064002000730074007200650061006D00002749006E00760061006C006900640020007400650072006D0069006E006100740069006F006E00001D49006E00760061006C006900640020006C0065006E00670074006800002555006E006500780070006500630074006500640020007200650070006C0079003A002000000D4500580049005300540053000007440045004C0000096100720067007300000949004E0043005200000D49004E00430052004200590000094400450043005200000D4400450043005200420059000009540059005000450000096E006F006E006500000D73007400720069006E006700000773006500740000096C0069007300740000097A0073006500740000096800610073006800001B49006E00760061006C00690064002000760061006C00750065000013520041004E0044004F004D004B004500590000156F006C0064004B00650079006E0061006D00650000156E00650077004B00650079006E0061006D006500000D520045004E0041004D004500000D4500580050004900520045000011450058005000490052004500410054000007540054004C00000D44004200530049005A00450000095300410056004500000D4200470053004100560045000011530048005500540044004F0057004E00001146004C0055005300480041004C004C00000F46004C005500530048004400420000114C004100530054005300410056004500000949004E0046004F00000F7000610074007400650072006E0000094B0045005900530000096B0065007900730000094D00470045005400004155006E006B006E006F0077006E0020007200650070006C00790020006F006E0020006D0075006C00740069002D0072006500710075006500730074003A002000010D4C00520041004E0047004500000B4C005000550053004800000B5200500055005300480000094C004C0045004E00000D4C0049004E0044004500580000094C0050004F0050000009520050004F00500000095300410044004400000B5300430041005200440000135300490053004D0045004D00420045005200001153004D0045004D00420045005200530000175300520041004E0044004D0045004D004200450052000009530050004F00500000095300520045004D00000D530055004E0049004F004E00000763006D0064000017530055004E0049004F004E00530054004F0052004500000D530049004E005400450052000017530049004E00540045005200530054004F0052004500000B53004400490046004600001553004400490046004600530054004F0052004500000B53004D004F005600450000095100550049005400000B4C0049004D0049005400000B41004C005000480041000005420059000080876B00650079002000770069007400680020007400680065002000730061006D00650020006E0061006D006500200061006C007200650061006400790020006500780069007300740073002C00200061006E00640020007200650070006C00610063006500200066006C006100670020006E006F007400200065006E00610062006C0065006400002F63006F006E007400650078007400200063006F006E006E0065006300740069006F006E003D00740072007500650000096900740065006D00000349000039730070005F00640065007300630072006900620065005F00660069007200730074005F0072006500730075006C0074005F0073006500740000097400730071006C00001F43006F006C0075006D006E0073004D006500740061006400610074006100000D43006F006C0075006D006E00000B6F007200640065007200001D63006F006C0075006D006E005F006F007200640069006E0061006C0000096E0061006D006500000F730071006C0054007900700065000021730079007300740065006D005F0074007900700065005F006E0061006D006500001B5200450044004900530051004C0052004F005700530045005400001D52006500730070006F006E007300650020006500720072006F007200000000560591B139EE1E4185920BB5EDA9CF6500042001010803200001052001011111042001010E0420010102052002010E0E0500001280E10520011D050E0D151280850215118089020E0E0E052002011C180E151280850215118089020E0E1D0524100303151279021E011E02151280ED011E0015128085021E001E0115128085021E001E020C0A0315118089020E0E0E1D0507151259020E1D05092000151280F10113000D1001011D1E00151280ED011E00030A010E092000151280F1011301040A011D051107081D05125D081D051D051D051D051D050600030E1C1C1C0500020E0E0E072003011D0508080420001D050407011D050520010E1D05050702081D1C040001020E0C0005011280FD081280FD0808021D05050702126508052001126503032000080320000E0C200301118101118105118109052002010E080320000205200101124D072002011280F9080807050E081D1C0E080600030E0E0E0E0500010E1D1C042001080E0507021D0502052001081D050B07070E1D05081D1C0E08020520020E0E0E040001010E050703080E03042001020E0420010E08060704080E0308060002020E10080807050E081D0508080420010308050002020E0E072003081D0508080307010E03070108042001010A0600011180BD0D090002117511751180BD0F07061D05151279020E0E1D0E080E0806151279020E0E0620011D0E1D0304200108030520020E080807200201130013010807031D1D051D0E080A0706080E03081D1D0508040001011C05070112808D042001081C0420001D1C070702120812809D0600011180B10E05070212080E07070212081180BD08151180AD011180BD04200013000320000D0507021208080F0704123C151280C1010E12081180BD06151280C1010E0520010113000A200101151280ED011300061512811D010E0A2001011512811D011300150706151280C1010E1280C51280C91280CD1280D108072002010E1280C50520001280CD0600011281250E0620010112812504200102080500020E1C1C0420011C08072002011281251C042001011C0C07041280C91280D11280CD0E0620010111813505200012813907200212813D0E1C0420011C0E082002011281251D1C0907041208021180BD0208070312081180BD0E0507021208020907041208113011100E072002020E1181450B0703120808151180AD010806151180AD010809070115118089020E0E0715118089020E0E04200013010407011208060702120811750507011180BD0900021180BD11751175062003010808080A0701151180AD011180BD08B77A5C561934E089080080B5F7F57F9F080400000000040100000004020000000403000000040400000004050000000306124D0306125102060E02060803061D0502060A020602030611100306117503061130030612380E06151280850215118089020E0E0E0F06151280850215118089020E0E1D050706151180AD01080420010E0E062002010E1D05052002020E0E062002020E1D0509200101151259020E0E0A200101151259020E1D05082002011D0E1D1D050720011D1D05120C0920031D1D050E0E1D1C0720021D050E1D05082003021D050E1D1C062002021D050E062002020E1D1C062002010E1D1C082003081D050E1D1C062002080E1D1C0620020E0E1D1C0720021D050E1D1C052001081D0E052002080E0805200111300E052002020E080420001175082000151279020E0E0420001D0E0520011D0E0E0720011D1D051D0E0720021D0E0E1D1C0820021D1D050E1D1C0820031D1D050E08080620021D050E080620011D1D050E062002010E1D0E052001011D0E072003020E0E1D0511000712809D0E080E151180AD01080E0808080002011C101180B10E00060E0E080E151180AD01080E080D00050E0E080E151180AD01080E170008010E080E151180AD01080E0E02151180AD011180BD0D0005080E080E151180AD01080E170008010E080E151180AD01080E0E151180AD011180BD02090001151280C1010E0E0700020E1280C50E0300000E160007010E080E151180AD01080E0E151180AD011180BD160007020E080E151180AD01080E0E151180AD011180BD1600070E0E080E151180AD01080E0E151180AD011180BD0D0005020E080E151180AD01080E0E0006020E080E151180AD01080E0E100006020E080E151180AD01080E1180BD0F0006020E080E151180AD01080E1175120005151180AD01080E080E151180AD01080E0F000512809D0E080E151180AD01080E0E000412809D0E080E151180AD01080C0003011C101180B1101180B10D0005010E080E151180AD0108020C0004010E080E151180AD01080D000411750E080E151180AD01080D000412080E080E151180AD01080500010D1175030000010A20010E15118089020E0E0B20011D0515118089020E0E0328000E032800080428010E0E04280011750428001D0E032800020308000E0801000800000000001E01000100540216577261704E6F6E457863657074696F6E5468726F7773010801000200000000000C0100075265646953716C000005010000000017010012436F7079726967687420C2A920203230313500002901002436363666653462372D306136622D343464662D623137392D63333934323334653333646500000C010007312E302E302E3000004701001A2E4E45544672616D65776F726B2C56657273696F6E3D76342E300100540E144672616D65776F726B446973706C61794E616D65102E4E4554204672616D65776F726B20340A010005444542554700001901000C4765744C6973744974656D73077265646973716C000080F3010004005455794D6963726F736F66742E53716C5365727665722E5365727665722E446174614163636573734B696E642C2053797374656D2E446174612C2056657273696F6E3D342E302E302E302C2043756C747572653D6E65757472616C2C205075626C69634B6579546F6B656E3D623737613563353631393334653038390A446174614163636573730000000054020F497344657465726D696E697374696300540E1146696C6C526F774D6574686F644E616D65164765744C6973744974656D735F526F7746696C6C6572540E0F5461626C65446566696E6974696F6E1356616C7565206E76617263686172286D617829200100134765744C6973744974656D734174496E646578077265646973716C000080A2010002005455794D6963726F736F66742E53716C5365727665722E5365727665722E446174614163636573734B696E642C2053797374656D2E446174612C2056657273696F6E3D342E302E302E302C2043756C747572653D6E65757472616C2C205075626C69634B6579546F6B656E3D623737613563353631393334653038390A446174614163636573730000000054020F497344657465726D696E6973746963001801000B4C6973744C656674506F70077265646973716C00001901000C4C6973745269676874506F70077265646973716C000016010009416464546F4C697374077265646973716C00001A01000D4765744C6973744C656E677468077265646973716C00002201001553746F72655175657279526573756C747344617461077265646973716C00001B01000E536574537472696E6756616C7565077265646973716C000026010019536574537472696E6756616C756549664E6F74457869737473077265646973716C00001E010011476574536574537472696E6756616C7565077265646973716C00001B01000E476574537472696E6756616C7565077265646973716C00001801000B49734B6579457869737473077265646973716C00001701000A4765744B657954797065077265646973716C00001601000952656E616D654B6579077265646973716C00002201001553657452656C617469766545787069726174696F6E077265646973716C00001F010012536574457861637445787069726174696F6E077265646973716C0000160100094765744B657954544C077265646973716C00001601000944656C6574654B6579077265646973716C0000140100074765744B657973077265646973716C000080F0010004005455794D6963726F736F66742E53716C5365727665722E5365727665722E446174614163636573734B696E642C2053797374656D2E446174612C2056657273696F6E3D342E302E302E302C2043756C747572653D6E65757472616C2C205075626C69634B6579546F6B656E3D623737613563353631393334653038390A446174614163636573730000000054020F497344657465726D696E697374696300540E1146696C6C526F774D6574686F644E616D65114765744B6579735F526F7746696C6C6572540E0F5461626C65446566696E6974696F6E154B65794E616D65206E7661726368617228353132291A01000D476574536572766572496E666F077265646973716C00008105010004005455794D6963726F736F66742E53716C5365727665722E5365727665722E446174614163636573734B696E642C2053797374656D2E446174612C2056657273696F6E3D342E302E302E302C2043756C747572653D6E65757472616C2C205075626C69634B6579546F6B656E3D623737613563353631393334653038390A446174614163636573730000000054020F497344657465726D696E697374696300540E1146696C6C526F774D6574686F644E616D6511476574496E666F5F526F7746696C6C6572540E0F5461626C65446566696E6974696F6E2A4B65794E616D65206E7661726368617228353132292C2056616C7565206E76617263686172286D6178291801000B536176654368616E676573077265646973716C000012010005466C757368077265646973716C00001901000C4765744C6173745361766564077265646973716C0000090100044974656D0000190100010054510C44656661756C7456616C75650E04363337396F0100010054510C44656661756C7456616C7565505A53797374656D2E44424E756C6C2C206D73636F726C69622C2056657273696F6E3D342E302E302E302C2043756C747572653D6E65757472616C2C205075626C69634B6579546F6B656E3D62373761356335363139333465303839180100010054510C44656661756C7456616C75650800000000180100010054510C44656661756C7456616C756508FFFFFFFF150100010054510C44656661756C7456616C75650201150100010054510C44656661756C7456616C75650200160100010054510C44656661756C7456616C75650E012A00000000000000C1A34456000000000200000057000000108C0000106E0000525344534FBA35F2B2B0214FB24683367CCDFA5001000000633A5C50726F6A656374735C5265646953514C43616368655C526564697353716C43616368655C6F626A5C52656C656173655C5265646953716C2E706462008F8C00000000000000000000A98C00000020000000000000000000000000000000000000000000009B8C0000000000000000000000005F436F72446C6C4D61696E006D73636F7265652E646C6C000000000000FF2500200010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100100000001800008000000000000000000000000000000100010000003000008000000000000000000000000000000100000000004800000058A000000C03000000000000000000000C0334000000560053005F00560045005200530049004F004E005F0049004E0046004F0000000000BD04EFFE00000100000001000000000000000100000000003F000000000000000400000002000000000000000000000000000000440000000100560061007200460069006C00650049006E0066006F00000000002400040000005400720061006E0073006C006100740069006F006E00000000000000B0046C020000010053007400720069006E006700460069006C00650049006E0066006F0000004802000001003000300030003000300034006200300000001A000100010043006F006D006D0065006E007400730000000000000022000100010043006F006D00700061006E0079004E0061006D0065000000000000000000380008000100460069006C0065004400650073006300720069007000740069006F006E00000000005200650064006900530071006C000000300008000100460069006C006500560065007200730069006F006E000000000031002E0030002E0030002E003000000038000C00010049006E007400650072006E0061006C004E0061006D00650000005200650064006900530071006C002E0064006C006C0000004800120001004C006500670061006C0043006F007000790072006900670068007400000043006F0070007900720069006700680074002000A90020002000320030003100350000002A00010001004C006500670061006C00540072006100640065006D00610072006B007300000000000000000040000C0001004F0072006900670069006E0061006C00460069006C0065006E0061006D00650000005200650064006900530071006C002E0064006C006C000000300008000100500072006F0064007500630074004E0061006D006500000000005200650064006900530071006C000000340008000100500072006F006400750063007400560065007200730069006F006E00000031002E0030002E0030002E003000000038000800010041007300730065006D0062006C0079002000560065007200730069006F006E00000031002E0030002E0030002E0030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000C000000BC3C00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
26 | WITH PERMISSION_SET = UNSAFE
27 |
28 |
29 | GO
30 | CREATE PROCEDURE redisql.AddToList(@host nvarchar(4000), @port int=6379, @password nvarchar(4000)=null, @dbId int=null, @key nvarchar(4000), @value nvarchar(4000), @addToEnd bit=0, @expiration time=null)
31 | AS EXTERNAL NAME[RediSql].[RediSql.SqlClrComponents.RedisqlLists].[AddToList]
32 | GO
33 |
34 |
35 | GO
36 | CREATE FUNCTION redisql.DeleteKey(@host nvarchar(4000), @port int=6379, @password nvarchar(4000)=null, @dbId int=null, @key nvarchar(4000))
37 | RETURNS bit
38 | AS EXTERNAL NAME[RediSql].[RediSql.SqlClrComponents.RedisqlKeysManipulationFunctions].[DeleteKey]
39 | GO
40 |
41 |
42 | GO
43 | CREATE PROCEDURE redisql.Flush(@host nvarchar(4000), @port int=6379, @password nvarchar(4000)=null, @dbId int=null)
44 | AS EXTERNAL NAME[RediSql].[RediSql.SqlClrComponents.RedisqlGlobalServerFunctions].[Flush]
45 | GO
46 |
47 |
48 | GO
49 | CREATE FUNCTION redisql.GetServerInfo(@host nvarchar(4000), @port int=6379, @password nvarchar(4000)=null, @dbId int=null)
50 | RETURNS table(KeyName nvarchar(512), Value nvarchar(max))
51 | AS EXTERNAL NAME[RediSql].[RediSql.SqlClrComponents.RedisqlGlobalServerFunctions].[GetInfo]
52 | GO
53 |
54 |
55 | GO
56 | CREATE FUNCTION redisql.GetKeys(@host nvarchar(4000), @port int=6379, @password nvarchar(4000)=null, @dbId int=null, @filter nvarchar(4000)='*')
57 | RETURNS table(KeyName nvarchar(512))
58 | AS EXTERNAL NAME[RediSql].[RediSql.SqlClrComponents.RedisqlKeysManipulationFunctions].[GetKeys]
59 | GO
60 |
61 |
62 | GO
63 | CREATE FUNCTION redisql.GetKeyTTL(@host nvarchar(4000), @port int=6379, @password nvarchar(4000)=null, @dbId int=null, @key nvarchar(4000))
64 | RETURNS int
65 | AS EXTERNAL NAME[RediSql].[RediSql.SqlClrComponents.RedisqlKeysManipulationFunctions].[GetKeyTTL]
66 | GO
67 |
68 |
69 | GO
70 | CREATE FUNCTION redisql.GetKeyType(@host nvarchar(4000), @port int=6379, @password nvarchar(4000)=null, @dbId int=null, @key nvarchar(4000))
71 | RETURNS nvarchar(4000)
72 | AS EXTERNAL NAME[RediSql].[RediSql.SqlClrComponents.RedisqlKeysManipulationFunctions].[GetKeyType]
73 | GO
74 |
75 |
76 | GO
77 | CREATE FUNCTION redisql.GetLastSaved(@host nvarchar(4000), @port int=6379, @password nvarchar(4000)=null, @dbId int=null)
78 | RETURNS datetime2
79 | AS EXTERNAL NAME[RediSql].[RediSql.SqlClrComponents.RedisqlGlobalServerFunctions].[GetLastSaved]
80 | GO
81 |
82 |
83 | GO
84 | CREATE FUNCTION redisql.GetListItemsAtIndex(@host nvarchar(4000), @port int=6379, @password nvarchar(4000)=null, @dbId int=null, @key nvarchar(4000), @index int)
85 | RETURNS nvarchar(4000)
86 | AS EXTERNAL NAME[RediSql].[RediSql.SqlClrComponents.RedisqlLists].[GetListItemAtIndex]
87 | GO
88 |
89 |
90 | GO
91 | CREATE FUNCTION redisql.GetListItems(@host nvarchar(4000), @port int=6379, @password nvarchar(4000)=null, @dbId int=null, @key nvarchar(4000), @start int=0, @end int=-1)
92 | RETURNS table(Value nvarchar(max))
93 | AS EXTERNAL NAME[RediSql].[RediSql.SqlClrComponents.RedisqlLists].[GetListItems]
94 | GO
95 |
96 |
97 | GO
98 | CREATE FUNCTION redisql.GetListLength(@host nvarchar(4000), @port int=6379, @password nvarchar(4000)=null, @dbId int=null, @key nvarchar(4000))
99 | RETURNS int
100 | AS EXTERNAL NAME[RediSql].[RediSql.SqlClrComponents.RedisqlLists].[GetListLength]
101 | GO
102 |
103 |
104 | GO
105 | CREATE FUNCTION redisql.GetSetStringValue(@host nvarchar(4000), @port int=6379, @password nvarchar(4000)=null, @dbId int=null, @key nvarchar(4000), @value nvarchar(4000), @expiration time=null)
106 | RETURNS nvarchar(4000)
107 | AS EXTERNAL NAME[RediSql].[RediSql.SqlClrComponents.RedisqlStringValuesFunctions].[GetSetStringValue]
108 | GO
109 |
110 |
111 | GO
112 | CREATE FUNCTION redisql.GetStringValue(@host nvarchar(4000), @port int=6379, @password nvarchar(4000)=null, @dbId int=null, @key nvarchar(4000))
113 | RETURNS nvarchar(4000)
114 | AS EXTERNAL NAME[RediSql].[RediSql.SqlClrComponents.RedisqlStringValuesFunctions].[GetStringValue]
115 | GO
116 |
117 |
118 | GO
119 | CREATE FUNCTION redisql.IsKeyExists(@host nvarchar(4000), @port int=6379, @password nvarchar(4000)=null, @dbId int=null, @key nvarchar(4000))
120 | RETURNS bit
121 | AS EXTERNAL NAME[RediSql].[RediSql.SqlClrComponents.RedisqlKeysManipulationFunctions].[IsKeyExists]
122 | GO
123 |
124 |
125 | GO
126 | CREATE FUNCTION redisql.ListLeftPop(@host nvarchar(4000), @port int=6379, @password nvarchar(4000)=null, @dbId int=null, @key nvarchar(4000))
127 | RETURNS nvarchar(4000)
128 | AS EXTERNAL NAME[RediSql].[RediSql.SqlClrComponents.RedisqlLists].[LeftPop]
129 | GO
130 |
131 |
132 | GO
133 | CREATE FUNCTION redisql.RenameKey(@host nvarchar(4000), @port int=6379, @password nvarchar(4000)=null, @dbId int=null, @key nvarchar(4000), @keyNewName nvarchar(4000))
134 | RETURNS bit
135 | AS EXTERNAL NAME[RediSql].[RediSql.SqlClrComponents.RedisqlKeysManipulationFunctions].[Rename]
136 | GO
137 |
138 |
139 | GO
140 | CREATE FUNCTION redisql.ListRightPop(@host nvarchar(4000), @port int=6379, @password nvarchar(4000)=null, @dbId int=null, @key nvarchar(4000))
141 | RETURNS nvarchar(4000)
142 | AS EXTERNAL NAME[RediSql].[RediSql.SqlClrComponents.RedisqlLists].[RightPop]
143 | GO
144 |
145 |
146 | GO
147 | CREATE PROCEDURE redisql.SaveChanges(@host nvarchar(4000), @port int=6379, @password nvarchar(4000)=null, @dbId int=null, @isBackground bit=0)
148 | AS EXTERNAL NAME[RediSql].[RediSql.SqlClrComponents.RedisqlGlobalServerFunctions].[Save]
149 | GO
150 |
151 |
152 | GO
153 | CREATE FUNCTION redisql.SetExactExpiration(@host nvarchar(4000), @port int=6379, @password nvarchar(4000)=null, @dbId int=null, @key nvarchar(4000), @expiration datetime2)
154 | RETURNS bit
155 | AS EXTERNAL NAME[RediSql].[RediSql.SqlClrComponents.RedisqlKeysManipulationFunctions].[SetExactExpiration]
156 | GO
157 |
158 |
159 | GO
160 | CREATE FUNCTION redisql.SetRelativeExpiration(@host nvarchar(4000), @port int=6379, @password nvarchar(4000)=null, @dbId int=null, @key nvarchar(4000), @expiration time)
161 | RETURNS bit
162 | AS EXTERNAL NAME[RediSql].[RediSql.SqlClrComponents.RedisqlKeysManipulationFunctions].[SetRelativeExpiration]
163 | GO
164 |
165 |
166 | GO
167 | CREATE PROCEDURE redisql.SetStringValue(@host nvarchar(4000), @port int=6379, @password nvarchar(4000)=null, @dbId int=null, @key nvarchar(4000), @value nvarchar(4000), @expiration time=null)
168 | AS EXTERNAL NAME[RediSql].[RediSql.SqlClrComponents.RedisqlStringValuesFunctions].[SetStringValue]
169 | GO
170 |
171 |
172 | GO
173 | CREATE FUNCTION redisql.SetStringValueIfNotExists(@host nvarchar(4000), @port int=6379, @password nvarchar(4000)=null, @dbId int=null, @key nvarchar(4000), @value nvarchar(4000), @expiration time=null)
174 | RETURNS bit
175 | AS EXTERNAL NAME[RediSql].[RediSql.SqlClrComponents.RedisqlStringValuesFunctions].[SetStringValueIfNotExists]
176 | GO
177 |
178 |
179 | GO
180 | CREATE PROCEDURE redisql.StoreQueryResultsData(@host nvarchar(4000), @port int=6379, @password nvarchar(4000)=null, @dbId int=null, @key nvarchar(4000), @query nvarchar(4000), @expiration time=null, @replaceExisting bit=1)
181 | AS EXTERNAL NAME[RediSql].[RediSql.SqlClrComponents.RedisqlRowsets].[StoreQueryResultsData]
182 | GO
183 |
184 |
185 | GO
186 |
187 | SET ANSI_NULLS ON
188 | GO
189 | SET QUOTED_IDENTIFIER ON
190 | GO
191 |
192 | CREATE PROCEDURE redisql.GetStoredRowset
193 | @host nvarchar(250), @port int = 6379, @password nvarchar(100) = null, @dbId int = null, @key nvarchar(256)
194 | AS
195 |
196 | BEGIN
197 | SET NOCOUNT ON;
198 |
199 | IF OBJECT_ID('tempdb..#items') IS NOT NULL DROP TABLE #items
200 |
201 | CREATE TABLE #items(val nvarchar(max))
202 | INSERT INTO #items(val)
203 | SELECT Value
204 | FROM redisql.GetListItems(@host, @port, @password, @dbId, @key, default, default)
205 |
206 | IF (SELECT COUNT(*) FROM #items) = 0
207 | BEGIN
208 | SELECT NULL
209 | RETURN -1
210 | END
211 |
212 | DELETE TOP (1)
213 | FROM #items
214 |
215 | DECLARE @metadataXml xml = (SELECT TOP 1 cast(val as xml) FROM #items)
216 | DELETE TOP (1)
217 | FROM #items
218 |
219 | DECLARE @columnsMetadata table(Seq int, Name nvarchar(250), DataType varchar(100))
220 | INSERT INTO @columnsMetadata(Seq, Name, DataType)
221 | SELECT col.value('(@order)[1]', 'nvarchar(max)'),
222 | col.value('(@name)[1]', 'nvarchar(max)'),
223 | col.value('(@sqlType)[1]', 'nvarchar(max)')
224 | FROM @metadataXml.nodes('/ColumnsMetadata/Column') as columns(col)
225 |
226 | DECLARE @dynamicSelectors nvarchar(max)
227 | SELECT @dynamicSelectors =COALESCE(@dynamicSelectors + ', ', '') + 'T.C.value(''/item[1]/I' +CAST(Seq as varchar(10)) +'[1]'', ''' + DataType + ''') ' + Name
228 | FROM @columnsMetadata
229 | ORDER BY Seq
230 |
231 | DECLARE @sql nvarchar(max) =
232 | '
233 | SELECT o.*
234 | FROM #items
235 | OUTER APPLY (
236 | SELECT CAST(val as xml) xmlData
237 | ) rowXml
238 | OUTER APPLY (
239 | SELECT TOP 1 dataColumns.*
240 | FROM rowXml.xmlData.nodes(''/item/*'') as T(C)
241 | OUTER APPLY (
242 | SELECT ' + @dynamicSelectors + '
243 | ) dataColumns
244 | ) o
245 | '
246 | EXECUTE(@sql)
247 | RETURN (SELECT COUNT(*) FROM #items)
248 | END
249 |
250 | GO
251 | GO
252 |
253 | CREATE PROCEDURE [redisql].[ConvertXmlToRowset]
254 | (
255 | @input xml
256 | )
257 | AS
258 | BEGIN
259 | IF OBJECT_ID('tempdb..#dataToPivot') IS NOT NULL DROP TABLE #dataToPivot
260 |
261 | CREATE TABLE #dataToPivot (BatchID uniqueidentifier, KeyName nvarchar(max), Value nvarchar(max))
262 | INSERT INTO #dataToPivot(BatchID, KeyName, Value)
263 |
264 | SELECT rowXml.ID,
265 | keyValueSet.Name,
266 | keyValueSet.Value
267 | FROM @input.nodes('/items/item') T(c)
268 | OUTER APPLY (
269 | SELECT CAST(T.c.query('.') as xml) xmlData,
270 | NEWID() id
271 | ) rowXml
272 | OUTER APPLY (
273 | SELECT
274 | C.Name,
275 | C.Value
276 | FROM rowXml.xmlData.nodes('/item/*') as T(C)
277 | OUTER APPLY (
278 | SELECT
279 | T.C.value('local-name(.)', 'nvarchar(max)') as Name,
280 | T.C.value('(./text())[1]', 'nvarchar(max)') as Value
281 | UNION ALL
282 | SELECT
283 | A.C.value('local-name(.)', 'nvarchar(max)') as Name,
284 | A.C.value('.', 'nvarchar(max)') as Value
285 | FROM T.C.nodes('@*') as A(C)
286 | ) as C
287 | where C.Value is not null
288 | ) keyValueSet
289 |
290 | DECLARE @colsNames NVARCHAR(2000)
291 | SELECT @colsNames =COALESCE(@colsNames + ', ', '') + '[' +KeyName + ']'
292 | FROM #dataToPivot
293 | GROUP BY KeyName
294 | DECLARE @query NVARCHAR(4000)
295 |
296 | SET @query = N' SELECT '+
297 | @colsNames +'
298 | FROM
299 | (
300 | SELECT t2.BatchID
301 | ,t1.KeyName
302 | ,t1.Value
303 | FROM #dataToPivot AS t1
304 | JOIN #dataToPivot AS t2 ON t1.BatchID = t2.BatchID
305 | ) p
306 | PIVOT (
307 | MAX([Value])
308 | FOR KeyName IN ( '+@colsNames +' )
309 | ) AS pvt
310 | ORDER BY BatchID;'
311 | EXECUTE(@query)
312 |
313 | END
314 |
315 |
316 | GO
317 |
318 | SET ANSI_NULLS ON
319 | GO
320 | SET QUOTED_IDENTIFIER ON
321 | GO
322 | CREATE PROCEDURE redisql.GetSetStoredRowset
323 | @key nvarchar(250),
324 | @host nvarchar(50),
325 | @port int = 6379,
326 | @password nvarchar(50) = null,
327 | @dbId int = null,
328 | @expiration time = null,
329 | @query nvarchar(max)
330 | AS
331 | BEGIN
332 | SET NOCOUNT ON;
333 |
334 | IF (redisql.GetKeyType(@host, @port, @password, @dbId, @key) = 'Rowset')
335 | BEGIN
336 | IF (@expiration IS NOT NULL)
337 | BEGIN
338 | SELECT redisql.SetRelativeExpiration(@host, @port, @password, @dbId, @key, @expiration)
339 | END
340 | DECLARE @numberOfRows int
341 | EXECUTE @numberOfRows = redisql.GetStoredRowset @host, @port, @password, @dbId, @key
342 | RETURN @numberOfRows
343 | END
344 | ELSE
345 | BEGIN
346 | EXECUTE redisql.StoreQueryResultsData @host, @port, @password, @dbId, @key, @query, @expiration
347 | EXEC sp_executesql @query
348 | RETURN -1
349 | END
350 | END
351 | GO
352 |
353 |
354 | sp_configure 'show advanced options', 1;
355 | GO
356 | RECONFIGURE;
357 | GO
358 | sp_configure 'clr enabled', 1;
359 | GO
360 | RECONFIGURE;
361 | GO
362 |
--------------------------------------------------------------------------------
/RedisSqlCache/Deployment/LICENSE.txt:
--------------------------------------------------------------------------------
1 | RediSql provided under MIT license.
2 | ---------------------------------------
3 |
4 | Copyright (c) 2015 Shahar Gvirtz
5 |
6 |
7 |
8 | Permission is hereby granted, free of charge, to any person obtaining a copy
9 | of this software and associated documentation files (the "Software"), to deal
10 | in the Software without restriction, including without limitation the rights
11 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | copies of the Software, and to permit persons to whom the Software is
13 | furnished to do so, subject to the following conditions:
14 |
15 |
16 |
17 | The above copyright notice and this permission notice shall be included in
18 | all copies or substantial portions of the Software.
19 |
20 |
21 |
22 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
28 | THE SOFTWARE.
29 |
30 |
--------------------------------------------------------------------------------
/RedisSqlCache/Deployment/Readme.txt:
--------------------------------------------------------------------------------
1 | ---------------------------------
2 | RediSql - T-SQL client for Redis
3 | ---------------------------------
4 |
5 | README
6 |
7 | * RediSql provided as-is, with no guaranees at all. It's your responsibility to take all the necessary precautions before installing it.
8 | * RediSql installation is fairly simple:
9 | 1. Copy all text from install.sql to text editor (SQL Server Management Studio recommended)
10 | 2. Change the first line - replace "check1" with your DB name
11 | 3. Make sure you run the script on the DB you want it, either by using sqlcmd and using the "-d" flag, or by choosing the DB name from
12 | the combo box in SSMS
13 | 4. Execute the statements.
14 |
15 | * How the installation script is going to affect your DB?
16 | - New schema, called "redisql" will created in your DB with the same permissions as the dbo schema
17 | - 2 SQL CLR assemblies will be added to your database
18 | - SQL CLR will be enabled in the server
19 | - Multiple functions and stored procedures will be added, all under "redisql" schema
20 | - (for a full list please refer to the official site, http://redisql.ishahar.net )
21 |
22 | * Where can you get more information?
23 | - Official website: http://redisql.ishahar.net
24 | - GitHub (for the source code): http://github.com/shahargv/redisql
25 |
26 | Hope you'll enjoy RediSql :)
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/RedisSqlCache/Deployment/Uninstall.sql:
--------------------------------------------------------------------------------
1 | --RediSql - Redis client for T-SQL
2 | --For installation instructions and other information, please visit http://redisql.ishahar.net
3 |
4 | --REMEMBER: make sure you run this query on the correct database!
5 | DROP PROCEDURE redisql.AddToList
6 | DROP FUNCTION redisql.DeleteKey
7 | DROP PROCEDURE redisql.Flush
8 | DROP FUNCTION redisql.GetServerInfo
9 | DROP FUNCTION redisql.GetKeys
10 | DROP FUNCTION redisql.GetKeyTTL
11 | DROP FUNCTION redisql.GetKeyType
12 | DROP FUNCTION redisql.GetLastSaved
13 | DROP FUNCTION redisql.GetListItemsAtIndex
14 | DROP FUNCTION redisql.GetListItems
15 | DROP FUNCTION redisql.GetListLength
16 | DROP FUNCTION redisql.GetSetStringValue
17 | DROP FUNCTION redisql.GetStringValue
18 | DROP FUNCTION redisql.IsKeyExists
19 | DROP FUNCTION redisql.ListLeftPop
20 | DROP FUNCTION redisql.RenameKey
21 | DROP FUNCTION redisql.ListRightPop
22 | DROP PROCEDURE redisql.SaveChanges
23 | DROP FUNCTION redisql.SetExactExpiration
24 | DROP FUNCTION redisql.SetRelativeExpiration
25 | DROP PROCEDURE redisql.SetStringValue
26 | DROP FUNCTION redisql.SetStringValueIfNotExists
27 | DROP PROCEDURE redisql.StoreQueryResultsData
28 | DROP ASSEMBLY [RediSql]
29 |
30 | GO
31 | DROP ASSEMBLY [SqlClrDeclarations]
32 |
33 | GO
34 | DROP PROCEDURE [redisql].[GetStoredRowset]
35 | GO
36 | DROP PROCEDURE [redisql].[ConvertXmlToRowset]
37 | GO
38 | DROP PROCEDURE [redisql].[GetSetStoredRowset]
39 | GO
40 | DROP SCHEMA [redisql]
41 | GO
42 |
--------------------------------------------------------------------------------
/RedisSqlCache/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 | using SqlClrDeclarations.Attributes;
5 |
6 | // General Information about an assembly is controlled through the following
7 | // set of attributes. Change these attribute values to modify the information
8 | // associated with an assembly.
9 | [assembly: AssemblyTitle("RediSql")]
10 | [assembly: AssemblyDescription("")]
11 | [assembly: AssemblyConfiguration("")]
12 | [assembly: AssemblyCompany("")]
13 | [assembly: AssemblyProduct("RediSql")]
14 | [assembly: AssemblyCopyright("Copyright © 2015")]
15 | [assembly: AssemblyTrademark("")]
16 | [assembly: AssemblyCulture("")]
17 |
18 |
19 | // Setting ComVisible to false makes the types in this assembly not visible
20 | // to COM components. If you need to access a type in this assembly from
21 | // COM, set the ComVisible attribute to true on that type.
22 | [assembly: ComVisible(false)]
23 |
24 | // The following GUID is for the ID of the typelib if this project is exposed to COM
25 | [assembly: Guid("666fe4b7-0a6b-44df-b179-c394234e33de")]
26 |
27 | // Version information for an assembly consists of the following four values:
28 | //
29 | // Major Version
30 | // Minor Version
31 | // Build Number
32 | // Revision
33 | //
34 | // You can specify all the values or you can default the Build and Revision Numbers
35 | // by using the '*' as shown below:
36 | // [assembly: AssemblyVersion("1.0.*")]
37 | [assembly: AssemblyVersion("1.0.0.0")]
38 | [assembly: AssemblyFileVersion("1.0.0.0")]
39 |
--------------------------------------------------------------------------------
/RedisSqlCache/RediSql.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {666FE4B7-0A6B-44DF-B179-C394234E33DE}
8 | Library
9 | Properties
10 | RediSql
11 | RediSql
12 | v4.0
13 | 512
14 |
15 |
16 |
17 | true
18 | full
19 | false
20 | bin\Debug\
21 | DEBUG;TRACE
22 | prompt
23 | 4
24 |
25 |
26 | pdbonly
27 | true
28 | bin\Release\
29 | TRACE
30 | prompt
31 | 4
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 | {56c24720-8053-4cf5-8bf8-bae7dba78424}
71 | SqlClrDeclarations
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 | powershell $(ProjectDir)\Scripts\DeploymentScriptsGenerator.ps1 -InstallerTemplatePath $(ProjectDir)\Scripts\InstallerTemplate.txt -UninstallerTemplatePath $(ProjectDir)\Scripts\UninstallTemplate.txt -FinalInstallerScriptPath $(ProjectDir)\Deployment\Install.sql -FinalUninstallerScriptPath $(ProjectDir)\Deployment\Uninstall.sql -SolutionDir $(SolutionDir) -RedisqlBinDir $(TargetDir) -RedisqlProjDir $(ProjectDir)
80 |
81 |
88 |
--------------------------------------------------------------------------------
/RedisSqlCache/RedisSharp/RedisSharp.cs:
--------------------------------------------------------------------------------
1 | //
2 | // redis-sharp.cs: ECMA CLI Binding to the Redis key-value storage system
3 | //
4 | // Authors:
5 | // Miguel de Icaza (miguel@gnome.org)
6 | //
7 | // Copyright 2010 Novell, Inc.
8 | //
9 | // Licensed under the same terms of reddis: new BSD license.
10 | //
11 | #define DEBUG
12 |
13 | using System;
14 | using System.IO;
15 | using System.Collections.Generic;
16 | using System.Net.Sockets;
17 | using System.Text;
18 | using System.Diagnostics;
19 | using System.Linq;
20 |
21 |
22 | public class Redis : IDisposable
23 | {
24 | Socket socket;
25 | BufferedStream bstream;
26 |
27 | public enum KeyType
28 | {
29 | None, String, List, Set,
30 | Hash,
31 | ZSet
32 | }
33 |
34 | public class ResponseException : Exception
35 | {
36 | public ResponseException(string code) : base("Response error")
37 | {
38 | Code = code;
39 | }
40 |
41 | public string Code { get; private set; }
42 | }
43 |
44 | public Redis(string host, int port)
45 | {
46 | if (host == null)
47 | throw new ArgumentNullException("host");
48 |
49 | Host = host;
50 | Port = port;
51 | SendTimeout = -1;
52 | }
53 |
54 | public Redis(string host) : this(host, 6379)
55 | {
56 | }
57 |
58 | public Redis() : this("localhost", 6379)
59 | {
60 | }
61 |
62 | public string Host { get; private set; }
63 | public int Port { get; private set; }
64 | public int RetryTimeout { get; set; }
65 | public int RetryCount { get; set; }
66 | public int SendTimeout { get; set; }
67 | public string Password { get; set; }
68 |
69 | int db;
70 | public int Db
71 | {
72 | get
73 | {
74 | return db;
75 | }
76 |
77 | set
78 | {
79 | db = value;
80 | SendExpectSuccess("SELECT", db);
81 | }
82 | }
83 |
84 | public string this[string key]
85 | {
86 | get { return GetString(key); }
87 | set { Set(key, value); }
88 | }
89 |
90 | public void Set(string key, string value)
91 | {
92 | if (key == null)
93 | throw new ArgumentNullException("key");
94 | if (value == null)
95 | throw new ArgumentNullException("value");
96 |
97 | Set(key, Encoding.UTF8.GetBytes(value));
98 | }
99 |
100 | public void Set(string key, byte[] value)
101 | {
102 | if (key == null)
103 | throw new ArgumentNullException("key");
104 | if (value == null)
105 | throw new ArgumentNullException("value");
106 |
107 | if (value.Length > 1073741824)
108 | throw new ArgumentException("value exceeds 1G", "value");
109 |
110 | if (!SendDataCommand(value, "SET", key))
111 | throw new Exception("Unable to connect");
112 | ExpectSuccess();
113 | }
114 |
115 | public bool SetNX(string key, string value)
116 | {
117 | if (key == null)
118 | throw new ArgumentNullException("key");
119 | if (value == null)
120 | throw new ArgumentNullException("value");
121 |
122 | return SetNX(key, Encoding.UTF8.GetBytes(value));
123 | }
124 |
125 | public bool SetNX(string key, byte[] value)
126 | {
127 | if (key == null)
128 | throw new ArgumentNullException("key");
129 | if (value == null)
130 | throw new ArgumentNullException("value");
131 |
132 | if (value.Length > 1073741824)
133 | throw new ArgumentException("value exceeds 1G", "value");
134 |
135 | return SendDataExpectInt(value, "SETNX", key) > 0 ? true : false;
136 | }
137 |
138 | public void Set(IDictionary dict)
139 | {
140 | if (dict == null)
141 | throw new ArgumentNullException("dict");
142 |
143 | Set(dict.ToDictionary(k => k.Key, v => Encoding.UTF8.GetBytes(v.Value)));
144 | }
145 |
146 | public void Set(IDictionary dict)
147 | {
148 | if (dict == null)
149 | throw new ArgumentNullException("dict");
150 |
151 | MSet(dict.Keys.ToArray(), dict.Values.ToArray());
152 | }
153 |
154 | public void MSet(string[] keys, byte[][] values)
155 | {
156 | if (keys.Length != values.Length)
157 | throw new ArgumentException("keys and values must have the same size");
158 |
159 | byte[] nl = Encoding.UTF8.GetBytes("\r\n");
160 | MemoryStream ms = new MemoryStream();
161 |
162 | for (int i = 0; i < keys.Length; i++)
163 | {
164 | byte[] key = Encoding.UTF8.GetBytes(keys[i]);
165 | byte[] val = values[i];
166 | byte[] kLength = Encoding.UTF8.GetBytes("$" + key.Length + "\r\n");
167 | byte[] k = Encoding.UTF8.GetBytes(keys[i] + "\r\n");
168 | byte[] vLength = Encoding.UTF8.GetBytes("$" + val.Length + "\r\n");
169 | ms.Write(kLength, 0, kLength.Length);
170 | ms.Write(k, 0, k.Length);
171 | ms.Write(vLength, 0, vLength.Length);
172 | ms.Write(val, 0, val.Length);
173 | ms.Write(nl, 0, nl.Length);
174 | }
175 |
176 | SendDataRESP(ms.ToArray(), "*" + (keys.Length * 2 + 1) + "\r\n$4\r\nMSET\r\n");
177 | ExpectSuccess();
178 | }
179 |
180 | public byte[] Get(string key)
181 | {
182 | if (key == null)
183 | throw new ArgumentNullException("key");
184 | return SendExpectData("GET", key);
185 | }
186 |
187 | public string GetString(string key)
188 | {
189 | if (key == null)
190 | throw new ArgumentNullException("key");
191 | var dataBytes = Get(key);
192 | if (dataBytes != null)
193 | return Encoding.UTF8.GetString(dataBytes);
194 | return null;
195 | }
196 |
197 | public byte[][] Sort(SortOptions options)
198 | {
199 | return Sort(options.Key, options.StoreInKey, options.ToArgs());
200 | }
201 |
202 | public byte[][] Sort(string key, string destination, params object[] options)
203 | {
204 | if (key == null)
205 | throw new ArgumentNullException("key");
206 |
207 | int offset = string.IsNullOrEmpty(destination) ? 1 : 3;
208 | object[] args = new object[offset + options.Length];
209 |
210 | args[0] = key;
211 | Array.Copy(options, 0, args, offset, options.Length);
212 | if (offset == 1)
213 | {
214 | return SendExpectDataArray("SORT", args);
215 | }
216 | else
217 | {
218 | args[1] = "STORE";
219 | args[2] = destination;
220 | int n = SendExpectInt("SORT", args);
221 | return new byte[n][];
222 | }
223 | }
224 |
225 | public byte[] GetSet(string key, byte[] value)
226 | {
227 | if (key == null)
228 | throw new ArgumentNullException("key");
229 | if (value == null)
230 | throw new ArgumentNullException("value");
231 |
232 | if (value.Length > 1073741824)
233 | throw new ArgumentException("value exceeds 1G", "value");
234 |
235 | if (!SendDataCommand(value, "GETSET", key))
236 | throw new Exception("Unable to connect");
237 |
238 | return ReadData();
239 | }
240 |
241 | public string GetSet(string key, string value)
242 | {
243 | if (key == null)
244 | throw new ArgumentNullException("key");
245 | if (value == null)
246 | throw new ArgumentNullException("value");
247 | var previousValue = GetSet(key, Encoding.UTF8.GetBytes(value));
248 | if (previousValue != null)
249 | return Encoding.UTF8.GetString(previousValue);
250 | return null;
251 |
252 | }
253 |
254 | string ReadLine()
255 | {
256 | StringBuilder sb = new StringBuilder();
257 | int c;
258 |
259 | while ((c = bstream.ReadByte()) != -1)
260 | {
261 | if (c == '\r')
262 | continue;
263 | if (c == '\n')
264 | break;
265 | sb.Append((char)c);
266 | }
267 | return sb.ToString();
268 | }
269 |
270 | void Connect()
271 | {
272 | socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
273 | socket.NoDelay = true;
274 | socket.SendTimeout = SendTimeout;
275 | socket.Connect(Host, Port);
276 | if (!socket.Connected)
277 | {
278 | socket.Close();
279 | socket = null;
280 | return;
281 | }
282 | bstream = new BufferedStream(new NetworkStream(socket), 16 * 1024);
283 |
284 | if (Password != null)
285 | SendExpectSuccess("AUTH", Password);
286 | }
287 |
288 | byte[] end_data = new byte[] { (byte)'\r', (byte)'\n' };
289 |
290 | bool SendDataCommand(byte[] data, string cmd, params object[] args)
291 | {
292 | string resp = "*" + (1 + args.Length + 1).ToString() + "\r\n";
293 | resp += "$" + cmd.Length + "\r\n" + cmd + "\r\n";
294 | foreach (object arg in args)
295 | {
296 | string argStr = arg.ToString();
297 | int argStrLength = Encoding.UTF8.GetByteCount(argStr);
298 | resp += "$" + argStrLength + "\r\n" + argStr + "\r\n";
299 | }
300 | resp += "$" + data.Length + "\r\n";
301 |
302 | return SendDataRESP(data, resp);
303 | }
304 |
305 | bool SendDataRESP(byte[] data, string resp)
306 | {
307 | if (socket == null)
308 | Connect();
309 | if (socket == null)
310 | return false;
311 |
312 | byte[] r = Encoding.UTF8.GetBytes(resp);
313 | try
314 | {
315 | Log("C", resp);
316 | socket.Send(r);
317 | if (data != null)
318 | {
319 | socket.Send(data);
320 | socket.Send(end_data);
321 | }
322 | }
323 | catch (SocketException)
324 | {
325 | // timeout;
326 | socket.Close();
327 | socket = null;
328 |
329 | return false;
330 | }
331 | return true;
332 | }
333 |
334 | bool SendCommand(string cmd, params object[] args)
335 | {
336 | if (socket == null)
337 | Connect();
338 | if (socket == null)
339 | return false;
340 |
341 | string resp = "*" + (1 + args.Length).ToString() + "\r\n";
342 | resp += "$" + cmd.Length + "\r\n" + cmd + "\r\n";
343 | foreach (object arg in args)
344 | {
345 | string argStr = arg.ToString();
346 | int argStrLength = Encoding.UTF8.GetByteCount(argStr);
347 | resp += "$" + argStrLength + "\r\n" + argStr + "\r\n";
348 | }
349 |
350 | byte[] r = Encoding.UTF8.GetBytes(resp);
351 | try
352 | {
353 | Log("C", resp);
354 | socket.Send(r);
355 | }
356 | catch (SocketException)
357 | {
358 | // timeout;
359 | socket.Close();
360 | socket = null;
361 |
362 | return false;
363 | }
364 | return true;
365 | }
366 |
367 | [Conditional("DEBUG")]
368 | void Log(string id, string message)
369 | {
370 | Console.WriteLine(id + ": " + message.Trim().Replace("\r\n", " "));
371 | }
372 |
373 | void ExpectSuccess()
374 | {
375 | int c = bstream.ReadByte();
376 | if (c == -1)
377 | throw new ResponseException("No more data");
378 |
379 | string s = ReadLine();
380 | Log("S", (char)c + s);
381 | if (c == '-')
382 | throw new ResponseException(s.StartsWith("ERR ") ? s.Substring(4) : s);
383 | }
384 |
385 | void SendExpectSuccess(string cmd, params object[] args)
386 | {
387 | if (!SendCommand(cmd, args))
388 | throw new Exception("Unable to connect");
389 |
390 | ExpectSuccess();
391 | }
392 |
393 | int SendDataExpectInt(byte[] data, string cmd, params object[] args)
394 | {
395 | if (!SendDataCommand(data, cmd, args))
396 | throw new Exception("Unable to connect");
397 |
398 | int c = bstream.ReadByte();
399 | if (c == -1)
400 | throw new ResponseException("No more data");
401 |
402 | string s = ReadLine();
403 | Log("S", (char)c + s);
404 | if (c == '-')
405 | throw new ResponseException(s.StartsWith("ERR ") ? s.Substring(4) : s);
406 | if (c == ':')
407 | {
408 | int i;
409 | if (int.TryParse(s, out i))
410 | return i;
411 | }
412 | throw new ResponseException("Unknown reply on integer request: " + c + s);
413 | }
414 |
415 | int SendExpectInt(string cmd, params object[] args)
416 | {
417 | if (!SendCommand(cmd, args))
418 | throw new Exception("Unable to connect");
419 |
420 | int c = bstream.ReadByte();
421 | if (c == -1)
422 | throw new ResponseException("No more data");
423 |
424 | string s = ReadLine();
425 | Log("S", (char)c + s);
426 | if (c == '-')
427 | throw new ResponseException(s.StartsWith("ERR ") ? s.Substring(4) : s);
428 | if (c == ':')
429 | {
430 | int i;
431 | if (int.TryParse(s, out i))
432 | return i;
433 | }
434 | throw new ResponseException("Unknown reply on integer request: " + c + s);
435 | }
436 |
437 | string SendExpectString(string cmd, params object[] args)
438 | {
439 | if (!SendCommand(cmd, args))
440 | throw new Exception("Unable to connect");
441 |
442 | int c = bstream.ReadByte();
443 | if (c == -1)
444 | throw new ResponseException("No more data");
445 |
446 | string s = ReadLine();
447 | Log("S", (char)c + s);
448 | if (c == '-')
449 | throw new ResponseException(s.StartsWith("ERR ") ? s.Substring(4) : s);
450 | if (c == '+')
451 | return s;
452 |
453 | throw new ResponseException("Unknown reply on integer request: " + c + s);
454 | }
455 |
456 | //
457 | // This one does not throw errors
458 | //
459 | string SendGetString(string cmd, params object[] args)
460 | {
461 | if (!SendCommand(cmd, args))
462 | throw new Exception("Unable to connect");
463 |
464 | return ReadLine();
465 | }
466 |
467 | byte[] SendExpectData(string cmd, params object[] args)
468 | {
469 | if (!SendCommand(cmd, args))
470 | throw new Exception("Unable to connect");
471 |
472 | return ReadData();
473 | }
474 |
475 | byte[] ReadData()
476 | {
477 | string s = ReadLine();
478 | Log("S", s);
479 | if (s.Length == 0)
480 | throw new ResponseException("Zero length respose");
481 |
482 | char c = s[0];
483 | if (c == '-')
484 | throw new ResponseException(s.StartsWith("-ERR ") ? s.Substring(5) : s.Substring(1));
485 |
486 | if (c == '$')
487 | {
488 | if (s == "$-1")
489 | return null;
490 | int n;
491 |
492 | if (Int32.TryParse(s.Substring(1), out n))
493 | {
494 | byte[] retbuf = new byte[n];
495 |
496 | int bytesRead = 0;
497 | do
498 | {
499 | int read = bstream.Read(retbuf, bytesRead, n - bytesRead);
500 | if (read < 1)
501 | throw new ResponseException("Invalid termination mid stream");
502 | bytesRead += read;
503 | }
504 | while (bytesRead < n);
505 | if (bstream.ReadByte() != '\r' || bstream.ReadByte() != '\n')
506 | throw new ResponseException("Invalid termination");
507 | return retbuf;
508 | }
509 | throw new ResponseException("Invalid length");
510 | }
511 |
512 | /* don't treat arrays here because only one element works -- use DataArray!
513 | //returns the number of matches
514 | if (c == '*') {
515 | int n;
516 | if (Int32.TryParse(s.Substring(1), out n))
517 | return n <= 0 ? new byte [0] : ReadData();
518 |
519 | throw new ResponseException ("Unexpected length parameter" + r);
520 | }
521 | */
522 |
523 | throw new ResponseException("Unexpected reply: " + s);
524 | }
525 |
526 | public bool ContainsKey(string key)
527 | {
528 | if (key == null)
529 | throw new ArgumentNullException("key");
530 | return SendExpectInt("EXISTS", key) == 1;
531 | }
532 |
533 | public bool Remove(string key)
534 | {
535 | if (key == null)
536 | throw new ArgumentNullException("key");
537 | return SendExpectInt("DEL", key) == 1;
538 | }
539 |
540 | public int Remove(params string[] args)
541 | {
542 | if (args == null)
543 | throw new ArgumentNullException("args");
544 | return SendExpectInt("DEL", args);
545 | }
546 |
547 | public int Increment(string key)
548 | {
549 | if (key == null)
550 | throw new ArgumentNullException("key");
551 | return SendExpectInt("INCR", key);
552 | }
553 |
554 | public int Increment(string key, int count)
555 | {
556 | if (key == null)
557 | throw new ArgumentNullException("key");
558 | return SendExpectInt("INCRBY", key, count);
559 | }
560 |
561 | public int Decrement(string key)
562 | {
563 | if (key == null)
564 | throw new ArgumentNullException("key");
565 | return SendExpectInt("DECR", key);
566 | }
567 |
568 | public int Decrement(string key, int count)
569 | {
570 | if (key == null)
571 | throw new ArgumentNullException("key");
572 | return SendExpectInt("DECRBY", key, count);
573 | }
574 |
575 | public KeyType TypeOf(string key)
576 | {
577 | if (key == null)
578 | throw new ArgumentNullException("key");
579 | switch (SendExpectString("TYPE", key))
580 | {
581 | case "none":
582 | return KeyType.None;
583 | case "string":
584 | return KeyType.String;
585 | case "set":
586 | return KeyType.Set;
587 | case "list":
588 | return KeyType.List;
589 | case "zset":
590 | return KeyType.ZSet;
591 | case "hash":
592 | return KeyType.Hash;
593 | }
594 | throw new ResponseException("Invalid value");
595 | }
596 |
597 | public string RandomKey()
598 | {
599 | return SendExpectString("RANDOMKEY");
600 | }
601 |
602 | public bool Rename(string oldKeyname, string newKeyname)
603 | {
604 | if (oldKeyname == null)
605 | throw new ArgumentNullException("oldKeyname");
606 | if (newKeyname == null)
607 | throw new ArgumentNullException("newKeyname");
608 | return SendGetString("RENAME", oldKeyname, newKeyname)[0] == '+';
609 | }
610 |
611 | public bool Expire(string key, int seconds)
612 | {
613 | if (key == null)
614 | throw new ArgumentNullException("key");
615 | return SendExpectInt("EXPIRE", key, seconds) == 1;
616 | }
617 |
618 | public bool ExpireAt(string key, int time)
619 | {
620 | if (key == null)
621 | throw new ArgumentNullException("key");
622 | return SendExpectInt("EXPIREAT", key, time) == 1;
623 | }
624 |
625 | public int TimeToLive(string key)
626 | {
627 | if (key == null)
628 | throw new ArgumentNullException("key");
629 | return SendExpectInt("TTL", key);
630 | }
631 |
632 | public int DbSize
633 | {
634 | get
635 | {
636 | return SendExpectInt("DBSIZE");
637 | }
638 | }
639 |
640 | public void Save()
641 | {
642 | SendExpectSuccess("SAVE");
643 | }
644 |
645 | public void BackgroundSave()
646 | {
647 | SendExpectSuccess("BGSAVE");
648 | }
649 |
650 | public void Shutdown()
651 | {
652 | SendCommand("SHUTDOWN");
653 | try
654 | {
655 | // the server may return an error
656 | string s = ReadLine();
657 | Log("S", s);
658 | if (s.Length == 0)
659 | throw new ResponseException("Zero length respose");
660 | throw new ResponseException(s.StartsWith("-ERR ") ? s.Substring(5) : s.Substring(1));
661 | }
662 | catch (IOException)
663 | {
664 | // this is the expected good result
665 | socket.Close();
666 | socket = null;
667 | }
668 | }
669 |
670 | public void FlushAll()
671 | {
672 | SendExpectSuccess("FLUSHALL");
673 | }
674 |
675 | public void FlushDb()
676 | {
677 | SendExpectSuccess("FLUSHDB");
678 | }
679 |
680 | const long UnixEpoch = 621355968000000000L;
681 |
682 | public DateTime LastSave
683 | {
684 | get
685 | {
686 | int t = SendExpectInt("LASTSAVE");
687 |
688 | return new DateTime(UnixEpoch) + TimeSpan.FromSeconds(t);
689 | }
690 | }
691 |
692 | public Dictionary GetInfo()
693 | {
694 | byte[] r = SendExpectData("INFO");
695 | var dict = new Dictionary();
696 |
697 | foreach (var line in Encoding.UTF8.GetString(r).Split('\n'))
698 | {
699 | int p = line.IndexOf(':');
700 | if (p == -1)
701 | continue;
702 | dict.Add(line.Substring(0, p), line.Substring(p + 1));
703 | }
704 | return dict;
705 | }
706 |
707 | public string[] Keys
708 | {
709 | get
710 | {
711 | return GetKeys("*");
712 | }
713 | }
714 |
715 | public string[] GetKeys(string pattern)
716 | {
717 | if (pattern == null)
718 | throw new ArgumentNullException("pattern");
719 |
720 | return SendExpectStringArray("KEYS", pattern);
721 | }
722 |
723 | public byte[][] MGet(params string[] keys)
724 | {
725 | if (keys == null)
726 | throw new ArgumentNullException("keys");
727 | if (keys.Length == 0)
728 | throw new ArgumentException("keys");
729 |
730 | return SendExpectDataArray("MGET", keys);
731 | }
732 |
733 |
734 | public string[] SendExpectStringArray(string cmd, params object[] args)
735 | {
736 | byte[][] reply = SendExpectDataArray(cmd, args);
737 | string[] keys = new string[reply.Length];
738 | for (int i = 0; i < reply.Length; i++)
739 | keys[i] = Encoding.UTF8.GetString(reply[i]);
740 | return keys;
741 | }
742 |
743 | public byte[][] SendExpectDataArray(string cmd, params object[] args)
744 | {
745 | if (!SendCommand(cmd, args))
746 | throw new Exception("Unable to connect");
747 | int c = bstream.ReadByte();
748 | if (c == -1)
749 | throw new ResponseException("No more data");
750 |
751 | string s = ReadLine();
752 | Log("S", (char)c + s);
753 | if (c == '-')
754 | throw new ResponseException(s.StartsWith("ERR ") ? s.Substring(4) : s);
755 | if (c == '*')
756 | {
757 | int count;
758 | if (int.TryParse(s, out count))
759 | {
760 | byte[][] result = new byte[count][];
761 |
762 | for (int i = 0; i < count; i++)
763 | result[i] = ReadData();
764 |
765 | return result;
766 | }
767 | }
768 | throw new ResponseException("Unknown reply on multi-request: " + c + s);
769 | }
770 |
771 | #region List commands
772 | public byte[][] ListRange(string key, int start, int end)
773 | {
774 | return SendExpectDataArray("LRANGE", key, start, end);
775 | }
776 |
777 | public void LeftPush(string key, string value)
778 | {
779 | LeftPush(key, Encoding.UTF8.GetBytes(value));
780 | }
781 |
782 | public void LeftPush(string key, byte[] value)
783 | {
784 | SendDataCommand(value, "LPUSH", key);
785 | ExpectSuccess();
786 | }
787 |
788 | public void RightPush(string key, string value)
789 | {
790 | RightPush(key, Encoding.UTF8.GetBytes(value));
791 | }
792 |
793 | public void RightPush(string key, byte[] value)
794 | {
795 | SendDataCommand(value, "RPUSH", key);
796 | ExpectSuccess();
797 | }
798 |
799 | public int ListLength(string key)
800 | {
801 | return SendExpectInt("LLEN", key);
802 | }
803 |
804 | public byte[] ListIndex(string key, int index)
805 | {
806 | SendCommand("LINDEX", key, index);
807 | return ReadData();
808 | }
809 |
810 | public byte[] LeftPop(string key)
811 | {
812 | SendCommand("LPOP", key);
813 | return ReadData();
814 | }
815 |
816 | public byte[] RightPop(string key)
817 | {
818 | SendCommand("RPOP", key);
819 | return ReadData();
820 | }
821 | #endregion
822 |
823 | #region Set commands
824 | public bool AddToSet(string key, byte[] member)
825 | {
826 | return SendDataExpectInt(member, "SADD", key) > 0;
827 | }
828 |
829 | public bool AddToSet(string key, string member)
830 | {
831 | return AddToSet(key, Encoding.UTF8.GetBytes(member));
832 | }
833 |
834 | public int CardinalityOfSet(string key)
835 | {
836 | return SendExpectInt("SCARD", key);
837 | }
838 |
839 | public bool IsMemberOfSet(string key, byte[] member)
840 | {
841 | return SendDataExpectInt(member, "SISMEMBER", key) > 0;
842 | }
843 |
844 | public bool IsMemberOfSet(string key, string member)
845 | {
846 | return IsMemberOfSet(key, Encoding.UTF8.GetBytes(member));
847 | }
848 |
849 | public byte[][] GetMembersOfSet(string key)
850 | {
851 | return SendExpectDataArray("SMEMBERS", key);
852 | }
853 |
854 | public byte[] GetRandomMemberOfSet(string key)
855 | {
856 | return SendExpectData("SRANDMEMBER", key);
857 | }
858 |
859 | public byte[] PopRandomMemberOfSet(string key)
860 | {
861 | return SendExpectData("SPOP", key);
862 | }
863 |
864 | public bool RemoveFromSet(string key, byte[] member)
865 | {
866 | return SendDataExpectInt(member, "SREM", key) > 0;
867 | }
868 |
869 | public bool RemoveFromSet(string key, string member)
870 | {
871 | return RemoveFromSet(key, Encoding.UTF8.GetBytes(member));
872 | }
873 |
874 | public byte[][] GetUnionOfSets(params string[] keys)
875 | {
876 | if (keys == null)
877 | throw new ArgumentNullException();
878 |
879 | return SendExpectDataArray("SUNION", keys);
880 |
881 | }
882 |
883 | void StoreSetCommands(string cmd, params string[] keys)
884 | {
885 | if (String.IsNullOrEmpty(cmd))
886 | throw new ArgumentNullException("cmd");
887 |
888 | if (keys == null)
889 | throw new ArgumentNullException("keys");
890 |
891 | SendExpectSuccess(cmd, keys);
892 | }
893 |
894 | public void StoreUnionOfSets(params string[] keys)
895 | {
896 | StoreSetCommands("SUNIONSTORE", keys);
897 | }
898 |
899 | public byte[][] GetIntersectionOfSets(params string[] keys)
900 | {
901 | if (keys == null)
902 | throw new ArgumentNullException();
903 |
904 | return SendExpectDataArray("SINTER", keys);
905 | }
906 |
907 | public void StoreIntersectionOfSets(params string[] keys)
908 | {
909 | StoreSetCommands("SINTERSTORE", keys);
910 | }
911 |
912 | public byte[][] GetDifferenceOfSets(params string[] keys)
913 | {
914 | if (keys == null)
915 | throw new ArgumentNullException();
916 |
917 | return SendExpectDataArray("SDIFF", keys);
918 | }
919 |
920 | public void StoreDifferenceOfSets(params string[] keys)
921 | {
922 | StoreSetCommands("SDIFFSTORE", keys);
923 | }
924 |
925 | public bool MoveMemberToSet(string srcKey, string destKey, byte[] member)
926 | {
927 | return SendDataExpectInt(member, "SMOVE", srcKey, destKey) > 0;
928 | }
929 | #endregion
930 |
931 | public void Dispose()
932 | {
933 | Dispose(true);
934 | GC.SuppressFinalize(this);
935 | }
936 |
937 | ~Redis()
938 | {
939 | Dispose(false);
940 | }
941 |
942 | protected virtual void Dispose(bool disposing)
943 | {
944 | if (disposing)
945 | {
946 | SendCommand("QUIT");
947 | ExpectSuccess();
948 | socket.Close();
949 | socket = null;
950 | }
951 | }
952 | }
953 |
954 | public class SortOptions
955 | {
956 | public string Key { get; set; }
957 | public bool Descending { get; set; }
958 | public bool Lexographically { get; set; }
959 | public Int32 LowerLimit { get; set; }
960 | public Int32 UpperLimit { get; set; }
961 | public string By { get; set; }
962 | public string StoreInKey { get; set; }
963 | public string Get { get; set; }
964 |
965 | public object[] ToArgs()
966 | {
967 | System.Collections.ArrayList args = new System.Collections.ArrayList();
968 |
969 | if (LowerLimit != 0 || UpperLimit != 0)
970 | {
971 | args.Add("LIMIT");
972 | args.Add(LowerLimit);
973 | args.Add(UpperLimit);
974 | }
975 | if (Lexographically)
976 | args.Add("ALPHA");
977 | if (!string.IsNullOrEmpty(By))
978 | {
979 | args.Add("BY");
980 | args.Add(By);
981 | }
982 | if (!string.IsNullOrEmpty(Get))
983 | {
984 | args.Add("GET");
985 | args.Add(Get);
986 | }
987 | return args.ToArray();
988 | }
989 | }
990 |
--------------------------------------------------------------------------------
/RedisSqlCache/Scripts/DeploymentScriptsGenerator.ps1:
--------------------------------------------------------------------------------
1 | param(
2 | [string]$InstallerTemplatePath,
3 | [string]$UninstallerTemplatePath,
4 | [string]$FinalInstallerScriptPath,
5 | [string]$FinalUninstallerScriptPath,
6 | [string]$SolutionDir,
7 | [string]$RedisqlBinDir,
8 | [string]$RedisqlProjDir
9 | )
10 | function ZipFiles( $zipfilename, $sourcedir )
11 | {
12 | Add-Type -Assembly System.IO.Compression.FileSystem
13 | $compressionLevel = [System.IO.Compression.CompressionLevel]::Optimal
14 | [System.IO.Compression.ZipFile]::CreateFromDirectory($sourcedir,
15 | $zipfilename, $compressionLevel, $false)
16 | }
17 |
18 | $sqlScriptsGeneratorPath = [IO.Path]::Combine($SolutionDir, "ScriptGenerator","InstallerScriptGenerator.exe")
19 | Write-Host $sqlScriptsGeneratorPath
20 | $installerTemplateText = [IO.File]::ReadAllText($InstallerTemplatePath)
21 | $tmpInstallerFile = [IO.Path]::GetTempFileName()
22 | [IO.File]::WriteAllText($tmpInstallerFile, $installerTemplateText.Replace("!!!binDir!!!", $RedisqlBinDir).Replace("!!!projDir!!!", $RedisqlProjDir))
23 | write-host $tmpInstallerFile
24 | Start-Process -FilePath $sqlScriptsGeneratorPath -ArgumentList "$tmpInstallerFile $FinalInstallerScriptPath" -Wait
25 |
26 | $uninstallerTemplateText = [IO.File]::ReadAllText($UninstallerTemplatePath)
27 | $tmpUninstallerFile = [IO.Path]::GetTempFileName()
28 | [IO.File]::WriteAllText($tmpUninstallerFile, $uninstallerTemplateText.Replace("!!!binDir!!!", $RedisqlBinDir).Replace("!!!projDir!!!", $RedisqlProjDir))
29 | write-host $tmpUninstallerFile
30 | Start-Process -FilePath $sqlScriptsGeneratorPath -ArgumentList "$tmpUninstallerFile $FinalUninstallerScriptPath" -Wait
--------------------------------------------------------------------------------
/RedisSqlCache/Scripts/InstallerTemplate.txt:
--------------------------------------------------------------------------------
1 | --RediSql - Redis client for T-SQL
2 | --For installation instructions and other information, please visit http://redisql.ishahar.net
3 |
4 | --REMEMBER: make sure you run this query on the correct database!
5 |
6 | DECLARE @dbName nvarchar(50) = '[check1]' --CHANGE HERE TO YOUR DB NAME
7 |
8 | EXEC('ALTER DATABASE ' + @dbname + ' SET TRUSTWORTHY ON')
9 |
10 |
11 | GO
12 | CREATE SCHEMA [redisql] AUTHORIZATION [dbo]
13 | GO
14 | ~~~InstallScript:~~~!!!binDir!!!\SqlClrDeclarations.dll
15 | GO
16 | ~~~InstallScript:~~~!!!binDir!!!\RediSql.dll
17 | GO
18 | ~~~IncludeFile:~~~!!!projDir!!!\TSQLCode\GetStoredRowset.sql
19 | GO
20 | ~~~IncludeFile:~~~!!!projDir!!!\TSQLCode\XmlToRowset.sql
21 | GO
22 | ~~~IncludeFile:~~~!!!projDir!!!\TSQLCode\GetSetStoredRowset.sql
23 |
24 | sp_configure 'show advanced options', 1;
25 | GO
26 | RECONFIGURE;
27 | GO
28 | sp_configure 'clr enabled', 1;
29 | GO
30 | RECONFIGURE;
31 | GO
--------------------------------------------------------------------------------
/RedisSqlCache/Scripts/SanityTest.sql:
--------------------------------------------------------------------------------
1 | --TEST 1 : non existent key test
2 | DECLARE @nonExistentKeyExists bit = [redisql].[IsKeyExists] (
3 | 'localhost'
4 | ,6379
5 | ,default
6 | ,default
7 | ,CAST(NEWID() as varchar(50))
8 | )
9 | IF @nonExistentKeyExists = 1
10 | BEGIN
11 | PRINT 'ERROR: non existent key test'
12 | END
13 | ELSE
14 | BEGIN
15 | PRINT 'success: non existent key test'
16 | END
17 | GO
18 |
19 | --TEST 2: add and remove key
20 | DECLARE @test2KeyName varchar(50) = CAST(NEWID() as varchar(50))
21 | EXEC [redisql].[SetStringValue]
22 | @host = N'localhost',
23 | @port = 6379,
24 | @key = @test2KeyName,
25 | @value = N'gv'
26 | IF (SELECT [redisql].[IsKeyExists] ('localhost',default,default,default,@test2KeyName)) = 0
27 | BEGIN
28 | PRINT 'ERROR (test 2):add key and check if exists'
29 | END
30 | ELSE
31 | BEGIN
32 | PRINT 'success: test 2 - key added successfully'
33 | END
34 |
35 | EXEC [redisql].DeleteKey
36 | @host='localhost',
37 | @key=@test2KeyName
38 | IF (SELECT [redisql].[IsKeyExists] ('localhost',default,default,default,@test2KeyName)) = 0
39 | BEGIN
40 | PRINT 'success (test 2): key removed successfully'
41 | END
42 | ELSE
43 | BEGIN
44 | PRINT 'ERROR: test 2 - key exists after removing'
45 | END
46 | GO
47 | --TEST 3: add key with expiration
48 | DECLARE @test3KeyName varchar(50) = CAST(NEWID() as varchar(50))
49 | EXEC [redisql].[SetStringValue]
50 | @host = N'localhost',
51 | @port = 6379,
52 | @key = @test3KeyName,
53 | @value = N'gv',
54 | @expiration = '00:00:10'
55 | IF (SELECT [redisql].[IsKeyExists] ('localhost',default,default,default,@test3KeyName)) = 0
56 | BEGIN
57 | PRINT 'ERROR:add key with expiration (test 3) - key not exists after adding it'
58 | END
59 | WAITFOR DELAY '00:00:11'
60 | IF (SELECT [redisql].[IsKeyExists] ('localhost',default,default,default,@test3KeyName)) = 1
61 | BEGIN
62 | PRINT 'ERROR:add key with expiration (test 3) - key exists after expiration time'
63 | END
64 | ELSE
65 | BEGIN
66 | PRINT 'success: add key and check if exists with expiration (test 3)'
67 | END
68 | GO
69 | --TEST 4: Check lists
70 | DECLARE @test4KeyName varchar(50) = CAST(NEWID() as varchar(50))
71 | EXEC [redisql].AddToList
72 | @host = N'localhost',
73 | @port = 6379,
74 | @key = @test4KeyName,
75 | @value = N'val1'
76 | EXEC [redisql].AddToList
77 | @host = N'localhost',
78 | @port = 6379,
79 | @key = @test4KeyName,
80 | @value = N'val2'
81 | EXEC [redisql].AddToList
82 | @host = N'localhost',
83 | @port = 6379,
84 | @key = @test4KeyName,
85 | @value = N'val3'
86 | DECLARE @numberOfItemsInResults int = (SELECT COUNT(*) FROM redisql.GetListItems('localhost', default, default, default, @test4KeyName, default, default))
87 | IF @numberOfItemsInResults <> 3
88 | BEGIN
89 | PRINT 'ERROR: lists test (test 4)'
90 | END
91 | ELSE
92 | BEGIN
93 | PRINT 'success: lists test (test 4)'
94 | END
95 | --TEST 5: Rowset storing
96 | DECLARE @test5KeyName varchar(50) = CAST(NEWID() as varchar(50))
97 |
98 | IF OBJECT_ID('tempdb..#test5') IS NOT NULL DROP TABLE #test5
99 | CREATE TABLE #test5(col1 nvarchar(200), col2 varchar(200), col3 nvarchar(max) null, col4 int null)
100 | INSERT INTO #test5(col1, col2, col3, col4) VALUES ('c1val', 'c2val', 'c3val', 9)
101 | INSERT INTO #test5(col1, col2, col3, col4) VALUES ('c1val', 'c2val', null, 90)
102 | INSERT INTO #test5(col1, col2, col3, col4) VALUES ('c1val', 'c2val', 'c3val', 91)
103 | INSERT INTO #test5(col1, col2, col3, col4) VALUES ('c1val', 'c2val', 'c3val', null)
104 | INSERT INTO #test5(col1, col2, col3, col4) VALUES ('c1val', 'c2val', 'c3val', null)
105 | EXEC [redisql].StoreQueryResultsData
106 | @host = N'localhost',
107 | @port = 6379,
108 | @key = @test5KeyName,
109 | @query = N'SELECT * FROM #test5',
110 | @replaceExisting = 1
111 | DECLARE @backFromCache table (col1 nvarchar(200), col2 varchar(200), col3 nvarchar(max) null, col4 int null)
112 | IF OBJECT_ID('tempdb..#test5_b') IS NOT NULL DROP TABLE #test5_b
113 | CREATE TABLE #test5_b(col1 nvarchar(200), col2 varchar(200), col3 nvarchar(max) null, col4 int null)
114 | INSERT INTO #test5_b(col1,col2,col3,col4) EXEC [redisql].[GetStoredRowset] @host = N'localhost', @key =@test5KeyName
115 | IF(SELECT COUNT(*) FROM #test5_b) <> 5
116 | BEGIN
117 | PRINT 'ERROR: rowset test - incorrect number of total returned rows (test5)'
118 | END
119 | ELSE
120 | BEGIN
121 | PRINT 'success: rowset test - correct number of total returned rows (test5)'
122 | END
123 | IF(SELECT COUNT(*) FROM #test5_b WHERE col4 IS NULL) <> 2
124 | BEGIN
125 | PRINT 'ERROR: rowset test - incorrect number of null returned rows (test5)'
126 | END
127 | ELSE
128 | BEGIN
129 | PRINT 'success: rowset test - correct number of null returned rows (test5)'
130 | END
--------------------------------------------------------------------------------
/RedisSqlCache/Scripts/UninstallTemplate.txt:
--------------------------------------------------------------------------------
1 | --RediSql - Redis client for T-SQL
2 | --For installation instructions and other information, please visit http://redisql.ishahar.net
3 |
4 | --REMEMBER: make sure you run this query on the correct database!
5 | ~~~UninstallScript:~~~!!!binDir!!!\RediSql.dll
6 | GO
7 | ~~~UninstallScript:~~~!!!binDir!!!\SqlClrDeclarations.dll
8 | GO
9 | DROP PROCEDURE [redisql].[GetStoredRowset]
10 | GO
11 | DROP PROCEDURE [redisql].[ConvertXmlToRowset]
12 | GO
13 | DROP PROCEDURE [redisql].[GetSetStoredRowset]
14 | GO
15 | DROP SCHEMA [redisql]
16 | GO
17 |
--------------------------------------------------------------------------------
/RedisSqlCache/Scripts/Usage.sql:
--------------------------------------------------------------------------------
1 | SELECT [redisql].[IsKeyExists] (
2 | 'localhost'
3 | ,6379
4 | ,default
5 | ,default
6 | ,'check1'
7 | )
8 |
9 | GO
10 |
11 | EXEC [redisql].[SetStringValue]
12 | @host = N'localhost',
13 | @port = 6379,
14 | @key = N'check1',
15 | @value = N'gv'
16 |
17 |
18 | GO
19 |
20 | SELECT [redisql].[GetStringValue] (
21 | 'localhost'
22 | ,6379
23 | ,default
24 | ,default
25 | ,'check1')
26 |
27 | GO
--------------------------------------------------------------------------------
/RedisSqlCache/SqlClrComponents/Common/RedisConnection.cs:
--------------------------------------------------------------------------------
1 | namespace RediSql.SqlClrComponents.Common
2 | {
3 | internal static class RedisConnection
4 | {
5 | internal static Redis GetConnection(string host, int port, string password = null, int? dbId = null)
6 | {
7 | Redis redis = new Redis(host, port);
8 | if (password != null)
9 | redis.Password = password;
10 | if (dbId != null)
11 | redis.Db = dbId.Value;
12 | return redis;
13 | }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/RedisSqlCache/SqlClrComponents/Enums.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 |
6 | namespace RediSql.SqlClrComponents
7 | {
8 | public enum KeyType
9 | {
10 | NotExisting,
11 | String,
12 | List,
13 | Rowset,
14 | Set,
15 | Hash
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/RedisSqlCache/SqlClrComponents/RedisqlGlobalServerFunctions.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections;
3 | using System.Collections.Generic;
4 | using System.Data.SqlTypes;
5 | using Microsoft.SqlServer.Server;
6 | using RediSql.SqlClrComponents.Common;
7 | using SqlClrDeclarations.Attributes;
8 |
9 | namespace RediSql.SqlClrComponents
10 | {
11 | public static class RedisqlGlobalServerFunctions
12 | {
13 | [SqlInstallerScriptGeneratorExportedFunction("GetServerInfo", "redisql")]
14 | [SqlFunction(DataAccess = DataAccessKind.None, IsDeterministic = false, FillRowMethodName = "GetInfo_RowFiller", TableDefinition = "KeyName nvarchar(512), Value nvarchar(max)")]
15 | public static IEnumerable GetInfo(string host,
16 | [SqlParameter(DefaultValue = "6379")]int port,
17 | [SqlParameter(DefaultValue = typeof(DBNull))]string password,
18 | [SqlParameter(DefaultValue = typeof(DBNull))]int? dbId)
19 | {
20 | using (var redis = RedisConnection.GetConnection(host, port, password, dbId))
21 | {
22 | return redis.GetInfo();
23 | }
24 | }
25 |
26 | public static void GetInfo_RowFiller(object item, out SqlString title, out SqlString value)
27 | {
28 | var settingRow = (KeyValuePair)item;
29 | title = settingRow.Key;
30 | value = settingRow.Value;
31 | }
32 |
33 | [SqlInstallerScriptGeneratorExportedProcedure("SaveChanges", "redisql")]
34 | [SqlProcedure]
35 | public static void Save(string host,
36 | [SqlParameter(DefaultValue = "6379")]int port,
37 | [SqlParameter(DefaultValue = typeof(DBNull))]string password,
38 | [SqlParameter(DefaultValue = typeof(DBNull))]int? dbId,
39 | [SqlParameter(DefaultValue = true)] bool isBackground)
40 |
41 | {
42 | using (var redis = RedisConnection.GetConnection(host, port, password, dbId))
43 | {
44 | if (isBackground)
45 | {
46 | redis.BackgroundSave();
47 | }
48 | else
49 | {
50 | redis.Save();
51 | }
52 | }
53 | }
54 |
55 | [SqlInstallerScriptGeneratorExportedProcedure("Flush", "redisql")]
56 | [SqlProcedure]
57 | public static void Flush(string host,
58 | [SqlParameter(DefaultValue = "6379")]int port,
59 | [SqlParameter(DefaultValue = typeof(DBNull))]string password,
60 | [SqlParameter(DefaultValue = typeof(DBNull))]int? dbId)
61 |
62 | {
63 | using (var redis = RedisConnection.GetConnection(host, port, password, dbId))
64 | {
65 | if (dbId != null)
66 | {
67 | redis.FlushDb();
68 | }
69 | else
70 | {
71 | redis.FlushAll();
72 | }
73 | }
74 | }
75 |
76 | [SqlInstallerScriptGeneratorExportedFunction("GetLastSaved", "redisql")]
77 | [SqlFunction(DataAccess = DataAccessKind.None, IsDeterministic = false)]
78 | public static DateTime GetLastSaved(string host,
79 | [SqlParameter(DefaultValue = "6379")]int port,
80 | [SqlParameter(DefaultValue = typeof(DBNull))]string password,
81 | [SqlParameter(DefaultValue = typeof(DBNull))]int? dbId)
82 | {
83 | using (var redis = RedisConnection.GetConnection(host, port, password, dbId))
84 | {
85 | return redis.LastSave;
86 | }
87 | }
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/RedisSqlCache/SqlClrComponents/RedisqlKeysManipulationFunctions.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections;
3 | using System.Data.SqlTypes;
4 | using Microsoft.SqlServer.Server;
5 | using RediSql.Common;
6 | using RediSql.SqlClrComponents.Common;
7 | using SqlClrDeclarations.Attributes;
8 |
9 | namespace RediSql.SqlClrComponents
10 | {
11 | public static class RedisqlKeysManipulationFunctions
12 | {
13 | [SqlInstallerScriptGeneratorExportedFunction("IsKeyExists", "redisql")]
14 | [SqlFunction(DataAccess = DataAccessKind.None, IsDeterministic = false)]
15 | public static bool IsKeyExists(string host,
16 | [SqlParameter(DefaultValue = "6379")]int port,
17 | [SqlParameter(DefaultValue = typeof(DBNull))]string password,
18 | [SqlParameter(DefaultValue = typeof(DBNull))]int? dbId,
19 | string key)
20 | {
21 | using (var redis = RedisConnection.GetConnection(host, port, password, dbId))
22 | {
23 | return redis.ContainsKey(key);
24 | }
25 | }
26 |
27 | [SqlInstallerScriptGeneratorExportedFunction("GetKeyType", "redisql")]
28 | [SqlFunction(DataAccess = DataAccessKind.None, IsDeterministic = false)]
29 | public static string GetKeyType(string host,
30 | [SqlParameter(DefaultValue = "6379")]int port,
31 | [SqlParameter(DefaultValue = typeof(DBNull))]string password,
32 | [SqlParameter(DefaultValue = typeof(DBNull))]int? dbId,
33 | string key)
34 | {
35 | using (var redis = RedisConnection.GetConnection(host, port, password, dbId))
36 | {
37 | var redisKeyType = redis.TypeOf(key);
38 | switch (redisKeyType)
39 | {
40 | case Redis.KeyType.None:
41 | return KeyType.NotExisting.ToString();
42 | case Redis.KeyType.String:
43 | return KeyType.String.ToString();
44 | case Redis.KeyType.List:
45 | if (RedisqlLists.GetListItemAtIndex(host, port, password, dbId, key, 0).Equals(RedisqlRowsets.RowsetMagic, StringComparison.OrdinalIgnoreCase))
46 | return KeyType.Rowset.ToString();
47 | return KeyType.List.ToString();
48 | case Redis.KeyType.Set:
49 | return KeyType.Set.ToString();
50 | case Redis.KeyType.ZSet:
51 | return KeyType.Set.ToString();
52 | case Redis.KeyType.Hash:
53 | return KeyType.Hash.ToString();
54 | default:
55 | throw new ArgumentOutOfRangeException();
56 | }
57 | }
58 | }
59 |
60 | [SqlInstallerScriptGeneratorExportedFunction("RenameKey", "redisql")]
61 | [SqlFunction(DataAccess = DataAccessKind.None, IsDeterministic = false)]
62 | public static bool Rename(string host,
63 | [SqlParameter(DefaultValue = "6379")]int port,
64 | [SqlParameter(DefaultValue = typeof(DBNull))]string password,
65 | [SqlParameter(DefaultValue = typeof(DBNull))]int? dbId,
66 | string key,
67 | string keyNewName)
68 | {
69 | using (var redis = RedisConnection.GetConnection(host, port, password, dbId))
70 | {
71 | return redis.Rename(key, keyNewName);
72 | }
73 | }
74 |
75 | [SqlInstallerScriptGeneratorExportedFunction("SetRelativeExpiration", "redisql")]
76 | [SqlFunction(DataAccess = DataAccessKind.None, IsDeterministic = false)]
77 | public static bool SetRelativeExpiration(string host,
78 | [SqlParameter(DefaultValue = "6379")]int port,
79 | [SqlParameter(DefaultValue = typeof(DBNull))]string password,
80 | [SqlParameter(DefaultValue = typeof(DBNull))]int? dbId,
81 | string key,
82 | TimeSpan expiration)
83 | {
84 | using (var redis = RedisConnection.GetConnection(host, port, password, dbId))
85 | {
86 | return redis.Expire(key, (int)expiration.TotalSeconds);
87 | }
88 | }
89 |
90 | [SqlInstallerScriptGeneratorExportedFunction("SetExactExpiration", "redisql")]
91 | [SqlFunction(DataAccess = DataAccessKind.None, IsDeterministic = false)]
92 | public static bool SetExactExpiration(string host,
93 | [SqlParameter(DefaultValue = "6379")]int port,
94 | [SqlParameter(DefaultValue = typeof(DBNull))]string password,
95 | [SqlParameter(DefaultValue = typeof(DBNull))]int? dbId,
96 | string key,
97 | DateTime expiration)
98 | {
99 | using (var redis = RedisConnection.GetConnection(host, port, password, dbId))
100 | {
101 | return redis.ExpireAt(key, (int)DateTimeUtils.ToUnixTime(expiration));
102 | }
103 | }
104 |
105 | [SqlInstallerScriptGeneratorExportedFunction("GetKeyTTL", "redisql")]
106 | [SqlFunction(DataAccess = DataAccessKind.None, IsDeterministic = false)]
107 | public static int? GetKeyTTL(string host,
108 | [SqlParameter(DefaultValue = "6379")]int port,
109 | [SqlParameter(DefaultValue = typeof(DBNull))]string password,
110 | [SqlParameter(DefaultValue = typeof(DBNull))]int? dbId,
111 | string key)
112 | {
113 | using (var redis = RedisConnection.GetConnection(host, port, password, dbId))
114 | {
115 | var ttl = redis.TimeToLive(key);
116 | return ttl >= 0 ? ttl : (int?)null;
117 | }
118 | }
119 |
120 | [SqlInstallerScriptGeneratorExportedFunction("DeleteKey", "redisql")]
121 | [SqlFunction(DataAccess = DataAccessKind.None, IsDeterministic = false)]
122 | public static bool DeleteKey(string host,
123 | [SqlParameter(DefaultValue = "6379")]int port,
124 | [SqlParameter(DefaultValue = typeof(DBNull))]string password,
125 | [SqlParameter(DefaultValue = typeof(DBNull))]int? dbId,
126 | string key)
127 | {
128 | using (var redis = RedisConnection.GetConnection(host, port, password, dbId))
129 | {
130 | return redis.Remove(key);
131 | }
132 | }
133 |
134 | [SqlInstallerScriptGeneratorExportedFunction("GetKeys", "redisql")]
135 | [SqlFunction(DataAccess = DataAccessKind.None, IsDeterministic = false, FillRowMethodName = "GetKeys_RowFiller", TableDefinition = "KeyName nvarchar(512)")]
136 | public static IEnumerable GetKeys(string host,
137 | [SqlParameter(DefaultValue = "6379")]int port,
138 | [SqlParameter(DefaultValue = typeof(DBNull))]string password,
139 | [SqlParameter(DefaultValue = typeof(DBNull))]int? dbId,
140 | [SqlParameter(DefaultValue = "*")]string filter)
141 | {
142 | using (var redis = RedisConnection.GetConnection(host, port, password, dbId))
143 | {
144 | return redis.GetKeys(filter);
145 | }
146 | }
147 |
148 | public static void GetKeys_RowFiller(object item, out SqlString keyName)
149 | {
150 | keyName = (string)item;
151 | }
152 | }
153 | }
154 |
--------------------------------------------------------------------------------
/RedisSqlCache/SqlClrComponents/RedisqlLists.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections;
3 | using System.Collections.Generic;
4 | using System.Data.SqlTypes;
5 | using System.Linq;
6 | using System.Text;
7 | using Microsoft.SqlServer.Server;
8 | using RediSql.SqlClrComponents.Common;
9 | using SqlClrDeclarations.Attributes;
10 |
11 | namespace RediSql.SqlClrComponents
12 | {
13 | public static class RedisqlLists
14 | {
15 | [SqlInstallerScriptGeneratorExportedFunction("GetListItems", "redisql")]
16 | [SqlFunction(DataAccess = DataAccessKind.None, IsDeterministic = false, FillRowMethodName = "GetListItems_RowFiller", TableDefinition = "Value nvarchar(max)")]
17 | public static IEnumerable GetListItems(string host,
18 | [SqlParameter(DefaultValue = "6379")]int port,
19 | [SqlParameter(DefaultValue = typeof(DBNull))]string password,
20 | [SqlParameter(DefaultValue = typeof(DBNull))]int? dbId,
21 | string key,
22 | [SqlParameter(DefaultValue = 0)]int start,
23 | [SqlParameter(DefaultValue = -1)]int end)
24 | {
25 | using (var redis = RedisConnection.GetConnection(host, port, password, dbId))
26 | {
27 | return redis.ListRange(key, start, end);
28 | }
29 | }
30 |
31 | public static void GetListItems_RowFiller(object item, out SqlString value)
32 | {
33 | byte[] txtEncoded = (byte[])item;
34 | value = Encoding.UTF8.GetString(txtEncoded);
35 | }
36 |
37 | [SqlInstallerScriptGeneratorExportedFunction("GetListItemsAtIndex", "redisql")]
38 | [SqlFunction(DataAccess = DataAccessKind.None, IsDeterministic = false)]
39 | public static string GetListItemAtIndex(string host,
40 | [SqlParameter(DefaultValue = "6379")]int port,
41 | [SqlParameter(DefaultValue = typeof(DBNull))]string password,
42 | [SqlParameter(DefaultValue = typeof(DBNull))]int? dbId,
43 | string key,
44 | int index)
45 | {
46 | using (var redis = RedisConnection.GetConnection(host, port, password, dbId))
47 | {
48 | return Encoding.UTF8.GetString(redis.ListIndex(key, index));
49 | }
50 | }
51 |
52 | [SqlInstallerScriptGeneratorExportedFunction("ListLeftPop", "redisql")]
53 | [SqlFunction(DataAccess = DataAccessKind.None, IsDeterministic = false)]
54 | public static string LeftPop(string host,
55 | [SqlParameter(DefaultValue = "6379")]int port,
56 | [SqlParameter(DefaultValue = typeof(DBNull))]string password,
57 | [SqlParameter(DefaultValue = typeof(DBNull))]int? dbId,
58 | string key)
59 | {
60 | using (var redis = RedisConnection.GetConnection(host, port, password, dbId))
61 | {
62 | return Encoding.UTF8.GetString(redis.LeftPop(key));
63 | }
64 | }
65 |
66 | [SqlInstallerScriptGeneratorExportedFunction("ListRightPop", "redisql")]
67 | [SqlFunction(DataAccess = DataAccessKind.None, IsDeterministic = false)]
68 | public static string RightPop(string host,
69 | [SqlParameter(DefaultValue = "6379")]int port,
70 | [SqlParameter(DefaultValue = typeof(DBNull))]string password,
71 | [SqlParameter(DefaultValue = typeof(DBNull))]int? dbId,
72 | string key)
73 | {
74 | using (var redis = RedisConnection.GetConnection(host, port, password, dbId))
75 | {
76 | return Encoding.UTF8.GetString(redis.RightPop(key));
77 | }
78 | }
79 |
80 | [SqlInstallerScriptGeneratorExportedProcedure("AddToList", "redisql")]
81 | [SqlProcedure]
82 | public static void AddToList(string host,
83 | [SqlParameter(DefaultValue = "6379")]int port,
84 | [SqlParameter(DefaultValue = typeof(DBNull))]string password,
85 | [SqlParameter(DefaultValue = typeof(DBNull))]int? dbId,
86 | string key,
87 | string value,
88 | [SqlParameter(DefaultValue = true)]bool addToEnd,
89 | [SqlParameter(DefaultValue = typeof(DBNull))] TimeSpan? expiration)
90 | {
91 | using (var redis = RedisConnection.GetConnection(host, port, password, dbId))
92 | {
93 | if (addToEnd)
94 | {
95 | redis.RightPush(key, value);
96 | }
97 | else
98 | {
99 | redis.LeftPush(key, value);
100 | }
101 | if (expiration != null)
102 | {
103 | redis.Expire(key, (int)expiration.Value.TotalSeconds);
104 | }
105 | }
106 | }
107 |
108 | [SqlInstallerScriptGeneratorExportedFunction("GetListLength", "redisql")]
109 | [SqlFunction(DataAccess = DataAccessKind.None, IsDeterministic = false)]
110 | public static int GetListLength(string host,
111 | [SqlParameter(DefaultValue = "6379")]int port,
112 | [SqlParameter(DefaultValue = typeof(DBNull))]string password,
113 | [SqlParameter(DefaultValue = typeof(DBNull))]int? dbId,
114 | string key)
115 | {
116 | using (var redis = RedisConnection.GetConnection(host, port, password, dbId))
117 | {
118 | return redis.ListLength(key);
119 | }
120 | }
121 |
122 |
123 | }
124 | }
125 |
--------------------------------------------------------------------------------
/RedisSqlCache/SqlClrComponents/RedisqlRowsets.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Data;
4 | using System.Data.SqlClient;
5 | using System.IO;
6 | using System.Linq;
7 | using System.Text;
8 | using System.Xml;
9 | using System.Xml.Linq;
10 | using Microsoft.SqlServer.Server;
11 | using RediSql.SqlClrComponents.Common;
12 | using SqlClrDeclarations.Attributes;
13 |
14 | namespace RediSql.SqlClrComponents
15 | {
16 | public static class RedisqlRowsets
17 | {
18 | [SqlInstallerScriptGeneratorExportedProcedure("StoreQueryResultsData", "redisql")]
19 | [SqlProcedure]
20 | public static void StoreQueryResultsData(string host,
21 | [SqlParameter(DefaultValue = "6379")]int port,
22 | [SqlParameter(DefaultValue = typeof(DBNull))]string password,
23 | [SqlParameter(DefaultValue = typeof(DBNull))]int? dbId,
24 | string key,
25 | string query,
26 | [SqlParameter(DefaultValue = typeof(DBNull))]TimeSpan? expiration,
27 | [SqlParameter(DefaultValue = false)]bool replaceExisting)
28 | {
29 | var rowsXmls = ExecuteQueryAndGetResultList(query);
30 | using (var redis = RedisConnection.GetConnection(host, port, password, dbId))
31 | {
32 | if (redis.ContainsKey(key))
33 | {
34 | if (replaceExisting)
35 | {
36 | redis.Remove(key);
37 | }
38 | else
39 | {
40 | throw new Exception("key with the same name already exists, and replace flag not enabled");
41 | }
42 | }
43 | List valuesToAdd = new List(rowsXmls.Count + 1) { RowsetMagic };
44 | valuesToAdd.AddRange(rowsXmls);
45 | valuesToAdd.ForEach(val => RedisqlLists.AddToList(host, port, password, dbId, key, val, true, null));
46 | if (expiration != null)
47 | {
48 | redis.Expire(key, (int)expiration.Value.TotalSeconds);
49 | }
50 | }
51 | }
52 |
53 | private static List ExecuteQueryAndGetResultList(string query)
54 | {
55 | List valuesToAdd = new List();
56 | using (SqlConnection connection = new SqlConnection("context connection=true"))
57 | {
58 | connection.Open();
59 | valuesToAdd.Add(GetColumnMetadataXml(connection, query));
60 | using (SqlCommand queryCommand = new SqlCommand(query, connection))
61 | using (SqlDataReader rowsetReader = queryCommand.ExecuteReader())
62 | {
63 | while (rowsetReader.Read())
64 | {
65 | XElement el = new XElement("item");
66 | for (int index = 0; index < rowsetReader.FieldCount; index++)
67 | {
68 | if (!rowsetReader.IsDBNull(index))
69 | el.Add(new XElement("I" + (index + 1), rowsetReader.GetValue(index)));
70 | }
71 | valuesToAdd.Add(el.ToString());
72 | }
73 | }
74 | }
75 | return valuesToAdd;
76 | }
77 |
78 | private static string GetColumnMetadataXml(SqlConnection connection, string query)
79 | {
80 | using (var cmd = new SqlCommand("sp_describe_first_result_set", connection))
81 | {
82 | cmd.CommandType = CommandType.StoredProcedure;
83 | cmd.Parameters.AddWithValue("tsql", query);
84 | XElement el = new XElement("ColumnsMetadata");
85 | using (var reader = cmd.ExecuteReader())
86 | {
87 | while (reader.Read())
88 | {
89 | el.Add(new XElement("Column",
90 | new XAttribute("order", reader["column_ordinal"]),
91 | new XAttribute("name", reader["name"]),
92 | new XAttribute("sqlType", reader["system_type_name"])));
93 | }
94 | }
95 | return el.ToString();
96 | }
97 | }
98 |
99 | public static string RowsetMagic => "REDISQLROWSET";
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/RedisSqlCache/SqlClrComponents/RedisqlStringValuesFunctions.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Microsoft.SqlServer.Server;
3 | using RediSql.SqlClrComponents.Common;
4 | using SqlClrDeclarations.Attributes;
5 |
6 | namespace RediSql.SqlClrComponents
7 | {
8 | public static class RedisqlStringValuesFunctions
9 | {
10 | [SqlInstallerScriptGeneratorExportedProcedure("SetStringValue", "redisql")]
11 | [SqlProcedure]
12 | public static void SetStringValue(string host,
13 | [SqlParameter(DefaultValue = "6379")]int port,
14 | [SqlParameter(DefaultValue = typeof(DBNull))]string password,
15 | [SqlParameter(DefaultValue = typeof(DBNull))]int? dbId,
16 | string key,
17 | string value,
18 | [SqlParameter(DefaultValue = typeof(DBNull))]TimeSpan? expiration)
19 | {
20 | using (var redis = RedisConnection.GetConnection(host, port, password, dbId))
21 | {
22 | redis.Set(key, value);
23 | if (expiration != null)
24 | redis.Expire(key, (int)expiration.Value.TotalSeconds);
25 | }
26 | }
27 |
28 | [SqlInstallerScriptGeneratorExportedFunction("SetStringValueIfNotExists", "redisql")]
29 | [SqlFunction(DataAccess = DataAccessKind.None, IsDeterministic = false)]
30 | public static bool SetStringValueIfNotExists(string host,
31 | [SqlParameter(DefaultValue = "6379")]int port,
32 | [SqlParameter(DefaultValue = typeof(DBNull))]string password,
33 | [SqlParameter(DefaultValue = typeof(DBNull))]int? dbId,
34 | string key,
35 | string value,
36 | [SqlParameter(DefaultValue = typeof(DBNull))]TimeSpan? expiration)
37 | {
38 | using (var redis = RedisConnection.GetConnection(host, port, password, dbId))
39 | {
40 | bool wasKeyCreated = redis.SetNX(key, value);
41 | if (wasKeyCreated && expiration != null)
42 | return redis.Expire(key, (int)expiration.Value.TotalSeconds);
43 | return wasKeyCreated;
44 | }
45 | }
46 |
47 | [SqlInstallerScriptGeneratorExportedFunction("GetSetStringValue", "redisql")]
48 | [SqlFunction(DataAccess = DataAccessKind.None, IsDeterministic = false)]
49 | public static string GetSetStringValue(string host,
50 | [SqlParameter(DefaultValue = "6379")]int port,
51 | [SqlParameter(DefaultValue = typeof(DBNull))]string password,
52 | [SqlParameter(DefaultValue = typeof(DBNull))]int? dbId,
53 | string key,
54 | string value,
55 | [SqlParameter(DefaultValue = typeof(DBNull))]TimeSpan? expiration)
56 | {
57 | using (var redis = RedisConnection.GetConnection(host, port, password, dbId))
58 | {
59 | string result = redis.GetSet(key, value);
60 | if (expiration != null)
61 | redis.Expire(key, (int)expiration.Value.TotalSeconds);
62 | return result ?? value; //change the default Redis behavior, and make it be like GetSet on the rowset
63 | }
64 | }
65 |
66 | [SqlInstallerScriptGeneratorExportedFunction("GetStringValue", "redisql")]
67 | [SqlFunction(DataAccess = DataAccessKind.None, IsDeterministic = false)]
68 | public static string GetStringValue(string host,
69 | [SqlParameter(DefaultValue = "6379")]int port,
70 | [SqlParameter(DefaultValue = typeof(DBNull))]string password,
71 | [SqlParameter(DefaultValue = typeof(DBNull))]int? dbId,
72 | string key)
73 | {
74 | using (var redis = RedisConnection.GetConnection(host, port, password, dbId))
75 | {
76 | return redis.GetString(key);
77 | }
78 | }
79 |
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/RedisSqlCache/TSQLCode/GetSetStoredRowset.sql:
--------------------------------------------------------------------------------
1 |
2 | SET ANSI_NULLS ON
3 | GO
4 | SET QUOTED_IDENTIFIER ON
5 | GO
6 | CREATE PROCEDURE redisql.GetSetStoredRowset
7 | @key nvarchar(250),
8 | @host nvarchar(50),
9 | @port int = 6379,
10 | @password nvarchar(50) = null,
11 | @dbId int = null,
12 | @expiration time = null,
13 | @query nvarchar(max)
14 | AS
15 | BEGIN
16 | SET NOCOUNT ON;
17 |
18 | IF (redisql.GetKeyType(@host, @port, @password, @dbId, @key) = 'Rowset')
19 | BEGIN
20 | IF (@expiration IS NOT NULL)
21 | BEGIN
22 | SELECT redisql.SetRelativeExpiration(@host, @port, @password, @dbId, @key, @expiration)
23 | END
24 | DECLARE @numberOfRows int
25 | EXECUTE @numberOfRows = redisql.GetStoredRowset @host, @port, @password, @dbId, @key
26 | RETURN @numberOfRows
27 | END
28 | ELSE
29 | BEGIN
30 | EXECUTE redisql.StoreQueryResultsData @host, @port, @password, @dbId, @key, @query, @expiration
31 | EXEC sp_executesql @query
32 | RETURN -1
33 | END
34 | END
35 | GO
36 |
--------------------------------------------------------------------------------
/RedisSqlCache/TSQLCode/GetStoredRowset.sql:
--------------------------------------------------------------------------------
1 |
2 | SET ANSI_NULLS ON
3 | GO
4 | SET QUOTED_IDENTIFIER ON
5 | GO
6 |
7 | CREATE PROCEDURE redisql.GetStoredRowset
8 | @host nvarchar(250), @port int = 6379, @password nvarchar(100) = null, @dbId int = null, @key nvarchar(256)
9 | AS
10 |
11 | BEGIN
12 | SET NOCOUNT ON;
13 |
14 | IF OBJECT_ID('tempdb..#items') IS NOT NULL DROP TABLE #items
15 |
16 | CREATE TABLE #items(val nvarchar(max))
17 | INSERT INTO #items(val)
18 | SELECT Value
19 | FROM redisql.GetListItems(@host, @port, @password, @dbId, @key, default, default)
20 |
21 | IF (SELECT COUNT(*) FROM #items) = 0
22 | BEGIN
23 | SELECT NULL
24 | RETURN -1
25 | END
26 |
27 | DELETE TOP (1)
28 | FROM #items
29 |
30 | DECLARE @metadataXml xml = (SELECT TOP 1 cast(val as xml) FROM #items)
31 | DELETE TOP (1)
32 | FROM #items
33 |
34 | DECLARE @columnsMetadata table(Seq int, Name nvarchar(250), DataType varchar(100))
35 | INSERT INTO @columnsMetadata(Seq, Name, DataType)
36 | SELECT col.value('(@order)[1]', 'nvarchar(max)'),
37 | col.value('(@name)[1]', 'nvarchar(max)'),
38 | col.value('(@sqlType)[1]', 'nvarchar(max)')
39 | FROM @metadataXml.nodes('/ColumnsMetadata/Column') as columns(col)
40 |
41 | DECLARE @dynamicSelectors nvarchar(max)
42 | SELECT @dynamicSelectors =COALESCE(@dynamicSelectors + ', ', '') + 'T.C.value(''/item[1]/I' +CAST(Seq as varchar(10)) +'[1]'', ''' + DataType + ''') ' + Name
43 | FROM @columnsMetadata
44 | ORDER BY Seq
45 |
46 | DECLARE @sql nvarchar(max) =
47 | '
48 | SELECT o.*
49 | FROM #items
50 | OUTER APPLY (
51 | SELECT CAST(val as xml) xmlData
52 | ) rowXml
53 | OUTER APPLY (
54 | SELECT TOP 1 dataColumns.*
55 | FROM rowXml.xmlData.nodes(''/item/*'') as T(C)
56 | OUTER APPLY (
57 | SELECT ' + @dynamicSelectors + '
58 | ) dataColumns
59 | ) o
60 | '
61 | EXECUTE(@sql)
62 | RETURN (SELECT COUNT(*) FROM #items)
63 | END
64 |
65 | GO
--------------------------------------------------------------------------------
/RedisSqlCache/TSQLCode/XmlToRowset.sql:
--------------------------------------------------------------------------------
1 |
2 | CREATE PROCEDURE [redisql].[ConvertXmlToRowset]
3 | (
4 | @input xml
5 | )
6 | AS
7 | BEGIN
8 | IF OBJECT_ID('tempdb..#dataToPivot') IS NOT NULL DROP TABLE #dataToPivot
9 |
10 | CREATE TABLE #dataToPivot (BatchID uniqueidentifier, KeyName nvarchar(max), Value nvarchar(max))
11 | INSERT INTO #dataToPivot(BatchID, KeyName, Value)
12 |
13 | SELECT rowXml.ID,
14 | keyValueSet.Name,
15 | keyValueSet.Value
16 | FROM @input.nodes('/items/item') T(c)
17 | OUTER APPLY (
18 | SELECT CAST(T.c.query('.') as xml) xmlData,
19 | NEWID() id
20 | ) rowXml
21 | OUTER APPLY (
22 | SELECT
23 | C.Name,
24 | C.Value
25 | FROM rowXml.xmlData.nodes('/item/*') as T(C)
26 | OUTER APPLY (
27 | SELECT
28 | T.C.value('local-name(.)', 'nvarchar(max)') as Name,
29 | T.C.value('(./text())[1]', 'nvarchar(max)') as Value
30 | UNION ALL
31 | SELECT
32 | A.C.value('local-name(.)', 'nvarchar(max)') as Name,
33 | A.C.value('.', 'nvarchar(max)') as Value
34 | FROM T.C.nodes('@*') as A(C)
35 | ) as C
36 | where C.Value is not null
37 | ) keyValueSet
38 |
39 | DECLARE @colsNames NVARCHAR(2000)
40 | SELECT @colsNames =COALESCE(@colsNames + ', ', '') + '[' +KeyName + ']'
41 | FROM #dataToPivot
42 | GROUP BY KeyName
43 | DECLARE @query NVARCHAR(4000)
44 |
45 | SET @query = N' SELECT '+
46 | @colsNames +'
47 | FROM
48 | (
49 | SELECT t2.BatchID
50 | ,t1.KeyName
51 | ,t1.Value
52 | FROM #dataToPivot AS t1
53 | JOIN #dataToPivot AS t2 ON t1.BatchID = t2.BatchID
54 | ) p
55 | PIVOT (
56 | MAX([Value])
57 | FOR KeyName IN ( '+@colsNames +' )
58 | ) AS pvt
59 | ORDER BY BatchID;'
60 | EXECUTE(@query)
61 |
62 | END
63 |
64 |
--------------------------------------------------------------------------------
/ScriptGenerator/InstallerScriptGenerator.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shahargv/redisql/405776a378ae2ce42155d5148f85d9b7b3121ccb/ScriptGenerator/InstallerScriptGenerator.exe
--------------------------------------------------------------------------------
/ScriptGenerator/InstallerScriptGenerator.exe.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/ScriptGenerator/InstallerScriptGenerator.vshost.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shahargv/redisql/405776a378ae2ce42155d5148f85d9b7b3121ccb/ScriptGenerator/InstallerScriptGenerator.vshost.exe
--------------------------------------------------------------------------------
/ScriptGenerator/InstallerScriptGenerator.vshost.exe.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/ScriptGenerator/InstallerScriptGenerator.vshost.exe.manifest:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/ScriptGenerator/SqlClrDeclarations.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shahargv/redisql/405776a378ae2ce42155d5148f85d9b7b3121ccb/ScriptGenerator/SqlClrDeclarations.dll
--------------------------------------------------------------------------------
/SqlClrDeclarations/Attributes/ExportedFunctionAttribute.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace SqlClrDeclarations.Attributes
4 | {
5 | [AttributeUsage(AttributeTargets.Method)]
6 | public class SqlInstallerScriptGeneratorExportedFunction : SqlInstallerScriptGeneratorExportedAttributeBase
7 | {
8 | public string SqlReturnType { get; set; }
9 |
10 | public SqlInstallerScriptGeneratorExportedFunction(string functionName, string schemaName)
11 | {
12 | Name = functionName;
13 | SchemaName = schemaName;
14 | }
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/SqlClrDeclarations/Attributes/SqlInstallerScriptGeneratorExportedAttributeBase.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace SqlClrDeclarations.Attributes
4 | {
5 | public class SqlInstallerScriptGeneratorExportedAttributeBase : Attribute
6 | {
7 | public string SchemaName { get; set; }
8 | public string Name { get; set; }
9 |
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/SqlClrDeclarations/Attributes/SqlInstallerScriptGeneratorExportedProcedure.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace SqlClrDeclarations.Attributes
4 | {
5 | [AttributeUsage(AttributeTargets.Method)]
6 | public class SqlInstallerScriptGeneratorExportedProcedure : SqlInstallerScriptGeneratorExportedAttributeBase
7 | {
8 | public SqlInstallerScriptGeneratorExportedProcedure(string functionName, string schemaName)
9 | {
10 | Name = functionName;
11 | SchemaName = schemaName;
12 | }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/SqlClrDeclarations/Attributes/SqlParameterAttribute.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace SqlClrDeclarations.Attributes
4 | {
5 | [AttributeUsage(AttributeTargets.Parameter)]
6 | public class SqlParameterAttribute : Attribute
7 | {
8 | public object DefaultValue { get; set; }
9 | public string Name { get; set; }
10 | public string SqlType { get; set; }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/SqlClrDeclarations/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 | using SqlClrDeclarations.Attributes;
5 |
6 | // General Information about an assembly is controlled through the following
7 | // set of attributes. Change these attribute values to modify the information
8 | // associated with an assembly.
9 | [assembly: AssemblyTitle("SqlClrDeclarations")]
10 | [assembly: AssemblyDescription("")]
11 | [assembly: AssemblyConfiguration("")]
12 | [assembly: AssemblyCompany("")]
13 | [assembly: AssemblyProduct("SqlClrDeclarations")]
14 | [assembly: AssemblyCopyright("Copyright © 2015")]
15 | [assembly: AssemblyTrademark("")]
16 | [assembly: AssemblyCulture("")]
17 |
18 |
19 | // Setting ComVisible to false makes the types in this assembly not visible
20 | // to COM components. If you need to access a type in this assembly from
21 | // COM, set the ComVisible attribute to true on that type.
22 | [assembly: ComVisible(false)]
23 |
24 | // The following GUID is for the ID of the typelib if this project is exposed to COM
25 | [assembly: Guid("56c24720-8053-4cf5-8bf8-bae7dba78424")]
26 |
27 | // Version information for an assembly consists of the following four values:
28 | //
29 | // Major Version
30 | // Minor Version
31 | // Build Number
32 | // Revision
33 | //
34 | // You can specify all the values or you can default the Build and Revision Numbers
35 | // by using the '*' as shown below:
36 | // [assembly: AssemblyVersion("1.0.*")]
37 | [assembly: AssemblyVersion("1.0.0.0")]
38 | [assembly: AssemblyFileVersion("1.0.0.0")]
39 |
--------------------------------------------------------------------------------
/SqlClrDeclarations/SqlClrDeclarations.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {56C24720-8053-4CF5-8BF8-BAE7DBA78424}
8 | Library
9 | Properties
10 | SqlClrDeclarations
11 | SqlClrDeclarations
12 | v4.0
13 | 512
14 |
15 |
16 |
17 | true
18 | full
19 | false
20 | bin\Debug\
21 | DEBUG;TRACE
22 | prompt
23 | 4
24 |
25 |
26 | pdbonly
27 | true
28 | bin\Release\
29 | TRACE
30 | prompt
31 | 4
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
58 |
--------------------------------------------------------------------------------