2 * Copyright (C) 2004, Leo Seib, Hannover
4 * Project: C++ Dynamic Library
5 * Module: Dataset abstraction layer realisation file
6 * Author: Leo Seib E-Mail: leoseib@web.de
9 * SPDX-License-Identifier: MIT
10 * See LICENSES/README.md for more information.
15 #include "utils/StringUtils.h"
16 #include "utils/log.h"
22 #pragma warning(disable : 4800)
27 //************* Database implementation ***************
30 : error(), //S_NO_CONNECTION,
36 sequence_table("db_sequence")
38 active
= false; // No connection yet
44 disconnect(); // Disconnect if connected to database
47 int Database::connectFull(const char* newHost
,
51 const char* newPasswd
,
55 const char* newCApath
,
56 const char* newCiphers
,
69 compression
= newCompression
;
73 std::string
Database::prepare(const char* format
, ...)
76 va_start(args
, format
);
77 std::string result
= vprepare(format
, args
);
83 //************* Dataset implementation ***************
85 Dataset::Dataset() : select_sql("")
89 haveError
= active
= false;
94 fields_object
= new Fields();
96 edit_object
= new Fields();
99 Dataset::Dataset(Database
* newDb
) : select_sql("")
103 haveError
= active
= false;
108 fields_object
= new Fields();
110 edit_object
= new Fields();
119 delete fields_object
;
123 void Dataset::setSqlParams(sqlType t
, const char* sqlFrmt
, ...)
126 char sqlCmd
[DB_BUFF_MAX
+ 1];
128 va_start(ap
, sqlFrmt
);
130 _vsnprintf(sqlCmd
, DB_BUFF_MAX
- 1, sqlFrmt
, ap
);
132 vsnprintf(sqlCmd
, DB_BUFF_MAX
- 1, sqlFrmt
, ap
);
139 set_select_sql(sqlCmd
);
142 add_update_sql(sqlCmd
);
145 add_insert_sql(sqlCmd
);
148 add_delete_sql(sqlCmd
);
156 void Dataset::set_select_sql(const char* sel_sql
)
158 select_sql
= sel_sql
;
161 void Dataset::set_select_sql(const std::string
& sel_sql
)
163 select_sql
= sel_sql
;
166 void Dataset::parse_sql(std::string
& sql
)
168 std::string fpattern
, by_what
;
169 for (unsigned int i
= 0; i
< fields_object
->size(); i
++)
171 fpattern
= ":OLD_" + (*fields_object
)[i
].props
.name
;
172 by_what
= "'" + (*fields_object
)[i
].val
.get_asString() + "'";
175 while ((idx
= sql
.find(fpattern
, next_idx
)) >= 0)
177 next_idx
= idx
+ fpattern
.size();
178 if (sql
.length() > ((unsigned int)next_idx
))
179 if (isalnum(sql
[next_idx
]) || sql
[next_idx
] == '_')
183 sql
.replace(idx
, fpattern
.size(), by_what
);
187 for (unsigned int i
= 0; i
< edit_object
->size(); i
++)
189 fpattern
= ":NEW_" + (*edit_object
)[i
].props
.name
;
190 by_what
= "'" + (*edit_object
)[i
].val
.get_asString() + "'";
193 while ((idx
= sql
.find(fpattern
, next_idx
)) >= 0)
195 next_idx
= idx
+ fpattern
.size();
196 if (sql
.length() > ((unsigned int)next_idx
))
197 if (isalnum(sql
[next_idx
]) || sql
[next_idx
] == '_')
201 sql
.replace(idx
, fpattern
.size(), by_what
);
206 void Dataset::close(void)
213 name2indexMap
.clear();
216 bool Dataset::seek(int pos
)
218 frecno
= (pos
< num_rows() - 1) ? pos
: num_rows() - 1;
219 frecno
= (frecno
< 0) ? 0 : frecno
;
220 fbof
= feof
= (num_rows() == 0) ? true : false;
221 return ((bool)frecno
);
224 void Dataset::refresh()
227 if ((row
!= 0) && active
)
237 void Dataset::first()
239 if (ds_state
== dsSelect
)
242 feof
= fbof
= (num_rows() > 0) ? false : true;
248 if (ds_state
== dsSelect
)
251 if (frecno
< num_rows() - 1)
265 if (ds_state
== dsSelect
)
282 if (ds_state
== dsSelect
)
284 frecno
= (num_rows() > 0) ? num_rows() - 1 : 0;
285 feof
= fbof
= (num_rows() > 0) ? false : true;
289 bool Dataset::goto_rec(int pos
)
291 if (ds_state
== dsSelect
)
293 return seek(pos
- 1);
298 void Dataset::insert()
300 edit_object
->resize(field_count());
301 for (int i
= 0; i
< field_count(); i
++)
303 (*fields_object
)[i
].val
= "";
304 (*edit_object
)[i
].val
= "";
305 (*edit_object
)[i
].props
= (*fields_object
)[i
].props
;
312 if (ds_state
!= dsSelect
)
314 throw DbErrors("Editing is possible only when query exists!");
316 edit_object
->resize(field_count());
317 for (unsigned int i
= 0; i
< fields_object
->size(); i
++)
319 (*edit_object
)[i
].props
= (*fields_object
)[i
].props
;
320 (*edit_object
)[i
].val
= (*fields_object
)[i
].val
;
327 if (ds_state
== dsInsert
)
329 else if (ds_state
== dsEdit
)
338 void Dataset::deletion()
340 if (ds_state
== dsDelete
)
344 bool Dataset::set_field_value(const char* f_name
, const field_value
& value
)
346 if ((ds_state
== dsInsert
) || (ds_state
== dsEdit
))
348 const int idx
= fieldIndex(f_name
);
351 (*edit_object
)[idx
].val
= value
;
354 throw DbErrors("Field not found: %s", f_name
);
356 throw DbErrors("Not in Insert or Edit state");
360 const field_value
& Dataset::get_field_value(const char* f_name
)
362 if (ds_state
!= dsInactive
)
364 if (ds_state
== dsEdit
|| ds_state
== dsInsert
)
366 const int idx
= fieldIndex(f_name
);
368 return (*edit_object
)[idx
].val
;
370 throw DbErrors("Field not found: %s", f_name
);
374 int idx
= fieldIndex(f_name
);
377 const char* name
= strstr(f_name
, ".");
382 idx
= fieldIndex(name
);
386 return (*fields_object
)[idx
].val
;
388 throw DbErrors("Field not found: %s", f_name
);
391 throw DbErrors("Dataset state is Inactive");
394 const field_value
& Dataset::get_field_value(int index
)
396 if (ds_state
!= dsInactive
)
398 if (ds_state
== dsEdit
|| ds_state
== dsInsert
)
400 if (index
< 0 || index
>= field_count())
401 throw DbErrors("Field index not found: %d", index
);
403 return (*edit_object
)[index
].val
;
407 if (index
< 0 || index
>= field_count())
408 throw DbErrors("Field index not found: %d", index
);
410 return (*fields_object
)[index
].val
;
413 throw DbErrors("Dataset state is Inactive");
416 const sql_record
* Dataset::get_sql_record()
418 if (result
.records
.empty() || frecno
>= (int)result
.records
.size())
421 return result
.records
[frecno
];
424 field_value
Dataset::f_old(const char* f_name
)
426 if (ds_state
!= dsInactive
)
427 for (int unsigned i
= 0; i
< fields_object
->size(); i
++)
428 if ((*fields_object
)[i
].props
.name
== f_name
)
429 return (*fields_object
)[i
].val
;
433 void Dataset::setParamList(const ParamList
& params
)
438 bool Dataset::locate()
444 std::map
<std::string
, field_value
>::const_iterator i
;
449 for (i
= plist
.begin(); i
!= plist
.end(); ++i
)
450 if (fv(i
->first
.c_str()).get_asString() == i
->second
.get_asString())
468 bool Dataset::locate(const ParamList
& params
)
474 bool Dataset::findNext(void)
480 std::map
<std::string
, field_value
>::const_iterator i
;
484 for (i
= plist
.begin(); i
!= plist
.end(); ++i
)
485 if (fv(i
->first
.c_str()).get_asString() == i
->second
.get_asString())
503 void Dataset::add_update_sql(const char* upd_sql
)
505 std::string s
= upd_sql
;
506 update_sql
.push_back(s
);
509 void Dataset::add_update_sql(const std::string
& upd_sql
)
511 update_sql
.push_back(upd_sql
);
514 void Dataset::add_insert_sql(const char* ins_sql
)
516 std::string s
= ins_sql
;
517 insert_sql
.push_back(s
);
520 void Dataset::add_insert_sql(const std::string
& ins_sql
)
522 insert_sql
.push_back(ins_sql
);
525 void Dataset::add_delete_sql(const char* del_sql
)
527 std::string s
= del_sql
;
528 delete_sql
.push_back(s
);
531 void Dataset::add_delete_sql(const std::string
& del_sql
)
533 delete_sql
.push_back(del_sql
);
536 void Dataset::clear_update_sql()
541 void Dataset::clear_insert_sql()
546 void Dataset::clear_delete_sql()
551 size_t Dataset::insert_sql_count()
553 return insert_sql
.size();
556 size_t Dataset::delete_sql_count()
558 return delete_sql
.size();
561 int Dataset::field_count()
563 return fields_object
->size();
565 int Dataset::fieldCount()
567 return fields_object
->size();
570 const char* Dataset::fieldName(int n
)
572 if (n
< field_count() && n
>= 0)
573 return (*fields_object
)[n
].props
.name
.c_str();
578 char* Dataset::str_toLower(char* s
)
580 for (char* p
= s
; *p
; p
++)
581 *p
= std::tolower(*p
);
586 int Dataset::fieldIndex(const char* fn
)
588 std::string
name(fn
);
589 const auto it
= name2indexMap
.find(str_toLower(name
.data()));
590 if (it
!= name2indexMap
.end())
596 //************* DbErrors implementation ***************
598 DbErrors::DbErrors() : msg_("Unknown Database Error")
602 DbErrors::DbErrors(const char* msg
, ...)
606 char buf
[DB_BUFF_MAX
] = "";
608 _vsnprintf(buf
, DB_BUFF_MAX
- 1, msg
, vl
);
610 vsnprintf(buf
, DB_BUFF_MAX
- 1, msg
, vl
);
616 CLog::Log(LOGERROR
, "{}", msg_
);
619 const char* DbErrors::getMsg()
624 } // namespace dbiplus