コード例 #1
0
        public IClickHouseColumnTypeInfo GetDetailedTypeInfo(List <ReadOnlyMemory <char> > options, IClickHouseTypeInfoProvider typeInfoProvider)
        {
            if (_elementTypes != null)
            {
                throw new ClickHouseException(ClickHouseErrorCodes.TypeNotSupported, "The type is already fully specified.");
            }

            var           complexTypeNameBuilder = new StringBuilder(TypeName).Append('(');
            var           elementTypes           = new List <IClickHouseColumnTypeInfo>(options.Count);
            List <string>?elementNames           = null;

            foreach (var option in options)
            {
                if (elementTypes.Count > 0)
                {
                    complexTypeNameBuilder.Append(", ");
                }

                var identifierLen = ClickHouseSyntaxHelper.GetIdentifierLiteralLength(option.Span);
                if (identifierLen == option.Span.Length)
                {
                    identifierLen = -1;
                }

                if (identifierLen < 0)
                {
                    if (elementNames != null)
                    {
                        throw new ClickHouseException(ClickHouseErrorCodes.InvalidTypeName, "A tuple can be either named or not. Mixing of named and unnamed arguments is not allowed.");
                    }

                    var typeInfo = typeInfoProvider.GetTypeInfo(option);
                    elementTypes.Add(typeInfo);
                }
                else
                {
                    if (elementNames == null)
                    {
                        if (elementTypes.Count > 0)
                        {
                            throw new ClickHouseException(ClickHouseErrorCodes.InvalidTypeName, "A tuple can be either named or not. Mixing of named and unnamed arguments is not allowed.");
                        }

                        elementNames = new List <string>(options.Count);
                    }

                    var name     = ClickHouseSyntaxHelper.GetIdentifier(option.Span.Slice(0, identifierLen));
                    var typeInfo = typeInfoProvider.GetTypeInfo(option.Slice(identifierLen + 1));

                    elementTypes.Add(typeInfo);
                    elementNames.Add(name);

                    complexTypeNameBuilder.Append(option.Slice(0, identifierLen)).Append(' ');
                }

                complexTypeNameBuilder.Append(elementTypes[^ 1].ComplexTypeName);
コード例 #2
0
        public IClickHouseColumnTypeInfo GetDetailedTypeInfo(List <ReadOnlyMemory <char> > options, IClickHouseTypeInfoProvider typeInfoProvider)
        {
            var  parsedOptions      = new List <KeyValuePair <string, TValue> >(options.Count);
            var  complexNameBuilder = new StringBuilder(TypeName).Append('(');
            bool isFirst            = true;

            foreach (var option in options)
            {
                if (isFirst)
                {
                    isFirst = false;
                }
                else
                {
                    complexNameBuilder.Append(", ");
                }

                var keyStrLen = ClickHouseSyntaxHelper.GetSingleQuoteStringLength(option.Span);
                if (keyStrLen < 0)
                {
                    throw new ClickHouseException(ClickHouseErrorCodes.InvalidTypeName, $"The fragment \"{option}\" is not recognized as an item of the enum.");
                }

                var key       = ClickHouseSyntaxHelper.GetSingleQuoteString(option.Slice(0, keyStrLen).Span);
                var valuePart = option.Slice(keyStrLen);
                var eqSignIdx = valuePart.Span.IndexOf('=');
                if (eqSignIdx < 0)
                {
                    throw new ClickHouseException(ClickHouseErrorCodes.InvalidTypeName, $"The fragment \"{option}\" is not recognized as an item of the enum.");
                }

                valuePart = valuePart.Slice(eqSignIdx + 1).Trim();
                if (!TryParse(valuePart.Span, out var value))
                {
                    throw new ClickHouseException(ClickHouseErrorCodes.InvalidTypeName, $"The value {valuePart} is not a valid value of {TypeName}.");
                }

                complexNameBuilder.Append(option);
                parsedOptions.Add(new KeyValuePair <string, TValue>(key, value));
            }

            var complexName = complexNameBuilder.Append(')').ToString();

            return(CreateDetailedTypeInfo(complexName, parsedOptions));
        }
コード例 #3
0
        private static (ReadOnlyMemory <char> baseTypeName, List <ReadOnlyMemory <char> >?options) ParseTypeName(ReadOnlyMemory <char> typeName)
        {
            var typeNameSpan = typeName.Span;

            var pOpenIdx = typeNameSpan.IndexOf('(');

            if (pOpenIdx == 0)
            {
                throw new ClickHouseException(ClickHouseErrorCodes.InvalidTypeName, $"The name of the type (\"{typeNameSpan.ToString()}\") can't start with \"(\".");
            }

            ReadOnlyMemory <char>         baseTypeName;
            List <ReadOnlyMemory <char> >?options = null;

            if (pOpenIdx < 0)
            {
                baseTypeName = typeName.Trim();
            }
            else
            {
                baseTypeName = typeName.Slice(0, pOpenIdx).Trim();

                int count          = 1;
                int currentIdx     = pOpenIdx;
                int optionStartIdx = pOpenIdx + 1;
                ReadOnlySpan <char> significantChars = "(,)'`";
                do
                {
                    if (typeNameSpan.Length - 1 == currentIdx)
                    {
                        break;
                    }

                    var pNextIdx = typeNameSpan.Slice(currentIdx + 1).IndexOfAny(significantChars);
                    if (pNextIdx < 0)
                    {
                        break;
                    }

                    pNextIdx  += currentIdx + 1;
                    currentIdx = pNextIdx;
                    if ("'`".Contains(typeNameSpan[currentIdx]))
                    {
                        var len = ClickHouseSyntaxHelper.GetQuotedTokenLength(typeNameSpan.Slice(currentIdx), typeNameSpan[currentIdx]);
                        if (len < 0)
                        {
                            break;
                        }

                        Debug.Assert(len > 0);
                        currentIdx += len - 1;
                    }
                    else if (typeNameSpan[currentIdx] == '(')
                    {
                        ++count;
                    }
                    else if (typeNameSpan[currentIdx] == ')')
                    {
                        --count;
                        if (count == 0)
                        {
                            break;
                        }
                    }
                    else if (count == 1)
                    {
                        var currentOption = typeName.Slice(optionStartIdx, currentIdx - optionStartIdx).Trim();
                        optionStartIdx = currentIdx + 1;

                        if (options != null)
                        {
                            options.Add(currentOption);
                        }
                        else
                        {
                            options = new List <ReadOnlyMemory <char> >(2)
                            {
                                currentOption
                            }
                        };
                    }
                } while (true);

                if (count != 0)
                {
                    throw new ClickHouseException(ClickHouseErrorCodes.InvalidTypeName, $"The number of open parentheses doesn't match to the number of close parentheses in the type name \"{typeNameSpan.ToString()}\".");
                }

                if (currentIdx != typeNameSpan.Length - 1)
                {
                    var unexpectedString = typeNameSpan.Slice(currentIdx + 1);
                    if (!unexpectedString.Trim().IsEmpty)
                    {
                        throw new ClickHouseException(
                                  ClickHouseErrorCodes.InvalidTypeName,
                                  $"There are unexpected characters (\"{unexpectedString.ToString()}\") in the type name \"{typeNameSpan.ToString()}\" after closing parenthesis.");
                    }
                }

                var lastOption = typeName.Slice(optionStartIdx, currentIdx - optionStartIdx).Trim();
                if (options != null)
                {
                    options.Add(lastOption);
                }
                else
                {
                    options = new List <ReadOnlyMemory <char> >(1)
                    {
                        lastOption
                    }
                };
            }

            return(baseTypeName, options);
        }