You've already forked linux-packaging-mono
Imported Upstream version 4.6.0.125
Former-commit-id: a2155e9bd80020e49e72e86c44da02a8ac0e57a4
This commit is contained in:
parent
a569aebcfd
commit
e79aa3c0ed
@@ -0,0 +1,145 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Data.Linq.Mapping;
|
||||
using System.Data.Linq.Provider;
|
||||
using System.Data.SqlClient;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace System.Data.Linq.SqlClient {
|
||||
|
||||
internal static class SqlIdentifier
|
||||
{
|
||||
private static SqlCommandBuilder builder = new SqlCommandBuilder();
|
||||
|
||||
const string ParameterPrefix = "@";
|
||||
const string QuotePrefix = "[";
|
||||
const string QuoteSuffix = "]";
|
||||
const string SchemaSeparator = ".";
|
||||
const char SchemaSeparatorChar = '.';
|
||||
|
||||
private static bool IsQuoted(string s) {
|
||||
if (s == null) {
|
||||
throw Error.ArgumentNull("s");
|
||||
}
|
||||
|
||||
if (s.Length < 2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return s.StartsWith(QuotePrefix, StringComparison.Ordinal)
|
||||
&& s.EndsWith(QuoteSuffix, StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
// This is MSSQL-specific quoting.
|
||||
// If the string begins and ends with [ and ], it will be assumed to already be quoted.
|
||||
// Otherwise periods are assumed to be namespace delimiters, and the string is split on each.
|
||||
// Each string from the split is then check to see if it is already quoted, and if
|
||||
// not, it is replaced with the result of SqlCommandBuilder.QuoteIdentifier.
|
||||
// Then the set of strings is rejoined with periods.
|
||||
internal static string QuoteCompoundIdentifier(string s) {
|
||||
if (s == null) {
|
||||
throw Error.ArgumentNull("s");
|
||||
}
|
||||
|
||||
// if it starts with @, then return unprocessed
|
||||
if (s.StartsWith(ParameterPrefix, StringComparison.Ordinal)) {
|
||||
return s;
|
||||
} else if (IsQuoted(s)) {
|
||||
return s;
|
||||
}
|
||||
else if (!s.StartsWith(QuotePrefix, StringComparison.Ordinal) && s.EndsWith(QuoteSuffix, StringComparison.Ordinal)) {
|
||||
//A.[B] => [A].[B]
|
||||
int splitPosition = s.IndexOf(SchemaSeparatorChar);
|
||||
if (splitPosition < 0){ //no . in the string
|
||||
return builder.QuoteIdentifier(s);
|
||||
}
|
||||
string left = s.Substring(0, splitPosition);
|
||||
string right = s.Substring(splitPosition + 1, s.Length - splitPosition - 1);
|
||||
if (!IsQuoted(right)) {
|
||||
right = builder.QuoteIdentifier(right);
|
||||
}
|
||||
return String.Concat(QuoteCompoundIdentifier(left), SchemaSeparatorChar + right);
|
||||
}
|
||||
else if (s.StartsWith(QuotePrefix, StringComparison.Ordinal) && !s.EndsWith(QuoteSuffix, StringComparison.Ordinal)) {
|
||||
//[A].B => [A].[B]
|
||||
int splitPosition = s.LastIndexOf(SchemaSeparatorChar);
|
||||
if (splitPosition < 0){ //no . in the string
|
||||
return builder.QuoteIdentifier(s);
|
||||
}
|
||||
string left = s.Substring(0, splitPosition);
|
||||
if (!IsQuoted(left)) {
|
||||
left = builder.QuoteIdentifier(left);
|
||||
}
|
||||
string right = s.Substring(splitPosition + 1, s.Length - splitPosition - 1);
|
||||
return String.Concat(left + SchemaSeparatorChar, QuoteCompoundIdentifier(right));
|
||||
}
|
||||
else {
|
||||
int splitPosition = s.IndexOf(SchemaSeparatorChar);
|
||||
if (splitPosition < 0) { //no . in the string
|
||||
//A => [A]
|
||||
return builder.QuoteIdentifier(s);
|
||||
}
|
||||
string left = s.Substring(0, splitPosition);
|
||||
string right = s.Substring(splitPosition + 1, s.Length - splitPosition - 1);
|
||||
return String.Concat(QuoteCompoundIdentifier(left) + SchemaSeparatorChar, QuoteCompoundIdentifier(right));
|
||||
}
|
||||
}
|
||||
|
||||
// This is MSSQL-specific quoting.
|
||||
// This is the same as above, but it doesn't consider anything compound.
|
||||
internal static string QuoteIdentifier(string s) {
|
||||
if (s == null) {
|
||||
throw Error.ArgumentNull("s");
|
||||
}
|
||||
|
||||
// if it starts with @, then return unprocessed
|
||||
if (s.StartsWith(ParameterPrefix, StringComparison.Ordinal)) {
|
||||
return s;
|
||||
} else if (IsQuoted(s)) {
|
||||
return s;
|
||||
} else {
|
||||
return builder.QuoteIdentifier(s);
|
||||
}
|
||||
}
|
||||
|
||||
// turns "[ABC].[PQR].[XYZ]" into {"[ABC]", "[PQR]", "[XYZ]"}
|
||||
internal static IEnumerable<string> GetCompoundIdentifierParts(string s) {
|
||||
if (s == null) {
|
||||
throw Error.ArgumentNull("s");
|
||||
}
|
||||
|
||||
// can't do this to parameters
|
||||
if (s.StartsWith(ParameterPrefix, StringComparison.Ordinal)) {
|
||||
throw Error.ArgumentWrongValue("s");
|
||||
}
|
||||
|
||||
string quotedS = QuoteCompoundIdentifier(s);
|
||||
string pattern = @"^(?<component>\[([^\]]|\]\])*\])(\.(?<component>\[([^\]]|\]\])*\]))*$";
|
||||
|
||||
// This pattern matches "."-delimited quoted SQL identifiers. Here's how:
|
||||
//
|
||||
// 1. It is wrapped in "^" and "$", which match the begining and end of text, so it will match
|
||||
// only the entire text and not any sub-part.
|
||||
// 2. The group "(?<component>\[([^\]]|\]\])*\])" captures a single quoted segment of the text.
|
||||
// It's a literal "[" followed by any number of non-"]" characters or "]]" strings, followed
|
||||
// by a literal "]". The "?<component>" bit names the capture so we can refer to it.
|
||||
// 3. After the first component, we will allow any number of groups which consist of a literal
|
||||
// "." followed by a component (and the component part is a repeat of the part described in 2).
|
||||
|
||||
Match m = Regex.Match(quotedS, pattern);
|
||||
if (!m.Success)
|
||||
{
|
||||
throw Error.ArgumentWrongValue("s");
|
||||
}
|
||||
|
||||
foreach (Capture cap in m.Groups["component"].Captures)
|
||||
{
|
||||
yield return cap.Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user