FV3 Bundle
odb_helper_mod.F90
Go to the documentation of this file.
1 ! (C) Copyright 2018 UCAR
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 
6 !> Fortran module with ODB API utility routines
7 
9 
10 implicit none
11 
12 integer, parameter, private :: real32 = selected_real_kind(6)
13 integer, parameter, private :: real64 = selected_real_kind(15)
14 
15 contains
16 
17 subroutine count_query_results (filename, &
18  query, &
19  num_results)
20 
21 use odbql_wrappers, only: &
22  odbql, &
23  odbql_close, &
24  odbql_done, &
25  odbql_finalize, &
26  odbql_open, &
27  odbql_prepare_v2, &
28  odbql_row, &
29  odbql_step, &
30  odbql_stmt
31 
32 use, intrinsic :: iso_c_binding, only: &
33  c_int, &
34  c_null_char
35 
36 character(len=*), intent(in) :: filename
37 character(len=*), intent(in) :: query
38 integer, intent(out) :: num_results
39 
40 type(odbql) :: db
41 integer(kind=c_int) :: errstat
42 character(len=500) :: message
43 character(len=*),parameter :: myname = "count_query_results"
44 type(odbql_stmt) :: stmt
45 character(len=1000) :: unparsed_sql
46 external :: abor1_ftn
47 
48 call odbql_open (trim(filename) // c_null_char, &
49  db, &
50  errstat)
51 
52 if (errstat /= 0) then
53  write (message, '(a,i0)') myname // ": failure in odbql_open when counting for input file " // &
54  trim(filename) // ", errstat = ", errstat
55  call abor1_ftn (message)
56 end if
57 
58 call odbql_prepare_v2 (db, &
59  trim(query), &
60  -1_c_int, &
61  stmt, &
62  unparsed_sql, &
63  errstat)
64 
65 if (errstat /= 0) then
66  write (message, '(a,i0)') myname // ": failure in odbql_prepare_v2 when counting for input file " // &
67  trim(filename) // ", errstat = ", errstat
68  call abor1_ftn (message)
69 end if
70 
71 num_results = 0
72 do
73  call odbql_step (stmt, &
74  errstat)
75  select case (errstat)
76  case (odbql_done)
77  exit
78  case (odbql_row)
79  num_results = num_results + 1
80  case default
81  write(message, '(a,i0,a,i0)') myname // ": failure in odbql_step when counting for input file " // &
82  trim(filename) // ", errstat = ", errstat, " row number = ", num_results + 1
83  call abor1_ftn (message)
84  end select
85 end do
86 
87 call odbql_finalize(stmt)
88 call odbql_close(db)
89 
90 end subroutine count_query_results
91 
92 subroutine get_vars (filename, &
93  columns, &
94  filter, &
95  data)
96 
97 use odbql_wrappers, only: &
98  odbql, &
99  odbql_close, &
100  odbql_column_text, &
101  odbql_column_type, &
102  odbql_column_value, &
103  odbql_done, &
104  odbql_finalize, &
105  odbql_float, &
106  odbql_integer, &
107  odbql_open, &
108  odbql_prepare_v2, &
109  odbql_row, &
110  odbql_step, &
111  odbql_stmt, &
112  odbql_text, &
113  odbql_value, &
114  odbql_value_double, &
115  odbql_value_int
116 
117 use, intrinsic :: iso_c_binding, only: &
118  c_int, &
119  c_null_char
120 
121 character(len=*), intent(in) :: filename
122 character(len=*), intent(in) :: columns(:)
123 character(len=*), intent(in) :: filter
124 real(kind=real64), allocatable, intent(out) :: data(:,:)
125 
126 type(odbql) :: db
127 integer(kind=c_int) :: errstat
128 character(len=500) :: message
129 character(len=*),parameter :: myname = "get_vars"
130 external :: abor1_ftn
131 type(odbql_stmt) :: stmt
132 character(len=1000) :: unparsed_sql
133 integer :: num_results, num_columns, i, j, type
134 type(odbql_value) :: val
135 character(len=5000) :: query
136 character(len=30) :: string_val
137 
138 call odbql_open (trim(filename) // c_null_char, &
139  db, &
140  errstat)
141 
142 if (errstat /= 0) then
143  write (message, '(a,i0)') myname // ": failure in odbql_open when reading for input file " // &
144  trim(filename) // ", errstat = ", errstat
145  call abor1_ftn (message)
146 end if
147 
148 num_columns = size(columns)
149 
150 call create_query_sql (columns, filename, filter, query)
151 
152 call count_query_results (filename, query, num_results)
153 
154 allocate (data(num_columns,num_results))
155 
156 call odbql_prepare_v2 (db, &
157  trim(query), &
158  -1_c_int, &
159  stmt, &
160  unparsed_sql, &
161  errstat)
162 
163 if (errstat /= 0) then
164  write (message, '(a,i0)') myname // ": failure in odbql_prepare_v2 when reading for input file " // &
165  trim(filename) // ", errstat = ", errstat
166  call abor1_ftn (message)
167 end if
168 
169 do i = 1, num_results
170  call odbql_step (stmt, &
171  errstat)
172  select case (errstat)
173  case (odbql_row)
174  continue
175  case (odbql_done)
176  write(message, '(a,i0,a,i0)') myname // ": odbql_step exited early reading input file " // &
177  trim(filename) // " row number = ", i, " out of ", num_results
178  call abor1_ftn (message)
179  case default
180  write(message, '(a,i0,a,i0)') myname // ": failure in odbql_step when reading for input file " // &
181  trim(filename) // ", errstat = ", errstat, " row number = ", i
182  call abor1_ftn (message)
183  end select
184  do j = 1, num_columns
185  val = odbql_column_value(stmt, j)
186  select case (odbql_column_type(stmt, j))
187  case (odbql_float)
188  data(j,i) = odbql_value_double(val)
189  case (odbql_integer)
190  data(j,i) = odbql_value_int(val)
191  case (odbql_text)
192  call odbql_column_text (stmt, j, string_val)
193  data(j,i) = transfer(string_val(1:8), data(j,i))
194  case default
195  write (message, '(a,i0,a,i0)') myname // ": invalid column type for row ", i, " and column ", j
196  call abor1_ftn (message)
197  end select
198  end do
199 end do
200 
201 call odbql_finalize(stmt)
202 call odbql_close(db)
203 
204 end subroutine get_vars
205 
206 subroutine create_query_sql (column_names, &
207  filename, &
208  filter, &
209  sql)
211 implicit none
212 
213 character(len=*), intent(in) :: column_names(:)
214 character(len=*), intent(in) :: filename
215 character(len=*), intent(in) :: filter
216 character(len=*), intent(out) :: sql
217 
218 integer :: i
219 character(len=10000) :: sql_buffer
220 
221 sql = "select "
222 do i = 1, size (column_names)
223  sql_buffer = column_names(i)
224  if (i < size (column_names)) then
225  sql_buffer = trim(sql_buffer) // ","
226  end if
227  sql = trim(sql) // " " // sql_buffer
228 end do
229 
230 sql = trim(sql) // " from '" // trim(filename) // "' where " // trim(filter) // ";"
231 
232 end subroutine create_query_sql
233 
234 subroutine create_table_sql (column_names, &
235  column_types, &
236  filename, &
237  sql)
239 use odb_c_binding, only: &
240  odb_integer, &
241  odb_real, &
242  odb_string
243 
244 implicit none
245 
246 character(len=*), intent(in) :: column_names(:)
247 integer, intent(in) :: column_types(:)
248 character(len=*), intent(in) :: filename
249 character(len=*), intent(out) :: sql
250 
251 character(len=300) :: messages(3)
252 integer :: i
253 character(len=10000) :: sql_buffer
254 
255 sql = "CREATE TABLE odb AS ("
256 do i = 1, size (column_types)
257  select case (column_types(i))
258  case (odb_integer)
259  sql_buffer = trim(column_names(i)) // " INTEGER"
260  case (odb_real)
261  sql_buffer = trim(column_names(i)) // " REAL"
262  case (odb_string)
263  sql_buffer = trim(column_names(i)) // " STRING"
264  end select
265  if (i < size (column_types)) then
266  sql_buffer = trim(sql_buffer) // ","
267  end if
268  sql = trim(sql) // sql_buffer
269 end do
270 sql = trim(sql) // ") ON '" // trim(filename) // "';"
271 
272 end subroutine create_table_sql
273 
274 subroutine insert_into_sql (column_names, &
275  sql)
277 implicit none
278 
279 character(len=*), intent(in) :: column_names(:)
280 character(len=*), intent(out) :: sql
281 
282 integer :: i
283 character(len=10000) :: sql_buffer
284 
285 sql = "INSERT INTO odb ("
286 do i = 1, size (column_names)
287  sql_buffer = column_names(i)
288  if (i < size (column_names)) then
289  sql_buffer = trim(sql_buffer) // ","
290  end if
291  sql = trim(sql) // sql_buffer
292 end do
293 sql = trim(sql) // ") VALUES (" // repeat("?,", size (column_names) - 1) // "?);"
294 
295 end subroutine insert_into_sql
296 
297 end module odb_helper_mod
subroutine insert_into_sql(column_names, sql)
subroutine create_query_sql(column_names, filename, filter, sql)
subroutine count_query_results(filename, query, num_results)
integer, parameter, private real64
Fortran module with ODB API utility routines.
subroutine create_table_sql(column_names, column_types, filename, sql)
integer, parameter, private real32
subroutine get_vars(filename, columns, filter, data)