IODA Bundle
legacy_fortran_api_examples.f90
Go to the documentation of this file.
1 ! (C) Copyright 1996-2012 ECMWF.
2 !
3 ! This software is licensed under the terms of the Apache Licence Version 2.0
4 ! which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
5 ! In applying this licence, ECMWF does not waive the privileges and immunities
6 ! granted to it by virtue of its status as an intergovernmental organisation nor
7 ! does it submit to any jurisdiction.
8 !
9 
11  use, intrinsic :: iso_c_binding
12  use odc_c_binding
13  implicit none
14 
15  integer, parameter :: max_varlen = 128
16  integer(kind=4), parameter :: ncolumns = 6
17 
18  ! Correct values for checking
19 
20  integer(c_int), dimension(ncolumns), parameter:: column_types = (/odb_integer, odb_real, odb_bitfield, &
22 
23  character(8), dimension(ncolumns), parameter :: column_names = (/'ifoo ', 'nbar ', 'status ', 'wigos ', &
24  'expver ', 'dbar '/)
25 
26  integer(c_int), dimension(ncolumns), parameter:: column_offsets = (/1, 2, 3, 4, 7, 8/)
27  integer(c_int), dimension(ncolumns), parameter:: column_sizes = (/1, 1, 1, 3, 1, 1/)
28  integer, parameter :: row_size_doubles = 8
29 
30  interface
31  function strlen(s) result(l) bind(c, name='strlen')
32  use, intrinsic :: iso_c_binding
33  character(c_char) :: s
34  integer(c_int) :: l
35  end function
36  end interface
37 
38  write(0,*) "Calling odb_start..."
39 
40  call odb_start()
41 
46 
47 contains
48 
50  implicit none
51  type(c_ptr) :: odb_handle, odb_it
52  integer(kind=C_INT) :: cerr
53  character(kind=C_CHAR, len=max_varlen) :: config = c_null_char
54  character(kind=C_CHAR, len=max_varlen) :: outputfile="example_fortran_api_append.odb"//achar(0)
55  integer(kind=4) :: i
56  integer(kind=C_INT) :: itype, c_ncolumns
57  real(kind=c_double), dimension(:), allocatable:: one_row
58  integer(kind=c_int) :: offsets(ncolumns)
59  integer(kind=c_int) :: row_length_doubles
60  character(len=100) :: expver="fihn"//achar(0)
61  character(len=100) :: wigos="this-is-a-long-string"//achar(0)
62 
63  write(0,*) 'example_fortran_api_append'
64  c_ncolumns = ncolumns
65  odb_handle = odb_write_new(config, cerr)
66  odb_it = odb_write_iterator_new(odb_handle, outputfile, cerr);
67 
68  cerr = odb_write_set_no_of_columns(odb_it, ncolumns)
69  if (cerr == 0) cerr = odb_write_set_column(odb_it, 0, odb_integer, "ifoo"//achar(0))
70  if (cerr == 0) cerr = odb_write_set_column(odb_it, 1, odb_real, "nbar"//achar(0))
71  if (cerr == 0) cerr = odb_write_set_bitfield(odb_it, 2, odb_bitfield, "status"//achar(0), &
72  "active:passive:blacklisted:"//achar(0), &
73  "1:1:4:"//achar(0))
74  if (cerr == 0) cerr = odb_write_set_column(odb_it, 3, odb_string, "wigos"//achar(0))
75  if (cerr == 0) cerr = odb_write_set_column_size_doubles(odb_it, 3, 4);
76  if (cerr == 0) cerr = odb_write_set_column(odb_it, 4, odb_string, "expver"//achar(0))
77  if (cerr == 0) cerr = odb_write_set_column(odb_it, 5, odb_double, "dbar"//achar(0))
78 
79  if (cerr == 0) cerr = odb_write_set_missing_value(odb_it, 0, 1.0_8)
80  if (cerr == 0) cerr = odb_write_header(odb_it)
81 
82  if (cerr == 0) cerr = odb_write_get_row_buffer_size_doubles(odb_it, row_length_doubles)
83  do i = 1, ncolumns
84  if (cerr == 0) cerr = odb_write_get_column_offset(odb_it, i-1, offsets(i))
85  enddo
86  if (cerr /= 0) stop 1
87 
88  ! Sanity check!
89  if (row_length_doubles /= 9) stop 1
90  if (any(offsets /= (/1, 2, 3, 4, 8, 9/))) stop 1
91 
92  allocate(one_row(row_length_doubles))
93  do i=1,10
94  one_row(offsets(1)) = i
95  one_row(offsets(2)) = i
96  one_row(offsets(3)) = 5
97  one_row(offsets(4):offsets(4)+3) = transfer(wigos, one_row(offsets(4):offsets(4)+3))
98  one_row(offsets(5)) = transfer(expver, one_row(5))
99  one_row(offsets(6)) = 5
100  cerr = odb_write_set_next_row(odb_it, one_row, c_ncolumns)
101  if (cerr /= 0) stop 1
102  enddo
103  deallocate(one_row)
104 
105  cerr = odb_write_iterator_delete(odb_it)
106 
107  if (cerr == 0) odb_it = odb_append_iterator_new(odb_handle, outputfile, cerr);
108 
109  if (cerr == 0) cerr = odb_write_set_no_of_columns(odb_it, ncolumns)
110  if (cerr == 0) cerr = odb_write_set_column(odb_it, 0, odb_integer, "ifoo"//achar(0))
111  if (cerr == 0) cerr = odb_write_set_column(odb_it, 1, odb_real, "nbar"//achar(0))
112  if (cerr == 0) cerr = odb_write_set_bitfield(odb_it, 2, odb_bitfield, "status"//achar(0), &
113  "active:passive:blacklisted:"//achar(0), &
114  "1:1:4:"//achar(0))
115  if (cerr == 0) cerr = odb_write_set_column(odb_it, 3, odb_string, "wigos"//achar(0))
116  if (cerr == 0) cerr = odb_write_set_column_size_doubles(odb_it, 3, 4);
117  if (cerr == 0) cerr = odb_write_set_column(odb_it, 4, odb_string, "expver"//achar(0))
118  if (cerr == 0) cerr = odb_write_set_column(odb_it, 5, odb_double, "dbar"//achar(0))
119 
120  if (cerr == 0) cerr = odb_write_set_missing_value(odb_it, 0, 1.0_8)
121  if (cerr == 0) cerr = odb_write_header(odb_it)
122 
123  if (cerr == 0) cerr = odb_write_get_row_buffer_size_doubles(odb_it, row_length_doubles)
124  do i = 1, ncolumns
125  if (cerr == 0) cerr = odb_write_get_column_offset(odb_it, i-1, offsets(i))
126  enddo
127  if (cerr /= 0) stop 1
128 
129  ! Sanity check!
130  if (row_length_doubles /= 9) stop 1
131  if (any(offsets /= (/1, 2, 3, 4, 8, 9/))) stop 1
132 
133  allocate(one_row(row_length_doubles))
134  do i=1,10
135  one_row(offsets(1)) = i
136  one_row(offsets(2)) = i
137  one_row(offsets(3)) = 5
138  one_row(offsets(4):offsets(4)+3) = transfer(wigos, one_row(offsets(4):offsets(4)+3))
139  one_row(offsets(5)) = transfer(expver, one_row(5))
140  one_row(offsets(6)) = 5
141  cerr = odb_write_set_next_row(odb_it, one_row, c_ncolumns)
142  if (cerr /= 0) stop 1
143  enddo
144  deallocate(one_row)
145 
146  cerr = odb_write_iterator_delete(odb_it)
147  if (cerr == 0) cerr = odb_write_delete(odb_handle)
148  if (cerr /= 0) stop 1
149 
150 end subroutine example_fortran_api_append
151 
153  implicit none
154  type(c_ptr) :: odb_handle, odb_it
155  integer(kind=C_INT) :: cerr
156  character(kind=C_CHAR, len=max_varlen) :: config = c_null_char
157  character(kind=C_CHAR, len=max_varlen) :: outputfile="test.odb"//achar(0)
158  integer(kind=4) :: i
159  integer(kind=C_INT) :: itype, c_ncolumns
160  real(kind=c_double), dimension(:), allocatable:: one_row
161  integer(kind=c_int) :: offsets(ncolumns)
162  integer(kind=c_int) :: row_length_doubles
163  character(len=100) :: expver="fihn"//achar(0)
164  character(len=100) :: wigos="this-is-a-long-string"//achar(0)
165 
166  write(0,*) 'example_fortran_api_setup'
167  c_ncolumns = ncolumns
168  odb_handle = odb_write_new(config, cerr)
169  odb_it = odb_write_iterator_new(odb_handle, outputfile, cerr);
170 
171  cerr = odb_write_set_no_of_columns(odb_it, ncolumns)
172  if (cerr == 0) cerr = odb_write_set_column(odb_it, 0, odb_integer, "ifoo"//achar(0))
173  if (cerr == 0) cerr = odb_write_set_column(odb_it, 1, odb_real, "nbar"//achar(0))
174  if (cerr == 0) cerr = odb_write_set_bitfield(odb_it, 2, odb_bitfield, "status"//achar(0), &
175  "active:passive:blacklisted:"//achar(0), &
176  "1:1:4:"//achar(0))
177  if (cerr == 0) cerr = odb_write_set_column(odb_it, 3, odb_string, "wigos"//achar(0))
178  if (cerr == 0) cerr = odb_write_set_column_size_doubles(odb_it, 3, 4);
179  if (cerr == 0) cerr = odb_write_set_column(odb_it, 4, odb_string, "expver"//achar(0))
180  if (cerr == 0) cerr = odb_write_set_column(odb_it, 5, odb_double, "dbar"//achar(0))
181 
182  if (cerr == 0) cerr = odb_write_set_missing_value(odb_it, 0, 1.0_8)
183  if (cerr == 0) cerr = odb_write_header(odb_it)
184 
185  if (cerr == 0) cerr = odb_write_get_row_buffer_size_doubles(odb_it, row_length_doubles)
186  do i = 1, ncolumns
187  if (cerr == 0) cerr = odb_write_get_column_offset(odb_it, i-1, offsets(i))
188  enddo
189  if (cerr /= 0) stop 1
190 
191  ! Sanity check!
192  if (row_length_doubles /= 9) stop 1
193  if (any(offsets /= (/1, 2, 3, 4, 8, 9/))) stop 1
194 
195  allocate(one_row(row_length_doubles))
196  do i=1,10
197  one_row(offsets(1)) = i
198  one_row(offsets(2)) = i
199  one_row(offsets(3)) = 5
200  one_row(offsets(4):offsets(4)+3) = transfer(wigos, one_row(offsets(4):offsets(4)+3))
201  one_row(offsets(5)) = transfer(expver, one_row(5))
202  one_row(offsets(6)) = 5
203  cerr = odb_write_set_next_row(odb_it, one_row, c_ncolumns)
204  if (cerr /= 0) stop 1
205  enddo
206  deallocate(one_row)
207 
208  cerr = odb_write_iterator_delete(odb_it)
209  if (cerr == 0) cerr = odb_write_delete(odb_handle)
210  if (cerr /= 0) stop 1
211 
212 end subroutine example_fortran_api_setup
213 
215 
216  ! This function tests the reader api
217 
218  implicit none
219  type(c_ptr) :: odb_handle, odb_it
220  integer(kind=C_INT) :: cerr
221  character(kind=C_CHAR, len=max_varlen) :: config = c_null_char
222  character(kind=C_CHAR, len=max_varlen) :: inputfile = "test.odb"//achar(0)
223  type(c_ptr) :: ptr_colname
224  type(c_ptr) :: ptr_bitfield_names
225  type(c_ptr) :: ptr_bitfield_sizes
226  character(kind=C_CHAR,len=1), dimension(:), pointer :: f_ptr_colname
227  character(kind=C_CHAR,len=1), dimension(:), pointer :: f_ptr_bitfield_names
228  character(kind=C_CHAR,len=1), dimension(:), pointer :: f_ptr_bitfield_sizes
229  character(len=max_varlen) :: colname
230  character(len=max_varlen) :: bitfield_names
231  character(len=max_varlen) :: bitfield_sizes
232  integer(kind=4) :: i
233  integer(kind=C_INT) :: itype, newdataset, c_ncolumns=2, size_name
234  integer(kind=C_INT) :: bitfield_names_size, bitfield_sizes_size
235  real(kind=c_double), dimension(:), allocatable:: one_row
236  real(kind=c_double) :: val
237  integer(c_int) :: isize, ioffset
238  character(len=24) :: tmp_str1
239  character(len=8) :: tmp_str2
240  integer :: col
241 
242  write(0,*) 'example_fortran_api1'
243  odb_handle = odb_read_new(config, cerr)
244  odb_it = odb_read_iterator_new(odb_handle, inputfile, cerr);
245  if (cerr /= 0) stop 1
246 
247  ! Total number of columns
248 
249  cerr = odb_read_get_no_of_columns(odb_it, c_ncolumns)
250  if (cerr /=0) stop 2
251  if (c_ncolumns /= ncolumns) stop 3
252 
253  ! Total amount of data
254 
255  cerr = odb_read_get_row_buffer_size_doubles(odb_it, isize)
256  if (cerr /= 0) stop 4
257  if (isize /= row_size_doubles) stop 5 ! n.b. 9 in writer, but only needed 3 columns to encode strings!
258 
259  ! Check the values reported per column ...
260 
261  do col = 1, ncolumns
262 
263  cerr = odb_read_get_column_name(odb_it, col-1, ptr_colname,size_name)
264  if (cerr == 0) cerr = odb_read_get_column_type(odb_it, col-1, itype)
265  if (cerr == 0) cerr = odb_read_get_column_offset(odb_it, col-1, ioffset)
266  if (cerr == 0) cerr = odb_read_get_column_size_doubles(odb_it, col-1, isize)
267  if (cerr /= 0) stop 6
268 
269  ! Check the column names
270 
271  call c_f_pointer(cptr=ptr_colname, fptr=f_ptr_colname, shape=(/size_name/));
272  do i=1, size_name
273  colname(i:i) = f_ptr_colname(i)
274  end do
275  write(0,'(a,i1,3a,i1,a,i1,a)') 'column name ', col, ' : ', colname(1:size_name), &
276  ' [', ioffset, ', ', isize, ']'
277 
278  ! Do we get the expected values?
279 
280  if (colname(1:size_name) /= trim(column_names(col))) stop 7
281  if (itype /= column_types(col)) stop 9
282  if (ioffset /= column_offsets(col)) stop 11
283  if (isize /= column_sizes(col)) stop 12
284 
285  end do
286 
287  ! Test modified missing value
288 
289  val = -13
290  cerr = odb_read_get_missing_value(odb_it, 0, val)
291  if (cerr /=0) stop 13
292  write(0,*) 'odb_read_get_missing_value: missing value of column 0 => ', val
293  if (val /= 1.0) stop 14
294 
295  ! Test the contents of the bitfields
296 
297  cerr = odb_read_get_bitfield(odb_it, 2, ptr_bitfield_names, ptr_bitfield_sizes, bitfield_names_size, bitfield_sizes_size)
298  write(0,*) 'odb_read_get_bitfield column 2 => ', cerr
299  if (cerr /=0) stop 15
300  write(0,*) 'column 2 bitfield_names_size: ', bitfield_names_size
301  call c_f_pointer(cptr=ptr_bitfield_names, fptr=f_ptr_bitfield_names, shape=(/bitfield_names_size/));
302  do i=1, bitfield_names_size
303  bitfield_names(i:i) = f_ptr_bitfield_names(i)
304  end do
305  write(0,*) 'column 2 bitfield_names: ', bitfield_names(1:bitfield_names_size)
306  if (bitfield_names(1:bitfield_names_size) /= 'active:passive:blacklisted:') stop 16
307 
308  write(0,*) 'column 2 bitfield_sizes_size: ', bitfield_sizes_size
309  call c_f_pointer(cptr=ptr_bitfield_sizes, fptr=f_ptr_bitfield_sizes, shape=(/bitfield_sizes_size/));
310  do i=1, bitfield_sizes_size
311  bitfield_sizes(i:i) = f_ptr_bitfield_sizes(i)
312  end do
313  write(0,*) 'column 2 bitfield_sizes: ', bitfield_sizes(1:bitfield_sizes_size)
314  if (bitfield_sizes(1:bitfield_sizes_size) /= '1:1:4:') stop 17
315 
316  ! Test the contents of the data section!
317 
318  allocate(one_row(row_size_doubles))
319  do i = 1, 100
320 
321  cerr = odb_read_get_next_row(odb_it, c_ncolumns, one_row, newdataset)
322  if (cerr /= 0) exit
323 
324  ! Extract the strings
325 
326  tmp_str1(1:24) = transfer(one_row(column_offsets(4):column_offsets(5)-1), tmp_str1(1:24))
327  tmp_str2(1:8) = transfer(one_row(column_offsets(5)), tmp_str2(1:8))
328 
329  write(0,*) i, ":", one_row(column_offsets(1)), &
330  one_row(column_offsets(2)), &
331  one_row(column_offsets(3)), &
332  tmp_str1(1:24), " ", &
333  tmp_str2(1:8), &
334  one_row(column_offsets(6))
335 
336  if (one_row(column_offsets(1)) /= i) stop 18
337  if (one_row(column_offsets(2)) /= i) stop 19
338  if (one_row(column_offsets(3)) /= 5) stop 20
339  if (trim(tmp_str1(1:strlen(tmp_str1))) /= 'this-is-a-long-string') stop 21
340  if (trim(tmp_str2(1:strlen(tmp_str2))) /= 'fihn') stop 22
341  if (one_row(column_offsets(6)) /= 5) stop 23
342 
343  enddo
344  deallocate(one_row)
345 
346  ! Did we get the correct number of rows?
347 
348  if (i /= 11) stop 24
349 
350  ! Clean up
351 
352  cerr = odb_read_iterator_delete(odb_it)
353  cerr = odb_read_delete(odb_handle)
354 
355 end subroutine example_fortran_api1
356 
358  implicit none
359  type(c_ptr) :: odb_handle, odb_it
360  integer(kind=C_INT) :: cerr
361  character(kind=C_CHAR, len=64) :: config = c_null_char
362  type(c_ptr) :: ptr_colname
363  type(c_ptr) :: ptr_bitfield_names
364  type(c_ptr) :: ptr_bitfield_sizes
365  character(kind=C_CHAR), dimension(:), pointer :: f_ptr_colname
366  character(kind=C_CHAR,len=1), dimension(:), pointer :: f_ptr_bitfield_names
367  character(kind=C_CHAR,len=1), dimension(:), pointer :: f_ptr_bitfield_sizes
368  character(len=max_varlen) :: colname
369  character(len=max_varlen) :: bitfield_names
370  character(len=max_varlen) :: bitfield_sizes
371  integer(kind=4) :: i
372  character(kind=C_CHAR, len=128) :: sql='select * from "test.odb"'//achar(0)
373  integer(kind=C_INT) :: itype, newdataset, c_ncolumns=3, size_name
374  integer(kind=C_INT) :: bitfield_names_size, bitfield_sizes_size, ioffset, isize
375  real(kind=c_double), dimension(:), allocatable:: one_row
376  character(len=64) :: tmp_str1, tmp_str2
377  integer :: col
378 
379  write(0,*) 'example_fortran_api2'
380 
381  odb_handle = odb_select_new(config, cerr)
382  if (cerr == 0) odb_it = odb_select_iterator_new(odb_handle, sql, cerr);
383  if (cerr /= 0) stop 25
384 
385  ! Total number of columns
386 
387  cerr = odb_select_get_no_of_columns(odb_it, c_ncolumns)
388  if (cerr /=0) stop 26
389  if (c_ncolumns /= ncolumns) stop 27
390 
391  ! Total amount of data
392 
393  cerr = odb_select_get_row_buffer_size_doubles(odb_it, isize)
394  if (cerr /= 0) stop 28
395  if (isize /= row_size_doubles) stop 29 ! n.b. 9 in writer, but only needed 3 columns to encode strings!
396 
397  ! Check the values reported per column ...
398 
399  do col = 1, ncolumns
400 
401  cerr = odb_select_get_column_name(odb_it, col-1, ptr_colname,size_name)
402  if (cerr == 0) cerr = odb_select_get_column_type(odb_it, col-1, itype)
403  if (cerr == 0) cerr = odb_select_get_column_offset(odb_it, col-1, ioffset)
404  if (cerr == 0) cerr = odb_select_get_column_size_doubles(odb_it, col-1, isize)
405  if (cerr /= 0) stop 30
406 
407  ! Check the column names
408 
409  call c_f_pointer(cptr=ptr_colname, fptr=f_ptr_colname, shape=(/size_name/));
410  do i=1, size_name
411  colname(i:i) = f_ptr_colname(i)
412  end do
413  write(0,'(a,i1,3a,i1,a,i1,a)') 'column name ', col, ' : ', colname(1:size_name), &
414  ' [', ioffset, ', ', isize, ']'
415 
416  ! Do we get the expected values
417 
418  write(9,*) itype, column_types(col)
419  if (colname(1:size_name) /= trim(column_names(col))) stop 31
420  if (itype /= column_types(col)) stop 32
421  if (ioffset /= column_offsets(col)) stop 33
422  if (isize /= column_sizes(col)) stop 34
423 
424  end do
425 
426  ! Test the contents of the bitfields
427 
428  cerr = odb_select_get_bitfield(odb_it, 2, ptr_bitfield_names, ptr_bitfield_sizes, bitfield_names_size, bitfield_sizes_size)
429  write(0,*) 'odb_select_get_bitfield column 2 => ', cerr
430  if (cerr /=0) stop 35
431  write(0,*) 'column 2 bitfield_names_size: ', bitfield_names_size
432  call c_f_pointer(cptr=ptr_bitfield_names, fptr=f_ptr_bitfield_names, shape=(/bitfield_names_size/));
433  do i=1, bitfield_names_size
434  bitfield_names(i:i) = f_ptr_bitfield_names(i)
435  end do
436  write(0,*) 'column 2 bitfield_names: ', bitfield_names(1:bitfield_names_size)
437  if (bitfield_names(1:bitfield_names_size) /= 'active:passive:blacklisted:') stop 36
438 
439  write(0,*) 'column 2 bitfield_sizes_size: ', bitfield_sizes_size
440  call c_f_pointer(cptr=ptr_bitfield_sizes, fptr=f_ptr_bitfield_sizes, shape=(/bitfield_sizes_size/));
441  do i=1, bitfield_sizes_size
442  bitfield_sizes(i:i) = f_ptr_bitfield_sizes(i)
443  end do
444  write(0,*) 'column 2 bitfield_sizes: ', bitfield_sizes(1:bitfield_sizes_size)
445  if (bitfield_sizes(1:bitfield_sizes_size) /= '1:1:4:') stop 37
446 
447  ! Test the contents of the data section!
448 
449  allocate(one_row(row_size_doubles))
450  do i = 1, 100
451 
452  cerr = odb_select_get_next_row(odb_it, c_ncolumns, one_row, newdataset)
453  if ( cerr /= 0) exit
454 
455  ! Extract the strings
456 
457  tmp_str1(1:24) = transfer(one_row(column_offsets(4):column_offsets(5)-1), tmp_str1(1:24))
458  tmp_str2(1:8) = transfer(one_row(column_offsets(5)), tmp_str2(1:8))
459 
460  write(0,*) i, ":", one_row(column_offsets(1)), &
461  one_row(column_offsets(2)), &
462  one_row(column_offsets(3)), &
463  tmp_str1(1:24), " ", &
464  tmp_str2(1:8), &
465  one_row(column_offsets(6))
466 
467  if (one_row(column_offsets(1)) /= i) stop 39
468  if (one_row(column_offsets(2)) /= i) stop 40
469  if (one_row(column_offsets(3)) /= 5) stop 41
470  if (trim(tmp_str1(1:strlen(tmp_str1))) /= 'this-is-a-long-string') stop 42
471  if (trim(tmp_str2(1:strlen(tmp_str2))) /= 'fihn') stop 43
472  if (one_row(column_offsets(6)) /= 5) stop 44
473 
474  enddo
475  deallocate(one_row)
476 
477  ! Did we get the correct number of rows?
478 
479  if (i /= 11) stop 24
480 
481  ! Clean up
482 
483  cerr = odb_select_iterator_delete(odb_it)
484  cerr = odb_read_delete(odb_handle)
485 
486 end subroutine example_fortran_api2
487 end program example_fortran_api
Initialize ODB API. This function must be called before any other function from the ODB API.
program example_fortran_api
subroutine example_fortran_api_setup
subroutine example_fortran_api1
subroutine example_fortran_api_append
subroutine example_fortran_api2
Provides Fortran bindings for ODB API.
integer, parameter odb_integer
integer, parameter odb_bitfield
integer, parameter odb_double
integer(kind=c_int) function odb_read_get_column_offset(odb_iterator, n, offset)
integer(kind=c_int) function odb_write_get_column_offset(odb_iterator, n, offset)
integer, parameter odb_real
integer, parameter odb_string
integer(kind=c_int) function odb_select_get_column_offset(odb_iterator, n, offset)