<  *  | *** >

Basics 

  • flat select
  • group by select
  • callback basics
  • common aggregation operators
  • other aggregation operators
  • orphans management and dimension priority
  • escape quote
  • Stormbase & Lua
  • utility Lua functions
  • callback Lua functions
  • data model modification #1
  • data model modification #2
  • where clause basics
  • where clause / Lua boolean function
  • (not)exists basics
  • col_type_checks basics
  • col_type_checks advanced
  • permissions
  • dynamic code

-- ###########################
-- RUNNING stop_on_error.sql
stop_on_error;
reponse
success

-- ###########################
-- RUNNING clear.sh

/*
sure mode, no confirmation prompt
clearing directory INTERNAL_FILES_DIR (../STORAGE/INT) ...
done
clearing directory MAX_PERF_FILES_DIR (../STORAGE/MAX_PERF) ...
done
clearing directory TRANSAC_FILES_DIR (../STORAGE/TRANSAC) ...
done
*/

-- ###########################
-- RUNNING doc_data_init.sql
create col_type t_site_id as text;
reponse
success

create col_type t_dept_id as text;
reponse
success

create col_type t_item_id as text;
reponse
success

create col_type t_customer_id as text;
reponse
success

create col_type t_date as text;
reponse
success

create col_type t_customer_info as text;
reponse
success

create col_type end_user as text;
reponse
success

create merge table items( item_id t_item_id, art_label text, dept t_dept_id, avg_week_sales number, sales_price number);
reponse
success

create merge table customers( customer_id t_customer_id, customer_name text);
reponse
success

create table item_tags( item_id t_item_id, tag text);
reponse
success

create table fidelity_cards( customer_id t_customer_id, card_label t_customer_info, valid_from t_date, valid_until t_date);
reponse
success

create table item_customer_infos( customer_id t_customer_id, item_id t_item_id, info t_customer_info, valid_from t_date, valid_until t_date);
reponse
success

create big table sales( item_id t_item_id, customer_id t_customer_id, sales_date t_date, sales_qty number, line_id text, packaging_id t_item_id);
reponse
success

create big table inventory( item_id t_item_id, inv_qty number);
reponse
success

create view v_items as select * from items;
reponse
success

create view v_item_tags as select * from item_tags;
reponse
success

create view v_fidelity_cards as select * from fidelity_cards;
reponse
success

create view v_item_customer_infos as select * from item_customer_infos;
reponse
success

create view v_sales as select * from sales, items, customers where items.item_id=sales.item_id and customers.customer_id=sales.customer_id;
reponse
success

create view v_inventory as select * from inventory, items where items.item_id=inventory.item_id;
reponse
success

insert into items values('artA','the article A','dept #1',10,1.5);
reponse
success

insert into items values('artB','the article B','dept #2',10,3.2);
reponse
success

insert into items values('box1','a box','packaging',10,0);
reponse
success

insert into customers values('C1','customer #1')('C2','customer #2');
reponse
success

insert into item_tags values('artA','tag #1');
reponse
success

insert into item_tags values('artA','tag #2');
reponse
success

insert into fidelity_cards values('C1','SILVER','20191201','20191231');
reponse
success

insert into fidelity_cards values('C1','GOLD','20201201','20201231');
reponse
success

insert into item_customer_infos values('C1','artA','FREQUENT BUYER of artA in 2019','20190101','20191231');
reponse
success

insert into item_customer_infos values('C1','artB','FREQUENT BUYER of artB in 2020','20200101','20201231');
reponse
success

insert into item_customer_infos values('C2','artB','FREQUENT BUYER of artB in 2020','20200101','20201231');
reponse
success

insert into sales values('artA','C1','20191231',5,'ID01','box1');
reponse
success

insert into sales values('artB','C2','20200102',6,'ID02','');
reponse
success

insert into sales values('artB','C1','20191231',4,'ID03','');
reponse
success

insert into sales values('artB','C2','20200102',7,'ID04','box1');
reponse
success

insert into sales values('artC','C1','20200102',8,'ID05','');
reponse
success

insert into sales values('artA','C1','20191231',5,'ID06','box1');
reponse
success

insert into sales values('artA','C2','20191231',5,'ID07','box1');
reponse
success

insert into inventory values('artA',32);
reponse
success

insert into inventory values('artC',12);
reponse
success

refresh dirty view;
reponse
success

-- ###########################
-- RUNNING doc_basics.sql
--

Basics

--

flat select

select <*|table1.*|col1|table1#col1>, ... from ...
desc view;
view_nametable_countrel_countis_dirtyis_mp_dirtyis_partialfirst_ilinemp_rare_countmp_often_countmp_countr_online_countmp_r_online_count
v_items13nnn100131300
v_item_tags12nnn100121200
v_fidelity_cards12nnn100121200
v_item_customer_infos13nnn100131300
v_sales32nnn100121200
v_sales_#partition#_0000132nnn100121200
v_sales_#partition#_0000232nnn100121200
v_inventory22nnn100121200
v_sales_#partition#_0000331nnn100111100

select * from v_items;
item_idart_labeldeptavg_week_salessales_price
artAthe article Adept #1101.500
artBthe article Bdept #2103.200
box1a boxpackaging100

select * from v_item_tags;
item_idtag
artAtag #1
artAtag #2

select * from v_sales;
item_idcustomer_idsales_datesales_qtyline_idpackaging_iditem_idart_labeldeptavg_week_salessales_pricecustomer_idcustomer_name
artAC1201912315ID01box1artAthe article Adept #1101.500C1customer #1
artBC2202001026ID02#artBthe article Bdept #2103.200C2customer #2
artBC1201912314ID03#artBthe article Bdept #2103.200C1customer #1
artBC2202001027ID04box1artBthe article Bdept #2103.200C2customer #2
#C1202001028ID05####00C1customer #1
artAC1201912315ID06box1artAthe article Adept #1101.500C1customer #1
artAC2201912315ID07box1artAthe article Adept #1101.500C2customer #2

select sales.* from v_sales;
item_idcustomer_idsales_datesales_qtyline_idpackaging_id
artAC1201912315ID01box1
artBC2202001026ID02#
artBC1201912314ID03#
artBC2202001027ID04box1
#C1202001028ID05#
artAC1201912315ID06box1
artAC2201912315ID07box1

--

group by select

select col1, col2, ... from ... group by col1, col2, ...
group by clause can be ommited
select item_id, count(*) from v_items group by item_id;
item_idcount(*)
artA1
artB1
box11

select item_id, count(*) from v_item_tags group by item_id;
item_idcount(*)
artA2

select customer_id, dept, avg_week_sales, count(*) from v_sales group by customer_id, dept, avg_week_sales;
customer_iddeptavg_week_salescount(*)
C1dept #1102
C2dept #2102
C1dept #2101
C1##1
C2dept #1101

--group by can be ommited if group by is on text columns
select customer_id, dept, count(*) from v_sales;
customer_iddeptcount(*)
C1dept #12
C2dept #22
C1dept #21
C1#1
C2dept #11

--

callback basics

Ths callback allows to run functions on the resultset
select .. from .. <callback|cb> callback_function1 callback_function2 ...
cb is a shortcut for callback
most common callbacks are sort and limit
more info are provided in "callback Lua functions" section
select customer_id, count(*) from v_sales group by customer_id
callback sort(2,'desc');
customer_idcount(*)
C14
C23

select customer_id, count(*) from v_sales group by customer_id
callback sort(2,'asc') limit(1);
customer_idcount(*)
C23

select customer_id, count(*) from v_sales group by customer_id
cb sort(2,'asc') limit(1);
customer_idcount(*)
C23

select customer_id, count(*)as nb_sales from v_sales group by customer_id
cb sort('nb_sales','asc') limit(1);
customer_idnb_sales
C23

--

common aggregation operators

<sum|count|countdistinct|min|max|avg>
--sum (number columns only)
select customer_id, sum(sales_qty), sum(avg_week_sales) from v_sales group by customer_id;
customer_idsum(sales_qty)sum(avg_week_sales)
C12230
C21830

--count
select customer_id, count(item_id), count(sales_qty), count(avg_week_sales) from v_sales group by customer_id;
customer_idcount(item_id)count(sales_qty)count(avg_week_sales)
C1343
C2333

--countdistinct
select customer_id, countdistinct(item_id), countdistinct(sales_qty), countdistinct(avg_week_sales) from v_sales group by customer_id;
customer_idcountdistinct(item_id)countdistinct(sales_qty)countdistinct(avg_week_sales)
C1231
C2231

--min
select customer_id, min(item_id), min(sales_qty), min(avg_week_sales) from v_sales group by customer_id;
customer_idmin(item_id)min(sales_qty)min(avg_week_sales)
C1artA410
C2artA510

--max
select customer_id, max(item_id), max(sales_qty), max(avg_week_sales) from v_sales group by customer_id;
customer_idmax(item_id)max(sales_qty)max(avg_week_sales)
C1artB810
C2artB710

--avg (number columns only)
select customer_id, avg(sales_qty), avg(avg_week_sales) from v_sales group by customer_id;
customer_idavg(sales_qty)avg(avg_week_sales)
C15.50010
C2610

--

other aggregation operators

<unique|countsequence|minstr|maxstr|list|ival|ivallist|ivalbin|p>
Note: uniquesoft can be used instead of unique for backward compatibility, behavior is the same
select customer_id, unique(line_id), unique(item_id), unique(customer_id) from v_sales group by customer_id;
customer_idunique(line_id)unique(item_id)unique(customer_id)
C1#artAC1
C2ID07#C2

select customer_id, countsequence(item_id) from v_sales group by customer_id;
customer_idcountsequence(item_id)
C13
C22

select customer_id, minstr(item_id) from v_sales group by customer_id;
customer_idminstr(item_id)
C1artA
C2artA

select customer_id, maxstr(item_id) from v_sales group by customer_id;
customer_idmaxstr(item_id)
C1artB
C2artB

select customer_id, list(item_id) from v_sales group by customer_id;
customer_idlist(item_id)
C1artA,artB
C2artA,artB

select customer_id, ival(item_id), ival(customer_id) from v_sales group by customer_id;
customer_idival(item_id)ival(customer_id)
C11111
C2#12

select customer_id, ivallist(item_id), ivallist(customer_id) from v_sales group by customer_id;
customer_idivallist(item_id)ivallist(customer_id)
C111/1211
C211/1212

select customer_id, ivalbin(item_id), ivalbin(customer_id) from v_sales group by customer_id;
customer_idivalbin(item_id)ivalbin(customer_id)
C161442048
C261444096

select customer_id, p(item_id), p(customer_id) from v_sales group by customer_id;
customer_id

orphans management and dimension priority

Column item_id in view v_sales can come from table sales or table items
For artA and artB we don't care
For artC we do care because artC is a orhan record (*)
By default SB will look for item_id in non empty (**) dimension tables (***), then in the fact table
But you can tell SB which one you want using table#col syntax
(*) exists in fact table but not in dimension table
(**) an empty dimension is skipped
(***) dimension1 is the second table of from clause of the view create statement etc...,
--> !!! the order of dimensions in the from clause of the view create statement is important
select item_id,sales#item_id,items#item_id from v_sales;
item_idsales#item_iditems#item_id
artAartAartA
artBartBartB
artBartBartB
artBartBartB
#artC#
artAartAartA
artAartAartA

select count(*) from v_sales and item_id='artC';
count(*)

select count(*) from v_sales and items#item_id='artC';
count(*)

select count(*) from v_sales and sales#item_id='artC';
count(*)
1

escape quote

''
insert into item_tags values('artD','A''__B');
reponse
success

refresh dirty view;
reponse
success

select * from v_item_tags where item_id='artD';
item_idtag
artDA'__B

select * from v_item_tags where tag='A''__B';
item_idtag
artDA'__B

Stormbase & Lua

Lua is a progamming langage.
Stormbase is not developped in Lua, it is developped in native C.
But in some cases (callbacks and where clause, see here under) Stormbase calls Lua code.
Standard Lua code (provided in Stormbase installer) is located in _FUNCTIONS/stormbase.lua.
Custom Lua code can also be added in _FUNCTIONS/custom.lua.

utility Lua functions

--utility functions list
desc function callback where(2,'utility');
function_namefunction_typesignaturecomment
ratioutilityratio( value1, value2)returns value1/value2 or 0 in limit cases (division by zero, nil value)
roundutilityround( v , n_digits )returns math.floor(v+0.5), with n_digits precision, n_digits defaults to 0
decodeutilitydecode( x , y , a , b )returns a in x equals y , b otherwise
leastutilityleast( x , y )checks that x and y are numbers and returns least
greatestutilitygreatest( x , y )checks that x and y are numbers and returns greatest
ceilutilityceil( x )checks that x is number and calls math.ceil
floorutilityfloor( x )checks that x is number and calls math.floor
checkutilitycheck( cond )boolean function
instrutilityinstr( str1 , str2 )calls string.find(str1, str2), returns -1 if not found
lengthutility length( tbl )return numbers of key of a key/value table
mergeutilitymerge( tbl1, tbl2 )sums the values of 2 key/value tables
stringifyutilitystringify( tbl )stringify a key/value table
joinutilityjoin(idx_values, arr_fields, _sep, _type, fn)joins an array _sep, _type and fn are optional
concatutilityconcat( a , b, c, d, e, f )returns a .. nvl(b,"") .. nvl(c,"") .. nvl(d,"") .. nvl(e,"") .. nvl(f,"")
nvlutilitynvl( a , b )returns b if a==nil

callback Lua functions

--callback functions list
desc function callback where(2,'callback');
function_namefunction_typesignaturecomment
add_numbercallbackadd_number( name, str_fn )adds a number column to resultset
add_textcallbackadd_text( name, str_fn )adds a text column to resultset
select_fromcallbackselect_from( 'group(<column_pos/column_name>) <sum/count/avg/min/max>(<column_pos/column_name>)' )does a select ... from (the_resultset)
sub_selectcallbacksub_select( 'group(<column_pos/column_name>) <sum/count/avg/min/max>(<column_pos/column_name>)' )adds a sub select column
wherecallbackwhere( <column_pos/column_name> , 'value' )does an "equal where clause" on the resultset
likecallbacklike( <column_pos/column_name> , 'value1!value2' )does a "like where clause" on the resultset
grepcallbackgrep( 'value1!value2' )does a "like where clause" on the resultset
limitcallbacklimit( rownum )limits the resultset to rownum lines
sortcallbacksort( <column_pos1/column_name1> , <'asc'/'desc'> , <column_pos2/column_name2> , ... )sorts the resultset
exportcallbackexport( path/to/file , header_yn )
open_joincallbackopen_join( 'with1,with2..' , 'join_col1,join_col2..' , 'new_with_name')do an open join on withs
renamecallbackrename( 'col_name' , 'new_col_name' )rename a column
keep_columnscallbackkeep_columns( 'col1,col2...' )keeps column list

select item_id,customer_id,sum(sales_qty) from v_sales group by item_id,customer_id callback sort(3,'asc');
item_idcustomer_idsum(sales_qty)
artBC14
artAC25
#C18
artAC110
artBC213

select item_id,sum(sales_qty) from v_sales group by item_id callback sort(2,'asc');
item_idsum(sales_qty)
#8
artA15
artB17

select customer_id,sum(sales_qty) from v_sales group by customer_id callback sort(2,'asc');
customer_idsum(sales_qty)
C218
C122

select item_id,customer_id,sales_qty from v_sales
callback select_from('group(1) group(2) sum(3)') sort(3,'asc');
group_item_idgroup_customer_idsum_sales_qty
artBC14
artAC25
#C18
artAC110
artBC213

select item_id,customer_id,sales_qty from v_sales
callback select_from('group(1) sum(3)') sort(2,'asc');
group_item_idsum_sales_qty
#8
artA15
artB17

select item_id,customer_id,sales_qty from v_sales
callback select_from('group(2) sum(3)') sort(2,'asc');
group_customer_idsum_sales_qty
C218
C122

select item_id,customer_id,sales_qty from v_sales
callback sub_select('group(1) group(2) sum(3)');
item_idcustomer_idsales_qtygroup_item_idgroup_customer_idsum_sales_qty
artAC15artAC110
artBC26artBC213
artBC14artBC14
artBC27artBC213
#C18#C18
artAC15artAC110
artAC25artAC25

select item_id,customer_id,sales_qty from v_sales
callback sub_select('group(2) sum(3)');
item_idcustomer_idsales_qtygroup_customer_idsum_sales_qty
artAC15C122
artBC26C218
artBC14C122
artBC27C218
#C18C122
artAC15C122
artAC25C218

select sales_date, dept, sum(sales_qty) from v_sales;
sales_datedeptsum(sales_qty)
20191231dept #115
20200102dept #213
20191231dept #24
20200102#8

select dept, sum(sales_qty) from v_sales;
deptsum(sales_qty)
dept #115
dept #217
#8

select sum(sales_qty) from v_sales;
sum(sales_qty)
40

with
a as(select sales_date, dept, sum(sales_qty) as sales_qty from v_sales),
b as(select dept, sum(sales_qty) as dept_sales_qty from v_sales),
c as(select sum(sales_qty) as tot_sales_qty from v_sales),
select from no_view, * function fn_nothing
cb
open_join('a,b','dept','a_b')
open_join('a_b,c')
add_number('dept_share','return round(line.sales_qty/line.dept_sales_qty*100,3)')
add_number('total_share','return line.sales_qty/line.tot_sales_qty*100')
keep_columns('sales_date,dept,sales_qty,dept_sales_qty,dept_share,total_share')
;
sales_datedeptsales_qtydept_sales_qtydept_sharetotal_share
20200102#8810020
20200102dept #2131776.47132.500
20191231dept #241723.52910
20191231dept #1151510037.500

data model modification #1

...
create big table sales( item_id t_item_id, customer_id t_customer_id, sales_date text, sales_qty number, line_id text, packaging_id t_item_id, sales_qty2 number);
reponse
success

--commit changes
refresh dirty view;
reponse
success

select sales.* from v_sales;
item_idcustomer_idsales_datesales_qtyline_idpackaging_idsales_qty2
artAC1201912315ID01box10
artBC2202001026ID02#0
artBC1201912314ID03#0
artBC2202001027ID04box10
#C1202001028ID05#0
artAC1201912315ID06box10
artAC2201912315ID07box10

insert into sales values('artA','C2','20191231',5,'ID09','',55);
reponse
success

refresh dirty view;
reponse
success

select sales.* from v_sales;
item_idcustomer_idsales_datesales_qtyline_idpackaging_idsales_qty2
artAC1201912315ID01box10
artBC2202001026ID02#0
artBC1201912314ID03#0
artBC2202001027ID04box10
#C1202001028ID05#0
artAC1201912315ID06box10
artAC2201912315ID07box10
artAC2201912315ID09#55

data model modification #2

Since v1.17.08 SB is a lot more flexible
create col_type t_a as text;
reponse
success

create col_type t_c as text;
reponse
success

create merge table dim_a (a t_a, aa text);
reponse
success

create big table foo (a t_a, b number, c text);
reponse
success

create view v_foo as select * from foo, dim_a where foo.a=dim_a.a;
reponse
success

refresh dirty view;
reponse
success

insert into foo values('a1',1,'c1');
reponse
success

insert into foo values('a2',2,'c2');
reponse
success

insert into dim_a values('a1','aa1')('a2','aa2')('a3','aa3');
reponse
success

refresh dirty view;
reponse
success

select * from v_foo;
abcaaa
a11c1a1aa1
a22c2a2aa2

--col_type change --> forbidden
continue_on_error(121);
reponse
success

create big table foo (a t_a, b number, c t_c);
reponse
error 121 (continue): changing column type during table alter is not allowed

--col position change and/or add column --> ok
create big table foo (c text, a t_a, b number, d text);
reponse
success

desc table cb grep('foo');
table_namecolumn_countline_counthas_deletehas_updateparent_view_hidden
foo32nnn
__NEW_foo__40nnn

desc view cb grep('foo');
view_nametable_countrel_countis_dirtyis_mp_dirtyis_partialfirst_ilinemp_rare_countmp_often_countmp_countr_online_countmp_r_online_count
v_foo22ynn100121200

--view must be recreated because joined columns position have changed, hence the error here under
continue_on_error(43);
reponse
success

refresh dirty view;
reponse
error 43 (continue): joined columns must have same column type

desc view cb grep('foo');
view_nametable_countrel_countis_dirtyis_mp_dirtyis_partialfirst_ilinemp_rare_countmp_often_countmp_countr_online_countmp_r_online_count
v_foo22ynn100121200

continue_on_error(1);
reponse
success

create view v_foo as select * from foo, dim_a where foo.a=dim_a.a;
reponse
success

refresh dirty view;
reponse
success

desc table cb grep('foo');
table_namecolumn_countline_counthas_deletehas_updateparent_view_hidden
foo42nnn

desc view cb grep('foo');
view_nametable_countrel_countis_dirtyis_mp_dirtyis_partialfirst_ilinemp_rare_countmp_often_countmp_countr_online_countmp_r_online_count
v_foo22nnn100121200

select * from v_foo;
cabdaaa
c1a11NO_DATAa1aa1
c2a22NO_DATAa2aa2

insert into foo values('c3','a3',3,'d3');
reponse
success

insert into foo values('c4','a4',4,'d4');
reponse
success

refresh dirty view;
reponse
success

select * from v_foo;
cabdaaa
c1a11NO_DATAa1aa1
c2a22NO_DATAa2aa2
c3a33d3a3aa3
c4#4d4##

create big table foo (c text, d text, b number);
reponse
success

create view v_foo as select * from foo;
reponse
success

refresh dirty view;
reponse
success

select * from v_foo;
cdb
c1NO_DATA1
c2NO_DATA2
c3d33
c4d44

--

where clause basics

select .. from ...
<where|and> where_clause1
and where_clause2
and where_clause3
..
Where clause syntax
column_name='value'
column_name in ('value1', 'value2', ...)
column_name nin ('value1', 'value2', ...)
column_name like 'value'
select * from v_sales and dept='dept #1';
item_idcustomer_idsales_datesales_qtyline_idpackaging_idsales_qty2item_idart_labeldeptavg_week_salessales_pricecustomer_idcustomer_name
artAC1201912315ID01box10artAthe article Adept #1101.500C1customer #1
artAC1201912315ID06box10artAthe article Adept #1101.500C1customer #1
artAC2201912315ID07box10artAthe article Adept #1101.500C2customer #2
artAC2201912315ID09#55artAthe article Adept #1101.500C2customer #2

--SB allows you to use "and" instead of where, bacause it is easier
select * from v_sales and dept='dept #1';
item_idcustomer_idsales_datesales_qtyline_idpackaging_idsales_qty2item_idart_labeldeptavg_week_salessales_pricecustomer_idcustomer_name
artAC1201912315ID01box10artAthe article Adept #1101.500C1customer #1
artAC1201912315ID06box10artAthe article Adept #1101.500C1customer #1
artAC2201912315ID07box10artAthe article Adept #1101.500C2customer #2
artAC2201912315ID09#55artAthe article Adept #1101.500C2customer #2

select * from v_sales and dept in ('dept #1');
item_idcustomer_idsales_datesales_qtyline_idpackaging_idsales_qty2item_idart_labeldeptavg_week_salessales_pricecustomer_idcustomer_name
artAC1201912315ID01box10artAthe article Adept #1101.500C1customer #1
artAC1201912315ID06box10artAthe article Adept #1101.500C1customer #1
artAC2201912315ID07box10artAthe article Adept #1101.500C2customer #2
artAC2201912315ID09#55artAthe article Adept #1101.500C2customer #2

select * from v_sales and dept nin ('dept #2');
item_idcustomer_idsales_datesales_qtyline_idpackaging_idsales_qty2item_idart_labeldeptavg_week_salessales_pricecustomer_idcustomer_name
artAC1201912315ID01box10artAthe article Adept #1101.500C1customer #1
#C1202001028ID05#0###00C1customer #1
artAC1201912315ID06box10artAthe article Adept #1101.500C1customer #1
artAC2201912315ID07box10artAthe article Adept #1101.500C2customer #2
artAC2201912315ID09#55artAthe article Adept #1101.500C2customer #2

--like is not case sensitive
select * from v_sales and dept like 'DePt #1';
item_idcustomer_idsales_datesales_qtyline_idpackaging_idsales_qty2item_idart_labeldeptavg_week_salessales_pricecustomer_idcustomer_name
artAC1201912315ID01box10artAthe article Adept #1101.500C1customer #1
artAC1201912315ID06box10artAthe article Adept #1101.500C1customer #1
artAC2201912315ID07box10artAthe article Adept #1101.500C2customer #2
artAC2201912315ID09#55artAthe article Adept #1101.500C2customer #2

--

where clause / Lua boolean function

any Lua boolean function can be used in a where clause using one and only one column
--boolean functions list
desc function callback where(2,'boolean');
function_namefunction_typesignaturecomment
regexbooleanregex( str , pattern )returns true is if string.match( str , pattern ) (upperbase comparaison) more info http://www.lua.org/manual/5.2/manual.html#6.4.1
is_notbooleanis_not( boolean_value )returns not boolean_value
regex_orbooleanfunction regex_or( str , pattern, pattern2, ...)returns regex( str , pattern ) or regex( str , pattern2 ) ...
btwbooleanbtw( x , y , z )returns true if y < x and x <=z then (number comparaison)
btwebooleanbtwe( x , y , z )returns true if y <= x and x <= z then (number comparaison)
btwe_sbooleanbtwe_s( x , y , z )returns true if y <= x and x <= z then (string comparaison)
nbtwebooleannbtwe( x , y , z )not between or equal, returns false if y <= x and x <= z
btwe_orbooleanfunction btwe_or( x , y , z , y2 , z2 ... )returns btwe( x , y , z ) or btwe( x , y2 , z2 )
nbtwe_andbooleanfunction nbtwe_and( x , y , z , y2 , z2 ... )returns nbtwe( x , y , z ) and nbtwe( x , y2 , z2 )
gtbooleangt( x , y )greater than, returns true is x > y (number comparaison)
gtebooleangte_( x , y )greater than or equal, returns true is x >= y (number comparaison)
ltbooleanlt( x , y )lower than, returns true is x < y (number comparaison)
ltebooleanlte( x , y )lower than or equal, returns true is x <= y (number comparaison)
gt_sbooleangt_s( x , y )greater than, returns true is x > y (string comparaison)
gte_sbooleangte_s( x , y )greater than or equal, returns true is x >= y (string comparaison)
lt_sbooleanlt_s( x , y )lower than, returns true is x < y (string comparaison)
lte_sbooleanlte_s( x , y )lower than or equal, returns true is x <= y (string comparaison)
ebooleane( x , y )equal, returns true is x==y
nebooleanne( x , y )not equal, returns true is x!=y
isinbooleanisin( x , { val1, val2, .. } )is in
isninbooleanisnin( x , { val1, val2, .. } )is not in
modbooleanmod( x , y , z )(x % y) == z

--

(not)exists basics

select .. from view1
and view2.col='something'
Exists
and view2!.col='something'
Not exists
The exists join between view1 and view2 is implicit (the first col_type in common will be used for join)
Use case: when view2 is based on a non merge table, which why it can't be included in view1
--
--
--exists
select sales.* from v_sales
where v_item_tags.tag='tag #1';
item_idcustomer_idsales_datesales_qtyline_idpackaging_idsales_qty2
artAC1201912315ID01box10
artAC1201912315ID06box10
artAC2201912315ID07box10
artAC2201912315ID09#55

--not exists
select sales.* from v_sales
where v_item_tags!.tag='tag #1';
item_idcustomer_idsales_datesales_qtyline_idpackaging_idsales_qty2
artBC2202001026ID02#0
artBC1201912314ID03#0
artBC2202001027ID04box10
#C1202001028ID05#0

col_type_checks basics

A col_type_check is a "select col, count(col) from .. where ... group by col"
It is used to filter other part of the sql
The filter will be applied on the first column that has same col_type as the col_type_check
If you alias your group by column in the with clause, the filter with apply in priority to a column with this name (if it exists)
with
with_name1 ( col_type_check1 ),
with_name2 ( col_type_check2 ),
...
select .. from view1, with_name1, with_name2! ..
select item_id, dept from v_items cb sort(1,'asc');
item_iddept
artAdept #1
artBdept #2
box1packaging

--sales in dept #1
with
a as(select item_id, count(item_id) from v_items where dept='dept #1' group by item_id)
select sales.* from v_sales, a
;
item_idcustomer_idsales_datesales_qtyline_idpackaging_idsales_qty2
artAC1201912315ID01box10
artAC1201912315ID06box10
artAC2201912315ID07box10
artAC2201912315ID09#55

--sales not in dept #1
with
a as(select item_id, count(item_id) from v_items where dept='dept #1' group by item_id)
select sales.* from v_sales, a!
;
item_idcustomer_idsales_datesales_qtyline_idpackaging_idsales_qty2
artBC2202001026ID02#0
artBC1201912314ID03#0
artBC2202001027ID04box10
#C1202001028ID05#0

--using alias
--if the alias can't be found, the "first column with same col_type" rule applies
with
a as(select item_id as columm_that_does_not_exists, count(item_id) from v_items where dept='dept #1' group by item_id)
select sales.* from v_sales, a
;
item_idcustomer_idsales_datesales_qtyline_idpackaging_idsales_qty2
artAC1201912315ID01box10
artAC1201912315ID06box10
artAC2201912315ID07box10
artAC2201912315ID09#55

--no packaging in dept #1
with
a as(select item_id as packaging_id, count(item_id) from v_items where dept='dept #1' group by item_id)
select sales.* from v_sales, a
;
item_idcustomer_idsales_datesales_qtyline_idpackaging_idsales_qty2

--sales of items having packaging in dept packaging
with
a as(select item_id as packaging_id, count(item_id) from v_items where dept='packaging' group by item_id)
select sales.* from v_sales, a
;
item_idcustomer_idsales_datesales_qtyline_idpackaging_idsales_qty2
artAC1201912315ID01box10
artBC2202001027ID04box10
artAC1201912315ID06box10
artAC2201912315ID07box10

col_type_checks advanced

Col_type_checks can be combined to do intersection etc...
It is used to filter other part of the sql
with
with_name1 ( col_type_check1 ),
with_name2 ( select col, count(col) from view2, with_name1 where ... group by col ),
...
select .. from view3, with_name2
select item_id, dept, customer_id, sales_qty from v_sales;
item_iddeptcustomer_idsales_qty
artAdept #1C15
artBdept #2C26
artBdept #2C14
artBdept #2C27
##C18
artAdept #1C15
artAdept #1C25
artAdept #1C25

select * from v_item_tags;
item_idtag
artAtag #1
artAtag #2
artDA'__B

--in which other departments do customers that buy from dept #1, buy from
--the group of customers is "customers that buy from dept #1"
with
group_of_customers as(select customer_id, count(customer_id) from v_sales and dept='dept #1' group by customer_id)
select dept,count(*),list(customer_id) from v_sales, group_of_customers and dept nin ('dept #1',null) group by dept
;
deptcount(*)list(customer_id)
dept #23C1,C2

select customer_id, count(customer_id) from v_sales and dept='dept #1' group by customer_id
;
customer_idcount(customer_id)
C12
C22

with
group_of_customers as(select customer_id, count(customer_id) from v_sales and dept='dept #1' group by customer_id)
select sales.* from v_sales, group_of_customers and dept nin ('dept #1',null)
;
item_idcustomer_idsales_datesales_qtyline_idpackaging_idsales_qty2
artBC2202001026ID02#0
artBC1201912314ID03#0
artBC2202001027ID04box10

--sames thing but my group of customers is "customers that buy from dept #1" and "buy item with tag #1"
with
items_with_tag1 as(select item_id, count(item_id) from v_item_tags and tag='tag #1' group by item_id),
group_of_customers as(select customer_id, count(customer_id) from v_sales, items_with_tag1 and dept='dept #1' group by customer_id)
select dept,count(*),list(customer_id) from v_sales, group_of_customers and dept nin ('dept #1',null) group by dept
;
deptcount(*)list(customer_id)
dept #23C1,C2

permissions

end_user col_type
create table article_permission ( user_name end_user, art_id t_item_id);
reponse
success

insert into article_permission values('rd','artA');
reponse
success

insert into article_permission values('pt','artA');
reponse
success

insert into article_permission values('pt','artB');
reponse
success

create view v_article_permission as select * from article_permission;
reponse
success

create table customer_permission ( user_name end_user, customer_id t_customer_id);
reponse
success

insert into customer_permission values('rd','C1');
reponse
success

insert into customer_permission values('pt','*');
reponse
success

create view v_customer_permission as select * from customer_permission;
reponse
success

refresh dirty view;
reponse
success

select * from v_sales where end_user='pt';
item_idcustomer_idsales_datesales_qtyline_idpackaging_idsales_qty2item_idart_labeldeptavg_week_salessales_pricecustomer_idcustomer_name
artAC1201912315ID01box10artAthe article Adept #1101.500C1customer #1
artBC2202001026ID02#0artBthe article Bdept #2103.200C2customer #2
artBC1201912314ID03#0artBthe article Bdept #2103.200C1customer #1
artBC2202001027ID04box10artBthe article Bdept #2103.200C2customer #2
artAC1201912315ID06box10artAthe article Adept #1101.500C1customer #1
artAC2201912315ID07box10artAthe article Adept #1101.500C2customer #2
artAC2201912315ID09#55artAthe article Adept #1101.500C2customer #2

select * from v_sales where end_user='rd';
item_idcustomer_idsales_datesales_qtyline_idpackaging_idsales_qty2item_idart_labeldeptavg_week_salessales_pricecustomer_idcustomer_name
artAC1201912315ID01box10artAthe article Adept #1101.500C1customer #1
artAC1201912315ID06box10artAthe article Adept #1101.500C1customer #1

dynamic code

The backquotes
TODO explain the tonumber
TODO explain the tag #DYN_SQL#, #DYN_SQL# before cache management
TODO explain number_to_string
TODO explain _headers
TODO note `join(a_headers)` the inside of the backquotes is considered as one word during parsing
select item_id, sales_qty from v_sales callback sort(2,'asc');
item_idsales_qty
artB4
artA5
artA5
artA5
artA5
artB6
artB7
#8

--#SB no_cache
select item_id, sales_qty from v_sales and gte(sales_qty,50/10) callback sort(2,'asc');
item_idsales_qty
artA5
artA5
artA5
artA5
artB6
artB7
#8

--#SB no_cache
select item_id, sales_qty from v_sales and gte(sales_qty,`#DYN_SQL#50/10`) callback sort(2,'asc');
item_idsales_qty
artA5
artA5
artA5
artA5
artB6
artB7
#8

--#SB no_cache
`#LOAD#num=50;den=10`select item_id, sales_qty from v_sales and gte(sales_qty,`#DYN_SQL#num/den`) callback sort(2,'asc');
item_idsales_qty
artA5
artA5
artA5
artA5
artB6
artB7
#8

with
total_sales as(select sum(sales_qty) as v from v_sales function fn_store),
a as(
  select item_id, sum(sales_qty) as v from v_sales function fn_store
  group by item_id)
b as(
  select item_id, sum(sales_qty) as v from v_sales function fn_store
  where gte(sales_qty,`total_sales.v/10`)
  group by item_id)
select
col_type.val,
total_sales.v,
a.v,
b.v,
`"11"..sep().."12"` as `"col1"..sep().."col2"`
from no_view, * function fn_merge;
col_type.valtotal_sales.va.vb.vcol1col2
458811!12
artA45202011!12
artB45171311!12

--#SB no_cache
`#DYN_SQL#decode(true,true,"select item_id, sales_qty from v_sales","another sql")` callback sort(1,'asc');
item_idsales_qty
#8
artA5
artA5
artA5
artA5
artB6
artB4
artB7

--#SB no_cache
`#LOAD#toto="ABC";``#DYN_SQL#decode(toto,"ABC","select item_id, sales_qty from v_sales callback sort(1,'asc')","another sql")`;
item_idsales_qty
#8
artA5
artA5
artA5
artA5
artB6
artB4
artB7

--#SB no_cache
with
total_sales as(
  `#LOAD#same_code="sum(sales_qty) as v from v_sales function fn_store" same_code2="group by item_id"`
  select `#DYN_SQL#same_code`
),
a as(
  select item_id, `#DYN_SQL#same_code`
  `#DYN_SQL#same_code2`)
b as(
  select item_id, `#DYN_SQL#same_code`
  where gte(sales_qty,`total_sales.v/10`)
  `#DYN_SQL#same_code2`)
select
col_type.val,
total_sales.v,
a.v,
b.v,
round(a.v)..sep()..'12' as `"col1"..sep().."col2"`,
number_to_string(a.v)..sep()..'12' as `"col3"..sep().."col4"`,
stringify(a) as txt,
from no_view, * function fn_merge;
col_type.valtotal_sales.va.vb.vcol1col2col3col4txt
45888!128!12{v:8,}
artA45202020!1220!12{v:20,}
artB45171317!1217!12{v:17,}

with a as(select item_id, sum(sales_qty), max(sales_qty), avg(sales_qty), min(sales_qty) from v_sales function fn_store group by item_id)
select col_type.val, stringify(a_headers) from no_view, * function fn_merge
;
col_type.valstringify(a_headers)
{1:'sum(sales_qty)',2:'max(sales_qty)',4:'min(sales_qty)',3:'avg(sales_qty)',}
artA{1:'sum(sales_qty)',2:'max(sales_qty)',4:'min(sales_qty)',3:'avg(sales_qty)',}
artB{1:'sum(sales_qty)',2:'max(sales_qty)',4:'min(sales_qty)',3:'avg(sales_qty)',}

with a as(select item_id, sum(sales_qty), max(sales_qty), avg(sales_qty), min(sales_qty) from v_sales function fn_store group by item_id)
select
  col_type.val,
  join(a,a_headers,"__"),
  join(a,a_headers) as `join(a_headers)`
from no_view, * function fn_merge
;
col_type.valjoin(a,a_headers,"__")sum(sales_qty)max(sales_qty)avg(sales_qty)min(sales_qty)
8__8__8__88!8!8!8
artA20__5__5__520!5!5!5
artB17__7__5.667__417!7!5.667!4

with
a as(select item_id, count(item_id) from v_items where dept='dept #1' group by item_id)
select sales.* from v_sales, a!
;
item_idcustomer_idsales_datesales_qtyline_idpackaging_idsales_qty2
artBC2202001026ID02#0
artBC1201912314ID03#0
artBC2202001027ID04box10
#C1202001028ID05#0

--sales of customer that have purchased in dept #1
with
b as(select customer_id, count(item_id) from v_sales where dept='dept #1' group by customer_id)
select sales.* from v_sales, b
;
item_idcustomer_idsales_datesales_qtyline_idpackaging_idsales_qty2
artAC1201912315ID01box10
artBC2202001026ID02#0
artBC1201912314ID03#0
artBC2202001027ID04box10
#C1202001028ID05#0
artAC1201912315ID06box10
artAC2201912315ID07box10
artAC2201912315ID09#55

--sales of customer that have purchased in dept #1, without the dept #1 sales
with
a as(select item_id, count(item_id) from v_items where dept='dept #1' group by item_id),
b as(select customer_id, count(item_id) from v_sales where dept='dept #1' group by customer_id)
select sales.* from v_sales, a!, b
;
item_idcustomer_idsales_datesales_qtyline_idpackaging_idsales_qty2
artBC2202001026ID02#0
artBC1201912314ID03#0
artBC2202001027ID04box10
#C1202001028ID05#0

select * from v_sales and dept like 'dept #1'
;
item_idcustomer_idsales_datesales_qtyline_idpackaging_idsales_qty2item_idart_labeldeptavg_week_salessales_pricecustomer_idcustomer_name
artAC1201912315ID01box10artAthe article Adept #1101.500C1customer #1
artAC1201912315ID06box10artAthe article Adept #1101.500C1customer #1
artAC2201912315ID07box10artAthe article Adept #1101.500C2customer #2
artAC2201912315ID09#55artAthe article Adept #1101.500C2customer #2

-- ###########################
-- RUNNING shutdown.sql
shutdown;