1 /*!
2   \file lib/db/dbmi_base/cursor.c
3 
4   \brief DBMI Library (base) - cursors management
5 
6   (C) 1999-2009 by the GRASS Development Team
7 
8   This program is free software under the GNU General Public
9   License (>=v2). Read the file COPYING that comes with GRASS
10   for details.
11 
12   \author Joel Jones (CERL/UIUC), Radim Blazek
13 */
14 
15 #include <stdlib.h>
16 #include <grass/dbmi.h>
17 
18 /*!
19   \brief Initialize dbCursor
20 
21   \param cursor pointer to dbCursor to be initialized
22 */
db_init_cursor(dbCursor * cursor)23 void db_init_cursor(dbCursor *cursor)
24 {
25     G_zero(cursor, sizeof(dbCursor));
26     cursor->token = -1;
27 }
28 
29 /*!
30    \brief Allocate table for cursor
31 
32    \param cursor pointer to dbCursor
33    \param ncols  number of column in table
34 
35    \return DB_OK on success
36    \return error code on error
37  */
db_alloc_cursor_table(dbCursor * cursor,int ncols)38 int db_alloc_cursor_table(dbCursor *cursor, int ncols)
39 {
40     cursor->table = db_alloc_table(ncols);
41     if (cursor->table == NULL)
42 	return db_get_error_code();
43     return DB_OK;
44 }
45 
46 /*!
47    \brief Free allocated dbCursor
48 
49    \param cursor pointer to dbCursor
50 */
db_free_cursor(dbCursor * cursor)51 void db_free_cursor(dbCursor *cursor)
52 {
53     if (cursor->table)
54 	db_free_table(cursor->table);
55     if (cursor->column_flags)
56 	db_free_cursor_column_flags(cursor);
57     db_init_cursor(cursor);
58 }
59 
60 /*!
61    \brief Get table allocated by cursor
62 
63    \param cursor pointer to dbCursor
64 
65    \return pointer to dbTable
66 */
db_get_cursor_table(dbCursor * cursor)67 dbTable *db_get_cursor_table(dbCursor *cursor)
68 {
69     return cursor->table;
70 }
71 
72 /*!
73   \brief Set table for given cursor
74 
75   \param cursor pointer to dbCursor
76   \param table  pointer to dbTable
77 */
db_set_cursor_table(dbCursor * cursor,dbTable * table)78 void db_set_cursor_table(dbCursor *cursor, dbTable *table)
79 {
80     cursor->table = table;
81 }
82 
83 /*!
84   \brief Get cursor token
85 
86   \param cursor pointer to dbCursor
87 
88   \return pointer to dbToken
89 */
db_get_cursor_token(dbCursor * cursor)90 dbToken db_get_cursor_token(dbCursor *cursor)
91 {
92     return cursor->token;
93 }
94 
95 /*!
96   \brief Set cursor token
97 
98   \param cursor pointer to dbCursor
99   \param token  pointer to dbToken
100 */
db_set_cursor_token(dbCursor * cursor,dbToken token)101 void db_set_cursor_token(dbCursor *cursor, dbToken token)
102 {
103     cursor->token = token;
104 }
105 
106 /*!
107    \brief Set cursor to be read-only (select)
108 
109    \param cursor pointer to dbCursor
110 */
db_set_cursor_type_readonly(dbCursor * cursor)111 void db_set_cursor_type_readonly(dbCursor *cursor)
112 {
113     cursor->type = DB_READONLY;
114 }
115 
116 /*!
117    \brief Set cursor to be writable (update)
118 
119    \param cursor pointer to dbCursor
120 */
db_set_cursor_type_update(dbCursor * cursor)121 void db_set_cursor_type_update(dbCursor *cursor)
122 {
123     cursor->type = DB_UPDATE;
124 }
125 
126 /*!
127    \brief Set cursor to be writable (insert)
128 
129    \param cursor pointer to dbCursor
130 */
db_set_cursor_type_insert(dbCursor * cursor)131 void db_set_cursor_type_insert(dbCursor *cursor)
132 {
133     cursor->type = DB_INSERT;
134 }
135 
136 /*!
137   \brief Check cursor type
138 
139   \param cursor pointer to dbCursor
140 
141   \return 1 for known cursor type
142   \return 0 for unknown cursor type
143 */
db_test_cursor_type_fetch(dbCursor * cursor)144 int db_test_cursor_type_fetch(dbCursor *cursor)
145 {
146     return (cursor->type == DB_READONLY ||
147 	    cursor->type == DB_UPDATE ||
148 	    cursor->type == DB_INSERT);
149 }
150 
151 /*!
152   \brief Check if cursor type is 'update'
153 
154   \param cursor pointer to dbCursor
155 
156   \return 1 if cursor type is 'update'
157   \return 0 otherwise
158 */
db_test_cursor_type_update(dbCursor * cursor)159 int db_test_cursor_type_update(dbCursor *cursor)
160 {
161     return (cursor->type == DB_UPDATE);
162 }
163 
164 /*!
165   \brief Check if cursor type is 'insert'
166 
167   \param cursor pointer to dbCursor
168 
169   \return 1 if cursor type is 'insert'
170   \return 0 otherwise
171 */
db_test_cursor_type_insert(dbCursor * cursor)172 int db_test_cursor_type_insert(dbCursor *cursor)
173 {
174     return (cursor->type == DB_INSERT);
175 }
176 
177 /*!
178   \brief Set cursor mode
179 
180   Modes:
181    - DB_SCROLL
182    - DB_INSENSITIVE
183 
184   \param cursor pointer to dbCursor
185   \param mode cursor mode
186  */
db_set_cursor_mode(dbCursor * cursor,int mode)187 void db_set_cursor_mode(dbCursor *cursor, int mode)
188 {
189     cursor->mode = mode;
190 }
191 
192 /*!
193   \brief Set 'scroll' cursor mode
194 
195   \param cursor pointer to dbCursor
196 */
db_set_cursor_mode_scroll(dbCursor * cursor)197 void db_set_cursor_mode_scroll(dbCursor *cursor)
198 {
199     cursor->mode |= DB_SCROLL;
200 }
201 
202 /*!
203   \brief Unset 'scroll' cursor mode
204 
205   \param cursor pointer to dbCursor
206 */
db_unset_cursor_mode_scroll(dbCursor * cursor)207 void db_unset_cursor_mode_scroll(dbCursor *cursor)
208 {
209     cursor->mode &= ~DB_SCROLL;
210 }
211 
212 /*!
213   \brief Unset cursor mode
214 
215   \param cursor pointer to dbCursor
216 */
db_unset_cursor_mode(dbCursor * cursor)217 void db_unset_cursor_mode(dbCursor *cursor)
218 {
219     cursor->mode = 0;
220 }
221 
222 /*!
223   \brief Set 'intensive' cursor mode
224 
225   \param cursor pointer to dbCursor
226 */
db_set_cursor_mode_insensitive(dbCursor * cursor)227 void db_set_cursor_mode_insensitive(dbCursor *cursor)
228 {
229     cursor->mode |= DB_INSENSITIVE;
230 }
231 
232 /*!
233   \brief Unset 'intensive' cursor mode
234 
235   \param cursor pointer to dbCursor
236 */
db_unset_cursor_mode_insensitive(dbCursor * cursor)237 void db_unset_cursor_mode_insensitive(dbCursor *cursor)
238 {
239     cursor->mode &= ~DB_INSENSITIVE;
240 }
241 
242 /*!
243   \brief Check if cursor mode is 'scroll'
244 
245   \param cursor pointer to dbCursor
246 
247   \return 1 if true
248   \return 0 if false
249 */
db_test_cursor_mode_scroll(dbCursor * cursor)250 int db_test_cursor_mode_scroll(dbCursor *cursor)
251 {
252     return (cursor->mode & DB_SCROLL);
253 }
254 
255 /*!
256   \brief Check if cursor mode is 'intensive'
257 
258   \param cursor pointer to dbCursor
259 
260   \return 1 if true
261   \return 0 if false
262 */
db_test_cursor_mode_insensitive(dbCursor * cursor)263 int db_test_cursor_mode_insensitive(dbCursor *cursor)
264 {
265     return (cursor->mode & DB_INSENSITIVE);
266 }
267 
268 /*!
269   \brief Allocate columns' flags for cursor
270 
271   \param cursor pointer to dbCursor
272 
273   \return DB_OK on success
274   \return error code on failure
275 */
db_alloc_cursor_column_flags(dbCursor * cursor)276 int db_alloc_cursor_column_flags(dbCursor *cursor)
277 {
278     int ncols;
279     int col;
280 
281     ncols = db_get_cursor_number_of_columns(cursor);
282     cursor->column_flags = (short *)db_calloc(ncols, sizeof(short));
283     if (cursor->column_flags == NULL)
284 	return db_get_error_code();
285     for (col = 0; col < ncols; col++)
286 	db_unset_cursor_column_flag(cursor, col);
287     return DB_OK;
288 }
289 
290 /*!
291   \brief Free columns' flags of cursor
292 
293   \param cursor pointer to dbCursor
294 */
db_free_cursor_column_flags(dbCursor * cursor)295 void db_free_cursor_column_flags(dbCursor *cursor)
296 {
297     if (cursor->column_flags)
298 	db_free(cursor->column_flags);
299     cursor->column_flags = NULL;
300 }
301 
302 /*!
303   \brief Set Column flag to 'update'
304 
305   \param cursor pointer to dbCursor
306   \param col    column index (starting with '0')
307 */
db_set_cursor_column_for_update(dbCursor * cursor,int col)308 void db_set_cursor_column_for_update(dbCursor *cursor, int col)
309 {
310     db_set_cursor_column_flag(cursor, col);
311 }
312 
313 /*!
314   \brief Unset 'update' column flag
315 
316   \param cursor pointer to dbCursor
317   \param col    column index (starting with '0')
318 */
db_unset_cursor_column_for_update(dbCursor * cursor,int col)319 void db_unset_cursor_column_for_update(dbCursor *cursor, int col)
320 {
321     db_unset_cursor_column_flag(cursor, col);
322 }
323 
324 /*!
325   \brief Check if column flag is 'update'
326 
327   \param cursor pointer to dbCursor
328   \param col    column index (starting with '0')
329 
330   \return 1 if true
331   \return 0 if false
332 */
db_test_cursor_column_for_update(dbCursor * cursor,int col)333 int db_test_cursor_column_for_update(dbCursor *cursor, int col)
334 {
335     return db_test_cursor_column_flag(cursor, col);
336 }
337 
338 /*!
339   \brief Check if columns' flag is 'update'
340 
341   \param cursor pointer to dbCursor
342 
343   \return 1 if true
344   \return 0 if false
345 */
db_test_cursor_any_column_for_update(dbCursor * cursor)346 int db_test_cursor_any_column_for_update(dbCursor *cursor)
347 {
348     return db_test_cursor_any_column_flag(cursor);
349 }
350 
351 /*!
352   \brief Set column's flag
353 
354   \param cursor pointer to dbCursor
355   \param col    column index (starting with '0')
356  */
db_set_cursor_column_flag(dbCursor * cursor,int col)357 void db_set_cursor_column_flag(dbCursor *cursor, int col)
358 {
359     if (cursor->column_flags)
360 	cursor->column_flags[col] = 1;
361 }
362 
363 /*!
364   \brief Unset column's flag
365 
366   \param cursor pointer to dbCursor
367   \param col    column index (starting with '0')
368  */
db_unset_cursor_column_flag(dbCursor * cursor,int col)369 void db_unset_cursor_column_flag(dbCursor *cursor, int col)
370 {
371     if (cursor->column_flags)
372 	cursor->column_flags[col] = 0;
373 }
374 
375 /*!
376   \brief Checks column's flag
377 
378   \param cursor pointer to dbCursor
379   \param col    column index (starting with '0')
380 
381   \return 1 if flag is defined
382   \return 0 otherwise
383 */
db_test_cursor_column_flag(dbCursor * cursor,int col)384 int db_test_cursor_column_flag(dbCursor *cursor, int col)
385 {
386     return cursor->column_flags && cursor->column_flags[col] ? 1 : 0;
387 }
388 
389 /*!
390   \brief Get number of columns
391 
392   \param cursor pointer to dbCursor
393 */
db_get_cursor_number_of_columns(dbCursor * cursor)394 int db_get_cursor_number_of_columns(dbCursor *cursor)
395 {
396     dbTable *table;
397 
398     table = db_get_cursor_table(cursor);
399     if (table)
400 	return db_get_table_number_of_columns(table);
401     return 0;
402 }
403 
404 /*!
405   \brief Checks columns' flag
406 
407   Is any cursor column flag set?
408 
409   \param cursor pointer to dbCursor
410 
411   \return 1 if true
412   \return 0 if false
413 */
db_test_cursor_any_column_flag(dbCursor * cursor)414 int db_test_cursor_any_column_flag(dbCursor *cursor)
415 {
416     int ncols, col;
417 
418     ncols = db_get_cursor_number_of_columns(cursor);
419     for (col = 0; col < ncols; col++)
420 	if (db_test_cursor_column_flag(cursor, col))
421 	    return 1;
422     return 0;
423 }
424