如何从SQL where子句创建JavaScript函数,以将其作为谓词传递给JavaScript数组的过滤器函数?

问题描述 投票:2回答:2

场景:

我有一个基于JavaScript的应用程序,它使用web sql数据库存储其数据

我已经开发了一个自定义实体集。

它具有一个可以接受包含sql查询的字符串的过滤器方法。

例如:People.filter(“ Name ='Test'and ...”)

我的实体集的行为具有两种模式,InMemoryNonInMemory

InMemory:filter方法将过滤内存中的源数组,而无需往返于db。

[NonInMemory:filter方法将使用新的filter再次从db中读取源。

为了使开发更容易,我想让开发人员透明地区别这些行为。

而且我想使我的过滤器方法在两种模式下(InMemoryNonInMemory都使用相同的代码。

我有成千上万个这样的过滤器,它们在.net和sql lite中都可以正常工作。

而且我想将它们尽可能轻松地迁移到JavaScript和Web sql。

我的问题:

有没有可以处理这种情况的JavaScript库?

哪个接受Sql查询并创建JavaScript函数作为我的谓词?

谢谢

javascript sql html5 web-sql jaydata
2个回答
2
投票

我实际上正在为JavaScript使用基于SQL的项目,该项目对where子句使用了生成的函数。其中一部分是在可行的情况下(AND> &&等)将SQL语法差异转换为JS,另一部分是为子句提供SQL函数。兼容性,只是为了允许最有用的sql功能和语法在javascript中工作。下面的where函数制作例程不是解析器或复杂的AST构建器,而只是一个半幼稚但又足够快速的字​​符串转换器。

它现在支持大量的where-ish SQL,并且应该很容易扩展到您自己;这里没有很多黑魔法。

生成的函数非常适合对对象数组进行filter()。

这里是项目相关部分的端口,该端口很大,这里是子句构建器:

// cache RegExps pseudo-globally for much better perf in query routine in webkit:
var rxOr = /\sOR\s/g,
    rxAnd = /\sAND\s/g,
    rxIn = /\sIN\(([\w\.\,\s]+)\)/g,
    rxSep = /\s*\,\s*/,
    rxDoubleEqual = /([^=])=([^=])/g,
    asRx = /\s+AS\s+/,
    eqRx = /(\w+)=/;
var fCache = {}; //

var SQLREPS = [
    [/([^=])=([^=])/g, "$1==$2"],
    [/\sAND\s/g, ") && ("],
    [/\sOR\s/g, ") || ("],
    [/\bUCASE\(/g, " ''.toUpperCase.call("],
    [/\bLCASE\(/g, " ''.toLowerCase.call("],
    [/\bUPPER\(/g, " ''.toUpperCase.call("],
    [/\bLOWER\(/g, " ''.toLowerCase.call("],
    [/\bINSTR\(/g, " 1+''.indexOf.call("],
    [/\bCONCAT\(/g, " ''.concat("],
    [/\bLTRIM\(/g, " ''.trimLeft.call("],
    [/\bRTRIM\(/g, " ''.trimRight.call("],
    [/\bTRIM\(/g, " ''.trim.call("],
    [/\bQUOTE\(/g, " JSON.stringify("],
    [/\bSPACE\(/g, " ' '.repeat("],
    [/\bREPLACE\(/g, " (function(s,n,r){return s.split(n).join('r');})("],
    [/\bRPAD\(/g, " (function(s,n,p){return (s+p.repeat(n)).slice(0,n)})("],
    [/\bASCII\(/g, " ''.charCodeAt.call("],
    [/\bBIN\(/g, " ''.charCodeAt.call("],
    [/\bLENGTH\(/g, " [].push.call("],
    [/\bSUBSTRING_INDEX\(/g, "(function(s,n,p){s=s.split(n);s=p>0?s.slice(0,p):s.slice(p);return s.join(n);})("],
    [/\bSUBSTRING\(/g, '(function(a,b,c){return b=[b>0?b-1:b],"".substr.apply(a,arguments.length==3?b.concat(c):b)})('],
    [/\bSUBSTR\(/g, '(function(a,b,c){return b=[b>0?b-1:b],"".substr.apply(a,arguments.length==3?b.concat(c):b)})('],
    [/\bMID\(/g, '(function(a,b,c){return b=[b>0?b-1:b],"".substr.apply(a,arguments.length==3?b.concat(c):b)})('],
    [/\bLOCATE\(/g, " (function(t,s,n){return 1+s.indexOf(t,n)})("],
    [/\bPOSITION\(/g, " (function(t,s,n){return 1+s.indexOf(t,n)})("],
    [/\bFIND_IN_SET\(/g, "(function(s,l){return l.split(',').indexOf(s)+1})("],
    [/\bREVERSE\(/g, " (function(s){return s.split('').reverse().join('');})("],
    [/\bLEFT\(/g, "(function(s,n){return s.slice(0,n)})("],
    [/ NOT /g, " ! "]
];



function rewrite(s) {

    var os = s;

    SQLREPS.forEach(function(a) {
        s = s.replace(a[0], a[1]);
    });

    s = s.replace(rxIn, function repIn(j, a) {
        return " in { " + a.split(rxSep).map(function mapIn(a) {
            return JSON.stringify(a)
        }).join(":1,") + ":1} ";
        return a;
    });

    return s;
}

function Function2(a, b, blnNoRewrite) {
    var c;
    if (!b.match(/return/)) {
        b = "return " + b;
    }
    if (c = fCache[a + b]) {
        return c;
    }
    return fCache[a + b] = Function(a, blnNoRewrite ? b : rewrite(b));
}


function sql(term) {
    return Function2("me,index,all", "return (" + rewrite(term) + ");");
}




//example strings and resulting functions:
sql(" UPPER(  me.gender  ) =='F' "); // function anonymous(me,index,all){return(''.toUpperCase.call(me.gender)=='F');}

sql(" me.gender IN(M,F,O)"); //  function anonymous(me,index,all){return(me.gender in{"M":1,"F":1,"O":1});}

sql("(me.name> 'j' AND me.age > 50) &&  NOT me.inActive "); // function anonymous(me,index,all){return((me.name>'j')&&(me.age>50)&&!me.inActive);}

大多数的js sql库在WHERE功能上有些somewhat弱,并且很难扩展,希望您和其他人可以从中得到一些使用或启发。我认为它是作者的公共领域。


0
投票

似乎OP只是想使用SQL query子句来where对象的JavaScript数组,无论他是否获得过滤器功能。

AlaSQL正是这样做的。但是,它为您的应用程序捆绑包can be too big

软件包的维护者还注意到(截至2019年12月):

AlaSQL项目还很年轻,仍处于活跃的开发阶段,因此可能会有错误。

© www.soinside.com 2019 - 2024. All rights reserved.