-- ########################### -- 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_data_update.sql -- data in stormbase can be read/updated using loop statements and C programs loop table_name(col1, coll2, ...) function function_name(param1, param2, ...) update (updated_col1, updated_col1, ...) where ..../_SO_CODE/common.h
typedef struct sb_vals {
 // SB's version of the SB_VALS structure
 int sb_vals_version;
 // number of columns
 int count;
 // i_val of each column (loop function only)
 // NULL value: NULL_IVAL (see define here above)
 U_INT *i_vals;
 // num_val of each column (loop function only)
 // NULL value: NAN (C macro) (any float for which isnan evals to true)
 float *num_vals;
 // str_val of each column (loop function only)
 // NULL value: NULL (C macro) or SB_NULL (see define here above)
 char **str_vals;
 // type of each column, 2 possible values T (text) or N (number)
 char *types;
 // obvious
 char *table_name;
 // obvious
 char **column_names;
 // obvious
 char **col_type_names;
 // number of distinct i_val of each column
 U_INT *col_i_val_counts;
 // number of lines in table
 // (where clause is not taken into account)
 // (partitions are taken into account)
 long table_line_count;
 // (in/out) type used to update the columns type of each column,
 // 3 possible values: T (text) or N (number) or I (i_val)
 char *update_types;
 // (in/out) whatever pointer you write here in the before function will be passed to the loop/after functions
 void *context;
 // (in/out) response of the loop statement
 char *result;
 // (in/out) #threads that SB will create, default is 1, of course your code must be thread safe if you put 2+
 int thread_count; //SB_LIB_VERSION >= 1
 // current thread (loop function only)
 int thread_pos; //SB_LIB_VERSION >= 1
 // if you need a mutex in the loop function, you can use this one
 // obsolete, do not use (kept for compatibility matters)
 pthread_mutex_t loop_mutex; //SB_LIB_VERSION >= 2
 // parameters passed to the loop function (parameters and columns are not the same thing!)
 char **params; //SB_LIB_VERSION >= 3
 // #parameters passed to the loop function (parameters and columns are not the same thing!)
 int params_len; //SB_LIB_VERSION >= 3
 //in out fields (can be modified in before function):
 // thread_count (default 1)
 // (in/out) defines which partition should be fetch (default ALL_PARTITIONS, can be set to DIRTY_PARTITIONS_ONLY)
 int partitions_scope; //SB_LIB_VERSION >= 4
 // (in/out) defines which lines should be fetch (default ALL_LINES, can be set to LINES_INSERTED_SINCE_LAST_REFRESH_DIRTY_ONLY)
 int lines_scope; //SB_LIB_VERSION >= 5
 // context field behavior:
 // Note that the context is global (there is only one "loop context" at a given time: "the current loop context")
 // - pass by stormbase to all loop command
 // - the before function can set the context (any non NULL value will be considered as the current loop context)
 // - the after function can set the context to NULL and usually frees memory at the same time (NULL value will be considered as "setting the current loop context to NULL")
 // - any function can manipulate the current loop context, it is standard C manipulation
 // - if the before function sets a name to the current loop context, it can be recall later (in computed columns). Of course in that case the after function should not free it.
 char *context_name; //SB_LIB_VERSION >= 6
 // see structure definition
 UTILITY *U; //SB_LIB_VERSION >= 7
 // (in/out) optional name of the function to be called to free the context if any (added in v1.16.81)
 // this fn must be t_fn_free_context type
 char *fn_free_context_name; //SB_LIB_VERSION >= 8
 // (in/out) if update_types uses text update (type T), y means SB will free the pointer, default n
 // Note: many malloc/free will generate memory fragmentation at OS level, so it is better to manage a buffer in your custom code for text updates
 char text_update_sb_free; //SB_LIB_VERSION >= 10
 // (in/out) whatever pointer you write here in the before function will be passed to the loop/after functions,
 // the work_area can be considered as a second context except that it can't be called after the loop execution
 void *work_area; //SB_LIB_VERSION >= 13
 // (in) unique line number provide by SB during the fetch, note that line is always < table_line_count
 // the goal in to facilitate multi threading, you don't have to manage a counter with a mutex in your code
 // Note: a given line in a table may receive a different line_fetch number in distinct loop execution
 // Note: in after fn line_fetch will be equal to the number of line fetch
 long line_fetch; //SB_LIB_VERSION >= 14
} SB_VALS;
// before function (returns OK or KO)
typedef int (*t_fn_line_before)(SB_VALS *read, SB_VALS *new);
// loop function (returns DELETED or UPDATED or NOT_MODIFIED)
typedef int (*t_fn_line)(SB_VALS *read, SB_VALS *new);
// after function (returns OK or KO)
typedef int (*t_fn_line_after)(SB_VALS *read, SB_VALS *new);
// free function
typedef void (*t_fn_free_context)(void *context);
//./_SO_CODE/Z_doc_loop_AA.c
#include "./common.h"
int fn1_before(SB_VALS* read, SB_VALS* new) {
 printf("## hello from fn1_before\n" );
 read->thread_count = 2;
 return OK;
}
pthread_mutex_t my_mutex = PTHREAD_MUTEX_INITIALIZER;
int fn1(SB_VALS* read, SB_VALS* new) {
 printf("## hello from fn1 (thread_pos %d) : " , read->thread_pos);
 for (int i = 0; i < read-> count; i++) {
   if (read->types[i] == 'T') {
     printf("%s=%s (ival %u)" , read->column_names[i], read->str_vals[i], read->i_vals[i]);
   } else if (read->types[i] == 'N') {
     printf("%s=%.2f (ival %u)" , read->column_names[i], read->num_vals[i], read->i_vals[i]);
   }
   if (i != read->count - 1) {
     printf(", " );
   }
 }
 printf("\n" );
 return NOT_MODIFIED;
}
int fn1_after(SB_VALS* read, SB_VALS* new) {
 printf("## hello from fn1_after\n" );
 return OK;
}
set SO_FILE_NAME='Z_doc_loop_AA.so';
reponse
success
refresh dirty view;
reponse
success
--ACCEPT_DIFF_START loop sales(item_id, sales_qty, line_id) function fn1; hello from fn1_before hello from fn1 (thread_pos 0) : item_id=artA (ival 11), sales_qty=5.00 (ival 10), line_id=ID01 (ival 10) hello from fn1 (thread_pos 1) : item_id=artB (ival 12), sales_qty=6.00 (ival 11), line_id=ID02 (ival 11) hello from fn1 (thread_pos 0) : item_id=artB (ival 12), sales_qty=4.00 (ival 12), line_id=ID03 (ival 12) hello from fn1 (thread_pos 0) : item_id=artB (ival 12), sales_qty=7.00 (ival 13), line_id=ID04 (ival 13) hello from fn1 (thread_pos 0) : item_id=artA (ival 11), sales_qty=5.00 (ival 10), line_id=ID06 (ival 15) hello from fn1 (thread_pos 1) : item_id=artC (ival 14), sales_qty=8.00 (ival 14), line_id=ID05 (ival 14) hello from fn1 (thread_pos 0) : item_id=artA (ival 11), sales_qty=5.00 (ival 10), line_id=ID07 (ival 16) hello from fn1_after
LOOP_RESULT
DONE
--ACCEPT_DIFF_END./_SO_CODE/Z_doc_loop_BB.c
#include "./common.h"
int fn1_before(SB_VALS* read, SB_VALS* new) {
 read->thread_count = 2;
 int *c = malloc(sizeof(int));
 *c = 99;
 read->context = c;
 new->update_types[0] = 'T';
 return OK;
}
char txt_th0[20];
char txt_th1[20];
pthread_mutex_t my_mutex = PTHREAD_MUTEX_INITIALIZER;
int fn1(SB_VALS* read, SB_VALS* new) {
 int *c = read->context;
 char *txt = read->thread_pos == 0 ? txt_th0 : txt_th1;
 sprintf(txt, "NEW_ID_%d" , *c);
 *c = *c - 1;
 new->str_vals[0] = txt;
 return UPDATED;
}
int fn1_after(SB_VALS* read, SB_VALS* new) {
 printf("## hello from fn1_after\n" );
 free(read->context);
 return OK;
}
set SO_FILE_NAME='Z_doc_loop_BB.so';
reponse
success
refresh dirty view;
reponse
success
select item_id, sales_qty, line_id from v_sales cb sort(1,'asc');
item_id sales_qty line_id
# 8 ID05
artA 5 ID01
artA 5 ID06
artA 5 ID07
artB 6 ID02
artB 4 ID03
artB 7 ID04
loop sales(item_id, sales_qty) function fn1 update(line_id) where item_id='artA'; hello from fn1_after
LOOP_RESULT
DONE
refresh dirty view;
reponse
success
select item_id, sales_qty, line_id from v_sales cb sort(1,'asc');
item_id sales_qty line_id
# 8 ID05
artA 5 NEW_ID_99
artA 5 NEW_ID_98
artA 5 NEW_ID_97
artB 6 ID02
artB 4 ID03
artB 7 ID04
./_SO_CODE/Z_doc_loop_AB.c
#include "./common.h"
int fn1_before(SB_VALS* read, SB_VALS* new) {
 printf("## hello from fn1_before\n" );
 for(int i=0;i params_len;i++){
   printf("## fn1_before param %d is %s\n" ,i+1,read->params[i]);
 }
 read->thread_count = 2;
 return OK;
}
pthread_mutex_t my_mutex = PTHREAD_MUTEX_INITIALIZER;
int fn1(SB_VALS* read, SB_VALS* new) {
 return NOT_MODIFIED;
}
int fn1_after(SB_VALS* read, SB_VALS* new) {
 printf("## hello from fn1_after\n" );
 return OK;
}
set SO_FILE_NAME='Z_doc_loop_AB.so';
reponse
success
refresh dirty view;
reponse
success
loop sales(item_id, sales_qty, line_id) function fn1('val1','val2'); hello from fn1_before fn1_before param 1 is val1 fn1_before param 2 is val2 hello from fn1_after
LOOP_RESULT
DONE
--ACCEPT_DIFF_START./_SO_CODE/Z_doc_loop_without_mutex.c
#include "./common.h"
int fn1_before(SB_VALS* read, SB_VALS* new) {
 read->thread_count = 2;
 return OK;
}
pthread_mutex_t my_mutex = PTHREAD_MUTEX_INITIALIZER;
int fn1(SB_VALS* read, SB_VALS* new) {
 int r=rand()%1000000;
 printf("## fn1 A %p %d\n" ,&r,read->thread_pos);
 usleep(r);
 printf("## fn1 B\n" );
 return NOT_MODIFIED;
}
int fn1_after(SB_VALS* read, SB_VALS* new) {
 printf("## hello from fn1_after\n" );
 return OK;
}
set SO_FILE_NAME='Z_doc_loop_without_mutex.so';
reponse
success
refresh dirty view;
reponse
success
loop sales(item_id, sales_qty) function fn1; fn1 A 0x70000f8ded4c 0 fn1 A 0x70000f961d4c 1 fn1 B fn1 A 0x70000f8ded4c 0 fn1 B fn1 B fn1 A 0x70000f8ded4c 0 fn1 A 0x70000f961d4c 1 fn1 B fn1 A 0x70000f961d4c 1 fn1 B fn1 B fn1 A 0x70000f961d4c 1 fn1 B hello from fn1_after
LOOP_RESULT
DONE
./_SO_CODE/Z_doc_loop_with_mutex.c
#include "./common.h"
int fn1_before(SB_VALS* read, SB_VALS* new) {
 read->thread_count = 2;
 return OK;
}
pthread_mutex_t my_mutex = PTHREAD_MUTEX_INITIALIZER;
int fn1(SB_VALS* read, SB_VALS* new) {
 int r=rand()%1000000;
 pthread_mutex_lock(&my_mutex);
 printf("## fn1 A %p %d\n" ,&r,read->thread_pos);
 usleep(r);
 printf("## fn1 B\n" );
 pthread_mutex_unlock(&my_mutex);
 return NOT_MODIFIED;
}
int fn1_after(SB_VALS* read, SB_VALS* new) {
 printf("## hello from fn1_after\n" );
 return OK;
}
set SO_FILE_NAME='Z_doc_loop_with_mutex.so';
reponse
success
refresh dirty view;
reponse
success
loop sales(item_id, sales_qty) function fn1; fn1 A 0x70000f8ded4c 0 fn1 B fn1 A 0x70000f8ded4c 0 fn1 B fn1 A 0x70000f961d4c 1 fn1 B fn1 A 0x70000f8ded4c 0 fn1 B fn1 A 0x70000f8ded4c 0 fn1 B fn1 A 0x70000f961d4c 1 fn1 B fn1 A 0x70000f961d4c 1 fn1 B hello from fn1_after
LOOP_RESULT
DONE
--ACCEPT_DIFF_END select item_id,sales#customer_id from v_sales cb sort(1,'asc');
item_id sales#customer_id
# C1
artA C1
artA C1
artA C2
artB C2
artB C1
artB C2
create table customer_update( item_id t_item_id, sales_date t_date, new_customer_id t_customer_id, new_sales_qty number, item_id_new t_item_id );
reponse
success
insert into customer_update values('artA','?','C_artA',123.45,'??');
reponse
success
insert into customer_update values('artB','20200102','C_artA',123.45,'??');
reponse
success
--fn_update_idx1 loop customer_update(item_id,new_customer_id) function fn_build_idx1 where item_id='artA';
LOOP_RESULT
DONE
desc context;
context_name is_drop_yn
IDX1#item_id->new_customer_id n
loop sales(item_id) function fn_update_idx1('IDX1#item_id->new_customer_id') update(customer_id);
LOOP_RESULT
DONE
refresh dirty view;
reponse
success
select item_id,sales#customer_id from v_sales cb sort(1,'asc');
item_id sales#customer_id
# C1
artA C_artA
artA C_artA
artA C_artA
artB C2
artB C1
artB C2
--fn_update_idx1_num loop customer_update(item_id,new_sales_qty) function fn_build_idx1_num where item_id='artA';
LOOP_RESULT
DONE
desc context;
context_name is_drop_yn
IDX1#item_id->new_customer_id n
IDX1_NUM#item_id->new_sales_qty n
loop sales(item_id) function fn_update_idx1_num('IDX1_NUM#item_id->new_sales_qty') update(sales_qty);
LOOP_RESULT
DONE
refresh dirty view;
reponse
success
select item_id,sales_qty from v_sales cb sort(1,'asc');
item_id sales_qty
# 0
artA 123.450
artA 123.450
artA 123.450
artB 0
artB 0
artB 0
--fn_update_idx2 loop customer_update(item_id,sales_date,new_customer_id) function fn_build_idx2 where item_id='artB';
LOOP_RESULT
DONE
desc context;
context_name is_drop_yn
IDX1#item_id->new_customer_id n
IDX1_NUM#item_id->new_sales_qty n
IDX2#item_id->sales_date->new_customer_id n
loop sales(item_id,sales_date) function fn_update_idx2('IDX2#item_id->sales_date->new_customer_id') update(customer_id);
LOOP_RESULT
DONE
refresh dirty view;
reponse
success
select item_id,sales_date,sales#customer_id from v_sales cb sort(1,'asc');
item_id sales_date sales#customer_id
# 20200102 C1
artA 20191231 C_artA
artA 20191231 C_artA
artA 20191231 C_artA
artB 20200102 C_artA
artB 20191231 C1
artB 20200102 C_artA
--fn_update_idx2_num loop customer_update(item_id,sales_date,new_sales_qty) function fn_build_idx2_num where item_id='artB';
LOOP_RESULT
DONE
desc context;
context_name is_drop_yn
IDX1#item_id->new_customer_id n
IDX1_NUM#item_id->new_sales_qty n
IDX2#item_id->sales_date->new_customer_id n
IDX2_NUM#item_id->sales_date->new_sales_qty n
loop sales(item_id,sales_date) function fn_update_idx2_num('IDX2_NUM#item_id->sales_date->new_sales_qty') update(sales_qty);
LOOP_RESULT
DONE
refresh dirty view;
reponse
success
select item_id,sales_date,sales_qty from v_sales cb sort(1,'asc');
item_id sales_date sales_qty
# 20200102 0
artA 20191231 123.450
artA 20191231 123.450
artA 20191231 123.450
artB 20200102 123.450
artB 20191231 0
artB 20200102 123.450
--fn_copy_col create view v_customer_update as select * from customer_update;
reponse
success
refresh dirty view;
reponse
success
select item_id,item_id_new from v_customer_update;
item_id item_id_new
artA ??
artB ??
loop customer_update(item_id) function fn_copy_col update(item_id_new);
LOOP_RESULT
DONE
refresh dirty view;
reponse
success
select item_id,item_id_new from v_customer_update;
item_id item_id_new
artA artA
artB artB
--fn_concat create table item_infos( item_id t_item_id, info1 text, info2 text);
reponse
success
create view v_item_infos as select * from item_infos;
reponse
success
insert into item_infos values ('artA','info1 A','info2 A')('artB','info1 B','info2 B');
reponse
success
refresh dirty view;
reponse
success
create table item_infos( item_id t_item_id, info1 text, info2 text, info3 text);
reponse
success
refresh dirty view;
reponse
success
select * from v_item_infos;
item_id info1 info2 info3
artA info1 A info2 A NO_DATA
artB info1 B info2 B NO_DATA
continue_on_error(148);
reponse
success
loop item_infos(info1,item_id,info2) function fn_concat('/') update(info3) where info3='NO_DATA';
LOOP_RESULT
DONE
refresh dirty view;
reponse
success
select * from v_item_infos;
item_id info1 info2 info3
artA info1 A info2 A info1 A/artA/info2 A
artB info1 B info2 B info1 B/artB/info2 B
loop sales(item_id, sales_qty) function fn_skip;
reponse
loop skip
-- ########################### -- RUNNING shutdown.sql shutdown;