diff --git a/db/migrations/20170127143149_create_users.cr b/db/migrations/20170127143149_create_users.cr index e70e5c35e..fedbeec77 100644 --- a/db/migrations/20170127143149_create_users.cr +++ b/db/migrations/20170127143149_create_users.cr @@ -1,6 +1,8 @@ class CreateUsers::V20170127143149 < Avram::Migrator::Migration::V1 def migrate create :users do + primary_key id : Int32 + add_timestamps add name : String add nickname : String? add age : Int32 diff --git a/db/migrations/20170127143150_create_admins.cr b/db/migrations/20170127143150_create_admins.cr index b88c5c7f0..718abcae7 100644 --- a/db/migrations/20170127143150_create_admins.cr +++ b/db/migrations/20170127143150_create_admins.cr @@ -1,6 +1,8 @@ class CreateAdmins::V20170127143150 < Avram::Migrator::Migration::V1 def migrate create :admins do + primary_key id : Int32 + add_timestamps add name : String end end diff --git a/db/migrations/20170127143151_create_sign_in_credentials.cr b/db/migrations/20170127143151_create_sign_in_credentials.cr index cf6f57849..6bfabaf54 100644 --- a/db/migrations/20170127143151_create_sign_in_credentials.cr +++ b/db/migrations/20170127143151_create_sign_in_credentials.cr @@ -1,6 +1,8 @@ class CreateSignInCredentials::V20170127143151 < Avram::Migrator::Migration::V1 def migrate create :sign_in_credentials do + primary_key id : Int32 + add_timestamps add user_id : Int32 end end diff --git a/db/migrations/20171006163153_create_posts_and_comments.cr b/db/migrations/20171006163153_create_posts_and_comments.cr index 078ca041c..9ef3fd0eb 100644 --- a/db/migrations/20171006163153_create_posts_and_comments.cr +++ b/db/migrations/20171006163153_create_posts_and_comments.cr @@ -1,10 +1,14 @@ class CreatePostsAndComments::V20171006163153 < Avram::Migrator::Migration::V1 def migrate create :posts do + primary_key id : Int32 + add_timestamps add title : String end create :comments do + primary_key id : Int32 + add_timestamps add body : String add post_id : Int32 end diff --git a/db/migrations/20171130064637_create_managers_and_employees.cr b/db/migrations/20171130064637_create_managers_and_employees.cr index 2ce36667a..2f4d27099 100644 --- a/db/migrations/20171130064637_create_managers_and_employees.cr +++ b/db/migrations/20171130064637_create_managers_and_employees.cr @@ -1,10 +1,14 @@ class CreateManagersAndEmployees::V20171130064637 < Avram::Migrator::Migration::V1 def migrate create :managers do + primary_key id : Int32 + add_timestamps add name : String end create :employees do + primary_key id : Int32 + add_timestamps add name : String add manager_id : Int32? end diff --git a/db/migrations/20180113081408_create_companies.cr b/db/migrations/20180113081408_create_companies.cr index 5e034f0e9..363d7e510 100644 --- a/db/migrations/20180113081408_create_companies.cr +++ b/db/migrations/20180113081408_create_companies.cr @@ -1,6 +1,8 @@ class CreateCompanies::V20180113081408 < Avram::Migrator::Migration::V1 def migrate create :companies do + primary_key id : Int32 + add_timestamps add sales : Int64 add earnings : Float end diff --git a/db/migrations/20180115194734_create_taggings.cr b/db/migrations/20180115194734_create_taggings.cr index 9d47a1e34..aca3b28c8 100644 --- a/db/migrations/20180115194734_create_taggings.cr +++ b/db/migrations/20180115194734_create_taggings.cr @@ -1,10 +1,14 @@ class CreateTaggings::V20180115194734 < Avram::Migrator::Migration::V1 def migrate create :tags do + primary_key id : Int32 + add_timestamps add name : String end create :taggings do + primary_key id : Int32 + add_timestamps add_belongs_to tag : Tag, on_delete: :cascade add_belongs_to post : Post, on_delete: :cascade end diff --git a/db/migrations/20180612221318_create_businesses.cr b/db/migrations/20180612221318_create_businesses.cr index e2eccbb6e..aba2b46db 100644 --- a/db/migrations/20180612221318_create_businesses.cr +++ b/db/migrations/20180612221318_create_businesses.cr @@ -1,15 +1,21 @@ class CreateBusinesses::V20180612221318 < Avram::Migrator::Migration::V1 def migrate create :businesses do + primary_key id : Int32 + add_timestamps add name : String end create :tax_ids do + primary_key id : Int32 + add_timestamps add number : Int32 add_belongs_to business : Business, on_delete: :cascade end create :email_addresses do + primary_key id : Int32 + add_timestamps add address : String add_belongs_to business : Business?, on_delete: :cascade end diff --git a/db/migrations/20180625202051_create_line_item.cr b/db/migrations/20180625202051_create_line_item.cr index 5457aa5ab..58a3844f0 100644 --- a/db/migrations/20180625202051_create_line_item.cr +++ b/db/migrations/20180625202051_create_line_item.cr @@ -1,6 +1,8 @@ class CreateLineItem::V20180625202051 < Avram::Migrator::Migration::V1 def migrate - create :line_items, primary_key_type: :uuid do + create :line_items do + primary_key id : UUID + add_timestamps add name : String end end diff --git a/db/migrations/20180628193054_create_product.cr b/db/migrations/20180628193054_create_product.cr index 15a991060..72f02ee26 100644 --- a/db/migrations/20180628193054_create_product.cr +++ b/db/migrations/20180628193054_create_product.cr @@ -1,6 +1,9 @@ class CreateProduct::V20180628193054 < Avram::Migrator::Migration::V1 def migrate - create :products, primary_key_type: :uuid + create :products do + primary_key id : UUID + add_timestamps + end end def rollback diff --git a/db/migrations/20180802180356_create_blobs.cr b/db/migrations/20180802180356_create_blobs.cr index 535d2850d..c8bfb43df 100644 --- a/db/migrations/20180802180356_create_blobs.cr +++ b/db/migrations/20180802180356_create_blobs.cr @@ -1,6 +1,8 @@ class CreateBlobs::V20180802180356 < Avram::Migrator::Migration::V1 def migrate create :blobs do + primary_key id : Int32 + add_timestamps add doc : JSON::Any?, default: JSON::Any.new({ "defa'ult" => JSON::Any.new("val'ue") }) end end diff --git a/db/migrations/20180802180357_test_defaults.cr b/db/migrations/20180802180357_test_defaults.cr index d52fc14d1..fcf522922 100644 --- a/db/migrations/20180802180357_test_defaults.cr +++ b/db/migrations/20180802180357_test_defaults.cr @@ -1,6 +1,8 @@ class TestDefaults::V20180802180357 < Avram::Migrator::Migration::V1 def migrate create :test_defaults do + primary_key id : Int32 + add_timestamps add greeting : String, default: "Hello there!" add drafted_at : Time, default: :now add published_at : Time, default: 1.day.from_now diff --git a/spec/migrator/create_table_statement_spec.cr b/spec/migrator/create_table_statement_spec.cr index 44ef331cb..dc147ffcb 100644 --- a/spec/migrator/create_table_statement_spec.cr +++ b/spec/migrator/create_table_statement_spec.cr @@ -7,15 +7,14 @@ describe Avram::Migrator::CreateTableStatement do built.statements.size.should eq 1 built.statements.first.should eq <<-SQL - CREATE TABLE users ( - id serial PRIMARY KEY, - created_at timestamptz NOT NULL, - updated_at timestamptz NOT NULL); + CREATE TABLE users (\n); SQL end it "can create tables" do built = Avram::Migrator::CreateTableStatement.new(:users).build do + primary_key id : Int32 + add_timestamps add name : String add age : Int32 add completed : Bool @@ -43,18 +42,25 @@ describe Avram::Migrator::CreateTableStatement do SQL end - it "can create tables with uuid primary keys" do - built = Avram::Migrator::CreateTableStatement.new(:users, Avram::Migrator::PrimaryKeyType::UUID).build do - add name : String + it "can create tables with other primary keys" do + built = Avram::Migrator::CreateTableStatement.new(:users).build do + primary_key id : UUID end built.statements.size.should eq 1 built.statements.first.should eq <<-SQL CREATE TABLE users ( - id uuid PRIMARY KEY, - created_at timestamptz NOT NULL, - updated_at timestamptz NOT NULL, - name text NOT NULL); + id uuid PRIMARY KEY); + SQL + + built = Avram::Migrator::CreateTableStatement.new(:users).build do + primary_key custom_id_name : Int64 + end + + built.statements.size.should eq 1 + built.statements.first.should eq <<-SQL + CREATE TABLE users ( + custom_id_name bigserial PRIMARY KEY); SQL end @@ -74,9 +80,6 @@ describe Avram::Migrator::CreateTableStatement do built.statements.size.should eq 1 built.statements.first.should eq <<-SQL CREATE TABLE users ( - id serial PRIMARY KEY, - created_at timestamptz NOT NULL, - updated_at timestamptz NOT NULL, name text NOT NULL DEFAULT 'name', email text DEFAULT 'optional', age int NOT NULL DEFAULT '1', @@ -102,9 +105,6 @@ describe Avram::Migrator::CreateTableStatement do built.statements.size.should eq 4 built.statements.first.should eq <<-SQL CREATE TABLE users ( - id serial PRIMARY KEY, - created_at timestamptz NOT NULL, - updated_at timestamptz NOT NULL, name text NOT NULL, age int NOT NULL, email text NOT NULL); @@ -144,9 +144,6 @@ describe Avram::Migrator::CreateTableStatement do built.statements.first.should eq <<-SQL CREATE TABLE comments ( - id serial PRIMARY KEY, - created_at timestamptz NOT NULL, - updated_at timestamptz NOT NULL, user_id int NOT NULL REFERENCES users ON DELETE CASCADE, post_id int REFERENCES posts ON DELETE RESTRICT, category_label_id int NOT NULL REFERENCES custom_table ON DELETE SET NULL, diff --git a/src/avram/migrator/columns/primary_keys/base.cr b/src/avram/migrator/columns/primary_keys/base.cr new file mode 100644 index 000000000..7fc0d8369 --- /dev/null +++ b/src/avram/migrator/columns/primary_keys/base.cr @@ -0,0 +1,11 @@ +abstract class Avram::Migrator::Columns::PrimaryKeys::Base + macro inherited + private getter name : String + end + + abstract def column_type + + def build : String + %( #{name} #{column_type} PRIMARY KEY) + end +end diff --git a/src/avram/migrator/columns/primary_keys/int32_primary_key.cr b/src/avram/migrator/columns/primary_keys/int32_primary_key.cr new file mode 100644 index 000000000..7caa4ca5c --- /dev/null +++ b/src/avram/migrator/columns/primary_keys/int32_primary_key.cr @@ -0,0 +1,12 @@ +require "./base" + +module Avram::Migrator::Columns::PrimaryKeys + class Int32PrimaryKey < Base + def initialize(@name) + end + + def column_type : String + "serial" + end + end +end diff --git a/src/avram/migrator/columns/primary_keys/int64_primary_key.cr b/src/avram/migrator/columns/primary_keys/int64_primary_key.cr new file mode 100644 index 000000000..24dd6cbcc --- /dev/null +++ b/src/avram/migrator/columns/primary_keys/int64_primary_key.cr @@ -0,0 +1,12 @@ +require "./base" + +module Avram::Migrator::Columns::PrimaryKeys + class Int64PrimaryKey < Base + def initialize(@name) + end + + def column_type : String + "bigserial" + end + end +end diff --git a/src/avram/migrator/columns/primary_keys/uuid_primary_key.cr b/src/avram/migrator/columns/primary_keys/uuid_primary_key.cr new file mode 100644 index 000000000..cafe85d95 --- /dev/null +++ b/src/avram/migrator/columns/primary_keys/uuid_primary_key.cr @@ -0,0 +1,12 @@ +require "./base" + +module Avram::Migrator::Columns::PrimaryKeys + class UUIDPrimaryKey < Base + def initialize(@name) + end + + def column_type : String + "uuid" + end + end +end diff --git a/src/avram/migrator/create_table_statement.cr b/src/avram/migrator/create_table_statement.cr index b081c6ef9..a5190617b 100644 --- a/src/avram/migrator/create_table_statement.cr +++ b/src/avram/migrator/create_table_statement.cr @@ -5,7 +5,7 @@ class Avram::Migrator::CreateTableStatement private getter rows = [] of String - def initialize(@table_name : Symbol, @primary_key_type : PrimaryKeyType = PrimaryKeyType::Serial) + def initialize(@table_name : Symbol) end # Accepts a block to build a table and indices using `add` and `add_index` methods. @@ -52,27 +52,28 @@ class Avram::Migrator::CreateTableStatement private def table_statement String.build do |statement| statement << initial_table_statement - statement << ",\n" unless rows.empty? - statement << rows.join(",\n") statement << ");" end end private def initial_table_statement - id_column_type = if @primary_key_type == PrimaryKeyType::UUID - "uuid" - else - "serial" - end <<-SQL - CREATE TABLE #{@table_name} ( - id #{id_column_type} PRIMARY KEY, - created_at timestamptz NOT NULL, - updated_at timestamptz NOT NULL + CREATE TABLE #{@table_name} (\n SQL end + macro primary_key(type_declaration) + rows << Avram::Migrator::Columns::PrimaryKeys::{{ type_declaration.type }}PrimaryKey + .new(name: {{ type_declaration.var.stringify }}) + .build + end + + macro add_timestamps + add created_at : Time + add updated_at : Time + end + macro add(type_declaration, default = nil, index = false, unique = false, using = :btree, **type_options) {% if type_declaration.type.is_a?(Union) %} {% type = type_declaration.type.types.first %} diff --git a/src/avram/migrator/migration.cr b/src/avram/migrator/migration.cr index 9cb1b7070..94a3a1f37 100644 --- a/src/avram/migrator/migration.cr +++ b/src/avram/migrator/migration.cr @@ -96,6 +96,16 @@ abstract class Avram::Migrator::Migration::V1 yield tx end end + rescue e : PQ::PQError + raise <<-ERROR + There was a problem running this statement: + + #{statements.join("\n")} + + Problem: + + #{e.message} + ERROR end def reset_prepared_statements diff --git a/src/avram/migrator/statement_helpers.cr b/src/avram/migrator/statement_helpers.cr index ff7be1fd0..ad9bfcc50 100644 --- a/src/avram/migrator/statement_helpers.cr +++ b/src/avram/migrator/statement_helpers.cr @@ -3,8 +3,8 @@ require "./index_statement_helpers" module Avram::Migrator::StatementHelpers include Avram::Migrator::IndexStatementHelpers - macro create(table_name, primary_key_type = Avram::Migrator::PrimaryKeyType::Serial) - statements = Avram::Migrator::CreateTableStatement.new({{ table_name }}, {{ primary_key_type }}).build do + macro create(table_name) + statements = Avram::Migrator::CreateTableStatement.new({{ table_name }}).build do {{ yield }} end.statements diff --git a/src/avram/tasks/gen/migration.ecr b/src/avram/tasks/gen/migration.ecr index 1b307a4b8..fa2196dfa 100644 --- a/src/avram/tasks/gen/migration.ecr +++ b/src/avram/tasks/gen/migration.ecr @@ -4,6 +4,9 @@ class <%= migration_class_name %> < Avram::Migrator::Migration::V1 <%= formatted_migrate_contents %> <%- else -%> # create :things do + # primary_key id : Int64 + # add_timestamps + # # add title : String # add description : String? # end