Skip to content
This repository has been archived by the owner on Jul 9, 2019. It is now read-only.

Commit

Permalink
Update readme, change sql_blob, remove sqldb class
Browse files Browse the repository at this point in the history
  • Loading branch information
Ryan Jennings committed Apr 25, 2018
1 parent 0aa0af8 commit 5a32774
Show file tree
Hide file tree
Showing 22 changed files with 172 additions and 90 deletions.
92 changes: 53 additions & 39 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ obj.set("first_name", "John");
obj.set("last_name", "Doe");
if(!obj.save()) {
cerr << testdb.last_error() << endl;
cerr << current_session.last_error() << endl;
}
```

Expand All @@ -143,7 +143,7 @@ user obj;
obj.set_id(1);

if(!obj.remove()) {
cerr << testdb.last_error() << endl;
cerr << current_session.last_error() << endl;
}
```

Expand Down Expand Up @@ -193,10 +193,10 @@ find_by_id<user>(schema, 1234, [](const shared_ptr<user> &record) {
example using a *return value* for a *generic record*:

```c++
auto results = find_all(user.schema());
auto results = find_all(schema);

for (auto record : results) {
cout << "User: " << record->to_string() << endl;
cout << "Obj: " << record->to_string() << endl;
}
```

Expand All @@ -215,7 +215,7 @@ insert.into("users").columns("id", "first_name", "last_name")
.values(4321, "dave", "patterson");

if (!query.execute()) {
cerr << testdb.last_error() << endl;
cerr << current_session.last_error() << endl;
} else {
cout << "last insert id " << query.last_insert_id() << endl;
}
Expand Down Expand Up @@ -271,11 +271,11 @@ query.from("users").execute([](const resultset & rs)
{
// do something with a resultset

rs.for_each([](const row & r)
rs.each([](const row & r)
{
// do something with a row

r.for_each([](const column & c)
r.each([](const column & c)
{
// do something with a column
});
Expand Down Expand Up @@ -305,27 +305,6 @@ select.columns("u.id", "s.setting").from("users u")
select.execute();
```

Batch Queries
-------------

The library supports batch mode by default. This means upon execution, its will reset the query to a pre-bind state.

```c++
/* execute some raw sql */
insert_query insert(current_session);

insert.into("users").columns("counter");

for(int i = 1000; i < 3000; i++) {
// set new values for the insert
insert.bind(1, i);

if (!insert.execute()) {
cerr << testdb.last_error() << endl;
}
}
```
Raw Queries
-----------

Expand All @@ -344,6 +323,7 @@ Transactions
Transactions can be performed on a session object.
```c++
...
{
auto tx = current_session->start_transaction();
Expand All @@ -360,16 +340,30 @@ Transactions can be performed on a session object.
tx->set_successful(true);
}
// tx will be commited here
...
```

Prepared Statements
===================

By default **the library will use the prepared statement syntax of the database being used**. This is the most efficient use.
#### Parameters

If you turn on **ENHANCED_PARAMENTER_MAPPING (experiemental feature)** then the syntaxes are database independent.
By default the library will use the prepared statement syntax of the database being used. This is the most efficient use.

Enhanced parameter mapping supports different syntaxes. You can use different syntaxes in the same query if you really wanted.
*****

###### **ENHANCED_PARAMENTER_MAPPING (experimental feature)**

If you compile with this flag, then the following syntaxes are managed by the library.

- **$1, $2**, etc :
- indexed parameter
- **?** :
- ordered index parameter (the first ? is equivalent to $1 and so on)
- **@name** :
- named paramters separate from indexed parameters

With this flag you can combine the different syntaxes.... in the same query if you really wanted.

Example:

Expand All @@ -379,9 +373,25 @@ Example:
"?, ?, @name, ?"
```

When mixing indexed parameters, the unidentified '?' is equivalent to parameter 1 or '$1' and so on.
#### Behaviour

Upon execution, the queries will be reset to a pre-bind state.

```c++
/* execute some raw sql */
insert_query insert(current_session);

insert.into("users").columns("counter");

for(int i = 1000; i < 3000; i++) {
// set new values for the insert
insert.bind(1, i);

Named parameters operate outside indexed parameters.
if (!insert.execute()) {
cerr << current_session.last_error() << endl;
}
}
```
Where Clauses / Binding
Expand All @@ -394,9 +404,9 @@ Where clauses in select/delete/join queries have a dedicated class.
query.where(equals("param1", value1)) and !in("param2", {24, 54}) or startswith("param3", "abc");
```

The 'and' and 'or' keywords are the same as calling the && || operators.
('and' and 'or' keywords are equivalent to the && || operators in c++)

The library will also put the appropriate combined AND/OR into brackets (experiemental). In the above example in postgres would result in:
The above example would produce the following SQL in postgres:

```
(param1 = $1 AND param2 NOT IN ($2,$3)) OR (param3 like $4)
Expand Down Expand Up @@ -427,7 +437,7 @@ They can all be negated using the operator! (ex. !like )
Types
=====

sql_value is implemented using a variant (currently boost::variant, untill c++17 variant becomes available).
sql_value is the base type and implemented using a variant (currently boost::variant, until c++17 variant becomes available).

sql_value is capable of converting between the basic SQL values (when possible).

Expand Down Expand Up @@ -476,7 +486,7 @@ currently defined as a vector of bytes.
```c++
/* set data here */
unsigned char *data = new unsigned char[size];
void *data = malloc(sz);
/*
* create a blob value, this will create a copy of the data
Expand Down Expand Up @@ -525,7 +535,11 @@ Alternatives
TODO / ROADMAP
==============

* More and better quality tests, especially around binding and data types
* better benchmarking and perf improvements
[ ] Custom where clause operators
[ ] More testing around binding
[ ] More testing around data types
[ ] More testing with where clauses
[ ] Better benchmarking and perf improvements
[ ] Finish/improve fuzz testing


12 changes: 12 additions & 0 deletions src/alloc.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "alloc.h"
#include <cstring>

namespace coda {
namespace db {
Expand All @@ -16,5 +17,16 @@ namespace coda {
}
return mem;
}

void *c_copy(const void *data, size_t sz) {
if (sz == 0 || data == nullptr) {
return nullptr;
}

void *mem = c_alloc(sz);

std::memmove(mem, data, sz);
return mem;
}
}
}
2 changes: 2 additions & 0 deletions src/alloc.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ namespace coda {
*/
void *c_alloc(size_t size, size_t num = 1);

void *c_copy(const void *data, size_t sz);

/*!
* reallocate a value to a new size
* @param value the existing memory block
Expand Down
9 changes: 3 additions & 6 deletions src/mysql/binding.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -253,8 +253,7 @@ namespace coda
case MYSQL_TYPE_LONG_BLOB:
case MYSQL_TYPE_BLOB: {
if (binding->length) {
unsigned char *blob = reinterpret_cast<unsigned char *>(binding->buffer);
return sql_blob(blob, blob + *binding->length);
return sql_blob(binding->buffer, *binding->length);
}

return sql_blob();
Expand Down Expand Up @@ -335,7 +334,7 @@ namespace coda
case MYSQL_TYPE_MEDIUM_BLOB:
case MYSQL_TYPE_LONG_BLOB:
case MYSQL_TYPE_BLOB: {
return sql_blob(value, value + length);
return sql_blob(value, length);
}
case MYSQL_TYPE_NULL:
return sql_null;
Expand Down Expand Up @@ -511,9 +510,7 @@ namespace coda
void operator()(const sql_blob &value) const
{
bind_->buffer_type = MYSQL_TYPE_BLOB;
void *ptr = c_alloc(value.size());
memcpy(ptr, value.data(), value.size());
bind_->buffer = ptr;
bind_->buffer = c_copy(value.get(), value.size());
bind_->buffer_length = value.size();
if (!bind_->length) {
bind_->length = c_alloc<unsigned long>();
Expand Down
6 changes: 3 additions & 3 deletions src/postgres/binding.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ namespace coda
case BYTEAOID: {
size_t blen = 0;
unsigned char *b = PQunescapeBytea(reinterpret_cast<const unsigned char *>(value), &blen);
sql_blob bin(b, b + blen);
sql_blob bin(b, blen);
free(b);
return bin;
}
Expand Down Expand Up @@ -250,8 +250,8 @@ namespace coda
}
void operator()(const sql_blob &value) const
{
string temp(value.begin(), value.end());
bind_.values_[index_] = strdup(temp.c_str());

bind_.values_[index_] = static_cast<char*>(c_copy(value.get(), value.size()));
bind_.types_[index_] = BYTEAOID;
bind_.lengths_[index_] = value.size();
bind_.formats_[index_] = 1;
Expand Down
2 changes: 1 addition & 1 deletion src/resultset.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ namespace coda {
return begin() == end();
}

void resultset::for_each(const std::function<void(const row &row)> &funk) const {
void resultset::each(const std::function<void(const row &row)> &funk) const {
for (auto &row : *this) {
funk(row);
}
Expand Down
2 changes: 1 addition & 1 deletion src/resultset.h
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,7 @@ namespace coda {
/*!
* @param funk the callback to perform for each row
*/
void for_each(const std::function<void(const row_type &)> &funk) const;
void each(const std::function<void(const row_type &)> &funk) const;

/*!
* @return a pointer to the implementation
Expand Down
2 changes: 1 addition & 1 deletion src/row.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ namespace coda {
return impl_ != nullptr && impl_->is_valid();
}

void row::for_each(const std::function<void( const db::column &)> &funk) const {
void row::each(const std::function<void( const db::column &)> &funk) const {
for ( auto &c : *this) {
funk(c);
}
Expand Down
2 changes: 1 addition & 1 deletion src/row.h
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,7 @@ namespace coda {
* performs a callback for each column
* @param funk the callback
*/
void for_each(const std::function<void(const db::column &)> &funk) const;
void each(const std::function<void(const db::column &)> &funk) const;

/*!
* gets the implementation for this row
Expand Down
13 changes: 11 additions & 2 deletions src/sql_common.cpp
Original file line number Diff line number Diff line change
@@ -1,17 +1,26 @@
#include "sql_common.h"
#include <codecvt>
#include <locale>
#include <cstdlib>
#include "sql_number.h"

namespace coda {
namespace db {
std::ostream &operator<<(std::ostream &out, const sql_blob &value) {
out << std::string(value.begin(), value.end());
if (value.size() == 0) {
out << "NULL";
} else {
out << std::hex << (intptr_t) value.get();
}
return out;
}

std::wostream &operator<<(std::wostream &out, const sql_blob &value) {
out << std::wstring(value.begin(), value.end());
if (value.size() == 0) {
out << "NULL";
} else {
out << std::hex << (intptr_t) value.get();
}
return out;
}

Expand Down
20 changes: 15 additions & 5 deletions src/sql_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

#include <string>
#include <vector>
#include <memory>

namespace coda {
namespace db {
Expand All @@ -17,18 +18,27 @@ namespace coda {
*/
extern const sql_null_type sql_null;

/*!
* blobs are simple vectors of unsigned chars
*/
typedef std::vector<unsigned char> sql_blob;

typedef std::string sql_string;
typedef std::wstring sql_wstring;

class sql_number;

class sql_time;

/*!
* blobs are simple vectors of unsigned chars
*/
class sql_blob {
public:
sql_blob();
sql_blob(const void *data, size_t size);
void *get() const;
size_t size() const;
private:
std::shared_ptr<void> value_;
size_t size_;
};

/**
* template helper to see if a type is appropriate for a sql number
*/
Expand Down

0 comments on commit 5a32774

Please sign in to comment.