1 module cassandra.keyspace; 2 3 import cassandra.client; 4 import cassandra.cql.result; 5 import cassandra.internal.utils; 6 import cassandra.schema; 7 import cassandra.table; 8 9 10 struct CassandraKeyspace { 11 private { 12 CassandraClient m_client; 13 string m_name; 14 } 15 16 this(CassandraClient client, string name) 17 { 18 enforceValidIdentifier(name); 19 20 m_client = client; 21 m_name = name; 22 23 m_client.lockConnection.useKeyspace(name); 24 } 25 26 @property string name() const { return m_name; } 27 @property inout(CassandraClient) client() inout { return m_client; } 28 29 CassandraSchema getSchema(string schema) { return CassandraSchema(this, schema); } 30 31 CassandraTable getTable(string table) { return CassandraTable(this, table); } 32 33 CassandraTable createTable(TABLE, ATTRIBUTES...)(string name, PrimaryKeyAttribute primary_key, ATTRIBUTES attributes) 34 { 35 //assert(isIdentifier(name)); 36 auto stmt = appender!string(); 37 stmt ~= "CREATE TABLE "~name~" ("; 38 foreach (i, T; typeof(TABLE.tupleof)) { 39 stmt ~= "\n " ~ __traits(identifier, TABLE.tupleof[i]) ~ " "; 40 stmt ~= bestCassandraType!T ~ ","; 41 } 42 43 stmt ~= "\n PRIMARY KEY ("; 44 if (primary_key.partitionKey.length > 1) { 45 stmt ~= "(" ~ primary_key.partitionKey.join(", ") ~ ")"; 46 if (primary_key.clusteringColumns.length) 47 stmt ~= ", " ~ primary_key.clusteringColumns.join(", "); 48 } else stmt ~= (primary_key.partitionKey ~ primary_key.clusteringColumns).join(", "); 49 stmt ~= ")\n)"; 50 51 // TODO: support WITH attributes! 52 53 query(stmt.data); 54 return CassandraTable(this, name); 55 } 56 57 CassandraResult query(string q, Consistency consistency = Consistency.one) 58 { 59 auto conn = m_client.lockConnection(); 60 conn.useKeyspace(m_name); 61 return conn.query(conn, q, consistency); 62 } 63 64 PreparedStatement prepare(string q) 65 { 66 auto conn = m_client.lockConnection(); 67 conn.useKeyspace(m_name); 68 return conn.prepare(q); 69 } 70 71 CassandraResult execute(ARGS...)(PreparedStatement stmt, ARGS args) 72 { 73 auto conn = m_client.lockConnection(); 74 // TODO: assert(stmt.keyspace is this); 75 return conn.execute(conn, stmt, args); 76 } 77 } 78 79 80 /+/** 81 Attribute for declaring the primary key of a table. 82 83 Params: 84 column_names = The names of the columns that make up the primary key. 85 This can be one or more columns, of which the first one will be 86 the partition key. 87 partition_key = An array of column names used as a composite 88 partition key. 89 clustering_columns = Additional columns to include for the primary key 90 to determine the clustering order. 91 */ 92 PrimaryKeyAttribute primaryKey(string[] column_names...) 93 { 94 assert(column_names.length >= 1); 95 return PrimaryKeyAttribute([column_names[0]], column_names[1 .. $]); 96 } 97 /// ditto 98 PrimaryKeyAttribute primaryKey(string[] partition_key, string[] clustering_columns...) 99 { 100 assert(partition_key.length >= 1); 101 return PrimaryKeyAttribute(partition_key, clustering_columns); 102 } 103 104 /** Examples translated from the CQL documentation 105 106 See also $(LINK http://www.datastax.com/documentation/cql/3.0/cql/cql_reference/create_table_r.html). 107 */ 108 unittest { 109 import std.uuid; 110 111 // single primary key: user_name 112 @primaryKey("user_name") 113 struct users { 114 string user_name; 115 string password; 116 string gender; 117 string session_token; 118 string state; 119 long birth_year; 120 } 121 122 // compound primary key: empID and deptID 123 @primaryKey("empID", "deptID") 124 struct emp { 125 int empID; 126 int deptID; 127 string first_name; 128 string last_name; 129 } 130 131 // composite partition key: block_id and breed 132 // additional clustering columne: color and short_hair 133 @primaryKey(["block_id", "breed"], "color", "short_hair") 134 struct Cats { 135 UUID block_id; 136 string breed; 137 string color; 138 bool short_hair; 139 } 140 }+/ 141 142 struct PrimaryKeyAttribute { 143 string[] partitionKey; 144 string[] clusteringColumns; 145 }