-- Clear previous proc DROP PROCEDURE IF EXISTS p_shop_user_eval; DROP PROCEDURE IF EXISTS p_shop_calc_user; DELIMITER // CREATE PROCEDURE p_shop_calc_user ( IN a_guid BINARY(36) , IN a_ids_user TEXT , IN a_get_inactive_user BIT , IN a_ids_permission VARCHAR(4000) , IN a_ids_access_level VARCHAR(4000) , IN a_ids_product TEXT , IN a_debug BIT ) BEGIN -- Variable declaration DECLARE v_has_filter_permission BIT; DECLARE v_has_filter_user BIT; DECLARE v_has_filter_access_level BIT; -- DECLARE v_has_filter_permutation BIT; DECLARE v_has_filter_product BIT; DECLARE v_id_permission_product INT; DECLARE v_id_permission INT; -- DECLARE v_ids_product VARCHAR(500); DECLARE v_id_access_level_view INT; # DECLARE v_id_access_level_product_required INT; DECLARE v_priority_access_level_view INT; DECLARE v_priority_access_level_edit INT; DECLARE v_priority_access_level_admin INT; DECLARE v_id_access_level INT; DECLARE v_priority_access_level INT; DECLARE v_time_start TIMESTAMP(6); DECLARE v_ids_row_delete VARCHAR(500); DECLARE v_code_type_error_bad_data VARCHAR(200); DECLARE v_id_type_error_bad_data INT; DECLARE v_code_error_permission VARCHAR(200); DECLARE v_id_permission_required INT; SET v_time_start := CURRENT_TIMESTAMP(6); SET v_code_type_error_bad_data := (SELECT code FROM Shop_Msg_Error_Type WHERE code = 'BAD_DATA'); SET v_id_type_error_bad_data := (SELECT id_type FROM Shop_Msg_Error_Type WHERE code = v_code_type_error_bad_data); SET v_code_error_permission := (SELECT code FROM Shop_Msg_Error_Type WHERE id_type = 2); CALL partsltd_prod.p_validate_guid ( a_guid ); SET a_ids_user := TRIM(IFNULL(a_ids_user, '')); SET a_get_inactive_user := IFNULL(a_get_inactive_user, 0); SET a_ids_permission := TRIM(IFNULL(a_ids_permission, '')); SET a_ids_access_level := TRIM(IFNULL(a_ids_access_level, '')); SET a_ids_product := TRIM(IFNULL(a_ids_product, '')); SET a_debug := IFNULL(a_debug, 0); IF a_debug = 1 THEN SELECT a_guid , a_ids_user , a_get_inactive_user , a_ids_permission , a_ids_access_level , a_ids_product , a_debug ; END IF; -- Clear previous proc results DROP TABLE IF EXISTS tmp_Calc_User; DROP TABLE IF EXISTS tmp_User_Calc_User; DROP TABLE IF EXISTS tmp_Product_Calc_User; DROP TABLE IF EXISTS tmp_Split; -- Permanent Table CREATE TEMPORARY TABLE tmp_Calc_User ( id_row INT PRIMARY KEY AUTO_INCREMENT NOT NULL, id_user INT NULL, id_permission_required INT NOT NULL, priority_access_level_required INT NOT NULL, id_product INT NULL, is_super_user BIT NULL, priority_access_level_user INT NULL, can_view BIT, can_edit BIT, can_admin BIT ); CREATE TEMPORARY TABLE tmp_Product_Calc_User ( -- id_row INT PRIMARY KEY AUTO_INCREMENT NOT NULL id_product INT NULL , id_access_level_required INT NOT NULL , priority_access_level_required INT NOT NULL -- guid BINARY(36) NOT NULL, -- rank_product INT NOT NULL ); CREATE TEMPORARY TABLE tmp_User_Calc_User ( id_user INT NOT NULL , is_super_user BIT NOT NULL -- , id_access_level INT , priority_access_level INT NOT NULL ); CREATE TEMPORARY TABLE IF NOT EXISTS tmp_Msg_Error ( display_order INT NOT NULL PRIMARY KEY AUTO_INCREMENT, -- guid BINARY(36) NOT NULL, id_type INT NULL, code VARCHAR(50) NOT NULL, msg VARCHAR(4000) NOT NULL ); CREATE TEMPORARY TABLE IF NOT EXISTS tmp_Split ( substring VARCHAR(4000) NOT NULL , as_int INT NULL ); DELETE FROM tmp_Split; SET v_has_filter_user = CASE WHEN a_ids_user = '' THEN 0 ELSE 1 END; SET a_ids_permission = REPLACE(a_ids_permission, '|', ','); SET v_has_filter_permission = CASE WHEN a_ids_permission = '' THEN 0 ELSE 1 END; SET a_ids_access_level = REPLACE(a_ids_access_level, '|', ','); SET v_has_filter_access_level = CASE WHEN a_ids_access_level = '' THEN 0 ELSE 1 END; /* SET a_ids_permutation = REPLACE(a_ids_permutation, '|', ','); SET v_has_filter_permutation = CASE WHEN a_ids_permutation = '' THEN 0 ELSE 1 END; */ SET a_ids_product = REPLACE(a_ids_product, '|', ','); SET v_has_filter_product = CASE WHEN a_ids_product = '' THEN 0 ELSE 1 END; SET v_id_access_level_view = (SELECT id_access_level FROM partsltd_prod.Shop_Access_Level WHERE code = 'VIEW' LIMIT 1); SET v_priority_access_level_view = (SELECT priority FROM partsltd_prod.Shop_Access_Level WHERE id_access_level = v_id_access_level_view); SET v_priority_access_level_edit = (SELECT priority FROM partsltd_prod.Shop_Access_Level WHERE code = 'EDIT' LIMIT 1); SET v_priority_access_level_admin = (SELECT priority FROM partsltd_prod.Shop_Access_Level WHERE code = 'ADMIN' LIMIT 1); IF a_debug = 1 THEN SELECT v_priority_access_level_view , v_priority_access_level_edit , v_priority_access_level_admin ; END IF; # Access levels IF v_has_filter_access_level THEN CALL partsltd_prod.p_split(a_guid, a_ids_access_level, ',', a_debug); INSERT INTO tmp_Split ( substring , as_int ) SELECT substring , CONVERT(substring, DECIMAL(10,0)) -- AS as_int FROM Split_Temp WHERE 1=1 AND GUID = a_guid AND NOT ISNULL(substring) AND substring != '' ; CALL partsltd_prod.p_clear_split_temp( a_guid ); # Invalid IDs IF EXISTS ( SELECT t_S.substring FROM tmp_Split t_S LEFT JOIN partsltd_prod.Shop_Access_Level AL ON t_S.as_int = AL.id_access_level WHERE ISNULL(t_S.as_int) OR ISNULL(AL.id_access_level) OR AL.active = 0 ) THEN INSERT INTO tmp_Msg_Error ( -- guid, id_type, code, msg ) SELECT -- a_guid, v_id_type_error_bad_data, v_code_type_error_bad_data, CONCAT('Invalid or inactive access level IDs: ', GROUP_CONCAT(t_S.substring SEPARATOR ', ')) FROM tmp_Split t_S LEFT JOIN partsltd_prod.Shop_Access_Level AL ON t_S.as_int = AL.id_access_level WHERE ISNULL(t_S.as_int) OR ISNULL(AL.id_access_level) OR AL.active = 0 ; ELSE IF v_has_filter_access_level THEN SET v_id_access_level := ( SELECT AL.id_access_level FROM tmp_Split t_S INNER JOIN partsltd_prod.Shop_Access_Level AL ON t_S.as_int = AL.id_access_level AND AL.active ORDER BY AL.priority ASC LIMIT 1 ); ELSE SET v_id_access_level = v_id_access_level_view; END IF; SET v_priority_access_level := (SELECT priority FROM partsltd_prod.Shop_Access_Level WHERE id_access_level = v_id_access_level LIMIT 1); END IF; END IF; DELETE FROM tmp_Split; -- Permission IDs IF v_has_filter_permission THEN CALL partsltd_prod.p_split(a_guid, a_ids_permission, ',', a_debug); INSERT INTO tmp_Split ( substring , as_int ) SELECT substring , CONVERT(substring, DECIMAL(10,0)) AS as_int FROM Split_Temp WHERE 1=1 AND GUID = a_guid AND NOT ISNULL(substring) AND substring != '' ; CALL partsltd_prod.p_clear_split_temp( a_guid ); # Invalid or inactive IF EXISTS (SELECT PERM.id_permission FROM tmp_Split t_S LEFT JOIN partsltd_prod.Shop_Permission PERM ON t_S.as_int = PERM.id_permission WHERE ISNULL(t_S.as_int) OR ISNULL(PERM.id_permission) OR PERM.active = 0) THEN INSERT INTO tmp_Msg_Error ( -- guid, id_type, code, msg ) SELECT -- a_guid, v_id_type_error_bad_data, v_code_type_error_bad_data, CONCAT('Invalid or inactive permission IDs: ', IFNULL(GROUP_CONCAT(t_S.substring SEPARATOR ', '), 'NULL')) FROM tmp_Split t_S LEFT JOIN partsltd_prod.Shop_Permission PERM ON t_S.as_int = PERM.id_permission WHERE ISNULL(t_S.as_int) OR ISNULL(PERM.id_permission) OR PERM.active = 0 ; ELSE SET v_id_permission_required := ( SELECT PERM.id_permission FROM partsltd_prod.Shop_Permission PERM INNER JOIN partsltd_prod.Shop_Access_Level AL ON PERM.id_access_level_required = AL.id_access_level ORDER BY AL.priority ASC LIMIT 1 ); END IF; END IF; DELETE FROM tmp_Split; # Users CALL partsltd_prod.p_split(a_guid, a_ids_user, ',', a_debug); INSERT INTO tmp_Split ( substring , as_int ) SELECT substring , CONVERT(substring, DECIMAL(10,0)) AS as_int FROM Split_Temp WHERE 1=1 AND GUID = a_guid AND NOT ISNULL(substring) AND substring != '' ; CALL partsltd_prod.p_clear_split_temp( a_guid ); # Invalid or inactive IF EXISTS (SELECT U.id_user FROM tmp_Split t_S LEFT JOIN partsltd_prod.Shop_User U ON t_S.as_int = U.id_user WHERE ISNULL(t_S.as_int) OR ISNULL(U.id_user) OR (a_get_inactive_user = 0 AND U.active = 0)) THEN INSERT INTO tmp_Msg_Error ( -- guid, id_type, code, msg ) SELECT -- a_guid, v_id_type_error_bad_data, v_code_type_error_bad_data, CONCAT('Invalid or inactive user IDs: ', IFNULL(GROUP_CONCAT(t_S.substring SEPARATOR ', '), 'NULL')) FROM tmp_Split t_S LEFT JOIN partsltd_prod.Shop_User U ON t_S.as_int = U.id_user WHERE ISNULL(t_S.as_int) OR ISNULL(U.id_user) OR ( a_get_inactive_user = 0 AND U.active = 0 ) ; ELSE /* SET a_ids_user = ( SELECT U.id_user FROM tmp_Split t_S INNER JOIN partsltd_prod.Shop_User U ON t_S.as_int = U.id_user ); SET v_has_filter_user = ISNULL(a_ids_user); */ IF NOT EXISTS (SELECT * FROM tmp_Split) THEN INSERT INTO tmp_Split (substring, as_int) VALUES ( '', NULL ); END IF; IF a_debug = 1 THEN SELECT * FROM tmp_Split; END IF; INSERT INTO tmp_User_Calc_User ( id_user -- , id_access_level , is_super_user , priority_access_level ) SELECT U.id_user , U.is_super_user -- , IFNULL(AL_U.id_access_level, v_id_access_level_view) AS id_access_level , IFNULL(MIN(AL_U.priority), v_priority_access_level_view) AS priority_access_level FROM tmp_Split t_S INNER JOIN partsltd_prod.Shop_User U ON t_S.as_int = U.id_user LEFT JOIN partsltd_prod.Shop_User_Role_Link URL ON U.id_user = URL.id_user AND URL.active LEFT JOIN partsltd_prod.Shop_Role_Permission_Link RPL ON URL.id_role = RPL.id_role AND RPL.active LEFT JOIN partsltd_prod.Shop_Access_Level AL_U ON RPL.id_access_level = AL_U.id_access_level AND AL_U.active GROUP BY U.id_user ; INSERT INTO tmp_Calc_User ( id_user , id_permission_required , priority_access_level_required , id_product , is_super_user , priority_access_level_user ) SELECT t_UCU.id_user , v_id_permission_required , v_priority_access_level AS priority_access_level_required , NULL , t_UCU.priority_access_level AS priority_access_level_user , t_UCU.is_super_user AS is_super_user FROM tmp_User_Calc_User t_UCU ; /* INSERT INTO tmp_Calc_User ( id_user , id_permission_required , priority_access_level_required -- , id_product , priority_access_level_user , is_super_user ) SELECT U.id_user , v_id_permission_required , v_priority_access_level AS priority_access_level_required -- , t_P.id_product , CASE WHEN MIN(IFNULL(AL_U.priority, 0)) = 0 THEN v_priority_access_level_view ELSE MIN(IFNULL(AL_U.priority, 0)) END AS priority_access_level_user , IFNULL(U.is_super_user, 0) AS is_super_user FROM tmp_Split t_S LEFT JOIN partsltd_prod.Shop_User U ON t_S.as_int = U.id_user AND U.active LEFT JOIN partsltd_prod.Shop_User_Role_Link URL ON U.id_user = URL.id_user AND URL.active LEFT JOIN partsltd_prod.Shop_Role_Permission_Link RPL ON URL.id_role = RPL.id_role AND RPL.active LEFT JOIN partsltd_prod.Shop_Access_Level AL_U ON RPL.id_access_level = AL_U.id_access_level AND AL_U.active * CROSS JOIN tmp_Product_Calc_User t_P LEFT JOIN partsltd_prod.Shop_Access_Level AL_P ON t_P.id_access_level_required = AL_P.id_access_level AND AL_P.active * GROUP BY t_S.as_int, U.id_user ; */ # SET v_has_filter_user = EXISTS ( SELECT * FROM tmp_User_Calc_User LIMIT 1 ); END IF; DELETE FROM tmp_Split; # Products IF v_has_filter_product = 1 THEN CALL partsltd_prod.p_split(a_guid, a_ids_product, ',', a_debug); INSERT INTO tmp_Split ( substring , as_int ) SELECT substring , CONVERT(substring, DECIMAL(10,0)) AS as_int FROM Split_Temp WHERE 1=1 AND GUID = a_guid AND NOT ISNULL(substring) AND substring != '' ; CALL partsltd_prod.p_clear_split_temp( a_guid ); # Invalid product IDs IF EXISTS (SELECT * FROM tmp_Split t_S LEFT JOIN partsltd_prod.Shop_Product P ON t_S.as_int = P.id_product WHERE ISNULL(t_S.as_int) OR ISNULL(P.id_product)) THEN INSERT INTO tmp_Msg_Error ( -- guid, id_type, code, msg ) SELECT -- a_guid, v_id_type_error_bad_data, v_code_type_error_bad_data, CONCAT('Invalid Product IDs: ', IFNULL(GROUP_CONCAT(t_S.substring SEPARATOR ', '), 'NULL')) FROM tmp_Split t_S LEFT JOIN partsltd_prod.Shop_Product P ON t_S.as_int = P.id_product WHERE ISNULL(t_S.as_int) OR ISNULL(P.id_product) OR P.active = 0 ; END IF; IF (EXISTS (SELECT * FROM tmp_Split)) THEN INSERT INTO tmp_Product_Calc_User ( id_product, -- id_permutation, id_access_level_required, priority_access_level_required ) SELECT DISTINCT P.id_product, -- PP.id_permutation, CASE WHEN AL_P.priority < AL_C.priority THEN AL_P.id_access_level ELSE AL_C.id_access_level END AS id_access_level_required, CASE WHEN AL_P.priority < AL_C.priority THEN AL_P.priority ELSE AL_C.priority END AS priority_access_level_required FROM tmp_Split t_S INNER JOIN partsltd_prod.Shop_Product P ON t_S.as_int = P.id_product # Shop_Product_Permutation PP INNER JOIN partsltd_prod.Shop_Access_Level AL_P ON P.id_access_level_required = AL_P.id_access_level AND AL_P.active INNER JOIN partsltd_prod.Shop_Product_Category C ON P.id_category = C.id_category INNER JOIN partsltd_prod.Shop_Access_Level AL_C ON C.id_access_level_required = AL_C.id_access_level AND AL_C.active ; SET v_has_filter_product = EXISTS (SELECT * FROM tmp_Product_Calc_User); /* UPDATE tmp_Product_Calc_User t_P INNER JOIN partsltd_prod.Shop_Product P ON t_P.id_product = P.id_product INNER JOIN partsltd_prod.Shop_Product_Category PC ON P.id_category = PC.id_category INNER JOIN partsltd_prod.Shop_Access_Level AL ON PC.id_access_level_required = AL.id_access_level SET t_P.id_access_level_required = CASE WHEN t_P.priority_access_level_required <= AL.priority THEN t_P.id_access_level_required ELSE AL.id_access_level END , t_P.priority_access_level_required = LEAST(t_P.priority_access_level_required, AL.priority) ; */ ELSE INSERT INTO tmp_Product_Calc_User ( id_product, -- id_permutation, id_access_level_required, priority_access_level_required ) VALUES ( NULL , v_id_access_level_view , v_priority_access_level_view ); END IF; END IF; DELETE FROM tmp_Split; INSERT INTO tmp_Calc_User ( id_user , id_permission_required , priority_access_level_required , id_product , is_super_user , priority_access_level_user ) SELECT t_U.id_user , v_id_permission_required , CASE WHEN AL.priority < v_priority_access_level THEN AL.priority ELSE v_priority_access_level END AS priority_access_level_required , t_P.id_product , t_U.priority_access_level AS priority_access_level_user , t_U.is_super_user AS is_super_user FROM tmp_User_Calc_User t_U CROSS JOIN tmp_Product_Calc_User t_P LEFT JOIN partsltd_prod.Shop_Access_Level AL ON t_P.id_access_level_required = AL.id_access_level ; -- Calculated fields UPDATE tmp_Calc_User t_CU SET t_CU.can_view = t_CU.is_super_user = 1 OR (t_CU.priority_access_level_user <= v_priority_access_level_view AND t_CU.priority_access_level_user <= t_CU.priority_access_level_required) , t_CU.can_edit = t_CU.is_super_user = 1 OR (t_CU.priority_access_level_user <= v_priority_access_level_edit AND t_CU.priority_access_level_user <= t_CU.priority_access_level_required) , t_CU.can_admin = t_CU.is_super_user = 1 OR (t_CU.priority_access_level_user <= v_priority_access_level_admin AND t_CU.priority_access_level_user <= t_CU.priority_access_level_required) ; -- Export data to staging table IF NOT EXISTS (SELECT * FROM tmp_Msg_Error) THEN START TRANSACTION; INSERT INTO partsltd_prod.Shop_Calc_User_Temp ( guid , id_user , id_permission_required , priority_access_level_required , id_product , is_super_user , priority_access_level_user , can_view , can_edit , can_admin ) SELECT a_guid , id_user , id_permission_required , priority_access_level_required , id_product , is_super_user , priority_access_level_user , can_view , can_edit , can_admin FROM tmp_Calc_User ; COMMIT; END IF; IF a_debug = 1 THEN SELECT * FROM tmp_Msg_Error; SELECT * FROM tmp_Calc_User; SELECT * FROM tmp_User_Calc_User; SELECT * FROM tmp_Product_Calc_User; SELECT * FROM partsltd_prod.Shop_Calc_User_Temp WHERE GUID = a_guid; CALL partsltd_prod.p_shop_clear_calc_user ( a_guid, a_debug ); END IF; -- Clean up DROP TABLE IF EXISTS tmp_Calc_User; DROP TABLE IF EXISTS tmp_User_Calc_User; DROP TABLE IF EXISTS tmp_Product_Calc_User; # Don't destroy common tables in nested Stored Procedures! -- DROP TABLE IF EXISTS tmp_Split; DELETE FROM tmp_Split; IF a_debug = 1 THEN CALL partsltd_prod.p_debug_timing_reporting( v_time_start ); END IF; END // DELIMITER ;; /* CALL partsltd_prod.p_shop_calc_user ( 'chips ' , 1 , 0 , '2' , '1' , '1,2,3,4,5' , 0 ); SELECT * FROM partsltd_prod.Shop_Calc_User_Temp WHERE GUID = 'chips '; DELETE FROM partsltd_prod.Shop_Calc_User_Temp WHERE GUID = 'chips '; -- SELECT * FROM partsltd_prod.Shop_Calc_User_Temp; SELECT * FROM partsltd_prod.Shop_Calc_User_Temp WHERE GUID = 'chips '; CALL partsltd_prod.p_shop_clear_calc_user ( 'chips ', 0 ); -- SELECT * FROM partsltd_prod.Shop_Calc_User_Temp; DROP TABLE IF EXISTS tmp_Msg_Error; CALL p_shop_calc_user( 'chips ' , 1 , FALSE -- a_get_inactive_users , 2 , 1 , '' -- a_ids_product , 0 -- a_debug ); SELECT * FROM partsltd_prod.Shop_Calc_User_Temp WHERE GUID = 'chips '; CALL partsltd_prod.p_shop_clear_calc_user ( 'chips ', 0 ); DROP TABLE IF EXISTS tmp_Msg_Error; SELECT * FROM partsltd_prod.shop_user_role_link; SELECT * FROM partsltd_prod.shop_role_permission_link; */