public DatabaseObjectMultipartName(string currentDatabase, string name)
        {
            if (name != null)
            {
                var parser = new IdentifierParser(new StringReader(name));
                var parts  = parser.Parse().ToArray();

                var i = parts.Length - 1;
                var commandBuilder = new SqlCommandBuilder();

                if (i >= 0)
                {
                    Name = parts[i];
                    i--;

                    if (i >= 0)
                    {
                        Schema = parts[i];
                        i--;

                        if (i >= 0)
                        {
                            Database = parts[i];
                            i--;

                            if (i >= 0)
                            {
                                _server = parts[i];
                            }
                        }
                    }
                }
            }

            if (Database == null)
            {
                Database = currentDatabase;
            }

            if (string.IsNullOrEmpty(Schema))
            {
                Schema = null;
            }

            if (Name != null)
            {
                var length = Name.Length;

                if (length > 0 && Name[0] == '[')
                {
                    Name = Name.Substring(1);
                    length--;
                }

                if (length > 0 && Name[length - 1] == ']')
                {
                    Name = Name.Substring(0, length - 1);
                }
            }
        }
예제 #2
0
        GetCompletionResponse IProvider.GetCompletion(ConnectionBase connection, IDbTransaction transaction, string text, int position)
        {
            var response = new GetCompletionResponse
            {
                FromCache = false
            };
            List <IObjectName> array = null;
            var sqlStatement         = new SqlParser(text);
            var tokens = sqlStatement.Tokens;

            sqlStatement.FindToken(position, out var previousToken, out var currentToken);

            if (currentToken != null)
            {
                var parts          = new IdentifierParser(new StringReader(currentToken.Value)).Parse().ToList();
                var lastPart       = parts.Count > 0 ? parts.Last() : null;
                var lastPartLength = lastPart != null ? lastPart.Length : 0;
                response.StartPosition = currentToken.EndPosition - lastPartLength + 1;
                response.Length        = lastPartLength;
                var value = currentToken.Value;
                if (value.Length > 0 && value[0] == '@')
                {
                    if (value.IndexOf("@@") == 0)
                    {
                        // array = keyWords.Where(k => k.StartsWith(value)).Select(keyWord => (IObjectName)new NonSqlObjectName(keyWord)).ToList();
                    }
                    else
                    {
                        var list = new SortedList <string, object>();

                        for (var i = 0; i < tokens.Count; i++)
                        {
                            var token   = tokens[i];
                            var keyWord = token.Value;

                            if (keyWord != null && keyWord.Length >= 2 && keyWord.IndexOf(value) == 0 && keyWord != value)
                            {
                                if (!list.ContainsKey(token.Value))
                                {
                                    list.Add(token.Value, null);
                                }
                            }
                        }

                        array = list.Keys.Select(keyWord => (IObjectName) new NonSqlObjectName(keyWord)).ToList();
                    }
                }
            }
            else
            {
                response.StartPosition = position;
                response.Length        = 0;
            }

            if (array == null)
            {
                var    sqlObject   = sqlStatement.FindSqlObject(previousToken, currentToken);
                string commandText = null;

                if (sqlObject != null)
                {
                    DatabaseObjectMultipartName name;
                    int i;

                    switch (sqlObject.Type)
                    {
                    case SqlObjectTypes.Database:
                        // TODO commandText = SqlServerObject.GetDatabases();
                        break;

                    case SqlObjectTypes.Table:
                    case SqlObjectTypes.View:
                    case SqlObjectTypes.Function:
                    case SqlObjectTypes.Table | SqlObjectTypes.View:
                    case SqlObjectTypes.Table | SqlObjectTypes.View | SqlObjectTypes.Function:
                    {
                        name = new DatabaseObjectMultipartName(connection.Database, sqlObject.Name);
                        var nameParts = sqlObject.Name != null
                                ? new IdentifierParser(new StringReader(sqlObject.Name)).Parse().ToList()
                                : null;
                        var namePartsCount = nameParts != null ? nameParts.Count : 0;
                        var statements     = new List <string>();

                        switch (namePartsCount)
                        {
                        case 0:
                        case 1:
                        {
                            // statements.Add(SqlServerObject.GetDatabases());
                            statements.Add(SqlServerObject.GetSchemas());

                            //var objectTypes = sqlObject.Type.ToObjectTypes();
                            //statements.Add(SqlServerObject.GetObjects(schema: "dbo", objectTypes: objectTypes));
                        }
                        break;

                        case 2:
                            if (nameParts[0] != null)
                            {
                                // TODO statements.Add(SqlServerObject.GetSchemas(database: nameParts[0]));

                                var objectTypes = sqlObject.Type.ToTableTypes();
                                statements.Add(SqlServerObject.GetTables(schema: nameParts[0], tableTypes: objectTypes));
                            }

                            break;

                        case 3:
                        {
                            if (nameParts[0] != null && nameParts[1] != null)
                            {
                                var objectTypes = sqlObject.Type.ToObjectTypes();
                                statements.Add(SqlServerObject.GetObjects(database: nameParts[0], schema: nameParts[1], objectTypes: objectTypes));
                            }
                        }
                        break;
                        }

                        commandText = statements.Count > 0 ? string.Join("\r\n", statements) : null;
                    }
                    break;

                    case SqlObjectTypes.Column:
                        name = new DatabaseObjectMultipartName(connection.Database, sqlObject.ParentName);
                        string[] owners;

                        if (name.Schema != null)
                        {
                            owners = new[] { name.Schema };
                        }
                        else
                        {
                            owners = new[] { "dbo", "sys" };
                        }

                        var sb = new StringBuilder();
                        for (i = 0; i < owners.Length; i++)
                        {
                            if (i > 0)
                            {
                                sb.Append(',');
                            }

                            sb.AppendFormat("'{0}'", owners[i]);
                        }

                        var ownersString = sb.ToString();
                        commandText =
                            $@"select c.column_name
from information_schema.columns c
where
    c.table_schema = '{name.Schema}'
    and c.table_name = '{name.Name}'
order by c.ordinal_position";
                        break;

                    case SqlObjectTypes.Procedure:
                        name = new DatabaseObjectMultipartName(connection.Database, sqlObject.Name);

                        if (name.Schema == null)
                        {
                            name.Schema = "dbo";
                        }

                        commandText = string.Format(@"select
     s.name
    ,o.name
from [{0}].sys.objects o
join [{0}].sys.schemas s
on o.schema_id = s.schema_id
where   o.type in('P','X')
order by 1", name.Database);
                        break;

                    case SqlObjectTypes.Trigger:
                        commandText = "select name from sysobjects where xtype = 'TR' order by name";
                        break;

                    case SqlObjectTypes.Value:
                        var items = sqlObject.ParentName.Split('.');
                        i = items.Length - 1;
                        var    columnName       = items[i];
                        string tableNameOrAlias = null;
                        if (i > 0)
                        {
                            i--;
                            tableNameOrAlias = items[i];
                        }

                        if (tableNameOrAlias != null)
                        {
                            var contains = sqlStatement.Tables.TryGetValue(tableNameOrAlias, out var tableName);
                            if (contains)
                            {
                                string where;
                                var tokenIndex = previousToken.Index + 1;
                                if (tokenIndex < tokens.Count)
                                {
                                    var token      = tokens[tokenIndex];
                                    var tokenValue = token.Value;
                                    var indexofAny = tokenValue.IndexOfAny(new[] { '\r', '\n' });
                                    if (indexofAny >= 0)
                                    {
                                        tokenValue = tokenValue.Substring(0, indexofAny);
                                    }

                                    string like;
                                    if (tokenValue.Length > 0)
                                    {
                                        if (tokenValue.Contains('%'))
                                        {
                                            like = tokenValue;
                                        }
                                        else
                                        {
                                            like = tokenValue + '%';
                                        }
                                    }
                                    else
                                    {
                                        like = "%";
                                    }

                                    @where = $"where {columnName} like N'{like}'";
                                }
                                else
                                {
                                    @where = null;
                                }

                                commandText = $"select distinct top 100 {columnName} from {tableName} (readpast) {@where} order by 1";
                            }
                        }

                        break;
                    }
                }

                if (commandText != null)
                {
                    Log.Write(LogLevel.Trace, "commandText:\r\n{0}", commandText);
                    var list = new List <IObjectName>();
                    try
                    {
                        if (connection.State != ConnectionState.Open)
                        {
                            connection.OpenAsync(CancellationToken.None).Wait();
                        }

                        var executor = connection.Connection.CreateCommandExecutor();
                        //new DbTransactionScope(connection.Connection, transaction);
                        executor.ExecuteReader(new ExecuteReaderRequest(commandText), dataReader =>
                        {
                            while (true)
                            {
                                var fieldCount = dataReader.FieldCount;
                                while (dataReader.Read())
                                {
                                    string schemaName;
                                    string objectName;

                                    if (fieldCount == 1)
                                    {
                                        schemaName = null;
                                        objectName = dataReader.GetString(0);
                                    }
                                    else
                                    {
                                        schemaName = dataReader.GetStringOrDefault(0);
                                        objectName = dataReader.GetString(1);
                                    }

                                    list.Add(new ObjectName(sqlObject, schemaName, objectName));
                                }

                                if (!dataReader.NextResult())
                                {
                                    break;
                                }
                            }
                        });
                    }
                    catch
                    {
                    }

                    array = list;
                }
            }

            response.Items = array;
            return(response);
        }