fcf.module({
  name: "fcf:tests/NFSQL/Parser.select.test.js",
  dependencies: ["fcf:NTest/uniTest.js", "fcf:NFSQL/NDetails/SingleParser.js"],
  module: function(uniTest, Parser) {
    var NTests = fcf.prepareObject(fcf, "NFSQL.NTests");

    uniTest.add("001 FSQL", "Parser (SELECT: simple fields)", function(a_tester) {
      var parser = new Parser();

      var data = parser.parse("SELECT f1 as alias FROM proj", [1]);
      uniTest.equalObject(
        data,
        { type: 'select', from: 'proj', join: [],
          fields: [ { field: 'f1', as: 'alias' } ], where: [],
          order: [], group: [], limit: undefined, offset: undefined },
        "");

      var data = parser.parse("SELECT  f1  as  alias  FROM  proj ", [1]);
      uniTest.equalObject(
        data,
        { type: 'select', from: 'proj', join: [],
          fields: [ { field: 'f1', as: 'alias' } ], where: [],
          order: [], group: [], limit: undefined, offset: undefined },
        "");

      var data = parser.parse("SELECT f1 as alias,f2  FROM proj ", [1]);
      uniTest.equalObject(
        data,
        { type: 'select', from: 'proj', join: [],
          fields: [ { field: 'f1', as: 'alias' }, { field: 'f2' } ], where: [],
          order: [], group: [], limit: undefined, offset: undefined },
        "");

      var data = parser.parse("SELECT f1 as alias, f2  FROM proj ", [1]);
      uniTest.equalObject(
        data,
        { type: 'select', from: 'proj', join: [],
          fields: [ { field: 'f1', as: 'alias' }, { field: 'f2' } ], where: [],
          order: [], group: [], limit: undefined, offset: undefined },
        "");

      var data = parser.parse("SELECT f1 as alias, f2 as alias2  FROM proj ", [1]);
      uniTest.equalObject(
        data,
        { type: 'select', from: 'proj', join: [],
          fields: [ { field: 'f1', as: 'alias' }, { field: 'f2', as: 'alias2' } ], where: [],
          order: [], group: [], limit: undefined, offset: undefined },
        "");


      var data = parser.parse("SELECT f1 as alias , f2 as alias2  FROM proj ", [1]);
      uniTest.equalObject(
        data,
        { type: 'select', from: 'proj', join: [],
          fields: [ { field: 'f1', as: 'alias' }, { field: 'f2', as: 'alias2' } ], where: [],
          order: [], group: [], limit: undefined, offset: undefined },
        "");

      var data = parser.parse("SELECT f1 , f2 as alias2  FROM proj ", [1]);
      uniTest.equalObject(
        data,
        { type: 'select', from: 'proj', join: [],
          fields: [ { field: 'f1' }, { field: 'f2', as: 'alias2' } ], where: [],
          order: [], group: [], limit: undefined, offset: undefined },
        "");

      var data = parser.parse("SELECT f1, f2 as alias2,f3 FROM proj ", [1]);
      uniTest.equalObject(
        data,
        { type: 'select', from: 'proj', join: [],
          fields: [ { field: 'f1' }, { field: 'f2', as: 'alias2' }, { field: 'f3' } ], where: [],
          order: [], group: [], limit: undefined, offset: undefined },
        "");


      var data = parser.parse("SELECT f1, f2 as alias2,  f3 FROM proj ", [1]);
      uniTest.equalObject(
        data,
        { type: 'select', from: 'proj', join: [],
          fields: [ { field: 'f1' }, { field: 'f2', as: 'alias2' }, { field: 'f3' } ], where: [],
          order: [], group: [], limit: undefined, offset: undefined },
        "");

    });

    uniTest.add("001 FSQL", "Parser (SELECT: fields *)", function(a_tester) {
      var parser = new Parser();

      var data = parser.parse("SELECT * FROM proj", [1]);
      uniTest.equalObject(
        data,
        { type: 'select', from: 'proj', join: [],
          fields: [ { field: '*' } ], where: [],
          order: [], group: [], limit: undefined, offset: undefined },
        "");

      var data = parser.parse("SELECT *, k FROM proj", [1]);
      uniTest.equalObject(
        data,
        { type: 'select', from: 'proj', join: [],
          fields: [ { field: '*' }, { field: 'k' } ], where: [],
          order: [], group: [], limit: undefined, offset: undefined },
        "");

      var data = parser.parse("SELECT proj2.*,k FROM proj", [1]);
      uniTest.equalObject(
        data,
        { type: 'select', from: 'proj', join: [],
          fields: [ { from: 'proj2', field: '*' }, { field: 'k' } ], where: [],
          order: [], group: [], limit: undefined, offset: undefined },
        "");

    });

    uniTest.add("001 FSQL", "Parser (SELECT: fieldsex)", function(a_tester) {
      var parser = new Parser();

      var data = parser.parse("SELECT field1:short, field2 : full FROM proj", [1]);
      uniTest.equalObject(
        { type: 'select', from: 'proj', join: [],
          fields: [ { field: 'field1', mode: "short" }, { field: 'field2', mode: "full" } ], where: [],
          order: [], group: [], limit: undefined, offset: undefined },
        data,
        "");

      var data = parser.parse("SELECT field1:short, field2:\"full\" as f2 FROM proj", [1]);
      uniTest.equalObject(
        { type: 'select', from: 'proj', join: [],
          fields: [ { field: 'field1', mode: "short" }, { field: 'field2', mode: "full", as: "f2" } ], where: [],
          order: [], group: [], limit: undefined, offset: undefined },
        data,
        "");

      var data = parser.parse("SELECT field1:default:subfield FROM proj", []);
      uniTest.equalObject(
        { type: 'select', from: 'proj', join: [],
          fields: [ { field: 'field1', result: "subfield", mode: "default" }], where: [],
          order: [], group: [], limit: undefined, offset: undefined },
        data,
        "");

      var data = parser.parse("SELECT field1:default : subfield FROM proj", []);
      uniTest.equalObject(
        { type: 'select', from: 'proj', join: [],
          fields: [ { field: 'field1', result: "subfield", mode: "default" }], where: [],
          order: [], group: [], limit: undefined, offset: undefined },
        data,
        "");


      var data = parser.parse("SELECT field1:default:\"subfield\" FROM proj", []);
      uniTest.equalObject(
        { type: 'select', from: 'proj', join: [],
          fields: [ { field: 'field1', result: "subfield", mode: "default" }], where: [],
          order: [], group: [], limit: undefined, offset: undefined },
        data,
        "");

      var data = parser.parse("SELECT field1->subfield1 FROM proj", []);
      uniTest.equalObject(
        { type: 'select', from: 'proj', join: [],
          fields: [ { field: 'field1', path: ["subfield1"] }], where: [],
          order: [], group: [], limit: undefined, offset: undefined },
        data,
        "");

      var data = parser.parse("SELECT field1->subfield1->subfield2 FROM proj", []);
      uniTest.equalObject(
        { type: 'select', from: 'proj', join: [],
          fields: [ { field: 'field1', path: ["subfield1", "subfield2"] }], where: [],
          order: [], group: [], limit: undefined, offset: undefined },
        data,
        "");

      var data = parser.parse("SELECT field1:default->subfield1->subfield2 FROM proj", []);
      uniTest.equalObject(
        { type: 'select', from: 'proj', join: [],
          fields: [ { field: 'field1', path: ["subfield1", "subfield2"], mode: "default" }], where: [],
          order: [], group: [], limit: undefined, offset: undefined },
        data,
        "");

      var data = parser.parse("SELECT field1:default->\"subfield1\"->\"subfield2\" FROM proj", []);
      uniTest.equalObject(
        { type: 'select', from: 'proj', join: [],
          fields: [ { field: 'field1', path: ["subfield1", "subfield2"], mode: "default" }], where: [],
          order: [], group: [], limit: undefined, offset: undefined },
        data,
        "");

    });


    uniTest.add("001 FSQL", "Parser (SELECT: functions)", function(a_tester) {
      var parser = new Parser();

      var data = parser.parse("SELECT count(), f1 FROM proj", [1]);
      uniTest.equalObject(
        data,
        { type: 'select', from: 'proj', join: [],
          fields: [ { function: 'count', args: [] }, {field: "f1"} ], where: [],
          order: [], group: [], limit: undefined, offset: undefined },
        "");

      var data = parser.parse("SELECT count(f2), f1 FROM proj", [1]);
      uniTest.equalObject(
        data,
        { type: 'select', from: 'proj', join: [],
          fields: [ { function: 'count', args: [{field: "f2"}] }, {field: "f1"} ], where: [],
          order: [], group: [], limit: undefined, offset: undefined },
        "");

      var data = parser.parse("SELECT count(\"f2\"), f1 FROM proj", [1]);
      uniTest.equalObject(
        data,
        { type: 'select', from: 'proj', join: [],
          fields: [ { function: 'count', args: [{field: "f2"}] }, {field: "f1"} ], where: [],
          order: [], group: [], limit: undefined, offset: undefined },
        "");

      var data = parser.parse("SELECT count( \"f2\" , \"f3\" ), \"f1\" FROM proj", [1]);
      uniTest.equalObject(
        data,
        { type: 'select', from: 'proj', join: [],
          fields: [ { function: 'count', args: [{field: "f2"}, {field: "f3"}] }, {field: "f1"} ], where: [],
          order: [], group: [], limit: undefined, offset: undefined },
        "");


      var data = parser.parse("SELECT count(\"f2\",\"f3\"),f1 FROM proj", [1]);
      uniTest.equalObject(
        data,
        { type: 'select', from: 'proj', join: [],
          fields: [ { function: 'count', args: [{field: "f2"}, {field: "f3"}] }, {field: "f1"} ], where: [],
          order: [], group: [], limit: undefined, offset: undefined },
        "");

      var data = parser.parse("SELECT count(f2,f3),f1,count2(d1) FROM proj", [1]);
      uniTest.equalObject(
        data,
        { type: 'select', from: 'proj', join: [],
          fields: [ { function: 'count', args: [{field: "f2"}, {field: "f3"}] }, {field: "f1"},{ function: 'count2', args: [{field: "d1"}] } ], where: [],
          order: [], group: [], limit: undefined, offset: undefined },
        "");

      var data = parser.parse("SELECT count(count2(${1}),\"f3\"),f1 FROM proj", [1]);
      uniTest.equalObject(
        data,
        { type: 'select', from: 'proj', join: [],
          fields: [
            { function: 'count',
              args: [
                {function: "count2", args:[{value: 1}]},
                {field: "f3"}
            ] },
            {field: "f1"}
          ],
          where: [],
          order: [], group: [], limit: undefined, offset: undefined },
        "");

    });


    uniTest.add("001 FSQL", "Parser (SELECT: quote fields)", function(a_tester) {
      var parser = new Parser();

      var data = parser.parse("SELECT \"f1\" FROM proj", [1]);
      uniTest.equalObject(
        data,
        { type: 'select', from: 'proj', join: [],
          fields: [ { field: 'f1' } ], where: [],
          order: [], group: [], limit: undefined, offset: undefined },
        "");

      var data = parser.parse("SELECT \"proj\".\"f1\" as \"ALIAS\",\"proj\".\"f2\" as \"ALIAS2\" FROM proj", [1]);
      uniTest.equalObject(
        data,
        { type: 'select', from: 'proj', join: [],
          fields: [ { from: 'proj', field: 'f1', as: 'ALIAS' }, { from: 'proj', field: 'f2', as: 'ALIAS2' } ], where: [],
          order: [], group: [], limit: undefined, offset: undefined },
        "");

      var data = parser.parse("SELECT \"proj\".\"f1\" as \"ALIAS\", \"proj\".\"f2\" as \"ALIAS2\" FROM proj", [1]);
      uniTest.equalObject(
        data,
        { type: 'select', from: 'proj', join: [],
          fields: [ { from: 'proj', field: 'f1', as: 'ALIAS' }, { from: 'proj', field: 'f2', as: 'ALIAS2' } ], where: [],
          order: [], group: [], limit: undefined, offset: undefined },
        "");

      var data = parser.parse("SELECT \"proj\".\"f1\" as \"ALIAS1\" , \"proj\".\"f2\" as \"ALIAS2\" FROM \"proj\"", [1]);
      uniTest.equalObject(
        data,
        { type: 'select', from: 'proj', join: [],
          fields: [ { from: 'proj', field: 'f1', as: 'ALIAS1' },
                    { from: 'proj', field: 'f2', as: 'ALIAS2' } ],
          where: [], order: [], group: [], limit: undefined, offset: undefined },
        "");
    });

    uniTest.add("001 FSQL", "Parser (SELECT: block where)", function(a_tester) {
      var parser = new Parser();

      var data = parser.parse("SELECT \"f1\" FROM proj WHERE id = ${1}", [2]);
      uniTest.equalObject(
        data,
        { type: 'select', from: 'proj', join: [],
          fields: [ { field: 'f1' } ],
          where: [{ logic: "and", type: "=", args: [ { field: "id" }, { value: 2 }, ] } ],
          order: [], group: [], limit: undefined, offset: undefined },
        "");

      var data = parser.parse("SELECT \"f1\" FROM proj WHERE id = ${1} and data = ${2}", [2, 3]);
      uniTest.equalObject(
        data,
        { type: 'select', from: 'proj', join: [],
          fields: [ { field: 'f1' } ],
          where: [{ logic: "and", type: "=", args: [ { field: "id" }, { value: 2 }, ] },
                  { logic: "and", type: "=", args: [ { field: "data" }, { value: 3 }, ] } ],
          order: [], group: [], limit: undefined, offset: undefined },
        "");

      var data = parser.parse("SELECT \"f1\" FROM proj WHERE id = ${1} or data = ${2}", [2, 3]);
      uniTest.equalObject(
        data,
        { type: 'select', from: 'proj', join: [],
          fields: [ { field: 'f1' } ],
          where: [{ logic: "and", type: "=", args: [ { field: "id" }, { value: 2 }, ] },
                  { logic: "or", type: "=", args: [ { field: "data" }, { value: 3 }, ] } ],
          order: [], group: [], limit: undefined, offset: undefined },
        "");

      var data = parser.parse("SELECT \"f1\" FROM proj WHERE id =${1}or data =${2}", [2, 3]);
      uniTest.equalObject(
        data,
        { type: 'select', from: 'proj', join: [],
          fields: [ { field: 'f1' } ],
          where: [{ logic: "and", type: "=", args: [ { field: "id" }, { value: 2 }, ] },
                  { logic: "or", type: "=", args: [ { field: "data" }, { value: 3 }, ] } ],
          order: [], group: [], limit: undefined, offset: undefined },
        "");


        var data = parser.parse("SELECT \"f1\" FROM proj WHERE ${1} = id", [2]);
        uniTest.equalObject(
          data,
          { type: 'select', from: 'proj', join: [],
            fields: [ { field: 'f1' } ],
            where: [{ logic: "and", type: "=", args: [ { value: 2 }, { field: "id" }] } ],
            order: [], group: [], limit: undefined, offset: undefined },
          "");

        var data = parser.parse("SELECT \"f1\" FROM proj WHERE ${1} = id or ${2} <> dt", [2, 5]);
        uniTest.equalObject(
          data,
          { type: 'select', from: 'proj', join: [],
            fields: [ { field: 'f1' } ],
            where: [{ logic: "and", type: "=", args: [ { value: 2 }, { field: "id" }] },
                    { logic: "or", type: "<>", args: [ { value: 5 }, { field: "dt" }] }],
            order: [], group: [], limit: undefined, offset: undefined },
          "");

        var data = parser.parse("SELECT \"f1\" FROM proj WHERE${1}=id or${2}<>dt", [2, 5]);
        uniTest.equalObject(
          data,
          { type: 'select', from: 'proj', join: [],
            fields: [ { field: 'f1' } ],
            where: [{ logic: "and", type: "=", args: [ { value: 2 },  { field: "id" }] },
                    { logic: "or",  type: "<>", args: [ { value: 5 }, { field: "dt" }] }],
            order: [], group: [], limit: undefined, offset: undefined },
          "");

        var data = parser.parse("SELECT \"f1\" FROM proj WHERE id=${1}or${2}<>dt and t1 = d2", [2, 5]);
        uniTest.equalObject(
          data,
          { type: 'select', from: 'proj', join: [],
            fields: [ { field: 'f1' } ],
            where: [{ logic: "and", type: "=", args: [ { field: "id" }, { value: 2 }] },
                    { logic: "or", type: "<>", args:  [ { value: 5 }, { field: "dt" }] },
                    { logic: "and", type: "=", args: [ { field: "t1" }, { field: "d2" }] }
                  ],
            order: [], group: [], limit: undefined, offset: undefined },
          "");

        // check quotes
        var data = parser.parse("SELECT \"f1\" FROM proj WHERE \"id\" = ${1}", [2]);
        uniTest.equalObject(
          data,
          { type: 'select', from: 'proj', join: [],
            fields: [ { field: 'f1' } ],
            where: [{ logic: "and", type: "=", args: [ { field: "id" }, { value: 2 }] } ],
            order: [], group: [], limit: undefined, offset: undefined },
          "");

        var data = parser.parse("SELECT \"f1\" FROM proj WHERE ${1} = \"id\"", [2]);
        uniTest.equalObject(
          data,
          { type: 'select', from: 'proj', join: [],
            fields: [ { field: 'f1' } ],
            where: [{ logic: "and", type: "=", args: [ { value: 2 }, { field: "id" }] } ],
            order: [], group: [], limit: undefined, offset: undefined },
          "");

        var data = parser.parse("SELECT \"f1\" FROM proj WHERE\"id\"=${1}", [2]);
        uniTest.equalObject(
          data,
          { type: 'select', from: 'proj', join: [],
            fields: [ { field: 'f1' } ],
            where: [{ logic: "and", type: "=", args: [ { field: "id" }, { value: 2 }] } ],
            order: [], group: [], limit: undefined, offset: undefined },
          "");

        var data = parser.parse("SELECT \"f1\" FROM \"proj\" WHERE${1}=\"id\"OR\"k\">=t", [2]);
        uniTest.equalObject(
          data,
          { type: 'select', from: 'proj', join: [],
            fields: [ { field: 'f1' } ],
            where:  [
                     { logic: "and", type: "=", args: [ { value: 2 }, { field: "id" }] },
                     { logic: "or", type: ">=", args: [ { field: "k" }, { field: "t" }] }
                    ],
            order: [], group: [], limit: undefined, offset: undefined },
          "");

          var data = parser.parse("SELECT \"f1\" FROM proj WHERE \"name\" LIKE ${1}", ["string"]);
          uniTest.equalObject(
            data,
            { type: 'select', from: 'proj', join: [],
              fields: [ { field: 'f1' } ],
              where: [{ logic: "and", type: "like", args: [ { field: "name" }, { value: "string" }] } ],
              order: [], group: [], limit: undefined, offset: undefined },
            "");

            var data = parser.parse("SELECT \"f1\" FROM proj WHERE \"name\"LIKE${1}", ["string"]);
            uniTest.equalObject(
              data,
              { type: 'select', from: 'proj', join: [],
                fields: [ { field: 'f1' } ],
                where: [{ logic: "and", type: "like", args: [ { field: "name" }, { value: "string" }] } ],
                order: [], group: [], limit: undefined, offset: undefined },
              "");

      });

      uniTest.add("001 FSQL", "Parser (SELECT: block where with froms)", function(a_tester) {
        var parser = new Parser();

        var data = parser.parse("SELECT \"f1\" FROM proj WHERE proj.id = ${1}", [2]);
        uniTest.equalObject(
          data,
          { type: 'select', from: 'proj', join: [],
            fields: [ { field: 'f1' } ],
            where: [{ logic: "and", type: "=", args: [ { from: "proj", field: "id" }, { value: 2 }, ] } ],
            order: [], group: [], limit: undefined, offset: undefined },
          "");

        var data = parser.parse("SELECT \"f1\" FROM proj WHERE proj.id=${1}", [2]);
        uniTest.equalObject(
          data,
          { type: 'select', from: 'proj', join: [],
            fields: [ { field: 'f1' } ],
            where: [{ logic: "and", type: "=", args: [ { from: "proj", field: "id" }, { value: 2 }, ] } ],
            order: [], group: [], limit: undefined, offset: undefined },
          "");

        var data = parser.parse("SELECT \"f1\" FROM proj WHERE \"proj\".id=${1}", [2]);
        uniTest.equalObject(
          data,
          { type: 'select', from: 'proj', join: [],
            fields: [ { field: 'f1' } ],
            where: [{ logic: "and", type: "=", args: [ { from: "proj", field: "id" }, { value: 2 }, ] } ],
            order: [], group: [], limit: undefined, offset: undefined },
          "");
        var data = parser.parse("SELECT \"f1\" FROM proj WHERE \"proj\".\"id\" = ${1}", [2]);
        uniTest.equalObject(
          data,
          { type: 'select', from: 'proj', join: [],
            fields: [ { field: 'f1' } ],
            where: [{ logic: "and", type: "=", args: [ { from: "proj", field: "id" }, { value: 2 }, ] } ],
            order: [], group: [], limit: undefined, offset: undefined },
          "");
        var data = parser.parse("SELECT \"f1\" FROM proj WHERE \"proj\" . \"id\"=   ${1}", [2]);
        uniTest.equalObject(
          data,
          { type: 'select', from: 'proj', join: [],
            fields: [ { field: 'f1' } ],
            where: [{ logic: "and", type: "=", args: [ { from: "proj", field: "id" }, { value: 2 }, ] } ],
            order: [], group: [], limit: undefined, offset: undefined },
          "");

          var data = parser.parse("SELECT \"f1\" FROM proj WHERE \"proj\" . \"id\" = proj2.id2", [2]);
          uniTest.equalObject(
            data,
            { type: 'select', from: 'proj', join: [],
              fields: [ { field: 'f1' } ],
              where: [{ logic: "and", type: "=", args: [ { from: "proj", field: "id" }, { from: "proj2", field: "id2" }, ] } ],
              order: [], group: [], limit: undefined, offset: undefined },
            "");

          var data = parser.parse("SELECT \"f1\" FROM proj WHERE \"proj\" . \"id\" =proj2 . id2", [2]);
          uniTest.equalObject(
            data,
            { type: 'select', from: 'proj', join: [],
              fields: [ { field: 'f1' } ],
              where: [{ logic: "and", type: "=", args: [ { from: "proj", field: "id" }, { from: "proj2", field: "id2" }, ] } ],
              order: [], group: [], limit: undefined, offset: undefined },
            "");

          var data = parser.parse("SELECT \"f1\" FROM proj WHERE \"proj\" . \"id\" =\"proj2\" . \"id2\" or\"proj3\".\"field\"<=${2} ", [2,3]);
          uniTest.equalObject(
            data,
            { type: 'select', from: 'proj', join: [],
              fields: [ { field: 'f1' } ],
              where: [{ logic: "and", type: "=",  args: [ { from: "proj", field: "id" }, { from: "proj2", field: "id2" }, ] },
                      { logic: "or",  type: "<=", args: [ { from: "proj3", field: "field" }, { value: 3 }, ] } ],
              order: [], group: [], limit: undefined, offset: undefined },
            "");
      });

      uniTest.add("001 FSQL", "Parser (SELECT: block where with brackets)", function(a_tester) {
        var parser = new Parser();

        var data = parser.parse("SELECT \"f1\" FROM proj WHERE (proj.id = ${1})", [2]);
        uniTest.equalObject(
          data,
          { type: 'select', from: 'proj', join: [],
            fields: [ { field: 'f1' } ],
            where: [
              { logic: "and", type: "block", args: [
                  { logic: "and", type: "=", args: [ { from: "proj", field: "id" }, { value: 2 }, ] }
                ]
              }
            ],
            order: [], group: [], limit: undefined, offset: undefined },
          "");

        var data = parser.parse("SELECT \"f1\" FROM proj WHERE (proj.id = ${1}) OR (proj2.id2 <> ${2})", [2,3]);
        uniTest.equalObject(
          data,
          { type: 'select', from: 'proj', join: [],
            fields: [ { field: 'f1' } ],
            where: [
              { logic: "and", type: "block", args: [
                  { logic: "and", type: "=", args: [ { from: "proj", field: "id" }, { value: 2 }, ] }
                ]
              },
              { logic: "or", type: "block", args: [
                  { logic: "and", type: "<>", args: [ { from: "proj2", field: "id2" }, { value: 3 }, ] }
                ]
              }
            ],
            order: [], group: [], limit: undefined, offset: undefined },
          "");


        var data = parser.parse("SELECT \"f1\" FROM proj WHERE(proj.id=${1})OR(proj2.id2<>${2})", [2,3]);
        uniTest.equalObject(
          data,
          { type: 'select', from: 'proj', join: [],
            fields: [ { field: 'f1' } ],
            where: [
              { logic: "and", type: "block", args: [
                  { logic: "and", type: "=", args: [ { from: "proj", field: "id" }, { value: 2 }, ] }
                ]
              },
              { logic: "or", type: "block", args: [
                  { logic: "and", type: "<>", args: [ { from: "proj2", field: "id2" }, { value: 3 }, ] }
                ]
              }
            ],
            order: [], group: [], limit: undefined, offset: undefined },
          "");

        var data = parser.parse("SELECT \"f1\" FROM proj WHERE((\"proj\".\"id\"=${1}) OR (\"proj2\".\"id2\"<>${2}))", [2,3]);
        uniTest.equalObject(
          data,
          { type: 'select', from: 'proj', join: [],
            fields: [ { field: 'f1' } ],
            where: [
              { logic: "and", type: "block", args: [
                  { logic: "and", type: "block", args: [
                      { logic: "and", type: "=", args: [ { from: "proj", field: "id" }, { value: 2 }, ] }
                    ]
                  },
                  { logic: "or", type: "block", args: [
                      { logic: "and", type: "<>", args: [ { from: "proj2", field: "id2" }, { value: 3 }, ] }
                    ]
                  }
                ]
              }
            ],
            order: [], group: [], limit: undefined, offset: undefined },
          "");

      });


      uniTest.add("001 FSQL", "Parser (SELECT: block where with NOT)", function(a_tester) {
        var parser = new Parser();

        var data = parser.parse("SELECT \"f1\" FROM proj WHERE NOT proj.id = ${1}", [2]);
        uniTest.equalObject(
          data,
          { type: 'select', from: 'proj', join: [],
            fields: [ { field: 'f1' } ],
            where: [
                { logic: "and", not: true, type: "=", args: [ { from: "proj", field: "id" }, { value: 2 }, ] }
            ],
            order: [], group: [], limit: undefined, offset: undefined },
        "");

        var data = parser.parse("SELECT \"f1\" FROM proj WHERE NOT ( proj.id = ${1})", [2]);
        uniTest.equalObject(
          data,
          { type: 'select', from: 'proj', join: [],
            fields: [ { field: 'f1' } ],
            where: [
              { logic: "and", not: true, type: "block", args: [
                  { logic: "and", type: "=", args: [ { from: "proj", field: "id" }, { value: 2 }, ] }
                ]
              }
            ],
            order: [], group: [], limit: undefined, offset: undefined },
        "");

        var data = parser.parse("SELECT \"f1\" FROM proj WHERE (NOT proj.id = ${1})", [2]);
        uniTest.equalObject(
          data,
          { type: 'select', from: 'proj', join: [],
            fields: [ { field: 'f1' } ],
            where: [
              { logic: "and", type: "block", args: [
                  { logic: "and", not: true, type: "=", args: [ { from: "proj", field: "id" }, { value: 2 }, ] }
                ]
              }
            ],
            order: [], group: [], limit: undefined, offset: undefined },
        "");

      });

      uniTest.add("001 FSQL", "Parser (SELECT: block order by)", function(a_tester) {
        var parser = new Parser();

        var data = parser.parse("SELECT \"f1\" FROM proj WHERE (proj.id = ${1}) ORDER BY field1 ASC", [2]);
        uniTest.equalObject(
          data,
          { type: 'select', from: 'proj', join: [],
            fields: [ { field: 'f1' } ],
            where: [
              { logic: "and", type: "block", args: [
                  { logic: "and", type: "=", args: [ { from: "proj", field: "id" }, { value: 2 }, ] }
                ]
              }
            ],
            order: [{field: "field1", order: "asc"}], group: [], limit: undefined, offset: undefined },
          "");

        var data = parser.parse("SELECT \"f1\" FROM proj WHERE (proj.id = ${1}) ORDER BY field1", [2]);
        uniTest.equalObject(
          data,
          { type: 'select', from: 'proj', join: [],
            fields: [ { field: 'f1' } ],
            where: [
              { logic: "and", type: "block", args: [
                  { logic: "and", type: "=", args: [ { from: "proj", field: "id" }, { value: 2 }, ] }
                ]
              }
            ],
            order: [{field: "field1", order: "asc"}], group: [], limit: undefined, offset: undefined },
          "");

        var data = parser.parse("SELECT \"f1\" FROM proj WHERE (proj.id = ${1}) ORDER BY field1 DESC", [2]);
        uniTest.equalObject(
          data,
          { type: 'select', from: 'proj', join: [],
            fields: [ { field: 'f1' } ],
            where: [
              { logic: "and", type: "block", args: [
                  { logic: "and", type: "=", args: [ { from: "proj", field: "id" }, { value: 2 }, ] }
                ]
              }
            ],
            order: [{field: "field1", order: "desc"}], group: [], limit: undefined, offset: undefined },
          "");

        var data = parser.parse("SELECT \"f1\" FROM proj ORDER BY field1 DESC", [2]);
        uniTest.equalObject(
          data,
          { type: 'select', from: 'proj', join: [],
            fields: [ { field: 'f1' } ],
            where: [ ],
            order: [{field: "field1", order: "desc"}], group: [], limit: undefined, offset: undefined },
          "");

        var data = parser.parse("SELECT \"f1\" FROM proj ORDER BY field1 DESC, field2 ASC", [2]);
        uniTest.equalObject(
          data,
          { type: 'select', from: 'proj', join: [],
            fields: [ { field: 'f1' } ],
            where: [ ],
            order: [{field: "field1", order: "desc"}, {field: "field2", order: "asc"}], group: [], limit: undefined, offset: undefined },
          "");

        var data = parser.parse("SELECT \"f1\" FROM proj ORDER BY field1,field2 ASC", [2]);
        uniTest.equalObject(
          data,
          { type: 'select', from: 'proj', join: [],
            fields: [ { field: 'f1' } ],
            where: [ ],
            order: [{field: "field1", order: "asc"}, {field: "field2", order: "asc"}], group: [], limit: undefined, offset: undefined },
          "");

        var data = parser.parse("SELECT \"f1\" FROM proj ORDER BY field1 , field2 ASC", [2]);
        uniTest.equalObject(
          data,
          { type: 'select', from: 'proj', join: [],
            fields: [ { field: 'f1' } ],
            where: [ ],
            order: [{field: "field1", order: "asc"}, {field: "field2", order: "asc"}], group: [], limit: undefined, offset: undefined },
          "");

        var data = parser.parse("SELECT \"f1\" FROM proj ORDER BY \"field1\",\"field2\" ASC", [2]);
        uniTest.equalObject(
          data,
          { type: 'select', from: 'proj', join: [],
            fields: [ { field: 'f1' } ],
            where: [ ],
            order: [{field: "field1", order: "asc"}, {field: "field2", order: "asc"}], group: [], limit: undefined, offset: undefined },
          "");


        var data = parser.parse("SELECT \"f1\" FROM proj ORDER BY\"field1\"DESC,\"field2\" ASC", [2]);
        uniTest.equalObject(
          data,
          { type: 'select', from: 'proj', join: [],
            fields: [ { field: 'f1' } ],
            where: [ ],
            order: [{field: "field1", order: "desc"}, {field: "field2", order: "asc"}], group: [], limit: undefined, offset: undefined },
          "");


        var data = parser.parse("SELECT \"f1\" FROM proj ORDER BY\"proj\".\"field1\"DESC,\"field2\" ASC", [2]);
        uniTest.equalObject(
          data,
          { type: 'select', from: 'proj', join: [],
            fields: [ { field: 'f1' } ],
            where: [ ],
            order: [{from:"proj", field: "field1", order: "desc"}, {field: "field2", order: "asc"}], group: [], limit: undefined, offset: undefined },
          "");

        var data = parser.parse("SELECT \"f1\" FROM proj ORDER BY\"proj\".\"field1\"DESC,proj2 . \"field2\" ASC", [2]);
        uniTest.equalObject(
          data,
          { type: 'select', from: 'proj', join: [],
            fields: [ { field: 'f1' } ],
            where: [ ],
            order: [{from:"proj", field: "field1", order: "desc"}, {from:"proj2",field: "field2", order: "asc"}], group: [], limit: undefined, offset: undefined },
          "");

        var data = parser.parse("SELECT \"f1\" FROM proj ORDER BY\"proj\".\"field1\"DESC, \"proj2\".\"field2\"", [2]);
        uniTest.equalObject(
          data,
          { type: 'select', from: 'proj', join: [],
            fields: [ { field: 'f1' } ],
            where: [ ],
            order: [{from:"proj", field: "field1", order: "desc"}, {from:"proj2", field: "field2", order: "asc"}], group: [], limit: undefined, offset: undefined },
          "");

      });


      uniTest.add("001 FSQL", "Parser (SELECT: block limit/offset)", function(a_tester) {
        var parser = new Parser();

        var data = parser.parse("SELECT \"f1\" FROM proj WHERE (proj.id = ${1}) ORDER BY \"field1\"LIMIT ${2}", [2, 3]);
        uniTest.equalObject(
          data,
          { type: 'select', from: 'proj', join: [],
            fields: [ { field: 'f1' } ],
            where: [
              { logic: "and", type: "block", args: [
                  { logic: "and", type: "=", args: [ { from: "proj", field: "id" }, { value: 2 }, ] }
                ]
              }
            ],
            order: [{field: "field1", order: "asc"}], group: [], limit: 3, offset: undefined },
          "");

        var data = parser.parse("SELECT \"f1\" FROM proj WHERE (proj.id = ${1}) ORDER BY field1 LIMIT ${2}", [2, 3]);
        uniTest.equalObject(
          data,
          { type: 'select', from: 'proj', join: [],
            fields: [ { field: 'f1' } ],
            where: [
              { logic: "and", type: "block", args: [
                  { logic: "and", type: "=", args: [ { from: "proj", field: "id" }, { value: 2 }, ] }
                ]
              }
            ],
            order: [{field: "field1", order: "asc"}], group: [], limit: 3, offset: undefined },
          "");

        var data = parser.parse("SELECT \"f1\" FROM proj WHERE (proj.id = ${1}) ORDER BY field1 LIMIT ${2} OFFSET ${3}", [2, 3, 5]);
        uniTest.equalObject(
          data,
          { type: 'select', from: 'proj', join: [],
            fields: [ { field: 'f1' } ],
            where: [
              { logic: "and", type: "block", args: [
                  { logic: "and", type: "=", args: [ { from: "proj", field: "id" }, { value: 2 }, ] }
                ]
              }
            ],
            order: [{field: "field1", order: "asc"}], group: [], limit: 3, offset: 5 },
          ""
        );
      }
    );



    uniTest.add("001 FSQL", "Parser (SELECT: extern arguments)", function(a_tester) {
      var parser = new Parser();

      var data = parser.parse("SELECT f1 FROM proj WHERE f2 = $[0][0][@insertId]", []);
      uniTest.equalObject(
        data,
        { type: 'select', from: 'proj', join: [],
          fields: [{ field: 'f1' }],
          where: [{logic: "and", type: "=", args: [{field: "f2"}, { result: 0, record: 0, item: "@insertId" }]}],
          order: [],
          group: [],
          limit: undefined,
          offset: undefined },
        "");

      var data = parser.parse("SELECT f1 FROM proj WHERE f2 = $[1][0][\"@insertId\"]", []);
      uniTest.equalObject(
        data,
        { type: 'select', from: 'proj', join: [],
          fields: [{ field: 'f1' }],
          where: [{logic: "and", type: "=", args: [{field: "f2"}, { result: 1, record: 0, item: "@insertId" }]}],
          order: [],
          group: [],
          limit: undefined,
          offset: undefined },
        "");

      var data = parser.parse("SELECT f1 FROM proj WHERE f2 = $[-1][0][\"@insertId\"]", []);
      uniTest.equalObject(
        data,
        { type: 'select', from: 'proj', join: [],
          fields: [{ field: 'f1' }],
          where: [{logic: "and", type: "=", args: [{field: "f2"}, { result: -1, record: 0, item: "@insertId" }]}],
          order: [],
          group: [],
          limit: undefined,
          offset: undefined },
        "");

      var data = parser.parse("SELECT f1 FROM proj WHERE f2 = $[ -1 ] [ 0 ] [ \"@insertId\" ] and f1 <> f2", []);
      uniTest.equalObject(
        data,
        { type: 'select', from: 'proj', join: [],
          fields: [{ field: 'f1' }],
          where: [ { logic: "and", type: "=",  args: [ {field: "f2"}, { result: -1, record: 0, item: "@insertId" } ] },
                   { logic: "and", type: "<>", args: [ {field: "f1"}, { field: "f2" } ] } ],
          order: [],
          group: [],
          limit: undefined,
          offset: undefined },
        "");
    });


    uniTest.add("001 FSQL", "Parser (SELECT: Language)", function(a_tester) {
      var parser = new Parser();

      var data = parser.parse("SELECT f1 FROM proj LANGUAGE ru", []);
      uniTest.equalObject(
        data,
        { type: 'select', from: 'proj', join: [],
          fields: [{ field: 'f1' }],
          where: [],
          order: [],
          group: [],
          language: "ru",
          limit: undefined,
          offset: undefined },
        "");     

      var data = parser.parse("SELECT f1 FROM proj LANGUAGE ru DEFAULT", []);
      uniTest.equalObject(
        data,
        { type: 'select', from: 'proj', join: [],
          fields: [{ field: 'f1' }],
          where: [],
          order: [],
          group: [],
          language: "ru",
          defaultLanguage: true,
          limit: undefined,
          offset: undefined },
        "");     

      var data = parser.parse("SELECT f1 FROM proj LANGUAGE ${1}", ["ru"]);
      uniTest.equalObject(
        data,
        { type: 'select', from: 'proj', join: [],
          fields: [{ field: 'f1' }],
          where: [],
          order: [],
          group: [],
          language: "ru",
          limit: undefined,
          offset: undefined },
        "");     

      var data = parser.parse("SELECT f1 FROM proj WHERE a1=a2 LANGUAGE en", []);
      uniTest.equalObject(
        data,
        { type: 'select', from: 'proj', join: [],
          fields: [{ field: 'f1' }],
          where: [{logic: "and", type:"=", args: [{ field: 'a1' }, { field: 'a2' }] }],
          order: [],
          group: [],
          language: "en",
          limit: undefined,
          offset: undefined },
        "");     

      var data = parser.parse("SELECT f1 FROM proj WHERE a1=a2 LANGUAGE ${1}", ["en"]);
      uniTest.equalObject(
        data,
        { type: 'select', from: 'proj', join: [],
          fields: [{ field: 'f1' }],
          where: [{logic: "and", type:"=", args: [{ field: 'a1' }, { field: 'a2' }] }],
          order: [],
          group: [],
          language: "en",
          limit: undefined,
          offset: undefined },
        "");     

      var data = parser.parse("SELECT f1 FROM proj WHERE a1=a2 ORDER BY f1 LANGUAGE en", []);
      uniTest.equalObject(
        data,
        { type: 'select', from: 'proj', join: [],
          fields: [{ field: 'f1' }],
          where: [{logic: "and", type:"=", args: [{ field: 'a1' }, { field: 'a2' }] }],
          order: [{field: "f1", order: "asc"}],
          group: [],
          language: "en",
          limit: undefined,
          offset: undefined },
        "");     

      var data = parser.parse("SELECT f1 FROM proj WHERE a1=a2 ORDER BY f1 DESC LANGUAGE en", []);
      uniTest.equalObject(
        data,
        { type: 'select', from: 'proj', join: [],
          fields: [{ field: 'f1' }],
          where: [{logic: "and", type:"=", args: [{ field: 'a1' }, { field: 'a2' }] }],
          order: [{field: "f1", order: "desc"}],
          group: [],
          language: "en",
          limit: undefined,
          offset: undefined },
        "");     

      var data = parser.parse("SELECT f1 FROM proj WHERE a1=a2 ORDER BY f1 DESC LIMIT ${1} LANGUAGE en", [100]);
      uniTest.equalObject(
        data,
        { type: 'select', from: 'proj', join: [],
          fields: [{ field: 'f1' }],
          where: [{logic: "and", type:"=", args: [{ field: 'a1' }, { field: 'a2' }] }],
          order: [{field: "f1", order: "desc"}],
          group: [],
          language: "en",
          limit: 100,
          offset: undefined },
        "");     

      var data = parser.parse("SELECT f1 FROM proj WHERE a1=a2 ORDER BY f1 DESC LIMIT ${1} OFFSET ${2} LANGUAGE en", [100, 10]);
      uniTest.equalObject(
        data,
        { type: 'select', from: 'proj', join: [],
          fields: [{ field: 'f1' }],
          where: [{logic: "and", type:"=", args: [{ field: 'a1' }, { field: 'a2' }] }],
          order: [{field: "f1", order: "desc"}],
          group: [],
          language: "en",
          limit: 100,
          offset: 10 },
        "");     

      var data = parser.parse("SELECT f1 FROM proj LEFT JOIN t2 ON proj1.f1 = t2.f1 WHERE a1=a2 ORDER BY f1 DESC LIMIT ${1} OFFSET ${2} LANGUAGE en", [100, 10]);
      uniTest.equalObject(
        data,
        { type: 'select', from: 'proj',
          fields: [{ field: 'f1' }],
          join: [
            {
              "join": "left",
              "from": "t2",
              "on": [
                {
                  "logic": "and",
                  "args": [
                    {
                      "field": "f1",
                      "from": "proj1"
                    },
                    {
                      "field": "f1",
                      "from": "t2"
                    }
                  ],
                  "type": "="
                }
              ]
            }
          ],
          where: [{logic: "and", type:"=", args: [{ field: 'a1' }, { field: 'a2' }] }],
          order: [{field: "f1", order: "desc"}],
          group: [],
          language: "en",
          limit: 100,
          offset: 10 },
        "");     


      var data = parser.parse("SELECT f1 FROM proj LEFT JOIN t2 ON proj1.f1 = t2.f1 LANGUAGE en", []);
      uniTest.equalObject(
        data,
        { type: 'select', from: 'proj',
          fields: [{ field: 'f1' }],
          join: [
            {
              "join": "left",
              "from": "t2",
              "on": [
                {
                  "logic": "and",
                  "args": [
                    {
                      "field": "f1",
                      "from": "proj1"
                    },
                    {
                      "field": "f1",
                      "from": "t2"
                    }
                  ],
                  "type": "="
                }
              ]
            }
          ],
          where: [],
          order: [],
          group: [],
          language: "en",
          limit: undefined,
          offset: undefined },
        "");     

    });


    return NTests;
  }
});
