1 /**
2 	MongoDatabase class representing common database for group of collections.
3 
4 	Technically it is very special collection with common query functions
5 	disabled and some service commands provided.
6 
7 	Copyright: © 2012-2014 Sönke Ludwig
8 	License: Subject to the terms of the MIT license, as written in the included LICENSE.txt file.
9 	Authors: Sönke Ludwig
10 */
11 module vibe.db.mongo.database;
12 
13 import vibe.db.mongo.client;
14 import vibe.db.mongo.collection;
15 import vibe.data.bson;
16 
17 import core.time;
18 
19 /** Represents a single database accessible through a given MongoClient.
20 */
21 struct MongoDatabase
22 {
23 @safe:
24 
25 	private {
26 		string m_name;
27 		MongoClient m_client;
28 	}
29 
30 	//@disable this();
31 
32 	this(MongoClient client, string name)
33 	{
34 		import std.algorithm;
35 
36 		assert(client !is null);
37 		m_client = client;
38 
39 		assert(
40 				!canFind(name, '.'),
41 				"Compound collection path provided to MongoDatabase constructor instead of single database name"
42 		  );
43 		m_name = name;
44 	}
45 
46 	/// The name of this database
47 	@property string name()
48 	{
49 		return m_name;
50 	}
51 
52 	/// The client which represents the connection to the database server
53 	@property MongoClient client()
54 	{
55 		return m_client;
56 	}
57 
58 	/** Accesses the collections of this database.
59 
60 		Returns: The collection with the given name
61 	*/
62 	MongoCollection opIndex(string name)
63 	{
64 		return MongoCollection(this, name);
65 	}
66 
67 	/** Retrieves the last error code (if any) from the database server.
68 
69 		Exact object format is not documented. MongoErrorDescription signature will be
70 		updated upon any issues. Note that this method will execute a query to service
71 		collection and thus is far from being "free".
72 
73 		Returns: struct storing data from MongoDB db.getLastErrorObj() object
74  	*/
75 	MongoErrorDescription getLastError()
76 	{
77 		return m_client.lockConnection().getLastError(m_name);
78 	}
79 
80 	/** Returns recent log messages for this database from the database server.
81 
82 		See $(LINK http://www.mongodb.org/display/DOCS/getLog+Command).
83 
84 	 	Params:
85 	 		mask = "global" or "rs" or "startupWarnings". Refer to official MongoDB docs.
86 
87 	 	Returns: Bson document with recent log messages from MongoDB service.
88  	 */
89 	Bson getLog(string mask)
90 	{
91 		static struct CMD {
92 			string getLog;
93 		}
94 		CMD cmd;
95 		cmd.getLog = mask;
96 		return runCommandChecked(cmd);
97 	}
98 
99 	/** Performs a filesystem/disk sync of the database on the server.
100 
101 		This method can only be called on the admin database.
102 
103 		See $(LINK http://www.mongodb.org/display/DOCS/fsync+Command)
104 
105 		Returns: check documentation
106  	 */
107 	Bson fsync(bool async = false)
108 	{
109 		static struct CMD {
110 			int fsync = 1;
111 			bool async;
112 		}
113 		CMD cmd;
114 		cmd.async = async;
115 		return runCommandChecked(cmd);
116 	}
117 
118 	deprecated("use runCommandChecked or runCommandUnchecked instead")
119 	Bson runCommand(T)(T command_and_options,
120 		string errorInfo = __FUNCTION__, string errorFile = __FILE__, size_t errorLine = __LINE__)
121 	{
122 		return runCommandUnchecked(command_and_options, errorInfo, errorFile, errorLine);
123 	}
124 
125 	/** Generic means to run commands on the database.
126 
127 		See $(LINK http://www.mongodb.org/display/DOCS/Commands) for a list
128 		of possible values for command_and_options.
129 
130 		Note that some commands return a cursor instead of a single document.
131 		In this case, use `runListCommand` instead of `runCommandChecked` or
132 		`runCommandUnchecked` to be able to properly iterate over the results.
133 
134 		Usually commands respond with a `double ok` field in them, the `Checked`
135 		version of this function checks that they equal to `1.0`. The `Unchecked`
136 		version of this function does not check that parameter.
137 
138 		With cursor functions on `runListCommand` the error checking is well
139 		defined.
140 
141 		Params:
142 			command_and_options = Bson object containing the command to be executed
143 				as well as the command parameters as fields
144 
145 		Returns: The raw response of the MongoDB server
146 	*/
147 	Bson runCommandChecked(T, ExceptionT = MongoDriverException)(
148 		T command_and_options,
149 		string errorInfo = __FUNCTION__,
150 		string errorFile = __FILE__,
151 		size_t errorLine = __LINE__
152 	)
153 	{
154 		Bson cmd;
155 		static if (is(T : Bson))
156 			cmd = command_and_options;
157 		else
158 			cmd = command_and_options.serializeToBson;
159 		return m_client.lockConnection().runCommand!(Bson, ExceptionT)(
160 			m_name, cmd, errorInfo, errorFile, errorLine);
161 	}
162 
163 	/// ditto
164 	Bson runCommandUnchecked(T, ExceptionT = MongoDriverException)(
165 		T command_and_options,
166 		string errorInfo = __FUNCTION__,
167 		string errorFile = __FILE__,
168 		size_t errorLine = __LINE__
169 	)
170 	{
171 		Bson cmd;
172 		static if (is(T : Bson))
173 			cmd = command_and_options;
174 		else
175 			cmd = command_and_options.serializeToBson;
176 		return m_client.lockConnection().runCommandUnchecked!(Bson, ExceptionT)(
177 			m_name, cmd, errorInfo, errorFile, errorLine);
178 	}
179 
180 	/// ditto
181 	MongoCursor!R runListCommand(R = Bson, T)(T command_and_options, int batchSize = 0, Duration getMoreMaxTime = Duration.max)
182 	{
183 		Bson cmd;
184 		static if (is(T : Bson))
185 			cmd = command_and_options;
186 		else
187 			cmd = command_and_options.serializeToBson;
188 		cmd["$db"] = Bson(m_name);
189 
190 		return MongoCursor!R(m_client, cmd, batchSize, getMoreMaxTime);
191 	}
192 }