Skip to content

Commit c44c534

Browse files
added logging logic
1 parent e2c19ad commit c44c534

File tree

2 files changed

+122
-12
lines changed

2 files changed

+122
-12
lines changed

sqlite3pp_ez.cpp

Lines changed: 96 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@
1818
#include <direct.h>
1919
#include <cassert>
2020

21+
22+
#define V_COUT(VB, V) {if (sqlite3pp::sql_base::GetVerbosityLevel() >= sqlite3pp::VBLV_##VB) {std::cout << __FUNCTION__ << ":" << #VB << ": " << V << std::endl;} }
23+
2124
namespace sqlite3pp
2225
{
2326
///////////////////////////////////////////////////////////////////////////
@@ -69,6 +72,17 @@ namespace sqlite3pp
6972
}
7073
#endif // _UNICODE
7174

75+
VerbosityLevels sql_base::m_VerbosityLevels = VBLV_ERROR;
76+
void sql_base::SetVerbosityLevel(VerbosityLevels v)
77+
{
78+
m_VerbosityLevels = v;
79+
}
80+
81+
VerbosityLevels sql_base::GetVerbosityLevel()
82+
{
83+
return m_VerbosityLevels;
84+
}
85+
7286
int database::connect( wchar_t const * dbname, int flags, const wchar_t * vfs )
7387
{
7488
if ( !borrowing_ )
@@ -340,11 +354,20 @@ namespace sqlite3pp
340354
const char *SQLiteClassBuilder::Nill = "#NILL#";
341355
const char *SQLiteClassBuilder::CreateHeaderForAllTables = "%_CreateHeaderForAllTables_%";
342356

343-
std::string SQLiteClassBuilder::GetType(const char* str_org)
357+
std::string SQLiteClassBuilder::GetType(const std::string &tblVw, const std::string &colName, const char* str_org)
358+
{
359+
std::string strtype = GetType_s(tblVw, colName, str_org);
360+
V_COUT(DETAIL, "Using type '" << strtype << "' for column '" << colName << "' in table/view '" << tblVw << "'.");
361+
return strtype;
362+
}
363+
364+
std::string SQLiteClassBuilder::GetType_s(const std::string &tblVw, const std::string &colName, const char* str_org)
344365
{
345366
const std::string DefaultType = "Text";
346367
if (!str_org)
347368
{
369+
// Logging out as DEBUG because some views do return NULL value for the column type.
370+
V_COUT(DEBUG, "Entered with DB type NULL value for column '" << colName << "' in table/view '" << tblVw << "'.\nGracefully continuing by returning default type '" << DefaultType << "'.");
348371
return DefaultType;
349372
}
350373
char str[99] = { 0 };
@@ -364,6 +387,14 @@ namespace sqlite3pp
364387

365388
if (UseBaseTypes || m_options.m.use_basic_types_only)
366389
{
390+
// Only output detail once
391+
static bool HasLoggedDetails = false;
392+
if (!HasLoggedDetails)
393+
{
394+
HasLoggedDetails = true;
395+
V_COUT(DETAIL, "Only setting DB types to basic types due to compiler #define SQLITE3PP_CONVERT_TO_RESULTING_AFFINITY(" << UseBaseTypes << ") or input option use_basic_types_only(" << m_options.m.use_basic_types_only << ")");
396+
}
397+
367398
if (strcmp("INTEGER", str) == 0 || strcmp("INT", str) == 0 || strcmp("TINYINT", str) == 0 || strcmp("SMALLINT", str) == 0 || strcmp("MEDIUMINTSMALLINT", str) == 0 || strcmp("BIGINT", str) == 0 || strcmp("UNSIGNED BIG INT", str) == 0 || strcmp("INT2", str) == 0 || strcmp("INT8", str) == 0)
368399
return "int";
369400
if (strcmp("REAL", str) == 0 || strcmp("DOUBLE", str) == 0 || strcmp("DOUBLE PRECISION", str) == 0 || strcmp("FLOAT", str) == 0 || strncmp("DECIMAL", str, 7) == 0 || strcmp("BOOLEANL", str) == 0 || strcmp("BOOLEAN", str) == 0 || strcmp("DATE", str) == 0 || strcmp("DATETIME", str) == 0 || strcmp("NUMERIC", str) == 0)
@@ -432,7 +463,9 @@ namespace sqlite3pp
432463
return "Nvarchar";
433464
}
434465

466+
V_COUT(WARN, "Received unknown type ('" << str_org << "') from DB for column '" << colName << "' in table/view '" << tblVw << "'.");
435467
assert(0); // Always assert, because the code should not reach this point.
468+
V_COUT(WARN, "Gracefully continuing by returning default type '" << DefaultType << "'.");
436469
return DefaultType; // Handle it gracefully for release mode.
437470
}
438471

@@ -451,32 +484,53 @@ namespace sqlite3pp
451484

452485
void SQLiteClassBuilder::Init(const std::string & TableOrView_name, const std::string & AndWhereClause)
453486
{
487+
if (m_options.h.dest_folder.size())
488+
{
489+
if (m_options.h.dest_folder[m_options.h.dest_folder.size() - 1] == '/')
490+
m_options.h.dest_folder[m_options.h.dest_folder.size() - 1] = '\\';
491+
else if (m_options.h.dest_folder[m_options.h.dest_folder.size() - 1] != '\\')
492+
m_options.h.dest_folder = +"\\";
493+
V_COUT(DEBUG, "Using destination path '" << m_options.h.dest_folder << "'.");
494+
}
495+
454496
if (TableOrView_name == CreateHeaderForAllTables)
497+
{
498+
V_COUT(DEBUG, "Calling CreateAllHeaders with Where Clause '" << AndWhereClause << "'.");
455499
CreateAllHeaders(m_options, AndWhereClause);
500+
}
456501
else if (!TableOrView_name.empty() && TableOrView_name != Nill)
502+
{
503+
V_COUT(DEBUG, "Calling CreateHeader with name '" << TableOrView_name << "'.");
457504
CreateHeader(TableOrView_name);
505+
}
458506
}
459507

460508
SQLiteClassBuilder::~SQLiteClassBuilder()
461509
{
510+
V_COUT(DEBUG, "Disconnecting database.");
462511
m_db.disconnect();
463512
}
464513

465514
bool SQLiteClassBuilder::CreateAllHeaders(const std::string &AndWhereClause)
466515
{
516+
V_COUT(DEBUG, "Calling CreateAllHeaders with Where Clause '" << AndWhereClause << "'.");
467517
return CreateAllHeaders(m_options, AndWhereClause);
468518
}
469519
static const char TopHeaderCommnetsPrt1[] = "/* This file was automatically generated using [Sqlite3pp_EZ].\nSqlite3pp_EZ Copyright (C) 2021 David Maisonave (http::\\www.axter.com)";
470520
static const char TopHeaderCommnetsPrt2[] = "For more details see https://github.com/David-Maisonave/sqlite3pp_EZ\n*/";
471521

472522
bool SQLiteClassBuilder::CreateHeaderPrefix(const std::string& TableName, std::ofstream &myfile, std::string& ClassName, std::string& HeaderUpper, std::string FirstColumnName, std::string LastColumnName, bool AppendToVect)
473523
{
524+
V_COUT(DEBUG, "Entering with arguments: '" << TableName << "', ofstream, '" << ClassName << "', '" << HeaderUpper << "', '" << FirstColumnName << "', '" << LastColumnName << "', " << AppendToVect);
474525
std::ios_base::openmode openMode = m_AppendTableToHeader ? std::ios_base::out | std::ios_base::app : std::ios_base::out;
475526
ClassName = m_options.h.header_prefix + TableName + m_options.h.header_postfix;
476527
const std::string HeaderFileName = m_options.h.dest_folder + ClassName + "." + m_options.h.file_type;
477528
myfile.open(HeaderFileName.c_str(), openMode);
478529
if (!myfile.is_open())
530+
{
531+
V_COUT(WARN, "Failed to open file '" << HeaderFileName << "'");
479532
return false;
533+
}
480534
if (AppendToVect)
481535
m_HeadersCreated.push_back(HeaderFileName);
482536
char headerupper[256] = { 0 };
@@ -504,8 +558,14 @@ namespace sqlite3pp
504558
myfile << "#define " << HeaderUpper << std::endl;
505559
myfile << m_options.s.str_include << std::endl;
506560
if (m_options.h.header_include.size())
507-
myfile << "#include \"" << m_options.h.header_include << "\"" << std::endl;
561+
{
562+
std::string AdditionalInclude = "#include \"" + m_options.h.header_include + "\"";
563+
// Make sure is not already included.
564+
if (AdditionalInclude != m_options.s.str_include)
565+
myfile << AdditionalInclude << std::endl;
566+
}
508567

568+
V_COUT(DETAIL, "Created prefix data for class '" << ClassName << "' in file '" << HeaderFileName << "' for table '" << TableName << "'");
509569
return true;
510570
}
511571

@@ -531,7 +591,7 @@ namespace sqlite3pp
531591
m_options.h.header_prefix = OrgPrefix;
532592
std::ofstream myfile;
533593
std::string ClassName, HeaderUpper;
534-
if (CreateHeaderPrefix("All_Headers", myfile, ClassName, HeaderUpper, "", "", false))
594+
if (CreateHeaderPrefix("Master_Header", myfile, ClassName, HeaderUpper, "", "", false))
535595
{
536596
for (auto s : m_HeadersCreated)
537597
myfile << "#include \"" << s << "\"" << std::endl;
@@ -575,6 +635,7 @@ namespace sqlite3pp
575635
}
576636
myfile << "\n#endif // !" << HeaderUpper << std::endl;
577637
myfile.close();
638+
V_COUT(DETAIL, "Finish creating Master_Header file.");
578639
}
579640

580641
return true;
@@ -630,7 +691,7 @@ namespace sqlite3pp
630691
{
631692
if (strstr(qry->column_name(i), ":") != NULL) continue;
632693

633-
columns.push_back(std::pair<std::string, std::string>(qry->column_name(i), GetType(qry->column_decltype(i))));
694+
columns.push_back(std::pair<std::string, std::string>(qry->column_name(i), GetType(TableName, qry->column_name(i), qry->column_decltype(i))));
634695
columns_with_comma.push_back(std::pair<std::string, std::string>(qry->column_name(i), i ? ", " : ""));
635696
if (FirstColumnName.empty())
636697
FirstColumnName = qry->column_name(i);
@@ -775,6 +836,7 @@ namespace sqlite3pp
775836

776837
//Done
777838
myfile.close();
839+
V_COUT(DETAIL, "Finish creating class '" << ClassName << "' for table '" << TableName << "'");
778840
return true;
779841
}
780842

@@ -796,13 +858,19 @@ namespace sqlite3pp
796858
#endif // !SQLITE3PP_ALLOW_NULL_STRING_RETURN
797859
std::wstring value;
798860
const char * strtype = sqlite3_column_decltype(stmt_, idx);
861+
if (!strtype)
862+
{
863+
V_COUT(WARN, "Received NULL value when getting column type for idx " << idx << ". Treating type as ASCII or UTF8.");
864+
}
865+
799866
bool GetUnicodeString = false;
800867
if (!strtype || strcmp(strtype, "TEXT") == 0 || strncmp("CHARACTER", strtype, 9) == 0 || strncmp("VARYING CHARACTER", strtype, 17) == 0 || strncmp("VARCHAR", strtype, 7) == 0)
801868
GetUnicodeString = false;
802869
else if ( strncmp("NCHAR", strtype, 5) == 0 || strncmp("NVARCHAR", strtype, 8) == 0 || strncmp("NATIVE CHARACTER", strtype, 16) == 0)
803870
GetUnicodeString = true;
804871
else
805872
{
873+
V_COUT(WARN, "Could not find a string type to process. Treating type as ASCII or UTF8.");
806874
assert(0);// Code should NOT get here. If it does something went wrong.
807875
GetUnicodeString = false;
808876
}
@@ -813,6 +881,7 @@ namespace sqlite3pp
813881
char const* Val_a;
814882
const void* Val;
815883
};
884+
816885
if (GetUnicodeString)
817886
{
818887
Val_w = get(idx, (wchar_t const*)0);
@@ -878,15 +947,23 @@ namespace sqlite3pp
878947
Date data = { 0 };
879948
int rc = sscanf_s(s, "%d-%d-%d", &d.tm_year, &d.tm_mon, &d.tm_mday);
880949
if (rc < 1 || !d.tm_mday)
950+
{
951+
if (s) V_COUT(WARN, "Could not parse value '" << s << "' into a date.");
952+
if (rc < 1) V_COUT(WARN, "sscanf_s returned value less than 1 indicating invalid data.");
953+
if (!d.tm_mday) V_COUT(WARN, "tm_mday == 0. Invalid value.");
881954
return data;
955+
}
882956
if (d.tm_year > 1900)
883957
{
884958
d.tm_year -= 1900;
885959
d.tm_mon -= 1;
886960
}
887961
data.t = mktime(&d);
888962
if (data.t == -1)
963+
{
964+
V_COUT(WARN, "Received -1 from mktime.");
889965
return Date();
966+
}
890967
return data;
891968
}
892969

@@ -897,6 +974,9 @@ namespace sqlite3pp
897974
int rc = sscanf_s(s, "%d-%d-%d %d:%d:%d", &data.tm_struct.tm_year, &data.tm_struct.tm_mon, &data.tm_struct.tm_mday, &data.tm_struct.tm_hour, &data.tm_struct.tm_min, &data.tm_struct.tm_sec);
898975
if (rc < 1 || !data.tm_struct.tm_mday)
899976
{
977+
if (s) V_COUT(WARN, "Could not parse value '" << s << "' into a date.");
978+
if (rc < 1) V_COUT(WARN, "sscanf_s returned value less than 1 indicating invalid data.");
979+
if (!data.tm_struct.tm_mday) V_COUT(WARN, "tm_mday == 0. Invalid value.");
900980
return Datetime();
901981
}
902982

@@ -959,7 +1039,10 @@ namespace sqlite3pp
9591039
os << buf;
9601040
}
9611041
else
1042+
{
1043+
V_COUT(WARN, "tm_mday == 0. Invalid value.");
9621044
os << L"0000-00-00 00:00:00";
1045+
}
9631046
return os;
9641047
}
9651048

@@ -972,7 +1055,10 @@ namespace sqlite3pp
9721055
os << buf;
9731056
}
9741057
else
1058+
{
1059+
V_COUT(WARN, "tm_mday == 0. Invalid value.");
9751060
os << "0000-00-00 00:00:00";
1061+
}
9761062
return os;
9771063
}
9781064

@@ -987,7 +1073,10 @@ namespace sqlite3pp
9871073
os << buf;
9881074
}
9891075
else
1076+
{
1077+
V_COUT(WARN, "t.t = Invalid Falue.");
9901078
os << L"0000-00-00";
1079+
}
9911080
return os;
9921081
}
9931082

@@ -1002,7 +1091,10 @@ namespace sqlite3pp
10021091
os << buf;
10031092
}
10041093
else
1094+
{
1095+
V_COUT(WARN, "t.t = Invalid Falue.");
10051096
os << "0000-00-00";
1097+
}
10061098
return os;
10071099
}
10081100
#endif // !SQLITE3PP_CONVERT_TO_RESULTING_AFFINITY

sqlite3pp_ez.h

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,15 @@
3232

3333
namespace sqlite3pp
3434
{
35+
enum VerbosityLevels {
36+
VerbosityLevels_NO_OUTPUT = 0
37+
, VBLV_ERROR = 1 // Prints out unexpected behavior which will cause program to fail
38+
, VBLV_WARN = 2 // Prints out unexpected behavior, but program can still continue.
39+
, VBLV_INFO = 3 // Prints out process information
40+
, VBLV_DEBUG = 4 // Prints out information mainly useful for debugging
41+
, VBLV_DETAIL = 5 // Prints out expected behavior
42+
};
43+
3544
class sql_base
3645
{
3746
public:
@@ -94,11 +103,14 @@ namespace sqlite3pp
94103
static const char TableArg_PreExecuteArg[];
95104
static const char TableArg_WhereClauseArg[];
96105
static const char TableArg_DbFileNameArg[];
106+
static void SetVerbosityLevel(VerbosityLevels v);
107+
static VerbosityLevels GetVerbosityLevel();
97108

98109
protected:
99110
static sqlite3pp::database global_db; // To be used as global DB
100111
static bool bIsGlblDbOpen; // To be used as global DB
101112
static const char TableArg_ValueArg[];
113+
static VerbosityLevels m_VerbosityLevels; // Default value VBLV_ERROR
102114
};
103115

104116

@@ -379,11 +391,11 @@ namespace sqlite3pp
379391
};
380392
struct HeaderOpt
381393
{
382-
std::string dest_folder; // Can be empty, but if folder is specified, it must end with "\\". Otherwise it will be treated as part of the file name.
383-
std::string header_prefix; // Can be empty, or can specify a desired prefix for headers created.
384-
std::string header_postfix; // Can be empty, or can specify a desired postfix for header created.
385-
std::string file_type; // Default "h". Other options (hpp, hxx, class)
386-
std::string header_include; // Default "sqlite3pp_ez.h". Other options (../SQLite3pp_ez.h)
394+
std::string dest_folder; // Default: "SQL\\" Destination folder where headers are created. If drive letter is not included in the path, folder is treated as relative path.
395+
std::string header_prefix; // Default: "sql_" Desired prefix for headers created.
396+
std::string header_postfix; // Default: "" Desired postfix for header created.
397+
std::string file_type; // Default: "h" Other options (hpp, hxx, class)
398+
std::string header_include; // Default: "sqlite3pp_ez.h" Other options (..\\SQLite3pp_ez.h)
387399
};
388400
struct MiscOptions
389401
{
@@ -395,7 +407,7 @@ namespace sqlite3pp
395407
bool exclude_comments; // If true, excludes comments and additional spaces.
396408
bool exclude_table_interface; // If true, excludes sqlite3pp::Table interface functions ( getTableName, getColumnNames, and getStreamData), and excludes Miscellaneous function(s).
397409
bool use_basic_types_only; // If true, only int, double, std::string, and std::wstring are used
398-
bool exclude_main_hdr_example; // If true, excludes example code added to sql_All_Headers.h
410+
bool exclude_main_hdr_example; // If true, excludes example code added to sql_Master_Header.h
399411
bool exclude_comment_out_exampl;// If true, does NOT comment out example code
400412
}; // Create a custom defined TblClassOptions variable, or used one of the SQLiteClassBuilder predefined types, or use the default type which is automatically set by the SQLiteClassBuilder constructor
401413

@@ -415,8 +427,8 @@ namespace sqlite3pp
415427
bool m_AppendTableToHeader;
416428
std::vector<std::string> m_HeadersCreated;
417429
std::vector<std::string> m_ClassNames;
418-
std::string GetType(const char* str);
419-
static bool dir_exists(const std::string& foldername);
430+
std::string GetType(const std::string &tblVw, const std::string &colName, const char* str);
431+
std::string GetType_s(const std::string &tblVw, const std::string &colName, const char* str);
420432
TblClassOptions Init(const StrOptions & stroptions, const MiscOptions & miscoptions, const HeaderOpt & headeropt);
421433
void Init(
422434
const std::string& TableOrView_name
@@ -448,6 +460,12 @@ namespace sqlite3pp
448460
bool CreateAllHeaders(const TblClassOptions &strtype, const std::string &AndWhereClause = "");
449461
bool CreateHeader(const std::string& TableName, const TblClassOptions *strtype = NULL, std::string QueryStr = "");
450462

463+
const std::vector<std::string>& GetHeadersCreated() const { return m_HeadersCreated; }
464+
const std::vector<std::string>& GetClassNames() const { return m_ClassNames; }
465+
const std::string& GetDestFolder() const { return m_options.h.dest_folder; }
466+
467+
static bool dir_exists(const std::string& foldername);
468+
451469
// Predefined string options
452470
static const StrOptions strOpt_std_string ; // TEXT type defaults to std::string
453471
static const StrOptions strOpt_std_wstring; // TEXT type defaults to std::wstring

0 commit comments

Comments
 (0)