These types were annoying to write out, and often involved importing
several types you wouldn't otherwise need to import.
These aliases are `serialize::Result` and `deserialize::Result`. I
intend to eventually move the relevant traits into these modules, but
this felt like a good standalone change.
If you run `infer_schema!` on an empty database, we generate this code:
allow_tables_to_appear_in_same_query!();
That macro doesn't allow an empty token list, so we get the error
"unexpected end of macro invocation" with no indication to the user of
how to fix it.
We could just skip generating that macro in `infer_schema!`, but this is
less code.
This adds `#[derive(SqlType)]`, which is responsible for implementing
`NotNull`, `SingleValue`, and potentially also implementing `HasSqlType`
on one or more backends. The body of `HasSqlType` is specified through
additional attributes. The only one of note is the `postgres` attribute,
which can do either static OIDs or dynamic type lookup.
`Array` and `Range` are not able to make full use of this derive, since
`Range` has a bunch of static OIDs and `Array` has a unique
implementation of `HasSqlType`.
At this point, the `custom_types` test is about as small as it's ever
going to get. The only way we could possibly eliminate any more code
there is by making it so you don't have to write as much of the
signature.
The nullable `ToSql` impl feels funky here,
but I've left it there to keep parity with the old macro.
Similar to `FromSqlRow`, there is an undocumented `foreign_derive` flag.
Any external crates attempting to use that flag would actually fail to
compile,
since `impl AsExpression<Nullable<Type>, DB> for NotLocal` is a
coherence violation.
This derive does not work for types which need to be generic on the SQL
type, so `Option`, arrays, and ranges can't use it.
The old form was a relic of the fact that we needed to use a
`macro_rules!` macro to parse the struct at one point in the past, and
there's no way to convert a string to an ident in non-procedural macros.
The parens form is inconsistent with the rest of Diesel, such as
`#[table_name = "foo"]` and `#[sql_type = "Integer"]`.
The only attribute which still uses the parens form is `#[primary_key]`,
since it needs to be able to take multiple values.
This is part of an ongoing effort to remove all macros with the word
`impl` in the name, and replace them with a derive.
I was actually surprised that using our own derives in Diesel itself
didn't just work. Unfortunately, since we can't access `$crate` in
`diesel_derives`, we did a hack where we wrap the whole thing in a dummy
const and do `extern crate diesel;` inside the block. You cannot do
`extern crate diesel` for code inside of Diesel. Luckily, it seems that
you can create new modules inside of const blocks as well, so I've
exported a macro that does `pub use $crate::*;` in Diesel and stuck that
in a module called `diesel`. This seems to work both inside and outside
of Diesel.
I've opted to exclude the `noop: ` form of the macro from the derive.
The number of types which need this is quite small, and are likely to
only be internal to Diesel. The actual impl you have to write in that
case is trivial, and I don't think it's worth adding machinery to the
derive to handle it.
Happy holidays!
This release contains no major code changes. There are a handful of
minor bug fixes (the most notable being that SQLite no longer panics
when we receive `SQLITE_BUSY`), but most changes are related to ensuring
that our API documentation renders better.
We do not expect any further changes to the codebase of any kind (other
than the version number) between this release and 1.0.0. Assuming no
critical issues are found with this release candidate, the code as it
exists at this point will be released as 1.0.0 on 2017-12-30.
When using this function in a guide, I noticed that using lifetimes
other than `'static` failed. This is because in our `QueryId` impl, we
reference `BoxableExpression` which is sugar in Rust for
`BoxableExpression + 'static`.
We don't need a static lifetime here, since boxed trait objects have no
query id, and thus don't need to satisfy the bounds of `Any`.
I noticed while writing the insert guide that if something inside of
`test_transaction` returns an error, the panic just says "Transaction
did not succeed" but doesn't say why.
I don't want to deal with fixing this right now, but ultimately to do so
we will need either `Display`, `Debug`, or `Error` as a bound, which is
a semver breaking change.
I've opted to use `Debug` as the bound so that we can switch to use
`Result::expect` later on.
This release contains 2 major changes from 0.99.0. The first is not
news, we have removed all deprecated code from the codebase. However,
this release also contains some major restructuring of the `query_dsl`
module.
Traits related to the construction of queries, such as `SelectDsl`,
`FilterDsl`, etc. Have been merged into a single `QueryDsl` trait.
Traits related to the execution of queries, such as `ExecuteDsl` and
`LoadDsl` have been merged into a single `RunQueryDsl` trait. The
individual method traits still exist under the `query_dsl::methods`
module, but they are no longer exported from prelude.
Though we promised there would be no significant changes other than
documentation, during our process of documenting this module, it became
clear that making this change would make discovering how to use Diesel's
query builder dramatically easier. It also gives us a much more
centralized place to document these logically grouped methods. While we
do not expect this change to break many apps, it is significant enough
to warrant an early release.
Most applications should not need to care about this change. Code which
is just doing `use diesel::prelude::*` and calling these methods will
continue to work with no changes (though error messages will be
improved if you make a mistake).
However, if you had code that was implementing `QueryFragment` or
`Query`, and expected to be able to call `.execute`, `.load`, or similar
on it (such as [the `Pagination` helper in
crates.io](82ac341240/src/pagination.rs)),
you will need to add `impl<Conn> RunQueryDsl<Conn> for YourType`.
If you have code that is calling query builder methods generically (e.g.
if you have `where T: FilterDsl<Something>`, you will likely need to
explicitly import things from `query_dsl::methods`
In addition to those changes, there are some minor improvements to
`#[derive(QueryableByName)]` which we had planned on releasing as
0.99.2.
Stability
---------
With this release, 0.99.x will only receive bug fixes and security
patches. No new features will be backported to that branch. However,
0.99 can be considered our first "LTS" release. While we have not yet
determined what exactly that means for Diesel, you can be assured that
release line will continue to be supported for as long as there is
demand.
We do not plan on having a 1.0.0.beta2, but there may be additional
minor breaking changes in that release if it is needed. If there are any
code changes between now and 1.0.0, even non-breaking ones, we will have
a release candidate before the final release.
Looking Ahead
-------------
As with 0.99.0, we expect that the only significant change between this
release and 1.0.0 will be documentation. We expect that the final
release of 1.0.0 will be before the end of the year.
Our only blocker for a final 1.0 release continues to be documentation.
There is a lot of work to do before the end of the year. We need help
from the community to reach our goal of releasing this year. If you're
interested in helping out, join [the impl period working group
channel](https://gitter.im/rust-impl-period/WG-libs-diesel).
This applies the same strategy as #1343 to `ExecuteDsl`, `LoadDsl`, and
`FirstDsl`. Ultimately I didn't think that `LoadDsl` and `FirstDsl` were
pulling their weight enough to continue to exist.
This will dramatically improve our error messages in some cases, since
we should never see `no method named "first" for <INSERT PAGE LONG TYPE
HERE OMG THIS IS PROOF DIESEL IS THE MOST COMPLEX THING EVER RUN FOR
YOUR LIFE>` again. Users should see the actual issue that caused
the query to be invalid. Many of those errors still need to be improved,
but it's a step in the right direction. This ends up killing the UFCS
trick.
There was one unfortunate side effect, which is that I had to convert an
impl which previously applied to all backends which support the
returning keyword to one that is PG specific. This will go away with
either specialization (maybe) or disjointness on associated types.
I've opted to change `ExecuteDsl` to not take a `self` parameter here,
as it seemed like most code using it with a where clause was also
imporitng `RunQueryDsl`.
This also forces an explicit impl of `RunQueryDsl` on types which we
want to be able to execute as a full query. Previously `Query` did this
for cases where we were using `get_result`, but it's actually possible
to do `id.eq(1).execute(&conn)` before this commit (which would of
course error).
This moves most traits that represent a single method into a new
`QueryBuilder` trait. While I said I didn't want to do any more big
changes until post-1.0, this change is primarily motivated by making
our documentation easier to browse. This change will need a 0.99.2
release.
In addition to making our docs easier to read, this may improve our
error messages slightly in a few places that required using UFCS to get
a decent error message. `SelectStatement`, `BoxedSelectStatement`, and
`Table` now unconditionally implement this trait, so the method will
always be present and error messages will be about why the where clause
failed.
That said, those cases will be pretty small. Most places where you end
up doing the UFCS trick are related to `.execute` and `.load`. I think
it would make sense to do a similar change there (maybe we call it
`RunQueryDsl`?)
There were two traits which did not make sense to keep around --
`CountDsl` and `JoinDsl`. There's perhaps an argument for keeping
`CountDsl` separate, as you could have relied on it from generic code.
However, any code that was using `JoinDsl` already would have needed the
where clauses required to use it from `QueryDsl`.
I've opted to add an inherent method for `filter` back onto update and
delete statements, rather than implementing `QueryDsl` for them.
`filter` is the only method that would ever work on those types, and
having it be an inherent method makes the docs for those methods more
visible.
I've opted to leave the `impl FilterDsl` in place though, because having
some generic code which adds a where clause to both select statements
and update statements is totally a reasonable thing to do 🙃.
crates.io still has 4 manual `QueryableByName` implementaitons. Of
those, half are because the struct is just "some other struct plus some
extra fields". I've opted to make the flag `#[diesel(embed)]` instead of
just `#[embed]`, as the name is generic enough that I'm concerned about
conflicts with other libraries.
This release only affects Diesel CLI. Applications do not need to
update.
Diesel CLI 0.99.0 mistakenly included an unbounded version constraint on
`clap`, which will cause it to stop compiling in the future. That
version has been yanked.
crates.io required 5 manual `QueryableByName` implementations. Of those
5, 4 of them were only required because they were for use with a struct
that didn't map to fields on a single table. This change allows use with
those structs by requiring that the SQL type be specified on each field
instead.
Since the default behavior is based on the table name, and forgetting to
annotate the fields is an easy mistake to make, I've changed
`QueryableByName` to no longer use the inferred table name. Instead the
annotation will be required to determine the SQL type based on the
column.
This release is by far the largest Diesel has ever had. It serves 2
purposes. You can consider this release to be a beta for 1.0. However,
1.0 will have an important significant difference. Anything that is
deprecated as of this release will not be present in the 1.0 release.
This includes functions which were newly deprecated in 0.99. We know
this may introduce a migration burden for some people, so we will
continue to support the 0.99 line with bug fixes as long as there is
demand and it is reasonable to do so.
Headline Features
----
This release is mainly focused on ergonomics. Our main new feature is
the [`sql_query`][] function. This is a new API which behaves similarly to
[`sql`][], but it is entirely focused on cases where you want to write
the *entire* query yourself. The main difference from `sql` is that you
do not need to specify the return type of the query, and values are
fetched by name rather than by index. This feature is still early, and
there's a lot of features still to come (specifically evolving
`#[derive(QueryableByName)]`, but we think this feature will ease a lot
of pains for cases where Diesel doesn't quite do what you need.
[`sql_query`]: http://docs.diesel.rs/diesel/fn.sql_query.html
[`sql`]: http://docs.diesel.rs/diesel/sql/fn.sql.html
Additionally, you can now use tuples for inserts the same as you can for
updates. If you've ever wanted to insert a row with just 1 or 2 values,
and been annoyed that you needed a struct that you're only using in this
one place, this feature will make you happy. We'll have new guides
highlighting this feature soon.
Additionally, this release comes with a ton of quality of life features.
Many of these changes are focused around making it easier to introduce
line breaks naturally in your code. For example, `.filter` is now
implemented on `UpdateStatement`, meaning you can write
`update(foo).filter(bar)` instead of `update(foo.filter(bar))`. We've
also introduced new APIs for `insert` and PG upsert which will have
similar readability improvements.
Breaking Changes
----
This release includes more deprecations than any release prior. In
particular, `insert` has been deprecated, along with our entire PG
upsert API. All deprecations in this release have direct replacements,
which will lead to code which formats much more nicely. It should be a
mostly mechanical replacement for most apps. See [the CHANGELOG file][] for
details.
[the CHANGELOG file]: https://github.com/diesel-rs/diesel/blob/v0.99.0/CHANGELOG.md
Growing the Team
----
With this release, we'd like to welcome several new members to the
Diesel committer team. @weiznich, @notryanb, and @katrinabrock you've
all done excellent work and we're very excited to officially welcome you
to the team!
Additional Thanks
----
In addition to the Diesel core and committer teams, 10 people
contributed to this release. A huge thank you to:
- Adam Perry
- Alex Kitchens
- Alexey Zabelin
- Arnar Mar Sig
- Bob
- Jordan
- Lauri Apple
- Maxime “pep” Buquet
- William Murphy
- bippityboppity
Our only remaining blockers from this release and 1.0 are documentation
changes, and having this tested in the wild. Thank you to every one of
our users for your support, and we look forward to Diesel 1.0 by the end
of the year!
This entry was very long, and didn't make it clear what action was
required by our users. I've shortened it to the 4 things that actually
affect users of Diesel. (This was an awesome PR, but the internal
changes will be seen by contributors without being listed in the user
facing changelog)
I want to be able to write `.between(now, now - 90.days())`. Having a
range requires that the lower and upper bound be the same type in Rust,
rather than requiring that they be the same type in SQL.
`sql` has always been a bit clunky to use if you wanted to write a whole
query with it. You have to specify the SQL type of the query, which also
means you have to list every column out explicitly to ensure they're in
the expected order.
This adds a replacement API that more geared towards writing complete
queries. There are two notable differences. The first is that the SQL
type of each field is specified during deserialization, not when the
query is constructed. The types are never checked anyway (other than to
make sure the deserialization is valid), so it makes sense to defer this
to a place where we can derive it.
The second difference is that columns are deserialized by name, not by
index. This has all of the gotchas that are associated with doing that
with other libraries (name conflicts between tables, etc)
I had originally planned on having `NamedRow::get` optionally also take
a table name. However, PG gives you the OID not the name, so we'd need
to do another query to get the table name. SQLite only gives you the
table/column name if compiled with a flag to enable it, which the system
sqlite3 on mac does not.
For those two reasons, I've opted to use the column name alone. This
means that the derived `QueryableByName` is unlikely to be usable with
joins, but that's a price we'll have to pay for now.
I'd like to expand the number of cases that our derive impl can handle
(e.g. allow providing a sql type in addition to a column name), but this
is a good bare minimum place to start.
Fixes#650.
The previous implementation would only handle the specific output format
of the `datetime` function. However, it is incorrect for us to assume
that we would get that specific function, as times may not have been
created by that function (which is why the range of input it accepts is
wider than the output it can give).
While values that were stored by using Diesel with chrono will be in the
expected format, we need to work with databases that have data from
other sources. The value in the column will just be whatever string was
given.
This implementation is updated to take every value that is defined as
valid input to the `strftime` function in SQLite, with the exception of
`'now'`. I've updated the tests to exercise all possible values. I've
also changed/removed tests which were testing for values that SQLite
does not handle. It documents its range as being from midnight of Jan 1
0000 to Dec 31 9999 23:59:59.999999. I explicitly opted not to test the
behavior of out of range values, as SQLite defines it as undefined.
This macro is basically a workaround for a lack of certain language
features. It's confusing, and unclear to users when they do or do not
need to invoke it. There's no downside to just speculatively adding it
for all tables, so let's do that.
However, for simplicity, I've opted to also remove the code that makes
`JoinTo` imply this. This will actually improve the error messages
(users won't see an error about a missing `JoinTo` implementation when
trying to use a table as a subselect), and makes it more clear when this
macro needs to be invoked, *especially* after we rename it to
`allow_tables_to_appear_in_same_query!`
I've checked the compile times both on crates.io and our own test suite
with this change, and didn't see any noticeable change.
Fixes#1237.
Fixes#1129.
The only time that a double reference `AsExpression` impl comes up is
from the derived impl of `Insertable` and `AsChangeset`. We can't vary
the generated code based on whether the type of a field is `Copy`, so we
have to assume that it isn't and always take a reference.
Previously we only did this for `str` and slices, as `String` and `Vec`
are the only non-copy types that we support (I think `BigDecimal` may
fall into that category now, but it's unlikely that avoiding a single
clone of that type is ever relevant).
Still, there's no reason that we shouldn't allow references of any type
to appear in `Insertable` structs. To avoid code bloat, I've cleaned
things up a bit and implemented more stuff on `str` and `[T]` directly,
letting the blanket reference impl apply to those types when it's
relevant.
Fixes#1242.
The most difficult part here is getting `Concat` to have its return type
be based on the type of its arguments. Since there's no easy way for me
to carry any possible `ty` value as a series of `tt` without accepting a
subset of possible `ty` values, I've opted only to handle the magic
`ReturnBasedOnArgs` value in the one place we need it.
Fixes#975
Since `Citext` is just text internally, I had hoped that this would be
all we needed. Unfortunately, doing `citext_column.eq("foo")` would do a
case sensitive comparison, as `"foo"` would not be coerced to `citext`.
This change is in the same spirit as #1166. By allowing the method to be
chained as part of the query, instead of on the argument to a function,
it becomes much easier to introduce line breaks naturally.
Why isn't this `impl FilterDsl`?
--------------------------------
Today `FilterDsl` is structured in such a way that it assumes that it's
only implemented on valid complete queries, and that it will return a
valid complete query (partially to ensure that the call to `filter`
can't change the SQL type). Since these structs are only complete
queries when they have a returning clause (and
`IncompleteUpdateStatement` is never a complete query), we would have to
loosen those bounds.
We may want to make that change eventually, but for now I opted to
implement these as inherent methods.
Why not add `find` as well?
---------------------------
We could. To me, `update(users).set(...).find(1)` just feels off. Given
that `find` is typically much shorter, I've opted to exclude it for now.