MySQL select statement tests.

This commit is contained in:
go-jet 2019-08-01 16:56:54 +02:00
parent 449cd9fd8f
commit 6af43f0c46
22 changed files with 65812 additions and 47193 deletions

View file

@ -172,10 +172,10 @@ func (q *sqlBuilder) writeString(str string) {
q.write([]byte(str)) q.write([]byte(str))
} }
func (q *sqlBuilder) writeIdentifier(name string) { func (q *sqlBuilder) writeIdentifier(name string, alwaysQuote ...bool) {
quoteWrap := name != strings.ToLower(name) || strings.ContainsAny(name, ". -") quoteWrap := name != strings.ToLower(name) || strings.ContainsAny(name, ". -")
if quoteWrap { if quoteWrap || len(alwaysQuote) > 0 {
identQuoteChar := string(q.dialect.IdentifierQuoteChar) identQuoteChar := string(q.dialect.IdentifierQuoteChar)
q.writeString(identQuoteChar + name + identQuoteChar) q.writeString(identQuoteChar + name + identQuoteChar)
} else { } else {

View file

@ -92,7 +92,7 @@ func (c columnImpl) serialize(statement statementType, out *sqlBuilder, options
if c.subQuery != nil { if c.subQuery != nil {
out.writeIdentifier(c.subQuery.Alias()) out.writeIdentifier(c.subQuery.Alias())
out.writeByte('.') out.writeByte('.')
out.writeAlias(c.defaultAlias()) out.writeIdentifier(c.defaultAlias(), true)
} else { } else {
if c.tableName != "" { if c.tableName != "" {
out.writeIdentifier(c.tableName) out.writeIdentifier(c.tableName)

View file

@ -33,7 +33,7 @@ func newMySQLDialect() Dialect {
mySQLDialect.SerializeOverrides["#"] = mysql_BIT_XOR mySQLDialect.SerializeOverrides["#"] = mysql_BIT_XOR
mySQLDialect.AliasQuoteChar = '"' mySQLDialect.AliasQuoteChar = '"'
mySQLDialect.IdentifierQuoteChar = '"' mySQLDialect.IdentifierQuoteChar = '`'
mySQLDialect.ArgumentPlaceholder = func(int) string { mySQLDialect.ArgumentPlaceholder = func(int) string {
return "?" return "?"
} }

View file

@ -18,7 +18,7 @@ func JsonPrint(v interface{}) {
fmt.Println(string(jsonText)) fmt.Println(string(jsonText))
} }
func JsonSave(path string, v interface{}) { func JsonSave(v interface{}, path string) {
jsonText, _ := json.MarshalIndent(v, "", "\t") jsonText, _ := json.MarshalIndent(v, "", "\t")
err := ioutil.WriteFile(path, jsonText, 0644) err := ioutil.WriteFile(path, jsonText, 0644)
@ -28,14 +28,14 @@ func JsonSave(path string, v interface{}) {
} }
} }
func AssertJSON(t *testing.T, data interface{}, expectedJSON string) { func AssertJSON(t *testing.T, expectedJSON string, data interface{}) {
jsonData, err := json.MarshalIndent(data, "", "\t") jsonData, err := json.MarshalIndent(data, "", "\t")
assert.NilError(t, err) assert.NilError(t, err)
assert.Equal(t, "\n"+string(jsonData)+"\n", expectedJSON) assert.Equal(t, "\n"+string(jsonData)+"\n", expectedJSON)
} }
func AssertJSONFile(t *testing.T, jsonFilePath string, data interface{}) { func AssertJSONFile(t *testing.T, data interface{}, jsonFilePath string) {
fileJSONData, err := ioutil.ReadFile(jsonFilePath) fileJSONData, err := ioutil.ReadFile(jsonFilePath)
assert.NilError(t, err) assert.NilError(t, err)

View file

@ -73,8 +73,23 @@ var MINUSi = jet.MINUSi
var MINUSf = jet.MINUSf var MINUSf = jet.MINUSf
var BIT_NOT = jet.BIT_NOT var BIT_NOT = jet.BIT_NOT
var SUMf = jet.SUMf
var AVG = jet.AVG
var MAXf = jet.MAXf
var MINf = jet.MINf
var COUNT = jet.COUNT
var SELECT = jet.SELECT var SELECT = jet.SELECT
type SelectLock jet.SelectLock
var (
UPDATE = jet.NewSelectLock("UPDATE")
SHARE = jet.NewSelectLock("SHARE")
)
var UNION = jet.UNION
//-----------------literals----------------------// //-----------------literals----------------------//
var STAR = jet.STAR var STAR = jet.STAR

47079
tests/init/data/mysql/dvds.sql Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1,648 +0,0 @@
-- Sakila Sample Database Schema
-- Version 1.0
-- Copyright (c) 2006, 2015, Oracle and/or its affiliates.
-- All rights reserved.
-- Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
-- * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
-- * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
-- * Neither the name of Oracle nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0;
SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;
SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='TRADITIONAL';
DROP SCHEMA IF EXISTS sakila;
CREATE SCHEMA sakila;
USE sakila;
--
-- Table structure for table `actor`
--
CREATE TABLE actor (
actor_id SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT,
first_name VARCHAR(45) NOT NULL,
last_name VARCHAR(45) NOT NULL,
last_update TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (actor_id),
KEY idx_actor_last_name (last_name)
)ENGINE=InnoDB DEFAULT CHARSET=utf8;
--
-- Table structure for table `address`
--
CREATE TABLE address (
address_id SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT,
address VARCHAR(50) NOT NULL,
address2 VARCHAR(50) DEFAULT NULL,
district VARCHAR(20) NOT NULL,
city_id SMALLINT UNSIGNED NOT NULL,
postal_code VARCHAR(10) DEFAULT NULL,
phone VARCHAR(20) NOT NULL,
/*!50705 location GEOMETRY NOT NULL,*/
last_update TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (address_id),
KEY idx_fk_city_id (city_id),
/*!50705 SPATIAL KEY `idx_location` (location),*/
CONSTRAINT `fk_address_city` FOREIGN KEY (city_id) REFERENCES city (city_id) ON DELETE RESTRICT ON UPDATE CASCADE
)ENGINE=InnoDB DEFAULT CHARSET=utf8;
--
-- Table structure for table `category`
--
CREATE TABLE category (
category_id TINYINT UNSIGNED NOT NULL AUTO_INCREMENT,
name VARCHAR(25) NOT NULL,
last_update TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (category_id)
)ENGINE=InnoDB DEFAULT CHARSET=utf8;
--
-- Table structure for table `city`
--
CREATE TABLE city (
city_id SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT,
city VARCHAR(50) NOT NULL,
country_id SMALLINT UNSIGNED NOT NULL,
last_update TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (city_id),
KEY idx_fk_country_id (country_id),
CONSTRAINT `fk_city_country` FOREIGN KEY (country_id) REFERENCES country (country_id) ON DELETE RESTRICT ON UPDATE CASCADE
)ENGINE=InnoDB DEFAULT CHARSET=utf8;
--
-- Table structure for table `country`
--
CREATE TABLE country (
country_id SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT,
country VARCHAR(50) NOT NULL,
last_update TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (country_id)
)ENGINE=InnoDB DEFAULT CHARSET=utf8;
--
-- Table structure for table `customer`
--
CREATE TABLE customer (
customer_id SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT,
store_id TINYINT UNSIGNED NOT NULL,
first_name VARCHAR(45) NOT NULL,
last_name VARCHAR(45) NOT NULL,
email VARCHAR(50) DEFAULT NULL,
address_id SMALLINT UNSIGNED NOT NULL,
active BOOLEAN NOT NULL DEFAULT TRUE,
create_date DATETIME NOT NULL,
last_update TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (customer_id),
KEY idx_fk_store_id (store_id),
KEY idx_fk_address_id (address_id),
KEY idx_last_name (last_name),
CONSTRAINT fk_customer_address FOREIGN KEY (address_id) REFERENCES address (address_id) ON DELETE RESTRICT ON UPDATE CASCADE,
CONSTRAINT fk_customer_store FOREIGN KEY (store_id) REFERENCES store (store_id) ON DELETE RESTRICT ON UPDATE CASCADE
)ENGINE=InnoDB DEFAULT CHARSET=utf8;
--
-- Table structure for table `film`
--
CREATE TABLE film (
film_id SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT,
title VARCHAR(255) NOT NULL,
description TEXT DEFAULT NULL,
release_year YEAR DEFAULT NULL,
language_id TINYINT UNSIGNED NOT NULL,
original_language_id TINYINT UNSIGNED DEFAULT NULL,
rental_duration TINYINT UNSIGNED NOT NULL DEFAULT 3,
rental_rate DECIMAL(4,2) NOT NULL DEFAULT 4.99,
length SMALLINT UNSIGNED DEFAULT NULL,
replacement_cost DECIMAL(5,2) NOT NULL DEFAULT 19.99,
rating ENUM('G','PG','PG-13','R','NC-17') DEFAULT 'G',
special_features SET('Trailers','Commentaries','Deleted Scenes','Behind the Scenes') DEFAULT NULL,
last_update TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (film_id),
KEY idx_title (title),
KEY idx_fk_language_id (language_id),
KEY idx_fk_original_language_id (original_language_id),
CONSTRAINT fk_film_language FOREIGN KEY (language_id) REFERENCES language (language_id) ON DELETE RESTRICT ON UPDATE CASCADE,
CONSTRAINT fk_film_language_original FOREIGN KEY (original_language_id) REFERENCES language (language_id) ON DELETE RESTRICT ON UPDATE CASCADE
)ENGINE=InnoDB DEFAULT CHARSET=utf8;
--
-- Table structure for table `film_actor`
--
CREATE TABLE film_actor (
actor_id SMALLINT UNSIGNED NOT NULL,
film_id SMALLINT UNSIGNED NOT NULL,
last_update TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (actor_id,film_id),
KEY idx_fk_film_id (`film_id`),
CONSTRAINT fk_film_actor_actor FOREIGN KEY (actor_id) REFERENCES actor (actor_id) ON DELETE RESTRICT ON UPDATE CASCADE,
CONSTRAINT fk_film_actor_film FOREIGN KEY (film_id) REFERENCES film (film_id) ON DELETE RESTRICT ON UPDATE CASCADE
)ENGINE=InnoDB DEFAULT CHARSET=utf8;
--
-- Table structure for table `film_category`
--
CREATE TABLE film_category (
film_id SMALLINT UNSIGNED NOT NULL,
category_id TINYINT UNSIGNED NOT NULL,
last_update TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (film_id, category_id),
CONSTRAINT fk_film_category_film FOREIGN KEY (film_id) REFERENCES film (film_id) ON DELETE RESTRICT ON UPDATE CASCADE,
CONSTRAINT fk_film_category_category FOREIGN KEY (category_id) REFERENCES category (category_id) ON DELETE RESTRICT ON UPDATE CASCADE
)ENGINE=InnoDB DEFAULT CHARSET=utf8;
--
-- Table structure for table `film_text`
--
-- InnoDB added FULLTEXT support in 5.6.10. If you use an
-- earlier version, then consider upgrading (recommended) or
-- changing InnoDB to MyISAM as the film_text engine
--
CREATE TABLE film_text (
film_id SMALLINT NOT NULL,
title VARCHAR(255) NOT NULL,
description TEXT,
PRIMARY KEY (film_id),
FULLTEXT KEY idx_title_description (title,description)
)ENGINE=InnoDB DEFAULT CHARSET=utf8;
--
-- Triggers for loading film_text from film
--
DELIMITER ;;
CREATE TRIGGER `ins_film` AFTER INSERT ON `film` FOR EACH ROW BEGIN
INSERT INTO film_text (film_id, title, description)
VALUES (new.film_id, new.title, new.description);
END;;
CREATE TRIGGER `upd_film` AFTER UPDATE ON `film` FOR EACH ROW BEGIN
IF (old.title != new.title) OR (old.description != new.description) OR (old.film_id != new.film_id)
THEN
UPDATE film_text
SET title=new.title,
description=new.description,
film_id=new.film_id
WHERE film_id=old.film_id;
END IF;
END;;
CREATE TRIGGER `del_film` AFTER DELETE ON `film` FOR EACH ROW BEGIN
DELETE FROM film_text WHERE film_id = old.film_id;
END;;
DELIMITER ;
--
-- Table structure for table `inventory`
--
CREATE TABLE inventory (
inventory_id MEDIUMINT UNSIGNED NOT NULL AUTO_INCREMENT,
film_id SMALLINT UNSIGNED NOT NULL,
store_id TINYINT UNSIGNED NOT NULL,
last_update TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (inventory_id),
KEY idx_fk_film_id (film_id),
KEY idx_store_id_film_id (store_id,film_id),
CONSTRAINT fk_inventory_store FOREIGN KEY (store_id) REFERENCES store (store_id) ON DELETE RESTRICT ON UPDATE CASCADE,
CONSTRAINT fk_inventory_film FOREIGN KEY (film_id) REFERENCES film (film_id) ON DELETE RESTRICT ON UPDATE CASCADE
)ENGINE=InnoDB DEFAULT CHARSET=utf8;
--
-- Table structure for table `language`
--
CREATE TABLE language (
language_id TINYINT UNSIGNED NOT NULL AUTO_INCREMENT,
name CHAR(20) NOT NULL,
last_update TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (language_id)
)ENGINE=InnoDB DEFAULT CHARSET=utf8;
--
-- Table structure for table `payment`
--
CREATE TABLE payment (
payment_id SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT,
customer_id SMALLINT UNSIGNED NOT NULL,
staff_id TINYINT UNSIGNED NOT NULL,
rental_id INT DEFAULT NULL,
amount DECIMAL(5,2) NOT NULL,
payment_date DATETIME NOT NULL,
last_update TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (payment_id),
KEY idx_fk_staff_id (staff_id),
KEY idx_fk_customer_id (customer_id),
CONSTRAINT fk_payment_rental FOREIGN KEY (rental_id) REFERENCES rental (rental_id) ON DELETE SET NULL ON UPDATE CASCADE,
CONSTRAINT fk_payment_customer FOREIGN KEY (customer_id) REFERENCES customer (customer_id) ON DELETE RESTRICT ON UPDATE CASCADE,
CONSTRAINT fk_payment_staff FOREIGN KEY (staff_id) REFERENCES staff (staff_id) ON DELETE RESTRICT ON UPDATE CASCADE
)ENGINE=InnoDB DEFAULT CHARSET=utf8;
--
-- Table structure for table `rental`
--
CREATE TABLE rental (
rental_id INT NOT NULL AUTO_INCREMENT,
rental_date DATETIME NOT NULL,
inventory_id MEDIUMINT UNSIGNED NOT NULL,
customer_id SMALLINT UNSIGNED NOT NULL,
return_date DATETIME DEFAULT NULL,
staff_id TINYINT UNSIGNED NOT NULL,
last_update TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (rental_id),
UNIQUE KEY (rental_date,inventory_id,customer_id),
KEY idx_fk_inventory_id (inventory_id),
KEY idx_fk_customer_id (customer_id),
KEY idx_fk_staff_id (staff_id),
CONSTRAINT fk_rental_staff FOREIGN KEY (staff_id) REFERENCES staff (staff_id) ON DELETE RESTRICT ON UPDATE CASCADE,
CONSTRAINT fk_rental_inventory FOREIGN KEY (inventory_id) REFERENCES inventory (inventory_id) ON DELETE RESTRICT ON UPDATE CASCADE,
CONSTRAINT fk_rental_customer FOREIGN KEY (customer_id) REFERENCES customer (customer_id) ON DELETE RESTRICT ON UPDATE CASCADE
)ENGINE=InnoDB DEFAULT CHARSET=utf8;
--
-- Table structure for table `staff`
--
CREATE TABLE staff (
staff_id TINYINT UNSIGNED NOT NULL AUTO_INCREMENT,
first_name VARCHAR(45) NOT NULL,
last_name VARCHAR(45) NOT NULL,
address_id SMALLINT UNSIGNED NOT NULL,
picture BLOB DEFAULT NULL,
email VARCHAR(50) DEFAULT NULL,
store_id TINYINT UNSIGNED NOT NULL,
active BOOLEAN NOT NULL DEFAULT TRUE,
username VARCHAR(16) NOT NULL,
password VARCHAR(40) BINARY DEFAULT NULL,
last_update TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (staff_id),
KEY idx_fk_store_id (store_id),
KEY idx_fk_address_id (address_id),
CONSTRAINT fk_staff_store FOREIGN KEY (store_id) REFERENCES store (store_id) ON DELETE RESTRICT ON UPDATE CASCADE,
CONSTRAINT fk_staff_address FOREIGN KEY (address_id) REFERENCES address (address_id) ON DELETE RESTRICT ON UPDATE CASCADE
)ENGINE=InnoDB DEFAULT CHARSET=utf8;
--
-- Table structure for table `store`
--
CREATE TABLE store (
store_id TINYINT UNSIGNED NOT NULL AUTO_INCREMENT,
manager_staff_id TINYINT UNSIGNED NOT NULL,
address_id SMALLINT UNSIGNED NOT NULL,
last_update TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (store_id),
UNIQUE KEY idx_unique_manager (manager_staff_id),
KEY idx_fk_address_id (address_id),
CONSTRAINT fk_store_staff FOREIGN KEY (manager_staff_id) REFERENCES staff (staff_id) ON DELETE RESTRICT ON UPDATE CASCADE,
CONSTRAINT fk_store_address FOREIGN KEY (address_id) REFERENCES address (address_id) ON DELETE RESTRICT ON UPDATE CASCADE
)ENGINE=InnoDB DEFAULT CHARSET=utf8;
--
-- View structure for view `customer_list`
--
CREATE VIEW customer_list
AS
SELECT cu.customer_id AS ID, CONCAT(cu.first_name, _utf8' ', cu.last_name) AS name, a.address AS address, a.postal_code AS `zip code`,
a.phone AS phone, city.city AS city, country.country AS country, IF(cu.active, _utf8'active',_utf8'') AS notes, cu.store_id AS SID
FROM customer AS cu JOIN address AS a ON cu.address_id = a.address_id JOIN city ON a.city_id = city.city_id
JOIN country ON city.country_id = country.country_id;
--
-- View structure for view `film_list`
--
CREATE VIEW film_list
AS
SELECT film.film_id AS FID, film.title AS title, film.description AS description, category.name AS category, film.rental_rate AS price,
film.length AS length, film.rating AS rating, GROUP_CONCAT(CONCAT(actor.first_name, _utf8' ', actor.last_name) SEPARATOR ', ') AS actors
FROM category LEFT JOIN film_category ON category.category_id = film_category.category_id LEFT JOIN film ON film_category.film_id = film.film_id
JOIN film_actor ON film.film_id = film_actor.film_id
JOIN actor ON film_actor.actor_id = actor.actor_id
GROUP BY film.film_id, category.name;
--
-- View structure for view `nicer_but_slower_film_list`
--
CREATE VIEW nicer_but_slower_film_list
AS
SELECT film.film_id AS FID, film.title AS title, film.description AS description, category.name AS category, film.rental_rate AS price,
film.length AS length, film.rating AS rating, GROUP_CONCAT(CONCAT(CONCAT(UCASE(SUBSTR(actor.first_name,1,1)),
LCASE(SUBSTR(actor.first_name,2,LENGTH(actor.first_name))),_utf8' ',CONCAT(UCASE(SUBSTR(actor.last_name,1,1)),
LCASE(SUBSTR(actor.last_name,2,LENGTH(actor.last_name)))))) SEPARATOR ', ') AS actors
FROM category LEFT JOIN film_category ON category.category_id = film_category.category_id LEFT JOIN film ON film_category.film_id = film.film_id
JOIN film_actor ON film.film_id = film_actor.film_id
JOIN actor ON film_actor.actor_id = actor.actor_id
GROUP BY film.film_id, category.name;
--
-- View structure for view `staff_list`
--
CREATE VIEW staff_list
AS
SELECT s.staff_id AS ID, CONCAT(s.first_name, _utf8' ', s.last_name) AS name, a.address AS address, a.postal_code AS `zip code`, a.phone AS phone,
city.city AS city, country.country AS country, s.store_id AS SID
FROM staff AS s JOIN address AS a ON s.address_id = a.address_id JOIN city ON a.city_id = city.city_id
JOIN country ON city.country_id = country.country_id;
--
-- View structure for view `sales_by_store`
--
CREATE VIEW sales_by_store
AS
SELECT
CONCAT(c.city, _utf8',', cy.country) AS store
, CONCAT(m.first_name, _utf8' ', m.last_name) AS manager
, SUM(p.amount) AS total_sales
FROM payment AS p
INNER JOIN rental AS r ON p.rental_id = r.rental_id
INNER JOIN inventory AS i ON r.inventory_id = i.inventory_id
INNER JOIN store AS s ON i.store_id = s.store_id
INNER JOIN address AS a ON s.address_id = a.address_id
INNER JOIN city AS c ON a.city_id = c.city_id
INNER JOIN country AS cy ON c.country_id = cy.country_id
INNER JOIN staff AS m ON s.manager_staff_id = m.staff_id
GROUP BY s.store_id
ORDER BY cy.country, c.city;
--
-- View structure for view `sales_by_film_category`
--
-- Note that total sales will add up to >100% because
-- some titles belong to more than 1 category
--
CREATE VIEW sales_by_film_category
AS
SELECT
c.name AS category
, SUM(p.amount) AS total_sales
FROM payment AS p
INNER JOIN rental AS r ON p.rental_id = r.rental_id
INNER JOIN inventory AS i ON r.inventory_id = i.inventory_id
INNER JOIN film AS f ON i.film_id = f.film_id
INNER JOIN film_category AS fc ON f.film_id = fc.film_id
INNER JOIN category AS c ON fc.category_id = c.category_id
GROUP BY c.name
ORDER BY total_sales DESC;
--
-- View structure for view `actor_info`
--
CREATE DEFINER=CURRENT_USER SQL SECURITY INVOKER VIEW actor_info
AS
SELECT
a.actor_id,
a.first_name,
a.last_name,
GROUP_CONCAT(DISTINCT CONCAT(c.name, ': ',
(SELECT GROUP_CONCAT(f.title ORDER BY f.title SEPARATOR ', ')
FROM sakila.film f
INNER JOIN sakila.film_category fc
ON f.film_id = fc.film_id
INNER JOIN sakila.film_actor fa
ON f.film_id = fa.film_id
WHERE fc.category_id = c.category_id
AND fa.actor_id = a.actor_id
)
)
ORDER BY c.name SEPARATOR '; ')
AS film_info
FROM sakila.actor a
LEFT JOIN sakila.film_actor fa
ON a.actor_id = fa.actor_id
LEFT JOIN sakila.film_category fc
ON fa.film_id = fc.film_id
LEFT JOIN sakila.category c
ON fc.category_id = c.category_id
GROUP BY a.actor_id, a.first_name, a.last_name;
--
-- Procedure structure for procedure `rewards_report`
--
DELIMITER //
CREATE PROCEDURE rewards_report (
IN min_monthly_purchases TINYINT UNSIGNED
, IN min_dollar_amount_purchased DECIMAL(10,2) UNSIGNED
, OUT count_rewardees INT
)
LANGUAGE SQL
NOT DETERMINISTIC
READS SQL DATA
SQL SECURITY DEFINER
COMMENT 'Provides a customizable report on best customers'
proc: BEGIN
DECLARE last_month_start DATE;
DECLARE last_month_end DATE;
/* Some sanity checks... */
IF min_monthly_purchases = 0 THEN
SELECT 'Minimum monthly purchases parameter must be > 0';
LEAVE proc;
END IF;
IF min_dollar_amount_purchased = 0.00 THEN
SELECT 'Minimum monthly dollar amount purchased parameter must be > $0.00';
LEAVE proc;
END IF;
/* Determine start and end time periods */
SET last_month_start = DATE_SUB(CURRENT_DATE(), INTERVAL 1 MONTH);
SET last_month_start = STR_TO_DATE(CONCAT(YEAR(last_month_start),'-',MONTH(last_month_start),'-01'),'%Y-%m-%d');
SET last_month_end = LAST_DAY(last_month_start);
/*
Create a temporary storage area for
Customer IDs.
*/
CREATE TEMPORARY TABLE tmpCustomer (customer_id SMALLINT UNSIGNED NOT NULL PRIMARY KEY);
/*
Find all customers meeting the
monthly purchase requirements
*/
INSERT INTO tmpCustomer (customer_id)
SELECT p.customer_id
FROM payment AS p
WHERE DATE(p.payment_date) BETWEEN last_month_start AND last_month_end
GROUP BY customer_id
HAVING SUM(p.amount) > min_dollar_amount_purchased
AND COUNT(customer_id) > min_monthly_purchases;
/* Populate OUT parameter with count of found customers */
SELECT COUNT(*) FROM tmpCustomer INTO count_rewardees;
/*
Output ALL customer information of matching rewardees.
Customize output as needed.
*/
SELECT c.*
FROM tmpCustomer AS t
INNER JOIN customer AS c ON t.customer_id = c.customer_id;
/* Clean up */
DROP TABLE tmpCustomer;
END //
DELIMITER ;
DELIMITER $$
CREATE FUNCTION get_customer_balance(p_customer_id INT, p_effective_date DATETIME) RETURNS DECIMAL(5,2)
DETERMINISTIC
READS SQL DATA
BEGIN
#OK, WE NEED TO CALCULATE THE CURRENT BALANCE GIVEN A CUSTOMER_ID AND A DATE
#THAT WE WANT THE BALANCE TO BE EFFECTIVE FOR. THE BALANCE IS:
# 1) RENTAL FEES FOR ALL PREVIOUS RENTALS
# 2) ONE DOLLAR FOR EVERY DAY THE PREVIOUS RENTALS ARE OVERDUE
# 3) IF A FILM IS MORE THAN RENTAL_DURATION * 2 OVERDUE, CHARGE THE REPLACEMENT_COST
# 4) SUBTRACT ALL PAYMENTS MADE BEFORE THE DATE SPECIFIED
DECLARE v_rentfees DECIMAL(5,2); #FEES PAID TO RENT THE VIDEOS INITIALLY
DECLARE v_overfees INTEGER; #LATE FEES FOR PRIOR RENTALS
DECLARE v_payments DECIMAL(5,2); #SUM OF PAYMENTS MADE PREVIOUSLY
SELECT IFNULL(SUM(film.rental_rate),0) INTO v_rentfees
FROM film, inventory, rental
WHERE film.film_id = inventory.film_id
AND inventory.inventory_id = rental.inventory_id
AND rental.rental_date <= p_effective_date
AND rental.customer_id = p_customer_id;
SELECT IFNULL(SUM(IF((TO_DAYS(rental.return_date) - TO_DAYS(rental.rental_date)) > film.rental_duration,
((TO_DAYS(rental.return_date) - TO_DAYS(rental.rental_date)) - film.rental_duration),0)),0) INTO v_overfees
FROM rental, inventory, film
WHERE film.film_id = inventory.film_id
AND inventory.inventory_id = rental.inventory_id
AND rental.rental_date <= p_effective_date
AND rental.customer_id = p_customer_id;
SELECT IFNULL(SUM(payment.amount),0) INTO v_payments
FROM payment
WHERE payment.payment_date <= p_effective_date
AND payment.customer_id = p_customer_id;
RETURN v_rentfees + v_overfees - v_payments;
END $$
DELIMITER ;
DELIMITER $$
CREATE PROCEDURE film_in_stock(IN p_film_id INT, IN p_store_id INT, OUT p_film_count INT)
READS SQL DATA
BEGIN
SELECT inventory_id
FROM inventory
WHERE film_id = p_film_id
AND store_id = p_store_id
AND inventory_in_stock(inventory_id);
SELECT FOUND_ROWS() INTO p_film_count;
END $$
DELIMITER ;
DELIMITER $$
CREATE PROCEDURE film_not_in_stock(IN p_film_id INT, IN p_store_id INT, OUT p_film_count INT)
READS SQL DATA
BEGIN
SELECT inventory_id
FROM inventory
WHERE film_id = p_film_id
AND store_id = p_store_id
AND NOT inventory_in_stock(inventory_id);
SELECT FOUND_ROWS() INTO p_film_count;
END $$
DELIMITER ;
DELIMITER $$
CREATE FUNCTION inventory_held_by_customer(p_inventory_id INT) RETURNS INT
READS SQL DATA
BEGIN
DECLARE v_customer_id INT;
DECLARE EXIT HANDLER FOR NOT FOUND RETURN NULL;
SELECT customer_id INTO v_customer_id
FROM rental
WHERE return_date IS NULL
AND inventory_id = p_inventory_id;
RETURN v_customer_id;
END $$
DELIMITER ;
DELIMITER $$
CREATE FUNCTION inventory_in_stock(p_inventory_id INT) RETURNS BOOLEAN
READS SQL DATA
BEGIN
DECLARE v_rentals INT;
DECLARE v_out INT;
#AN ITEM IS IN-STOCK IF THERE ARE EITHER NO ROWS IN THE rental TABLE
#FOR THE ITEM OR ALL ROWS HAVE return_date POPULATED
SELECT COUNT(*) INTO v_rentals
FROM rental
WHERE inventory_id = p_inventory_id;
IF v_rentals = 0 THEN
RETURN TRUE;
END IF;
SELECT COUNT(rental_id) INTO v_out
FROM inventory LEFT JOIN rental USING(inventory_id)
WHERE inventory.inventory_id = p_inventory_id
AND rental.return_date IS NULL;
IF v_out > 0 THEN
RETURN FALSE;
ELSE
RETURN TRUE;
END IF;
END $$
DELIMITER ;
SET SQL_MODE=@OLD_SQL_MODE;
SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS;
SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS;

View file

@ -41,6 +41,7 @@ func main() {
func initMySQLDB() { func initMySQLDB() {
mySQLDBs := []string{ mySQLDBs := []string{
"dvds",
"test_sample", "test_sample",
} }

View file

@ -24,7 +24,7 @@ func TestAllTypes(t *testing.T) {
assert.NilError(t, err) assert.NilError(t, err)
//testutils.JsonPrint(dest) //testutils.JsonPrint(dest)
testutils.AssertJSON(t, dest, allTypesJson) testutils.AssertJSON(t, allTypesJson, dest)
} }
func TestExpressionOperators(t *testing.T) { func TestExpressionOperators(t *testing.T) {
@ -66,7 +66,7 @@ LIMIT ?;
//testutils.JsonPrint(dest) //testutils.JsonPrint(dest)
testutils.AssertJSON(t, dest, ` testutils.AssertJSON(t, `
[ [
{ {
"IsNull": false, "IsNull": false,
@ -85,7 +85,7 @@ LIMIT ?;
"NotInSelect": null "NotInSelect": null
} }
] ]
`) `, dest)
} }
func TestBoolOperators(t *testing.T) { func TestBoolOperators(t *testing.T) {
@ -155,7 +155,7 @@ FROM test_sample.all_types;
assert.NilError(t, err) assert.NilError(t, err)
testutils.AssertJSONFile(t, "./testdata/common/bool_operators.json", dest) testutils.AssertJSONFile(t, dest, "./testdata/common/bool_operators.json")
} }
func TestFloatOperators(t *testing.T) { func TestFloatOperators(t *testing.T) {
@ -252,7 +252,7 @@ LIMIT ?;
assert.NilError(t, err) assert.NilError(t, err)
testutils.AssertJSONFile(t, "./testdata/common/float_operators.json", dest) testutils.AssertJSONFile(t, dest, "./testdata/common/float_operators.json")
} }
func TestIntegerOperators(t *testing.T) { func TestIntegerOperators(t *testing.T) {
@ -391,7 +391,7 @@ LIMIT ?;
//testutils.JsonPrint(dest) //testutils.JsonPrint(dest)
testutils.AssertJSONFile(t, "./testdata/common/int_operators.json", dest) testutils.AssertJSONFile(t, dest, "./testdata/common/int_operators.json")
} }
var allTypesJson = ` var allTypesJson = `

View file

@ -1,41 +0,0 @@
package mysql
import (
"github.com/go-jet/jet/internal/testutils"
. "github.com/go-jet/jet/mysql"
"github.com/go-jet/jet/tests/.gentestdata/sakila/model"
. "github.com/go-jet/jet/tests/.gentestdata/sakila/table"
"gotest.tools/assert"
"testing"
)
func TestSelect_ScanToStruct(t *testing.T) {
expectedSQL := `
SELECT DISTINCT actor.actor_id AS "actor.actor_id",
actor.first_name AS "actor.first_name",
actor.last_name AS "actor.last_name",
actor.last_update AS "actor.last_update"
FROM sakila.actor
WHERE actor.actor_id = ?;
`
query := Actor.
SELECT(Actor.AllColumns).
DISTINCT().
WHERE(Actor.ActorID.EQ(Int(1)))
testutils.AssertStatementSql(t, query, expectedSQL, int64(1))
actor := model.Actor{}
err := query.Query(db, &actor)
assert.NilError(t, err)
assert.DeepEqual(t, actor, model.Actor{
ActorID: 1,
FirstName: "PENELOPE",
LastName: "GUINESS",
LastUpdate: *testutils.TimestampWithoutTimeZone("2006-02-15 04:34:33", 2),
})
}

387
tests/mysql/select_test.go Normal file
View file

@ -0,0 +1,387 @@
package mysql
import (
"github.com/go-jet/jet/internal/testutils"
. "github.com/go-jet/jet/mysql"
"github.com/go-jet/jet/tests/.gentestdata/mysql/dvds/enum"
"github.com/go-jet/jet/tests/.gentestdata/mysql/dvds/model"
. "github.com/go-jet/jet/tests/.gentestdata/mysql/dvds/table"
"gotest.tools/assert"
"testing"
)
func TestSelect_ScanToStruct(t *testing.T) {
query := Actor.
SELECT(Actor.AllColumns).
DISTINCT().
WHERE(Actor.ActorID.EQ(Int(1)))
testutils.AssertStatementSql(t, query, `
SELECT DISTINCT actor.actor_id AS "actor.actor_id",
actor.first_name AS "actor.first_name",
actor.last_name AS "actor.last_name",
actor.last_update AS "actor.last_update"
FROM dvds.actor
WHERE actor.actor_id = ?;
`, int64(1))
actor := model.Actor{}
err := query.Query(db, &actor)
assert.NilError(t, err)
assert.DeepEqual(t, actor, actor1)
}
var actor1 = model.Actor{
ActorID: 1,
FirstName: "PENELOPE",
LastName: "GUINESS",
LastUpdate: *testutils.TimestampWithoutTimeZone("2006-02-15 04:34:33", 2),
}
func TestSelect_ScanToSlice(t *testing.T) {
query := Actor.
SELECT(Actor.AllColumns).
ORDER_BY(Actor.ActorID)
testutils.AssertStatementSql(t, query, `
SELECT actor.actor_id AS "actor.actor_id",
actor.first_name AS "actor.first_name",
actor.last_name AS "actor.last_name",
actor.last_update AS "actor.last_update"
FROM dvds.actor
ORDER BY actor.actor_id;
`)
dest := []model.Actor{}
err := query.Query(db, &dest)
assert.NilError(t, err)
assert.Equal(t, len(dest), 200)
assert.DeepEqual(t, dest[0], actor1)
//testutils.JsonPrint(dest)
//testutils.JsonSave(dest, "mysql/testdata/all_actors.json")
testutils.AssertJSONFile(t, dest, "mysql/testdata/all_actors.json")
}
func TestSelectGroupByHaving(t *testing.T) {
expectedSQL := `
SELECT customer.customer_id AS "customer.customer_id",
customer.store_id AS "customer.store_id",
customer.first_name AS "customer.first_name",
customer.last_name AS "customer.last_name",
customer.email AS "customer.email",
customer.address_id AS "customer.address_id",
customer.active AS "customer.active",
customer.create_date AS "customer.create_date",
customer.last_update AS "customer.last_update",
SUM(payment.amount) AS "amount.sum",
AVG(payment.amount) AS "amount.avg",
MAX(payment.amount) AS "amount.max",
MIN(payment.amount) AS "amount.min",
COUNT(payment.amount) AS "amount.count"
FROM dvds.payment
INNER JOIN dvds.customer ON (customer.customer_id = payment.customer_id)
GROUP BY payment.customer_id
HAVING SUM(payment.amount) > 125.6
ORDER BY payment.customer_id, SUM(payment.amount) ASC;
`
query := Payment.
INNER_JOIN(Customer, Customer.CustomerID.EQ(Payment.CustomerID)).
SELECT(
Customer.AllColumns,
SUMf(Payment.Amount).AS("amount.sum"),
AVG(Payment.Amount).AS("amount.avg"),
MAXf(Payment.Amount).AS("amount.max"),
MINf(Payment.Amount).AS("amount.min"),
COUNT(Payment.Amount).AS("amount.count"),
).
GROUP_BY(Payment.CustomerID).
HAVING(
SUMf(Payment.Amount).GT(Float(125.6)),
).
ORDER_BY(
Payment.CustomerID, SUMf(Payment.Amount).ASC(),
)
//fmt.Println(query.DebugSql())
testutils.AssertDebugStatementSql(t, query, expectedSQL, float64(125.6))
var dest []struct {
model.Customer
Amount struct {
Sum float64
Avg float64
Max float64
Min float64
Count int64
} `alias:"amount"`
}
err := query.Query(db, &dest)
assert.NilError(t, err)
//testutils.JsonPrint(dest)
assert.Equal(t, len(dest), 174)
//testutils.JsonSave(dest, "mysql/testdata/customer_payment_sum.json")
testutils.AssertJSONFile(t, dest, "mysql/testdata/customer_payment_sum.json")
}
func getRowLockTestData() map[SelectLock]string {
return map[SelectLock]string{
UPDATE(): "UPDATE",
SHARE(): "SHARE",
}
}
func TestRowLock(t *testing.T) {
expectedSQL := `
SELECT *
FROM dvds.address
LIMIT 3
OFFSET 1
FOR`
query := Address.
SELECT(STAR).
LIMIT(3).
OFFSET(1)
for lockType, lockTypeStr := range getRowLockTestData() {
query.FOR(lockType)
expectedQuery := expectedSQL + " " + lockTypeStr + ";\n"
testutils.AssertDebugStatementSql(t, query, expectedQuery, int64(3), int64(1))
tx, _ := db.Begin()
_, err := query.Exec(tx)
assert.NilError(t, err)
err = tx.Rollback()
assert.NilError(t, err)
}
for lockType, lockTypeStr := range getRowLockTestData() {
query.FOR(lockType.NOWAIT())
testutils.AssertDebugStatementSql(t, query, expectedSQL+" "+lockTypeStr+" NOWAIT;\n", int64(3), int64(1))
tx, _ := db.Begin()
_, err := query.Exec(tx)
assert.NilError(t, err)
err = tx.Rollback()
assert.NilError(t, err)
}
for lockType, lockTypeStr := range getRowLockTestData() {
query.FOR(lockType.SKIP_LOCKED())
testutils.AssertDebugStatementSql(t, query, expectedSQL+" "+lockTypeStr+" SKIP LOCKED;\n", int64(3), int64(1))
tx, _ := db.Begin()
_, err := query.Exec(tx)
assert.NilError(t, err)
err = tx.Rollback()
assert.NilError(t, err)
}
}
func TestSubQuery(t *testing.T) {
rRatingFilms := Film.
SELECT(
Film.FilmID,
Film.Title,
Film.Rating,
).
WHERE(Film.Rating.EQ(enum.FilmRating.R)).
AsTable("rFilms")
rFilmID := Film.FilmID.From(rRatingFilms)
query := rRatingFilms.
INNER_JOIN(FilmActor, FilmActor.FilmID.EQ(rFilmID)).
INNER_JOIN(Actor, Actor.ActorID.EQ(FilmActor.ActorID)).
SELECT(
Actor.AllColumns,
FilmActor.AllColumns,
rRatingFilms.AllColumns(),
).
ORDER_BY(rFilmID, Actor.ActorID)
var dest []struct {
model.Film
Actors []model.Actor
}
err := query.Query(db, &dest)
assert.NilError(t, err)
//testutils.JsonSave(dest, "mysql/testdata/r_rating_films.json")
testutils.AssertJSONFile(t, dest, "mysql/testdata/r_rating_films.json")
}
func TestSelectAndUnionInProjection(t *testing.T) {
expectedSQL := `
SELECT payment.payment_id AS "payment.payment_id",
(
SELECT customer.customer_id AS "customer.customer_id"
FROM dvds.customer
LIMIT ?
),
(
(
(
SELECT payment.payment_id AS "payment.payment_id"
FROM dvds.payment
LIMIT ?
OFFSET ?
)
UNION
(
SELECT payment.payment_id AS "payment.payment_id"
FROM dvds.payment
LIMIT ?
OFFSET ?
)
)
LIMIT ?
)
FROM dvds.payment
LIMIT ?;
`
query := Payment.
SELECT(
Payment.PaymentID,
Customer.SELECT(Customer.CustomerID).LIMIT(1),
UNION(
Payment.SELECT(Payment.PaymentID).LIMIT(1).OFFSET(10),
Payment.SELECT(Payment.PaymentID).LIMIT(1).OFFSET(2),
).LIMIT(1),
).
LIMIT(12)
testutils.AssertStatementSql(t, query, expectedSQL, int64(1), int64(1), int64(10), int64(1), int64(2), int64(1), int64(12))
}
func TestJoinQueryStruct(t *testing.T) {
expectedSQL := `
SELECT film_actor.actor_id AS "film_actor.actor_id",
film_actor.film_id AS "film_actor.film_id",
film_actor.last_update AS "film_actor.last_update",
film.film_id AS "film.film_id",
film.title AS "film.title",
film.description AS "film.description",
film.release_year AS "film.release_year",
film.language_id AS "film.language_id",
film.original_language_id AS "film.original_language_id",
film.rental_duration AS "film.rental_duration",
film.rental_rate AS "film.rental_rate",
film.length AS "film.length",
film.replacement_cost AS "film.replacement_cost",
film.rating AS "film.rating",
film.special_features AS "film.special_features",
film.last_update AS "film.last_update",
language.language_id AS "language.language_id",
language.name AS "language.name",
language.last_update AS "language.last_update",
actor.actor_id AS "actor.actor_id",
actor.first_name AS "actor.first_name",
actor.last_name AS "actor.last_name",
actor.last_update AS "actor.last_update",
inventory.inventory_id AS "inventory.inventory_id",
inventory.film_id AS "inventory.film_id",
inventory.store_id AS "inventory.store_id",
inventory.last_update AS "inventory.last_update",
rental.rental_id AS "rental.rental_id",
rental.rental_date AS "rental.rental_date",
rental.inventory_id AS "rental.inventory_id",
rental.customer_id AS "rental.customer_id",
rental.return_date AS "rental.return_date",
rental.staff_id AS "rental.staff_id",
rental.last_update AS "rental.last_update"
FROM dvds.language
INNER JOIN dvds.film ON (film.language_id = language.language_id)
INNER JOIN dvds.film_actor ON (film_actor.film_id = film.film_id)
INNER JOIN dvds.actor ON (actor.actor_id = film_actor.actor_id)
LEFT JOIN dvds.inventory ON (inventory.film_id = film.film_id)
LEFT JOIN dvds.rental ON (rental.inventory_id = inventory.inventory_id)
ORDER BY language.language_id ASC, film.film_id ASC, actor.actor_id ASC, inventory.inventory_id ASC, rental.rental_id ASC
LIMIT ?;
`
for i := 0; i < 2; i++ {
query := Language.
INNER_JOIN(Film, Film.LanguageID.EQ(Language.LanguageID)).
INNER_JOIN(FilmActor, FilmActor.FilmID.EQ(Film.FilmID)).
INNER_JOIN(Actor, Actor.ActorID.EQ(FilmActor.ActorID)).
LEFT_JOIN(Inventory, Inventory.FilmID.EQ(Film.FilmID)).
LEFT_JOIN(Rental, Rental.InventoryID.EQ(Inventory.InventoryID)).
SELECT(
FilmActor.AllColumns,
Film.AllColumns,
Language.AllColumns,
Actor.AllColumns,
Inventory.AllColumns,
Rental.AllColumns,
).
ORDER_BY(
Language.LanguageID.ASC(),
Film.FilmID.ASC(),
Actor.ActorID.ASC(),
Inventory.InventoryID.ASC(),
Rental.RentalID.ASC(),
).
LIMIT(1000)
//fmt.Println(query.Sql())
testutils.AssertStatementSql(t, query, expectedSQL, int64(1000))
var dest []struct {
model.Language
Films []struct {
model.Film
Actors []struct {
model.Actor
}
Inventories *[]struct {
model.Inventory
Rentals *[]model.Rental
}
}
}
err := query.Query(db, &dest)
assert.NilError(t, err)
//assert.Equal(t, len(dest), 1)
//assert.Equal(t, len(dest[0].Films), 10)
//assert.Equal(t, len(dest[0].Films[0].Actors), 10)
//testutils.JsonSave(dest, "./mysql/testdata/lang_film_actor_inventory_rental.json")
testutils.AssertJSONFile(t, dest, "./mysql/testdata/lang_film_actor_inventory_rental.json")
}
}

1202
tests/mysql/testdata/all_actors.json vendored Normal file

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

9469
tests/mysql/testdata/r_rating_films.json vendored Normal file

File diff suppressed because it is too large Load diff

View file

@ -95,7 +95,7 @@ LIMIT $5;
//testutils.JsonPrint(dest) //testutils.JsonPrint(dest)
testutils.AssertJSON(t, dest, ` testutils.AssertJSON(t, `
[ [
{ {
"IsNull": false, "IsNull": false,
@ -114,7 +114,7 @@ LIMIT $5;
"NotInSelect": null "NotInSelect": null
} }
] ]
`) `, dest)
} }
func TestExpressionCast(t *testing.T) { func TestExpressionCast(t *testing.T) {
@ -299,7 +299,7 @@ LIMIT $5;
assert.NilError(t, err) assert.NilError(t, err)
testutils.AssertJSONFile(t, "./testdata/common/bool_operators.json", dest) testutils.AssertJSONFile(t, dest, "./testdata/common/bool_operators.json")
} }
func TestFloatOperators(t *testing.T) { func TestFloatOperators(t *testing.T) {
@ -397,7 +397,7 @@ LIMIT $35;
//testutils.JsonPrint(dest) //testutils.JsonPrint(dest)
testutils.AssertJSONFile(t, "./testdata/common/float_operators.json", dest) testutils.AssertJSONFile(t, dest, "./testdata/common/float_operators.json")
} }
func TestIntegerOperators(t *testing.T) { func TestIntegerOperators(t *testing.T) {
@ -536,7 +536,7 @@ LIMIT $22;
//testutils.JsonSave("./testdata/common/int_operators.json", dest) //testutils.JsonSave("./testdata/common/int_operators.json", dest)
//testutils.JsonPrint(dest) //testutils.JsonPrint(dest)
testutils.AssertJSONFile(t, "./testdata/common/int_operators.json", dest) testutils.AssertJSONFile(t, dest, "./testdata/common/int_operators.json")
} }
func TestTimeOperators(t *testing.T) { func TestTimeOperators(t *testing.T) {

View file

@ -102,7 +102,7 @@ func TestJoinEverything(t *testing.T) {
assert.NilError(t, err) assert.NilError(t, err)
assert.Equal(t, len(dest), 275) assert.Equal(t, len(dest), 275)
testutils.AssertJSONFile(t, "./postgres/testdata/joined_everything.json", dest) testutils.AssertJSONFile(t, dest, "./postgres/testdata/joined_everything.json")
} }
func TestSelfJoin(t *testing.T) { func TestSelfJoin(t *testing.T) {
@ -142,7 +142,7 @@ ORDER BY "Employee"."EmployeeId";
assert.NilError(t, err) assert.NilError(t, err)
assert.Equal(t, len(dest), 8) assert.Equal(t, len(dest), 8)
testutils.AssertJSON(t, dest[0:2], ` testutils.AssertJSON(t, `
[ [
{ {
"EmployeeId": 1, "EmployeeId": 1,
@ -197,7 +197,7 @@ ORDER BY "Employee"."EmployeeId";
} }
} }
] ]
`) `, dest[0:2])
} }

View file

@ -62,5 +62,5 @@ func TestNorthwindJoinEverything(t *testing.T) {
assert.NilError(t, err) assert.NilError(t, err)
//jsonSave("./testdata/northwind-all.json", dest) //jsonSave("./testdata/northwind-all.json", dest)
testutils.AssertJSONFile(t, "./postgres/testdata/northwind-all.json", dest) testutils.AssertJSONFile(t, dest, "./postgres/testdata/northwind-all.json")
} }

View file

@ -47,7 +47,7 @@ FROM test_sample.person;
err := query.Query(db, &result) err := query.Query(db, &result)
assert.NilError(t, err) assert.NilError(t, err)
testutils.AssertJSON(t, result, ` testutils.AssertJSON(t, `
[ [
{ {
"PersonID": "b68dbff4-a87d-11e9-a7f2-98ded00c39c6", "PersonID": "b68dbff4-a87d-11e9-a7f2-98ded00c39c6",
@ -68,7 +68,7 @@ FROM test_sample.person;
"Mood": "ok" "Mood": "ok"
} }
] ]
`) `, result)
} }
func TestSelecSelfJoin1(t *testing.T) { func TestSelecSelfJoin1(t *testing.T) {

View file

@ -534,7 +534,7 @@ ORDER BY city.city_id, address.address_id, customer.customer_id;
assert.NilError(t, err) assert.NilError(t, err)
assert.Equal(t, len(dest), 2) assert.Equal(t, len(dest), 2)
testutils.AssertJSON(t, dest, ` testutils.AssertJSON(t, `
[ [
{ {
"CityID": 312, "CityID": 312,
@ -573,7 +573,7 @@ ORDER BY city.city_id, address.address_id, customer.customer_id;
] ]
} }
] ]
`) `, dest)
} }
func TestJoinQuerySliceWithPtrs(t *testing.T) { func TestJoinQuerySliceWithPtrs(t *testing.T) {
@ -992,60 +992,72 @@ ORDER BY film.film_id ASC;
func TestSelectGroupByHaving(t *testing.T) { func TestSelectGroupByHaving(t *testing.T) {
expectedSQL := ` expectedSQL := `
SELECT payment.customer_id AS "customer_payment_sum.customer_id", SELECT customer.customer_id AS "customer.customer_id",
SUM(payment.amount) AS "customer_payment_sum.amount_sum", customer.store_id AS "customer.store_id",
AVG(payment.amount) AS "customer_payment_sum.amount_avg", customer.first_name AS "customer.first_name",
MAX(payment.amount) AS "customer_payment_sum.amount_max", customer.last_name AS "customer.last_name",
MIN(payment.amount) AS "customer_payment_sum.amount_min", customer.email AS "customer.email",
COUNT(payment.amount) AS "customer_payment_sum.amount_count" customer.address_id AS "customer.address_id",
customer.activebool AS "customer.activebool",
customer.create_date AS "customer.create_date",
customer.last_update AS "customer.last_update",
customer.active AS "customer.active",
SUM(payment.amount) AS "amount.sum",
AVG(payment.amount) AS "amount.avg",
MAX(payment.amount) AS "amount.max",
MIN(payment.amount) AS "amount.min",
COUNT(payment.amount) AS "amount.count"
FROM dvds.payment FROM dvds.payment
GROUP BY payment.customer_id INNER JOIN dvds.customer ON (customer.customer_id = payment.customer_id)
HAVING SUM(payment.amount) > 100 GROUP BY customer.customer_id
ORDER BY SUM(payment.amount) ASC; HAVING SUM(payment.amount) > 125.6
ORDER BY customer.customer_id, SUM(payment.amount) ASC;
` `
customersPaymentQuery := Payment. query := Payment.
INNER_JOIN(Customer, Customer.CustomerID.EQ(Payment.CustomerID)).
SELECT( SELECT(
Payment.CustomerID.AS("customer_payment_sum.customer_id"), Customer.AllColumns,
SUMf(Payment.Amount).AS("customer_payment_sum.amount_sum"),
AVG(Payment.Amount).AS("customer_payment_sum.amount_avg"), SUMf(Payment.Amount).AS("amount.sum"),
MAXf(Payment.Amount).AS("customer_payment_sum.amount_max"), AVG(Payment.Amount).AS("amount.avg"),
MINf(Payment.Amount).AS("customer_payment_sum.amount_min"), MAXf(Payment.Amount).AS("amount.max"),
COUNT(Payment.Amount).AS("customer_payment_sum.amount_count"), MINf(Payment.Amount).AS("amount.min"),
). COUNT(Payment.Amount).AS("amount.count"),
GROUP_BY(Payment.CustomerID).
ORDER_BY(
SUMf(Payment.Amount).ASC(),
). ).
GROUP_BY(Customer.CustomerID).
HAVING( HAVING(
SUMf(Payment.Amount).GT(Float(100)), SUMf(Payment.Amount).GT(Float(125.6)),
).
ORDER_BY(
Customer.CustomerID, SUMf(Payment.Amount).ASC(),
) )
testutils.AssertDebugStatementSql(t, customersPaymentQuery, expectedSQL, float64(100)) //fmt.Println(query.DebugSql())
type CustomerPaymentSum struct { testutils.AssertDebugStatementSql(t, query, expectedSQL, float64(125.6))
CustomerID int16
AmountSum float64 var dest []struct {
AmountAvg float64 model.Customer
AmountMax float64
AmountMin float64 Amount struct {
AmountCount int64 Sum float64
Avg float64
Max float64
Min float64
Count int64
} `alias:"amount"`
} }
customerPaymentSum := []CustomerPaymentSum{} err := query.Query(db, &dest)
err := customersPaymentQuery.Query(db, &customerPaymentSum)
assert.NilError(t, err) assert.NilError(t, err)
assert.Equal(t, len(customerPaymentSum), 296) //testutils.JsonPrint(dest)
assert.DeepEqual(t, customerPaymentSum[0], CustomerPaymentSum{
CustomerID: 135, assert.Equal(t, len(dest), 104)
AmountSum: 100.72,
AmountAvg: 3.597142857142857, //testutils.JsonSave(dest, "postgres/testdata/customer_payment_sum.json")
AmountMax: 7.99, testutils.AssertJSONFile(t, dest, "postgres/testdata/customer_payment_sum.json")
AmountMin: 0.99,
AmountCount: 28,
})
} }
func TestSelectGroupBy2(t *testing.T) { func TestSelectGroupBy2(t *testing.T) {
@ -1125,7 +1137,7 @@ func TestSelectStaff(t *testing.T) {
assert.NilError(t, err) assert.NilError(t, err)
testutils.AssertJSON(t, staffs, ` testutils.AssertJSON(t, `
[ [
{ {
"StaffID": 1, "StaffID": 1,
@ -1154,7 +1166,7 @@ func TestSelectStaff(t *testing.T) {
"Picture": null "Picture": null
} }
] ]
`) `, staffs)
} }
func TestSelectTimeColumns(t *testing.T) { func TestSelectTimeColumns(t *testing.T) {
@ -1460,7 +1472,7 @@ ORDER BY actor.actor_id ASC, film.film_id ASC;
assert.NilError(t, err) assert.NilError(t, err)
//jsonSave("./testdata/quick-start-dest.json", dest) //jsonSave("./testdata/quick-start-dest.json", dest)
testutils.AssertJSONFile(t, "./postgres/testdata/quick-start-dest.json", dest) testutils.AssertJSONFile(t, dest, "./postgres/testdata/quick-start-dest.json")
var dest2 []struct { var dest2 []struct {
model.Category model.Category
@ -1473,7 +1485,7 @@ ORDER BY actor.actor_id ASC, film.film_id ASC;
assert.NilError(t, err) assert.NilError(t, err)
//jsonSave("./testdata/quick-start-dest2.json", dest2) //jsonSave("./testdata/quick-start-dest2.json", dest2)
testutils.AssertJSONFile(t, "./postgres/testdata/quick-start-dest2.json", dest2) testutils.AssertJSONFile(t, dest2, "./postgres/testdata/quick-start-dest2.json")
} }
func TestQuickStartWithSubQueries(t *testing.T) { func TestQuickStartWithSubQueries(t *testing.T) {
@ -1525,7 +1537,7 @@ func TestQuickStartWithSubQueries(t *testing.T) {
assert.NilError(t, err) assert.NilError(t, err)
//jsonSave("./testdata/quick-start-dest.json", dest) //jsonSave("./testdata/quick-start-dest.json", dest)
testutils.AssertJSONFile(t, "./postgres/testdata/quick-start-dest.json", dest) testutils.AssertJSONFile(t, dest, "./postgres/testdata/quick-start-dest.json")
var dest2 []struct { var dest2 []struct {
model.Category model.Category
@ -1538,5 +1550,5 @@ func TestQuickStartWithSubQueries(t *testing.T) {
assert.NilError(t, err) assert.NilError(t, err)
//jsonSave("./testdata/quick-start-dest2.json", dest2) //jsonSave("./testdata/quick-start-dest2.json", dest2)
testutils.AssertJSONFile(t, "./postgres/testdata/quick-start-dest2.json", dest2) testutils.AssertJSONFile(t, dest2, "./postgres/testdata/quick-start-dest2.json")
} }

File diff suppressed because it is too large Load diff