Шаблонизация SQL еще один велосипед             Алексей Романчук
Обо мне
О чем будем говорить?
Для кого• Разработчики• Много SQL• Динамический SQL
Для чего стараемся?• Сложные выборки• Отчеты• Любые SQL запросы
Очень простой пример
Очень простой пример
Простой пример
Простой пример
Простой пример
Пример
Пример
Не такой простой пример
Не такой простой пример
Не такой простой пример
Не такой простой пример
Пример почти из жизни
Пример почти из жизни
Почувствуйте разницу
Недостатки inline подхода
Недостатки inline подхода• Невозможность ограничить текст запроса• Дублирование логики в запросах и в  параметрах• Часть с...
Как происходит разработка SQL•   Получить SQL из кода•   Заменить «?» на значения•   Внести изменения в SQL редакторе•   В...
Что делать?
Шаблонизация FTW
Шаблонизация FTW
Шаблонизация FTW
Стало ли проще?
Стало ли проще?
Что дает шаблонизация?• Возможность ограничить текст запроса• Текст первичен• Многострочные запросы легко копировать
Какой должна быть разработка SQL•   Получить SQL из кода•   Заменить «?» на значения•   Внести изменения в SQL редакторе• ...
Наконец!
Требования к шаблонизатору• Шаблон должен быть максимально  валидным SQL• Возможность «выключить» ненужный join• Поддержка...
Где хранить метаданные чтобышаблон оставался валидным SQL?
XDoclet        Java source*.hbm                 javac   .class
И не только•   Javadoc•   Google Closure Compiler for JS•   Eclipse localization (//$NON-NLS-1$)•   UML Doclet
Шаблонизатор               ШаблонSQL редактор            Движок       Запрос                        Parameters
Шаблонизатор в двух словах• Элемент• Дерево
Элемент    Единственная языковая конструкция       /*id(int */1045/*)*/ /*cond(*/inner join orders o…/*)*/• Имя• Тип• Знач...
Варианты синтаксиса элемента•   /*{name*/1045/*}*/•   /*<name type=“int”>*/1045/*</name>*/•   /*<name:int*/1045/*>*/•   /*...
Работа с элементом• По умолчанию элемент «выключен»• Явное задание значение и проверка типа• Использование значения из шаб...
Простой примерselect c.id, c.namefrom company cwhere c.name ilike ‘2 gis’
Простой примерselect c.id, c.namefrom company cwhere c.name ilike /*name(*/‘2 gis%’/*)*/
Простой примерTemplate t = new Template(“…”);t.assignValue(“name”, “Sbertech%”);
Простой примерselect c.id, c.namefrom company cwhere c.name ilike ‘Sbertech%’
Дерево• Шаблон – дерево текста и элементов (xml)• По умолчанию элемент «выключен»• Включение элемента включает элемент  ро...
Дерево /*filter(*/where name = /*name(*/’Jack’/*))*/• Шаблон –filter    • name
Пример с joinselect distinct c.id, c.namefrom company cinner join comp_office co on co.comp_id = c.idwhere c.name ilike 2 ...
Пример с joinselect distinct c.id, c.namefrom company cinner join comp_office co on co.comp_id = c.idwhere c.name ilike /*...
Пример с joinselect distinct c.id, c.namefrom company cinner join comp_office co on co.comp_id = c.idwhere c.name ilike /*...
Пример с joinselect distinct c.id, c.namefrom company c/*office(*/inner join comp_office co on co.comp_id = c.id/*)*/where...
Пример с join• Шаблон  – office (join)  – name  – office (where)     • country
Пример с joinTemplate t = new Template(“…”);t.assignValue(“name”, “Sbertech%”);
Пример с joinselect distinct c.id, c.namefrom company cwhere c.name ilike ‘Sbertech%’
Пример с joinTemplate t = new Template(“…”);t.assignValue(“name”, “Sbertech%”);t.assignValue(“country”, “Rus%”);
Пример с joinselect distinct c.id, c.namefrom company cinner join comp_office co on co.comp_id = c.idwhere c.name ilike ‘S...
Реальный примерselect distinct c.id, c.namefrom company cinner join comp_office co on co.comp_id = c.idinner join orders o...
Реальный примерselect distinct c.id, c.namefrom company cinner join comp_office co on co.comp_id = c.idinner join orders o...
Реальный примерselect distinct c.id, c.namefrom company cinner join comp_office co on co.comp_id = c.idinner join orders o...
Реальный примерselect distinct c.id, c.namefrom company cinner join comp_office co on co.comp_id = c.id/*active(*/inner jo...
Реальный примерselect distinct c.id, c.namefrom company c/*office(*/inner join comp_office co on co.comp_id = c.id/*)*//*a...
Реальный пример• Шаблон  –   office (join)  –   active (join)  –   name  –   office (where)       • country       • city  ...
Реальный примерTemplate t = new Template(“…”);t.assignValue(“name”, “2 gis”);t.assignValue(“country”, “russia”);t.assignVa...
Что дает нам велосипед?•   Ограничение текста запроса•   Позволяет контролировать тип параметров•   Позволяет не удалять з...
Что дальше?•   POJO как конфигурация запроса•   Как получить PreparedStatement, а не текст?•   “Reflection” API и автотест...
Вместо заключения•   Заимствуйте в смежных областях•   Сфокусируйтесь на узкой задаче•   Придумывайте простое решение•   D...
?              @1eshawww.linkedin.com/in/alexeyromanchuk   alexey.romanchuk@gmail.com
Реализации         https://github.com/seratch/scalikejdbc        https://github.com/jbzdak/query-builderhttp://amateras.so...
Upcoming SlideShare
Loading in …5
×

Шаблонизация sql, или история еще одного велосипеда, в трех частях, Алексей Романчук (СберБанк Технологии)

937 views

Published on

- Часть первая. SQL и программный код - как, имея очень простую задачу, получить очень плохое решение.
- Антракт. Почему нам неудобно писать SQL
- Часть вторая. Почему существующие решения - отстой.
- Антракт. Мечты об идеальном инструменте разработки SQL
- Часть третья. История велосипеда, или свой инструмент самый лучший

0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
937
On SlideShare
0
From Embeds
0
Number of Embeds
259
Actions
Shares
0
Downloads
12
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Шаблонизация sql, или история еще одного велосипеда, в трех частях, Алексей Романчук (СберБанк Технологии)

  1. 1. Шаблонизация SQL еще один велосипед Алексей Романчук
  2. 2. Обо мне
  3. 3. О чем будем говорить?
  4. 4. Для кого• Разработчики• Много SQL• Динамический SQL
  5. 5. Для чего стараемся?• Сложные выборки• Отчеты• Любые SQL запросы
  6. 6. Очень простой пример
  7. 7. Очень простой пример
  8. 8. Простой пример
  9. 9. Простой пример
  10. 10. Простой пример
  11. 11. Пример
  12. 12. Пример
  13. 13. Не такой простой пример
  14. 14. Не такой простой пример
  15. 15. Не такой простой пример
  16. 16. Не такой простой пример
  17. 17. Пример почти из жизни
  18. 18. Пример почти из жизни
  19. 19. Почувствуйте разницу
  20. 20. Недостатки inline подхода
  21. 21. Недостатки inline подхода• Невозможность ограничить текст запроса• Дублирование логики в запросах и в параметрах• Часть свойств в тексте запроса, часть как явные параметры• Сложность разработки и отладки SQL
  22. 22. Как происходит разработка SQL• Получить SQL из кода• Заменить «?» на значения• Внести изменения в SQL редакторе• Внедрить изменения в код или «оживить» написанный SQL целиком
  23. 23. Что делать?
  24. 24. Шаблонизация FTW
  25. 25. Шаблонизация FTW
  26. 26. Шаблонизация FTW
  27. 27. Стало ли проще?
  28. 28. Стало ли проще?
  29. 29. Что дает шаблонизация?• Возможность ограничить текст запроса• Текст первичен• Многострочные запросы легко копировать
  30. 30. Какой должна быть разработка SQL• Получить SQL из кода• Заменить «?» на значения• Внести изменения в SQL редакторе• Внедрить изменения в код или «оживить» написанный SQL целиком
  31. 31. Наконец!
  32. 32. Требования к шаблонизатору• Шаблон должен быть максимально валидным SQL• Возможность «выключить» ненужный join• Поддержка типизированных параметров• Автоматическое включение joinов
  33. 33. Где хранить метаданные чтобышаблон оставался валидным SQL?
  34. 34. XDoclet Java source*.hbm javac .class
  35. 35. И не только• Javadoc• Google Closure Compiler for JS• Eclipse localization (//$NON-NLS-1$)• UML Doclet
  36. 36. Шаблонизатор ШаблонSQL редактор Движок Запрос Parameters
  37. 37. Шаблонизатор в двух словах• Элемент• Дерево
  38. 38. Элемент Единственная языковая конструкция /*id(int */1045/*)*/ /*cond(*/inner join orders o…/*)*/• Имя• Тип• Значение
  39. 39. Варианты синтаксиса элемента• /*{name*/1045/*}*/• /*<name type=“int”>*/1045/*</name>*/• /*<name:int*/1045/*>*/• /*name(int */1045/*)*/
  40. 40. Работа с элементом• По умолчанию элемент «выключен»• Явное задание значение и проверка типа• Использование значения из шаблона
  41. 41. Простой примерselect c.id, c.namefrom company cwhere c.name ilike ‘2 gis’
  42. 42. Простой примерselect c.id, c.namefrom company cwhere c.name ilike /*name(*/‘2 gis%’/*)*/
  43. 43. Простой примерTemplate t = new Template(“…”);t.assignValue(“name”, “Sbertech%”);
  44. 44. Простой примерselect c.id, c.namefrom company cwhere c.name ilike ‘Sbertech%’
  45. 45. Дерево• Шаблон – дерево текста и элементов (xml)• По умолчанию элемент «выключен»• Включение элемента включает элемент родителя
  46. 46. Дерево /*filter(*/where name = /*name(*/’Jack’/*))*/• Шаблон –filter • name
  47. 47. Пример с joinselect distinct c.id, c.namefrom company cinner join comp_office co on co.comp_id = c.idwhere c.name ilike 2 gis%’and co.country ilike ‘russia%’
  48. 48. Пример с joinselect distinct c.id, c.namefrom company cinner join comp_office co on co.comp_id = c.idwhere c.name ilike /*name(*/2 gis%’/*)*/and co.country ilike /*country(*/ ‘russia%’/*)*/
  49. 49. Пример с joinselect distinct c.id, c.namefrom company cinner join comp_office co on co.comp_id = c.idwhere c.name ilike /*name(*/2 gis%’/*)*//*office(*/and co.country ilike /*country(*/ ‘russia%’/*))*/
  50. 50. Пример с joinselect distinct c.id, c.namefrom company c/*office(*/inner join comp_office co on co.comp_id = c.id/*)*/where c.name ilike /*name(*/2 gis%’/*)*//*office(*/and co.country ilike /*country(*/ ‘russia%’/*))*/
  51. 51. Пример с join• Шаблон – office (join) – name – office (where) • country
  52. 52. Пример с joinTemplate t = new Template(“…”);t.assignValue(“name”, “Sbertech%”);
  53. 53. Пример с joinselect distinct c.id, c.namefrom company cwhere c.name ilike ‘Sbertech%’
  54. 54. Пример с joinTemplate t = new Template(“…”);t.assignValue(“name”, “Sbertech%”);t.assignValue(“country”, “Rus%”);
  55. 55. Пример с joinselect distinct c.id, c.namefrom company cinner join comp_office co on co.comp_id = c.idwhere c.name ilike ‘Sbertech%’and co.country ilike ‘Rus%’
  56. 56. Реальный примерselect distinct c.id, c.namefrom company cinner join comp_office co on co.comp_id = c.idinner join orders o on o.comp_id = c.idwhere c.name ilike 2 gis%and co.country ilike russia%and co.city ilike novosibirsk%and co.street ilike marks%and o.date > currenttime - 6 month::intervallimit 10 offset 5
  57. 57. Реальный примерselect distinct c.id, c.namefrom company cinner join comp_office co on co.comp_id = c.idinner join orders o on o.comp_id = c.idwhere c.name ilike /*name(*/2 gis%’/*)*/and co.country ilike /*country(*/russia% /*)*/and co.city ilike /*city(*/novosibirsk%’/*)*/and co.street ilike /*street(*/marks%/*)*/and o.date > currenttime - 6 month::intervallimit /*limit(int*/10/*)*/ offset /*offset(int*/5/*)*/
  58. 58. Реальный примерselect distinct c.id, c.namefrom company cinner join comp_office co on co.comp_id = c.idinner join orders o on o.comp_id = c.idwhere c.name ilike /*name(*/2 gis%’/*)*/and co.country ilike /*country(*/russia% /*)*/and co.city ilike /*city(*/novosibirsk%’/*)*/and co.street ilike /*street(*/marks%/*)*//*active(*/and o.date > currenttime - 6 month::interval/*)*/limit /*limit(int*/10/*)*/ offset /*offset(int*/5/*)*/
  59. 59. Реальный примерselect distinct c.id, c.namefrom company cinner join comp_office co on co.comp_id = c.id/*active(*/inner join orders o on o.comp_id = c.id/*)*/where c.name ilike /*name(*/2 gis%’/*)*/and co.country ilike /*country(*/russia% /*)*/and co.city ilike /*city(*/novosibirsk%’/*)*/and co.street ilike /*street(*/marks%/*)*//*active(*/and o.date > currenttime - 6 month::interval/*)*/limit /*limit(int*/10/*)*/ offset /*offset(int*/5/*)*/
  60. 60. Реальный примерselect distinct c.id, c.namefrom company c/*office(*/inner join comp_office co on co.comp_id = c.id/*)*//*active(*/inner join orders o on o.comp_id = c.id/*)*/where c.name ilike /*name(*/2 gis%’/*)*//*office(*/and co.country ilike /*country(*/russia% /*)*/and co.city ilike /*city(*/novosibirsk%’/*)*/and co.street ilike /*street(*/marks%/*))*//*active(*/and o.date > currenttime - 6 month::interval/*)*/limit /*limit(int*/10/*)*/ offset /*offset(int*/5/*)*/
  61. 61. Реальный пример• Шаблон – office (join) – active (join) – name – office (where) • country • city • street – active (where) – limit и offset
  62. 62. Реальный примерTemplate t = new Template(“…”);t.assignValue(“name”, “2 gis”);t.assignValue(“country”, “russia”);t.assignValue(“city”, “novosibirsk”);t.assignValue(“street”, “marksa”);t.assignValue(“limit”, 10);t.assignValue(“offset”, 5);t.enable(“active”);
  63. 63. Что дает нам велосипед?• Ограничение текста запроса• Позволяет контролировать тип параметров• Позволяет не удалять значения параметров• Позволяет разрабатывать и использовать в программе один и тот же шаблон
  64. 64. Что дальше?• POJO как конфигурация запроса• Как получить PreparedStatement, а не текст?• “Reflection” API и автотесты• IDE plugins
  65. 65. Вместо заключения• Заимствуйте в смежных областях• Сфокусируйтесь на узкой задаче• Придумывайте простое решение• DSL FTW
  66. 66. ? @1eshawww.linkedin.com/in/alexeyromanchuk alexey.romanchuk@gmail.com
  67. 67. Реализации https://github.com/seratch/scalikejdbc https://github.com/jbzdak/query-builderhttp://amateras.sourceforge.jp/site/mirage/welcome.html

×