1 /*
2  * Copyright (C) 2008 - 2011 Vivien Malerba <malerba@gnome-db.org>
3  * Copyright (C) 2009 Bas Driessen <bas.driessen@xobas.com>
4  * Copyright (C) 2010 David King <davidk@openismus.com>
5  * Copyright (C) 2010 Murray Cumming <murrayc@murrayc.com>
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
20  * Boston, MA  02110-1301, USA.
21  */
22 
23 #include <libgda/sql-parser/gda-statement-struct.h>
24 #include <libgda/gda-debug-macros.h>
25 #include <libgda/sql-parser/gda-statement-struct-trans.h>
26 #include <libgda/sql-parser/gda-statement-struct-util.h>
27 #include <string.h>
28 
29 static gpointer  gda_sql_statement_trans_new (void);
30 static void      gda_sql_statement_trans_free (gpointer stmt);
31 static gpointer  gda_sql_statement_trans_copy (gpointer src);
32 static gchar    *gda_sql_statement_trans_serialize (gpointer stmt);
33 
34 /* BEGIN */
35 GdaSqlStatementContentsInfo begin_infos = {
36 	GDA_SQL_STATEMENT_BEGIN,
37 	"BEGIN",
38 	gda_sql_statement_trans_new,
39 	gda_sql_statement_trans_free,
40 	gda_sql_statement_trans_copy,
41 	gda_sql_statement_trans_serialize,
42 	NULL,
43 	NULL,
44 	NULL,
45 	NULL,
46 	NULL,
47 	NULL
48 };
49 
50 GdaSqlStatementContentsInfo *
51 _gda_sql_statement_begin_get_infos (void)
52 {
53 	return &begin_infos;
54 }
55 
56 /* COMMIT */
57 GdaSqlStatementContentsInfo commit_infos = {
58 	GDA_SQL_STATEMENT_COMMIT,
59 	"COMMIT",
60 	gda_sql_statement_trans_new,
61 	gda_sql_statement_trans_free,
62 	gda_sql_statement_trans_copy,
63 	gda_sql_statement_trans_serialize,
64 	NULL,
65 	NULL,
66 	NULL,
67 	NULL,
68 	NULL,
69 	NULL
70 };
71 
72 GdaSqlStatementContentsInfo *
73 _gda_sql_statement_commit_get_infos (void)
74 {
75 	return &commit_infos;
76 }
77 
78 /* ROLLBACK */
79 GdaSqlStatementContentsInfo rollback_infos = {
80 	GDA_SQL_STATEMENT_ROLLBACK,
81 	"ROLLBACK",
82 	gda_sql_statement_trans_new,
83 	gda_sql_statement_trans_free,
84 	gda_sql_statement_trans_copy,
85 	gda_sql_statement_trans_serialize,
86 	NULL,
87 	NULL,
88 	NULL,
89 	NULL,
90 	NULL,
91 	NULL
92 };
93 
94 GdaSqlStatementContentsInfo *
95 _gda_sql_statement_rollback_get_infos (void)
96 {
97 	return &rollback_infos;
98 }
99 
100 /* SAVEPOINT */
101 GdaSqlStatementContentsInfo svp_infos = {
102 	GDA_SQL_STATEMENT_SAVEPOINT,
103 	"SAVEPOINT",
104 	gda_sql_statement_trans_new,
105 	gda_sql_statement_trans_free,
106 	gda_sql_statement_trans_copy,
107 	gda_sql_statement_trans_serialize,
108 	NULL,
109 	NULL,
110 	NULL,
111 	NULL,
112 	NULL,
113 	NULL
114 };
115 
116 GdaSqlStatementContentsInfo *
117 _gda_sql_statement_savepoint_get_infos (void)
118 {
119 	return &svp_infos;
120 }
121 
122 /* ROLLBACK SAVEPOINT */
123 GdaSqlStatementContentsInfo rollback_svp_infos = {
124 	GDA_SQL_STATEMENT_ROLLBACK_SAVEPOINT,
125 	"ROLLBACK_SAVEPOINT",
126 	gda_sql_statement_trans_new,
127 	gda_sql_statement_trans_free,
128 	gda_sql_statement_trans_copy,
129 	gda_sql_statement_trans_serialize,
130 	NULL,
131 	NULL,
132 	NULL,
133 	NULL,
134 	NULL,
135 	NULL
136 };
137 
138 GdaSqlStatementContentsInfo *
139 _gda_sql_statement_rollback_savepoint_get_infos (void)
140 {
141 	return &rollback_svp_infos;
142 }
143 
144 /* DELETE SAVEPOINT */
145 GdaSqlStatementContentsInfo delete_svp_infos = {
146 	GDA_SQL_STATEMENT_DELETE_SAVEPOINT,
147 	"DELETE_SAVEPOINT",
148 	gda_sql_statement_trans_new,
149 	gda_sql_statement_trans_free,
150 	gda_sql_statement_trans_copy,
151 	gda_sql_statement_trans_serialize,
152 	NULL,
153 	NULL,
154 	NULL,
155 	NULL,
156 	NULL,
157 	NULL
158 };
159 
160 GdaSqlStatementContentsInfo *
161 _gda_sql_statement_delete_savepoint_get_infos (void)
162 {
163 	return &delete_svp_infos;
164 }
165 
166 
167 static gpointer
168 gda_sql_statement_trans_new (void)
169 {
170 	GdaSqlStatementTransaction *trans;
171 	trans = g_new0 (GdaSqlStatementTransaction, 1);
172 	trans->isolation_level = GDA_TRANSACTION_ISOLATION_UNKNOWN;
173 	return trans;
174 }
175 
176 static void
177 gda_sql_statement_trans_free (gpointer stmt)
178 {
179 	GdaSqlStatementTransaction *trans = (GdaSqlStatementTransaction *) stmt;
180 	g_free (trans->trans_mode);
181 	g_free (trans->trans_name);
182 	g_free (trans);
183 }
184 
185 static gpointer
186 gda_sql_statement_trans_copy (gpointer src)
187 {
188 	GdaSqlStatementTransaction *dest;
189 	GdaSqlStatementTransaction *trans = (GdaSqlStatementTransaction *) src;
190 
191 	dest = g_new0 (GdaSqlStatementTransaction, 1);
192 	if (trans->trans_mode)
193 		dest->trans_mode = g_strdup (trans->trans_mode);
194 	if (trans->trans_name)
195 		dest->trans_name = g_strdup (trans->trans_name);
196 	dest->isolation_level = trans->isolation_level;
197 
198 	return dest;
199 }
200 
201 static gchar *
202 gda_sql_statement_trans_serialize (gpointer stmt)
203 {
204         GString *string;
205         gchar *str;
206 	GdaSqlStatementTransaction *trans = (GdaSqlStatementTransaction *) stmt;
207 
208         g_return_val_if_fail (stmt, NULL);
209 
210         string = g_string_new ("\"contents\":{");
211 	g_string_append (string, "\"trans_mode\":");
212 
213 	str = _json_quote_string (trans->trans_mode);
214 	g_string_append (string, str);
215 	g_free (str);
216 
217 	g_string_append (string, ",\"trans_name\":");
218 	str = _json_quote_string (trans->trans_name);
219 	g_string_append (string, str);
220 	g_free (str);
221 
222 	g_string_append (string, ",\"isol_level\":");
223 	switch (trans->isolation_level) {
224 	default:
225 	case GDA_TRANSACTION_ISOLATION_UNKNOWN:
226 		str = NULL;
227 		break;
228 	case GDA_TRANSACTION_ISOLATION_READ_COMMITTED:
229 		str = "COMMITTED_READ";
230 		break;
231 	case GDA_TRANSACTION_ISOLATION_READ_UNCOMMITTED:
232 		str = "UNCOMMITTED_READ";
233 		break;
234 	case GDA_TRANSACTION_ISOLATION_REPEATABLE_READ:
235 		str = "REPEATABLE_READ";
236 		break;
237 	case GDA_TRANSACTION_ISOLATION_SERIALIZABLE:
238 		str = "SERIALIZABLE";
239 		break;
240 	}
241 	if (str)
242 		g_string_append_printf (string, "\"%s\"", str);
243 	else
244 		g_string_append (string, "null");
245 
246         g_string_append_c (string, '}');
247         str = string->str;
248         g_string_free (string, FALSE);
249         return str;
250 }
251 
252 /**
253  * gda_sql_statement_trans_take_name
254  * @stmt: a #GdaSqlStatement pointer
255  * @value: (transfer full): a G_TYPE_STRING value
256  *
257  * Sets the name of the transaction
258  *
259  * @value's ownership is transferred to
260  * @stmt (which means @stmt is then responsible for freeing it when no longer needed).
261  */
262 void
263 gda_sql_statement_trans_take_name (GdaSqlStatement *stmt, GValue *value)
264 {
265 	GdaSqlStatementTransaction *trans = (GdaSqlStatementTransaction *) stmt->contents;
266 	if (trans->trans_name) {
267 		g_free (trans->trans_name);
268 		trans->trans_name = NULL;
269 	}
270 	if (value) {
271 		trans->trans_name = g_value_dup_string (value);
272 		gda_value_free (value);
273 	}
274 }
275 
276 /**
277  * gda_sql_statement_trans_take_mode
278  * @stmt: a #GdaSqlStatement pointer
279  * @value: (transfer full): a G_TYPE_STRING value
280  *
281  * Sets the model of the transaction
282  *
283  * @value's ownership is transferred to
284  * @stmt (which means @stmt is then responsible for freeing it when no longer needed).
285  */
286 void
287 gda_sql_statement_trans_take_mode (GdaSqlStatement *stmt, GValue *value)
288 {
289 	GdaSqlStatementTransaction *trans = (GdaSqlStatementTransaction *) stmt->contents;
290 	if (trans->trans_mode) {
291 		g_free (trans->trans_mode);
292 		trans->trans_mode = NULL;
293 	}
294 	if (value) {
295 		trans->trans_mode = g_value_dup_string (value);
296 		gda_value_free (value);
297 	}
298 }
299 
300 /**
301  * gda_sql_statement_set_isol_level
302  * @stmt: a #GdaSqlStatement pointer
303  * @level: the transacion level
304  *
305  * Sets the transaction level of the transaction
306  */
307 void
308 gda_sql_statement_trans_set_isol_level (GdaSqlStatement *stmt, GdaTransactionIsolation level)
309 {
310 	GdaSqlStatementTransaction *trans = (GdaSqlStatementTransaction *) stmt->contents;
311 	trans->isolation_level = level;
312 }
313