Commit Graph

151 Commits

Author SHA1 Message Date
Martin Kleusberg
02db68107a Refactor the way we store a database schema
This commit does a lot of refactoring. But most noticeably it changes
two things:

1) Instead of saving all objects (tables, views, indices, triggers) of a
   schema in a common map, we now store tables/views, indices and
   triggers in three separate maps. This has a number of benefits:
   - It resembles more closely how SQLite stores its data internally and
     therefore achieves greater compatability e.g. for databases with a
     view and a trigger with the same name.
   - It reduces the need for runtime polymorphism. This makes the code
     run a bit faster.
   - By working with explicit types more often more error checking can
     be done at compile time, making the code less error prone.
   - The code becomes a lot clearer to read.

2) By making View inherit form Table, views are now a sort of tables.
   This has the following benefits:
   - This is a again how SQLite stores views internally which again
     should increase compatibility a bit.
   - We mostly treat views and tables the same anyway and with these
     changes we can unify the code for them even more.
2021-01-30 20:47:31 +01:00
Martin Kleusberg
e54664dd03 Change some function parameters with negated name
Change some function parameters which are named like "dont..." to make a
positive statement. This should hopefully avoid some confisions with
double negation.
2021-01-24 10:20:50 +01:00
mgrojo
c8cd858699 Add "Save Database As..." action
The feature is implemented using the SQLite backup API.

https://sqlite.org/backup.html

This allows saving in-memory databases and saving database files to another
file name.
2021-01-22 23:54:26 +01:00
freddii
e8405b78d7 fixed wrong spelled words 2021-01-14 12:44:44 +01:00
Martin Kleusberg
73f60a5c47 Simplify code 2020-08-24 10:57:08 +02:00
horst-p-w-neubauer
29635e9e80 detach additional database connection
See issue #2239
2020-08-22 15:02:29 +02:00
Martin Kleusberg
ba1270cedb Clean up the code and make some more minor optimisations
This also includes replacing some more Qt containers by their STL
counterparts.
2019-11-06 20:25:18 +01:00
Martin Kleusberg
4e8eff7af0 Some more minor performance improvements in often called functions 2019-10-07 18:23:43 +02:00
mgrojo
4081debd71 Attach Database didn't escape filepath of selected file
See issue #2002
2019-09-22 21:22:34 +02:00
Martin Kleusberg
ed4c252dbb Add comment to avoid future problems 2019-08-18 14:22:35 +02:00
Martin Kleusberg
74e0df376a When updating a field try to respect the affinity data type if possible
When modifying the value of a field in the Browse Data tab, we used to
always hand over the new value to SQLite as text. This works most of the
time but can cause problems e.g. when a CHECK constraint checks the data
type of the value and expects something other than text. It is also a
pretty lazy approach in general.

This commit checks if the new value matches the affinity data type of
the column, and if it does hands over the new value as the correct data
type.

See issue #1952.
2019-08-01 13:30:01 +02:00
Martin Kleusberg
b17755c46a Only register error log callback once at start of application
Instead of registering the error log callback function every time a
database file is opened, we now register it only once when the
application is first started. This way we can avoid calling
sqlite_shutdown which can have unintended side effects.

See issue #1932.
2019-07-05 22:13:46 +02:00
Martin Kleusberg
64a596a887 Use even less Qt containers 2019-05-06 18:50:05 +02:00
Martin Kleusberg
5e90d90ac6 Replace all typedefs by usings
This is just a matter of code style, no functional change whatsoever.
2019-05-03 15:06:48 +02:00
Martin Kleusberg
189652d350 Remove some unnecessary includes 2019-04-29 20:54:26 +02:00
Martin Kleusberg
15c23bb0d3 Use some more SQL containers instead of their Qt equivalents 2019-04-29 18:11:19 +02:00
Martin Kleusberg
f59a2453a2 Fix some warning and other code style changes 2019-04-26 14:48:24 +02:00
Martin Kleusberg
a615c7b5a0 Initial support for multiple primary key columns in WITHOUT ROWID tables
This add initial and mostly untested support for WITHOUT ROWID tables
with multiple primary key columns. It should now be possible to update
and to delete records in these tables.

This commit also improves the overall handling of multiple primary key
columns in preparation for better support of them in general.

Note that this makes us depend on an SQLite version with a built-in JSON
extension.

See issues #516, #1075, and #1834.
2019-04-01 21:43:00 +02:00
Martin Kleusberg
282387ced7 Add new logging section for SQLite's error log
Add a new logging section to the SQL log panel called "Error Log".
Register a callback to receive errors and warnings from SQLite and add
them to the new error log section.

See issue #1754.
2019-02-21 14:19:47 +01:00
Manuel
3b455afccf Allow custom display formats (#1720)
Allow user to define their own display formats. The SQL code is editable
and the combo box changes automatically to custom if the user edits one
of the predefined formats.

The display format (either custom or predefined) is validated with a 
case-insensitive regex so at least it contains a function applied to the column
name. 

Added a new callback for executeSQL following the model of sqlite3_exec.
Using this, the number of columns is got from a checking query execution. If
it is not one, the custom display format is also rejected.

Note that these validations might still be fooled in some unforeseen way, but
the users should know what they're doing.

See issue #573
2019-02-15 20:10:52 +01:00
Martin Kleusberg
d783d36dbd Further performance improvements in the SQL import
This eliminates some unneeded conversions in the SQL import code which
should speed up the import and reduce its memory consumption.

See issue #1045.
2019-02-14 18:01:20 +01:00
Martin Kleusberg
13a8a1f282 Speed up the SQL import a bit
This commit attempts to speed up the SQL import a bit by removing
unnecessary conversions and counting of characters. It's still far from
perfect though.

See issue #1045.
2019-02-14 13:45:18 +01:00
Martin Kleusberg
1f9101ae2a Move SQL execution in Execute SQL tab into a separate thread 2018-12-05 18:37:52 +01:00
Martin Kleusberg
9e36f21112 Allow any number of changes to the table schema in one alterTable call
In the Edit Table dialog we used to call our alterTable function (which
works around SQLite's missing full ALTER TABLE support by - besided
other things - copying all the data of the table) for pretty much every
change immediately. This was taking a lot of time for larger tables.

Our alterTable function allowed any number of changes if they affect
only one field of the table at once. So we could have reduced the number
of calls a lot by just using that capability. Instead however, this
commit improves the alterTable function to make possible transforming a
table completely in just one call. It does so by taking the new table
schema and using that without further modification. It also takes a new
parameter to keep track of what column in the old table becomes what
column in the new table, so the data can be preserved.

This commit obviously also changes the Edit Table dialog to make proper
use of the new features. This means that whatever changes you make to a
table, you will only have to wait once until for the alterTable call,
and that's when clicking the OK button.

See issue #1444.
2018-11-16 10:59:20 +01:00
mgrojo
f262bf6b18 Prepare for different options when the DB is in use
waitForDbRelease receives a parameter for waiting, cancelling the other
operation or asking the user; defaulting to ask.

The wait option is used for the conditional formatting, so it doesn't
interfere with the loading. This avoid opening a dialog when scrolling
the table over a still not fetched area with conditional formats.
And it is done independently of the threading model supported by SQLite.
2018-11-15 14:45:43 +01:00
Martin Kleusberg
11ace1efa6 Show current database action in status bar and add cancel button
This adds a label to the status bar which becomes visible whenever the
database is busy. It also specifies the currently running action. Also
add a button which allows you to cancel this action at the next
opportunity.

Note that this doesn't work for the Execute SQL tab yet which requires
some more rewriting of the code there.
2018-11-08 16:52:38 +01:00
Martin Kleusberg
35a5b43ce0 Move SQL object classes into a separate directory 2018-11-08 16:20:33 +01:00
Martin Kleusberg
064ce6f8fe Simplify code
Merge two very similar functions into one while keeping the best parts
of both.
2018-10-30 21:38:57 +01:00
Manuel
abb6f686a3 Initial implementation of "conditional formatting" (#1503)
After setting a filter, the user can select from the context menu in the
filter line a new option "Use for Conditional Format", that assigns
automatically a colour to the background of cells fulfilling that
condition.

The formatting is preserved after the user has removed the filter. Several
conditional formats can be successively added to a column using different
filters.

The conditional formats of a column can be cleared when the filter is empty
selecting "Clear All Conditional Formats" from the filter line context
menu.

The conditional formats are saved and loaded in project files as other
browse table settings.

A new class Palette has been added for reusing the automatic colour
assignment of the Plot Dock. It takes into account the theme kind of the
application (dark, light) for the colour selection.

A new class CondFormat for using the conditional formatting settings from
several classes. The conversion of a filter string from our format to an
SQL condition has been moved here for reuse in filters and conditional
formatting.

Whether the conditional format applies is resolved by SQLite, so filters
and conditional formats give the same exact results.

Code for getting a pragma value has been reused for getting the condition
result, and consequently renamed to selectSingleCell.

Possible future improvement:
- New dialog for editing the conditional formatting (at least colour and
application order of conditions, but maybe too: adding new conditions and
editing the condition itself).
2018-10-30 21:22:14 +01:00
Martin Kleusberg
5ec03baef4 Make use of the improved ALTER TABLE abilities from SQLite 3.25.0
SQLite 3.25.0 introduced an extended ALTER TABLE command which now
allows renaming an existing field. Before this we were emulating this
functionality in our code. There are however three reasons to switch to
the new feature from SQLite, even though it doesn't safe us any code:
1) It is faster because it does less steps
2) It is less error prone for the same reason
3) It is better at also renaming the field in triggers and views

This is somewhat improving the situation in issue #1444 but not
addressing the main problem described there.
2018-10-22 23:05:55 +02:00
Martin Kleusberg
fb1eba1391 Remove some virtuals and add some overrides
In our case this is more a question of code style.
2018-10-09 20:28:22 +02:00
mgr
071f963fcc Better messages for a table edition when foreign-key check detect problems
The message when there are problems and the user has made changes and
accepted them must be different to the case when the user has cancelled
and any possible changes have been already reverted by the dialog.

In the first case the fault may be ours and we actually revert changes.
In the second case, we know for sure the problems were there before
editing the table. We warn user about it, since we already know.

The last error from the DB is inappropriate for both cases because it
hasn't been updated by the foreign-key check.

Also fixed the typo in a function identifier.

Room for improvement: maybe the check should be done before opening the
dialog, so we don't let the user edit the table until the issues have
been solved.

See issue #1547
2018-09-29 16:22:03 +02:00
Martin Kleusberg
918248acaa Simplify code 2018-09-26 15:54:39 +02:00
Martin Kleusberg
130afb1c08 Clean up code 2018-09-06 00:08:32 +02:00
Martin Kleusberg
bf505edf66 Code refactoring
This commit refactors vast parts of the sqlitetypes.h interface. Its
main goals are: less code, easier code, a more modern interface, reduced
likelihood for strange errors and more flexibility for future
extensions.

The main reason why the sqlitetypes.h functions were working so well in
DB4S was not because they were that stable but because they were
extremely interlinked with the rest of the code. This is fine because we
do not plan to ship them as a separate library. But it makes it hard to
find the obvious spot to fix an issue or to put a new function. It can
always be done in the sqlitetypes function or in the rest of the DB4S
code because it is just not clear what the interface between the two
should look like. This is supposed to be improved by this commit. One
main thing here is to make ownership of objects a bit clearer.

In theory the new code should be faster too but that difference will be
neglectable from a user POV.

This commit also fixes a hidden bug which caused all table constraints
to be removed in the Edit Table dialog when a single field was removed
from the table.

This is all still WIP and more work is needed to be done here.
2018-09-05 22:24:46 +02:00
Martin Kleusberg
f3e6aec57d Load SQLite extensions earlier
In the Preferences dialog we allow the user to configure a list of
SQLite extensions which should be loaded whenever a new database file is
create or an existing database file is loaded. This commit changes the
order of actions after creating or opening a file so that the extensions
are loaded significantly earlier. This way they are already loaded for
most of the time during the process.

This fixes some subtle bugs. One of the more prominent ones was
triggered when there is a view which uses some function which is
defined in such an extension. After loading the file, parsing would fail
and you couldn't see the fields of the view. Browsing it would work but
trying to edit the display format crashed the application.
2018-09-04 22:06:12 +02:00
Martin Kleusberg
b28d0f63ec Show SQLite and SQLCipher version in About dialog when using SQLCipher
See issue #1474.
2018-08-10 19:17:59 +02:00
Martin Kleusberg
75e4c32bc4 Don't use the SqliteTableModel class for querying row counts in export
When exporting a database to an SQL file we need to query the row count
of each table to calculate the progress later in the actual export. This
commit replaces the SqliteTableModel class which was used for this
purpose by a simple query function. This might be slightly faster here
but more importantly avoids a progress window being shown for each table
before finally seeing the one for the actual export.

See issue #1476.
2018-08-10 14:26:00 +02:00
Iulian Onofrei
3cdc65a63f Add automatic crypted databases open via dotenvs (#1404)
* Rename confusing variables

* Fix some project warnings

* Fix code style

* Add constant for the default page size

* Move KeyFormats enum to CipherSettings

* Fix code style

* Fix memory leak

* Stop relying on CipherDialog for encryption settings management

* Fix code style

* Add .env format for QSettings

* Add automatic crypted databases open via dotenvs

This adds support for `.env` files next to the crypted databases that
are to be opened that contains the needed cipher settings.

The only required one is the plain-text password as a value for the key
with the name of the database like this:

    myCryptedDatabase.sqlite = MyPassword

This way, databases with a different extension are supported too:

    myCryptedDatabase.db = MyPassword

You can also specify a custom page size adding a different line
(anywhere in the file) like this:

    myCryptedDatabase.db_pageSize = 2048

If not specified, `1024` is used.

You can also specify the format of the specified key using the
associated integer id:

    anotherCryptedDatabase.sqlite = 0xCAFEBABE
    anotherCryptedDatabase.sqlite_keyFormat = 1

where `1` means a Raw key. If not specified, `0` is used, which means a
simple text Passphrase.

Dotenv files (`.env`) are already used on other platforms and by
different tools to manage environment variables, and it's recommended
to be ignored from version control systems, so they won't leak.

* Add new files to CMakeLists

* Move DotenvFormat include to the implementation

* Fix build error

* Remove superfluous method

(related to ac51c23)

* Remove superfluous checks

* Fix memory leaks

(introduced by 94bbb46)

* Fix code style

* Make dotenv related variable and comment clearer

* Remove duplicated code

* Remove unused forward declaration

(introduced by e5a0293)
2018-07-10 20:46:17 +02:00
Martin Kleusberg
3da520cdd1 Clean up multi threading patch, fix build and some bugs
Make strings translatable, remove some more debug code, fix tests,
reduce size of patch slightly, remove weird tooltip, don't crash when
closing database, simplify code, fix filters, don't link agains pthread
on Windows.
2018-06-08 22:46:47 +02:00
Martin Kleusberg
51dbe72e23 Multi-threading patch
This was done by Michael Krause.
https://lists.sqlitebrowser.org/pipermail/db4s-dev/2018-February/000305.html

In this commit I only fixed two compiler warnings, some whitespace
issues and removed some debug messages.
2018-06-08 22:46:47 +02:00
Martin Kleusberg
f51b44d8d7 Add support for deleting rows in views which are unlocked for editing
If a view has been unlocked for editing by specifiying a pseudo primary
key, with this commit you can now delete records from the view if an
appropriate trigger exists.

See issue #141.
2018-06-07 16:08:08 +02:00
Martin Kleusberg
b6c05609dc Change order of statements in exported SQL file
When exporting a database to an SQL file we used to export it like this:
- Table 1 schema
- Table 1 data
- Table 2 schema
- Table 2 data
With this commit that is changed like this:
- Table 1 schema
- Table 2 schema
- Table 1 data
- Table 2 data

This makes the resulting SQL file more robust for import because it
avoids any foreign key errors as long as foreign keys are deferred.
2018-05-16 18:18:56 +02:00
Martin Kleusberg
2b68afb664 Rename function
Rename the DBBrowserDB::renameColumn() function to alterTable() because
it can do a lot more than just renaming a column.
2017-11-18 11:24:05 +01:00
Martin Kleusberg
87c0476d1c Introduce helper function for generating unique temporary table names 2017-10-31 13:06:27 +01:00
Martin Kleusberg
5a14e47419 Mark some more constructors as explicit 2017-10-31 12:11:03 +01:00
Martin Kleusberg
ee32b3e4e1 Use nullptr where possible 2017-10-30 21:20:02 +01:00
Martin Kleusberg
4ae601dafd Fix default collation for UTF16 strings
Fix our default collation which we install when an unknown collation is
requested to (more or less) support UTF16 strings as well. Before this
UTF16 strings wouldn't compare correctly because they might contain null
bytes which would lead to only the first (few) byte(s) getting compared.

See issue #1172.
2017-10-19 14:54:30 +02:00
Martin Kleusberg
32da4de94d Fix collate warning after addition of multi-threaded loading
The no collate function warning is triggered in a thread which is used
for loading data. However, the warning is a message box and GUI elements
can only be drawn in the main thread. So the old code would crash. This
is fixed here by jumping to the main thread for showing the message box.
2017-10-16 21:58:30 +02:00
Martin Kleusberg
6029e25bcc Store row columns in a vector instead of a list
This should speed things marginally up.
2017-10-08 20:06:49 +02:00