mirror of
https://github.com/rbock/sqlpp11.git
synced 2024-11-15 20:31:16 +08:00
Merge tag '0.36' into develop
Several breaking changes: * `from(a,b)` not allowed anymore, please use explicit joins * `where(true)` not allowed anymore, please use `.unconditionally()` or sqlpp::value(true) * `some_sql_expression and true` not allowed anymore, please use `tab.col == sqlpp::value(true)` if you really want to express this. * `having(expression)` requires `expression` to be made of aggregates, e.g. columns named in `group_by()` or aggregate functions like `count()` or constant values. * `where()` and `having()` accept only one parameter Several more clauses are now available as free functions. Lots of additional tests.
This commit is contained in:
commit
e629086e72
109
ChangeLog.md
Normal file
109
ChangeLog.md
Normal file
@ -0,0 +1,109 @@
|
||||
Important changes in sqlpp11
|
||||
============================
|
||||
|
||||
Breaking changes in 0.36:
|
||||
-------------------------
|
||||
__Abstract__:
|
||||
|
||||
One of the main motivations of sqlpp11 is to prevent SQL programming mistakes at compile time. The following changes prevent reported mishaps.
|
||||
* `from(a,b)` not allowed anymore, please use explicit joins
|
||||
* `where(true)` not allowed anymore, please use `.unconditionally()` or sqlpp::value(true)
|
||||
* `some_sql_expression and true` not allowed anymore, please use `tab.col == sqlpp::value(true)` if you really want to express this.
|
||||
* `having(expression)` requires `expression` to be made of aggregates, e.g. columns named in `group_by()` or aggregate functions like `count()` or constant values.
|
||||
* `where()` and `having` accept only one parameter
|
||||
|
||||
__Explicit joins required__:
|
||||
|
||||
Up until sqlpp11-0.35 you could write something like
|
||||
|
||||
```
|
||||
auto result = db(select(all_of(a), all_of(b))
|
||||
.from(a,b)
|
||||
.where(true));
|
||||
```
|
||||
|
||||
Using this syntax in `from()`, it was expected to have the join condition implicitly in the `where()` call.
|
||||
But there is no reliable way to tell whether or not that condition is there. Or, if there definitely is none, whether
|
||||
it was omitted on purpose or by accident.
|
||||
In one case, an accidentally omitted join condition in the `where()` brought a production system to a screeching halt.
|
||||
|
||||
In order to prevent this in the future, sqlpp11 now requires you to join table explicitly, including an explicit join condition, e.g.
|
||||
|
||||
```
|
||||
auto result = db(select(all_of(a), all_of(b))
|
||||
.from(a.join(b).on(a.b == b.id))
|
||||
.where(true));
|
||||
```
|
||||
|
||||
Most joins, (`join`/`inner_join`, `left_outer_join`, `right_outer_join` and `outer_join`) require a join condition to given via `on()`.
|
||||
The join condition has to be some sqlpp11 boolean expression.
|
||||
|
||||
In those rare cases, when you really need a cross join, you can also use `cross_join()` which has no join condition, of course.
|
||||
|
||||
```
|
||||
auto result = db(select(all_of(a), all_of(b))
|
||||
.from(a.cross_join(b))
|
||||
.where(true));
|
||||
```
|
||||
|
||||
__Use `.unconditionally()`__
|
||||
|
||||
If you want to select/update/remove all rows, earlier versions of sqlpp11 required the use of `where(true)`. Since version 0.36, use `unconditionally()`, for instance:
|
||||
```
|
||||
auto result = db(select(all_of(t)).from(t).unconditionally());
|
||||
```
|
||||
|
||||
__Use `sqlpp::value()` to wrap bool values in boolean expressions__
|
||||
|
||||
Lets say you had
|
||||
|
||||
```
|
||||
struct X
|
||||
{
|
||||
int a;
|
||||
int b;
|
||||
};
|
||||
auto x = X{};
|
||||
```
|
||||
|
||||
Then earlier versions of sqlpp11 would compile the following expression:
|
||||
|
||||
```
|
||||
select(all_of(t)).from(t).where(x.a == x.a or t.b == t.b);
|
||||
```
|
||||
|
||||
What you probably meant was:
|
||||
|
||||
```
|
||||
select(all_of(t)).from(t).where(t.a == x.a and t.b == x.b);
|
||||
```
|
||||
|
||||
In order to prevent this kind of mistake, boolean operators in sql expressions require sqlpp boolean expressions as operators.
|
||||
The library also requires the types of the left/right hand side operands of a comparison to be different, so that `t.a < t.a` does not compile any more.
|
||||
|
||||
In the rare case you really have a bool value that you want to use a boolean sql expression, you have to wrap it in sqlpp::value(x), e.g.
|
||||
|
||||
```
|
||||
select(all_of(t)).from(t).where(sqlpp::value(x.a == 17) and t.b == x.b);
|
||||
```
|
||||
|
||||
__`having()` requires aggregate expressions__
|
||||
|
||||
In older versions, the following code was allowed:
|
||||
|
||||
```
|
||||
select(all_of(t)).from(t).where(t.a > 7).having(t.b != "");
|
||||
```
|
||||
|
||||
As of sqlpp11-0.36, the having argument must be made of aggregate columns or functions, e.g.
|
||||
|
||||
```
|
||||
select(all_of(t)).from(t).unconditionally().group_by(t.b).having(t.b != "", avg(t.c) < 42);
|
||||
```
|
||||
|
||||
__`where()` and `having` accept only one expression__
|
||||
|
||||
In older versions, `where()` and `having()` would accept more than one argument and combine those arguments with `and`.
|
||||
I am not sure this was ever used. So it just made life harder for the compiler.
|
||||
|
||||
As of version 0.36, `where()` and `having()` accept only one parameter.
|
15
README.md
15
README.md
@ -145,11 +145,22 @@ Basic usage:
|
||||
__Linux install:__
|
||||
git clone date library, needed connectors, cmake and make install them.
|
||||
|
||||
create DDL files (like mysql: 'show create table MyDatabase.MyTable', but remove backticks), create headers for them with provided python script:
|
||||
|
||||
__Create DDL files__:
|
||||
```
|
||||
mysql: 'show create table MyDatabase.MyTable' #or
|
||||
mysqldump --no-data MyDatabase > MyDatabase.sql
|
||||
|
||||
```
|
||||
Create headers for them with provided python script:
|
||||
```
|
||||
%sqlpp11_dir%/scripts/ddl2cpp ~/temp/MyTable.ddl ~/temp/MyTable %DatabaseNamespaceForExample%
|
||||
```
|
||||
include generated header (MyTable.h), that's all
|
||||
(In case you're getting notes about unsupported column type take a look at the other datatypes in sqlpp11/data_types. They are not hard to implement.)
|
||||
|
||||
Include generated header (MyTable.h), that's all
|
||||
|
||||
|
||||
|
||||
|
||||
License:
|
||||
|
@ -128,6 +128,8 @@ types = {
|
||||
'date' : 'day_point',
|
||||
'datetime' : 'time_point',
|
||||
'timestamp' : 'time_point',
|
||||
'enum' : 'text', # MYSQL
|
||||
'set' : 'text', # MYSQL
|
||||
}
|
||||
|
||||
|
||||
@ -145,7 +147,7 @@ print('#include <' + INCLUDE + '/char_sequence.h>', file=header)
|
||||
print('', file=header)
|
||||
print('namespace ' + namespace, file=header)
|
||||
print('{', file=header)
|
||||
|
||||
DataTypeError = False;
|
||||
for create in tableCreations:
|
||||
sqlTableName = create.tableName
|
||||
tableClass = toClassName(sqlTableName)
|
||||
@ -181,7 +183,11 @@ for create in tableCreations:
|
||||
print(' const T& operator()() const { return ' + columnMember + '; }', file=header)
|
||||
print(' };', file=header)
|
||||
print(' };', file=header)
|
||||
traitslist = [NAMESPACE + '::' + types[sqlColumnType]];
|
||||
try:
|
||||
traitslist = [NAMESPACE + '::' + types[sqlColumnType]];
|
||||
except KeyError as e:
|
||||
print ('Error: datatype "' + sqlColumnType + '"" is not supported.')
|
||||
DataTypeError = True
|
||||
requireInsert = True
|
||||
if column.hasAutoValue:
|
||||
traitslist.append(NAMESPACE + '::tag::must_not_insert');
|
||||
@ -217,4 +223,10 @@ for create in tableCreations:
|
||||
|
||||
print('}', file=header)
|
||||
print('#endif', file=header)
|
||||
|
||||
if (DataTypeError):
|
||||
print("Error: unsupported datatypes." )
|
||||
print("Possible solutions:")
|
||||
print("A) Implement this datatype (examples: sqlpp11/data_types)" )
|
||||
print("B) Extend/upgrade ddl2cpp (edit types map)" )
|
||||
print("C) Raise an issue on github" )
|
||||
sys.exit(10) #return non-zero error code, we might need it for automation
|
||||
|
Loading…
Reference in New Issue
Block a user