Criando uma fonte de dados

Um DataSource é construído a partir de um script .ids no sistema de arquivos virtual ou somente instanciando o DataSource e passando como parâmetro um objeto literal. O objeto literal definido no .ids ou passado direto como parâmetro deve conter as seguintes propriedades e funções:

  • includes (opcional): é um array de chaves ou scripts que devem ser inclusos quando for necessário utilizar alguma biblioteca ou função externa ao DataSource. Utilizada quando algum script faz uso de bibliotecas ou funções externas ao DataSource.

  • help: a ajuda do DataSource. Certas classes que utilizam o DataSource, como por exemplo a DataSourceVisualization, podem exibir esta ajuda em tela.

  • onDefineFilters (opcional): esse método, quando definido, será executado na definição especializada dos filtros do datasource e roda no início de sua criação. Isso será especialmente útil quando, na preparação do availableFilters, for necessário acessar os scripts sinalizados na propriedade includes. O primeiro parâmetro passado é a própria definição do objeto literal que constrói o datasource. O segundo parâmetro passado é a instância do datasource.

  • onDefineColumns (opcional): esse método, quando definido, será executado na definição especializada das colunas do datasource e roda no início de sua criação. Isso também será útil quando, na preparação do availableColumns, for necessário acessar os scripts sinalizados na propriedade includes. O primeiro parâmetro passado é a própria definição do objeto literal que constrói o datasource. O segundo parâmetro passado é a instância do datasource.

  • onCreate (opcional): esse método será executado no final da construção do DataSource. Recebe o próprio DataSource como único parâmetro.

  • availableFilters: definição dos filtros que podem ser usados para a consulta que o DataSource realiza. Não é necessário usá-los todos durante uma consulta. Essa propriedade é um Array de objetos, cujo formato será detalhado mais adiante neste manual.

  • availableColumns: definição das colunas que ficarão disponíveis para uso em consultas. Ao menos uma coluna precisa ser utilizada durante uma consulta. Esta propriedade é um Array de objetos, cujo formato será detalhado mais adiante.

  • onCreate (opcional): esse método será executado durante a criação do DataSource. Recebe o próprio DataSource como único parâmetro.

  • onGetQuery: esse método recebe o próprio DataSource, uma instância de DataSourceFilters e uma de DataSourceColumns. Os dois últimos parâmetros são objetos montados pelo DataSource a partir de suas definições. O método onGetQuery deve retornar uma query SQL, que será utilizada pelo método getDataSet do DataSource.

    Segue um exemplo de implementação:

    onGetQuery: function (dataSource, filters, columns) {
      var flts = filters.getIQueryFilters("U_*", "and");
      var cols = columns.getIQueryColumns("U_*");
      if (columns.indexOf("U_iKey") === -1) {
        cols.push({
          alias: "U_iKey",
          field: "iKey"
        });
      }
      var iquery = IQuery.from(-1898187809) /* Usuários */
        .where(flts)
        .column(cols);
      return iquery.toSql();
    }
    
  • onMountDataSet (opcional): executado após a obtenção do DataSet no método getDataSet do DataSource. O DataSet obtido é informado como parâmetro, e o retorno deste método substitui o retorno do método getDataSet.

Os filtros e colunas no script são objetos literais, cuja documentação das definições se encontra em DataSourceFilterDef e DataSourceColumnDef.

Opcionalmente, uma fonte de dados pode ser construída de forma imperativa criando uma instância da classe DataSourceDef. Essa forma alternativa é útil quando a definição de filtros e colunas dependem de regras externas à fonte de dados ou quando deseja-se reaproveitar lógicas existentes em outros códigos.

Além do DataSource, existe também a classe DataSourceQuery. Ela funciona como uma camada sobre o DataSource, permitindo que se refinem os filtros e colunas utilizados.

Tornando um DataSource público

O conceito de publicidade da fonte de dados tem o intuito de garantir que somente aquelas fontes de dados que estiverem sinalizadas como públicas poderão ser consumidas pela API HTTP genérica de consultas automatizadas, o que quer dizer que as fontes de dados públicas podem ser consumidas por outros sistemas.

Para que uma fonte de dados seja pública, o desenvolvedor da fonte de dados deve garantir que ela seja segura, ou seja, os valores dos filtros serão validados e as permissões dos usuários serão sempre obedecidas. É papel do desenvolvedor ainda, elaborar fontes de dados públicas que atendam os requisitos de segurança, evitando que injeções SQL e outras vulnerabilidades possam ser exploradas durante o consumo de uma fonte de dados pública. Fontes de dados públicas não podem conter artifícios que as tornem inseguras.

A maneira mais fácil de realizar a validação das permissões é utilizar uma instância de IQuery no retorno de onGetQuery em vez de utilizar uma “Query SQL” ou qualquer outro mecanismo de exposição de dados como acesso direto ao cache local.

Para tornar uma fonte de dados pública deve ser utilizada a propriedade public da fonte de dados. Abaixo, um exemplo ilustra a definição de uma fonte de dados publicada:

{
  includes: [
    -1897036629 //IQuery.ijs
  ],

  help: "Help do DataSource",

  public: true,

  availableFilters: [{
    classKey: -1898187809, /* Usuários */
    prefix: "U",
    options: {}
  }],

  availableColumns: [{
    classKey: -1898187809, /* Usuários */
    prefix: "U"
  }],

  onCreate: function (ds) {},

  onGetQuery: function (dataSource, filters, columns) {
    var flts = filters.getIQueryFilters( "U_*", "and" );
    var cols = columns.getIQueryColumns( "U_*" );
    var iquery = IQuery.from(-1898187809).where(flts).column(cols);
    return iquery;
  }
}