Избегайте написания операторов SQL в коде MATLAB - PullRequest
0 голосов
/ 14 сентября 2018

Я работаю над приложением со сложными взаимосвязями между заданным значением некоторых элементов управления и допустимыми значениями других элементов управления.

Предполагается, что логика, управляющая этими взаимосвязями, хранится в базе данных sqlite.

Так что в моем коде раскадровки есть множество примеров таких вещей, как

% Extract the coordinates of this location
q = sprintf("%s %s %s '%s';" ...
    , "SELECT latitude, longitude, altitude " ...
    , "FROM locale" ...
    , "WHERE name = " ...
    , app.LocationDropDown.Value ...
    );
llaTbl = app.queryDB(q);

или хуже (sprintf работает с десятью или более строками и использует три или более параметров).

У этого есть все обычные проблемы размещения бизнес-логики в коде с дополнительным бонусом, что ограничение синтаксиса строковых литералов Matlab и системы замены параметров делает его болезненным и подверженным ошибкам, пытаясь вырезать или вставить это в или изСреда тестирования SQL.

Какие существуют механизмы для централизации хранения и редактирования или запросов текстов, которые делают тестирование настолько безболезненным, насколько это возможно?

Ответы [ 2 ]

0 голосов
/ 14 сентября 2018

Я тестирую экспериментальный вариант, и решил добавить его сюда для полноты.

Хранение запросов в самой БД

То есть я добавил в схему таблицу (которая не имеет отношения к другим таблицам, за исключением мета-уровня, на который эти другие таблицы являются ссылками в хранимых запросах. 1

Насколько хорошо это решает проблему

То, что он делает :

  1. отделение бизнес-логики от кода.
  2. позволяет мне довольно легко вырезать и вставлять запросы в тестовую среду (хотя мне приходится вводить значения параметров вручную).
  3. упрощает основную базу кода, так как код в вопросе заменяется на

    llaTbl = app.getFromDB('latlongByLocale',app.LocationDropDown.Value);

Вещи, которые не делают:

  1. Решить проблему «очень длинные строки или неприятный синтаксис». SQL также не имеет хорошего синтаксиса для многострочных строковых литералов.

Как это выглядит?

Пока я создаю базу данных вручную, поэтому queryStore.sql выглядит так:

-- Experimental idea to store the queries that the app will use on
-- the main database in an auxiliary table inside the database.

CREATE TABLE IF NOT EXISTS qstore ( name TEXT NOT NULL
                                  , nparam INT
                                  , querytext TEXT
                                  , comment TEXT
                                  );

INSERT INTO qstore VALUES ( 'localesInRegion', 1
                          , "SELECT locale.name as name FROM locale JOIN region ON locale.regionID = region.id WHERE region.name = '%s';"
                          , ""
                          );
INSERT INTO qstore VALUES ( 'regionMapData', 1
                          , "SELECT mapformat, maprights, mapfile FROM region WHERE name = '%s';"
                          , ""
                          );
INSERT INTO qstore VALUES ( 'localeMapData', 1
                          , "SELECT mapformat, maprights, mapfile FROM locale WHERE name = '%s';"
                          , ""
                          );                          
INSERT INTO qstore VALUES ( 'latlongByLocale', 1
                          , "SELECT latitude, longitude, altitude FROM locale  WHERE name = '%s';"
                          , ""
                          );

И поиск в matlab опосредуется набором функций, включая

function str = parameterizeQuery(app, qname, varargin)
% Retrieve parameterized query from the DB and perform string
% substitution.

% Get the querytext and expected number of parameters making sure the 
% result is non-null
q = sprintf("SELECT nparam, querytext FROM qstore WHERE name = '%s';",qname);
tbl = app.queryDB(q);
if isempty(tbl)
    error('storyboard2:parameterizeQuery:nomatch'...
        ,"No query stroed in the dabase by name '%s'.",qname);
end

nparam = tbl.nparam(1);
querytext = tbl.querytext{1};
if nparam ~= nargin - 2
    warning('storyboard2:parameterizeQuery:wrongParameterCount'...
        ,"The number of parameters passed does not match the number in the query retrieved. Hoping for the best.");
end
% insert parameters
str = sprintf(querytext,varargin{:});
end

function tbl = getFromDB(app, qname, varargin)
% A pass-through convenience function that calls
% parameterizeQuery() and passes the result to
% queryDB()
str = app.parameterizeQuery(qname, varargin{:});
tbl = app.queryDB(str);
end

1 Я немного волнуюсь, что это пример каждой проблемы, которая выглядит так, как будто она соответствует моему молотку, или как-то так.

0 голосов
/ 14 сентября 2018

Вы можете создать класс, подобный классу CRUDservice, а затем централизовать все ваши SQL-запросы. Поступая так, вы не будете огорчены ловушками, связанными с распределением запросов по всему коду.

Другим вариантом будет разгрузка ваших запросов в функции и хранимые процедуры, но я не верю, что это возможно в sqlite

...