/* Copyright 2017 Vector Creations Ltd
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

-- Table keeping track of who shares a room with who. We only keep track
-- of this for local users, so `user_id` is local users only (but we do keep track
-- of which remote users share a room)
CREATE TABLE users_who_share_rooms (
    user_id TEXT NOT NULL,
    other_user_id TEXT NOT NULL,
    room_id TEXT NOT NULL,
    share_private BOOLEAN NOT NULL  -- is the shared room private? i.e. they share a private room
);

CREATE UNIQUE INDEX users_who_share_rooms_u_idx ON users_who_share_rooms(user_id, other_user_id);
CREATE INDEX users_who_share_rooms_r_idx ON users_who_share_rooms(room_id, user_id);

-- Make sure that we popualte the table initially
UPDATE user_directory_stream_pos SET stream_id = NULL;

Fix up indices for users_who_share_rooms

/* Copyright 2017 Vector Creations Ltd
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

-- Table keeping track of who shares a room with who. We only keep track
-- of this for local users, so `user_id` is local users only (but we do keep track
-- of which remote users share a room)
CREATE TABLE users_who_share_rooms (
    user_id TEXT NOT NULL,
    other_user_id TEXT NOT NULL,
    room_id TEXT NOT NULL,
    share_private BOOLEAN NOT NULL  -- is the shared room private? i.e. they share a private room
);

CREATE UNIQUE INDEX users_who_share_rooms_u_idx ON users_who_share_rooms(user_id, other_user_id);
CREATE INDEX users_who_share_rooms_r_idx ON users_who_share_rooms(room_id);
CREATE INDEX users_who_share_rooms_o_idx ON users_who_share_rooms(other_user_id);

-- Make sure that we popualte the table initially
UPDATE user_directory_stream_pos SET stream_id = NULL;


\unset ECHO
\set QUIET 1
-- Turn off echo and keep things quiet.
-- Format the output for nice TAP.
\pset format unaligned
\pset tuples_only true
\pset pager
-- Revert all changes on failure.
\set ON_ERROR_ROLLBACK 1
\set ON_ERROR_STOP true

-- Load the TAP functions.
BEGIN;
\i pgtap.sql
\i plparrot.sql

-- Plan the tests.
SELECT plan(3);

CREATE FUNCTION test_void_plperl6(integer) RETURNS void AS $$ Nil $$ LANGUAGE plperl6;

CREATE FUNCTION test_int_plperl6(integer) RETURNS int AS $$ 42 $$ LANGUAGE plperl6;

CREATE FUNCTION test_float_plperl6(integer) RETURNS float AS $$ 5.0 $$ LANGUAGE plperl6;

select is(test_int_plperl6(89),42,'Return an integer from PL/Perl6');
select is(test_void_plperl6(42)::text,''::text,'Return nothing from PL/Perl6');
select is(test_float_plperl6(2), 5.0::float,'Return a float from PL/Perl6');

-- Finish the tests and clean up.
SELECT * FROM finish();

rollback;

Add a test for returning strings from PL/Perl6

\unset ECHO
\set QUIET 1
-- Turn off echo and keep things quiet.
-- Format the output for nice TAP.
\pset format unaligned
\pset tuples_only true
\pset pager
-- Revert all changes on failure.
\set ON_ERROR_ROLLBACK 1
\set ON_ERROR_STOP true

-- Load the TAP functions.
BEGIN;
\i pgtap.sql
\i plparrot.sql

-- Plan the tests.
SELECT plan(4);

CREATE FUNCTION test_void_plperl6(integer) RETURNS void AS $$ Nil $$ LANGUAGE plperl6;

CREATE FUNCTION test_int_plperl6(integer) RETURNS int AS $$ 42 $$ LANGUAGE plperl6;

CREATE FUNCTION test_float_plperl6(integer) RETURNS float AS $$ 5.0 $$ LANGUAGE plperl6;

CREATE FUNCTION test_string_plperl6() RETURNS varchar AS $$ "rakudo" $$ LANGUAGE plperl6;

select is(test_int_plperl6(89),42,'Return an integer from PL/Perl6');
select is(test_void_plperl6(42)::text,''::text,'Return nothing from PL/Perl6');
select is(test_float_plperl6(2), 5.0::float,'Return a float from PL/Perl6');
select is(test_string_plperl6(), 'rakudo','Return a varchar from PL/Perl6');

-- Finish the tests and clean up.
SELECT * FROM finish();

rollback;


--   Copyright 2020 MSolution.IO
--
--   Licensed under the Apache License, Version 2.0 (the "License");
--   you may not use this file except in compliance with the License.
--   You may obtain a copy of the License at
--
--       http://www.apache.org/licenses/LICENSE-2.0
--
--   Unless required by applicable law or agreed to in writing, software
--   distributed under the License is distributed on an "AS IS" BASIS,
--   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
--   See the License for the specific language governing permissions and
--   limitations under the License.

ALTER TABLE user ADD account_type VARCHAR(255) NOT NULL DEFAULT "";
ALTER TABLE user DROP CONSTRAINT unique_email;
ALTER TABLE user ADD CONSTRAINT type_email_unique UNIQUE (email, account_type);

Add default value for user.account_type field to trackit

--   Copyright 2020 MSolution.IO
--
--   Licensed under the Apache License, Version 2.0 (the "License");
--   you may not use this file except in compliance with the License.
--   You may obtain a copy of the License at
--
--       http://www.apache.org/licenses/LICENSE-2.0
--
--   Unless required by applicable law or agreed to in writing, software
--   distributed under the License is distributed on an "AS IS" BASIS,
--   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
--   See the License for the specific language governing permissions and
--   limitations under the License.

ALTER TABLE user ADD account_type VARCHAR(255) NOT NULL DEFAULT "trackit";
ALTER TABLE user DROP CONSTRAINT unique_email;
ALTER TABLE user ADD CONSTRAINT type_email_unique UNIQUE (email, account_type);


.print 'Load database'
.read ../../../database/database.sql

.mode csv
.headers on

.print 'Query the database to build the crosstabulation table'
.once crosstab.csv
SELECT
  CASE WHEN un.iso3_code IS NULL THEN 'NOT UN' ELSE 'UN' END AS UN,
  IFNULL('WMO ' || wmo.state_or_territory, 'NOT WMO') AS WMO,
  CASE WHEN ipcc.iso3_code IS NULL THEN 'NOT IPCC' ELSE 'IPCC' END AS IPCC,
  COUNT(*) AS count
FROM (
  SELECT DISTINCT iso3_code
  FROM (
    SELECT iso3_code
    FROM current_un_members
    UNION
    SELECT iso3_code
    FROM current_wmo_members
    UNION
    SELECT iso3_code
    FROM current_ipcc_members
  ) every
) each
LEFT JOIN
(
  SELECT iso3_code
  FROM current_un_members
) un
USING (iso3_code)
LEFT JOIN
(
  SELECT iso3_code, state_or_territory
  FROM current_wmo_members
) wmo
USING (iso3_code)
LEFT JOIN
(
  SELECT iso3_code
  FROM current_ipcc_members
) ipcc
USING (iso3_code)
GROUP BY UN, WMO, IPCC
ORDER BY UN DESC, WMO, IPCC
;

Define intermediate views to allow further calculations

.print 'Load database'
.read ../../../database/database.sql

CREATE VIEW all_members
AS
SELECT DISTINCT iso3_code
FROM (
  SELECT iso3_code
  FROM current_un_members
  UNION
  SELECT iso3_code
  FROM current_wmo_members
  UNION
  SELECT iso3_code
  FROM current_ipcc_members
) every
;

CREATE VIEW cross_counts
AS
SELECT
  CASE WHEN un.iso3_code IS NULL THEN 'NOT UN' ELSE 'UN' END AS UN,
  IFNULL('WMO ' || wmo.state_or_territory, 'NOT WMO') AS WMO,
  CASE WHEN ipcc.iso3_code IS NULL THEN 'NOT IPCC' ELSE 'IPCC' END AS IPCC,
  COUNT(*) AS count
FROM all_members
LEFT JOIN
(
  SELECT iso3_code
  FROM current_un_members
) un
USING (iso3_code)
LEFT JOIN
(
  SELECT iso3_code, state_or_territory
  FROM current_wmo_members
) wmo
USING (iso3_code)
LEFT JOIN
(
  SELECT iso3_code
  FROM current_ipcc_members
) ipcc
USING (iso3_code)
GROUP BY UN, WMO, IPCC
;

.mode csv
.headers on

.print 'Query the database to build the crosstabulation table'
.once crosstab.csv
SELECT *
FROM cross_counts
ORDER BY UN DESC, WMO, IPCC
;


-- See the NOTICE file distributed with this work for additional information
-- regarding copyright ownership.
--
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.
-- You may obtain a copy of the License at
--
--      http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and
-- limitations under the License.

# patch_106_107_b.sql
#
# Title: Alter stable_id to make case sensitive.
#
# Description:
#   Make the stable_id field case sensitive so that values remain UNIQUE with case differences.

ALTER TABLE gene_member MODIFY stable_id VARCHAR(128) BINARY NOT NULL;
ALTER TABLE seq_member MODIFY stable_id VARCHAR(128) BINARY NOT NULL;
ALTER TABLE gene_member_qc MODIFY gene_member_stable_id VARCHAR(128) BINARY NOT NULL;

# Patch identifier
INSERT INTO meta (species_id, meta_key, meta_value)
  VALUES (NULL, 'patch', 'patch_106_107_b.sql|case_sensitive_stable_id');

Switch off foreign key checks for smoother running

-- See the NOTICE file distributed with this work for additional information
-- regarding copyright ownership.
--
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.
-- You may obtain a copy of the License at
--
--      http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and
-- limitations under the License.

# patch_106_107_b.sql
#
# Title: Alter stable_id to make case sensitive.
#
# Description:
#   Make the stable_id field case sensitive so that values remain UNIQUE with case differences.

SET FOREIGN_KEY_CHECKS = 0;
ALTER TABLE gene_member MODIFY stable_id VARCHAR(128) BINARY NOT NULL;
ALTER TABLE seq_member MODIFY stable_id VARCHAR(128) BINARY NOT NULL;
ALTER TABLE gene_member_qc MODIFY gene_member_stable_id VARCHAR(128) BINARY NOT NULL;
SET FOREIGN_KEY_CHECKS = 1;

# Patch identifier
INSERT INTO meta (species_id, meta_key, meta_value)
  VALUES (NULL, 'patch', 'patch_106_107_b.sql|case_sensitive_stable_id');


UPDATE NOTIFICATION_TYPE SET ACTION_CODE='323' WHERE MODULE_CODE='9' AND DESCRIPTION='IACUC Protocol Amendment Created Action'
/

Update action code for Amendment Created notification

UPDATE NOTIFICATION_TYPE SET ACTION_CODE='323' WHERE MODULE_CODE='9' AND DESCRIPTION='IACUC Protocol Amendment Created Action'
/
UPDATE NOTIFICATION_TYPE SET ACTION_CODE='322' WHERE MODULE_CODE='9' AND DESCRIPTION='IACUC Protocol Renewal Created Action'
/


SELECT
  content.hashId, content.numViews, image.width, image.height
FROM
  content, image
WHERE
  content.id = image.contentid AND
  content.state = 'completed:success'
ORDER BY (image.width * image.height) DESC
LIMIT 10;

Make query for largest images more friendly

SELECT
  ("http://zoomhub.net/" || content.hashId) AS URL,
  content.numViews AS Views,
  ROUND(image.width * image.height / 1e6, 1) AS Megapixels
FROM
  content, image
WHERE
  content.id = image.contentid AND
  content.state = 'completed:success'
ORDER BY (image.width * image.height) DESC
LIMIT 10;


-- Add area to country (in square km).
-- Copyright (c) 2014 University of Oxford

ALTER TABLE country ADD COLUMN area double precision;
UPDATE country SET area=st_area(st_transform(geom, 3410))/1000000;
ALTER TABLE country ALTER COLUMN area SET NOT NULL;

Make sure area migration works with test data

-- Add area to country (in square km). "COALESCE with 0" is for compatibility with "create.test.database", where some countries lack geoms.
-- Copyright (c) 2014 University of Oxford

ALTER TABLE country ADD COLUMN area double precision;
UPDATE country SET area=COALESCE(st_area(st_transform(geom, 3410))/1000000, 0);
ALTER TABLE country ALTER COLUMN area SET NOT NULL;


create table blog_post_subject(
    post_id int UNSIGNED NOT NULL,
    subject_id int UNSIGNED NOT NULL,
    CONSTRAINT pk_ps PRIMARY KEY(post_id, subject_id),
    FOREIGN KEY (post_id) REFERENCES blog_post(id),
    FOREIGN KEY (subject_id) REFERENCES blog_subject(id)
);

insert blog_post_subject (post_id, subject_id)
    select id, subject_id from blog_post;

ALTER TABLE blog_post
  DROP FOREIGN KEY blog_post_ibfk_1;

Update selectors search question script.

create table blog_post_subject(
    post_id int UNSIGNED NOT NULL,
    subject_id int UNSIGNED NOT NULL,
    CONSTRAINT pk_post_subject PRIMARY KEY(post_id, subject_id),
    FOREIGN KEY (post_id) REFERENCES blog_post(id),
    FOREIGN KEY (subject_id) REFERENCES blog_subject(id)
);

insert blog_post_subject (post_id, subject_id)
    select id, subject_id from blog_post;

ALTER TABLE blog_post
  DROP FOREIGN KEY blog_post_ibfk_1;

ALTER TABLE blog_post
  DROP subject_id;


ALTER TABLE  `contest` CHANGE  `status`  `status` ENUM(  'Open',  'Closed' ) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT  'Open';
ALTER TABLE  `contest` ADD  `visibility`  ENUM( 'Visible',  'Hidden' ) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT  'Hidden';

Make table changes remember status before changeing

ALTER TABLE  `contest` ADD  `visibility`  ENUM( 'Visible',  'Hidden' ) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT  'Hidden';

UPDATE `contest` SET `startDate` = NOW(), `endDate` = NOW() + INTERVAL 3 YEAR WHERE `status` = 'RunningContest';
UPDATE `contest` SET `startDate` = NOW() + INTERVAL 2 YEAR, `endDate` = NOW() + INTERVAL 3 YEAR WHERE `status` = 'FutureContest';
UPDATE `contest` SET `startDate` = NOW() - INTERVAL 2 YEAR, `endDate` = NOW() WHERE `status` = 'PastContest';
UPDATE `contest` SET `visibilty` = 'Visible' WHERE `status` != 'Hidden';

ALTER TABLE  `contest` CHANGE  `status`  `status` ENUM(  'Open',  'Closed' ) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT  'Open';


exec sp_rename 'sb_reminder.trigger_durationProp', trigger_prop, 'COLUMN';

ALTER TABLE sb_reminder
    ADD process_name VARCHAR(200);

UPDATE sb_reminder
SET process_name = 'CalendarEventUserNotification'
WHERE sb_reminder.trigger_prop = 'NEXT_START_DATE_TIME';

ALTER TABLE sb_reminder
    ALTER COLUMN process_name VARCHAR(200) NOT NULL;

Fix the migration script of the reminder module when upgrading to version 003


INSERT INTO portti_bundle (name, startup)
       VALUES ('featuredata2','{}');

UPDATE portti_bundle set startup = '{
    "title" : "Feature data",
    "fi" : "featuredata2",
    "sv" : "featuredata2",
    "en" : "featuredata2",
    "bundlename" : "featuredata2",
    "bundleinstancename" : "featuredata2",
    "metadata" : {
        "Import-Bundle" : {
            "featuredata2" : {
                "bundlePath" : "/Oskari/packages/framework/bundle/"
            }
        },
        "Require-Bundle-Instance" : []
    },
    "instanceProps" : {}
}' WHERE name = 'featuredata2';

Add selection tools by default for featuredata2

INSERT INTO portti_bundle (name, startup)
       VALUES ('featuredata2','{}');

UPDATE portti_bundle set startup = '{
    "title" : "Feature data",
    "fi" : "featuredata2",
    "sv" : "featuredata2",
    "en" : "featuredata2",
    "bundlename" : "featuredata2",
    "bundleinstancename" : "featuredata2",
    "metadata" : {
        "Import-Bundle" : {
            "featuredata2" : {
                "bundlePath" : "/Oskari/packages/framework/bundle/"
            }
        },
        "Require-Bundle-Instance" : []
    },
    "instanceProps" : {}
}' WHERE name = 'featuredata2';

UPDATE portti_bundle set config = '{
    "selectionTools": true
}' WHERE name = 'featuredata2';


CREATE OR REPLACE procedure Fibonacci_Series(n  number)is
fs1 number := 0;
fs2 number := 1;
fs3 number;
cnt number default 0;
t number;
begin
dbms_output.put_line(fs1);
dbms_output.put_line(fs2);
while cnt!= n-2
loop
  fs3:=fs1+fs2;
  dbms_output.put_line(fs3);
  t:=fs2;
  fs2:=fs3;
  fs1:=t;
  cnt:=cnt+1;
end loop;
exception
when others then
dbms_output.put_line(sqlerrm);
end;

/*APPEL
EXECUTE Fibonacci_Series(20)
*/

Remove variable t while keeping same behaviour

CREATE OR REPLACE procedure Fibonacci_Series(n  number)is
fs1 number := 0;
fs2 number := 1;
fs3 number;
cnt number default 0;
begin
dbms_output.put_line(fs1);
dbms_output.put_line(fs2);
while cnt!= n-2
loop
  fs3:=fs1+fs2;
  dbms_output.put_line(fs3);
  fs1:=fs2;
  fs2:=fs3;
  cnt:=cnt+1;
end loop;
exception
when others then
dbms_output.put_line(sqlerrm);
end;
/
/*APPEL
EXECUTE Fibonacci_Series(20);
*/


ALTER TABLE `m_client_loan_counter`
	ADD COLUMN `group_id` BIGINT(20) NOT NULL AFTER `client_id`,
	ADD CONSTRAINT `FK_m_group_loan_counter` FOREIGN KEY (`group_id`) REFERENCES `m_group` (`id`);

RENAME TABLE `m_client_loan_counter` TO `m_loan_counter`;

ALTER TABLE `m_loan_counter`
	CHANGE COLUMN `client_id` `client_id` BIGINT(20) NULL DEFAULT NULL AFTER `id`,
	CHANGE COLUMN `group_id` `group_id` BIGINT(20) NULL DEFAULT NULL AFTER `client_id`;

ALTER TABLE `m_loan`
	ADD COLUMN `loan_counter` SMALLINT NULL DEFAULT NULL AFTER `sync_disbursement_with_meeting`,
	ADD COLUMN `loan_product_counter` SMALLINT NULL DEFAULT NULL AFTER `loan_counter`;

DROP TABLE `m_loan_counter`;

Update DB Script for loan counter changes

DROP TABLE `m_client_loan_counter`;
ALTER TABLE `m_loan`
	ADD COLUMN `loan_counter` SMALLINT NULL DEFAULT NULL AFTER `sync_disbursement_with_meeting`,
	ADD COLUMN `loan_product_counter` SMALLINT NULL DEFAULT NULL AFTER `loan_counter`;


CREATE TABLE IF NOT EXISTS AM_USAGE_UPLOADED_FILES (
   FILE_NAME varchar(255) NOT NULL,
   FILE_TIMESTAMP TIMESTAMP(0) DEFAULT CURRENT_TIMESTAMP,
   FILE_PROCESSED tinyint DEFAULT 0,
   FILE_CONTENT MEDIUMBLOB DEFAULT NULL,
   PRIMARY KEY (FILE_NAME, FILE_TIMESTAMP)
);

Update the DB2 query used to create AM_USAGE_UPLOAD_FILES table

CREATE TABLE IF NOT EXISTS AM_USAGE_UPLOADED_FILES (
   FILE_NAME varchar(255) NOT NULL,
   FILE_TIMESTAMP TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
   FILE_PROCESSED SMALLINT DEFAULT 0,
   FILE_CONTENT BLOB(16777215) DEFAULT NULL,
   PRIMARY KEY (FILE_NAME, FILE_TIMESTAMP)
);


-- Add area to country (in square km). "COALESCE with 0" is for compatibility with "create.test.database", where some countries lack geoms.
-- Copyright (c) 2014 University of Oxford

ALTER TABLE country ADD COLUMN area double precision;
UPDATE country SET area=COALESCE(st_area(st_transform(geom, 3410))/1000000, 0);
ALTER TABLE country ALTER COLUMN area SET NOT NULL;

Change CRS for area calculation to Zhi's suggestion

-- Add area to country (in square km). "COALESCE with 0" is for compatibility with "create.test.database", where some countries lack geoms.
-- Copyright (c) 2014 University of Oxford

-- Add Zhi's recommend area calculation projection (http://epsg.io/54009)
INSERT into spatial_ref_sys (srid, auth_name, auth_srid, proj4text, srtext) values ( 54009, 'ESRI', 54009, '+proj=moll +lon_0=0 +x_0=0 +y_0=0 +datum=WGS84 +units=m +no_defs ', 'PROJCS["World_Mollweide",GEOGCS["GCS_WGS_1984",DATUM["WGS_1984",SPHEROID["WGS_1984",6378137,298.257223563]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]],PROJECTION["Mollweide"],PARAMETER["False_Easting",0],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",0],UNIT["Meter",1],AUTHORITY["EPSG","54009"]]');

ALTER TABLE country ADD COLUMN area double precision;
UPDATE country SET area=COALESCE(st_area(st_transform(geom, 54009))/1000000, 0);
ALTER TABLE country ALTER COLUMN area SET NOT NULL;


--
-- Table structure for table `shoppingcart_coupon`
--

DROP TABLE IF EXISTS `shoppingcart_coupon`;
CREATE TABLE `shoppingcart_coupon` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `code` varchar(32) NOT NULL,
  `description` varchar(255) DEFAULT NULL,
  `course_id` varchar(255) NOT NULL,
  `percentage_discount` int(11) NOT NULL,
  `created_at` datetime(6) NOT NULL,
  `is_active` tinyint(1) NOT NULL,
  `expiration_date` datetime(6) DEFAULT NULL,
  `created_by_id` int(11) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

--
-- Dumping data for table `shoppingcart_coupon`
--

INSERT INTO `shoppingcart_coupon` VALUES
  (2,'SC_VER_40_PCT_OFF','40% off the verified mode of the Shopping Cart Course','course-v1:AccTest+ShoppingCart+Verified',40,'2016-03-22 20:19:55.693594',1,NULL,5),
  (3,'SC_PAID_80_PCT_OFF','80% off the paid ShoppingCart course','course-v1:AccTest+ShoppingCart+Paid',80,'2016-03-22 20:20:39.722085',1,NULL,5);

Fix type in coupon fixture data.

--
-- Table structure for table `shoppingcart_coupon`
--

DROP TABLE IF EXISTS `shoppingcart_coupon`;
CREATE TABLE `shoppingcart_coupon` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `code` varchar(32) NOT NULL,
  `description` varchar(255) DEFAULT NULL,
  `course_id` varchar(255) NOT NULL,
  `percentage_discount` int(11) NOT NULL,
  `created_at` datetime NOT NULL,
  `is_active` tinyint(1) NOT NULL,
  `expiration_date` datetime DEFAULT NULL,
  `created_by_id` int(11) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

--
-- Dumping data for table `shoppingcart_coupon`
--

INSERT INTO `shoppingcart_coupon` VALUES
  (2,'SC_VER_40_PCT_OFF','40% off the verified mode of the Shopping Cart Course','course-v1:AccTest+ShoppingCart+Verified',40,'2016-03-22 20:19:55.693594',1,NULL,5),
  (3,'SC_PAID_80_PCT_OFF','80% off the paid ShoppingCart course','course-v1:AccTest+ShoppingCart+Paid',80,'2016-03-22 20:20:39.722085',1,NULL,5);


-- Donations count
INSERT INTO speakeasy_petition_metrics (campaign_id, activity, npeople)
  SELECT
    campaign_id, 'donation', count(id) donations_count
  FROM civicrm_contribution
  WHERE contribution_status_id = 1 AND is_test = 0 AND campaign_id IS NOT NULL
  GROUP BY campaign_id;

-- Donations amount
INSERT INTO speakeasy_petition_metrics (campaign_id, activity, npeople)
  SELECT
    campaign_id, 'donation_amount', sum(total_amount)
  FROM civicrm_contribution
  WHERE contribution_status_id = 1 AND is_test = 0 AND campaign_id IS NOT NULL
  GROUP BY campaign_id;

Add currency to donation metrics

-- Donations count
INSERT INTO speakeasy_petition_metrics (activity, campaign_id, status, npeople)
  SELECT
    'donation', campaign_id, currency, count(id) donations_count
  FROM civicrm_contribution
  WHERE contribution_status_id = 1 AND is_test = 0 AND campaign_id IS NOT NULL
  GROUP BY campaign_id, currency;

-- Donations amount
INSERT INTO speakeasy_petition_metrics (activity, campaign_id, status, npeople)
  SELECT
    'donation_amount', campaign_id, currency, sum(total_amount)
  FROM civicrm_contribution
  WHERE contribution_status_id = 1 AND is_test = 0 AND campaign_id IS NOT NULL
  GROUP BY campaign_id, currency;


SELECT
FilePath = SUBSTRING(CONVERT(VARCHAR, DATEADD(hh, blog.TimeZoneOffset, c.DatePublishedUtc), 120), 1, 10) + '-' + c.EntryName + '.aspx.markdown',
Content =
'---
layout: post
title: "' + REPLACE(c.Title, '"', '"') + '"
date: ' + SUBSTRING(CONVERT(VARCHAR, DATEADD(hh, blog.TimeZoneOffset, c.DatePublishedUtc), 120), 1, 10) + '
comments: true
categories: [' +
 ISNULL(SUBSTRING(
   (SELECT ',' + cat.Title AS [text()]
    FROM subtext_LinkCategories cat
    INNER JOIN subtext_Links l
    ON l.CategoryID = cat.CategoryID
    WHERE c.ID = l.PostID
    FOR XML PATH ('')), 2, 1000), '') + ']
---
' + CAST(c.[Text] as NVARCHAR(MAX))
FROM subtext_Content c
INNER JOIN subtext_Config blog
ON c.BlogID = blog.BlogID
WHERE blog.BlogID = 0
 AND c.PostConfig & 1 = 1

Add support for existing "articles"

SELECT
FilePath = (
CASE c.PostType
WHEN 2 THEN 'articles-' + c.EntryName + '.aspx.markdown'
ELSE SUBSTRING(CONVERT(VARCHAR, DATEADD(hh, blog.TimeZoneOffset, c.DatePublishedUtc), 120), 1, 10) + '-' + c.EntryName + '.aspx.markdown'
END),
Content =
'---
layout: ' + (CASE c.PostType WHEN 2 THEN 'page' ELSE 'post' END) + '
title: "' + REPLACE(c.Title, '"', '"') + '"
date: ' + SUBSTRING(CONVERT(VARCHAR, DATEADD(hh, blog.TimeZoneOffset, c.DatePublishedUtc), 120), 1, 10) + '
comments: true
categories: [' +
 ISNULL(SUBSTRING(
   (SELECT ',' + cat.Title AS [text()]
    FROM subtext_LinkCategories cat
    INNER JOIN subtext_Links l
    ON l.CategoryID = cat.CategoryID
    WHERE c.ID = l.PostID
    FOR XML PATH ('')), 2, 1000), '') + ']
---
' + CAST(c.[Text] as NVARCHAR(MAX))
FROM subtext_Content c
INNER JOIN subtext_Config blog
ON c.BlogID = blog.BlogID
WHERE blog.BlogID = 0
 AND c.PostConfig & 1 = 1


-- An example of monitoring pgBackRest from within PostgresSQL
--
-- Use copy to export data from the pgBackRest info command into the jsonb
-- type so it can be queried directly by PostgresSQL.

-- Create monitor schema
create schema monitor;

-- Get pgBackRest info in JSON format
create function monitor.pgbackrest_info()
    returns jsonb AS $$
declare
    data jsonb;
begin
    -- Create a temp table to hold the JSON data
    create temp table temp_pgbackrest_data (data jsonb);

    -- Copy data into the table directory from the pgBackRest into command
    copy temp_pgbackrest_data (data)
        from program
            'pgbackrest --output=json info | tr ''\n'' '' ''' (format text);

    select temp_pgbackrest_data.data
      into data
      from temp_pgbackrest_data;

    drop table temp_pgbackrest_data;

    return data;
end $$ language plpgsql;

Fix typos in monitoring examples.

-- An example of monitoring pgBackRest from within PostgreSQL
--
-- Use copy to export data from the pgBackRest info command into the jsonb
-- type so it can be queried directly by PostgreSQL.

-- Create monitor schema
create schema monitor;

-- Get pgBackRest info in JSON format
create function monitor.pgbackrest_info()
    returns jsonb AS $$
declare
    data jsonb;
begin
    -- Create a temp table to hold the JSON data
    create temp table temp_pgbackrest_data (data jsonb);

    -- Copy data into the table directory from the pgBackRest into command
    copy temp_pgbackrest_data (data)
        from program
            'pgbackrest --output=json info | tr ''\n'' '' ''' (format text);

    select temp_pgbackrest_data.data
      into data
      from temp_pgbackrest_data;

    drop table temp_pgbackrest_data;

    return data;
end $$ language plpgsql;


CREATE TABLE `logs` (
	`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
	`level` VARCHAR(50) NOT NULL,
	`message` TEXT NOT NULL,
	`context` LONGTEXT NOT NULL,
	`datetime` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
	PRIMARY KEY (`id`)
);

Support for MySQL 5.5 and lower

CREATE TABLE `logs` (
	`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
	`level` VARCHAR(50) NOT NULL,
	`message` TEXT NOT NULL,
	`context` LONGTEXT NOT NULL,
	`datetime` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
	PRIMARY KEY (`id`)
);


-- DROP DATABASE ykval;
CREATE DATABASE ykval;
USE ykval;

CREATE TABLE clients (
  id INT NOT NULL AUTO_INCREMENT,
  active BOOLEAN DEFAULT TRUE,
  created DATETIME NOT NULL,
  secret VARCHAR(60) NOT NULL DEFAULT '',
  email VARCHAR(255),
  notes VARCHAR(100) DEFAULT '',
  otp VARCHAR(100) DEFAULT '',
  PRIMARY KEY (id)
);

CREATE TABLE yubikeys (
  id INT NOT NULL UNIQUE AUTO_INCREMENT,
  active BOOLEAN DEFAULT TRUE,
  created DATETIME NOT NULL,
  accessed DATETIME,
  publicName VARCHAR(16) UNIQUE NOT NULL,
  internalName VARCHAR(12) NOT NULL,
  counter INT,
  low INT,
  high INT,
  sessionUse INT,
  PRIMARY KEY (id)
);

-- DROP USER 'ykval_verifier'@'localhost';
CREATE USER 'ykval_verifier'@'localhost';
GRANT SELECT,INSERT,UPDATE(accessed, counter, low, high, sessionUse)
       ON ykval.yubikeys to 'ykval_verifier'@'localhost';
GRANT SELECT(id, secret, active)
       ON ykval.clients to 'ykval_verifier'@'localhost';

CREATE USER 'ykval_getapikey'@'localhost';
GRANT SELECT(id),INSERT
	ON ykval.clients to 'ykval_getapikey'@'localhost';

FLUSH PRIVILEGES;

Add comment to drop ykval_getapikey.

-- DROP DATABASE ykval;
CREATE DATABASE ykval;
USE ykval;

CREATE TABLE clients (
  id INT NOT NULL AUTO_INCREMENT,
  active BOOLEAN DEFAULT TRUE,
  created DATETIME NOT NULL,
  secret VARCHAR(60) NOT NULL DEFAULT '',
  email VARCHAR(255),
  notes VARCHAR(100) DEFAULT '',
  otp VARCHAR(100) DEFAULT '',
  PRIMARY KEY (id)
);

CREATE TABLE yubikeys (
  id INT NOT NULL UNIQUE AUTO_INCREMENT,
  active BOOLEAN DEFAULT TRUE,
  created DATETIME NOT NULL,
  accessed DATETIME,
  publicName VARCHAR(16) UNIQUE NOT NULL,
  internalName VARCHAR(12) NOT NULL,
  counter INT,
  low INT,
  high INT,
  sessionUse INT,
  PRIMARY KEY (id)
);

-- DROP USER 'ykval_verifier'@'localhost';
CREATE USER 'ykval_verifier'@'localhost';
GRANT SELECT,INSERT,UPDATE(accessed, counter, low, high, sessionUse)
       ON ykval.yubikeys to 'ykval_verifier'@'localhost';
GRANT SELECT(id, secret, active)
       ON ykval.clients to 'ykval_verifier'@'localhost';

-- DROP USER 'ykval_getapikey'@'localhost';
CREATE USER 'ykval_getapikey'@'localhost';
GRANT SELECT(id),INSERT
	ON ykval.clients to 'ykval_getapikey'@'localhost';

FLUSH PRIVILEGES;


SELECT  spid SPID,
        sp.[status] Status,
        loginame [Login],
        hostname HostName,
        blocked BlockedBy,
        sd.name DatabaseName,
        cmd Command,
        cpu CPUTime,
        physical_io DiskIO,
        last_batch LastBatch,
        [program_name] ProgramName
FROM master.dbo.sysprocesses sp
	JOIN master.dbo.sysdatabases sd ON sp.dbid = sd.dbid
WHERE
	sd.name = @sourceDbName
ORDER BY spid

Trim output from sysprocesses since they're not variable length...variables. yea.

SELECT  spid SPID,
        RTRIM(sp.[status]) Status,
        RTRIM(loginame) [Login],
        RTRIM(hostname) HostName,
        RTRIM(blocked) BlockedBy,
        RTRIM(sd.name) DatabaseName,
        RTRIM(cmd) Command,
        cpu CPUTime,
        physical_io DiskIO,
        RTRIM(last_batch) LastBatch,
        RTRIM([program_name]) ProgramName
FROM master.dbo.sysprocesses sp
	JOIN master.dbo.sysdatabases sd ON sp.dbid = sd.dbid
WHERE
	sd.name = @sourceDbName
ORDER BY spid


UPDATE NOTIFICATION_TYPE SET ACTION_CODE='323' WHERE MODULE_CODE='9' AND DESCRIPTION='IACUC Protocol Amendment Created Action'
/

Update action code for Amendment Created notification

UPDATE NOTIFICATION_TYPE SET ACTION_CODE='323' WHERE MODULE_CODE='9' AND DESCRIPTION='IACUC Protocol Amendment Created Action'
/
UPDATE NOTIFICATION_TYPE SET ACTION_CODE='322' WHERE MODULE_CODE='9' AND DESCRIPTION='IACUC Protocol Renewal Created Action'
/


CREATE OR REPLACE VIEW gestion.v_interventions AS (
	SELECT e.geom, i.*
	FROM maintenance_intervention AS i, core_topology AS e
	WHERE i.topology_id = e.id
	AND i.deleted = FALSE
);

CREATE OR REPLACE VIEW gestion.v_projects AS (
	SELECT ST_Union(t.geom) AS geom_chantier, s.*
	FROM maintenance_intervention AS t, maintenance_project AS s
	WHERE t.project_id = s.id
	GROUP BY t.project_id, s.id
);

Fix view sql v interventions

CREATE OR REPLACE VIEW gestion.v_interventions AS (
	SELECT e.geom, i.*
	FROM maintenance_intervention AS i, core_topology AS e
	WHERE i.topology_id = e.id
	AND i.deleted = FALSE
);

CREATE OR REPLACE VIEW gestion.v_projects AS (
	SELECT ST_Union(t.geom) AS geom_chantier, s.*
	FROM v_interventions AS t, maintenance_project AS s
	WHERE t.project_id = s.id
	GROUP BY t.project_id, s.id
);


create table InstanceConfigSetting (
	id serial,
	instance integer not null references Instance(id),
	name varchar(255) not null,
	value varchar(255),
	primary key (id)
);

CREATE INDEX InstanceConfigSetting_name_index ON InstanceConfigSetting(name);

Make instance config value 1024 rather than 255

create table InstanceConfigSetting (
	id serial,
	instance integer not null references Instance(id),
	name varchar(255) not null,
	value varchar(1024),
	primary key (id)
);

CREATE INDEX InstanceConfigSetting_name_index ON InstanceConfigSetting(name);


DROP TABLE measurements;

CREATE TABLE measurements (
  id INT PRIMARY KEY NOT NULL AUTO_INCREMENT,
  time_stamp DATETIME,
  stroom_dal FLOAT,
  stroom_piek FLOAT,
  stroom_current FLOAT,
  gas FLOAT,

  diff_stroom_dal FLOAT,
  diff_stroom_piek FLOAT,
  diff_gas FLOAT
);

Add index to measurements time_stamp.

DROP TABLE measurements;

CREATE TABLE measurements (
  id INT PRIMARY KEY NOT NULL AUTO_INCREMENT,
  time_stamp DATETIME,
  stroom_dal FLOAT,
  stroom_piek FLOAT,
  stroom_current FLOAT,
  gas FLOAT,

  diff_stroom_dal FLOAT,
  diff_stroom_piek FLOAT,
  diff_gas FLOAT
);

CREATE INDEX measurement_time_index ON measurements(time_stamp);


-- Version number of the extension release
CREATE OR REPLACE FUNCTION cdb_crankshaft_version()
RETURNS text AS $$
  SELECT '@@VERSION@@'::text;
$$ language 'sql' IMMUTABLE STRICT;

-- Internal identifier of the installed extension instence
-- e.g. 'dev' for current development version
CREATE OR REPLACE FUNCTION _cdb_crankshaft_internal_version()
RETURNS text AS $$
  SELECT installed_version FROM pg_available_extensions where name='crankshaft' and pg_available_extensions IS NOT NULL;
$$ language 'sql' IMMUTABLE STRICT;

Change version function from IMMUTABLE to STABLE

-- Version number of the extension release
CREATE OR REPLACE FUNCTION cdb_crankshaft_version()
RETURNS text AS $$
  SELECT '@@VERSION@@'::text;
$$ language 'sql' STABLE STRICT;

-- Internal identifier of the installed extension instence
-- e.g. 'dev' for current development version
CREATE OR REPLACE FUNCTION _cdb_crankshaft_internal_version()
RETURNS text AS $$
  SELECT installed_version FROM pg_available_extensions where name='crankshaft' and pg_available_extensions IS NOT NULL;
$$ language 'sql' STABLE STRICT;


CREATE VIEW [DashboardReporting].[ApprenticeshipsWithNoEmail]
	AS
SELECT
	C.EmployerAndProviderApprovedOn AS ApprovedOn,
	A.Id AS ApprenticeshipId
FROM Apprenticeship A
INNER JOIN Commitment C ON A.CommitmentId = C.Id
WHERE A.IsApproved = 1 AND C.EmployerAndProviderApprovedOn >= '2000-09-10' AND A.Email IS NULL
GO

Fix query to count apprenticeships with missing email addresses

CREATE VIEW [DashboardReporting].[ApprenticeshipsWithNoEmail]
	AS
SELECT
	C.EmployerAndProviderApprovedOn AS ApprovedOn,
	A.Id AS ApprenticeshipId
FROM Apprenticeship A
INNER JOIN Commitment C ON A.CommitmentId = C.Id
WHERE A.IsApproved = 1 AND C.EmployerAndProviderApprovedOn >= '2021-09-10' AND A.Email IS NULL AND A.ContinuationOfId IS NULL
GO


CREATE EXTENSION hstore;

CREATE TABLE users (
    email text PRIMARY KEY
);

CREATE TABLE identities (
    id integer PRIMARY KEY,
    token text UNIQUE
);

CREATE TABLE servers (
    id integer NOT NULL,
    hostname text NOT NULL,
    port integer NOT NULL,
    ssl boolean NOT NULL
);

CREATE TABLE channels (
    user_email text references users(email),
    name text NOT NULL,
    server_id integer NOT NULL,
    enabled boolean DEFAULT true NOT NULL,
    key text,
    topic text,
    users hstore DEFAULT hstore(array[]::text[]),
    PRIMARY KEY (user_email, name)
);

CREATE TABLE events (
    id integer NOT NULL,
    server_id integer references servers(id),
    source integer references identities(id),
    target integer references identities(id),
    args text[],
    "timestamp" timestamp with time zone DEFAULT now() NOT NULL,
    observer_email text references users(email),
    kind text DEFAULT 'privmsg'::text,
    PRIMARY KEY (id, observer_id, server_id)
);

CREATE TABLE server_configs (
    user_email integer references users(email),
    server_id integer references servers(id),
    nick text NOT NULL,
    enabled boolean DEFAULT false NOT NULL,
    PRIMARY KEY (user_email, server_id)
);

Fix server_configs.user_email's type in the setup SQL.

CREATE EXTENSION hstore;

CREATE TABLE users (
    email text PRIMARY KEY
);

CREATE TABLE identities (
    id integer PRIMARY KEY,
    token text UNIQUE
);

CREATE TABLE servers (
    id integer NOT NULL,
    hostname text NOT NULL,
    port integer NOT NULL,
    ssl boolean NOT NULL
);

CREATE TABLE channels (
    user_email text references users(email),
    name text NOT NULL,
    server_id integer NOT NULL,
    enabled boolean DEFAULT true NOT NULL,
    key text,
    topic text,
    users hstore DEFAULT hstore(array[]::text[]),
    PRIMARY KEY (user_email, name)
);

CREATE TABLE events (
    id integer NOT NULL,
    server_id integer references servers(id),
    source integer references identities(id),
    target integer references identities(id),
    args text[],
    "timestamp" timestamp with time zone DEFAULT now() NOT NULL,
    observer_email text references users(email),
    kind text DEFAULT 'privmsg'::text,
    PRIMARY KEY (id, observer_id, server_id)
);

CREATE TABLE server_configs (
    user_email text references users(email),
    server_id integer references servers(id),
    nick text NOT NULL,
    enabled boolean DEFAULT false NOT NULL,
    PRIMARY KEY (user_email, server_id)
);


-- Sample database schema for tourbillon
CREATE TABLE IF NOT EXISTS jobs (
    id VARCHAR PRIMARY KEY,
    data TEXT
);

CREATE TABLE IF NOT EXISTS workflows (
    id VARCHAR PRIMARY KEY,
    data TEXT
);

CREATE TABLE IF NOT EXISTS accounts (
    id VARCHAR PRIMARY KEY,
    data TEXT
);

CREATE TABLE IF NOT EXISTS templates (
    id VARCHAR PRIMARY KEY,
    data TEXT
);

CREATE TABLE IF NOT EXISTS kv (
    key VARCHAR PRIMARY KEY,
    value TEXT
);

CREATE TABLE IF NOT EXISTS events (
    id VARCHAR,
    job_id VARCHAR,
    "start" BIGINT NOT NULL,
    "interval" INT NULL,
    data TEXT,
    is_expired BOOLEAN NOT NULL DEFAULT false,
    PRIMARY KEY (id, job_id, "start")
);

CREATE INDEX events_active_events_start
ON events ("start", is_expired);

Remove kv table from postgres ddl script

-- Sample database schema for tourbillon
CREATE TABLE IF NOT EXISTS jobs (
    id VARCHAR PRIMARY KEY,
    data TEXT
);

CREATE TABLE IF NOT EXISTS workflows (
    id VARCHAR PRIMARY KEY,
    data TEXT
);

CREATE TABLE IF NOT EXISTS accounts (
    id VARCHAR PRIMARY KEY,
    data TEXT
);

CREATE TABLE IF NOT EXISTS templates (
    id VARCHAR PRIMARY KEY,
    data TEXT
);

CREATE TABLE IF NOT EXISTS events (
    id VARCHAR,
    job_id VARCHAR,
    "start" BIGINT NOT NULL,
    "interval" INT NULL,
    data TEXT,
    is_expired BOOLEAN NOT NULL DEFAULT false,
    PRIMARY KEY (id, job_id, "start")
);

CREATE INDEX events_active_events_start
ON events ("start", is_expired);


CREATE DATABASE weather;
USE weather;

CREATE TABLE `results` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `latitude` decimal(11,8) NOT NULL,
  `longitude` decimal(11,8) NOT NULL,
  `summary` varchar(50) NOT NULL,
  `temperature` decimal(3,2) NOT NULL,
  `units` varchar(5) NOT NULL,
  `icon` enum('clear-day','clear-night','rain','snow','sleet','wind','fog','cloudy','partly-cloudy-day','or partly-cloudy-night') NOT NULL,
  `created_on` int(10) unsigned NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

Optimize database table field lengths

CREATE DATABASE weather;
USE weather;

CREATE TABLE `results` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `latitude` decimal(7,4) NOT NULL,
  `longitude` decimal(7,4) NOT NULL,
  `summary` varchar(50) NOT NULL,
  `temperature` decimal(5,2) NOT NULL,
  `units` enum('auto','ca','uk2','us','si') NOT NULL,
  `icon` enum('clear-day','clear-night','rain','snow','sleet','wind','fog','cloudy','partly-cloudy-day','partly-cloudy-night') NOT NULL,
  `created_on` int(10) unsigned NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;


ALTER TABLE `previews`
    DROP FOREIGN KEY `previews_ibfk_1`,
    DROP FOREIGN KEY `previews_ibfk_2`,
    DROP INDEX `previews_ibfk_2`,
    CHANGE COLUMN `modified` `modified` DATETIME (6) NOT NULL,
    CHANGE COLUMN `id` `id` INT (10) UNSIGNED NOT NULL AUTO_INCREMENT,
    CHANGE COLUMN `addon_id` `addon_id` INT (10) UNSIGNED NOT NULL,
    CHANGE COLUMN `caption` `caption` INT (10) UNSIGNED DEFAULT NULL,
    CHANGE COLUMN `position` `position` INT (11) NOT NULL,
    CHANGE COLUMN `created` `created` DATETIME (6) NOT NULL,
    ADD INDEX `previews_caption_f5d9791a_fk_translations_id` (`caption`),
    ADD INDEX `previews_addon_id_320f2325_fk_addons_id` (`addon_id`),
    ADD UNIQUE INDEX `caption` (`caption`),
    ADD CONSTRAINT `previews_addon_id_320f2325_fk_addons_id` FOREIGN KEY (`addon_id`) REFERENCES `addons` (`id`),
    ADD CONSTRAINT `previews_caption_f5d9791a_fk_translations_id` FOREIGN KEY (`caption`) REFERENCES `translations` (`id`);

Add UPDATE statement to fix broken data in preview table

/* There are some old entries in previews which have a caption that point to non-existant translations, need to NULL the captions them to add the missing constraint */
UPDATE `previews`
    LEFT JOIN `translations` ON `previews`.`caption` = `translations`.`id`
    SET `previews`.`caption`=NULL
    WHERE `translations`.`id` IS NULL AND `previews`.`caption` IS NOT NULL;

ALTER TABLE `previews`
    DROP FOREIGN KEY `previews_ibfk_1`,
    DROP FOREIGN KEY `previews_ibfk_2`,
    DROP INDEX `previews_ibfk_2`,
    CHANGE COLUMN `modified` `modified` DATETIME (6) NOT NULL,
    CHANGE COLUMN `id` `id` INT (10) UNSIGNED NOT NULL AUTO_INCREMENT,
    CHANGE COLUMN `addon_id` `addon_id` INT (10) UNSIGNED NOT NULL,
    CHANGE COLUMN `caption` `caption` INT (10) UNSIGNED DEFAULT NULL,
    CHANGE COLUMN `position` `position` INT (11) NOT NULL,
    CHANGE COLUMN `created` `created` DATETIME (6) NOT NULL,
    ADD INDEX `previews_caption_f5d9791a_fk_translations_id` (`caption`),
    ADD INDEX `previews_addon_id_320f2325_fk_addons_id` (`addon_id`),
    ADD UNIQUE INDEX `caption` (`caption`),
    ADD CONSTRAINT `previews_addon_id_320f2325_fk_addons_id` FOREIGN KEY (`addon_id`) REFERENCES `addons` (`id`),
    ADD CONSTRAINT `previews_caption_f5d9791a_fk_translations_id` FOREIGN KEY (`caption`) REFERENCES `translations` (`id`);


GRANT EXECUTE ON FUNCTION cdb_dataservices_client._DST_PrepareTableOBS_GetMeasure(output_table_name text, function_name text, params json) TO publicuser;
GRANT EXECUTE ON FUNCTION cdb_dataservices_client._DST_PopulateTableOBS_GetMeasure(table_name text, output_table_name text, function_name text, params json) TO publicuser;

Update grants for new signatures

GRANT EXECUTE ON FUNCTION cdb_dataservices_client._DST_PrepareTableOBS_GetMeasure(output_table_name text, params json) TO publicuser;
GRANT EXECUTE ON FUNCTION cdb_dataservices_client._DST_PopulateTableOBS_GetMeasure(table_name text, output_table_name text, params json) TO publicuser;


insert into Pizza_Base (id, name, description, active, price) VALUES (1, 'Thin', 'Thin and crispy base', 1, 3.75);
insert into Pizza_Base (id, name, description, active, price) VALUES (2, 'Big dough', 'More dough', 1, 5.75);

insert into Topping (id, name, description, active, price) VALUES (1, 'Mozzarella', 'Mozzarella di buffala, it''s great!', 1, 1.50);
insert into Topping (id, name, description, active, price) VALUES (2, 'Tomato', 'Red and nice addition', 1, 1.50);

Add more bases and toppings

insert into Pizza_Base (id, name, description, active, price) VALUES (1, 'Thin and small', 'Thin and crispy base', 1, 3.75);
insert into Pizza_Base (id, name, description, active, price) VALUES (2, 'Thin and wide', 'Your preferred crust but bigger', 1, 4.95);
insert into Pizza_Base (id, name, description, active, price) VALUES (3, 'Fully loaded', 'More dough, bigger, BETTER!', 1, 8.50);

insert into Topping (id, name, description, active, price) VALUES (1, 'Mozzarella', 'Mozzarella di buffala, it''s great!', 1, 1.50);
insert into Topping (id, name, description, active, price) VALUES (2, 'Tomato', 'Red and nice addition', 1, 1.50);
insert into Topping (id, name, description, active, price) VALUES (3, 'Peppers', 'Good for you', 1, 1.50);
insert into Topping (id, name, description, active, price) VALUES (4, 'Onion', 'More flavour', 1, 1.50);
insert into Topping (id, name, description, active, price) VALUES (5, 'Mushrooms', 'More flavour', 1, 1.50);
insert into Topping (id, name, description, active, price) VALUES (6, 'Sweetcorn', 'More flavour', 1, 1.50);
insert into Topping (id, name, description, active, price) VALUES (7, 'Chicken', 'Get more meat!', 1, 2.50);
insert into Topping (id, name, description, active, price) VALUES (8, 'Pepperoni', 'Get more meat!', 1, 2.50);


select
  min(
    ifsapp.work_time_calendar_api.get_end_date(
      wc.calendar_id,
      ifsapp.work_time_calendar_api.get_end_time(
        wc.calendar_id,
        greatest(
          fc.start_work_day,
          ifsapp.work_time_calendar_api.get_end_date(
            wc.calendar_id,
            trunc(sysdate),
            :pre_ccr_buffer
          )
        ),
        :total_touch_time
      ),
      :post_ccr_buffer
    )
  ) best_end_date
from finiteload.free_capacity fc
join ifsapp.work_center wc
  on fc.contract = wc.contract
  and fc.work_center_no = wc.work_center_no
where fc.contract = :contract
  and fc.work_center_no = :work_center_no
  and fc.finish_work_day >=
    ifsapp.work_time_calendar_api.get_end_date(
      wc.calendar_id,
      trunc(sysdate),
      :pre_ccr_buffer
    )
  and fc.start_work_day <=
    ifsapp.work_time_calendar_api.get_start_time(
      wc.calendar_id,
      fc.finish_work_day,
      :total_touch_time
    )
  and ifsapp.work_time_calendar_api.get_end_date(
      wc.calendar_id,
      trunc(sysdate),
      :pre_ccr_buffer
    ) <=
    ifsapp.work_time_calendar_api.get_start_time(
      wc.calendar_id,
      fc.finish_work_day,
      :total_touch_time
    )

Simplify best end date query a little

select
  min(
    ifsapp.work_time_calendar_api.get_end_date(
      wc.calendar_id,
      ifsapp.work_time_calendar_api.get_end_time(
        wc.calendar_id,
        greatest(
          fc.start_work_day,
          ifsapp.work_time_calendar_api.get_end_date(
            wc.calendar_id,
            trunc(sysdate),
            :pre_ccr_buffer
          )
        ),
        :total_touch_time
      ),
      :post_ccr_buffer
    )
  ) best_end_date
from finiteload.free_capacity fc
join ifsapp.work_center wc
  on fc.contract = wc.contract
  and fc.work_center_no = wc.work_center_no
where fc.contract = :contract
  and fc.work_center_no = :work_center_no
  and fc.capacity_available >= :total_touch_time
  and fc.finish_work_day >=
    ifsapp.work_time_calendar_api.get_end_date(
      wc.calendar_id,
      trunc(sysdate),
      :pre_ccr_buffer
    )
  and ifsapp.work_time_calendar_api.get_end_date(
      wc.calendar_id,
      trunc(sysdate),
      :pre_ccr_buffer
    ) <=
    ifsapp.work_time_calendar_api.get_start_time(
      wc.calendar_id,
      fc.finish_work_day,
      :total_touch_time
    )


-- complain if script is sourced in psql, rather than via CREATE EXTENSION
\echo Use "CREATE EXTENSION formatbase" to load this file. \quit

CREATE FUNCTION to_base(val bigint, base integer)
RETURNS text
LANGUAGE sql IMMUTABLE STRICT AS $$
  WITH cte AS (
    SELECT regexp_split_to_array(
      '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-',
      '') AS idx
  )
  SELECT regexp_replace(string_agg(idx[((val / pow(base, g))::int % base) + 1], ''), '^0+', '')
  FROM generate_series(63, 0, -1) AS g, cte
  WHERE base <= 64
$$;

CREATE FUNCTION as_base(bigint, integer)
RETURNS text
AS '$libdir/formatbase'
LANGUAGE C IMMUTABLE STRICT;

Update script to allow use with integers without a cast

-- complain if script is sourced in psql, rather than via CREATE EXTENSION
\echo Use "CREATE EXTENSION formatbase" to load this file. \quit

CREATE FUNCTION to_base(val bigint, base integer)
RETURNS text
LANGUAGE sql IMMUTABLE STRICT AS $$
  WITH cte AS (
    SELECT regexp_split_to_array(
      '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-',
      '') AS idx
  )
  SELECT regexp_replace(string_agg(idx[((val / pow(base, g))::int % base) + 1], ''), '^0+', '')
  FROM generate_series(63, 0, -1) AS g, cte
  WHERE base <= 64
$$;

CREATE FUNCTION to_base(val integer, base integer)
RETURNS text
LANGUAGE sql IMMUTABLE STRICT AS $$
  SELECT to_base(val::bigint, base);
$$;

CREATE FUNCTION as_base(bigint, integer)
RETURNS text
AS '$libdir/formatbase'
LANGUAGE C IMMUTABLE STRICT;

CREATE FUNCTION as_base(val integer, base integer)
RETURNS text
LANGUAGE sql IMMUTABLE STRICT AS $$
  SELECT as_base(val::bigint, base);
$$;


select
	courses.code as course_code,
	courses.name as course_name,
	institutions.name as institution_name
from course_enrolled_students
inner join courses
	on course_enrolled_students.course = courses.id
inner join institutions
	on courses.institution = institutions.id
where
	person = '1'
order by courses.year, courses.autumn, courses.code;

Include semester in query for all enrolled courses.

select
	courses.code as course_code,
	courses.name as course_name,
	institutions.name as institution_name,
	CASE
		WHEN courses.autumn THEN 'Autumn'
		ELSE 'Spring'
	END || ', ' || courses.year as semester
from course_enrolled_students
inner join courses
	on course_enrolled_students.course = courses.id
inner join institutions
	on courses.institution = institutions.id
where
	person = '1'
order by courses.year, courses.autumn, courses.code;


ALTER TABLE `library` DROP FOREIGN KEY `Record`;||
ALTER TABLE `library` DROP INDEX `Label_idx`;||
ALTER TABLE `library` DROP COLUMN `labelid`;

Insert library label info into int table before dropping column

INSERT INTO library_recordlabel (SELECT RefCode, labelid FROM library);||
ALTER TABLE `library` DROP FOREIGN KEY `Record`;||
ALTER TABLE `library` DROP INDEX `Label_idx`;||
ALTER TABLE `library` DROP COLUMN `labelid`;


SET work_mem TO '256MB';

INSERT INTO rnacen.rnc_coordinates AS t1 (
  accession,
  name,
  local_start,
  local_end,
  strand,
  assembly_id,
  id
)
SELECT
  load.accession,
  load.chromosome,
  load.local_start,
  load.local_end,
  load.strand,
  assembly.assembly_id,
  NEXTVAL('rnc_coordinates_pk_seq')
FROM rnacen.load_rnc_coordinates as load
join ensembl_assembly assembly
on
    assembly.assembly_id = load.assembly_id
WHERE
  load.chromosome is not null
ON CONFLICT (accession, name, local_start, local_end, assembly_id)
DO NOTHING
;

Add update to primary locations

SET work_mem TO '256MB';

INSERT INTO rnacen.rnc_coordinates AS t1 (
  accession,
  name,
  local_start,
  local_end,
  strand,
  assembly_id,
  id
)
SELECT
  load.accession,
  load.chromosome,
  load.local_start,
  load.local_end,
  load.strand,
  assembly.assembly_id,
  NEXTVAL('rnc_coordinates_pk_seq')
FROM rnacen.load_rnc_coordinates as load
join ensembl_assembly assembly
on
    assembly.assembly_id = load.assembly_id
WHERE
  load.chromosome is not null
ON CONFLICT (accession, name, local_start, local_end, assembly_id)
DO NOTHING
;

update rnc_coordinates coord
set
  primary_start = coord.local_start,
  primary_end = coord.local_end
from rnc_accessions acc
where
  acc.accession = coord.accession
  and coord.primary_start is null
  and coord.primary_end is null
  and acc."database" in ('ENSEMBL', 'GENCODE', 'LNCIPEDIA', 'E_PLANTS')
;


OPTIONS
compile yes
merge trees.all.pak

Add comment (just a test commit!)

OPTIONS
compile yes
merge trees.all.pak
# There's relatively little sense in allowing users to manipulate single trees, usually they are only all deleted for network games.


-- Table definitions for the tournament project.
--
-- Put your SQL 'create table' statements in this file; also 'create view'
-- statements if you choose to use it.
--
-- You can write comments in this file by starting them with two dashes, like
-- these lines here.

Add table schema for players and matches

-- Table definitions for the tournament project.
--
-- Put your SQL 'create table' statements in this file; also 'create view'
-- statements if you choose to use it.
--
-- You can write comments in this file by starting them with two dashes, like
-- these lines here.

CREATE TABLE players (
    id SERIAL PRIMARY KEY,
    name TEXT
)

CREATE TABLE matches (
    id SERIAL PRIMARY KEY,
    winner INT,
    loser INT,
    FOREIGN KEY (winner, loser) REFERENCES players (id, id)
)

-- Extra credit
-- CREATE TABLE tournaments (
--     id SERIAL PRIMARY KEY,
--     name TEXT
-- )


-- create database
CREATE DATABASE amy WITH OWNER postgres;

-- create database user (read/write)
CREATE USER amy WITH
    LOGIN
    PASSWORD 'secret password'
    NOSUPERUSER
    INHERIT
    NOCREATEDB
    NOCREATEROLE
    NOREPLICATION
    VALID UNTIL 'infinity';

-- create database user (read/only)
CREATE USER amy_ro WITH
    LOGIN
    PASSWORD 'secret password'
    NOSUPERUSER
    INHERIT
    NOCREATEDB
    NOCREATEROLE
    NOREPLICATION
    VALID UNTIL 'infinity';

-- roles and permissions
GRANT TEMPORARY ON DATABASE amy TO amy;
GRANT TEMPORARY ON DATABASE amy TO amy_ro;
GRANT ALL ON DATABASE amy TO postgres;
GRANT amy TO postgres;
GRANT amy_ro TO postgres;

GRANT ALL ON SCHEMA public TO amy;
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON TABLES to amy;
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON SEQUENCES to amy;

GRANT USAGE ON SCHEMA public TO amy_ro;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO amy_ro;
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO amy_ro;

Extend R/O privileges in PostgreSQL

-- create database
CREATE DATABASE amy WITH OWNER postgres;

-- create database user (read/write)
CREATE USER amy WITH
    LOGIN
    PASSWORD 'secret password'
    NOSUPERUSER
    INHERIT
    NOCREATEDB
    NOCREATEROLE
    NOREPLICATION
    VALID UNTIL 'infinity';

-- create database user (read/only)
CREATE USER amy_ro WITH
    LOGIN
    PASSWORD 'secret password'
    NOSUPERUSER
    INHERIT
    NOCREATEDB
    NOCREATEROLE
    NOREPLICATION
    VALID UNTIL 'infinity';

-- roles and permissions
GRANT TEMPORARY ON DATABASE amy TO amy;
GRANT TEMPORARY ON DATABASE amy TO amy_ro;
GRANT ALL ON DATABASE amy TO postgres;
GRANT amy TO postgres;
GRANT amy_ro TO postgres;

GRANT ALL ON SCHEMA public TO amy;
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON TABLES to amy;
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON SEQUENCES to amy;

GRANT USAGE ON SCHEMA public TO amy_ro;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO amy_ro;
GRANT SELECT ON ALL SEQUENCES IN SCHEMA public TO amy_ro;
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO amy_ro;
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON SEQUENCES to amy_ro;


#2.5.0

CREATE TABLE IF NOT EXISTS `#__improvemycity_timestamp` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  `triggered` varchar(255),
  PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=0 DEFAULT COLLATE=utf8_general_ci;

INSERT INTO `#__improvemycity_timestamp` (`triggered`) VALUES (MD5(RAND()));

Fix autoupdate create new table

#2.5.0
DROP TABLE IF EXISTS `#__improvemycity_timestamp`;
CREATE TABLE `#__improvemycity_timestamp` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  `triggered` varchar(255),
  PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=0 DEFAULT COLLATE=utf8_general_ci;
INSERT INTO `#__improvemycity_timestamp` (`triggered`) VALUES (MD5(RAND()));


--
-- Time Warsong Gulch
--
INSERT INTO `ascemu_world`.`worldstate_templates` (`map`, `zone`, `field`, `value`) VALUES (489, 3277, 4247, 1);
INSERT INTO `ascemu_world`.`worldstate_templates` (`map`, `zone`, `field`, `value`) VALUES (489, 3277, 4248, 25);

--
-- Update world db version
--
UPDATE `world_db_version` SET `LastUpdate` = '2016-01-30_01_time_warsong' WHERE `LastUpdate` = '2016-01-25_02_loot_creatures';

Use REPLACE INTO (maybe the new rows already exist) Removed db specification.

--
-- Time Warsong Gulch
--
REPLACE INTO `worldstate_templates` (`map`, `zone`, `field`, `value`) VALUES (489, 3277, 4247, 1);
REPLACE INTO `worldstate_templates` (`map`, `zone`, `field`, `value`) VALUES (489, 3277, 4248, 25);

--
-- Update world db version
--
UPDATE `world_db_version` SET `LastUpdate` = '2016-01-30_01_time_warsong' WHERE `LastUpdate` = '2016-01-25_02_loot_creatures';


CREATE TABLE projects (
    id serial PRIMARY KEY,
    keys text[]
);

CREATE TABLE documents (
    id serial PRIMARY KEY,
    locale varchar(128),
    pairs hstore,
    project_id integer REFERENCES projects (id) ON DELETE CASCADE
);

Add locale not empty contraint

CREATE TABLE projects (
    id serial PRIMARY KEY,
    keys text[]
);

CREATE TABLE documents (
    id serial PRIMARY KEY,
    locale varchar(128) NOT NULL CHECK (locale <> ''),
    pairs hstore,
    project_id integer REFERENCES projects (id) ON DELETE CASCADE
);


-- Upgrade: schema_version 9 to 10
--

ALTER TABLE patches DROP COLUMN content_SHA1;
DROP TABLE patch_contents;

UPDATE schema_version SET version_nbr = 10;

Fix "null null" user names during schema upgrade from 9 to 10

-- Upgrade: schema_version 9 to 10
--

ALTER TABLE patches DROP COLUMN content_SHA1;
DROP TABLE patch_contents;

UPDATE accounts SET full_name = NULL WHERE full_name = 'null null';

UPDATE schema_version SET version_nbr = 10;


CREATE TABLE IF NOT EXISTS lddb (
    id text not null unique primary key,
    data jsonb not null,
    collection text not null,
    changedIn text not null,
    changedBy text,
    checksum text not null,
    created timestamp with time zone not null default now(),
    modified timestamp with time zone not null default now(),
    deleted boolean default false,
    depMinModified timestamp with time zone not null default now(),
    depMaxModified timestamp with time zone not null default now()
    );

CREATE TABLE IF NOT EXISTS lddb__identifiers (
    pk serial,
    id text not null,
    iri text not null,
    graphIndex integer,
    mainId boolean not null
);

CREATE TABLE IF NOT EXISTS lddb__dependencies (
    pk serial,
    id text not null,
    dependsOnId text not null
);

CREATE TABLE IF NOT EXISTS lddb__versions (
    pk serial,
    id text not null,
    data jsonb not null,
    collection text not null,
    changedIn text not null,
    changedBy text,
    checksum text not null,
    modified timestamp with time zone not null default now(),
    deleted boolean default false,
    unique (id, checksum, modified)
    );

CREATE TABLE IF NOT EXISTS lddb__settings (
    key text not null unique primary key,
    settings jsonb not null
);

Add table for export profiles.

CREATE TABLE IF NOT EXISTS lddb (
    id text not null unique primary key,
    data jsonb not null,
    collection text not null,
    changedIn text not null,
    changedBy text,
    checksum text not null,
    created timestamp with time zone not null default now(),
    modified timestamp with time zone not null default now(),
    deleted boolean default false,
    depMinModified timestamp with time zone not null default now(),
    depMaxModified timestamp with time zone not null default now()
    );

CREATE TABLE IF NOT EXISTS lddb__identifiers (
    pk serial,
    id text not null,
    iri text not null,
    graphIndex integer,
    mainId boolean not null
);

CREATE TABLE IF NOT EXISTS lddb__dependencies (
    pk serial,
    id text not null,
    dependsOnId text not null
);

CREATE TABLE IF NOT EXISTS lddb__versions (
    pk serial,
    id text not null,
    data jsonb not null,
    collection text not null,
    changedIn text not null,
    changedBy text,
    checksum text not null,
    modified timestamp with time zone not null default now(),
    deleted boolean default false,
    unique (id, checksum, modified)
    );

CREATE TABLE IF NOT EXISTS lddb__settings (
    key text not null unique primary key,
    settings jsonb not null
);

CREATE TABLE IF NOT EXISTS lddb__profiles (
    library_id text not null unique primary key,
    profile text not null
);


# Move current id to hash column
ALTER TABLE `vocabulary` ADD hash BINARY(16) NOT NULL;
UPDATE `vocabulary` SET hash = id;

# Change id to auto-increment int
ALTER TABLE `vocabulary` DROP PRIMARY KEY;
UPDATE vocabulary SET id = 0;
ALTER TABLE `vocabulary` MODIFY id int(11) NOT NULL PRIMARY KEY AUTO_INCREMENT;

# Update users_vocabulary vocabulary_id column
ALTER TABLE `users_vocabulary` CHANGE vocabulary_id hash binary(16) NOT NULL;
ALTER TABLE `users_vocabulary` ADD vocabulary_id int(11) NOT NULL;
UPDATE `users_vocabulary`
    LEFT OUTER JOIN `vocabulary` ON(vocabulary.hash=users_vocabulary.hash)
    SET vocabulary_id = vocabulary.id;

Fix unique key for users_vocabulary

# Move current id to hash column
ALTER TABLE `vocabulary` ADD hash BINARY(16) NOT NULL;
UPDATE `vocabulary` SET hash = id;

# Change id to auto-increment int
ALTER TABLE `vocabulary` DROP PRIMARY KEY;
UPDATE vocabulary SET id = 0;
ALTER TABLE `vocabulary` MODIFY id int(11) NOT NULL PRIMARY KEY AUTO_INCREMENT;

# Update users_vocabulary vocabulary_id column
ALTER TABLE `users_vocabulary` CHANGE vocabulary_id hash binary(16) NOT NULL;
ALTER TABLE `users_vocabulary` ADD vocabulary_id int(11) NOT NULL;
UPDATE `users_vocabulary`
    LEFT OUTER JOIN `vocabulary` ON(vocabulary.hash=users_vocabulary.hash)
    SET vocabulary_id = vocabulary.id;

# Update index
ALTER TABLE users_vocabulary DROP INDEX user_vocabulary;
ALTER TABLE users_vocabulary ADD UNIQUE KEY `user_vocabulary` (`user_id`,`vocabulary_id`);


CREATE TYPE role AS ENUM ('user', 'admin');

CREATE TABLE users (
  id              SERIAL PRIMARY KEY,
  email           VARCHAR(255) NOT NULL,
  password_digest VARCHAR(255) NOT NULL,
  remember_token  VARCHAR(255) NOT NULL,
  role            role         NOT NULL DEFAULT 'user',
  created_at      TIMESTAMPTZ  NOT NULL DEFAULT now(),
  updated_at      TIMESTAMPTZ  NOT NULL DEFAULT now()
);

CREATE UNIQUE INDEX idx__users__email
  ON users (email);

CREATE UNIQUE INDEX idx__users__remember_token
  ON users (remember_token);

Change users table migration a bit

CREATE TABLE users (
  id              SERIAL PRIMARY KEY,
  email           VARCHAR(255) NOT NULL,
  password_digest VARCHAR(255) NOT NULL,
  remember_token  VARCHAR(255) NOT NULL,
  role            VARCHAR(255) NOT NULL DEFAULT 'user',
  created_at      TIMESTAMPTZ  NOT NULL DEFAULT now(),
  updated_at      TIMESTAMPTZ  NOT NULL DEFAULT now()
);

CREATE UNIQUE INDEX idx__users__email
  ON users (email);

CREATE UNIQUE INDEX idx__users__remember_token
  ON users (remember_token);


-- run as a cronjob: psql packages -f tools/daily.sql -o /dev/null
delete from cookies where last_seen < now()-INTERVAL'1day';
delete from openid_sessions where expires < now();
delete from openid_nonces where created < now()-INTERVAL'1day';
delete from users where name in (select name from rego_otk where date < now()-INTERVAL'7days');

Delete openids of expired users.

-- run as a cronjob: psql packages -f tools/daily.sql -o /dev/null
delete from cookies where last_seen < now()-INTERVAL'1day';
delete from openid_sessions where expires < now();
delete from openid_nonces where created < now()-INTERVAL'1day';
delete from openids where name in (select name from rego_otk where date < now()-INTERVAL'7days');
delete from users where name in (select name from rego_otk where date < now()-INTERVAL'7days');


-- avoid innocuous NOTICEs about automatic sequence creation
set client_min_messages='WARNING';

-- Tell psql to stop on an error. Default behavior is to proceed.
\set ON_ERROR_STOP 1

-- Tables for the KM

-- ----------------------------------------------------------------------
DROP TABLE IF EXISTS km_asserted_attribute;

CREATE TABLE km_asserted_attribute (
  id SERIAL PRIMARY KEY,
  eppn VARCHAR NOT NULL,
  name VARCHAR NOT NULL,
  value VARCHAR NOT NULL,
  asserter_id UUID,
  created timestamp DEFAULT NOW() AT TIME ZONE 'UTC'
);

CREATE INDEX km_asserted_attribute_eppn ON km_asserted_attribute (eppn);

Fix a SQL syntax error

-- avoid innocuous NOTICEs about automatic sequence creation
set client_min_messages='WARNING';

-- Tell psql to stop on an error. Default behavior is to proceed.
\set ON_ERROR_STOP 1

-- Tables for the KM

-- ----------------------------------------------------------------------
DROP TABLE IF EXISTS km_asserted_attribute;

CREATE TABLE km_asserted_attribute (
  id SERIAL PRIMARY KEY,
  eppn VARCHAR NOT NULL,
  name VARCHAR NOT NULL,
  value VARCHAR NOT NULL,
  asserter_id UUID,
  created timestamp DEFAULT (NOW() AT TIME ZONE 'UTC')
);

CREATE INDEX km_asserted_attribute_eppn ON km_asserted_attribute (eppn);


CREATE OR REPLACE FUNCTION ddl_tools.schema__drop(
    schema_name name
) RETURNS void LANGUAGE plpgsql SET client_min_messages = 'DEBUG' AS $body$
DECLARE
  prefix name;
BEGIN
  FOREACH prefix IN ARRAY '{"",_,_test_,_test__}'::name[] LOOP
    PERFORM ddl_tools.exec( format( 'DROP SCHEMA IF EXISTS %I', prefix || schema_name ) );
  END LOOP;
END
$body$;

-- vi: expandtab ts=2 sw=2

Change log level back to warning

CREATE OR REPLACE FUNCTION ddl_tools.schema__drop(
    schema_name name
) RETURNS void LANGUAGE plpgsql SET client_min_messages = 'WARNING' AS $body$
DECLARE
  prefix name;
BEGIN
  FOREACH prefix IN ARRAY '{"",_,_test_,_test__}'::name[] LOOP
    PERFORM ddl_tools.exec( format( 'DROP SCHEMA IF EXISTS %I', prefix || schema_name ) );
  END LOOP;
END
$body$;

-- vi: expandtab ts=2 sw=2


-- :name create-profile :<! :1
-- :doc Create a new user entry.
insert into users (id, fullname, username, email, password, metadata)
  values (:id, :fullname, :username, :email, :password, :metadata)
  returning *;

-- :name get-profile :? :1
-- :doc Retrieve the profile data.
select * from users
  where id = :id and deleted = false;

-- :name get-profile-by-username :? :1
-- :doc Retrieve the profile data.
select * from users
  where (username = :username or email = :username)
        and deleted = false;

-- :name update-profile :<! :1
-- :doc Update profile.
update users set username = :username,
                 email = :email,
                 fullname = :fullname,
                 metadata = :metadata
  where id = :id and deleted = false
  returning *;

-- :name update-profile-password :! :n
-- :doc Update profile password
update users set password = :password
  where id = :id and deleted = false;

Add update user photo sql function.

-- :name create-profile :<! :1
insert into users (id, fullname, username, email, password, metadata, photo)
values (:id, :fullname, :username, :email, :password, :metadata, '')
returning *;

-- :name get-profile :? :1
select * from users
 where id = :id and deleted = false;

-- :name get-profile-by-username :? :1
select * from users
 where (username = :username or email = :username)
   and deleted = false;

-- :name update-profile :<! :1
update users
   set username = :username,
       email = :email,
       fullname = :fullname,
       metadata = :metadata
 where id = :id and deleted = false
returning *;

-- :name update-profile-password :! :n
update users set password = :password
 where id = :id and deleted = false;

-- :name update-profile-photo :! :n
update users set photo = :photo
 where id = :id and deleted = false;


BEGIN;

ALTER TABLE activity_stream_stats_daily ADD COLUMN date DATE;
UPDATE activity_stream_stats_daily SET date = TRUNC(receive_at);
ALTER TABLE activity_stream_stats_daily ALTER COLUMN date SET NOT NULL;

ALTER TABLE activity_stream_stats_daily ADD COLUMN page VARCHAR(16) NOT NULL;

ALTER TABLE activity_stream_stats_daily DROP COLUMN click_position;

ALTER TABLE activity_stream_stats_daily DROP COLUMN source;

CREATE TABLE activity_stream_events_daily (
    client_id VARCHAR(64) NOT NULL,
    tab_id VARCHAR(64) NOT NULL,
    addon_version VARCHAR(16) NOT NULL,
    source VARCHAR(64) NOT NULL,
    page VARCHAR(16) NOT NULL,
    action_position VARCHAR(16) NOT NULL,
    event VARCHAR(16) NOT NULL,
    receive_at TIMESTAMP WITHOUT TIME ZONE NOT NULL,
    date DATE NOT NULL,
    locale VARCHAR(14) NOT NULL,
    country_code VARCHAR(5) NOT NULL,
    os VARCHAR(64) NOT NULL,
    browser VARCHAR(64) NOT NULL,
    version VARCHAR(64) NOT NULL,
    device VARCHAR(64) NOT NULL
);

COMMIT;

Fix the migration SQL script for Redshift

BEGIN;

ALTER TABLE activity_stream_stats_daily ADD COLUMN date DATE DEFAULT CURRENT_DATE NOT NULL;
UPDATE activity_stream_stats_daily SET date = TRUNC(receive_at);

ALTER TABLE activity_stream_stats_daily ADD COLUMN page VARCHAR(16) DEFAULT 'newtab' NOT NULL;

ALTER TABLE activity_stream_stats_daily DROP COLUMN click_position;

ALTER TABLE activity_stream_stats_daily DROP COLUMN source;

CREATE TABLE activity_stream_events_daily (
    client_id VARCHAR(64) NOT NULL,
    tab_id VARCHAR(64) NOT NULL,
    addon_version VARCHAR(16) NOT NULL,
    source VARCHAR(64) NOT NULL,
    page VARCHAR(16) NOT NULL,
    action_position VARCHAR(16) NOT NULL,
    event VARCHAR(16) NOT NULL,
    receive_at TIMESTAMP WITHOUT TIME ZONE NOT NULL,
    date DATE NOT NULL,
    locale VARCHAR(14) NOT NULL,
    country_code VARCHAR(5) NOT NULL,
    os VARCHAR(64) NOT NULL,
    browser VARCHAR(64) NOT NULL,
    version VARCHAR(64) NOT NULL,
    device VARCHAR(64) NOT NULL
);

COMMIT;


CREATE EXTENSION IF NOT EXISTS "uuid-ossp";

CREATE TABLE traces(
trace_uuid uuid PRIMARY KEY,
transaction_uuid uuid,
origin_uuid uuid,
trace_name text,
start_time timestamp(6),
end_time timestamp(6),
meta jsonb
)

CREATE TABLE spans(
trace_uuid uuid,
span_name text,
start_time timestamp(6),
end_time timestamp(6),
meta jsonb,
FOREIGN KEY (trace_uuid) REFERENCES traces(trace_uuid)
)

Update db schema and add new table for application tracing

CREATE EXTENSION IF NOT EXISTS "uuid-ossp";

CREATE TABLE applications(
uuid uuid PRIMARY KEY DEFAULT uuid_generate_v4(),
name text,
original_name text
);

CREATE TABLE traces(
uuid uuid PRIMARY KEY,
transaction_uuid uuid,
origin_uuid uuid,
application_uuid uuid,
name text,
start_time timestamp(6),
end_time timestamp(6),
meta jsonb
);

CREATE TABLE spans(
trace_uuid uuid,
uuid uuid,
name text,
start_time timestamp(6),
end_time timestamp(6),
meta jsonb,
FOREIGN KEY (trace_uuid) REFERENCES traces(uuid)
);


CREATE TABLE users (
	id INTEGER PRIMARY KEY,
	user TEXT UNIQUE NOT NULL,
	mail TEXT,
	admin INTEGER NOT NULL
);
CREATE TABLE images (
	id INTEGER PRIMARY KEY,
	location TEXT NOT NULL,
	path TEXT NOT NULL,
	original_name TEXT NOT NULL,
	ip TEXT NOT NULL,
	time INTEGER NOT NULL,
	user INTEGER REFERENCES users(id),
	md5 VARCHAR(32) NOT NULL,
	uploadid VARCHAR(36),
	width INT NOT NULL,
	height INT NOT NULL,
	size INT NOT NULL
);
CREATE TABLE tags (
	id INTEGER PRIMARY KEY,
	tag TEXT UNIQUE NOT NULL,
	count INTEGER NOT NULL
);
CREATE TABLE imagetags (
	id INTEGER PRIMARY KEY,
	image INTEGER NOT NULL REFERENCES images(id),
	tag INTEGER NOT NULL REFERENCES tags(id)
);
CREATE UNIQUE INDEX idx_imagetags_image_tag ON imagetags(image,tag);

Use case-insensitive sorting for tags

CREATE TABLE users (
	id INTEGER PRIMARY KEY,
	user TEXT UNIQUE NOT NULL,
	mail TEXT,
	admin INTEGER NOT NULL
);
CREATE TABLE images (
	id INTEGER PRIMARY KEY,
	location TEXT NOT NULL,
	path TEXT NOT NULL,
	original_name TEXT NOT NULL,
	ip TEXT NOT NULL,
	time INTEGER NOT NULL,
	user INTEGER REFERENCES users(id),
	md5 VARCHAR(32) NOT NULL,
	uploadid VARCHAR(36),
	width INT NOT NULL,
	height INT NOT NULL,
	size INT NOT NULL
);
CREATE TABLE tags (
	id INTEGER PRIMARY KEY,
	tag TEXT UNIQUE NOT NULL COLLATE NOCASE,
	count INTEGER NOT NULL
);
CREATE TABLE imagetags (
	id INTEGER PRIMARY KEY,
	image INTEGER NOT NULL REFERENCES images(id),
	tag INTEGER NOT NULL REFERENCES tags(id)
);
CREATE UNIQUE INDEX idx_imagetags_image_tag ON imagetags(image,tag);


CREATE VIEW {# geotrek.signage #}.v_signages AS (
	SELECT e.geom, e.id, t.*
	FROM signage_signage AS t, signage_signagetype AS b, core_topology AS e
	WHERE t.topo_object_id = e.id AND t.type_id = b.id
	AND e.deleted = FALSE
);

Add UUID to signages view

CREATE VIEW {# geotrek.signage #}.v_signages AS (
	SELECT e.geom, e.id, e.uuid, t.*
	FROM signage_signage AS t, signage_signagetype AS b, core_topology AS e
	WHERE t.topo_object_id = e.id AND t.type_id = b.id
	AND e.deleted = FALSE
);


# Create a MySQL user with limited privileges for backup purposes.
# This isn't strictly necessary on a local machine - you could just use the root
# MySQL user in the backup script.
# ==============================================================================

# Get a MySQL/MariaDB prompt:
mysql -u root -p

# In the MySQL shell enter:
CREATE USER 'backup_user'@'localhost' IDENTIFIED BY 'CiCHVQ2o8TSCq31SbWhQBkmn6';
GRANT SELECT, SHOW VIEW, RELOAD, REPLICATION CLIENT, EVENT, TRIGGER ON *.* TO 'backup_user'@'localhost';
FLUSH PRIVILEGES;
SHOW GRANTS FOR 'backup_user'@'localhost';

Make MySQL user passwords match

# Create a MySQL user with limited privileges for backup purposes.
# This isn't strictly necessary on a local machine - you could just use the root
# MySQL user in the backup script.
# ==============================================================================

# Get a MySQL/MariaDB prompt:
mysql -u root -p

# In the MySQL shell enter:
CREATE USER 'backup_user'@'localhost' IDENTIFIED BY 'nicelongpassword';
GRANT SELECT, SHOW VIEW, RELOAD, REPLICATION CLIENT, EVENT, TRIGGER ON *.* TO 'backup_user'@'localhost';
FLUSH PRIVILEGES;
SHOW GRANTS FOR 'backup_user'@'localhost';


CREATE TABLE IF NOT EXISTS `posts_{{ board }}` (
  `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
  `thread` int(11) DEFAULT NULL,
  `subject` varchar(100) DEFAULT NULL,
  `email` varchar(30) DEFAULT NULL,
  `name` varchar(35) DEFAULT NULL,
  `trip` varchar(15) DEFAULT NULL,
  `capcode` varchar(50) DEFAULT NULL,
  `body` text NOT NULL,
  `body_nomarkup` text DEFAULT NULL,
  `time` int(11) NOT NULL,
  `bump` int(11) DEFAULT NULL,
  `thumb` varchar(50) DEFAULT NULL,
  `thumbwidth` int(11) DEFAULT NULL,
  `thumbheight` int(11) DEFAULT NULL,
  `file` varchar(50) DEFAULT NULL,
  `filewidth` int(11) DEFAULT NULL,
  `fileheight` int(11) DEFAULT NULL,
  `filesize` int(11) DEFAULT NULL,
  `filename` text DEFAULT NULL,
  `filehash` text DEFAULT NULL,
  `password` varchar(20) DEFAULT NULL,
  `ip` varchar(45) NOT NULL,
  `sticky` int(1) NOT NULL,
  `locked` int(1) NOT NULL,
  `sage` int(1) NOT NULL,
  `embed` text,
  UNIQUE KEY `id` (`id`),
  KEY `thread` (`thread`),
  KEY `time` (`time`),
  FULLTEXT KEY `body` (`body`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;

Add (`thread`, `id`) multi-column key to optimize rebuilding index pages.

CREATE TABLE IF NOT EXISTS `posts_{{ board }}` (
  `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
  `thread` int(11) DEFAULT NULL,
  `subject` varchar(100) DEFAULT NULL,
  `email` varchar(30) DEFAULT NULL,
  `name` varchar(35) DEFAULT NULL,
  `trip` varchar(15) DEFAULT NULL,
  `capcode` varchar(50) DEFAULT NULL,
  `body` text NOT NULL,
  `body_nomarkup` text DEFAULT NULL,
  `time` int(11) NOT NULL,
  `bump` int(11) DEFAULT NULL,
  `thumb` varchar(50) DEFAULT NULL,
  `thumbwidth` int(11) DEFAULT NULL,
  `thumbheight` int(11) DEFAULT NULL,
  `file` varchar(50) DEFAULT NULL,
  `filewidth` int(11) DEFAULT NULL,
  `fileheight` int(11) DEFAULT NULL,
  `filesize` int(11) DEFAULT NULL,
  `filename` text DEFAULT NULL,
  `filehash` text DEFAULT NULL,
  `password` varchar(20) DEFAULT NULL,
  `ip` varchar(45) NOT NULL,
  `sticky` int(1) NOT NULL,
  `locked` int(1) NOT NULL,
  `sage` int(1) NOT NULL,
  `embed` text,
  UNIQUE KEY `id` (`id`),
  KEY `thread` (`thread`),
  KEY `thread_id` (`thread`, `id`),
  KEY `time` (`time`),
  FULLTEXT KEY `body` (`body`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;


/*
 * Copyright 2022 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

WITH logins AS
(
SELECT
  timestamp,
  protopayload_auditlog.authenticationInfo.principalEmail,
  protopayload_auditlog.requestMetadata.callerIp,
  protopayload_auditlog.resourceName,
  JSON_QUERY_ARRAY(protopayload_auditlog.metadataJson, '$.event[0].parameter') AS parameters,
FROM `[MY_DATASET_ID].[MY_PROJECT_ID].cloudaudit_googleapis_com_data_access`
WHERE
  timestamp >= TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 60 DAY)
  AND protopayload_auditlog.serviceName = "login.googleapis.com"
  AND protopayload_auditlog.methodName LIKE "google.login.LoginService.loginSuccess"
)

SELECT
  timestamp, principalEmail, callerIp, resourceName
FROM logins
WHERE EXISTS(
  SELECT * FROM UNNEST(parameters) AS x
  WHERE
    JSON_VALUE(x, '$.name') = 'is_suspicious' AND JSON_VALUE(x, '$.boolValue') = 'false'
)

Simplify CSA 1.02 SQL query with UNNEST

/*
 * Copyright 2022 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

SELECT
  timestamp,
  protopayload_auditlog.authenticationInfo.principalEmail,
  protopayload_auditlog.requestMetadata.callerIp,
  protopayload_auditlog.methodName
FROM `[MY_PROJECT_ID].[MY_DATASET_ID].cloudaudit_googleapis_com_data_access`,
  UNNEST(JSON_QUERY_ARRAY(protopayload_auditlog.metadataJson, '$.event[0].parameter')) AS parameter
WHERE
  timestamp >= TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 60 DAY)
  AND protopayload_auditlog.metadataJson IS NOT NULL
  AND protopayload_auditlog.serviceName = "login.googleapis.com"
  AND protopayload_auditlog.methodName = "google.login.LoginService.loginSuccess"
  AND JSON_VALUE(parameter, '$.name') = "is_suspicious"
  AND JSON_VALUE(parameter, '$.boolValue') = "false"


ALTER TABLE share ADD latency_threshold NUMBER(*,0);

UPDATE share SET latency_threshold = 20;
COMMIT;
QUIT;

Fix the Oracle upgrade script

ALTER TABLE "share" ADD latency_threshold NUMBER(*,0);

UPDATE "share" SET latency_threshold = 20;
COMMIT;
QUIT;


-- Drop, copy & recreate pushers table to change unique key
-- Also add access_token column at the same time
CREATE TABLE IF NOT EXISTS pushers2 (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  user_name TEXT NOT NULL,
  access_token INTEGER DEFAULT NULL,
  profile_tag varchar(32) NOT NULL,
  kind varchar(8) NOT NULL,
  app_id varchar(64) NOT NULL,
  app_display_name varchar(64) NOT NULL,
  device_display_name varchar(128) NOT NULL,
  pushkey blob NOT NULL,
  ts BIGINT NOT NULL,
  lang varchar(8),
  data blob,
  last_token TEXT,
  last_success BIGINT,
  failing_since BIGINT,
  FOREIGN KEY(user_name) REFERENCES users(name),
  UNIQUE (app_id, pushkey, user_name)
);
INSERT INTO pushers2 (id, user_name, profile_tag, kind, app_id, app_display_name, device_display_name, pushkey, ts, lang, data, last_token, last_success, failing_since)
  SELECT id, user_name, profile_tag, kind, app_id, app_display_name, device_display_name, pushkey, ts, lang, data, last_token, last_success, failing_since FROM pushers;
DROP TABLE pushers;
ALTER TABLE pushers2 RENAME TO pushers;

Fix schema delta 15 on postgres in the very unlikley event that anyone upgrades to 15...

-- Drop, copy & recreate pushers table to change unique key
-- Also add access_token column at the same time
CREATE TABLE IF NOT EXISTS pushers2 (
  id BIGINT PRIMARY KEY,
  user_name TEXT NOT NULL,
  access_token INTEGER DEFAULT NULL,
  profile_tag varchar(32) NOT NULL,
  kind varchar(8) NOT NULL,
  app_id varchar(64) NOT NULL,
  app_display_name varchar(64) NOT NULL,
  device_display_name varchar(128) NOT NULL,
  pushkey blob NOT NULL,
  ts BIGINT NOT NULL,
  lang varchar(8),
  data blob,
  last_token TEXT,
  last_success BIGINT,
  failing_since BIGINT,
  FOREIGN KEY(user_name) REFERENCES users(name),
  UNIQUE (app_id, pushkey, user_name)
);
INSERT INTO pushers2 (id, user_name, profile_tag, kind, app_id, app_display_name, device_display_name, pushkey, ts, lang, data, last_token, last_success, failing_since)
  SELECT id, user_name, profile_tag, kind, app_id, app_display_name, device_display_name, pushkey, ts, lang, data, last_token, last_success, failing_since FROM pushers;
DROP TABLE pushers;
ALTER TABLE pushers2 RENAME TO pushers;


start transaction;
CREATE TABLE my_copytest (
col1 INT,
col2 INT,
col3 INT,
col4 VARCHAR(1),
col5 VARCHAR(1)
) ;

COPY 3 RECORDS INTO my_copytest FROM stdin USING DELIMITERS '|','\n'
NULL as '';
123|1.01||aaa|bbb
553|.02||aaa|bbb
223|2.03||aaa|bbb

select * from my_copytest;
abort;

Use a single error per line.

CREATE TABLE my_copytest (
col1 INT,
col2 INT,
col3 INT,
col4 VARCHAR(1),
col5 VARCHAR(1)
) ;

COPY 1 RECORDS INTO my_copytest FROM stdin USING DELIMITERS '|','\n'
NULL as '';
123|1.01||a|b

COPY 1 RECORDS INTO my_copytest FROM stdin USING DELIMITERS '|','\n'
NULL as '';
553|.02||a|b

COPY 1 RECORDS INTO my_copytest FROM stdin USING DELIMITERS '|','\n'
NULL as '';
223|2.03||a|b

COPY 1 RECORDS INTO my_copytest FROM stdin USING DELIMITERS '|','\n'
NULL as '';
223|2||aaa|b

COPY 1 RECORDS INTO my_copytest FROM stdin USING DELIMITERS '|','\n'
NULL as '';
223|3||a|bbb

select * from my_copytest;
drop table my_copytest;


CREATE TABLE IF NOT EXISTS image_collections (
  id uuid PRIMARY KEY DEFAULT uuid_generate_v4(),
  created_at timestamptz NOT NULL DEFAULT clock_timestamp(),
  modified_at timestamptz NOT NULL DEFAULT clock_timestamp(),

  version bigint NOT NULL DEFAULT 0,

  "user" uuid NOT NULL REFERENCES users(id),
  name text NOT NULL
) WITH (OIDS=FALSE);

CREATE TRIGGER image_collections_occ_tgr BEFORE UPDATE ON image_collections
  FOR EACH ROW EXECUTE PROCEDURE handle_occ();

CREATE TRIGGER image_collections_modified_at_tgr BEFORE UPDATE ON image_collections
  FOR EACH ROW EXECUTE PROCEDURE update_modified_at();

CREATE TABLE IF NOT EXISTS images (
  id uuid PRIMARY KEY DEFAULT uuid_generate_v4(),
  created_at timestamptz NOT NULL DEFAULT clock_timestamp(),

  "user" uuid NOT NULL REFERENCES users(id),
  collection uuid REFERENCES image_collections(id)
                  ON DELETE SET NULL
                  DEFAULT NULL,

  name text NOT NULL,
  size bigint NOT NULL,
  path text NOT NULL
) WITH (OIDS=FALSE);

Add improvements to images tables (migrations).

CREATE TABLE IF NOT EXISTS image_collections (
  id uuid PRIMARY KEY DEFAULT uuid_generate_v4(),
  created_at timestamptz NOT NULL DEFAULT clock_timestamp(),
  modified_at timestamptz NOT NULL DEFAULT clock_timestamp(),
  deleted_at timestamptz DEFAULT NULL,

  version bigint NOT NULL DEFAULT 0,

  "user" uuid NOT NULL REFERENCES users(id),
  name text NOT NULL,

  deleted boolean NOT NULL DEFAULT false
) WITH (OIDS=FALSE);

CREATE TRIGGER image_collections_occ_tgr BEFORE UPDATE ON image_collections
  FOR EACH ROW EXECUTE PROCEDURE handle_occ();

CREATE TRIGGER image_collections_modified_at_tgr BEFORE UPDATE ON image_collections
  FOR EACH ROW EXECUTE PROCEDURE update_modified_at();

CREATE TABLE IF NOT EXISTS images (
  id uuid PRIMARY KEY DEFAULT uuid_generate_v4(),
  created_at timestamptz NOT NULL DEFAULT clock_timestamp(),
  modified_at timestamptz NOT NULL DEFAULT clock_timestamp(),
  deleted_at timestamptz DEFAULT NULL,

  version bigint NOT NULL DEFAULT 0,
  "user" uuid NOT NULL REFERENCES users(id),

  collection uuid REFERENCES image_collections(id)
                  ON DELETE SET NULL
                  DEFAULT NULL,

  name text NOT NULL,
  path text NOT NULL
) WITH (OIDS=FALSE);

CREATE INDEX ON images (collection);

CREATE TRIGGER images_occ_tgr BEFORE UPDATE ON images
  FOR EACH ROW EXECUTE PROCEDURE handle_occ();

CREATE TRIGGER images_modified_at_tgr BEFORE UPDATE ON images
  FOR EACH ROW EXECUTE PROCEDURE update_modified_at();


select E.JOB_EXECUTION_ID, E.START_TIME, E.END_TIME, E.STATUS, E.EXIT_CODE, E.EXIT_MESSAGE, E.CREATE_TIME, E.LAST_UPDATED, E.VERSION, I.JOB_INSTANCE_ID, I.JOB_NAME, P.KEY_NAME, P.TYPE_CD, P.STRING_VAL, P.DATE_VAL, P.LONG_VAL, P.DOUBLE_VAL, P.IDENTIFYING
 from @results_schema.BATCH_JOB_EXECUTION E
 join @results_schema.BATCH_JOB_INSTANCE I on I.JOB_INSTANCE_ID = E.JOB_INSTANCE_ID
 left outer join @results_schema.BATCH_JOB_EXECUTION_PARAMS P on P.JOB_EXECUTION_ID = E.JOB_EXECUTION_ID

Add 'order by' to get the most recent job execution first

select E.JOB_EXECUTION_ID, E.START_TIME, E.END_TIME, E.STATUS, E.EXIT_CODE, E.EXIT_MESSAGE, E.CREATE_TIME, E.LAST_UPDATED, E.VERSION, I.JOB_INSTANCE_ID, I.JOB_NAME, P.KEY_NAME, P.TYPE_CD, P.STRING_VAL, P.DATE_VAL, P.LONG_VAL, P.DOUBLE_VAL, P.IDENTIFYING
 from @results_schema.BATCH_JOB_EXECUTION E
 join @results_schema.BATCH_JOB_INSTANCE I on I.JOB_INSTANCE_ID = E.JOB_INSTANCE_ID
 left outer join @results_schema.BATCH_JOB_EXECUTION_PARAMS P on P.JOB_EXECUTION_ID = E.JOB_EXECUTION_ID
 order by E.START_TIME DESC


-- fix Mastery (thx Nevan)

DELETE FROM spell_linked_spell where spell_trigger IN (86497, 86491, 86492, 86493, 86494, 86495, 86496, 86497, 86498, 86500);
INSERT INTO spell_linked_spell VALUES
(86467, 86473, 3, "Mastery Mage"),
(86491, 86470, 3, "Mastery Druid"),
(86492, 86471, 3, "Mastery DeathKnight"),
(86493, 86472, 3, "Mastery Hunter"),
(86494, 86474, 3, "Mastery Paladin"),
(86495, 86475, 3, "Mastery Priest"),
(86496, 86476, 3, "Mastery Rogue"),
(86497, 86477, 3, "Mastery Shaman"),
(86498, 86478, 3, "Mastery Warlock"),
(86500, 86479, 3, "Mastery Warrior");

Fix Mastery commit typos. Thx to kraven5 for pointing out


/*L
  Copyright ScenPro Inc, SAIC-F

  Distributed under the OSI-approved BSD 3-Clause License.
  See http://ncip.github.com/cadsr-cdecurate/LICENSE.txt for details.
L*/

update sbrext.tool_options_view_ext set value = 'http://lexevsapi60.nci.nih.gov/lexevsapi60'
where Tool_name = 'CURATION' and Property = 'EVS.URL'
/
update sbrext.tool_options_view_ext set value = 'http://lexevsapi60.nci.nih.gov/lexevsapi60'
where Tool_name = 'EVSAPI' and Property = 'URL'
/
commit
/

Comment out unused endpoint for lexEVS 6.0.3.

/*L
  Copyright ScenPro Inc, SAIC-F

  Distributed under the OSI-approved BSD 3-Clause License.
  See http://ncip.github.com/cadsr-cdecurate/LICENSE.txt for details.
L*/

--update sbrext.tool_options_view_ext set value = 'http://lexevsapi60.nci.nih.gov/lexevsapi60'
--where Tool_name = 'CURATION' and Property = 'EVS.URL'
--/
update sbrext.tool_options_view_ext set value = 'http://lexevsapi60.nci.nih.gov/lexevsapi60'
where Tool_name = 'EVSAPI' and Property = 'URL'
/
commit
/


alter table dataset
    add constraint acquisition_ref
    foreign key (acquisition_id) references acquisition;

-- The Modis ingester contains multiple datasets of different processing levels in a single NetCDF file.
-- Replace the unique path constraint with a unique (path, processing level) constraint.

alter table dataset
    drop constraint dataset_path_key;

drop index dataset_dataset_path_idx;

alter table dataset
    add constraint dataset_path_level
    unique (dataset_path, level_id);

Replace the implicit unique index with an explicit one.

alter table dataset
    add constraint acquisition_ref
    foreign key (acquisition_id) references acquisition;

-- The Modis ingester contains multiple datasets of different processing levels in a single NetCDF file.
-- Replace the unique path constraint with a unique (path, processing level) constraint.

alter table dataset
    drop constraint dataset_path_key;

drop index dataset_dataset_path_idx;

create unique index dataset_dataset_path_level_id_idx
    on public.dataset(dataset_path, level_id);

alter table dataset
    add constraint dataset_path_level_uniq
    unique using index dataset_dataset_path_level_id_idx;


CREATE TABLE album_file
    ( album_id  INTEGER NOT NULL
    , file_id   INTEGER NOT NULL
    , PRIMARY KEY (album_id, file_id)
    , FOREIGN KEY (album_id) REFERENCES album(album_id)
    , FOREIGN KEY (file_id) REFERENCES file(file_id)
    );

Add file_to_album SQL index to speed up albums-with-person listings

CREATE TABLE album_file
    ( album_id  INTEGER NOT NULL
    , file_id   INTEGER NOT NULL
    , PRIMARY KEY (album_id, file_id)
    , FOREIGN KEY (album_id) REFERENCES album(album_id)
    , FOREIGN KEY (file_id) REFERENCES file(file_id)
    );

CREATE INDEX file_to_album ON album_file(file_id, album_id);


-- -------------------
-- Drop abac, identity, account, abac, shib portal tables
-- See geni-portal #299
-- -------------------

drop table abac_assertion;
drop table abac;
drop table account;
drop table account_privilege;
drop table identity_attribute;
drop table identity;
drop view requested_account;
drop table shib_attribute;
drop table slice;

Drop tables in correct order.

-- -------------------
-- Drop abac, identity, account, abac, shib portal tables
-- See geni-portal #299
-- -------------------

-- avoid innocuous NOTICEs about automatic sequence creation
set client_min_messages='WARNING';

-- Tell psql to stop on an error. Default behavior is to proceed.
\set ON_ERROR_STOP 1

drop table if exists abac_assertion;
drop table if exists abac;
drop view  if exists requested_account;
drop table if exists identity_attribute;
drop table if exists identity;
drop table if exists account_privilege;
drop table if exists slice;
drop table if exists account;
drop table if exists shib_attribute;


Title	ISSN	eISSN
Engineering Geology Special Publications	0267-9914	2041-4730
Geochemistry: Exploration, Environment, Analysis	1467-7873	2041-4943
Geological Society, London, Memoirs	0435-4052	2041-4722
Geological Society, London, Special Publications	0305-8719	2041-4927
Journal of Micropalaeontology	0262-821X	2041-4978
Journal of the Geological Society	0016-7649	2041-479X
Petroleum Geoscience	1354-0793	2041-496X
Proceedings of the Yorkshire Geological Society	0044-0604	2041-4811
Quarterly Journal of Engineering Geology and Hydrogeology	1470-9236	2041-4803
Scottish Journal of Geology	0036-9276	2041-4951

Remove "Journal of Micropalaeontology" from The Geological Society of London

Title	ISSN	eISSN
Engineering Geology Special Publications	0267-9914	2041-4730
Geochemistry: Exploration, Environment, Analysis	1467-7873	2041-4943
Geological Society, London, Memoirs	0435-4052	2041-4722
Geological Society, London, Special Publications	0305-8719	2041-4927
Journal of the Geological Society	0016-7649	2041-479X
Petroleum Geoscience	1354-0793	2041-496X
Proceedings of the Yorkshire Geological Society	0044-0604	2041-4811
Quarterly Journal of Engineering Geology and Hydrogeology	1470-9236	2041-4803
Scottish Journal of Geology	0036-9276	2041-4951


SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO";

CREATE TABLE `auth_codes` (
  `code` varchar(40) NOT NULL,
  `client_id` varchar(20) NOT NULL,
  `redirect_uri` varchar(200) NOT NULL,
  `expires` int(11) NOT NULL,
  `scope` varchar(250) DEFAULT NULL,
  PRIMARY KEY (`code`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

CREATE TABLE `clients` (
  `client_id` varchar(20) NOT NULL,
  `client_secret` varchar(20) NOT NULL,
  `redirect_uri` varchar(200) NOT NULL,
  PRIMARY KEY (`client_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

CREATE TABLE `access_tokens` (
  `oauth_token` varchar(40) NOT NULL,
  `client_id` varchar(20) NOT NULL,
  `user_id` int(11) UNSIGNED NOT NULL,
  `expires` int(11) NOT NULL,
  `scope` varchar(200) DEFAULT NULL,
  PRIMARY KEY (`oauth_token`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

CREATE TABLE `refresh_tokens` (
  `refresh_token` varchar(40) NOT NULL,
  `client_id` varchar(20) NOT NULL,
  `user_id` int(11) UNSIGNED NOT NULL,
  `expires` int(11) NOT NULL,
  `scope` varchar(200) DEFAULT NULL,
  PRIMARY KEY (`oauth_token`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

Fix primary key in PDO example schema

SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO";

CREATE TABLE `auth_codes` (
  `code` varchar(40) NOT NULL,
  `client_id` varchar(20) NOT NULL,
  `redirect_uri` varchar(200) NOT NULL,
  `expires` int(11) NOT NULL,
  `scope` varchar(250) DEFAULT NULL,
  PRIMARY KEY (`code`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

CREATE TABLE `clients` (
  `client_id` varchar(20) NOT NULL,
  `client_secret` varchar(20) NOT NULL,
  `redirect_uri` varchar(200) NOT NULL,
  PRIMARY KEY (`client_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

CREATE TABLE `access_tokens` (
  `oauth_token` varchar(40) NOT NULL,
  `client_id` varchar(20) NOT NULL,
  `user_id` int(11) UNSIGNED NOT NULL,
  `expires` int(11) NOT NULL,
  `scope` varchar(200) DEFAULT NULL,
  PRIMARY KEY (`oauth_token`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

CREATE TABLE `refresh_tokens` (
  `refresh_token` varchar(40) NOT NULL,
  `client_id` varchar(20) NOT NULL,
  `user_id` int(11) UNSIGNED NOT NULL,
  `expires` int(11) NOT NULL,
  `scope` varchar(200) DEFAULT NULL,
  PRIMARY KEY (`refresh_token`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;


-- avoid innocuous NOTICEs about automatic sequence creation
set client_min_messages='WARNING';

-- Tell psql to stop on an error. Default behavior is to proceed.
\set ON_ERROR_STOP 1

set TIME ZONE 'utc';

-- Tables for IdP accounts

-- ----------------------------------------------------------------------
DROP TABLE IF EXISTS idp_account_request;

CREATE TABLE idp_account_request (
  id SERIAL PRIMARY KEY,
  first_name VARCHAR NOT NULL,
  last_name VARCHAR NOT NULL,
  email VARCHAR NOT NULL,
  username_requested VARCHAR NOT NULL,
  phone VARCHAR NOT NULL,
  password_hash VARCHAR NOT NULL,
  organization VARCHAR NOT NULL,
  title VARCHAR NOT NULL,
  url VARCHAR,
  reason VARCHAR NOT NULL,
  request_ts timestamp DEFAULT NOW() at time zone 'utc',
  username_assigned VARCHAR,
  created_ts timestamp DEFAULT NULL,
  request_state VARCHAR DEFAULT 'REQUESTED'
);

DROP TABLE IF EXISTS idp_account_actions;

CREATE TABLE idp_account_actions (
     id SERIAL PRIMARY KEY,
     uid VARCHAR NOT NULL,
     action_ts timestamp DEFAULT NOW() at time zone 'utc',
     performer VARCHAR,
     action_performed VARCHAR NOT NULL,
     comment VARCHAR
);

Fix format of utc timestamp default

-- avoid innocuous NOTICEs about automatic sequence creation
set client_min_messages='WARNING';

-- Tell psql to stop on an error. Default behavior is to proceed.
\set ON_ERROR_STOP 1

set TIME ZONE 'utc';

-- Tables for IdP accounts

-- ----------------------------------------------------------------------
DROP TABLE IF EXISTS idp_account_request;

CREATE TABLE idp_account_request (
  id SERIAL PRIMARY KEY,
  first_name VARCHAR NOT NULL,
  last_name VARCHAR NOT NULL,
  email VARCHAR NOT NULL,
  username_requested VARCHAR NOT NULL,
  phone VARCHAR NOT NULL,
  password_hash VARCHAR NOT NULL,
  organization VARCHAR NOT NULL,
  title VARCHAR NOT NULL,
  url VARCHAR,
  reason VARCHAR NOT NULL,
  request_ts timestamp DEFAULT (NOW() at time zone 'utc'),
  username_assigned VARCHAR,
  created_ts timestamp DEFAULT NULL,
  request_state VARCHAR DEFAULT 'REQUESTED'
);

DROP TABLE IF EXISTS idp_account_actions;

CREATE TABLE idp_account_actions (
     id SERIAL PRIMARY KEY,
     uid VARCHAR NOT NULL,
     action_ts timestamp DEFAULT (NOW() at time zone 'utc'),
     performer VARCHAR,
     action_performed VARCHAR NOT NULL,
     comment VARCHAR
);


CREATE TABLE [dbo].ApprenticeshipFlexibleEmployment
(
	[ApprenticeshipId] BIGINT NOT NULL,
	[EmploymentPrice] INT NULL,
	[EmploymentEndDate] DATETIME2 NULL,
	CONSTRAINT [FK_ApprenticeshipFlexibleEmployment_ApprenticeshipId] FOREIGN KEY ([ApprenticeshipId]) REFERENCES [Apprenticeship]([Id]),
    CONSTRAINT [PK_ApprenticeshipFlexibleEmployment] PRIMARY KEY ([ApprenticeshipId])
)
GO

Delete entire cohort including flexible employment data

CREATE TABLE [dbo].ApprenticeshipFlexibleEmployment
(
	[ApprenticeshipId] BIGINT NOT NULL,
	[EmploymentPrice] INT NULL,
	[EmploymentEndDate] DATETIME2 NULL,
	CONSTRAINT [FK_ApprenticeshipFlexibleEmployment_ApprenticeshipId] FOREIGN KEY ([ApprenticeshipId]) REFERENCES [Apprenticeship]([Id]) ON DELETE CASCADE,
    CONSTRAINT [PK_ApprenticeshipFlexibleEmployment] PRIMARY KEY ([ApprenticeshipId])
)
GO


CREATE TABLE IF NOT EXISTS reservation (
  id                              SERIAL,
  reservation_title                VARCHAR(255) NOT NULL,
  address_line_one                  VARCHAR(500),
  address_line_two                  VARCHAR(500),
  address_city                     VARCHAR(255),
  address_state                    VARCHAR(20),
  address_zip_code                  VARCHAR(20),
  rsvp_code                        VARCHAR(6) NOT NULL,
  rsvp_code_source                  VARCHAR(500) NOT NULL,
  email_address                    VARCHAR(255),
  reservation_notes                VARCHAR(2048),
  dietary_restrictions             VARCHAR(2048),
  notes_for_bride_groom              VARCHAR(2048),
  is_invited_to_rehearsal_dinner      BOOLEAN,
  is_attending_big_day               BOOLEAN,
  is_attending_rehearsal_dinner      BOOLEAN,
  create_date                     TIMESTAMP NOT NULL,
  modified_date                   TIMESTAMP NOT NULL
);

CREATE TABLE IF NOT EXISTS contact (
  id                          SERIAL,
  reservation_id              INT,
  first_name                   VARCHAR(255) NOT NULL,
  middle_name                  VARCHAR(255),
  last_name                    VARCHAR(255) NOT NULL,
  is_child                     BOOLEAN,
  is_attending_big_day           BOOLEAN,
  is_attending_rehearsal_dinner  BOOLEAN
);

Make the ID and RSVP CODE a composite primary key.

CREATE TABLE IF NOT EXISTS reservation (
  id                              SERIAL,
  reservation_title                VARCHAR(255) NOT NULL,
  address_line_one                  VARCHAR(500),
  address_line_two                  VARCHAR(500),
  address_city                     VARCHAR(255),
  address_state                    VARCHAR(20),
  address_zip_code                  VARCHAR(20),
  rsvp_code                        VARCHAR(6) NOT NULL,
  rsvp_code_source                  VARCHAR(500) NOT NULL,
  email_address                    VARCHAR(255),
  reservation_notes                VARCHAR(2048),
  dietary_restrictions             VARCHAR(2048),
  notes_for_bride_groom              VARCHAR(2048),
  is_invited_to_rehearsal_dinner      BOOLEAN,
  is_attending_big_day               BOOLEAN,
  is_attending_rehearsal_dinner      BOOLEAN,
  create_date                     TIMESTAMP NOT NULL,
  modified_date                   TIMESTAMP NOT NULL,
  PRIMARY KEY(id, rsvp_code)
);

CREATE TABLE IF NOT EXISTS contact (
  id                          SERIAL,
  reservation_id              INT,
  first_name                   VARCHAR(255) NOT NULL,
  middle_name                  VARCHAR(255),
  last_name                    VARCHAR(255) NOT NULL,
  is_child                     BOOLEAN,
  is_attending_big_day           BOOLEAN,
  is_attending_rehearsal_dinner  BOOLEAN
);


DROP TABLE ip_net_plan;
DROP TABLE ip_net_pool_def_prefix_len;
DROP TABLE ip_net_pool;
DROP TABLE ip_net_schema;

DROP TYPE ip_net_plan_type;
DROP TYPE priority_3step;

Remove old and unused table

DROP TABLE ip_net_plan;
DROP TABLE ip_net_pool;
DROP TABLE ip_net_schema;

DROP TYPE ip_net_plan_type;
DROP TYPE priority_3step;