С++ + SQL
От: Мёртвый Даун Россия  
Дата: 01.10.15 18:59
Оценка:
Всем привет!

Собсна, вот какая штука. Достался мне один очень большой и очень лохматый проект лохматых годов. Который пока требуется "причесать", потом уже думать рефакторинг и прочие. Проект рабочий и используется.
Сам проект — толстый GUI клиент к СУБД. По всему коду тьма развесистых строк вида

std::string strQuery = "SELECT ... (бла-бла-бла)... %ll, ... %d"; // встречаются очень длинные строки запросы на два десятка строк кода в редакторе


Трогать всё это рекомендуется осторожно.
Какую та часть потихоньку переношу в процедуры и функции в БД.
Есть какой та best practice как и где всё это хранить, SQL строки, что ли?! Может в ресурсах? Но тогда искать их там и править еще сложней будет, т.к. не будет ясен контекст.

Кто как делает?! Какие рекомендации?

P.S. Т.к. мопед не мой, и особого опыта написания и проектирования больших проектов работающих с СУБД не имею.
Только Путин, и никого кроме Путина! О Великий и Могучий Путин — царь на веки веков, навсегда!
Смотрю только Соловьева и Михеева, для меня это самые авторитетные эксперты.
КРЫМ НАШ! СКОРО И ВСЯ УКРАИНА БУДЕТ НАШЕЙ!
c++ sql
Re: С++ + SQL
От: BlackEric http://black-eric.lj.ru
Дата: 01.10.15 19:43
Оценка: +1
Здравствуйте, Мёртвый Даун, Вы писали:

МД>P.S. Т.к. мопед не мой, и особого опыта написания и проектирования больших проектов работающих с СУБД не имею.


Хранить как строковые константы. Можно в том же файле где используется, а можно завести отдельный.
https://github.com/BlackEric001
Re: С++ + SQL
От: dya-victor Россия  
Дата: 01.10.15 21:31
Оценка: +1
Здравствуйте, Мёртвый Даун, Вы писали:

МД>Всем привет!


МД>Какую та часть потихоньку переношу в процедуры и функции в БД.


Вот этого я бы делать не стал. Минусы: тестировать сложней, сложность вследствие размазанности кода возрастает, зависимость от субд возрастает, версионность кода поддерживать сложней.
Re[2]: С++ + SQL
От: Мёртвый Даун Россия  
Дата: 02.10.15 01:24
Оценка:
Здравствуйте, dya-victor, Вы писали:

DV>Здравствуйте, Мёртвый Даун, Вы писали:


МД>>Всем привет!


МД>>Какую та часть потихоньку переношу в процедуры и функции в БД.


DV>Вот этого я бы делать не стал. Минусы: тестировать сложней, сложность вследствие размазанности кода возрастает, зависимость от субд возрастает, версионность кода поддерживать сложней.


Согласен в какой та степени. Но мой намёк и посыл был: как бы вообще избавиться от SQL строк в текстах программы?
Только Путин, и никого кроме Путина! О Великий и Могучий Путин — царь на веки веков, навсегда!
Смотрю только Соловьева и Михеева, для меня это самые авторитетные эксперты.
КРЫМ НАШ! СКОРО И ВСЯ УКРАИНА БУДЕТ НАШЕЙ!
Re[2]: С++ + SQL
От: Мёртвый Даун Россия  
Дата: 02.10.15 01:30
Оценка:
Здравствуйте, BlackEric, Вы писали:

BE>Здравствуйте, Мёртвый Даун, Вы писали:


МД>>P.S. Т.к. мопед не мой, и особого опыта написания и проектирования больших проектов работающих с СУБД не имею.


BE>Хранить как строковые константы. Можно в том же файле где используется, а можно завести отдельный.


Т.е. все SQL строки-запросы всё таки хранить в тексте программы? Чтото типа:

//file.h

class A
{
...
};

//file.cpp

namespace
{
const char* szQuery1 = "SELECT...";
const char* szQuery2 = "SELECT...";
...
const char* szQueryN = "SELECT...";
}

A::A()
{
// используем SQL
...
}


Ну, пока что действительно, мне видится это правильным решением.
Только Путин, и никого кроме Путина! О Великий и Могучий Путин — царь на веки веков, навсегда!
Смотрю только Соловьева и Михеева, для меня это самые авторитетные эксперты.
КРЫМ НАШ! СКОРО И ВСЯ УКРАИНА БУДЕТ НАШЕЙ!
Re[3]: С++ + SQL
От: dya-victor Россия  
Дата: 02.10.15 06:04
Оценка:
Здравствуйте, Мёртвый Даун, Вы писали:

DV>>Вот этого я бы делать не стал. Минусы: тестировать сложней, сложность вследствие размазанности кода возрастает, зависимость от субд возрастает, версионность кода поддерживать сложней.


МД>Согласен в какой та степени. Но мой намёк и посыл был: как бы вообще избавиться от SQL строк в текстах программы?


BlackEric до меня ответил, поэтому я не стал ) Можно еще рассмотреть внешний файл, если есть необходимость менять запросы на лету.
Отредактировано 02.10.2015 6:06 dya-victor . Предыдущая версия .
Re: С++ + SQL
От: szag  
Дата: 02.10.15 06:28
Оценка:
Здравствуйте, Мёртвый Даун, Вы писали:

МД>Всем привет!


МД>Собсна, вот какая штука. Достался мне один очень большой и очень лохматый проект лохматых годов. Который пока требуется "причесать", потом уже думать рефакторинг и прочие. Проект рабочий и используется.

МД>Сам проект — толстый GUI клиент к СУБД. По всему коду тьма развесистых строк вида

МД>
МД>std::string strQuery = "SELECT ... (бла-бла-бла)... %ll, ... %d"; // встречаются очень длинные строки запросы на два десятка строк кода в редакторе
МД>


МД>Трогать всё это рекомендуется осторожно.

МД>Какую та часть потихоньку переношу в процедуры и функции в БД.
МД>Есть какой та best practice как и где всё это хранить, SQL строки, что ли?! Может в ресурсах? Но тогда искать их там и править еще сложней будет, т.к. не будет ясен контекст.

МД>Кто как делает?! Какие рекомендации?


МД>P.S. Т.к. мопед не мой, и особого опыта написания и проектирования больших проектов работающих с СУБД не имею.


Я бы посмотрел в сторону написания ORM'а и полного отказа от хранения sql строк в коде.
Re: С++ + SQL
От: PM  
Дата: 02.10.15 07:58
Оценка: +1
Здравствуйте, Мёртвый Даун, Вы писали:

МД>
МД>std::string strQuery = "SELECT ... (бла-бла-бла)... %ll, ... %d"; // встречаются очень длинные строки запросы на два десятка строк кода в редакторе
МД>


Елси это реальная строчка из проекта, то для меня подозрительны тут 2 вещи:

1) Использование типа std::string вместо строковых литералов char const* const. Зачем загонять строку запроса в контейнер, содержимое которого можно поменять во время исполнения программы? Ни разу не сталкивался с такой необходимостью.

2) С какой целью используются флаги форматирования %ll, %d и не грозит ли это SQL injection? Может быть, для таких запросов нужно использовать prepared statements.

МД>Трогать всё это рекомендуется осторожно.


Это самое главное условие. Хорошо, если доступ к БД сгруппирован в отдельном слое классов или функций. Тогда неважно как хранятся запросы в программе, они ведь не будут видимы остальному коду.
Re[2]: С++ + SQL
От: BlackEric http://black-eric.lj.ru
Дата: 02.10.15 08:22
Оценка:
Здравствуйте, PM, Вы писали:

PM>1) Использование типа std::string вместо строковых литералов char const* const. Зачем загонять строку запроса в контейнер, содержимое которого можно поменять во время исполнения программы? Ни разу не сталкивался с такой необходимостью.


Очевидно, запрос формируется в run time. Это нормальная практика.

PM>2) С какой целью используются флаги форматирования %ll, %d и не грозит ли это SQL injection? Может быть, для таких запросов нужно использовать prepared statements.


Там могут поставляться имена полей и таблиц для запроса. prepared statements тут не помогут.
https://github.com/BlackEric001
Re: С++ + SQL
От: Igore Россия  
Дата: 02.10.15 08:30
Оценка: +1
Здравствуйте, Мёртвый Даун, Вы писали:

МД>Какие рекомендации?

1) Спрятать всё за DAO.
2) Попробовать odb
Re: С++ + SQL
От: uzhas Ниоткуда  
Дата: 02.10.15 09:02
Оценка: +1
Здравствуйте, Мёртвый Даун, Вы писали:

МД> Сам проект — толстый GUI клиент к СУБД.

МД> // встречаются очень длинные строки запросы на два десятка строк кода в редакторе

МД>Кто как делает?! Какие рекомендации?


рекомендую все переносить в базу данных (процедуры, вьюхи). задача клиента будет подставить правильные аргументы при вызове. при необходимости можно использовать динамические запросы на стороне базы (см. https://dev.mysql.com/doc/refman/5.0/en/sql-syntax-prepared-statements.html )
можно будет менять запросы в базе без перекомпиляции клиента

если же текст запросов не получается выкинуть из C++ кода, то желательно изолировать возню с ними : перетащить форматирование запросов в отдельный файл. при желании код форматирования можно будет покрыть тестами
пример (мета-код):
//query.h
std::string ComposeQueryToGetCustomers(int ageFilter);


//query.cpp
std::string ComposeQueryToGetCustomers(int ageFilter)
{
  //fight with sprintf, long queries and SQL injections
  return sprintf("SELECT * FROM Customers WHERE Age > %d", ageFilter);
}


//FatGUI.cpp
OnClick()
{
  int ageFilter = intBox.Value;
  std::string q = ComposeQueryToGetCustomers(ageFilter);
  std::vector<Customer> c = FetchRecords<Customer>(query, ConvertRecordSetToCustomer);
}


успехов
Re[2]: С++ + SQL
От: Мёртвый Даун Россия  
Дата: 02.10.15 09:40
Оценка:
Здравствуйте, Igore, Вы писали:

I>Здравствуйте, Мёртвый Даун, Вы писали:


МД>>Какие рекомендации?

I>1) Спрятать всё за DAO.
Ну понятно что можно каких угодно прослоек наделать...
I>2) Попробовать odb
А вот за это спасибо! буду посмотреть!
Только Путин, и никого кроме Путина! О Великий и Могучий Путин — царь на веки веков, навсегда!
Смотрю только Соловьева и Михеева, для меня это самые авторитетные эксперты.
КРЫМ НАШ! СКОРО И ВСЯ УКРАИНА БУДЕТ НАШЕЙ!
Re[3]: С++ + SQL
От: PM  
Дата: 02.10.15 10:07
Оценка: 1 (1) +1
Здравствуйте, Мёртвый Даун, Вы писали:

МД>>>Какие рекомендации?

I>>1) Спрятать всё за DAO.
МД>Ну понятно что можно каких угодно прослоек наделать...
I>>2) Попробовать odb
МД>А вот за это спасибо! буду посмотреть!

Насколько я помню, ODB использует свой препроцессор чтобы обойти отсутствие compile-time reflection в языке, что может быть довольно радикально для давно существующего проекта.

Я использовал более классический подход — безопасные C++ обертки типа SOCI, cppDB, edba
Re[3]: С++ + SQL
От: AlexGin Беларусь  
Дата: 03.10.15 10:52
Оценка:
Здравствуйте, Мёртвый Даун, Вы писали:

МД>Т.е. все SQL строки-запросы всё таки хранить в тексте программы? Чтото типа:

..............................
МД>Ну, пока что действительно, мне видится это правильным решением.

Не уверен, что это решение верное.
В наших проектах я сделал подгрузку файлов *.sql из каталога SQL — там хранятся все эти строки "SELECT...FROM...".
Каталог SQL — там же, где и исполнимый (*.exe файл) модуль приложения.
Явная выгода- если надо что-то менять, не нужно трогать: ни код приложения, ни саму БД.
Re[4]: С++ + SQL
От: PM  
Дата: 03.10.15 13:19
Оценка: +3
Здравствуйте, AlexGin, Вы писали:

AG>Не уверен, что это решение верное.

AG>В наших проектах я сделал подгрузку файлов *.sql из каталога SQL — там хранятся все эти строки "SELECT...FROM...".
AG>Каталог SQL — там же, где и исполнимый (*.exe файл) модуль приложения.
AG>Явная выгода- если надо что-то менять, не нужно трогать: ни код приложения, ни саму БД.

Мне просто любопытно, был ли хоть один случай когда после изменения SQL запроса действительно не пришлось менять ни схему БД, ни код приложения?
Re[5]: С++ + SQL
От: dya-victor Россия  
Дата: 04.10.15 11:13
Оценка:
Здравствуйте, PM, Вы писали:

PM>Мне просто любопытно, был ли хоть один случай когда после изменения SQL запроса действительно не пришлось менять ни схему БД, ни код приложения?


В прошлом проекте время от времени хинты разные добавляли, например. И потом, один и тот же набор данных можно получить разными запросами.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.