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 }