/// <summary>
        /// Gets the definition of a User defined type
        /// </summary>
        public UdtColumnInfo GetUdtDefinition(string keyspace, string typeName)
        {
            var rs  = Query(String.Format(SelectUdts + " WHERE keyspace_name='{0}' AND type_name = '{1}';", keyspace, typeName));
            var row = rs.FirstOrDefault();

            if (row == null)
            {
                return(null);
            }
            var udt        = new UdtColumnInfo(row.GetValue <string>("keyspace_name") + "." + row.GetValue <string>("type_name"));
            var fieldNames = row.GetValue <List <string> >("field_names");
            var fieldTypes = row.GetValue <List <string> >("field_types");

            if (fieldNames.Count != fieldTypes.Count)
            {
                var ex = new DriverInternalError("Field names and types for UDT do not match");
                _logger.Error(ex);
                throw ex;
            }
            for (var i = 0; i < fieldNames.Count; i++)
            {
                var field = TypeCodec.ParseDataType(fieldTypes[i]);
                field.Name = fieldNames[i];
                udt.Fields.Add(field);
            }
            return(udt);
        }
        public void ParseDataTypeNameFrozenTest()
        {
            var dataType = TypeCodec.ParseDataType("org.apache.cassandra.db.marshal.FrozenType(org.apache.cassandra.db.marshal.ListType(org.apache.cassandra.db.marshal.TimeUUIDType))");

            Assert.AreEqual(ColumnTypeCode.List, dataType.TypeCode);
            Assert.IsInstanceOf <ListColumnInfo>(dataType.TypeInfo);
            Assert.AreEqual(ColumnTypeCode.Timeuuid, (dataType.TypeInfo as ListColumnInfo).ValueTypeCode);

            dataType = TypeCodec.ParseDataType("org.apache.cassandra.db.marshal.MapType(org.apache.cassandra.db.marshal.UTF8Type,org.apache.cassandra.db.marshal.FrozenType(org.apache.cassandra.db.marshal.ListType(org.apache.cassandra.db.marshal.Int32Type)))");
            Assert.AreEqual(ColumnTypeCode.Map, dataType.TypeCode);
            Assert.IsInstanceOf <MapColumnInfo>(dataType.TypeInfo);
            Assert.AreEqual(ColumnTypeCode.Varchar, (dataType.TypeInfo as MapColumnInfo).KeyTypeCode);
            Assert.AreEqual(ColumnTypeCode.List, (dataType.TypeInfo as MapColumnInfo).ValueTypeCode);
            var subType = (ListColumnInfo)((dataType.TypeInfo as MapColumnInfo).ValueTypeInfo);

            Assert.AreEqual(ColumnTypeCode.Int, subType.ValueTypeCode);
        }
Exemple #3
0
        /// <summary>
        /// Creates a new instance of function metadata based on a schema_function row.
        /// </summary>
        internal static FunctionMetadata Build(Row row)
        {
            var emptyArray = new string[0];

            return(new FunctionMetadata
            {
                Name = row.GetValue <string>("function_name"),
                KeyspaceName = row.GetValue <string>("keyspace_name"),
                Signature = row.GetValue <string[]>("signature") ?? emptyArray,
                ArgumentNames = row.GetValue <string[]>("argument_names") ?? emptyArray,
                Body = row.GetValue <string>("body"),
                CalledOnNullInput = row.GetValue <bool>("called_on_null_input"),
                Language = row.GetValue <string>("language"),
                ReturnType = TypeCodec.ParseDataType(row.GetValue <string>("return_type")),
                ArgumentTypes = (row.GetValue <string[]>("argument_types") ?? emptyArray).Select(s => TypeCodec.ParseDataType(s)).ToArray()
            });
        }
Exemple #4
0
        /// <summary>
        /// Creates a new instance of function metadata based on a schema_function row.
        /// </summary>
        internal static AggregateMetadata Build(int protocolVersion, Row row)
        {
            var emptyArray = new string[0];
            var aggregate  = new AggregateMetadata
            {
                Name          = row.GetValue <string>("aggregate_name"),
                KeyspaceName  = row.GetValue <string>("keyspace_name"),
                Signature     = row.GetValue <string[]>("signature") ?? emptyArray,
                StateFunction = row.GetValue <string>("state_func"),
                StateType     = TypeCodec.ParseDataType(row.GetValue <string>("state_type")),
                FinalFunction = row.GetValue <string>("final_func"),
                ReturnType    = TypeCodec.ParseDataType(row.GetValue <string>("return_type")),
                ArgumentTypes = (row.GetValue <string[]>("argument_types") ?? emptyArray).Select(s => TypeCodec.ParseDataType(s)).ToArray(),
            };

            aggregate.InitialCondition = TypeCodec.Decode(protocolVersion, row.GetValue <byte[]>("initcond"), aggregate.StateType.TypeCode, aggregate.StateType.TypeInfo);
            return(aggregate);
        }
        public void ParseDataTypeNameSingleTest()
        {
            var dataType = TypeCodec.ParseDataType("org.apache.cassandra.db.marshal.Int32Type");

            Assert.AreEqual(ColumnTypeCode.Int, dataType.TypeCode);
            dataType = TypeCodec.ParseDataType("org.apache.cassandra.db.marshal.UUIDType");
            Assert.AreEqual(ColumnTypeCode.Uuid, dataType.TypeCode);
            dataType = TypeCodec.ParseDataType("org.apache.cassandra.db.marshal.UTF8Type");
            Assert.AreEqual(ColumnTypeCode.Varchar, dataType.TypeCode);
            dataType = TypeCodec.ParseDataType("org.apache.cassandra.db.marshal.BytesType");
            Assert.AreEqual(ColumnTypeCode.Blob, dataType.TypeCode);
            dataType = TypeCodec.ParseDataType("org.apache.cassandra.db.marshal.FloatType");
            Assert.AreEqual(ColumnTypeCode.Float, dataType.TypeCode);
            dataType = TypeCodec.ParseDataType("org.apache.cassandra.db.marshal.DoubleType");
            Assert.AreEqual(ColumnTypeCode.Double, dataType.TypeCode);
            dataType = TypeCodec.ParseDataType("org.apache.cassandra.db.marshal.BooleanType");
            Assert.AreEqual(ColumnTypeCode.Boolean, dataType.TypeCode);
            dataType = TypeCodec.ParseDataType("org.apache.cassandra.db.marshal.InetAddressType");
            Assert.AreEqual(ColumnTypeCode.Inet, dataType.TypeCode);
            dataType = TypeCodec.ParseDataType("org.apache.cassandra.db.marshal.DateType");
            Assert.AreEqual(ColumnTypeCode.Timestamp, dataType.TypeCode);
            dataType = TypeCodec.ParseDataType("org.apache.cassandra.db.marshal.TimestampType");
            Assert.AreEqual(ColumnTypeCode.Timestamp, dataType.TypeCode);
            dataType = TypeCodec.ParseDataType("org.apache.cassandra.db.marshal.LongType");
            Assert.AreEqual(ColumnTypeCode.Bigint, dataType.TypeCode);
            dataType = TypeCodec.ParseDataType("org.apache.cassandra.db.marshal.DecimalType");
            Assert.AreEqual(ColumnTypeCode.Decimal, dataType.TypeCode);
            dataType = TypeCodec.ParseDataType("org.apache.cassandra.db.marshal.IntegerType");
            Assert.AreEqual(ColumnTypeCode.Varint, dataType.TypeCode);
            dataType = TypeCodec.ParseDataType("org.apache.cassandra.db.marshal.CounterColumnType");
            Assert.AreEqual(ColumnTypeCode.Counter, dataType.TypeCode);
            dataType = TypeCodec.ParseDataType("org.apache.cassandra.db.marshal.TimeUUIDType");
            Assert.AreEqual(ColumnTypeCode.Timeuuid, dataType.TypeCode);
            dataType = TypeCodec.ParseDataType("org.apache.cassandra.db.marshal.AsciiType");
            Assert.AreEqual(ColumnTypeCode.Ascii, dataType.TypeCode);
            dataType = TypeCodec.ParseDataType("org.apache.cassandra.db.marshal.SimpleDateType");
            Assert.AreEqual(ColumnTypeCode.Date, dataType.TypeCode);
            dataType = TypeCodec.ParseDataType("org.apache.cassandra.db.marshal.TimeType");
            Assert.AreEqual(ColumnTypeCode.Time, dataType.TypeCode);
            dataType = TypeCodec.ParseDataType("org.apache.cassandra.db.marshal.ShortType");
            Assert.AreEqual(ColumnTypeCode.SmallInt, dataType.TypeCode);
            dataType = TypeCodec.ParseDataType("org.apache.cassandra.db.marshal.ByteType");
            Assert.AreEqual(ColumnTypeCode.TinyInt, dataType.TypeCode);
        }
Exemple #6
0
        public void ParseDataTypeNameMultipleTest()
        {
            var dataType = TypeCodec.ParseDataType("org.apache.cassandra.db.marshal.ListType(org.apache.cassandra.db.marshal.Int32Type)");

            Assert.AreEqual(ColumnTypeCode.List, dataType.TypeCode);
            Assert.IsInstanceOf <ListColumnInfo>(dataType.TypeInfo);
            Assert.AreEqual(ColumnTypeCode.Int, (dataType.TypeInfo as ListColumnInfo).ValueTypeCode);

            dataType = TypeCodec.ParseDataType("org.apache.cassandra.db.marshal.SetType(org.apache.cassandra.db.marshal.UUIDType)");
            Assert.AreEqual(ColumnTypeCode.Set, dataType.TypeCode);
            Assert.IsInstanceOf <SetColumnInfo>(dataType.TypeInfo);
            Assert.AreEqual(ColumnTypeCode.Uuid, (dataType.TypeInfo as SetColumnInfo).KeyTypeCode);

            dataType = TypeCodec.ParseDataType("org.apache.cassandra.db.marshal.MapType(org.apache.cassandra.db.marshal.UTF8Type,org.apache.cassandra.db.marshal.LongType)");
            Assert.AreEqual(ColumnTypeCode.Map, dataType.TypeCode);
            Assert.IsInstanceOf <MapColumnInfo>(dataType.TypeInfo);
            Assert.AreEqual(ColumnTypeCode.Varchar, (dataType.TypeInfo as MapColumnInfo).KeyTypeCode);
            Assert.AreEqual(ColumnTypeCode.Bigint, (dataType.TypeInfo as MapColumnInfo).ValueTypeCode);
        }
Exemple #7
0
        public void ParseDataTypeNameUdtTest()
        {
            var typeText =
                "org.apache.cassandra.db.marshal.UserType(" +
                "tester,70686f6e65,616c696173:org.apache.cassandra.db.marshal.UTF8Type,6e756d626572:org.apache.cassandra.db.marshal.UTF8Type" +
                ")";
            var dataType = TypeCodec.ParseDataType(typeText);

            Assert.AreEqual(ColumnTypeCode.Udt, dataType.TypeCode);
            //Udt name
            Assert.AreEqual("phone", dataType.Name);
            Assert.IsInstanceOf <UdtColumnInfo>(dataType.TypeInfo);
            var subTypes = (dataType.TypeInfo as UdtColumnInfo).Fields;

            Assert.AreEqual(2, subTypes.Count);
            Assert.AreEqual("alias", subTypes[0].Name);
            Assert.AreEqual(ColumnTypeCode.Varchar, subTypes[0].TypeCode);
            Assert.AreEqual("number", subTypes[1].Name);
            Assert.AreEqual(ColumnTypeCode.Varchar, subTypes[1].TypeCode);
        }
        /// <summary>
        /// Gets the definition of a User defined type
        /// </summary>
        internal UdtColumnInfo GetUdtDefinition(string typeName)
        {
            var keyspaceName = Name;
            var rs           = _cc.Query(String.Format(SelectUdts, keyspaceName, typeName), true);
            var row          = rs.FirstOrDefault();

            if (row == null)
            {
                return(null);
            }
            var udt        = new UdtColumnInfo(row.GetValue <string>("keyspace_name") + "." + row.GetValue <string>("type_name"));
            var fieldNames = row.GetValue <List <string> >("field_names");
            var fieldTypes = row.GetValue <List <string> >("field_types");

            for (var i = 0; i < fieldNames.Count && i < fieldTypes.Count; i++)
            {
                var field = TypeCodec.ParseDataType(fieldTypes[i]);
                field.Name = fieldNames[i];
                udt.Fields.Add(field);
            }
            return(udt);
        }
Exemple #9
0
        public void ParseDataTypeNameUdtNestedTest()
        {
            var typeText =
                "org.apache.cassandra.db.marshal.UserType(" +
                "tester," +
                "61646472657373," +
                "737472656574:org.apache.cassandra.db.marshal.UTF8Type," +
                "5a4950:org.apache.cassandra.db.marshal.Int32Type," +
                "70686f6e6573:org.apache.cassandra.db.marshal.SetType(" +
                "org.apache.cassandra.db.marshal.UserType(" +
                "tester," +
                "70686f6e65," +
                "616c696173:org.apache.cassandra.db.marshal.UTF8Type," +
                "6e756d626572:org.apache.cassandra.db.marshal.UTF8Type))" +
                ")";
            var dataType = TypeCodec.ParseDataType(typeText);

            Assert.AreEqual(ColumnTypeCode.Udt, dataType.TypeCode);
            Assert.IsInstanceOf <UdtColumnInfo>(dataType.TypeInfo);
            Assert.AreEqual("address", dataType.Name);
            Assert.AreEqual("tester.address", (dataType.TypeInfo as UdtColumnInfo).Name);
            var subTypes = (dataType.TypeInfo as UdtColumnInfo).Fields;

            Assert.AreEqual(3, subTypes.Count);
            Assert.AreEqual("street,ZIP,phones", String.Join(",", subTypes.Select(s => s.Name)));
            Assert.AreEqual(ColumnTypeCode.Varchar, subTypes[0].TypeCode);
            Assert.AreEqual(ColumnTypeCode.Set, subTypes[2].TypeCode);
            //field name
            Assert.AreEqual("phones", subTypes[2].Name);

            var phonesSubType = (UdtColumnInfo)((SetColumnInfo)subTypes[2].TypeInfo).KeyTypeInfo;

            Assert.AreEqual("tester.phone", phonesSubType.Name);
            Assert.AreEqual(2, phonesSubType.Fields.Count);
            Assert.AreEqual("alias", phonesSubType.Fields[0].Name);
            Assert.AreEqual("number", phonesSubType.Fields[1].Name);
        }
        /// <summary>
        ///  Returns metadata of specified table in this keyspace.
        /// </summary>
        /// <param name="tableName"> the name of table to retrieve </param>
        /// <returns>the metadata for table <c>tableName</c> in this keyspace if it
        ///  exists, <c>null</c> otherwise.</returns>
        public TableMetadata GetTableMetadata(string tableName)
        {
            TableMetadata table;

            if (_tables.TryGetValue(tableName, out table))
            {
                //The table metadata is available in local cache
                return(table);
            }
            var keyspaceName     = Name;
            var columns          = new Dictionary <string, TableColumn>();
            var partitionKeys    = new List <Tuple <int, TableColumn> >();
            var tableMetadataRow = _cc.Query(String.Format(SelectSingleTable, tableName, keyspaceName), true).FirstOrDefault();

            if (tableMetadataRow == null)
            {
                return(null);
            }
            //Read table options
            var options = new TableOptions
            {
                isCompactStorage  = false,
                bfFpChance        = tableMetadataRow.GetValue <double>("bloom_filter_fp_chance"),
                caching           = tableMetadataRow.GetValue <string>("caching"),
                comment           = tableMetadataRow.GetValue <string>("comment"),
                gcGrace           = tableMetadataRow.GetValue <int>("gc_grace_seconds"),
                localReadRepair   = tableMetadataRow.GetValue <double>("local_read_repair_chance"),
                readRepair        = tableMetadataRow.GetValue <double>("read_repair_chance"),
                compactionOptions = GetCompactionStrategyOptions(tableMetadataRow),
                compressionParams =
                    (SortedDictionary <string, string>)Utils.ConvertStringToMap(tableMetadataRow.GetValue <string>("compression_parameters"))
            };

            //replicate_on_write column not present in C* >= 2.1
            if (tableMetadataRow.GetColumn("replicate_on_write") != null)
            {
                options.replicateOnWrite = tableMetadataRow.GetValue <bool>("replicate_on_write");
            }

            var columnsMetadata = _cc.Query(String.Format(SelectColumns, tableName, keyspaceName), true);

            foreach (var row in columnsMetadata)
            {
                var dataType = TypeCodec.ParseDataType(row.GetValue <string>("validator"));
                var col      = new TableColumn
                {
                    Name               = row.GetValue <string>("column_name"),
                    Keyspace           = row.GetValue <string>("keyspace_name"),
                    Table              = row.GetValue <string>("columnfamily_name"),
                    TypeCode           = dataType.TypeCode,
                    TypeInfo           = dataType.TypeInfo,
                    SecondaryIndexName = row.GetValue <string>("index_name"),
                    SecondaryIndexType = row.GetValue <string>("index_type"),
                    KeyType            =
                        row.GetValue <string>("index_name") != null
                            ? KeyType.SecondaryIndex
                            : KeyType.None,
                };
                if (row.GetColumn("type") != null && row.GetValue <string>("type") == "partition_key")
                {
                    partitionKeys.Add(Tuple.Create(row.GetValue <int?>("component_index") ?? 0, col));
                }
                columns.Add(col.Name, col);
            }
            var comparator          = tableMetadataRow.GetValue <string>("comparator");
            var comparatorComposite = false;

            if (comparator.StartsWith(TypeCodec.CompositeTypeName))
            {
                comparator          = comparator.Replace(TypeCodec.CompositeTypeName, "");
                comparatorComposite = true;
            }
            //Remove reversed type
            comparator = comparator.Replace(TypeCodec.ReversedTypeName, "");
            if (partitionKeys.Count == 0 && tableMetadataRow.GetColumn("key_aliases") != null)
            {
                //In C* 1.2, keys are not stored on the schema_columns table
                var colNames = tableMetadataRow.GetValue <string>("column_aliases");
                var rowKeys  = colNames.Substring(1, colNames.Length - 2).Split(',');
                for (var i = 0; i < rowKeys.Length; i++)
                {
                    if (rowKeys[i].StartsWith("\""))
                    {
                        rowKeys[i] = rowKeys[i].Substring(1, rowKeys[i].Length - 2).Replace("\"\"", "\"");
                    }
                }
                if (rowKeys.Length > 0 && rowKeys[0] != string.Empty)
                {
                    var rg           = new Regex(@"org\.apache\.cassandra\.db\.marshal\.\w+");
                    var rowKeysTypes = rg.Matches(comparator);

                    for (var i = 0; i < rowKeys.Length; i++)
                    {
                        var keyName  = rowKeys[i];
                        var dataType = TypeCodec.ParseDataType(rowKeysTypes[i].ToString());
                        var dsc      = new TableColumn
                        {
                            Name     = keyName,
                            Keyspace = tableMetadataRow.GetValue <string>("keyspace_name"),
                            Table    = tableMetadataRow.GetValue <string>("columnfamily_name"),
                            TypeCode = dataType.TypeCode,
                            TypeInfo = dataType.TypeInfo,
                            KeyType  = KeyType.Clustering,
                        };
                        columns[dsc.Name] = dsc;
                    }
                }
                var keys = tableMetadataRow.GetValue <string>("key_aliases")
                           .Replace("[", "")
                           .Replace("]", "")
                           .Split(',');
                var keyTypes = tableMetadataRow.GetValue <string>("key_validator")
                               .Replace("org.apache.cassandra.db.marshal.CompositeType", "")
                               .Replace("(", "")
                               .Replace(")", "")
                               .Split(',');


                for (var i = 0; i < keys.Length; i++)
                {
                    var name     = keys[i].Replace("\"", "").Trim();
                    var dataType = TypeCodec.ParseDataType(keyTypes[i].Trim());
                    var c        = new TableColumn()
                    {
                        Name     = name,
                        Keyspace = tableMetadataRow.GetValue <string>("keyspace_name"),
                        Table    = tableMetadataRow.GetValue <string>("columnfamily_name"),
                        TypeCode = dataType.TypeCode,
                        TypeInfo = dataType.TypeInfo,
                        KeyType  = KeyType.Partition
                    };
                    columns[name] = c;
                    partitionKeys.Add(Tuple.Create(i, c));
                }
            }

            options.isCompactStorage = tableMetadataRow.GetColumn("is_dense") != null && tableMetadataRow.GetValue <bool>("is_dense");
            if (!options.isCompactStorage)
            {
                //is_dense column does not exist in previous versions of Cassandra
                //also, compact pk, ck and val appear as is_dense false
                // clusteringKeys != comparator types - 1
                // or not composite (comparator)
                options.isCompactStorage = !comparatorComposite;
            }

            table = new TableMetadata(
                tableName, columns.Values.ToArray(),
                partitionKeys.OrderBy(p => p.Item1).Select(p => p.Item2).ToArray(),
                options);
            //Cache it
            _tables.AddOrUpdate(tableName, table, (k, o) => table);
            return(table);
        }
        /// <summary>
        ///  Returns metadata of specified table in this keyspace.
        /// </summary>
        /// <param name="tableName"> the name of table to retrieve </param>
        /// <returns>the metadata for table <c>tableName</c> in this keyspace if it
        ///  exists, <c>null</c> otherwise.</returns>
        public TableMetadata GetTableMetadata(string tableName)
        {
            TableMetadata table;

            if (_tables.TryGetValue(tableName, out table))
            {
                //The table metadata is available in local cache
                return(table);
            }
            var          keyspaceName     = Name;
            var          cols             = new Dictionary <string, TableColumn>();
            TableOptions options          = null;
            var          tableMetadataRow = _cc.Query(String.Format(SelectSingleTable, tableName, keyspaceName), true).FirstOrDefault();

            if (tableMetadataRow == null)
            {
                return(null);
            }
            var columnsMetadata = _cc.Query(String.Format(SelectColumns, tableName, keyspaceName), true);

            foreach (var row in columnsMetadata)
            {
                var dataType = TypeCodec.ParseDataType(row.GetValue <string>("validator"));
                var dsc      = new TableColumn
                {
                    Name               = row.GetValue <string>("column_name"),
                    Keyspace           = row.GetValue <string>("keyspace_name"),
                    Table              = row.GetValue <string>("columnfamily_name"),
                    TypeCode           = dataType.TypeCode,
                    TypeInfo           = dataType.TypeInfo,
                    SecondaryIndexName = row.GetValue <string>("index_name"),
                    SecondaryIndexType = row.GetValue <string>("index_type"),
                    KeyType            =
                        row.GetValue <string>("index_name") != null
                            ? KeyType.SecondaryIndex
                            : KeyType.None,
                };
                cols.Add(dsc.Name, dsc);
            }

            var colNames = tableMetadataRow.GetValue <string>("column_aliases");
            var rowKeys  = colNames.Substring(1, colNames.Length - 2).Split(',');

            for (var i = 0; i < rowKeys.Length; i++)
            {
                if (rowKeys[i].StartsWith("\""))
                {
                    rowKeys[i] = rowKeys[i].Substring(1, rowKeys[i].Length - 2).Replace("\"\"", "\"");
                }
            }
            if (rowKeys.Length > 0 && rowKeys[0] != string.Empty)
            {
                bool isCompact  = true;
                var  comparator = tableMetadataRow.GetValue <string>("comparator");
                //Remove reversed type
                comparator = comparator.Replace(TypeCodec.ReversedTypeName, "");
                if (comparator.StartsWith(TypeCodec.CompositeTypeName))
                {
                    comparator = comparator.Replace(TypeCodec.CompositeTypeName, "");
                    isCompact  = false;
                }

                var rg           = new Regex(@"org\.apache\.cassandra\.db\.marshal\.\w+");
                var rowKeysTypes = rg.Matches(comparator);

                for (var i = 0; i < rowKeys.Length; i++)
                {
                    var keyName  = rowKeys[i];
                    var dataType = TypeCodec.ParseDataType(rowKeysTypes[i].ToString());
                    var dsc      = new TableColumn
                    {
                        Name     = keyName,
                        Keyspace = tableMetadataRow.GetValue <string>("keyspace_name"),
                        Table    = tableMetadataRow.GetValue <string>("columnfamily_name"),
                        TypeCode = dataType.TypeCode,
                        TypeInfo = dataType.TypeInfo,
                        KeyType  = KeyType.Clustering,
                    };
                    cols[dsc.Name] = dsc;
                }

                options = new TableOptions
                {
                    isCompactStorage  = isCompact,
                    bfFpChance        = tableMetadataRow.GetValue <double>("bloom_filter_fp_chance"),
                    caching           = tableMetadataRow.GetValue <string>("caching"),
                    comment           = tableMetadataRow.GetValue <string>("comment"),
                    gcGrace           = tableMetadataRow.GetValue <int>("gc_grace_seconds"),
                    localReadRepair   = tableMetadataRow.GetValue <double>("local_read_repair_chance"),
                    readRepair        = tableMetadataRow.GetValue <double>("read_repair_chance"),
                    compactionOptions = GetCompactionStrategyOptions(tableMetadataRow),
                    compressionParams =
                        (SortedDictionary <string, string>)Utils.ConvertStringToMap(tableMetadataRow.GetValue <string>("compression_parameters"))
                };
                //replicate_on_write column not present in C* >= 2.1
                if (tableMetadataRow.GetColumn("replicate_on_write") != null)
                {
                    options.replicateOnWrite = tableMetadataRow.GetValue <bool>("replicate_on_write");
                }
            }
            //In Cassandra 1.2, the keys are not stored in the system.schema_columns table
            //But you can get it from system.schema_columnfamilies
            var keys = tableMetadataRow.GetValue <string>("key_aliases")
                       .Replace("[", "")
                       .Replace("]", "")
                       .Split(',');
            var keyTypes = tableMetadataRow.GetValue <string>("key_validator")
                           .Replace("org.apache.cassandra.db.marshal.CompositeType", "")
                           .Replace("(", "")
                           .Replace(")", "")
                           .Split(',');
            var partitionKeys = new TableColumn[keys.Length];

            for (var i = 0; i < keys.Length; i++)
            {
                var name     = keys[i].Replace("\"", "").Trim();
                var dataType = TypeCodec.ParseDataType(keyTypes[i].Trim());
                var c        = new TableColumn()
                {
                    Name     = name,
                    Keyspace = tableMetadataRow.GetValue <string>("keyspace_name"),
                    Table    = tableMetadataRow.GetValue <string>("columnfamily_name"),
                    TypeCode = dataType.TypeCode,
                    TypeInfo = dataType.TypeInfo,
                    KeyType  = KeyType.Partition
                };
                cols[name]       = c;
                partitionKeys[i] = c;
            }

            table = new TableMetadata(tableName, cols.Values.ToArray(), partitionKeys, options);
            //Cache it
            _tables.AddOrUpdate(tableName, table, (k, o) => table);
            return(table);
        }
        public TableMetadata GetTableMetadata(string tableName, string keyspaceName)
        {
            var          cols    = new Dictionary <string, TableColumn>();
            TableOptions options = null;

            {
                var cqlQuery = string.Format(SelectColumns + " WHERE columnfamily_name='{0}' AND keyspace_name='{1}';", tableName, keyspaceName);
                var rows     = Query(cqlQuery);
                foreach (var row in rows)
                {
                    var dataType = TypeCodec.ParseDataType(row.GetValue <string>("validator"));
                    var dsc      = new TableColumn
                    {
                        Name               = row.GetValue <string>("column_name"),
                        Keyspace           = row.GetValue <string>("keyspace_name"),
                        Table              = row.GetValue <string>("columnfamily_name"),
                        TypeCode           = dataType.TypeCode,
                        TypeInfo           = dataType.TypeInfo,
                        SecondaryIndexName = row.GetValue <string>("index_name"),
                        SecondaryIndexType = row.GetValue <string>("index_type"),
                        KeyType            =
                            row.GetValue <string>("index_name") != null
                                ? KeyType.SecondaryIndex
                                : KeyType.None,
                    };

                    cols.Add(dsc.Name, dsc);
                }
            }
            {
                var cqlQuery = string.Format(SelectColumnFamilies + " WHERE columnfamily_name='{0}' AND keyspace_name='{1}';", tableName, keyspaceName);
                var rows     = Query(cqlQuery);
                var row      = rows.First();
                var colNames = row.GetValue <string>("column_aliases");
                var rowKeys  = colNames.Substring(1, colNames.Length - 2).Split(',');
                for (var i = 0; i < rowKeys.Length; i++)
                {
                    if (rowKeys[i].StartsWith("\""))
                    {
                        rowKeys[i] = rowKeys[i].Substring(1, rowKeys[i].Length - 2).Replace("\"\"", "\"");
                    }
                }
                //Needs cleanup
                if (rowKeys.Length > 0 && rowKeys[0] != string.Empty)
                {
                    bool isCompact  = true;
                    var  comparator = row.GetValue <string>("comparator");
                    //Remove reversed type
                    comparator = comparator.Replace(TypeCodec.ReversedTypeName, "");
                    if (comparator.StartsWith(TypeCodec.CompositeTypeName))
                    {
                        comparator = comparator.Replace(TypeCodec.CompositeTypeName, "");
                        isCompact  = false;
                    }

                    var             rg           = new Regex(@"org\.apache\.cassandra\.db\.marshal\.\w+");
                    MatchCollection rowKeysTypes = rg.Matches(comparator);

                    int i = 0;
                    foreach (var keyName in rowKeys)
                    {
                        var dataType = TypeCodec.ParseDataType(rowKeysTypes[i].ToString());
                        var dsc      = new TableColumn
                        {
                            Name     = keyName,
                            Keyspace = row.GetValue <string>("keyspace_name"),
                            Table    = row.GetValue <string>("columnfamily_name"),
                            TypeCode = dataType.TypeCode,
                            TypeInfo = dataType.TypeInfo,
                            KeyType  = KeyType.Clustering,
                        };
                        cols[dsc.Name] = dsc;
                        i++;
                    }

                    options = new TableOptions
                    {
                        isCompactStorage  = isCompact,
                        bfFpChance        = row.GetValue <double>("bloom_filter_fp_chance"),
                        caching           = row.GetValue <string>("caching"),
                        comment           = row.GetValue <string>("comment"),
                        gcGrace           = row.GetValue <int>("gc_grace_seconds"),
                        localReadRepair   = row.GetValue <double>("local_read_repair_chance"),
                        readRepair        = row.GetValue <double>("read_repair_chance"),
                        compactionOptions = getCompactionStrategyOptions(row),
                        compressionParams =
                            (SortedDictionary <string, string>)Utils.ConvertStringToMap(row.GetValue <string>("compression_parameters"))
                    };
                    //replicate_on_write column not present in C* >= 2.1
                    if (row.GetColumn("replicate_on_write") != null)
                    {
                        options.replicateOnWrite = row.GetValue <bool>("replicate_on_write");
                    }
                }
                //In Cassandra 1.2, the keys are not stored in the system.schema_columns table
                //But you can get it from system.schema_columnfamilies
                var keys = row.GetValue <string>("key_aliases")
                           .Replace("[", "")
                           .Replace("]", "")
                           .Split(',');
                var keyTypes = row.GetValue <string>("key_validator")
                               .Replace("org.apache.cassandra.db.marshal.CompositeType", "")
                               .Replace("(", "")
                               .Replace(")", "")
                               .Split(',');
                for (var i = 0; i < keys.Length; i++)
                {
                    var name     = keys[i].Replace("\"", "").Trim();
                    var dataType = TypeCodec.ParseDataType(keyTypes[i].Trim());
                    cols[name] = new TableColumn()
                    {
                        Name     = name,
                        Keyspace = row.GetValue <string>("keyspace_name"),
                        Table    = row.GetValue <string>("columnfamily_name"),
                        TypeCode = dataType.TypeCode,
                        TypeInfo = dataType.TypeInfo,
                        KeyType  = KeyType.Partition
                    };
                }
            }
            return(new TableMetadata(tableName, cols.Values.ToArray(), options));
        }