SlideShare una empresa de Scribd logo
1 de 83
Slick in Practice
Alexander Ioffe
OOP Theory vs Practice
Theory
class Cat extends Animal
{
...
}
Practice
class ManagerFactory extends Factory {
...
}
Noun Verb
Theory
class Cat extends Animal
{
...
}
Practice
class ManagerFactory extends Factory {
Manager construct() {…}
} <- The Real verb
* https://steve-yegge.blogspot.com/2006/03/execution-in-kingdom-of-nouns.html
Noun Verb Chaperone
SQL Theory vs Practice
Theory
Nouns
Theory Practice
select (…)
from
Really, really
complicated stuff
VerbsNouns
Theory Practice
Specification Driven
+ Minimize Incidental Complexity
Nouns Verbs
Theory
Nouns Verbs
Practice
Constructed Ad-Hoc
= Maximize Incidental Complexity
The Practice
SELECT DISTINCT
account.name, alias,
CASE WHEN code = 'EV'
THEN cast(account.number AS VARCHAR)
ELSE cast(account.number AS VARCHAR) + substring(alias, 1, 2) END AS OFFICIAL_IDENTITY,
CASE WHEN order_permission IN ('A', 'S')
THEN 'ST' ELSE 'ENH' END
FROM (
SELECT DISTINCT mc.alias, mc.code, order_permission, mc.account_tag
FROM MERCHANT_CLIENTS mc
JOIN REGISTRY r ON r.alias = mc.alias
WHERE r.market = 'us' AND r.record_type = 'M'
UNION ALL
SELECT DISTINCT sc.alias, 'EV' AS code, part.order_permission, sc.account_tag
FROM SERVICE_CLIENTS sc
JOIN REGISTRY r ON r.alias = sc.alias AND r.record_type = 'S' AND r.market = 'us'
JOIN PARTNERSHIPS part ON part.id = sc.partnership_fk) client
INNER JOIN (
dbo.ACCOUNTS account
INNER JOIN ACCOUNT_TYPES accountType ON account.type = accountType.account_type
LEFT JOIN DEDICATED_ACCOUNTS dedicated ON dedicated.account_number = account.number)
ON (accountType.mapping_type = 0)
OR (accountType.mapping_type = 2 AND account.tag = client.account_tag)
OR (accountType.mapping_type = 1 AND dedicated.client_alias = client.alias)
UML?
SELECT DISTINCT
account.name, alias,
CASE (...) AS OFFICIAL_IDENTITY,
CASE (...)
FROM (
SELECT DISTINCT
mc.alias, mc.code, order_permission, mc.account_tag (code, alias, perm, tag)
FROM MERCHANT_CLIENTS mc
JOIN REGISTRY r ON (alias) AND (otherConditions)
UNION ALL
SELECT DISTINCT
sc.alias, 'EV' AS code, part.order_permission, sc.account_tag (code, alias, perm, tag)
FROM SERVICE_CLIENTS sc
JOIN REGISTRY r ON (alias) AND (otherConditions)
JOIN PARTNERSHIPS part ON (id <-> fk)) client
INNER JOIN (
dbo.ACCOUNTS account
INNER JOIN ACCOUNT_TYPES accountType ON (account_type)
LEFT JOIN DEDICATED_ACCOUNTS dedicated ON (account_number)
)
ON (possibly anything...)
OR (possibly the account tag...)
OR (possibly the alias...) → All Depending on the accountType
SELECT DISTINCT
account.name, alias,
CASE (...) AS OFFICIAL_IDENTITY,
CASE (...)
FROM (
SELECT DISTINCT
mc.alias, mc.code, order_permission, mc.account_tag (code, alias, perm, tag)
FROM MERCHANT_CLIENTS mc
JOIN REGISTRY r ON (alias) AND (otherConditions)
UNION ALL
SELECT DISTINCT
sc.alias, 'EV' AS code, part.order_permission, sc.account_tag (code, alias, perm, tag)
FROM SERVICE_CLIENTS sc
JOIN REGISTRY r ON (alias) AND (otherConditions)
JOIN PARTNERSHIPS part ON (id <-> fk)) client
INNER JOIN (
dbo.ACCOUNTS account
INNER JOIN ACCOUNT_TYPES accountType ON (account_type)
LEFT JOIN DEDICATED_ACCOUNTS dedicated ON (account_number)
)
ON (possibly anything...)
OR (possibly the account tag...)
OR (possibly the alias...) → All Depending on the accountType
SELECT DISTINCT
account.name, alias,
CASE (...) AS OFFICIAL_IDENTITY,
CASE (...)
FROM (
SELECT DISTINCT
mc.alias, mc.code, order_permission, mc.account_tag (code, alias, perm, tag)
FROM MERCHANT_CLIENTS mc
JOIN REGISTRY r ON (alias) AND (otherConditions)
UNION ALL
SELECT DISTINCT
sc.alias, 'EV' AS code, part.order_permission, sc.account_tag (code, alias, perm, tag)
FROM SERVICE_CLIENTS sc
JOIN REGISTRY r ON (alias) AND (otherConditions)
JOIN PARTNERSHIPS part ON (id <-> fk)) client
INNER JOIN (
dbo.ACCOUNTS account
INNER JOIN ACCOUNT_TYPES accountType ON (account_type)
LEFT JOIN DEDICATED_ACCOUNTS dedicated ON (account_number)
)
ON (possibly anything...)
OR (possibly the account tag...)
OR (possibly the alias...) → All Depending on the accountType
Alias RecType Mkt Description
ACMC M ca ACME Canada.
ACME M us ACME Corp.
ACMI M eu ACME International Corp.
FNF S us Frin and Flyn Association
FNJ S us
Krueger and Voorhees
Alliance
Alias Code Perm
ACME INC T
ACMI INC T
ACMC INC T
ALIAS FK Account Tag
YOGL 1 YOG
FNF 2 SID
FNJ 3 FF
ID PERM DESCRIPTION
1 S Y.G. Schwartz Supplies Procurement
2 T Frin and Flyn Procurement
3 H Special Individuals Fulfillment
4 H Special Individuals Fulfillment International
Alias Code Perm Tag
ACME INC T
ACMI INC T
ACMC INC T
YOGL S S YOG
FNF T T SID
FNJ H H FF
SELECT DISTINCT
account.name, alias,
CASE (...) AS OFFICIAL_IDENTITY,
CASE (...)
FROM (...) client
INNER JOIN (
dbo.ACCOUNTS account
INNER JOIN ACCOUNT_TYPES accountType ON (account_type)
LEFT JOIN DEDICATED_ACCOUNTS dedicated ON (account_number)
)
ON (accountType.mapping_type = 0)
OR (possibly the account tag...)
OR (possibly the alias...)
name alias OFFICIAL_IDENTITY perm
TUNV FNF 111 ENH
TUNV ACME 111AC ENH
SIADV FNF 456 ENH
AUNV FNF 222 ENH
AUNV ACME 222AC ENH
ACMEINV ACME 808AC ENH
YOGADV YOGL 123 ST
TUNV YOGL 111 ST
AUNV YOGL 222 ST
SELECT DISTINCT
account.name, alias,
CASE (...) AS OFFICIAL_IDENTITY,
CASE (...)
FROM (...) client
INNER JOIN (
dbo.ACCOUNTS account
INNER JOIN ACCOUNT_TYPES accountType ON (account_type)
LEFT JOIN DEDICATED_ACCOUNTS dedicated ON (account_number)
)
ON (possibly anything...)
OR (accountType.mapping_type = 2 AND account.tag = client.account_tag)
OR (possibly the alias...)
name alias OFFICIAL_IDENTITY perm
TUNV FNF 111 ENH
TUNV ACME 111AC ENH
SIADV FNF 456 ENH
AUNV FNF 222 ENH
AUNV ACME 222AC ENH
ACMEINV ACME 808AC ENH
YOGADV YOGL 123 ST
TUNV YOGL 111 ST
AUNV YOGL 222 ST
SELECT DISTINCT
account.name, alias,
CASE (...) AS OFFICIAL_IDENTITY,
CASE (...)
FROM (...) client
INNER JOIN (
dbo.ACCOUNTS account
INNER JOIN ACCOUNT_TYPES accountType ON (account_type)
LEFT JOIN DEDICATED_ACCOUNTS dedicated ON (account_number)
)
ON (possibly anything...)
OR (possibly the account tag...)
OR (accountType.mapping_type = 1 AND dedicated.client_alias = client.alias)
name alias OFFICIAL_IDENTITY perm
TUNV FNF 111 ENH
TUNV ACME 111AC ENH
SIADV FNF 456 ENH
AUNV FNF 222 ENH
AUNV ACME 222AC ENH
ACMEINV ACME 808AC ENH
YOGADV YOGL 123 ST
TUNV YOGL 111 ST
AUNV YOGL 222 ST
Can We Simplify?
SELECT DISTINCT
account.name, alias,
CASE WHEN code = 'EV'
THEN cast(account.number AS VARCHAR)
ELSE cast(account.number AS VARCHAR) + substring(alias, 1, 2) END AS OFFICIAL_IDENTITY,
CASE WHEN order_permission IN ('A', 'S')
THEN 'ST' ELSE 'ENH' END
FROM (
SELECT DISTINCT mc.alias, mc.code, order_permission, mc.account_tag
FROM MERCHANT_CLIENTS mc
JOIN REGISTRY r ON r.alias = mc.alias
WHERE r.market = 'us' AND r.record_type = 'M'
UNION ALL
SELECT DISTINCT sc.alias, 'EV' AS code, part.order_permission, sc.account_tag
FROM SERVICE_CLIENTS sc
JOIN REGISTRY r ON r.alias = sc.alias AND r.record_type = 'S' AND r.market = 'us'
JOIN PARTNERSHIPS part ON part.id = sc.partnership_fk) client
INNER JOIN (
dbo.ACCOUNTS account
INNER JOIN ACCOUNT_TYPES accountType ON account.type = accountType.account_type
LEFT JOIN DEDICATED_ACCOUNTS dedicated ON dedicated.account_number = account.number)
ON (accountType.mapping_type = 0)
OR (accountType.mapping_type = 2 AND account.tag = client.account_tag)
OR (accountType.mapping_type = 1 AND dedicated.client_alias = client.alias)
WITH merchantClients AS (
SELECT DISTINCT mc.alias, mc.code, order_permission, mc.account_tag
FROM MERCHANT_CLIENTS mc
JOIN REGISTRY r ON r.alias = mc.alias),
serviceClients AS (SELECT DISTINCT
sc.alias, 'EV' AS code, partnership.order_permission, sc.account_tag
FROM SERVICE_CLIENTS sc
JOIN REGISTRY r ON r.alias = sc.alias AND r.record_type = 'S' AND r.market = 'us'
JOIN PARTNERSHIPS partnership ON partnership.id = sc.partnership_fk),
client AS (SELECT * FROM merchantClients UNION ALL SELECT * FROM serviceClients)
SELECT DISTINCT account.name, alias,
CASE WHEN code = 'EV'
THEN cast(account.number AS VARCHAR)
ELSE cast(account.number AS VARCHAR) + substring(alias, 1, 2) END AS OFFICIAL_IDENTITY,
CASE WHEN order_permission IN ('A', 'S')
THEN 'ST' ELSE 'ENH' END
FROM client
INNER JOIN (
dbo.ACCOUNTS account
INNER JOIN ACCOUNT_TYPES accountType ON account.type = accountType.account_type
LEFT JOIN DEDICATED_ACCOUNTS dedicated ON dedicated.account_number = account.number)
ON (accountType.mapping_type = 0)
OR (accountType.mapping_type = 2 AND account.tag = client.account_tag)
OR (accountType.mapping_type = 1 AND dedicated.client_alias = client.alias)
CREATE VIEW MERCHANT_CLIENTS_V AS
SELECT DISTINCT
mc.alias,
mc.code,
order_permission,
mc.account_tag
FROM MERCHANT_CLIENTS mc
JOIN REGISTRY entry ON entry.alias = mc.alias
WHERE entry.market = 'us'
AND entry.record_type = 'M'
CREATE VIEW SERVICE_CLIENTS_V AS
SELECT DISTINCT
sc.alias,
'EV' AS code,
partnership.order_permission,
sc.account_tag
FROM SERVICE_CLIENTS sc
JOIN REGISTRY entry ON entry.alias = sc.alias
AND entry.record_type = 'S'
AND entry.market = 'us'
JOIN PARTNERSHIPS partnership
ON partnership.id = sc.partnership_fk
CREATE VIEW CLIENTS AS
SELECT * FROM MERCHANT_CLIENTS_V
UNION ALL SELECT * FROM SERVICE_CLIENTS_V
CREATE VIEW MERCHANT_CLIENTS_V AS
SELECT DISTINCT (...)
FROM MERCHANT_CLIENTS mc
JOIN REGISTRY entry ON entry.alias = mc.alias
WHERE entry.market = 'us'
AND entry.record_type = 'M'
CREATE VIEW SERVICE_CLIENTS_V AS
SELECT DISTINCT (...)
FROM SERVICE_CLIENTS sc
JOIN REGISTRY entry ON entry.alias = sc.alias
AND entry.record_type = 'S'
AND entry.market = 'us'
JOIN PARTNERSHIPS partnership
ON partnership.id = sc.partnership_fk
CREATE VIEW CLIENT_ACCOUNTS AS
SELECT DISTINCT
account.name, alias,
CASE WHEN code = 'EV'
THEN cast(account.number AS VARCHAR)
ELSE cast(account.number AS VARCHAR) + substring(alias, 1, 2) END AS OFFICIAL_IDENTITY,
CASE WHEN order_permission IN ('A', 'S')
THEN 'ST' ELSE 'ENH' END
FROM CLIENTS AS client
INNER JOIN (
dbo.ACCOUNTS account
INNER JOIN ACCOUNT_TYPES accountType ON account.type = accountType.account_type
LEFT JOIN DEDICATED_ACCOUNTS dedicated ON dedicated.account_number = account.number)
ON (accountType.mapping_type = 0)
OR (accountType.mapping_type = 2 AND account.tag = client.account_tag)
OR (accountType.mapping_type = 1 AND dedicated.client_alias = client.alias)
CREATE VIEW CLIENTS AS
SELECT * FROM MERCHANT_CLIENTS_V
UNION ALL SELECT * FROM SERVICE_CLIENTS_V
New Requirements
1.New European Business Unit
with Client Codes from
the Partnership
2.New Canadian Business Unit
without Service Clients
CREATE VIEW EU_MERCHANT_CLIENTS AS
SELECT DISTINCT (...)
FROM MERCHANT_CLIENTS mc
JOIN REGISTRY entry ON entry.alias = mc.alias
WHERE entry.market = 'eu'
AND entry.record_type = 'M'
CREATE VIEW EU_SERVICE_CLIENTS AS
SELECT DISTINCT (... pc.code, ...)
FROM SERVICE_CLIENTS sc
JOIN REGISTRY entry ON entry.alias = sc.alias
AND entry.record_type = 'S'
AND entry.market = 'eu'
JOIN PARTNERSHIPS partnership
ON partnership.id = sc.partnership_fk
JOIN PARTNERSHIP_CODES pc
ON partnership.ID = pc.partnership_fk
CREATE VIEW EU_CLIENT_ACCOUNTS AS
SELECT DISTINCT
account.name, alias,
CASE WHEN code = 'EV'
THEN cast(account.number AS VARCHAR)
ELSE cast(account.number AS VARCHAR) + substring(alias, 1, 2) END AS OFFICIAL_IDENTITY,
CASE WHEN order_permission IN ('A', 'S')
THEN 'ST' ELSE 'ENH' END
FROM EU_CLIENTS AS client
INNER JOIN (
dbo.ACCOUNTS account
INNER JOIN ACCOUNT_TYPES accountType ON account.type = accountType.account_type
LEFT JOIN DEDICATED_ACCOUNTS dedicated ON dedicated.account_number = account.number)
ON (accountType.mapping_type = 0)
OR (accountType.mapping_type = 2 AND account.tag = client.account_tag)
OR (accountType.mapping_type = 1 AND dedicated.client_alias = client.alias)
CREATE VIEW EU_CLIENTS AS
SELECT * FROM EU_MERCHANT_CLIENTS
UNION ALL SELECT * FROM US_SERVICE_CLIENTS
CREATE VIEW CA_MERCHANT_CLIENTS AS
SELECT DISTINCT (...)
FROM MERCHANT_CLIENTS mc
JOIN REGISTRY entry ON entry.alias = mc.alias
WHERE entry.market = 'ca'
AND entry.record_type = 'M'
CREATE VIEW CA_CLIENT_ACCOUNTS AS
SELECT DISTINCT
account.name, alias,
CASE WHEN code = 'EV'
THEN cast(account.number AS VARCHAR)
ELSE cast(account.number AS VARCHAR) + substring(alias, 1, 2) END AS OFFICIAL_IDENTITY,
CASE WHEN order_permission IN ('A', 'S')
THEN 'ST' ELSE 'ENH' END
FROM CA_MERCHANT_CLIENTS AS client
INNER JOIN (
dbo.ACCOUNTS account
INNER JOIN ACCOUNT_TYPES accountType ON account.type = accountType.account_type
LEFT JOIN DEDICATED_ACCOUNTS dedicated ON dedicated.account_number = account.number)
ON (accountType.mapping_type = 0)
OR (accountType.mapping_type = 2 AND account.tag = client.account_tag)
OR (accountType.mapping_type = 1 AND dedicated.client_alias = client.alias)
~O(N) Codebase Size Per N Business Units!
Tables:
• MERCHANT_CLIENTS_V
• SERVICE_CLIENTS_V
• CLIENTS
• CLIENT_ACCOUNTS
Tables:
• US_MERCHANT_CLIENTS
• US_SERVICE_CLIENTS
• US_CLIENTS
• US_CLIENT_ACCOUNTS
• EU_MERCHANT_CLIENTS +
• EU_SERVICE_CLIENTS +
• EU_CLIENTS +
• EU_CLIENT_ACCOUNTS +
• CA_MERCHANT_CLIENTS +
• CA_CLIENT_ACCOUNTS +
= Lots of Technical Debt
CREATE FUNCTION dbo.merchantClientsUdf (@market)
RETURNS table as RETURN (
SELECT DISTINCT
alias, code, order_permission, account_tag
FROM MERCHANT_CLIENTS merchantClient
JOIN REGISTRY entry
ON entry.alias = merchantClient.alias
WHERE entry.market = @market
AND entry.record_type = 'M')
CREATE VIEW CLIENT_ACCOUNTS AS
SELECT DISTINCT
account.name, alias,
CASE WHEN code = 'EV'
THEN cast(account.number AS VARCHAR)
ELSE cast(account.number AS VARCHAR) + substring(alias, 1, 2) END AS OFFICIAL_IDENTITY,
CASE WHEN order_permission IN ('A', 'S')
THEN 'ST' ELSE 'ENH' END
FROM (select * from merchantClientsUdf ('us') union
select * from serviceClientsUdf ('us')) as client
INNER JOIN (
dbo.ACCOUNTS account
INNER JOIN ACCOUNT_TYPES accountType ON account.type = accountType.account_type
LEFT JOIN DEDICATED_ACCOUNTS dedicated ON dedicated.account_number = account.number)
ON (accountType.mapping_type = 0)
OR (accountType.mapping_type = 2 AND account.tag = client.account_tag)
OR (accountType.mapping_type = 1 AND dedicated.client_alias = client.alias)
CREATE FUNCTION dbo.serviceClientsUdf (@market)
RETURNS table as RETURN (
SELECT DISTINCT
alias, code, order_permission, account_tag
FROM SERVICE_CLIENTS serviceClient
JOIN REGISTRY entry
ON entry.alias = serviceClient.alias
AND entry.record_type = 'S'
AND entry.market = @market
JOIN PARTNERSHIPS partnership
ON partnership.id = serviceClient.partnership_fk)
CREATE FUNCTION dbo.merchantClientsUdf (@market)
RETURNS table as RETURN (…)
CREATE VIEW EU_CLIENT_ACCOUNTS AS
SELECT DISTINCT
account.name, alias,
CASE WHEN code = 'EV'
THEN cast(account.number AS VARCHAR)
ELSE cast(account.number AS VARCHAR) + substring(alias, 1, 2) END AS OFFICIAL_IDENTITY,
CASE WHEN order_permission IN ('A', 'S')
THEN 'ST' ELSE 'ENH' END
FROM (select * from merchantClientsUdf ('eu') union
select * from enhancedServiceClientsUdf ('eu')) as client
INNER JOIN (
dbo.ACCOUNTS account
INNER JOIN ACCOUNT_TYPES accountType ON account.type = accountType.account_type
LEFT JOIN DEDICATED_ACCOUNTS dedicated ON dedicated.account_number = account.number)
ON (accountType.mapping_type = 0)
OR (accountType.mapping_type = 2 AND account.tag = client.account_tag)
OR (accountType.mapping_type = 1 AND dedicated.client_alias = client.alias)
CREATE FUNCTION dbo.enhancedServiceClientsUdf (@market)
RETURNS table as RETURN (
SELECT DISTINCT
alias, code, order_permission, account_tag
FROM SERVICE_CLIENTS serviceClient
JOIN REGISTRY entry
ON (... entry.market = @market ...)
JOIN PARTNERSHIPS partnership ON (…)
JOIN PARTNERSHIP_CODES pc
ON partnership.ID = pc.partnership_fk
CREATE FUNCTION dbo.merchantClientsUdf (@market)
RETURNS table as RETURN (…)
CREATE VIEW CA_CLIENT_ACCOUNTS AS
SELECT DISTINCT
account.name, alias,
CASE WHEN code = 'EV'
THEN cast(account.number AS VARCHAR)
ELSE cast(account.number AS VARCHAR) + substring(alias, 1, 2) END AS OFFICIAL_IDENTITY,
CASE WHEN order_permission IN ('A', 'S')
THEN 'ST' ELSE 'ENH' END
FROM (select * from merchantClientsUdf ('ca') union
select * from enhancedServiceClientsUdf ('ca')) as client
INNER JOIN (
dbo.ACCOUNTS account
INNER JOIN ACCOUNT_TYPES accountType ON account.type = accountType.account_type
LEFT JOIN DEDICATED_ACCOUNTS dedicated ON dedicated.account_number = account.number)
ON (accountType.mapping_type = 0)
OR (accountType.mapping_type = 2 AND account.tag = client.account_tag)
OR (accountType.mapping_type = 1 AND dedicated.client_alias = client.alias)
~O(N)/2 Codebase Size Per N Business Units!
Tables:
• merchantClientsUdf
• serviceClientsUdf
• CLIENT_ACCOUNTS
• merchantClientsUdf
• serviceClientsUdf
• US_CLIENT_ACCOUNTS
• enhancedServiceClientsUdf +
• EU_CLIENT_ACCOUNTS +
• CA_CLIENT_ACCOUNTS +
Tables:
= (Still) Lots of Technical Debt
What abstraction is significantly better?
Tables:
• merchantClientsUdf
• serviceClientsUdf
• CLIENT_ACCOUNTS
• merchantClientsUdf
• serviceClientsUdf
• US_CLIENT_ACCOUNTS
• enhancedServiceClientsUdf +
• EU_CLIENT_ACCOUNTS +
• CA_CLIENT_ACCOUNTS +
Tables:
define Client = Table[alias, code, perm, tag]
Tables:
• merchantClientsUdf → Client
• serviceClientsUdf → Client
• CLIENT_ACCOUNTS(c:Client)
• merchantClientsUdf → Client
• serviceClientsUdf → Client
• CLIENT_ACCOUNTS(c:Client)
• enhancedServiceClientsUdf → Client
Tables:
define Client = Table[alias, code, perm, tag]
Codebase Size only Increases with new Features!
Tables:
• merchantClientsUdf → Client
• serviceClientsUdf → Client
• CLIENT_ACCOUNTS(c:Client)
define Client = Table[alias, code, perm, tag]
CLIENT_ACCOUNTS(merchantClientsUdf('us') union serviceClientsUdf('us‘))
CLIENT_ACCOUNTS(merchantClientsUdf('eu') union enhancedServiceClientsUdf('eu'))
CLIENT_ACCOUNTS(merchantClientsUdf('eu'))
• merchantClientsUdf → Client
• serviceClientsUdf → Client
• CLIENT_ACCOUNTS(c:Client)
• enhancedServiceClientsUdf → Client
Tables:
= almost 0 additional Technical Debt
Tables:
• merchantClientsUdf → Client
• serviceClientsUdf → Client
• CLIENT_ACCOUNTS(c:Client)
define Client = Table[alias, code, perm, tag]
CLIENT_ACCOUNTS(merchantClientsUdf('us') union serviceClientsUdf('us‘))
CLIENT_ACCOUNTS(merchantClientsUdf('eu') union serviceClientsUdf('eu'))
CLIENT_ACCOUNTS(merchantClientsUdf('eu'))
• merchantClientsUdf → Client
• serviceClientsUdf → Client
• CLIENT_ACCOUNTS(c:Client)
• enhancedServiceClientsUdf → Client
Tables:
There is no RDBMS in existence that does this!
Tables:
• merchantClientsUdf → Client
• serviceClientsUdf → Client
• CLIENT_ACCOUNTS(c:Client)
define Client = Table[alias, code, perm, tag]
CLIENT_ACCOUNTS(merchantClientsUdf('us') union serviceClientsUdf('us‘))
CLIENT_ACCOUNTS(merchantClientsUdf('eu') union serviceClientsUdf('eu'))
CLIENT_ACCOUNTS(merchantClientsUdf('eu'))
• merchantClientsUdf → Client
• serviceClientsUdf → Client
• CLIENT_ACCOUNTS(c:Client)
• enhancedServiceClientsUdf → Client
Tables:
What about ORM?
@Entity
class Registry {...}
@Entity
class MerchantClient {...}
@Entity
class ServiceClient {...}
@Entity
class Partnership {...}
@Entity
class Registry {...}
@Entity
class MerchantClient {...}
List<MerchantClient> merchantClients = em.createQuery(
"select distinct mc from Registry r, MerchantClient mc
where r.alias = mc.alias and r.market = :market and r.recordType = 'M'"
)
List<ServiceClient> serviceClients = em.createQuery(
"select distinct u from Registry r, ServiceClient sc, Partnership a
where r.alias = mc.alias and r.market = :market and r.recordType = 'S'"
)
@Entity
class ServiceClient {...}
@Entity
class Partnership {...}
@Entity
class Registry {...}
@Entity
class MerchantClient {...}
List<MerchantClient> merchantClients = em.createQuery(
"select distinct mc from Registry r, MerchantClient mc
where r.alias = mc.alias and r.market = :market and r.recordType = 'M'"
)
List<ServiceClient> serviceClients = em.createQuery(
"select distinct u from Registry r, ServiceClient sc, Partnership a
where r.alias = mc.alias and r.market = :market and r.recordType = 'S'"
)
@Entity
class ServiceClient {...}
@Entity
class Partnership {...}
How Can We Compose them???
merchantClients ++ serviceClients
@Entity
class AccountType {...}
@Entity
class Account {...}
@Entity
class DedicatedAccount {...}
@Entity
class AccountType {...}
@Entity
class Account {...}
@Entity
class DedicatedAccount {...}
List<Accounts> allAccounts() = em.createQuery(
"select distinct a from Account a, AccountType at
where a.accountType = at.type and "
)
List<Accounts> taggedAccounts(String tag) = em.createQuery(
"select distinct a from Account a, AccountType at
where a.accountType = at.type and a.tag = :tag"
)
List<Accounts> dedicatedAccounts(String alias) = em.createQuery(
"select distinct a from Account a, AccountType at, DedicatedAccount da
where a.accountType = at.type and da.account = a.name and da.alias = :alias"
)
List<Pair<Client, Account>> output = new ArrayList<>()
for (MerchantClient mc : merchantClients()) {
output.addAll(Tuple.of(mc, allAccounts()))
output.addAll(Tuple.of(taggedAccounts(mc.tag))
output.addAll(Tuple.of(dedicatedAccounts(mc.alias))
}
List<Pair<Client, Account>> output = new ArrayList<>()
for (ServiceClient sc : serviceClients()) {
output.addAll(Tuple.of(allAccounts()))
output.addAll(Tuple.of(taggedAccounts(sc.tag)))
output.addAll(Tuple.of(dedicatedAccounts(sc.alias)))
}
select merchantClients0_.alias as subsidiary1_0_ (MORE COLUMNS) from merchantClients
merchantClinets0_
where upper(merchantClients0_.alias) like ?
select merchantClients0_.alias as subsidiary1_0_ (MORE COLUMNS) from merchantClients
merchantClinets0_
where upper(merchantClients0_.alias) like ?
select merchantClients0_.alias as subsidiary1_0_ (MORE COLUMNS) from merchantClients
merchantClinets0_
where upper(merchantClients0_.alias) like ?
select merchantClients0_.alias as subsidiary1_0_ (MORE COLUMNS) from merchantClients
merchantClinets0_
where upper(merchantClients0_.alias) like ?
select merchantClients0_.alias as subsidiary1_0_ (MORE COLUMNS) from merchantClients
merchantClinets0_
where upper(merchantClients0_.alias) like ?
select merchantClients0_.alias as subsidiary1_0_ (MORE COLUMNS) from merchantClients
merchantClinets0_
where upper(merchantClients0_.alias) like ?
select merchantClients0_.alias as subsidiary1_0_ (MORE COLUMNS) from merchantClients
merchantClinets0_
where upper(merchantClients0_.alias) like ?
select merchantClients0_.alias as subsidiary1_0_ (MORE COLUMNS) from merchantClients
merchantClinets0_
where upper(merchantClients0_.alias) like ?
select merchantClients0_.alias as subsidiary1_0_ (MORE COLUMNS) from merchantClients
merchantClinets0_
where upper(merchantClients0_.alias) like ?
select merchantClients0_.alias as subsidiary1_0_ (MORE COLUMNS) from merchantClients
merchantClinets0_
where upper(merchantClients0_.alias) like ?
select merchantClients0_.alias as subsidiary1_0_ (MORE COLUMNS) from merchantClients
merchantClinets0_
where upper(merchantClients0_.alias) like ?
select merchantClients0_.alias as subsidiary1_0_ (MORE COLUMNS) from merchantClients
merchantClinets0_
where upper(merchantClients0_.alias) like ?
select merchantClients0_.alias as subsidiary1_0_ (MORE COLUMNS) from merchantClients
merchantClinets0_
where upper(merchantClients0_.alias) like ?
select merchantClients0_.alias as subsidiary1_0_ (MORE COLUMNS) from merchantClients
merchantClinets0_
where upper(merchantClients0_.alias) like ?
select merchantClients0_.alias as subsidiary1_0_ (MORE COLUMNS) from merchantClients
merchantClinets0_
where upper(merchantClients0_.alias) like ?
select merchantClients0_.alias as subsidiary1_0_ (MORE COLUMNS) from merchantClients
merchantClinets0_
where upper(merchantClients0_.alias) like ?
N+1
Criteria Queries?
List<MerchantClient> merchantClients() = em.createQuery(
select distinct mc from Registry r, MerchantClient mc
where r.alias = mc.alias and r.market = :market and r.recordType = 'M’)
Root<MerchantClient> fromMerchantClient = query.from(MerchantClient.class);
Join<MerchantClient, Registry> registry = fromUpdates.join("alias");
List<Predicate> conditions = new ArrayList();
conditions.add(builder.equal(registry.get("market"), market));
conditions.add(builder.equal(registry.get("recordType"), "M"));
TypedQuery<Update> typedQuery = em.createQuery(query
.select(fromMerchantClient)
.where(conditions.toArray(new Predicate[] {}))
.distinct(true)
);
I’ll Stick with HQL Thanks
List<MerchantClient> merchantClients() = em.createQuery(
select distinct mc from Registry r, MerchantClient mc
where r.alias = mc.alias and r.market = :market and r.recordType = 'M’)
Root<MerchantClient> fromMerchantClient = query.from(MerchantClient.class);
Join<MerchantClient, Registry> registry = fromUpdates.join("alias");
List<Predicate> conditions = new ArrayList();
conditions.add(builder.equal(registry.get("market"), market));
conditions.add(builder.equal(registry.get("recordType"), "M"));
TypedQuery<Update> typedQuery = em.createQuery(query
.select(fromMerchantClient)
.where(conditions.toArray(new Predicate[] {}))
.distinct(true)
);
ORM does not give us
define Client = Table[alias, code, perm, tag]
It just pretends it doesn’t exist!
* https://blog.codinghorror.com/object-relational-mapping-is-the-vietnam-of-computer-science/
What is SQL?
How can we do better?
SELECT DISTINCT
account.name, alias,
CASE (...) AS OFFICIAL_IDENTITY,
CASE (...)
FROM (
SELECT DISTINCT
mc.alias, mc.code, order_permission, mc.account_tag
FROM MERCHANT_CLIENTS mc
JOIN REGISTRY r ON ((alias) AND (otherConditions))
UNION ALL
SELECT DISTINCT
sc.alias, 'EV' AS code, part.order_permission, sc.account_tag
FROM SERVICE_CLIENTS sc
JOIN REGISTRY r ON ((alias) AND (otherConditions))
JOIN PARTNERSHIPS part ON (id <-> fk)) client
INNER JOIN (
dbo.ACCOUNTS account
INNER JOIN ACCOUNT_TYPES accountType ON (account_type)
LEFT JOIN DEDICATED_ACCOUNTS dedicated ON (account_number))
ON (possibly anything...)
OR (possibly the account tag...)
OR (possibly the alias...)
SELECT DISTINCT
account.name, alias,
CASE (...) AS OFFICIAL_IDENTITY,
CASE (...)
FROM (
SELECT DISTINCT
mc.alias, mc.code, order_permission, mc.account_tag
FROM MERCHANT_CLIENTS mc
JOIN REGISTRY r ON ((alias) AND (otherConditions))
UNION ALL
SELECT DISTINCT
sc.alias, 'EV' AS code, part.order_permission, sc.account_tag
FROM SERVICE_CLIENTS sc
JOIN REGISTRY r ON ((alias) AND (otherConditions))
JOIN PARTNERSHIPS part ON (id <-> fk)) client
INNER JOIN (
dbo.ACCOUNTS account
INNER JOIN ACCOUNT_TYPES accountType ON (account_type)
LEFT JOIN DEDICATED_ACCOUNTS dedicated ON (account_number))
ON (possibly anything...)
OR (possibly the account tag...)
OR (possibly the alias...)
𝝀( ) →(String, String, Char, String)
𝝀( ) →(Boolean)
SELECT DISTINCT
account.name, alias,
CASE (...) AS OFFICIAL_IDENTITY,
CASE (...)
FROM (
SELECT DISTINCT
mc.alias, mc.code, order_permission, mc.account_tag
FROM MERCHANT_CLIENTS mc
JOIN REGISTRY r ON ((alias) AND (otherConditions))
UNION ALL
SELECT DISTINCT
sc.alias, 'EV' AS code, part.order_permission, sc.account_tag
FROM SERVICE_CLIENTS sc
JOIN REGISTRY r ON ((alias) AND (otherConditions))
JOIN PARTNERSHIPS part ON (id <-> fk)) client
INNER JOIN (
dbo.ACCOUNTS account
INNER JOIN ACCOUNT_TYPES accountType ON (account_type)
LEFT JOIN DEDICATED_ACCOUNTS dedicated ON (account_number))
ON (possibly anything...)
OR (possibly the account tag...)
OR (possibly the alias...)
𝝀( ) →(String, String, Char, String)
𝝀( ) →(Boolean)
𝝀( ) →(String, String, Char, String)
𝝀( ) →(Boolean)
𝝀( ) →(Boolean)
SELECT DISTINCT
account.name, alias,
CASE (...) AS OFFICIAL_IDENTITY,
CASE (...)
FROM (
SELECT DISTINCT
mc.alias, mc.code, order_permission, mc.account_tag
FROM MERCHANT_CLIENTS mc
JOIN REGISTRY r ON ((alias) AND (otherConditions))
UNION ALL
SELECT DISTINCT
sc.alias, 'EV' AS code, part.order_permission, sc.account_tag
FROM SERVICE_CLIENTS sc
JOIN REGISTRY r ON ((alias) AND (otherConditions))
JOIN PARTNERSHIPS part ON (id <-> fk)) client
INNER JOIN (
dbo.ACCOUNTS account
INNER JOIN ACCOUNT_TYPES accountType ON (account_type)
LEFT JOIN DEDICATED_ACCOUNTS dedicated ON (account_number))
ON (possibly anything...)
OR (possibly the account tag...)
OR (possibly the alias...)
𝝀( ) →(String, String, Char, String)
𝝀( ) →(Boolean)
𝝀( ) →(String, String, Char, String)
𝝀( ) →(Boolean)
𝝀( ) →(Boolean)
𝝀( ) →(String, String, Char, String)
SELECT DISTINCT
account.name, alias,
CASE (...) AS OFFICIAL_IDENTITY,
CASE (...)
FROM (
SELECT DISTINCT
mc.alias, mc.code, order_permission, mc.account_tag
FROM MERCHANT_CLIENTS mc
JOIN REGISTRY r ON ((alias) AND (otherConditions))
UNION ALL
SELECT DISTINCT
sc.alias, 'EV' AS code, part.order_permission, sc.account_tag
FROM SERVICE_CLIENTS sc
JOIN REGISTRY r ON ((alias) AND (otherConditions))
JOIN PARTNERSHIPS part ON (id <-> fk)) client
INNER JOIN (
dbo.ACCOUNTS account
INNER JOIN ACCOUNT_TYPES accountType ON (account_type)
LEFT JOIN DEDICATED_ACCOUNTS dedicated ON (account_number))
ON (possibly anything...)
OR (possibly the account tag...)
OR (possibly the alias...)
𝝀( ) →(String, String, Char, String)
𝝀( ) →(Boolean)
𝝀( ) →(String, String, Char, String)
𝝀( ) →(Boolean)
𝝀( ) →(Boolean)
𝝀( ) →(String, String, Char, String)
𝝀( ) →(Boolean)
𝝀( ) →(Boolean)
𝝀( ) →(Boolean)
𝝀( ) →(Boolean)
𝝀( ) →(String, String, Int, String)
𝝀( ) →(String, Int)
𝝀( ) →(Int, String)
𝝀( ) →(Boolean)
SELECT DISTINCT
account.name, alias,
CASE (...) AS OFFICIAL_IDENTITY,
CASE (...)
FROM (
SELECT DISTINCT
mc.alias, mc.code, order_permission, mc.account_tag
FROM MERCHANT_CLIENTS mc
JOIN REGISTRY r ON ((alias) AND (otherConditions))
UNION ALL
SELECT DISTINCT
sc.alias, 'EV' AS code, part.order_permission, sc.account_tag
FROM SERVICE_CLIENTS sc
JOIN REGISTRY r ON ((alias) AND (otherConditions))
JOIN PARTNERSHIPS part ON (id <-> fk)) client
INNER JOIN (
dbo.ACCOUNTS account
INNER JOIN ACCOUNT_TYPES accountType ON (account_type)
LEFT JOIN DEDICATED_ACCOUNTS dedicated ON (account_number))
ON (possibly anything...)
OR (possibly the account tag...)
OR (possibly the alias...)
𝝀( ) →(String, String, Char, String)
𝝀( ) →(Boolean)
𝝀( ) →(String, String, Char, String)
𝝀( ) →(Boolean)
𝝀( ) →(Boolean)
𝝀( ) →(String, String, Char, String)
𝝀( ) →(Boolean)
𝝀( ) →(Boolean)
𝝀( ) →(Boolean)
𝝀( ) →(Boolean)
𝝀( ) →(String, String, String, String)
𝝀( ) →(String, String, Int, String)
𝝀( ) →(String, Int)
𝝀( ) →(Int, String)
𝝀( ) →(Boolean)
SELECT DISTINCT
account.name, alias,
CASE (...) AS OFFICIAL_IDENTITY,
CASE (...)
FROM (
SELECT DISTINCT
mc.alias, mc.code, order_permission, mc.account_tag
FROM MERCHANT_CLIENTS mc
JOIN REGISTRY r ON ((alias) AND (otherConditions))
UNION ALL
SELECT DISTINCT
sc.alias, 'EV' AS code, part.order_permission, sc.account_tag
FROM SERVICE_CLIENTS sc
JOIN REGISTRY r ON ((alias) AND (otherConditions))
JOIN PARTNERSHIPS part ON (id <-> fk)) client
INNER JOIN (
dbo.ACCOUNTS account
INNER JOIN ACCOUNT_TYPES accountType ON (account_type)
LEFT JOIN DEDICATED_ACCOUNTS dedicated ON (account_number))
ON (possibly anything...)
OR (possibly the account tag...)
OR (possibly the alias...)
𝑴(String, String, Char, String)
𝝀( ) →(Boolean)
𝑴(String, String, Char, String)
𝝀( ) →(Boolean)
𝝀( ) →(Boolean)
𝑴 →(String, String, Char, String)
𝝀( ) →(Boolean)
𝝀( ) →(Boolean)
𝝀( ) →(Boolean)
𝝀( ) →(Boolean)
𝑴(String, String, String, String)
𝑴(String, String, Int, String)
𝑴(String, Int)
𝑴(Int, String)
SELECT DISTINCT
account.name, alias,
CASE (...) AS OFFICIAL_IDENTITY,
CASE (...)
FROM (
SELECT DISTINCT
mc.alias, mc.code, order_permission, mc.account_tag
FROM MERCHANT_CLIENTS mc
JOIN REGISTRY r ON ((alias) AND (otherConditions))
UNION ALL
SELECT DISTINCT
sc.alias, 'EV' AS code, part.order_permission, sc.account_tag
FROM SERVICE_CLIENTS sc
JOIN REGISTRY r ON ((alias) AND (otherConditions))
JOIN PARTNERSHIPS part ON (id <-> fk)) client
INNER JOIN (
dbo.ACCOUNTS account
INNER JOIN ACCOUNT_TYPES accountType ON (account_type)
LEFT JOIN DEDICATED_ACCOUNTS dedicated ON (account_number))
ON (possibly anything...)
OR (possibly the account tag...)
OR (possibly the alias...)
𝑴(String, String, Char, String)
𝝀( ) →(Boolean)
𝑴(String, String, Char, String)
𝝀( ) →(Boolean)
𝝀( ) →(Boolean)
𝑴 →(String, String, Char, String)
𝝀( ) →(Boolean)
𝝀( ) →(Boolean)
𝝀( ) →(Boolean)
𝝀( ) →(Boolean)
𝑴(String, String, String, String)
𝑴(String, String, Int, String)
𝑴(String, Int)
𝑴(Int, String)
SELECT DISTINCT
account.name, alias,
CASE (...) AS OFFICIAL_IDENTITY,
CASE (...)
FROM (
SELECT DISTINCT
mc.alias, mc.code, order_permission, mc.account_tag
FROM MERCHANT_CLIENTS mc
JOIN REGISTRY r ON ((alias) AND (otherConditions))
UNION ALL
SELECT DISTINCT
sc.alias, 'EV' AS code, part.order_permission, sc.account_tag
FROM SERVICE_CLIENTS sc
JOIN REGISTRY r ON ((alias) AND (otherConditions))
JOIN PARTNERSHIPS part ON (id <-> fk)) client
INNER JOIN (
dbo.ACCOUNTS account
INNER JOIN ACCOUNT_TYPES accountType ON (account_type)
LEFT JOIN DEDICATED_ACCOUNTS dedicated ON (account_number))
ON (possibly anything...)
OR (possibly the account tag...)
OR (possibly the alias...)
𝑸𝒖𝒆𝒓𝒚[Client]
𝝀( ) →(Boolean)
𝑸𝒖𝒆𝒓𝒚 [Client]
𝝀( ) →(Boolean)
𝝀( ) →(Boolean)
𝑸𝒖𝒆𝒓𝒚 [Client]
𝝀( ) →(Boolean)
𝝀( ) →(Boolean)
𝝀( ) →(Boolean)
𝝀( ) →(Boolean)
𝑸𝒖𝒆𝒓𝒚[ClientAccountMapping]
𝑸𝒖𝒆𝒓𝒚[Account]
𝑸𝒖𝒆𝒓𝒚[AccountType]
𝑸𝒖𝒆𝒓𝒚[DedicatedAccount]
def merchantClientsUdf(market:String):Query[(String, String, Char, String)] = {
for {
mc <- mercantClients
r <- registry
if (r.alias === mc.alias && r.market === market
&& r.recordType === 'M')
} yield (mc.alias, mc.code, mc.orderPermission, mc.accountTag)
}
SELECT DISTINCT mc.alias, mc.code, order_permission, mc.account_tag
FROM MERCHANT_CLIENTS mc
JOIN REGISTRY r ON r.alias = mc.alias
WHERE r.market = 'us' AND r.record_type = 'M'
def serviceClientsUdf(market:String):Query[(String, String, Char, String)] = {
for {
sc <- serviceClients
r <- registry
if (r.alias === sc.alias && r.market === market
&& r.recordType === 'S')
part <- parnerships
if (part.id === sc.partnershipFk)
} yield (sc.alias, "EV".bind.?, part.orderPermission, sc.accountTag)
}
SELECT DISTINCT sc.alias, 'EV' AS code, part.order_permission, sc.account_tag
FROM SERVICE_CLIENTS sc
JOIN REGISTRY r ON r.alias = sc.alias AND r.record_type = 'S' AND r.market = 'us'
JOIN PARTNERSHIPS part ON part.id = sc.partnership_fk) client
def merchantClientsUdf(market:String):Query[(String, String, Char, String)] =
for {
mc <- mercantClients
r <- registry
if (r.alias === mc.alias && r.market === market && r.recordType === 'M')
} yield (mc.alias, mc.code, mc.orderPermission, mc.accountTag)
def serviceClientsUdf(market:String):Query[(String, String, Char, String)] =
for {
sc <- serviceClients
r <- registry
if (r.alias === sc.alias && r.market === market && r.recordType === 'S')
part <- parnerships
if (part.id === sc.partnershipFk)
} yield (sc.alias, "EV".bind.?, part.orderPermission, sc.accountTag)
def clients(market:String):Query[(String, String, Char, String)]
= merchantClientsUdf(market) ++ serviceClientsUdf(market)
def merchantClientsUdf(market:String):Query[Client] =
for {
mc <- mercantClients
r <- registry
if (r.alias === mc.alias && r.market === market && r.recordType === 'M')
} yield Client(mc.alias, mc.code, mc.orderPermission, mc.accountTag)
def serviceClientsUdf(market:String):Query[Client] =
for {
sc <- serviceClients
r <- registry
if (r.alias === sc.alias && r.market === market && r.recordType === 'S')
part <- parnerships
if (part.id === sc.partnershipFk)
} yield Client(sc.alias, "EV".bind.?, part.orderPermission, sc.accountTag)
def clients(market:String):Query[Client]
= merchantClientsUdf(market) ++ serviceClientsUdf(market)
def nonDedicatedAccounts = for {
account <- accounts
accountType <- accountTypes if (account.`type` === accountType.accountType)
} yield (account, accountType)
def allAccounts = for {
((account, accountType), dedicatedAccount) <- nonDedicatedAccounts.joinLeft(dedicatedAccounts)
.on({case ((a, at), d) => (a.number === d.accountNumber)})
} yield (account, accountType, dedicatedAccount)
def mappingConditionsMet(mappingType:Rep[Int], accountTag:Rep[String], clientTag:Rep[String], clientAlias:Rep[String], dedicatedAlias:Rep[String]):Rep[Int] =
Case.If(mappingType === 0).Then(1)
.If(mappingType === 2 && accountTag === clientTag).Then(1)
.If(mappingType === 1 && clientAlias === dedicatedAlias).Then(1)
.Else(0)
def accountMapping(clients:Query[Client]):Query[Clients,Accounts,AccountTypes,Option[DedicatedAccounts]]
for {
(account, accountType, dedicatedAccount) <- allAccounts
client <- clients if (mappingConditionsMet(
accountType.mappingType.oz, account.tag.oe,
client.tag.oe, client.alias.oe, dedicatedAccount.map(_.clientAlias).flatten.oe) == 1)
} yield (client, account, accountType, dedicatedAccount)
SELECT DISTINCT (...)
FROM (...)
INNER JOIN (
dbo.ACCOUNTS account
INNER JOIN ACCOUNT_TYPES accountType ON account.type = accountType.account_type
LEFT JOIN DEDICATED_ACCOUNTS dedicated ON dedicated.account_number = account.number)
ON (accountType.mapping_type = 0)
OR (accountType.mapping_type = 2 AND account.tag = client.account_tag)
OR (accountType.mapping_type = 1 AND dedicated.client_alias = client.alias)
def render(
query: Query[(Client, Accounts, AccountTypes, Option[DedicatedAccounts])]) = {
for {
(client, account, accountType, dedicatedAccount) <- query
} yield (
account.name,
Case.If(client.code === "EV")
.Then(account.number.asString)
.Else(account.number.asString.substring(1,2)),
Case.If(client.permission.min.inSet(Seq('A','S'))).Then("ST").Else("ENH")
)
}
SELECT DISTINCT
account.name, alias,
CASE WHEN code = 'EV'
THEN cast(account.number AS VARCHAR)
ELSE cast(account.number AS VARCHAR) + substring(alias, 1, 2) END AS OFFICIAL_IDENTITY,
CASE WHEN order_permission IN ('A', 'S')
THEN 'ST' ELSE 'ENH' END
def usClientAccounts =
render(accountMapping(clients("us")))
def render(
query: Query[(Client, Accounts, AccountTypes, Option[DedicatedAccounts])]) = {
for {
(client, account, accountType, dedicatedAccount) <- query
} yield (
account.name,
Case.If(client.code === "EV")
.Then(account.number.asString)
.Else(account.number.asString.substring(1,2)),
Case.If(client.permission.min.inSet(Seq('A','S'))).Then("ST").Else("ENH")
)
}
SELECT DISTINCT
account.name, alias,
CASE WHEN code = 'EV'
THEN cast(account.number AS VARCHAR)
ELSE cast(account.number AS VARCHAR) + substring(alias, 1, 2) END AS OFFICIAL_IDENTITY,
CASE WHEN order_permission IN ('A', 'S')
THEN 'ST' ELSE 'ENH' END
New Requirements… Re-examined
1.New European Business Unit
with Client Codes from
the Partnership
2.New Canadian Business Unit
without Service Clients
Can We Do Better?
def serviceClientsUdf(market:String) =
for {
sc <- serviceClients
r <- registry if (r.alias === sc.alias && r.market === market && r.recordType === 'S')
part <- parnerships if (part.id === sc.partnershipFk)
} yield (Client(sc.alias, "EV".bind.?, part.orderPermission, sc.accountTag))
def serviceClientsUdfEnhanced(market:String) =
for {
sc <- serviceClients
r <- registry if (r.alias === sc.alias && r.market === market && r.recordType === 'S')
part <- parnerships if (part.id === sc.partnershipFk)
pc <- parnershipCodes if (part.id === pc.partnershipFk)
} yield (Client(sc.alias, pc.code, part.orderPermission, sc.accountTag))
Here is How
def serviceClientsDual(market:String, usePartnershipCodes:Boolean) = {
val clientsAndPartnerships = for {
sc <- serviceClients
r <- registry if (r.alias === sc.alias && r.market === market && r.recordType === 'S')
part <- parnerships if (part.id === sc.partnershipFk)
} yield (sc.alias, part.orderPermission, sc.accountTag, part.id)
usePartnershipCodes match {
case true => for {
(alias, permission, tag, partnershipId) <- clientsAndPartnerships
pc <- parnershipCodes if (partnershipId === pc.partnershipFk)
} yield Client(alias, pc.code, permission, tag)
case false => for {
(alias, permission, tag, partnershipId) <- clientsAndPartnerships
} yield Client(alias, "EV".bind.?, permission, tag)
}
}
def mapAndRender(clients:Query[Client, ClientRow, scala.Seq]) =
render(accountMapping(clients))
def usClientAccounts =
mapAndRender(serviceClientsDual("us", false) ++ mercantClientsUdf("us"))
def euClientAccounts =
mapAndRender(serviceClientsDual("eu", true) ++ mercantClientsUdf("eu"))
def caClientAccounts = mapAndRender(mercantClientsUdf("ca"))
Better!
def merchantClientsUdf(market:String):Query[Client] =
for {
mc <- mercantClients
r <- registry
if (r.alias === mc.alias && r.market === market && r.recordType === 'M')
} yield Client(mc.alias, mc.code, mc.orderPermission, mc.accountTag)
def serviceClientsUdf(market:String):Query[Client] =
for {
sc <- serviceClients
r <- registry
if (r.alias === sc.alias && r.market === market && r.recordType === 'S')
part <- parnerships
if (part.id === sc.partnershipFk)
} yield Client(sc.alias, "EV".bind.?, part.orderPermission, sc.accountTag)
Registry is Just a Filter…
filterByRegistry(q, recordType)
Query[Service or Merchant Client]
Query[Service or Merchant Client]
filterByRegistry(q, recordType, f)
Query[T] +
Query[T]
f(T)→SomeFieldToJoin
def filterByRegistry[E, U](q:Query[E, U, Seq],
recordType:Char, market:String)(f:(E) => Rep[String])(
implicit shape: Shape[_ <: FlatShapeLevel, E, U, E]):Query[E, U, Seq] = {
for {
record <- q
r <- registry if (f(record) === r.alias && r.recordType === recordType
&& r.market === market)
} yield (record)
}
def merchantClientsUdf(market:String) = {
for {
mc <- filterByRegistry(mercantClients, 'M', market)(_.alias.oe)
} yield (Client(mc.alias, mc.code, mc.orderPermission, mc.accountTag))
}
def serviceClientsUdf(market:String) = {
for {
sc <- filterByRegistry(serviceClients, 'M', market)(_.alias.oe)
part <- parnerships if (part.id === sc.partnershipFk)
} yield (Client(sc.alias, "EV".bind.?, part.orderPermission, sc.accountTag))
}
Better!
Some Caveats
• Query[(String, String, Char, String)]
• Query[(Option[String], Option[String], Option[Char], Option[String])]
• Query[(Rep[Option[String]], Rep[Option[String]], Rep[Option[Char]], Rep[Option[String]])]
• Query[(Rep[Option[String]], Rep[Option[String]], Rep[Option[Char]], Rep[Option[String]]),
(Option[String], Option[String], Option[Char], Option[String]),
Seq]
• Query[Client], Client(String, String, Char, String)
• Query[Client], Client(Option[String], Option[String], Option[Char], Option[String])
• Query[Client, ClientRow, Seq]
Client(Rep[Option[String]], Rep[Option[String]], Rep[Option[Char]], Rep[Option[String]])
ClientRow(Option[String], Option[String], Option[Char], Option[String],
Seq)
Type Inferencing mostly does this for us
Some Caveats
• Query[(String, String, Char, String)]
• Query[(Option[String], Option[String], Option[Char], Option[String])]
• Query[(Rep[Option[String]], Rep[Option[String]], Rep[Option[Char]], Rep[Option[String]])]
• Query[(Rep[Option[String]], Rep[Option[String]], Rep[Option[Char]], Rep[Option[String]]),
(Option[String], Option[String], Option[Char], Option[String]),
Seq]
• Query[Client], Client(String, String, Char, String)
• Query[Client], Client(Option[String], Option[String], Option[Char], Option[String])
• Query[Client, ClientRow, Seq]
Client(Rep[Option[String]], Rep[Option[String]], Rep[Option[Char]], Rep[Option[String]])
ClientRow(Option[String], Option[String], Option[Char], Option[String],
Seq)
Type Inferencing mostly does this for us
Some Caveats
• Query[(String, String, Char, String)]
• Query[(Option[String], Option[String], Option[Char], Option[String])]
• Query[(Rep[Option[String]], Rep[Option[String]], Rep[Option[Char]], Rep[Option[String]])]
• Query[(Rep[Option[String]], Rep[Option[String]], Rep[Option[Char]], Rep[Option[String]]),
(Option[String], Option[String], Option[Char], Option[String]),
Seq]
• Query[Client], Client(String, String, Char, String)
• Query[Client], Client(Option[String], Option[String], Option[Char], Option[String])
• Query[Client, ClientRow, Seq]
Client(Rep[Option[String]], Rep[Option[String]], Rep[Option[Char]], Rep[Option[String]])
ClientRow(Option[String], Option[String], Option[Char], Option[String],
Seq)
Type Inferencing mostly does this for us
Some Caveats
• Query[(String, String, Char, String)]
• Query[(Option[String], Option[String], Option[Char], Option[String])]
• Query[(Rep[Option[String]], Rep[Option[String]], Rep[Option[Char]], Rep[Option[String]])]
• Query[(Rep[Option[String]], Rep[Option[String]], Rep[Option[Char]], Rep[Option[String]]),
(Option[String], Option[String], Option[Char], Option[String]),
Seq]
• Query[Client], Client(String, String, Char, String)
• Query[Client], Client(Option[String], Option[String], Option[Char], Option[String])
• Query[Client, ClientRow, Seq]
Client(Rep[Option[String]], Rep[Option[String]], Rep[Option[Char]], Rep[Option[String]])
ClientRow(Option[String], Option[String], Option[Char], Option[String],
Seq)
Type Inferencing mostly does this for us
Some Caveats
• Query[(String, String, Char, String)]
• Query[(Option[String], Option[String], Option[Char], Option[String])]
• Query[(Rep[Option[String]], Rep[Option[String]], Rep[Option[Char]], Rep[Option[String]])]
• Query[(Rep[Option[String]], Rep[Option[String]], Rep[Option[Char]], Rep[Option[String]]),
(Option[String], Option[String], Option[Char], Option[String]),
Seq]
• Query[Client], Client(String, String, Char, String)
• Query[Client], Client(Option[String], Option[String], Option[Char], Option[String])
• Query[Client, ClientRow, Seq]
Client(Rep[Option[String]], Rep[Option[String]], Rep[Option[Char]], Rep[Option[String]])
ClientRow(Option[String], Option[String], Option[Char], Option[String],
Seq)
Type Inferencing mostly does this for us
Some Caveats
• Query[(String, String, Char, String)]
• Query[(Option[String], Option[String], Option[Char], Option[String])]
• Query[(Rep[Option[String]], Rep[Option[String]], Rep[Option[Char]], Rep[Option[String]])]
• Query[(Rep[Option[String]], Rep[Option[String]], Rep[Option[Char]], Rep[Option[String]]),
(Option[String], Option[String], Option[Char], Option[String]),
Seq]
• Query[Client], Client(String, String, Char, String)
• Query[Client], Client(Option[String], Option[String], Option[Char], Option[String])
• Query[Client, ClientRow, Seq]
Client(Rep[Option[String]], Rep[Option[String]], Rep[Option[Char]], Rep[Option[String]])
ClientRow(Option[String], Option[String], Option[Char], Option[String],
Seq)
Type Inferencing mostly does this for us
Some Caveats
• Query[(String, String, Char, String)]
• Query[(Option[String], Option[String], Option[Char], Option[String])]
• Query[(Rep[Option[String]], Rep[Option[String]], Rep[Option[Char]], Rep[Option[String]])]
• Query[(Rep[Option[String]], Rep[Option[String]], Rep[Option[Char]], Rep[Option[String]]),
(Option[String], Option[String], Option[Char], Option[String]),
Seq]
• Query[Client], Client(String, String, Char, String)
• Query[Client], Client(Option[String], Option[String], Option[Char], Option[String])
• Query[Client, ClientRow, Seq]
Client(Rep[Option[String]], Rep[Option[String]], Rep[Option[Char]], Rep[Option[String]])
ClientRow(Option[String], Option[String], Option[Char], Option[String],
Seq)
Type Inferencing mostly does this for us
Conclusions
• Scala solves Old and New Problems in great ways!
• Check out Scala’s No-ORM Frameworks:
Slick - http://slick.lightbend.com/
Quill - http://getquill.io/

Más contenido relacionado

La actualidad más candente

Everything you always wanted to know about forms* *but were afraid to ask
Everything you always wanted to know about forms* *but were afraid to askEverything you always wanted to know about forms* *but were afraid to ask
Everything you always wanted to know about forms* *but were afraid to askAndrea Giuliano
 
Taming forms with React
Taming forms with ReactTaming forms with React
Taming forms with ReactGreeceJS
 
Job centre presentation
Job centre presentationJob centre presentation
Job centre presentationMunavvar Patel
 

La actualidad más candente (6)

Les20
Les20Les20
Les20
 
Everything you always wanted to know about forms* *but were afraid to ask
Everything you always wanted to know about forms* *but were afraid to askEverything you always wanted to know about forms* *but were afraid to ask
Everything you always wanted to know about forms* *but were afraid to ask
 
Taming forms with React
Taming forms with ReactTaming forms with React
Taming forms with React
 
Job centre presentation
Job centre presentationJob centre presentation
Job centre presentation
 
DDl
DDlDDl
DDl
 
Sql commands
Sql commandsSql commands
Sql commands
 

Similar a OOP Theory vs Practice in SQL

Shangz R Brown Presentation
Shangz R Brown PresentationShangz R Brown Presentation
Shangz R Brown Presentationshangbaby
 
Below is my code- I have an error that I still have difficulty figurin.pdf
Below is my code- I have an error that I still have difficulty figurin.pdfBelow is my code- I have an error that I still have difficulty figurin.pdf
Below is my code- I have an error that I still have difficulty figurin.pdfarmanuelraj
 
How to transfer bad PLSQL into good (AAAPEKS23)
How to transfer bad PLSQL into good (AAAPEKS23)How to transfer bad PLSQL into good (AAAPEKS23)
How to transfer bad PLSQL into good (AAAPEKS23)Maik Becker
 
Security Slicing for Auditing XML, XPath, and SQL Injection Vulnerabilities
Security Slicing for Auditing XML, XPath, and SQL Injection VulnerabilitiesSecurity Slicing for Auditing XML, XPath, and SQL Injection Vulnerabilities
Security Slicing for Auditing XML, XPath, and SQL Injection VulnerabilitiesLionel Briand
 
Finance data model
Finance data modelFinance data model
Finance data modelsridhark1981
 
A Tour to MySQL Commands
A Tour to MySQL CommandsA Tour to MySQL Commands
A Tour to MySQL CommandsHikmat Dhamee
 
Swift 성능 이해하기
Swift 성능 이해하기Swift 성능 이해하기
Swift 성능 이해하기Hangyeol Lee
 

Similar a OOP Theory vs Practice in SQL (12)

Actividad 1
Actividad 1Actividad 1
Actividad 1
 
Shangz R Brown Presentation
Shangz R Brown PresentationShangz R Brown Presentation
Shangz R Brown Presentation
 
c_tutorial_2.ppt
c_tutorial_2.pptc_tutorial_2.ppt
c_tutorial_2.ppt
 
Clean code
Clean codeClean code
Clean code
 
Below is my code- I have an error that I still have difficulty figurin.pdf
Below is my code- I have an error that I still have difficulty figurin.pdfBelow is my code- I have an error that I still have difficulty figurin.pdf
Below is my code- I have an error that I still have difficulty figurin.pdf
 
How to transfer bad PLSQL into good (AAAPEKS23)
How to transfer bad PLSQL into good (AAAPEKS23)How to transfer bad PLSQL into good (AAAPEKS23)
How to transfer bad PLSQL into good (AAAPEKS23)
 
Fin data model
Fin data modelFin data model
Fin data model
 
Security Slicing for Auditing XML, XPath, and SQL Injection Vulnerabilities
Security Slicing for Auditing XML, XPath, and SQL Injection VulnerabilitiesSecurity Slicing for Auditing XML, XPath, and SQL Injection Vulnerabilities
Security Slicing for Auditing XML, XPath, and SQL Injection Vulnerabilities
 
Finance data model
Finance data modelFinance data model
Finance data model
 
A Tour to MySQL Commands
A Tour to MySQL CommandsA Tour to MySQL Commands
A Tour to MySQL Commands
 
Functional DDD
Functional DDDFunctional DDD
Functional DDD
 
Swift 성능 이해하기
Swift 성능 이해하기Swift 성능 이해하기
Swift 성능 이해하기
 

Último

Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...OnePlan Solutions
 
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfkalichargn70th171
 
Test Automation Strategy for Frontend and Backend
Test Automation Strategy for Frontend and BackendTest Automation Strategy for Frontend and Backend
Test Automation Strategy for Frontend and BackendArshad QA
 
Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...OnePlan Solutions
 
Diamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionDiamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionSolGuruz
 
How To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.jsHow To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.jsAndolasoft Inc
 
Right Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsRight Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsJhone kinadey
 
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...kellynguyen01
 
5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdfWave PLM
 
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...harshavardhanraghave
 
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdfThe Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdfkalichargn70th171
 
Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVshikhaohhpro
 
A Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxA Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxComplianceQuest1
 
DNT_Corporate presentation know about us
DNT_Corporate presentation know about usDNT_Corporate presentation know about us
DNT_Corporate presentation know about usDynamic Netsoft
 
Software Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsSoftware Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsArshad QA
 
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...MyIntelliSource, Inc.
 
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerHow To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerThousandEyes
 
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...gurkirankumar98700
 

Último (20)

Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
 
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
 
Test Automation Strategy for Frontend and Backend
Test Automation Strategy for Frontend and BackendTest Automation Strategy for Frontend and Backend
Test Automation Strategy for Frontend and Backend
 
Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...
 
Diamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionDiamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with Precision
 
How To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.jsHow To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.js
 
Right Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsRight Money Management App For Your Financial Goals
Right Money Management App For Your Financial Goals
 
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
 
5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf
 
Exploring iOS App Development: Simplifying the Process
Exploring iOS App Development: Simplifying the ProcessExploring iOS App Development: Simplifying the Process
Exploring iOS App Development: Simplifying the Process
 
Vip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS Live
Vip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS LiveVip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS Live
Vip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS Live
 
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
 
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdfThe Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
 
Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTV
 
A Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxA Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docx
 
DNT_Corporate presentation know about us
DNT_Corporate presentation know about usDNT_Corporate presentation know about us
DNT_Corporate presentation know about us
 
Software Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsSoftware Quality Assurance Interview Questions
Software Quality Assurance Interview Questions
 
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
 
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerHow To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
 
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
 

OOP Theory vs Practice in SQL

  • 2. OOP Theory vs Practice
  • 3. Theory class Cat extends Animal { ... } Practice class ManagerFactory extends Factory { ... } Noun Verb
  • 4. Theory class Cat extends Animal { ... } Practice class ManagerFactory extends Factory { Manager construct() {…} } <- The Real verb * https://steve-yegge.blogspot.com/2006/03/execution-in-kingdom-of-nouns.html Noun Verb Chaperone
  • 5. SQL Theory vs Practice
  • 7. Theory Practice select (…) from Really, really complicated stuff VerbsNouns
  • 8. Theory Practice Specification Driven + Minimize Incidental Complexity Nouns Verbs
  • 9. Theory Nouns Verbs Practice Constructed Ad-Hoc = Maximize Incidental Complexity
  • 11. SELECT DISTINCT account.name, alias, CASE WHEN code = 'EV' THEN cast(account.number AS VARCHAR) ELSE cast(account.number AS VARCHAR) + substring(alias, 1, 2) END AS OFFICIAL_IDENTITY, CASE WHEN order_permission IN ('A', 'S') THEN 'ST' ELSE 'ENH' END FROM ( SELECT DISTINCT mc.alias, mc.code, order_permission, mc.account_tag FROM MERCHANT_CLIENTS mc JOIN REGISTRY r ON r.alias = mc.alias WHERE r.market = 'us' AND r.record_type = 'M' UNION ALL SELECT DISTINCT sc.alias, 'EV' AS code, part.order_permission, sc.account_tag FROM SERVICE_CLIENTS sc JOIN REGISTRY r ON r.alias = sc.alias AND r.record_type = 'S' AND r.market = 'us' JOIN PARTNERSHIPS part ON part.id = sc.partnership_fk) client INNER JOIN ( dbo.ACCOUNTS account INNER JOIN ACCOUNT_TYPES accountType ON account.type = accountType.account_type LEFT JOIN DEDICATED_ACCOUNTS dedicated ON dedicated.account_number = account.number) ON (accountType.mapping_type = 0) OR (accountType.mapping_type = 2 AND account.tag = client.account_tag) OR (accountType.mapping_type = 1 AND dedicated.client_alias = client.alias)
  • 12. UML?
  • 13. SELECT DISTINCT account.name, alias, CASE (...) AS OFFICIAL_IDENTITY, CASE (...) FROM ( SELECT DISTINCT mc.alias, mc.code, order_permission, mc.account_tag (code, alias, perm, tag) FROM MERCHANT_CLIENTS mc JOIN REGISTRY r ON (alias) AND (otherConditions) UNION ALL SELECT DISTINCT sc.alias, 'EV' AS code, part.order_permission, sc.account_tag (code, alias, perm, tag) FROM SERVICE_CLIENTS sc JOIN REGISTRY r ON (alias) AND (otherConditions) JOIN PARTNERSHIPS part ON (id <-> fk)) client INNER JOIN ( dbo.ACCOUNTS account INNER JOIN ACCOUNT_TYPES accountType ON (account_type) LEFT JOIN DEDICATED_ACCOUNTS dedicated ON (account_number) ) ON (possibly anything...) OR (possibly the account tag...) OR (possibly the alias...) → All Depending on the accountType
  • 14. SELECT DISTINCT account.name, alias, CASE (...) AS OFFICIAL_IDENTITY, CASE (...) FROM ( SELECT DISTINCT mc.alias, mc.code, order_permission, mc.account_tag (code, alias, perm, tag) FROM MERCHANT_CLIENTS mc JOIN REGISTRY r ON (alias) AND (otherConditions) UNION ALL SELECT DISTINCT sc.alias, 'EV' AS code, part.order_permission, sc.account_tag (code, alias, perm, tag) FROM SERVICE_CLIENTS sc JOIN REGISTRY r ON (alias) AND (otherConditions) JOIN PARTNERSHIPS part ON (id <-> fk)) client INNER JOIN ( dbo.ACCOUNTS account INNER JOIN ACCOUNT_TYPES accountType ON (account_type) LEFT JOIN DEDICATED_ACCOUNTS dedicated ON (account_number) ) ON (possibly anything...) OR (possibly the account tag...) OR (possibly the alias...) → All Depending on the accountType
  • 15. SELECT DISTINCT account.name, alias, CASE (...) AS OFFICIAL_IDENTITY, CASE (...) FROM ( SELECT DISTINCT mc.alias, mc.code, order_permission, mc.account_tag (code, alias, perm, tag) FROM MERCHANT_CLIENTS mc JOIN REGISTRY r ON (alias) AND (otherConditions) UNION ALL SELECT DISTINCT sc.alias, 'EV' AS code, part.order_permission, sc.account_tag (code, alias, perm, tag) FROM SERVICE_CLIENTS sc JOIN REGISTRY r ON (alias) AND (otherConditions) JOIN PARTNERSHIPS part ON (id <-> fk)) client INNER JOIN ( dbo.ACCOUNTS account INNER JOIN ACCOUNT_TYPES accountType ON (account_type) LEFT JOIN DEDICATED_ACCOUNTS dedicated ON (account_number) ) ON (possibly anything...) OR (possibly the account tag...) OR (possibly the alias...) → All Depending on the accountType Alias RecType Mkt Description ACMC M ca ACME Canada. ACME M us ACME Corp. ACMI M eu ACME International Corp. FNF S us Frin and Flyn Association FNJ S us Krueger and Voorhees Alliance Alias Code Perm ACME INC T ACMI INC T ACMC INC T ALIAS FK Account Tag YOGL 1 YOG FNF 2 SID FNJ 3 FF ID PERM DESCRIPTION 1 S Y.G. Schwartz Supplies Procurement 2 T Frin and Flyn Procurement 3 H Special Individuals Fulfillment 4 H Special Individuals Fulfillment International Alias Code Perm Tag ACME INC T ACMI INC T ACMC INC T YOGL S S YOG FNF T T SID FNJ H H FF
  • 16. SELECT DISTINCT account.name, alias, CASE (...) AS OFFICIAL_IDENTITY, CASE (...) FROM (...) client INNER JOIN ( dbo.ACCOUNTS account INNER JOIN ACCOUNT_TYPES accountType ON (account_type) LEFT JOIN DEDICATED_ACCOUNTS dedicated ON (account_number) ) ON (accountType.mapping_type = 0) OR (possibly the account tag...) OR (possibly the alias...) name alias OFFICIAL_IDENTITY perm TUNV FNF 111 ENH TUNV ACME 111AC ENH SIADV FNF 456 ENH AUNV FNF 222 ENH AUNV ACME 222AC ENH ACMEINV ACME 808AC ENH YOGADV YOGL 123 ST TUNV YOGL 111 ST AUNV YOGL 222 ST
  • 17. SELECT DISTINCT account.name, alias, CASE (...) AS OFFICIAL_IDENTITY, CASE (...) FROM (...) client INNER JOIN ( dbo.ACCOUNTS account INNER JOIN ACCOUNT_TYPES accountType ON (account_type) LEFT JOIN DEDICATED_ACCOUNTS dedicated ON (account_number) ) ON (possibly anything...) OR (accountType.mapping_type = 2 AND account.tag = client.account_tag) OR (possibly the alias...) name alias OFFICIAL_IDENTITY perm TUNV FNF 111 ENH TUNV ACME 111AC ENH SIADV FNF 456 ENH AUNV FNF 222 ENH AUNV ACME 222AC ENH ACMEINV ACME 808AC ENH YOGADV YOGL 123 ST TUNV YOGL 111 ST AUNV YOGL 222 ST
  • 18. SELECT DISTINCT account.name, alias, CASE (...) AS OFFICIAL_IDENTITY, CASE (...) FROM (...) client INNER JOIN ( dbo.ACCOUNTS account INNER JOIN ACCOUNT_TYPES accountType ON (account_type) LEFT JOIN DEDICATED_ACCOUNTS dedicated ON (account_number) ) ON (possibly anything...) OR (possibly the account tag...) OR (accountType.mapping_type = 1 AND dedicated.client_alias = client.alias) name alias OFFICIAL_IDENTITY perm TUNV FNF 111 ENH TUNV ACME 111AC ENH SIADV FNF 456 ENH AUNV FNF 222 ENH AUNV ACME 222AC ENH ACMEINV ACME 808AC ENH YOGADV YOGL 123 ST TUNV YOGL 111 ST AUNV YOGL 222 ST
  • 20. SELECT DISTINCT account.name, alias, CASE WHEN code = 'EV' THEN cast(account.number AS VARCHAR) ELSE cast(account.number AS VARCHAR) + substring(alias, 1, 2) END AS OFFICIAL_IDENTITY, CASE WHEN order_permission IN ('A', 'S') THEN 'ST' ELSE 'ENH' END FROM ( SELECT DISTINCT mc.alias, mc.code, order_permission, mc.account_tag FROM MERCHANT_CLIENTS mc JOIN REGISTRY r ON r.alias = mc.alias WHERE r.market = 'us' AND r.record_type = 'M' UNION ALL SELECT DISTINCT sc.alias, 'EV' AS code, part.order_permission, sc.account_tag FROM SERVICE_CLIENTS sc JOIN REGISTRY r ON r.alias = sc.alias AND r.record_type = 'S' AND r.market = 'us' JOIN PARTNERSHIPS part ON part.id = sc.partnership_fk) client INNER JOIN ( dbo.ACCOUNTS account INNER JOIN ACCOUNT_TYPES accountType ON account.type = accountType.account_type LEFT JOIN DEDICATED_ACCOUNTS dedicated ON dedicated.account_number = account.number) ON (accountType.mapping_type = 0) OR (accountType.mapping_type = 2 AND account.tag = client.account_tag) OR (accountType.mapping_type = 1 AND dedicated.client_alias = client.alias)
  • 21. WITH merchantClients AS ( SELECT DISTINCT mc.alias, mc.code, order_permission, mc.account_tag FROM MERCHANT_CLIENTS mc JOIN REGISTRY r ON r.alias = mc.alias), serviceClients AS (SELECT DISTINCT sc.alias, 'EV' AS code, partnership.order_permission, sc.account_tag FROM SERVICE_CLIENTS sc JOIN REGISTRY r ON r.alias = sc.alias AND r.record_type = 'S' AND r.market = 'us' JOIN PARTNERSHIPS partnership ON partnership.id = sc.partnership_fk), client AS (SELECT * FROM merchantClients UNION ALL SELECT * FROM serviceClients) SELECT DISTINCT account.name, alias, CASE WHEN code = 'EV' THEN cast(account.number AS VARCHAR) ELSE cast(account.number AS VARCHAR) + substring(alias, 1, 2) END AS OFFICIAL_IDENTITY, CASE WHEN order_permission IN ('A', 'S') THEN 'ST' ELSE 'ENH' END FROM client INNER JOIN ( dbo.ACCOUNTS account INNER JOIN ACCOUNT_TYPES accountType ON account.type = accountType.account_type LEFT JOIN DEDICATED_ACCOUNTS dedicated ON dedicated.account_number = account.number) ON (accountType.mapping_type = 0) OR (accountType.mapping_type = 2 AND account.tag = client.account_tag) OR (accountType.mapping_type = 1 AND dedicated.client_alias = client.alias)
  • 22. CREATE VIEW MERCHANT_CLIENTS_V AS SELECT DISTINCT mc.alias, mc.code, order_permission, mc.account_tag FROM MERCHANT_CLIENTS mc JOIN REGISTRY entry ON entry.alias = mc.alias WHERE entry.market = 'us' AND entry.record_type = 'M' CREATE VIEW SERVICE_CLIENTS_V AS SELECT DISTINCT sc.alias, 'EV' AS code, partnership.order_permission, sc.account_tag FROM SERVICE_CLIENTS sc JOIN REGISTRY entry ON entry.alias = sc.alias AND entry.record_type = 'S' AND entry.market = 'us' JOIN PARTNERSHIPS partnership ON partnership.id = sc.partnership_fk CREATE VIEW CLIENTS AS SELECT * FROM MERCHANT_CLIENTS_V UNION ALL SELECT * FROM SERVICE_CLIENTS_V
  • 23. CREATE VIEW MERCHANT_CLIENTS_V AS SELECT DISTINCT (...) FROM MERCHANT_CLIENTS mc JOIN REGISTRY entry ON entry.alias = mc.alias WHERE entry.market = 'us' AND entry.record_type = 'M' CREATE VIEW SERVICE_CLIENTS_V AS SELECT DISTINCT (...) FROM SERVICE_CLIENTS sc JOIN REGISTRY entry ON entry.alias = sc.alias AND entry.record_type = 'S' AND entry.market = 'us' JOIN PARTNERSHIPS partnership ON partnership.id = sc.partnership_fk CREATE VIEW CLIENT_ACCOUNTS AS SELECT DISTINCT account.name, alias, CASE WHEN code = 'EV' THEN cast(account.number AS VARCHAR) ELSE cast(account.number AS VARCHAR) + substring(alias, 1, 2) END AS OFFICIAL_IDENTITY, CASE WHEN order_permission IN ('A', 'S') THEN 'ST' ELSE 'ENH' END FROM CLIENTS AS client INNER JOIN ( dbo.ACCOUNTS account INNER JOIN ACCOUNT_TYPES accountType ON account.type = accountType.account_type LEFT JOIN DEDICATED_ACCOUNTS dedicated ON dedicated.account_number = account.number) ON (accountType.mapping_type = 0) OR (accountType.mapping_type = 2 AND account.tag = client.account_tag) OR (accountType.mapping_type = 1 AND dedicated.client_alias = client.alias) CREATE VIEW CLIENTS AS SELECT * FROM MERCHANT_CLIENTS_V UNION ALL SELECT * FROM SERVICE_CLIENTS_V
  • 24. New Requirements 1.New European Business Unit with Client Codes from the Partnership 2.New Canadian Business Unit without Service Clients
  • 25. CREATE VIEW EU_MERCHANT_CLIENTS AS SELECT DISTINCT (...) FROM MERCHANT_CLIENTS mc JOIN REGISTRY entry ON entry.alias = mc.alias WHERE entry.market = 'eu' AND entry.record_type = 'M' CREATE VIEW EU_SERVICE_CLIENTS AS SELECT DISTINCT (... pc.code, ...) FROM SERVICE_CLIENTS sc JOIN REGISTRY entry ON entry.alias = sc.alias AND entry.record_type = 'S' AND entry.market = 'eu' JOIN PARTNERSHIPS partnership ON partnership.id = sc.partnership_fk JOIN PARTNERSHIP_CODES pc ON partnership.ID = pc.partnership_fk CREATE VIEW EU_CLIENT_ACCOUNTS AS SELECT DISTINCT account.name, alias, CASE WHEN code = 'EV' THEN cast(account.number AS VARCHAR) ELSE cast(account.number AS VARCHAR) + substring(alias, 1, 2) END AS OFFICIAL_IDENTITY, CASE WHEN order_permission IN ('A', 'S') THEN 'ST' ELSE 'ENH' END FROM EU_CLIENTS AS client INNER JOIN ( dbo.ACCOUNTS account INNER JOIN ACCOUNT_TYPES accountType ON account.type = accountType.account_type LEFT JOIN DEDICATED_ACCOUNTS dedicated ON dedicated.account_number = account.number) ON (accountType.mapping_type = 0) OR (accountType.mapping_type = 2 AND account.tag = client.account_tag) OR (accountType.mapping_type = 1 AND dedicated.client_alias = client.alias) CREATE VIEW EU_CLIENTS AS SELECT * FROM EU_MERCHANT_CLIENTS UNION ALL SELECT * FROM US_SERVICE_CLIENTS
  • 26. CREATE VIEW CA_MERCHANT_CLIENTS AS SELECT DISTINCT (...) FROM MERCHANT_CLIENTS mc JOIN REGISTRY entry ON entry.alias = mc.alias WHERE entry.market = 'ca' AND entry.record_type = 'M' CREATE VIEW CA_CLIENT_ACCOUNTS AS SELECT DISTINCT account.name, alias, CASE WHEN code = 'EV' THEN cast(account.number AS VARCHAR) ELSE cast(account.number AS VARCHAR) + substring(alias, 1, 2) END AS OFFICIAL_IDENTITY, CASE WHEN order_permission IN ('A', 'S') THEN 'ST' ELSE 'ENH' END FROM CA_MERCHANT_CLIENTS AS client INNER JOIN ( dbo.ACCOUNTS account INNER JOIN ACCOUNT_TYPES accountType ON account.type = accountType.account_type LEFT JOIN DEDICATED_ACCOUNTS dedicated ON dedicated.account_number = account.number) ON (accountType.mapping_type = 0) OR (accountType.mapping_type = 2 AND account.tag = client.account_tag) OR (accountType.mapping_type = 1 AND dedicated.client_alias = client.alias)
  • 27. ~O(N) Codebase Size Per N Business Units! Tables: • MERCHANT_CLIENTS_V • SERVICE_CLIENTS_V • CLIENTS • CLIENT_ACCOUNTS Tables: • US_MERCHANT_CLIENTS • US_SERVICE_CLIENTS • US_CLIENTS • US_CLIENT_ACCOUNTS • EU_MERCHANT_CLIENTS + • EU_SERVICE_CLIENTS + • EU_CLIENTS + • EU_CLIENT_ACCOUNTS + • CA_MERCHANT_CLIENTS + • CA_CLIENT_ACCOUNTS + = Lots of Technical Debt
  • 28. CREATE FUNCTION dbo.merchantClientsUdf (@market) RETURNS table as RETURN ( SELECT DISTINCT alias, code, order_permission, account_tag FROM MERCHANT_CLIENTS merchantClient JOIN REGISTRY entry ON entry.alias = merchantClient.alias WHERE entry.market = @market AND entry.record_type = 'M') CREATE VIEW CLIENT_ACCOUNTS AS SELECT DISTINCT account.name, alias, CASE WHEN code = 'EV' THEN cast(account.number AS VARCHAR) ELSE cast(account.number AS VARCHAR) + substring(alias, 1, 2) END AS OFFICIAL_IDENTITY, CASE WHEN order_permission IN ('A', 'S') THEN 'ST' ELSE 'ENH' END FROM (select * from merchantClientsUdf ('us') union select * from serviceClientsUdf ('us')) as client INNER JOIN ( dbo.ACCOUNTS account INNER JOIN ACCOUNT_TYPES accountType ON account.type = accountType.account_type LEFT JOIN DEDICATED_ACCOUNTS dedicated ON dedicated.account_number = account.number) ON (accountType.mapping_type = 0) OR (accountType.mapping_type = 2 AND account.tag = client.account_tag) OR (accountType.mapping_type = 1 AND dedicated.client_alias = client.alias) CREATE FUNCTION dbo.serviceClientsUdf (@market) RETURNS table as RETURN ( SELECT DISTINCT alias, code, order_permission, account_tag FROM SERVICE_CLIENTS serviceClient JOIN REGISTRY entry ON entry.alias = serviceClient.alias AND entry.record_type = 'S' AND entry.market = @market JOIN PARTNERSHIPS partnership ON partnership.id = serviceClient.partnership_fk)
  • 29. CREATE FUNCTION dbo.merchantClientsUdf (@market) RETURNS table as RETURN (…) CREATE VIEW EU_CLIENT_ACCOUNTS AS SELECT DISTINCT account.name, alias, CASE WHEN code = 'EV' THEN cast(account.number AS VARCHAR) ELSE cast(account.number AS VARCHAR) + substring(alias, 1, 2) END AS OFFICIAL_IDENTITY, CASE WHEN order_permission IN ('A', 'S') THEN 'ST' ELSE 'ENH' END FROM (select * from merchantClientsUdf ('eu') union select * from enhancedServiceClientsUdf ('eu')) as client INNER JOIN ( dbo.ACCOUNTS account INNER JOIN ACCOUNT_TYPES accountType ON account.type = accountType.account_type LEFT JOIN DEDICATED_ACCOUNTS dedicated ON dedicated.account_number = account.number) ON (accountType.mapping_type = 0) OR (accountType.mapping_type = 2 AND account.tag = client.account_tag) OR (accountType.mapping_type = 1 AND dedicated.client_alias = client.alias) CREATE FUNCTION dbo.enhancedServiceClientsUdf (@market) RETURNS table as RETURN ( SELECT DISTINCT alias, code, order_permission, account_tag FROM SERVICE_CLIENTS serviceClient JOIN REGISTRY entry ON (... entry.market = @market ...) JOIN PARTNERSHIPS partnership ON (…) JOIN PARTNERSHIP_CODES pc ON partnership.ID = pc.partnership_fk
  • 30. CREATE FUNCTION dbo.merchantClientsUdf (@market) RETURNS table as RETURN (…) CREATE VIEW CA_CLIENT_ACCOUNTS AS SELECT DISTINCT account.name, alias, CASE WHEN code = 'EV' THEN cast(account.number AS VARCHAR) ELSE cast(account.number AS VARCHAR) + substring(alias, 1, 2) END AS OFFICIAL_IDENTITY, CASE WHEN order_permission IN ('A', 'S') THEN 'ST' ELSE 'ENH' END FROM (select * from merchantClientsUdf ('ca') union select * from enhancedServiceClientsUdf ('ca')) as client INNER JOIN ( dbo.ACCOUNTS account INNER JOIN ACCOUNT_TYPES accountType ON account.type = accountType.account_type LEFT JOIN DEDICATED_ACCOUNTS dedicated ON dedicated.account_number = account.number) ON (accountType.mapping_type = 0) OR (accountType.mapping_type = 2 AND account.tag = client.account_tag) OR (accountType.mapping_type = 1 AND dedicated.client_alias = client.alias)
  • 31. ~O(N)/2 Codebase Size Per N Business Units! Tables: • merchantClientsUdf • serviceClientsUdf • CLIENT_ACCOUNTS • merchantClientsUdf • serviceClientsUdf • US_CLIENT_ACCOUNTS • enhancedServiceClientsUdf + • EU_CLIENT_ACCOUNTS + • CA_CLIENT_ACCOUNTS + Tables: = (Still) Lots of Technical Debt
  • 32. What abstraction is significantly better? Tables: • merchantClientsUdf • serviceClientsUdf • CLIENT_ACCOUNTS • merchantClientsUdf • serviceClientsUdf • US_CLIENT_ACCOUNTS • enhancedServiceClientsUdf + • EU_CLIENT_ACCOUNTS + • CA_CLIENT_ACCOUNTS + Tables:
  • 33. define Client = Table[alias, code, perm, tag]
  • 34. Tables: • merchantClientsUdf → Client • serviceClientsUdf → Client • CLIENT_ACCOUNTS(c:Client) • merchantClientsUdf → Client • serviceClientsUdf → Client • CLIENT_ACCOUNTS(c:Client) • enhancedServiceClientsUdf → Client Tables: define Client = Table[alias, code, perm, tag]
  • 35. Codebase Size only Increases with new Features! Tables: • merchantClientsUdf → Client • serviceClientsUdf → Client • CLIENT_ACCOUNTS(c:Client) define Client = Table[alias, code, perm, tag] CLIENT_ACCOUNTS(merchantClientsUdf('us') union serviceClientsUdf('us‘)) CLIENT_ACCOUNTS(merchantClientsUdf('eu') union enhancedServiceClientsUdf('eu')) CLIENT_ACCOUNTS(merchantClientsUdf('eu')) • merchantClientsUdf → Client • serviceClientsUdf → Client • CLIENT_ACCOUNTS(c:Client) • enhancedServiceClientsUdf → Client Tables:
  • 36. = almost 0 additional Technical Debt Tables: • merchantClientsUdf → Client • serviceClientsUdf → Client • CLIENT_ACCOUNTS(c:Client) define Client = Table[alias, code, perm, tag] CLIENT_ACCOUNTS(merchantClientsUdf('us') union serviceClientsUdf('us‘)) CLIENT_ACCOUNTS(merchantClientsUdf('eu') union serviceClientsUdf('eu')) CLIENT_ACCOUNTS(merchantClientsUdf('eu')) • merchantClientsUdf → Client • serviceClientsUdf → Client • CLIENT_ACCOUNTS(c:Client) • enhancedServiceClientsUdf → Client Tables:
  • 37. There is no RDBMS in existence that does this! Tables: • merchantClientsUdf → Client • serviceClientsUdf → Client • CLIENT_ACCOUNTS(c:Client) define Client = Table[alias, code, perm, tag] CLIENT_ACCOUNTS(merchantClientsUdf('us') union serviceClientsUdf('us‘)) CLIENT_ACCOUNTS(merchantClientsUdf('eu') union serviceClientsUdf('eu')) CLIENT_ACCOUNTS(merchantClientsUdf('eu')) • merchantClientsUdf → Client • serviceClientsUdf → Client • CLIENT_ACCOUNTS(c:Client) • enhancedServiceClientsUdf → Client Tables:
  • 39. @Entity class Registry {...} @Entity class MerchantClient {...} @Entity class ServiceClient {...} @Entity class Partnership {...}
  • 40. @Entity class Registry {...} @Entity class MerchantClient {...} List<MerchantClient> merchantClients = em.createQuery( "select distinct mc from Registry r, MerchantClient mc where r.alias = mc.alias and r.market = :market and r.recordType = 'M'" ) List<ServiceClient> serviceClients = em.createQuery( "select distinct u from Registry r, ServiceClient sc, Partnership a where r.alias = mc.alias and r.market = :market and r.recordType = 'S'" ) @Entity class ServiceClient {...} @Entity class Partnership {...}
  • 41. @Entity class Registry {...} @Entity class MerchantClient {...} List<MerchantClient> merchantClients = em.createQuery( "select distinct mc from Registry r, MerchantClient mc where r.alias = mc.alias and r.market = :market and r.recordType = 'M'" ) List<ServiceClient> serviceClients = em.createQuery( "select distinct u from Registry r, ServiceClient sc, Partnership a where r.alias = mc.alias and r.market = :market and r.recordType = 'S'" ) @Entity class ServiceClient {...} @Entity class Partnership {...} How Can We Compose them??? merchantClients ++ serviceClients
  • 42. @Entity class AccountType {...} @Entity class Account {...} @Entity class DedicatedAccount {...}
  • 43. @Entity class AccountType {...} @Entity class Account {...} @Entity class DedicatedAccount {...} List<Accounts> allAccounts() = em.createQuery( "select distinct a from Account a, AccountType at where a.accountType = at.type and " ) List<Accounts> taggedAccounts(String tag) = em.createQuery( "select distinct a from Account a, AccountType at where a.accountType = at.type and a.tag = :tag" ) List<Accounts> dedicatedAccounts(String alias) = em.createQuery( "select distinct a from Account a, AccountType at, DedicatedAccount da where a.accountType = at.type and da.account = a.name and da.alias = :alias" )
  • 44. List<Pair<Client, Account>> output = new ArrayList<>() for (MerchantClient mc : merchantClients()) { output.addAll(Tuple.of(mc, allAccounts())) output.addAll(Tuple.of(taggedAccounts(mc.tag)) output.addAll(Tuple.of(dedicatedAccounts(mc.alias)) } List<Pair<Client, Account>> output = new ArrayList<>() for (ServiceClient sc : serviceClients()) { output.addAll(Tuple.of(allAccounts())) output.addAll(Tuple.of(taggedAccounts(sc.tag))) output.addAll(Tuple.of(dedicatedAccounts(sc.alias))) }
  • 45. select merchantClients0_.alias as subsidiary1_0_ (MORE COLUMNS) from merchantClients merchantClinets0_ where upper(merchantClients0_.alias) like ? select merchantClients0_.alias as subsidiary1_0_ (MORE COLUMNS) from merchantClients merchantClinets0_ where upper(merchantClients0_.alias) like ? select merchantClients0_.alias as subsidiary1_0_ (MORE COLUMNS) from merchantClients merchantClinets0_ where upper(merchantClients0_.alias) like ? select merchantClients0_.alias as subsidiary1_0_ (MORE COLUMNS) from merchantClients merchantClinets0_ where upper(merchantClients0_.alias) like ? select merchantClients0_.alias as subsidiary1_0_ (MORE COLUMNS) from merchantClients merchantClinets0_ where upper(merchantClients0_.alias) like ? select merchantClients0_.alias as subsidiary1_0_ (MORE COLUMNS) from merchantClients merchantClinets0_ where upper(merchantClients0_.alias) like ? select merchantClients0_.alias as subsidiary1_0_ (MORE COLUMNS) from merchantClients merchantClinets0_ where upper(merchantClients0_.alias) like ? select merchantClients0_.alias as subsidiary1_0_ (MORE COLUMNS) from merchantClients merchantClinets0_ where upper(merchantClients0_.alias) like ?
  • 46. select merchantClients0_.alias as subsidiary1_0_ (MORE COLUMNS) from merchantClients merchantClinets0_ where upper(merchantClients0_.alias) like ? select merchantClients0_.alias as subsidiary1_0_ (MORE COLUMNS) from merchantClients merchantClinets0_ where upper(merchantClients0_.alias) like ? select merchantClients0_.alias as subsidiary1_0_ (MORE COLUMNS) from merchantClients merchantClinets0_ where upper(merchantClients0_.alias) like ? select merchantClients0_.alias as subsidiary1_0_ (MORE COLUMNS) from merchantClients merchantClinets0_ where upper(merchantClients0_.alias) like ? select merchantClients0_.alias as subsidiary1_0_ (MORE COLUMNS) from merchantClients merchantClinets0_ where upper(merchantClients0_.alias) like ? select merchantClients0_.alias as subsidiary1_0_ (MORE COLUMNS) from merchantClients merchantClinets0_ where upper(merchantClients0_.alias) like ? select merchantClients0_.alias as subsidiary1_0_ (MORE COLUMNS) from merchantClients merchantClinets0_ where upper(merchantClients0_.alias) like ? select merchantClients0_.alias as subsidiary1_0_ (MORE COLUMNS) from merchantClients merchantClinets0_ where upper(merchantClients0_.alias) like ? N+1
  • 47. Criteria Queries? List<MerchantClient> merchantClients() = em.createQuery( select distinct mc from Registry r, MerchantClient mc where r.alias = mc.alias and r.market = :market and r.recordType = 'M’) Root<MerchantClient> fromMerchantClient = query.from(MerchantClient.class); Join<MerchantClient, Registry> registry = fromUpdates.join("alias"); List<Predicate> conditions = new ArrayList(); conditions.add(builder.equal(registry.get("market"), market)); conditions.add(builder.equal(registry.get("recordType"), "M")); TypedQuery<Update> typedQuery = em.createQuery(query .select(fromMerchantClient) .where(conditions.toArray(new Predicate[] {})) .distinct(true) );
  • 48. I’ll Stick with HQL Thanks List<MerchantClient> merchantClients() = em.createQuery( select distinct mc from Registry r, MerchantClient mc where r.alias = mc.alias and r.market = :market and r.recordType = 'M’) Root<MerchantClient> fromMerchantClient = query.from(MerchantClient.class); Join<MerchantClient, Registry> registry = fromUpdates.join("alias"); List<Predicate> conditions = new ArrayList(); conditions.add(builder.equal(registry.get("market"), market)); conditions.add(builder.equal(registry.get("recordType"), "M")); TypedQuery<Update> typedQuery = em.createQuery(query .select(fromMerchantClient) .where(conditions.toArray(new Predicate[] {})) .distinct(true) );
  • 49. ORM does not give us define Client = Table[alias, code, perm, tag] It just pretends it doesn’t exist! * https://blog.codinghorror.com/object-relational-mapping-is-the-vietnam-of-computer-science/
  • 50. What is SQL? How can we do better?
  • 51. SELECT DISTINCT account.name, alias, CASE (...) AS OFFICIAL_IDENTITY, CASE (...) FROM ( SELECT DISTINCT mc.alias, mc.code, order_permission, mc.account_tag FROM MERCHANT_CLIENTS mc JOIN REGISTRY r ON ((alias) AND (otherConditions)) UNION ALL SELECT DISTINCT sc.alias, 'EV' AS code, part.order_permission, sc.account_tag FROM SERVICE_CLIENTS sc JOIN REGISTRY r ON ((alias) AND (otherConditions)) JOIN PARTNERSHIPS part ON (id <-> fk)) client INNER JOIN ( dbo.ACCOUNTS account INNER JOIN ACCOUNT_TYPES accountType ON (account_type) LEFT JOIN DEDICATED_ACCOUNTS dedicated ON (account_number)) ON (possibly anything...) OR (possibly the account tag...) OR (possibly the alias...)
  • 52. SELECT DISTINCT account.name, alias, CASE (...) AS OFFICIAL_IDENTITY, CASE (...) FROM ( SELECT DISTINCT mc.alias, mc.code, order_permission, mc.account_tag FROM MERCHANT_CLIENTS mc JOIN REGISTRY r ON ((alias) AND (otherConditions)) UNION ALL SELECT DISTINCT sc.alias, 'EV' AS code, part.order_permission, sc.account_tag FROM SERVICE_CLIENTS sc JOIN REGISTRY r ON ((alias) AND (otherConditions)) JOIN PARTNERSHIPS part ON (id <-> fk)) client INNER JOIN ( dbo.ACCOUNTS account INNER JOIN ACCOUNT_TYPES accountType ON (account_type) LEFT JOIN DEDICATED_ACCOUNTS dedicated ON (account_number)) ON (possibly anything...) OR (possibly the account tag...) OR (possibly the alias...) 𝝀( ) →(String, String, Char, String) 𝝀( ) →(Boolean)
  • 53. SELECT DISTINCT account.name, alias, CASE (...) AS OFFICIAL_IDENTITY, CASE (...) FROM ( SELECT DISTINCT mc.alias, mc.code, order_permission, mc.account_tag FROM MERCHANT_CLIENTS mc JOIN REGISTRY r ON ((alias) AND (otherConditions)) UNION ALL SELECT DISTINCT sc.alias, 'EV' AS code, part.order_permission, sc.account_tag FROM SERVICE_CLIENTS sc JOIN REGISTRY r ON ((alias) AND (otherConditions)) JOIN PARTNERSHIPS part ON (id <-> fk)) client INNER JOIN ( dbo.ACCOUNTS account INNER JOIN ACCOUNT_TYPES accountType ON (account_type) LEFT JOIN DEDICATED_ACCOUNTS dedicated ON (account_number)) ON (possibly anything...) OR (possibly the account tag...) OR (possibly the alias...) 𝝀( ) →(String, String, Char, String) 𝝀( ) →(Boolean) 𝝀( ) →(String, String, Char, String) 𝝀( ) →(Boolean) 𝝀( ) →(Boolean)
  • 54. SELECT DISTINCT account.name, alias, CASE (...) AS OFFICIAL_IDENTITY, CASE (...) FROM ( SELECT DISTINCT mc.alias, mc.code, order_permission, mc.account_tag FROM MERCHANT_CLIENTS mc JOIN REGISTRY r ON ((alias) AND (otherConditions)) UNION ALL SELECT DISTINCT sc.alias, 'EV' AS code, part.order_permission, sc.account_tag FROM SERVICE_CLIENTS sc JOIN REGISTRY r ON ((alias) AND (otherConditions)) JOIN PARTNERSHIPS part ON (id <-> fk)) client INNER JOIN ( dbo.ACCOUNTS account INNER JOIN ACCOUNT_TYPES accountType ON (account_type) LEFT JOIN DEDICATED_ACCOUNTS dedicated ON (account_number)) ON (possibly anything...) OR (possibly the account tag...) OR (possibly the alias...) 𝝀( ) →(String, String, Char, String) 𝝀( ) →(Boolean) 𝝀( ) →(String, String, Char, String) 𝝀( ) →(Boolean) 𝝀( ) →(Boolean) 𝝀( ) →(String, String, Char, String)
  • 55. SELECT DISTINCT account.name, alias, CASE (...) AS OFFICIAL_IDENTITY, CASE (...) FROM ( SELECT DISTINCT mc.alias, mc.code, order_permission, mc.account_tag FROM MERCHANT_CLIENTS mc JOIN REGISTRY r ON ((alias) AND (otherConditions)) UNION ALL SELECT DISTINCT sc.alias, 'EV' AS code, part.order_permission, sc.account_tag FROM SERVICE_CLIENTS sc JOIN REGISTRY r ON ((alias) AND (otherConditions)) JOIN PARTNERSHIPS part ON (id <-> fk)) client INNER JOIN ( dbo.ACCOUNTS account INNER JOIN ACCOUNT_TYPES accountType ON (account_type) LEFT JOIN DEDICATED_ACCOUNTS dedicated ON (account_number)) ON (possibly anything...) OR (possibly the account tag...) OR (possibly the alias...) 𝝀( ) →(String, String, Char, String) 𝝀( ) →(Boolean) 𝝀( ) →(String, String, Char, String) 𝝀( ) →(Boolean) 𝝀( ) →(Boolean) 𝝀( ) →(String, String, Char, String) 𝝀( ) →(Boolean) 𝝀( ) →(Boolean) 𝝀( ) →(Boolean) 𝝀( ) →(Boolean) 𝝀( ) →(String, String, Int, String) 𝝀( ) →(String, Int) 𝝀( ) →(Int, String) 𝝀( ) →(Boolean)
  • 56. SELECT DISTINCT account.name, alias, CASE (...) AS OFFICIAL_IDENTITY, CASE (...) FROM ( SELECT DISTINCT mc.alias, mc.code, order_permission, mc.account_tag FROM MERCHANT_CLIENTS mc JOIN REGISTRY r ON ((alias) AND (otherConditions)) UNION ALL SELECT DISTINCT sc.alias, 'EV' AS code, part.order_permission, sc.account_tag FROM SERVICE_CLIENTS sc JOIN REGISTRY r ON ((alias) AND (otherConditions)) JOIN PARTNERSHIPS part ON (id <-> fk)) client INNER JOIN ( dbo.ACCOUNTS account INNER JOIN ACCOUNT_TYPES accountType ON (account_type) LEFT JOIN DEDICATED_ACCOUNTS dedicated ON (account_number)) ON (possibly anything...) OR (possibly the account tag...) OR (possibly the alias...) 𝝀( ) →(String, String, Char, String) 𝝀( ) →(Boolean) 𝝀( ) →(String, String, Char, String) 𝝀( ) →(Boolean) 𝝀( ) →(Boolean) 𝝀( ) →(String, String, Char, String) 𝝀( ) →(Boolean) 𝝀( ) →(Boolean) 𝝀( ) →(Boolean) 𝝀( ) →(Boolean) 𝝀( ) →(String, String, String, String) 𝝀( ) →(String, String, Int, String) 𝝀( ) →(String, Int) 𝝀( ) →(Int, String) 𝝀( ) →(Boolean)
  • 57. SELECT DISTINCT account.name, alias, CASE (...) AS OFFICIAL_IDENTITY, CASE (...) FROM ( SELECT DISTINCT mc.alias, mc.code, order_permission, mc.account_tag FROM MERCHANT_CLIENTS mc JOIN REGISTRY r ON ((alias) AND (otherConditions)) UNION ALL SELECT DISTINCT sc.alias, 'EV' AS code, part.order_permission, sc.account_tag FROM SERVICE_CLIENTS sc JOIN REGISTRY r ON ((alias) AND (otherConditions)) JOIN PARTNERSHIPS part ON (id <-> fk)) client INNER JOIN ( dbo.ACCOUNTS account INNER JOIN ACCOUNT_TYPES accountType ON (account_type) LEFT JOIN DEDICATED_ACCOUNTS dedicated ON (account_number)) ON (possibly anything...) OR (possibly the account tag...) OR (possibly the alias...) 𝑴(String, String, Char, String) 𝝀( ) →(Boolean) 𝑴(String, String, Char, String) 𝝀( ) →(Boolean) 𝝀( ) →(Boolean) 𝑴 →(String, String, Char, String) 𝝀( ) →(Boolean) 𝝀( ) →(Boolean) 𝝀( ) →(Boolean) 𝝀( ) →(Boolean) 𝑴(String, String, String, String) 𝑴(String, String, Int, String) 𝑴(String, Int) 𝑴(Int, String)
  • 58. SELECT DISTINCT account.name, alias, CASE (...) AS OFFICIAL_IDENTITY, CASE (...) FROM ( SELECT DISTINCT mc.alias, mc.code, order_permission, mc.account_tag FROM MERCHANT_CLIENTS mc JOIN REGISTRY r ON ((alias) AND (otherConditions)) UNION ALL SELECT DISTINCT sc.alias, 'EV' AS code, part.order_permission, sc.account_tag FROM SERVICE_CLIENTS sc JOIN REGISTRY r ON ((alias) AND (otherConditions)) JOIN PARTNERSHIPS part ON (id <-> fk)) client INNER JOIN ( dbo.ACCOUNTS account INNER JOIN ACCOUNT_TYPES accountType ON (account_type) LEFT JOIN DEDICATED_ACCOUNTS dedicated ON (account_number)) ON (possibly anything...) OR (possibly the account tag...) OR (possibly the alias...) 𝑴(String, String, Char, String) 𝝀( ) →(Boolean) 𝑴(String, String, Char, String) 𝝀( ) →(Boolean) 𝝀( ) →(Boolean) 𝑴 →(String, String, Char, String) 𝝀( ) →(Boolean) 𝝀( ) →(Boolean) 𝝀( ) →(Boolean) 𝝀( ) →(Boolean) 𝑴(String, String, String, String) 𝑴(String, String, Int, String) 𝑴(String, Int) 𝑴(Int, String)
  • 59. SELECT DISTINCT account.name, alias, CASE (...) AS OFFICIAL_IDENTITY, CASE (...) FROM ( SELECT DISTINCT mc.alias, mc.code, order_permission, mc.account_tag FROM MERCHANT_CLIENTS mc JOIN REGISTRY r ON ((alias) AND (otherConditions)) UNION ALL SELECT DISTINCT sc.alias, 'EV' AS code, part.order_permission, sc.account_tag FROM SERVICE_CLIENTS sc JOIN REGISTRY r ON ((alias) AND (otherConditions)) JOIN PARTNERSHIPS part ON (id <-> fk)) client INNER JOIN ( dbo.ACCOUNTS account INNER JOIN ACCOUNT_TYPES accountType ON (account_type) LEFT JOIN DEDICATED_ACCOUNTS dedicated ON (account_number)) ON (possibly anything...) OR (possibly the account tag...) OR (possibly the alias...) 𝑸𝒖𝒆𝒓𝒚[Client] 𝝀( ) →(Boolean) 𝑸𝒖𝒆𝒓𝒚 [Client] 𝝀( ) →(Boolean) 𝝀( ) →(Boolean) 𝑸𝒖𝒆𝒓𝒚 [Client] 𝝀( ) →(Boolean) 𝝀( ) →(Boolean) 𝝀( ) →(Boolean) 𝝀( ) →(Boolean) 𝑸𝒖𝒆𝒓𝒚[ClientAccountMapping] 𝑸𝒖𝒆𝒓𝒚[Account] 𝑸𝒖𝒆𝒓𝒚[AccountType] 𝑸𝒖𝒆𝒓𝒚[DedicatedAccount]
  • 60. def merchantClientsUdf(market:String):Query[(String, String, Char, String)] = { for { mc <- mercantClients r <- registry if (r.alias === mc.alias && r.market === market && r.recordType === 'M') } yield (mc.alias, mc.code, mc.orderPermission, mc.accountTag) } SELECT DISTINCT mc.alias, mc.code, order_permission, mc.account_tag FROM MERCHANT_CLIENTS mc JOIN REGISTRY r ON r.alias = mc.alias WHERE r.market = 'us' AND r.record_type = 'M'
  • 61. def serviceClientsUdf(market:String):Query[(String, String, Char, String)] = { for { sc <- serviceClients r <- registry if (r.alias === sc.alias && r.market === market && r.recordType === 'S') part <- parnerships if (part.id === sc.partnershipFk) } yield (sc.alias, "EV".bind.?, part.orderPermission, sc.accountTag) } SELECT DISTINCT sc.alias, 'EV' AS code, part.order_permission, sc.account_tag FROM SERVICE_CLIENTS sc JOIN REGISTRY r ON r.alias = sc.alias AND r.record_type = 'S' AND r.market = 'us' JOIN PARTNERSHIPS part ON part.id = sc.partnership_fk) client
  • 62. def merchantClientsUdf(market:String):Query[(String, String, Char, String)] = for { mc <- mercantClients r <- registry if (r.alias === mc.alias && r.market === market && r.recordType === 'M') } yield (mc.alias, mc.code, mc.orderPermission, mc.accountTag) def serviceClientsUdf(market:String):Query[(String, String, Char, String)] = for { sc <- serviceClients r <- registry if (r.alias === sc.alias && r.market === market && r.recordType === 'S') part <- parnerships if (part.id === sc.partnershipFk) } yield (sc.alias, "EV".bind.?, part.orderPermission, sc.accountTag) def clients(market:String):Query[(String, String, Char, String)] = merchantClientsUdf(market) ++ serviceClientsUdf(market)
  • 63. def merchantClientsUdf(market:String):Query[Client] = for { mc <- mercantClients r <- registry if (r.alias === mc.alias && r.market === market && r.recordType === 'M') } yield Client(mc.alias, mc.code, mc.orderPermission, mc.accountTag) def serviceClientsUdf(market:String):Query[Client] = for { sc <- serviceClients r <- registry if (r.alias === sc.alias && r.market === market && r.recordType === 'S') part <- parnerships if (part.id === sc.partnershipFk) } yield Client(sc.alias, "EV".bind.?, part.orderPermission, sc.accountTag) def clients(market:String):Query[Client] = merchantClientsUdf(market) ++ serviceClientsUdf(market)
  • 64. def nonDedicatedAccounts = for { account <- accounts accountType <- accountTypes if (account.`type` === accountType.accountType) } yield (account, accountType) def allAccounts = for { ((account, accountType), dedicatedAccount) <- nonDedicatedAccounts.joinLeft(dedicatedAccounts) .on({case ((a, at), d) => (a.number === d.accountNumber)}) } yield (account, accountType, dedicatedAccount) def mappingConditionsMet(mappingType:Rep[Int], accountTag:Rep[String], clientTag:Rep[String], clientAlias:Rep[String], dedicatedAlias:Rep[String]):Rep[Int] = Case.If(mappingType === 0).Then(1) .If(mappingType === 2 && accountTag === clientTag).Then(1) .If(mappingType === 1 && clientAlias === dedicatedAlias).Then(1) .Else(0) def accountMapping(clients:Query[Client]):Query[Clients,Accounts,AccountTypes,Option[DedicatedAccounts]] for { (account, accountType, dedicatedAccount) <- allAccounts client <- clients if (mappingConditionsMet( accountType.mappingType.oz, account.tag.oe, client.tag.oe, client.alias.oe, dedicatedAccount.map(_.clientAlias).flatten.oe) == 1) } yield (client, account, accountType, dedicatedAccount) SELECT DISTINCT (...) FROM (...) INNER JOIN ( dbo.ACCOUNTS account INNER JOIN ACCOUNT_TYPES accountType ON account.type = accountType.account_type LEFT JOIN DEDICATED_ACCOUNTS dedicated ON dedicated.account_number = account.number) ON (accountType.mapping_type = 0) OR (accountType.mapping_type = 2 AND account.tag = client.account_tag) OR (accountType.mapping_type = 1 AND dedicated.client_alias = client.alias)
  • 65. def render( query: Query[(Client, Accounts, AccountTypes, Option[DedicatedAccounts])]) = { for { (client, account, accountType, dedicatedAccount) <- query } yield ( account.name, Case.If(client.code === "EV") .Then(account.number.asString) .Else(account.number.asString.substring(1,2)), Case.If(client.permission.min.inSet(Seq('A','S'))).Then("ST").Else("ENH") ) } SELECT DISTINCT account.name, alias, CASE WHEN code = 'EV' THEN cast(account.number AS VARCHAR) ELSE cast(account.number AS VARCHAR) + substring(alias, 1, 2) END AS OFFICIAL_IDENTITY, CASE WHEN order_permission IN ('A', 'S') THEN 'ST' ELSE 'ENH' END
  • 67. def render( query: Query[(Client, Accounts, AccountTypes, Option[DedicatedAccounts])]) = { for { (client, account, accountType, dedicatedAccount) <- query } yield ( account.name, Case.If(client.code === "EV") .Then(account.number.asString) .Else(account.number.asString.substring(1,2)), Case.If(client.permission.min.inSet(Seq('A','S'))).Then("ST").Else("ENH") ) } SELECT DISTINCT account.name, alias, CASE WHEN code = 'EV' THEN cast(account.number AS VARCHAR) ELSE cast(account.number AS VARCHAR) + substring(alias, 1, 2) END AS OFFICIAL_IDENTITY, CASE WHEN order_permission IN ('A', 'S') THEN 'ST' ELSE 'ENH' END
  • 68. New Requirements… Re-examined 1.New European Business Unit with Client Codes from the Partnership 2.New Canadian Business Unit without Service Clients
  • 69. Can We Do Better? def serviceClientsUdf(market:String) = for { sc <- serviceClients r <- registry if (r.alias === sc.alias && r.market === market && r.recordType === 'S') part <- parnerships if (part.id === sc.partnershipFk) } yield (Client(sc.alias, "EV".bind.?, part.orderPermission, sc.accountTag)) def serviceClientsUdfEnhanced(market:String) = for { sc <- serviceClients r <- registry if (r.alias === sc.alias && r.market === market && r.recordType === 'S') part <- parnerships if (part.id === sc.partnershipFk) pc <- parnershipCodes if (part.id === pc.partnershipFk) } yield (Client(sc.alias, pc.code, part.orderPermission, sc.accountTag))
  • 70. Here is How def serviceClientsDual(market:String, usePartnershipCodes:Boolean) = { val clientsAndPartnerships = for { sc <- serviceClients r <- registry if (r.alias === sc.alias && r.market === market && r.recordType === 'S') part <- parnerships if (part.id === sc.partnershipFk) } yield (sc.alias, part.orderPermission, sc.accountTag, part.id) usePartnershipCodes match { case true => for { (alias, permission, tag, partnershipId) <- clientsAndPartnerships pc <- parnershipCodes if (partnershipId === pc.partnershipFk) } yield Client(alias, pc.code, permission, tag) case false => for { (alias, permission, tag, partnershipId) <- clientsAndPartnerships } yield Client(alias, "EV".bind.?, permission, tag) } }
  • 71. def mapAndRender(clients:Query[Client, ClientRow, scala.Seq]) = render(accountMapping(clients)) def usClientAccounts = mapAndRender(serviceClientsDual("us", false) ++ mercantClientsUdf("us")) def euClientAccounts = mapAndRender(serviceClientsDual("eu", true) ++ mercantClientsUdf("eu")) def caClientAccounts = mapAndRender(mercantClientsUdf("ca")) Better!
  • 72. def merchantClientsUdf(market:String):Query[Client] = for { mc <- mercantClients r <- registry if (r.alias === mc.alias && r.market === market && r.recordType === 'M') } yield Client(mc.alias, mc.code, mc.orderPermission, mc.accountTag) def serviceClientsUdf(market:String):Query[Client] = for { sc <- serviceClients r <- registry if (r.alias === sc.alias && r.market === market && r.recordType === 'S') part <- parnerships if (part.id === sc.partnershipFk) } yield Client(sc.alias, "EV".bind.?, part.orderPermission, sc.accountTag) Registry is Just a Filter…
  • 73. filterByRegistry(q, recordType) Query[Service or Merchant Client] Query[Service or Merchant Client]
  • 74. filterByRegistry(q, recordType, f) Query[T] + Query[T] f(T)→SomeFieldToJoin
  • 75. def filterByRegistry[E, U](q:Query[E, U, Seq], recordType:Char, market:String)(f:(E) => Rep[String])( implicit shape: Shape[_ <: FlatShapeLevel, E, U, E]):Query[E, U, Seq] = { for { record <- q r <- registry if (f(record) === r.alias && r.recordType === recordType && r.market === market) } yield (record) } def merchantClientsUdf(market:String) = { for { mc <- filterByRegistry(mercantClients, 'M', market)(_.alias.oe) } yield (Client(mc.alias, mc.code, mc.orderPermission, mc.accountTag)) } def serviceClientsUdf(market:String) = { for { sc <- filterByRegistry(serviceClients, 'M', market)(_.alias.oe) part <- parnerships if (part.id === sc.partnershipFk) } yield (Client(sc.alias, "EV".bind.?, part.orderPermission, sc.accountTag)) } Better!
  • 76. Some Caveats • Query[(String, String, Char, String)] • Query[(Option[String], Option[String], Option[Char], Option[String])] • Query[(Rep[Option[String]], Rep[Option[String]], Rep[Option[Char]], Rep[Option[String]])] • Query[(Rep[Option[String]], Rep[Option[String]], Rep[Option[Char]], Rep[Option[String]]), (Option[String], Option[String], Option[Char], Option[String]), Seq] • Query[Client], Client(String, String, Char, String) • Query[Client], Client(Option[String], Option[String], Option[Char], Option[String]) • Query[Client, ClientRow, Seq] Client(Rep[Option[String]], Rep[Option[String]], Rep[Option[Char]], Rep[Option[String]]) ClientRow(Option[String], Option[String], Option[Char], Option[String], Seq) Type Inferencing mostly does this for us
  • 77. Some Caveats • Query[(String, String, Char, String)] • Query[(Option[String], Option[String], Option[Char], Option[String])] • Query[(Rep[Option[String]], Rep[Option[String]], Rep[Option[Char]], Rep[Option[String]])] • Query[(Rep[Option[String]], Rep[Option[String]], Rep[Option[Char]], Rep[Option[String]]), (Option[String], Option[String], Option[Char], Option[String]), Seq] • Query[Client], Client(String, String, Char, String) • Query[Client], Client(Option[String], Option[String], Option[Char], Option[String]) • Query[Client, ClientRow, Seq] Client(Rep[Option[String]], Rep[Option[String]], Rep[Option[Char]], Rep[Option[String]]) ClientRow(Option[String], Option[String], Option[Char], Option[String], Seq) Type Inferencing mostly does this for us
  • 78. Some Caveats • Query[(String, String, Char, String)] • Query[(Option[String], Option[String], Option[Char], Option[String])] • Query[(Rep[Option[String]], Rep[Option[String]], Rep[Option[Char]], Rep[Option[String]])] • Query[(Rep[Option[String]], Rep[Option[String]], Rep[Option[Char]], Rep[Option[String]]), (Option[String], Option[String], Option[Char], Option[String]), Seq] • Query[Client], Client(String, String, Char, String) • Query[Client], Client(Option[String], Option[String], Option[Char], Option[String]) • Query[Client, ClientRow, Seq] Client(Rep[Option[String]], Rep[Option[String]], Rep[Option[Char]], Rep[Option[String]]) ClientRow(Option[String], Option[String], Option[Char], Option[String], Seq) Type Inferencing mostly does this for us
  • 79. Some Caveats • Query[(String, String, Char, String)] • Query[(Option[String], Option[String], Option[Char], Option[String])] • Query[(Rep[Option[String]], Rep[Option[String]], Rep[Option[Char]], Rep[Option[String]])] • Query[(Rep[Option[String]], Rep[Option[String]], Rep[Option[Char]], Rep[Option[String]]), (Option[String], Option[String], Option[Char], Option[String]), Seq] • Query[Client], Client(String, String, Char, String) • Query[Client], Client(Option[String], Option[String], Option[Char], Option[String]) • Query[Client, ClientRow, Seq] Client(Rep[Option[String]], Rep[Option[String]], Rep[Option[Char]], Rep[Option[String]]) ClientRow(Option[String], Option[String], Option[Char], Option[String], Seq) Type Inferencing mostly does this for us
  • 80. Some Caveats • Query[(String, String, Char, String)] • Query[(Option[String], Option[String], Option[Char], Option[String])] • Query[(Rep[Option[String]], Rep[Option[String]], Rep[Option[Char]], Rep[Option[String]])] • Query[(Rep[Option[String]], Rep[Option[String]], Rep[Option[Char]], Rep[Option[String]]), (Option[String], Option[String], Option[Char], Option[String]), Seq] • Query[Client], Client(String, String, Char, String) • Query[Client], Client(Option[String], Option[String], Option[Char], Option[String]) • Query[Client, ClientRow, Seq] Client(Rep[Option[String]], Rep[Option[String]], Rep[Option[Char]], Rep[Option[String]]) ClientRow(Option[String], Option[String], Option[Char], Option[String], Seq) Type Inferencing mostly does this for us
  • 81. Some Caveats • Query[(String, String, Char, String)] • Query[(Option[String], Option[String], Option[Char], Option[String])] • Query[(Rep[Option[String]], Rep[Option[String]], Rep[Option[Char]], Rep[Option[String]])] • Query[(Rep[Option[String]], Rep[Option[String]], Rep[Option[Char]], Rep[Option[String]]), (Option[String], Option[String], Option[Char], Option[String]), Seq] • Query[Client], Client(String, String, Char, String) • Query[Client], Client(Option[String], Option[String], Option[Char], Option[String]) • Query[Client, ClientRow, Seq] Client(Rep[Option[String]], Rep[Option[String]], Rep[Option[Char]], Rep[Option[String]]) ClientRow(Option[String], Option[String], Option[Char], Option[String], Seq) Type Inferencing mostly does this for us
  • 82. Some Caveats • Query[(String, String, Char, String)] • Query[(Option[String], Option[String], Option[Char], Option[String])] • Query[(Rep[Option[String]], Rep[Option[String]], Rep[Option[Char]], Rep[Option[String]])] • Query[(Rep[Option[String]], Rep[Option[String]], Rep[Option[Char]], Rep[Option[String]]), (Option[String], Option[String], Option[Char], Option[String]), Seq] • Query[Client], Client(String, String, Char, String) • Query[Client], Client(Option[String], Option[String], Option[Char], Option[String]) • Query[Client, ClientRow, Seq] Client(Rep[Option[String]], Rep[Option[String]], Rep[Option[Char]], Rep[Option[String]]) ClientRow(Option[String], Option[String], Option[Char], Option[String], Seq) Type Inferencing mostly does this for us
  • 83. Conclusions • Scala solves Old and New Problems in great ways! • Check out Scala’s No-ORM Frameworks: Slick - http://slick.lightbend.com/ Quill - http://getquill.io/

Notas del editor

  1. 3
  2. 4
  3. 6
  4. 7
  5. 8
  6. 9
  7. The RG device. YS
  8. 12
  9. All G in K until it’s not
  10. European service industry not necessarily EV
  11. EU_Client_accounts almost all technical debt
  12. EU_Client_accounts almost all technical debt
  13. Whenever introduce new business unit, copy almost all code
  14. EU_Client_accounts almost all technical debt, pretend inline udf exists that can return parameterized views
  15. EU_Client_accounts almost all technical debt
  16. EU_Client_accounts almost all technical debt
  17. Whenever introduce new business unit, copy almost all code
  18. Whenever introduce new business unit, copy almost all code
  19. Whenever introduce new business unit, copy almost all code
  20. Whenever introduce new business unit, copy almost all code
  21. Whenever introduce new business unit, copy almost all code (i.e. codebase size increase after constant effects)
  22. Whenever introduce new business unit, copy almost all code
  23. Whenever introduce new business unit, copy almost all code
  24. Lambdas in context, associative, have unit function (select of select –sto)
  25. Lambdas in context, associative, have unit function (select of select –sto)
  26. Lambdas in context, associative, have unit function (select of select –sto)
  27. Lambdas in context, associative, have unit function (select of select –sto)
  28. Lambdas in context, associative, have unit function (select of select –sto)
  29. Lambdas in context, associative, have unit function (select of select –sto)
  30. These-things-are-iso-morphic
  31. Note, that union operator is possible because same type is returned
  32. Note, that union operator is possible because same type is returned
  33. European service industry not necessarily EV
  34. Note, that union operator is possible because same type is returned
  35. Some field to join on registry alias