anchor.diff:          roles MySQL wildcards ("%" and "_") can be used to specify objects
           to be granted on, including databases, tables and columns names. A
           script runs periodically to find all matching objects and grants on
  -        them. Objects are denoted as "schema[.table[.column]]".
  +        them. Objects are denoted as "database[.table[.column]]".
         '';
         example = {
           top_role = [ "basic_role" ];
  
positive.code:     done
    '';
  
    addRoles = ''
      ${concatMapStrings (r: "CREATE ROLE IF NOT EXISTS '${r}';\n") (attrNames roles)}
  
      ${concatStrings
         (mapAttrsToList (role: subroles: ''
          ${concatMapStringsSep "\n" (r: "GRANT '${r}' TO '${role}';") subroles}
          '') topRoles)
      }
    '';
  
    revokeRoles = ''
      ${concatMapAttrs (role: subroles: ''
        SELECT CONCAT('REVOKE \''', role, '\' FROM \''', user, '\';') FROM roles_mapping
          WHERE user = '${role}'
          AND role NOT IN (${sqlList subroles});
      '') topRoles
      }
  
      SELECT CONCAT('DROP ROLE \''', user, '\';') FROM user WHERE is_role='Y'
        ${optionalString (allRoles != []) "AND user NOT IN (${sqlList allRoles})"}
      ;
    '';
  
    roleType =
  
negative.code: { config, lib, pkgs, ... }:
  let
  
    inherit (builtins)
      elemAt filter isAttrs isList length ;
  
    inherit (lib)
      attrNames concatMapStrings concatMapStringsSep concatStrings
      concatStringsSep filterAttrs flatten mapAttrsToList mkIf mkOption mkOrder
      optionalString replaceStrings splitString ;
  
    inherit (lib.types)
      attrsOf either listOf str submodule ;
  
    cfg = config.nixsap.apps.mariadb;
  