patterncppMinor
C++ SQL wrapper/Statement
Viewed 0 times
sqlwrapperstatement
Problem
Part 2: (Part 1)
Working on my SQL project at last.
The concept is easy to use and integrate SQL into C++.
Statement:
Is the generic statement object.
StatementProxy:
Holds DB specific code used by the statement.
Cursor:
Private class.
Used to iterate over each returned row from the DB.
BindArgs and Bind:
Way of grouping arguments that need to be bound.
I tried to make this code work without this type but that meant I would need to put the function first and the bind arguments last in the
Statement/Cursor is where we get the interesting meta programming happening. Have some fun and I hope you find it interesting.
Note: If you want to try compiling the code I suggest you check it out of the git repo and compile using the instructions there. But Saying that you can potentially compile it using only the source here just add a main().
Statement.h
```
#ifndef THORS_ANVIL_SQL_STATEMENT_H
#define THORS_ANVIL_SQL_STATEMENT_H
#include "SQLUtil.h"
#include
#include
namespace ThorsAnvil
{
namespace SQL
Working on my SQL project at last.
The concept is easy to use and integrate SQL into C++.
ThorsSQL::Connection mysql("mysql://host", "username", "password", "databaseName");
ThorsSQL::Statement bigEarnerStat(mysql,
"SELECT ID, Name, Salary FROM Employee WHERE Salary > % and Age < %"
ThorsAnvil::SQL::Prepare);
// Bind variables to '%' in statement
// Then execute the SQL statement.
// Call function for every row returned.
bigEarnerStat.execute(Bind(1000000, 32), // parameter bound to % in statement.
// Function executed for each row returned.
// Parameters are matched against the SELECT in the statement.
// A bad type conversion will throw an exception.
[](u64 id, std::string const& name, int salary){
std::cout << name << " is a fat cat earning $" << salary/100 << "." << salary%100 << "\n";
}
);Statement:
Is the generic statement object.
StatementProxy:
Holds DB specific code used by the statement.
Cursor:
Private class.
Used to iterate over each returned row from the DB.
BindArgs and Bind:
Way of grouping arguments that need to be bound.
I tried to make this code work without this type but that meant I would need to put the function first and the bind arguments last in the
execute() call (because of the way template var arguments are expanded).Statement/Cursor is where we get the interesting meta programming happening. Have some fun and I hope you find it interesting.
Note: If you want to try compiling the code I suggest you check it out of the git repo and compile using the instructions there. But Saying that you can potentially compile it using only the source here just add a main().
Statement.h
```
#ifndef THORS_ANVIL_SQL_STATEMENT_H
#define THORS_ANVIL_SQL_STATEMENT_H
#include "SQLUtil.h"
#include
#include
namespace ThorsAnvil
{
namespace SQL
Solution
[&list](){}();No. I don't care why you have it -- never put something like this in real code. At the very least, add a comment explaining what it's doing there. I, for one, can't tell at all.
Is it getting rid of an otherwise-present "unused variable" warning? Use
#pragma GCC diagnostic ignored "-Wunused-variable" instead, or at the very least (void) list, as is the standard (as far as I can tell) idiom. Is it to... play with the lifetime, or something? Maybe keep it from getting optimized out? Add a comment explaining that. Does it serve some other purpose that I can't see by looking at the code? Well, clearly you've got a problem, so explain what it's doing there.As it is, it's useless code, and all it's going to do is make someone -- maybe you, six months down the line -- stare at it and go, "What?"
It's also a huge code smell that it's necessary. I'd suggest rewriting the bits that have it to not use whatever clever tricks mean that it's necessary.
To add a little more, here are some things I found while scanning the code:
- Why do you have
ThorsSQLandThorsAnvil::SQL? Picking one and sticking with it would probably be better.
- Why is
Statement/StatementProxybasically a PIMPL, butStatementProxyis defined in the header? If, as seems to be the case, you're not using it anywhere except as pointers in your own classes, where it can be an incomplete type, you should move it out of the header and into the source file. That way you can change its internals without making everyone who uses your library recompile (since the header didn't change).
- I've never seen the
.tpppattern, but it looks both interesting and, in this case, somewhat pointless. Is there a specific reason to include it?
Code Snippets
[&list](){}();Context
StackExchange Code Review Q#94901, answer score: 6
Revisions (0)
No revisions yet.