在SQLite视图中复杂选择

时间:2017-04-09 22:42:59

标签: sqlite view

我有两个表,FileSystemRights保存给定NTFS文件系统扫描的访问位掩码,FileSystemRights ================ Id Name Value -- ---- ----- 1 None 0 2 ListDirectory 1 3 ReadData 1 4 WriteData 2 5 CreateFiles 2 6 CreateDirectories 4 7 AppendData 4 8 ReadExtendedAttributes 8 9 WriteExtendedAttributes 16 10 ExecuteFile 32 11 Traverse 32 12 DeleteSubdirectoriesAndFiles 64 13 ReadAttributes 128 14 WriteAttributes 256 15 Write 278 16 Delete 65536 17 ReadPermissions 131072 18 Read 131209 19 ReadAndExecute 131241 20 Modify 197055 21 ChangePermissions 262144 22 TakeOwnership 524288 23 Synchronize 1048576 24 FullControl 2032127 25 GenericAll 268435456 26 GenericExecute 536870912 27 GenericWrite 1073741824 28 GenericRead 2147483648 Security ======== Id FileSystemRights IdentityReference -- ---------------- ----------------- 20 2032127 BUILTIN\Administrators 21 2032127 BUILTIN\Administrators 22 2032127 NT AUTHORITY\SYSTEM 23 268435456 CREATOR OWNER 24 1179817 BUILTIN\Users 25 4 BUILTIN\Users 26 2 BUILTIN\Users MyView ====== SELECT s.Id AS SecurityId, f.Name FROM Security s JOIN FileSystemRights f ON CASE f.Value WHEN 0 THEN s.FileSystemRights = f.Value ELSE (s.FileSystemRights & f.Value) == f.Value END ORDER BY s.Id, f.Name; 等同于众所周知的位掩码的字符串表示。我需要创建一个视图,它暴露给定位掩码的预期(不仅仅是正确的)字符串表示。问题是几个枚举值复合并包含较低值的组合,因此理想的想法是不重复隐含值。

例如,值1179817(Security.Id = 24)应仅报告 ReadAndExecute Synchronize ,不包括 ExecuteFile ListDirectory 读取 ReadAttributes ReadData ReadExtendedAttributes ReadPermissions Traverse ,因为它们都是 ReadAndExecute 的一部分(例如 ReadAndExecute & Read == 读取)。将它们全部展示显然是正确的,但用户只希望看到非隐式值。

我在SQL的限制范围内迷失了,以产生一个行为类似的联接,而没有一些糟糕的嵌套情况,这将是一个噩梦。

是否存在更好的编程方法?

const https = require('https');
const fs = require('fs');

var ssl = {
    key:  fs.readFileSync('/etc/letsencrypt/live/example.com/privkey.pem'),
    cert: fs.readFileSync('/etc/letsencrypt/live/example.com/cert.pem')
};

var server = https.createServer(ssl, httpRequestsHandler).listen(_port_, function() {
    process.setgid('www-data');
    process.setuid('user1');
});

1 个答案:

答案 0 :(得分:0)

将名称的实际值添加到查询中。 然后围绕它包装另一个查询,以过滤掉作为另一个值的子集的相同条目的值:

WITH AllValues(SecurityId, Name, Value) AS (
    SELECT s.Id,
           f.Name,
           f.Value
     FROM Security s
     JOIN FileSystemRights f
          ON CASE f.Value
                 WHEN 0 THEN s.FileSystemRights = f.Value
                 ELSE (s.FileSystemRights & f.Value) == f.Value
          END
)
SELECT SecurityId,
       Name
  FROM AllValues
 WHERE NOT EXISTS (SELECT *
                     FROM AllValues AS AV2
                    WHERE  AV2.SecurityId = AllValues.SecurityId
                      AND (AV2.Value & AllValues.Value) != 0
                      AND  AV2.Value > AllValues.Value
                  )
 ORDER BY 1, 2;