Managing postgresql views without having to write migrations? - postgresql

The problems with SQL views is that every time I need to make a small change I need to create another migration. Being in a small startup, that's quite a hindrance to have to change something small to change the view.
Is it advisable to do the following
Drop and recreate view everytime I deploy my app;
This way, when I change something in the view, it will get updated in the database as soon as I deploy my app.

What you are describing is just another type of migration that get reversed on deploy. This may make sense for your business needs, and if you get blocked by this technique, you can always fall back to the regular migration system.
The best way to implement such a system in PostgreSQL is to create a schema that you drop on deploy. This way you don't have to create all the DROP VIEW ... commands, just DROP SCHEMA and everything in there will be deleted. Then you can run you procedure to rebuild it.
Example deploy script to execute on deploy:
/* Drop and rebuild the schema */
DROP SCHEMA IF EXISTS view_schema;
CREATE VIEW view_schema.my_users AS (SELECT * FROM users);
CREATE VIEW view_schema.my_products AS (SELECT * FROM products);
....

Related

How to detect if tableview was changed

I have following idea: user can edit database and when he will press exit from database he will be asked if he want to save edited database or if he edited something and then turned it back he wont be asked.
I think i should compare created database and database after editing when user press exit, but don't know how.
This is my code for creating database
model = new QSqlRelationalTableModel(this, *db);
model->setTable("cv");
model->setFilter("cv_id = "+currentCV+"");
model->removeColumns(0,1);
model->select();
ui->tableView->show();
ui->tableView->setModel(model);
You have 2 options.
Create event triggers in the database. Event triggers work when users change database table structures or create tables or change columns. Thus, these triggers work when the user executes any DDL commands. (change table, add column, create index, drop table, etc.) You can insert these commands into your log tables using event triggers.
Your database structures (all tables, columns, indexes, etc.) are stored in information_shema. You can select the data of these tables and save it somewhere and then compare it with the data that has changed.
Take in mind that no change to database is performed before you're submitting the user changes. By default, sumbit is performed when changes occur, and this does not help you. But, you can set
model.setEditStrategy(QSqlTableModel.EditStrategy.OnManualSubmit)
At this point, changes are persisted only when the method model.submitAll() is called.
All you have to do, at this point, is exploiting dataChanged signal of your model and use a flag variable to check if changes have been operated:
data_changed = False
def on_data_changed()
data_changed = True
model.dataChanged.connect(on_data_changed)
Now you can adjust the logic of the code to serve your specific purpose

Does CitusDB support `CREATE VIEW`?

Assume we have a distributed CitusDB table named customer_reviews, and we try to create a view on it:
CREATE VIEW book_reviews AS
(SELECT * FROM customer_reviews WHERE product_group = 'Book');
This appears to work. But if we run:
SELECT COUNT(1) FROM book_reviews;
CitusDB gives the following error:
ERROR: cannot plan queries that include both regular and partitioned relations
Two questions:
Is there a way to work around this by manually creating the view on all worker nodes?
Is there a way to make CREATE VIEW and DROP VIEW work correctly on the master node, for apps which create and destroy views automatically at runtime?
UPDATE: View support is added to Citus with this PR.
First of all, I created an issue to track this. Please feel free to add your comments and feedback on that issue.
Until we implement this feature, I see two workarounds;
Using a UDF or a PL/pgSQL function to wrap the view query instead of creating the view. I added specific examples to the GitHub issue
Create some UDFs and PL/pgSQL functions to propagate views down to the shards on worker nodes and manipulate metadata to simulate views on the master node. I also added a prototype approach to the GitHub issue
I think what is best for you depends on your CREATE VIEW queries and your application stack. Could you explain your use-case and how do you plan to use views a bit more?

flyway Working with existing Db

I'm start to use flyway in my project, i configure to apply new changes on my db, but i want to know if can i use 2 parans init-method="init, migrate" because every time i want to start on a new computer i need to restore some db backup from pgadim change the ini-method to init, so he will create the table to control the updates. so then i need to change my init-method to migrate to apply future changes.
i want to know if have an better way to do this.
sorry my english.
Flyway 2.1 will come with an initOnMigrate setting that does exactly what you need. Until then, you can always wrap the Flyway class with one containing the logic you need.

Managing database changes

I'm starting to move more logic into the database, using triggers, views, functions, CTEs, etc. When plv8/json comes out for postgres, I can see myself putting lots of logic in there.
I'm having problems with the "standard" way of doing database migrations in sequel and activerecord. Both sequel and activerecord let you put arbitrary sql code into timestamped files. When each file is ran, a schema_versions table is updated with the filename (or timestamp in the filename), which keeps record of which migrations have been applied to the current database.
If a lot of coding is being done at the database level, that means that modifications to existing views, functions, etc follow the below pattern:
Migration 1 defines a function and a view that uses that function.
-- Migration 1
create function calculate(x int) returns int as $$
return x + 1;
$$ language sql;
create view foos as (
select something, calculate(something) from a_table
);
Requirements change, and I need to change a function type. In Migration 2 I have to drop all objects that depend on foo, and recreate them by copying their entire body -- even if there weren't any changes in most of the other code!
-- Migration 2
-- Have to drop all views and functions that depend on the
-- `calculate(int)` function.
drop view foos;
create or replace calculate(x bigint) returns bigint as $$
return x + 1;
$$ language sql;
-- I could do `drop function calculate(int) cascade`,
-- but I might accidentally drop some objects that wouldn't get recreated below.
-- Now I have to recreate foo.
create view foos as (
select something, calculate(something) from a_table
);
If I'm building a system based on views and functions and triggers, my migrations would be filled with duplicated code, and it's difficult to find the latest version of the code. You might say "don't do that!", but for my purposes (e-commerce, shipping, transactions), I'm finding it's a lot easier and faster to have the database ensure the integrity of the data by doing the logic inside the database.
You can (of course) dump the current database schema (which includes all the code definitions), but I think you lose comments. And you wouldn't generally want to edit a giant file that contains the whole schema.
Any ideas on how to solve this problem?
My best idea is to how the sql code contained in their own canonical files (app/sql/orders/shipping.sql, app/sql/orders/creation.sql, etc). Everyone develops directly on these. Whenever it's time for a release, then you'd want to make a new migration file, look at all the changed code since the previous release, figure out the dependency chain of the database objects that need to be dropped and recreated, and then copy the sql from the canonical sql files into a new sequel/activerecord migration file. But it's a pain. :/
Thoughts are very welcome. I hope I explained this well enough, I'm cutting back on my caffeine intake and I'm a little groggy atm.
Oh, I asked a similar question on Stack Overflow: Changing the type of a column used in other views The answer was a function that let me pass in:
sql code to run
database views to drop and recreate
The function would retrieve the view definition, drop the views, run the sql code, then recreate the view definition (in reverse order of dropping). Perhaps a system of functions like this would help solve the problem of having to copy/paste sql code into the migration files.
I'd recommend liquibase.
You create files which track the changes to your database and these will be run into the database in the correct migration order.
You might find Dave Wheeler's blog-posts interesting starting from here:
http://justatheory.com/computers/databases/simple-sql-change-management.html
My rate of database change is fairly small but I tend to be careless and make small changes to the schema directly, so I've had to come up with a fair bit of infrastructure to catch when I've done so. The basic elements are:
A makefile that can rebuild a development database from scratch
A set of schema-files separated into "modules" (lookups_schema.sql, lookup_data.sql)
A set of update files that transition from one revision to the next
I don't usually have the corresponding downgrade scripts, some people do
A script to populate my database with a plausible amount of test data
Crucially, a test suite via pgTAP that checks my various functions, views and also the upgrade scripts. The upgrade tests can be run against a live database too.
If you have a separate instance of PostgreSQL set up with fsync turned off / on ramdisk etc then rebuilding the whole DB and populating it can take seconds (if you don't have too much test data).
Start with #1, #2, then add #6 (pgTAP is very cool), then the rest. The crucial thing is a test suite that checks your in-database code.
There are tools that try to automate schema changes for you, but they are really only good at adding a new column to a table and that sort of thing. Once you have code in your db then they're not much help.

iOS - Create Database Schema (Run code only once)

I'm using FMDB for my iPhone App database and i want to create the database and tables schema only once.
How can i run OBJC code when the user installs or updates the app?
Kinds Regards
You can set a boolean value in NSUserDefaults - NSUserDefaults is only reset when the user deletes the app, so you have some code that executes if a particular boolean value is not found in the user defaults (and then saves that value after execution to prevent it from being run again).
That will cover your plain 'run code once upon install' scenario - you can achieve the same for updates with a similar approach, but utilising the CFBundleVersion variable (which will be different for each version of your app).
First of all, you might not want to think about executing something during upgrading, because it's not possible. Like #lxt suggested, you can store a value in the preference to indicate database version, but it might not be bulletproof.
A common approach to solve this problem is to use self-built meta-data. When you first created the database, you should create an extra table named "metadata" or "properties", with two varchar columns, "name" and "value". You insert one row, ("database_ver", "1").
In your database layer (or adapter) class, you create an "open" method to handle opening. Within this method, you first run select database_ver from metadata; to check database version. If nothing is fetched, you run table creation scripts, and insert database_ver=1 row.
Later on if you upgraded your table format, provide alter table statements for each version, and run them based on database_ver. For installations after the upgrade, you can use the updated create table statements, then set "database_ver" to "2" (or above) directly, without going through alter table.
Compared to storing value in the preference, it's actually more common to store it in the database itself. Because even if the user backed up the file somewhere, or skipped a version, you can still tell the format of the database by its metadata table.
FMDB has no problem running such mechanism.