72DUSPYXB64ECTFQWWD7XSY4YJUNRCFZT22AS4BDRIIUZP33CZGAC
WUYZYVZXH2IPB3NSMEUWKP7A6PHOWECLGBHGOAN5FFMXPLWIDYNQC
JQCVFJKLLXVEUEJ72U5MLVC4BIHNMMYI6DT2ZECXDO5XCPHORWDQC
CPA3Q5AQOEU4RWB3F3ZILCYTCHWSEOYXEWBL467UBWUOLGHFZTMAC
HTDKGL7WF3ESALRVW2MK64X6MUC6NMIBCQLQDY7P6DZDYCSA5DQQC
QSEGNTGEAE4GCH6VRPHJL2JJI3WFXBDO4VJ2LTEFYHYK4576ZEHAC
X723YRMNH2CY3RKNFZPOP5JG2DOLVIW3WVELT2ZTEXU7MRVI7Y2AC
NF2TA3BN5FXWG6LFHHI3IDBVRPMLVRNUUZBE3NWIBASMSKEQPC4QC
47JKAGWEDSPFXKMFOVMTEYGUFFS5SEJMNZIZPJJAWJ5U3CH5YGMQC
NJ233BBUD2WBHKNEWPO5JWQTECTGR5F43NYTSNOZ5J3K22U5C47QC
E4HFJ4L4PAGV7R7EXVG2B2CWDGGW7XWU4D37VURZ66HZ3ILHCFUAC
NBGKNI25T2AKNWDH5Z6U6JDUHLQPNRL6GQFF5VS37OOHONSP4CKQC
NDMM44EV2XD5RP7J4Q25ZX52LUP7WOMTKO3C2PDXW7IWFEVWUW6QC
5RSETDN4QCQLU7Z55EFXSW27CBEW6HD2MVD2MKB6WDBXIKXFHKNQC
ZBUC3VBT42SDAG42OCUX7MTT6GNPX2GEGWU2QIUYAY4NMX33IGLAC
63VXWIHIAKGK7J4VTNRUAG2V32N2QUSWFELB6GD34S54FGRWAPCQC
H7WIMUC46JPR6FJ7JGTLDWLJ3JZH53UH6QCECYOGL3YIOL57JGOAC
NAAQ2HMF7NXGJDRPXATVAGGZWL5MAIQWF4K5S23VFYBPOPZUXJZAC
PEVQ4WY77RA6HMHM2C4HLJ5YKRLHYCAD7MDIWD6POZTJZMMMBVGAC
SE6MCCXTIXSGMAH5EL7EPDXIQKV6THCCY2H4OQJJQOHCUQAWE5VQC
OE75DBM36Z3EXJ7XPQVSSBEIT4UR275RP43URXF4OOFSXKEYTA4AC
I4MTA4E4GTMWJ4NC42QRWV55JRZ2K2W7SDSH5GAW2N4MIAQWS3DQC
WYTMZJFYVKHR4QH7AV5JUNWXT6NAC5NNQNPZCQSDI6LGI7DVXFYAC
X4XDT5S7ISHUZAJ4TK2FBEV55NY6CCUVZL2LN7DTBQ7AJCP5P3QAC
create unique index upi_product_3p on product (producer, joined_name, type) where brand is null;
create unique index upi_product_3b on product (brand, joined_name, type) where producer is null;
create unique index upi_product_4 on product (producer, brand, joined_name, type) where brand is not null and producer is not null;
create unique index upi_product_3 on product (brand, joined_name, type) where producer is null;
create unique index upi_product_4 on product (producer, brand, joined_name, type) where producer is not null;
$$ language sql;
create or replace function thc2tc(thc numrange, cbd numrange) returns numeric as $$
select ((lower(thc) + upper(thc)) / 2) / (((lower(thc) + upper(thc)) / 2) + ((lower(cbd) + upper(cbd)) / 2))
$$ language sql;
$$ language sql stable;
create or replace function avg_range(numrange) returns numeric as $$
select (lower($1) + upper($1)) / 2
$$ language sql immutable;--idk if immutable actually helps or makes sense(documentation is a little unclear. is argument a value or a reference to a row's column??)
create or replace function thc2tc(thc numrange, cbd numrange) returns numeric as $$--how does nested inlining work?? stackoverflow.com/q/53040170. time to raise notice or case when pg_sleep(.01) is null then 2 else actual end.... yay fun. constant folding? can't explain analyze functions, so leave as separate exercise dba.stackexchange.com/q/84414
select avg_range(thc) / (avg_range(thc) + avg_range(cbd))
$$ language sql immutable;
_store_id integer = null,
--_user_id integer = null,
_species species = null,
_effect effect = null,--not working yet
_strain_id integer = null,
_type product_type = null,
in_stock boolean = null,
_store_id integer = null,--soon to be array? for geolocation sort
_species species[] = null,--how about default to empty array?
_effects effect[] = null,
_strain_ids integer[] = null,
_types product_type[] = null,
frequency text = 'daily',
in_stock boolean = null,--true in stock only. false oos only. null everything
sort_thc boolean = null,--not working yet
sort_cbd boolean = null,--not working yet
sort_thc boolean = null,--in frontend, warn user that the sort does not make sense if types from more than one method of consumption(inhalation, sublingual, ingestion) are included in filter
sort_cbd boolean = null,--ditto
search text = null
search text = null,
--_user_id integer = null, cte vs plpgsql variable?. will replace below parameters once user stuff is done
akt1 akt1 = null,
comt comt = null,
cyp2c19_2 cyp2c19_2 = null,
cyp2c19_3 cyp2c19_3 = null,
cyp2c19_17 cyp2c19_17 = null,
cyp2c9 cyp2c9 = null
(strain_id = _strain_id or _strain_id is null) and
(type = _type or _type is null) and
(species = _species or _species is null)
(strain_id = any(_strain_ids) or _strain_ids is null) and
(type = any(_types) or _types is null) and
(species = any(_species) or _species is null) and case
when akt1 in ('C/T', 'C/C') then thc2tc(thc, cbd) < .6
else true
end and case
when comt in ('Val/Val', 'Val/Met') then
thc2tc(thc, cbd) < .75 or
terpenes[1] ilike '%pinene' or
terpenes[2] ilike '%pinene'
else true
end and case--cbd
when--slow
(cyp2c19_17 = '*1/*1' or cyp2c19_17 = '*1/*17') and
((cyp2c19_2 = '*1/*1' and cyp2c19_3 = '*1/*3') or (cyp2c19_2 = '*1/*2' and cyp2c19_3 = '*1/*1'))
then
type in ('flower', 'preroll', 'cartridge', 'disposable') or
thc2tc(thc, cbd) > .3 or
avg_range(thc) < case--76. need to fix
when type = 'oil' then 20
when type = 'spray' then 2
when type in ('capsule', 'tea', 'gummy', 'mint', 'chocolate', 'baked') then 5 / first
end
when--very slow
cyp2c19_17 = '*1/*1' and (
cyp2c19_2 = '*1/*1' and cyp2c19_3 = '*3/*3' or
cyp2c19_2 = '*1/*2' and cyp2c19_3 = '*1/*3' or
cyp2c19_2 = '*2/*2' and cyp2c19_3 = '*1/*1'
)
then
type in ('flower', 'preroll', 'cartridge', 'disposable') or
thc2tc(thc, cbd) > .3 or
avg_range(thc) < case--20. need to fix
when type = 'oil' then 20
when type = 'spray' then 2
when type in ('capsule', 'tea', 'gummy', 'mint', 'chocolate', 'baked') then 5 / first
end
else true
end and case
when (frequency = 'daily' and (cyp2c9 is null or cyp2c9 in ('inconclusive', '*1/*1'))) or type in ('oil', 'spray') then true
else avg_range(thc) < case
when type in ('flower', 'preroll') then case
when frequency = 'daily' then case
when cyp2c9 = '*1/*3' then 240
when cyp2c9 = '*3/*3' then 200
end
when frequency = 'weekly' then case
when cyp2c9 = '*1/*3' then 215
when cyp2c9 = '*3/*3' then 165
else 365
end
when frequency = 'monthly' then case
when cyp2c9 = '*1/*3' then 70
when cyp2c9 = '*3/*3' then 40
else 130
end
else case--'rarely'
when cyp2c9 = '*1/*3' then 50
when cyp2c9 = '*3/*3' then 25
else 100
end
end
when type in ('cartridge', 'disposable') then case
when frequency = 'daily' then case
when cyp2c9 = '*1/*3' then 240--fixme
when cyp2c9 = '*3/*3' then 200--fixme
end
when frequency = 'weekly' then case
when cyp2c9 = '*1/*3' then 215--fixme
when cyp2c9 = '*3/*3' then 165--fixme
else 365
end
when frequency = 'monthly' then case
when cyp2c9 = '*1/*3' then 70--fixme
when cyp2c9 = '*3/*3' then 40--fixme
else 130
end
else case--'rarely'
when cyp2c9 = '*1/*3' then 50--fixme
when cyp2c9 = '*3/*3' then 25--fixme
else 100
end
end
when type in ('capsule', 'tea', 'gummy', 'mint', 'chocolate', 'baked') then case
when frequency = 'daily' then case--need to divide by first, but capsule breaks it...
when cyp2c9 = '*1/*3' then 7.5
when cyp2c9 = '*3/*3' then 5
end
when frequency = 'weekly' then case
when cyp2c9 = '*1/*3' then 5
when cyp2c9 = '*3/*3' then 3
else 7.5
end
when frequency = 'monthly' then case
when cyp2c9 = '*1/*3' then 3
when cyp2c9 = '*3/*3' then 2
else 5
end
else case--'rarely'
when cyp2c9 = '*1/*3' then 2.4
when cyp2c9 = '*3/*3' then 1.2
else 3
end
end
end
end and
coalesce((select bool_or(case
when x = 'sleep' then species = 'indica' and thc2tc(thc, cbd) >= .1
when x = 'calm' then species in ('indica', 'hybrid', 'blend') and thc2tc(thc, cbd) <= .6
when x = 'pain' then thc2tc(thc, cbd) between .1 and .8
when x = 'happy' then species = 'sativa' or species = 'hybrid' and thc2tc(thc, cbd) >= .35
when x = 'energetic' then species = 'sativa' and thc2tc(thc, cbd) >= .1
when x = 'focused' then species = 'hybrid' and thc2tc(thc, cbd) between .25 and .7 or species = 'sativa' and avg_range(thc) <= case
when type in ('flower', 'preroll') then 100
when type in ('disposable', 'cartridge') then 550
when type = 'oil' then 20
when type = 'spray' then 2
when type in ('capsule', 'tea', 'gummy', 'mint', 'chocolate', 'baked') then 5 / first
end
end) from unnest(_effects) as t(x)), true)-- and
--(search is null or word_similarity(concat_ws(' ', producer, brand, product.display_name), lower(search)) > 0.5)--0.5 is too high... maybe limit instead if present?
case when not sort_price then min end desc
$$ language sql;
case when not sort_price then min end desc,
case
when cyp2c9 in ('*1/*3', '*3/*3') then case
when type in ('flower', 'preroll', 'cartridge', 'disposable') then 1
when type in ('oil', 'spray') then 2
when type in ('capsule', 'tea', 'gummy', 'mint', 'chocolate', 'baked') then 3
end
end,
case
when
'sleep' = any(_effects) and terpenes[1] ilike '%myrcene' or
'calm' = any(_effects) and terpenes[1] ilike '%limonene' or
'pain' = any(_effects) and terpenes[1] ilike '%caryo%lene' and terpenes[2] ilike '%humulene' or
'focused' = any(_effects) and terpenes[1] ilike '%pinene' or
'energetic' = any(_effects) and terpenes[1] ilike '%terpinolene' or
'happy' = any(_effects) and terpenes[1] ilike '%linalool'
then 1
when
'sleep' = any(_effects) and terpenes[2] ilike '%myrcene' or
'calm' = any(_effects) and terpenes[1] ilike '%caryo%lene' or
'pain' = any(_effects) and terpenes[1] ilike '%caryo%lene' or
'focused' = any(_effects) and terpenes[2] ilike '%pinene' or
'energetic' = any(_effects) and terpenes[2] ilike '%terpinolene' or
'happy' = any(_effects) and terpenes[2] ilike '%linalool'
then 2
when
'calm' = any(_effects) and terpenes[2] ilike '%limonene' or
'pain' = any(_effects) and terpenes[2] ilike '%caryo%lene'
then 3
when
'calm' = any(_effects) and terpenes[2] ilike '%caryo%lene'
then 4
when strain.effect = any(_effects) then 10
else 11
end
$$ language sql stable;
round(@ ((lower(thc) + upper(thc)) / 2) - (select ((lower(thc) + upper(thc)) / 2) from p), -1) asc nulls last--this is wrong thc_mg, but temporary(take into account user pref for flower, recommend at variant level) but maybe doesn't matter since same type? need to fix if type becomes optional though
round(@ avg_range(thc) - (select avg_range(thc) from p), -1) asc nulls last--this is wrong thc_mg, but temporary(take into account user pref for flower, recommend at variant level) but maybe doesn't matter since same type? need to fix if type becomes optional though
let s = Number(parameters.store);
if(Number.isInteger(s)) {
qs += `_store_id => $${params.push(s)},`;
if((parameters.store = Number(parameters.store)) && Number.isInteger(parameters.store)) {
qs += `_store_id => $${params.push(parameters.store)},`;
let st = Number(parameters.strain_id);
if(Number.isInteger(st)) {
qs += `_strain_id => $${params.push(st)},`;
if(Array.isArray(parameters.strain_ids) && (parameters.strain_ids = parameters.strain_ids.map(Number)).every(Number.isInteger)) {
qs += `_strain_ids => $${params.push(parameters.strain_ids)},`;
if(typeof parameters.type === 'string') {
qs += `_type => $${params.push(parameters.type)},`;
if(Array.isArray(parameters.types) && parameters.types.every(s => typeof s === 'string')) {
qs += `_types => $${params.push(parameters.types)},`;
if(typeof parameters.frequency === 'string') {
qs += `frequency => $${params.push(parameters.frequency)},`;
}
if(typeof parameters.akt1 === 'string') {
qs += `akt1 => $${params.push(parameters.akt1)},`;
}
if(typeof parameters.comt === 'string') {
qs += `comt => $${params.push(parameters.comt)},`;
}
if(typeof parameters.cyp2c9 === 'string') {
qs += `cyp2c9 => $${params.push(parameters.cyp2c9)},`;
}
if(typeof parameters.cyp2c19_2 === 'string') {
qs += `cyp2c19_2 => $${params.push(parameters.cyp2c19_2)},`;
}
if(typeof parameters.cyp2c19_3 === 'string') {
qs += `cyp2c19_3 => $${params.push(parameters.cyp2c19_3)},`;
}
if(typeof parameters.cyp2c19_17 === 'string') {
qs += `cyp2c19_17 => $${params.push(parameters.cyp2c19_17)},`;
}
}
if(Array.isArray(parameters.producers) && parameters.producers.every(p => typeof p === 'object' && typeof p.producer === 'string' && (Array.isArray(p.brands) || p.brands === undefined))) {
wack = ` where ${parameters.producers.map(p => `producer = $${params.push(p.producer)}${Array.isArray(p.brands) ? ` and brand = any($${params.push(p.brands)})`: ''}`).join(' or ')}`;