Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[8.x] Add computed column support (storedAs, virtualAs) to SQLite #33618

Merged
merged 3 commits into from
Jul 24, 2020
Merged

[8.x] Add computed column support (storedAs, virtualAs) to SQLite #33618

merged 3 commits into from
Jul 24, 2020

Conversation

iamgergo
Copy link
Contributor

@iamgergo iamgergo commented Jul 22, 2020

This PR adds the ability to use computed columns – storedAs and virtualAs – in SQLite.

Since version 3.31.0, which released on 2020-01-22, SQLite supports computed columns.


Supporting features like useful JSON functions or computed columns can help developers to build or test concepts or ideas. Of course, in production SQLite is not the best choice. But for quickly testing an idea or a concept it can be a nice tool, especially because it's fast and no configuration – or very little – is needed.

The Blueprint syntax is the same as in case of MySQL, however, due to its limitations, some modification is required:

  • "Generated columns may not have a default value...": when using the default() method on the column definition, in case if it's a computed column, the default clause will be omitted from the SQL.
  • "It is not possible to ALTER TABLE ADD COLUMN a STORED column...": the alter table add column clause that contains the as (...) stored string will be omitted from the SQL.

The syntax is the same as for MySQL:

Schema::create('products', function (Blueprint $table) {
    $table->id();
    $table->string('name');
    $table->integer('price');
    $table->integer('tax')->virtualAs('"price" * 0.27')->nullable();
    $table->integer('discount')->storedAs('"price" - 100')->nullable();
});

This feature requires SQLite 3.31.0 or higher. According to the documentation, Laravel supports SQLite 3.8.8 – which released on 2015-01-16, more than 5 years ago – or higher. As I mentioned, we already support various JSON functionality for SQLite, which requires at least 3.9.0. So the documentation is incorrect about the required version currently.

Since probably no one uses SQLite in production and using homebrew it can be updated easily on a local machine, it might worth bumping the minimum supported version of SQLite for Laravel 8.x, especially if we could gain features like computed columns.

If this PR gets merged, I'll create a PR for the documentation to update the minimum required version (and the migration guide as well?).

@sisve
Copy link
Contributor

sisve commented Jul 23, 2020

What happens if we're using an older sqlite version? Can we detect that, and throw an exception with a descriptive error message?

"It is not possible to ALTER TABLE ADD COLUMN a STORED column...": the alter table add column clause that contains the as (...) stored string will be omitted from the SQL.

Does this mean that we are silently dropping sql clauses that the user expects to be executed? Could we throw an exception with a descriptive error message instead?

As I mentioned, we already support various JSON functionality for SQLite, which requires at least 3.9.0. So the documentation is incorrect about the required version currently.

This doesn't mean that we require a newer version, just that the user gets query-related exceptions if they try to use the related json functionality. I would have liked some descriptive error messages instead... do you see the pattern here? ;)

I think that adding error messages that clearly state that something is unsupported, preferably something that mentions the current and required sqlite version, would be a step in the right direction. We could also document which sqlite versions are required for some functionality, but I don't think we need to raise the minimum supported version.

@iamgergo
Copy link
Contributor Author

From my aspect, if there is a minimum version of a tool that the framework requires, it indicates, the framework is working well with that version and all the functionality should work as it was documented without errors.

If the minimum required version of SQLite is 3.8.8, but we clearly know that it requires 3.9.0 to work with the documented features, I don't see why would it be a better solution to throw an exception instead of bumping the version and make things work.

On the other hand, 3.8.8 was released more than 5 years ago, 3.31.0 more than 6 months ago, and probably when L8 will be released it will be 7-8 months, so we can't really say it's a fresh version (since then 3.32.0 released).

I understand your point and maybe in case of MySQL or Postgres there should be more indication if a feature does not compatible with the current version, but SQLite is clearly a development tool and to keep things cleaner, I think it's easier to bump the version than just watching if the feature is backward compatible or not.

@nCrazed
Copy link
Contributor

nCrazed commented Jul 23, 2020

but SQLite is clearly a development tool

https://www.sqlite.org/famous.html

@iamgergo
Copy link
Contributor Author

I mean, in the Laravel community probably the number of developers who use it in a local environment or for testing is probably bigger than, who use it in production. On other platforms, the situation is different I guess.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants