Хотелось рассказать о том, как многими любимый Sublime Text можно использовать как неплохое средство для разработки на PL/SQL.

Хотелось бы начать с того, для чего нужен был этот велосипед, ведь есть вроде бы много других IDE для работы с SQL и в частности Oracle PL/SQL, такие как Toad for Oracle, SQL Navigator, PL/SQL Developer и даже бесплатный Oracle SQL Developer, однако у большинства из них есть несколько недостатков по сравнению с текстовыми редакторами типа Emacs, SciTe, Vim, Notepad++, Sublime Text и т.д.

Перечислю некоторые из них, данный список сугубо субъективный:

  • “Тяжеловесность” каждой IDE, это выражается не только в размере дистрибутива, но и общими ощущениями, наличием множества не нужных функций, кнопок, отзывчивостью и т.д.
  • Большинство приемлемых IDE являются платными, или условно бесплатными с ограниченным функционалом.
  • Хотелось бы кроссплатформенность, под это требование из приведенных IDE попадает только Oracle SQL Developer.
  • Функционал редактирования текста. В большинстве из них есть только базовые методы по работе с текстом: это набор текста, copy-paste, подсветка синтаксиса. Ни о каких “CTRL+D” как Sublime Text речи и не идет.
  • Простота расширения, практически все IDE закрыты, никакой поддержки самописных пагинов и т.д.

Есть еще один пункт, но он больше относится к организации проектов и задач на рабочем месте. Хотелось бы немного затронуть эту тему, так как организация на проектах наложила свой отпечаток на настройку Sublime Text.

У нас на работе есть одно правило — “В исходниках правда”. Т.е. мы работаем непосредственно с файлами-исходниками, а не в самой базе. В первую очередь потому что нам нужна версионность, да и систему контроля версий исходников ни кто не отменял. Таким образом мы всегда можем посмотреть что сейчас на базе и что у нас в SVN, чтобы понять в чем расхождения, если клиент например сам залез в базу что-то ручками подправил, например в процедуре или пакете. Так же у нас на работе все катается через sqlplus.

На нашем проекте принята определенная структура хранения исходников, где в каждом файле хранятся свои объекты. Н-р: таблицы по задаче лежат в папке “tables”, имя файла имеет название таблицы “table_contract.tab.sql”, представления лежат в папке “views” и файлы имеют название “vv_table_contract.sql”, пакеты лежат в папке “packages” и файлы пакетов имеют названия “contract_utl_spec.sql” и “contract_utl_body.sql” ну и так далее, основная концепция понятна и проста.

Если будет интересно как у нас организована структура, SVN, выпуск версий, обновление клиентов и т.д. с учетом того что мы пишем фактически только на SQL и PL/SQL, то могу попробовать написать на эту тему статью, хотя про организацию SQL кода на Хабре статьи были.

Подсветка синтаксиса и объектов БД


Начнем с простого — это подсветка синтаксиса. Речь пойдет не о цветовой палитре, это дело личное, а подсвечивать мы будем объекты БД, т.к. это удобно и код становиться более ясным и понятным. Вот пример того как это выглядит:



Для подсветки объектов я использую файл (PL_SQL (Oracle).tmLanguage) для подсветки синтаксиса из плагина github.com/bizoo/OracleSQL, о котором речь пойдет чуть позже.

В файле добавляем новый тег:

<dict>
	<key>match</key>
	<string>(?i)\b()\b</string>
	<key>name</key>
	<string>dbobject.oracle</string>
</dict>

Где между скобок добавляем новые объекты БД для подсветки. У меня это таблицы и представления. Список объектов я получаю простым скриптом:

select lower(rtrim(xmlcast(xmlagg(xmlelement(e,object_name,'|') order by object_name) as clob),'|')) 
  from all_objects
 where owner = user
   and object_type in ('TABLE', 'VIEW')
 order by object_name

Осталось настроить цвет объектов, делается это в файле вашей темы ..\Packages\Color Scheme — Default\YourTheme.tmTheme. Добавляем в файл:

<dict>
	<key>name</key>
	<string>String</string>
	<key>scope</key>
	<string>dbobject.oracle</string>
	<key>settings</key>
	<dict>
		<key>foreground</key>
		<string>#7F7F00</string>
	</dict>
</dict>

Всплывающая подсказка по объектам


Для настройки всплывающей подсказки по объектам по сочетанию ctrl+space, а так же для помощи в завершении слов или названий объектов был создан отдельный файл “db_objects.sublime-completions”, выглядит он примерно вот так:

{        "scope": "source.plsql.oracle",
        "completions":
        [
{"trigger": "abon_device\tTABLE", "contents": "abon_device"},
{"trigger": "abon_device_conflict\tTABLE", "contents": "abon_device_conflict"},
{"trigger": "abon_device_err\tTABLE", "contents": "abon_device_err"}
…
]
}

Это стандартный формат для Sublime Text, для срабатывания по сочетании Ctrl+Space. Необходимые данные я достаю примерно таким же скриптом как и данные для подсветки объектов БД.

select '{"trigger": "'||object_name||'\t'||object_type||'", "contents": "'||object_name||'"},' 
  from all_objects
 where owner = user
   and object_type in ('TABLE', 'VIEW')
 order by object_name

Для помощи в завершении слов или названии объектов БД я использую плагин “All autocomplete” — данный плагин просматривает все открытые вкладки, выбирает в них все слова, исключая дубли и показывает тоже в подсказке. В итоге выглядит это примерно вот так.



Система контроля версий


В качестве системы контроля версий мы используем SVN. В репозитарии у Sublime Text есть много разных плагинов, я остановился на “TourtoiseSVN”, простой, необходимые базовые операции выполняет Commit, Update, Show log, Diff с соответствующими хот-кеями (Alt+C, Alt+L, Alt+U), а для более сложных вещей, типа тагирования или слияния есть одноименный клиент.

Поиск по объектам


Для поиска по объектам в задаче(проекте) я использую как стандартный функционал Sublime Text — Goto Anything, так и небольшой плагин который сам написал. Плагин очень простой и фактически немного дополняет стандартный Goto Anything тем что в поле ввода сразу же добавляет слово на котором стоит курсор. Код плагина:

import sublime, sublime_plugin
import os.path, string
import re

class MeOpenCommand(sublime_plugin.WindowCommand):
    def run(self):
        view = self.window.active_view()
        for region in view.sel():
            if region.begin() == region.end():
                word = view.word(region)
            else:
                word = region
            if not word.empty():
                keyword = view.substr(word)
        self.window.run_command("show_overlay", {"overlay": "goto", "show_files": "true", "text": keyword})

С учетом того как у нас организованна структура файлов проекта, описанная в начале статьи я получил функционал для быстрого доступа к необходимому мне объекту.



Выполнение кода


Теперь переходим к самому интересному, это выполнение/прокатка скриптов из Sublime Text. Для выполнения этих целей я использую модифицированный под свои нужды и требования пакет github.com/bizoo/OracleSQL. Модификации были сделаны в основном в плане упрощения плагина, т.к. сам плагин тоже немного заточен под нужды автора. Сейчас плагин выглядит вот так:

oracle_exec.py

import sublime, sublime_plugin
execcmd = __import__("exec")
import re
import os
import thread
import subprocess

class OracleExecCommand(execcmd.ExecCommand):
    def run(self, dsn="", **kwargs):
# Передаем параметры для прокатки скрипта, sqlplus.exe, строка подключения, имя файла активной вкладки в Sublime Text
        cmd = ["sqlplus.exe", dsn, "@", self.window.active_view().file_name()]
# Выполняем команду и регулярное выражение для поиска ошибок по F4 и Shift+F4 после прокатки скрипта, что тоже встроено в Sublime Text.
        super(OracleExecCommand, self).run(cmd, "($file)(^([0-9]+))", "(^ORA-([0-9]+)(.+)(.+)$)|(PLS-([0-9]+)(.+)$)", **kwargs)

oracle_functions.py

import sublime, sublime_plugin

# список баз и схем которые вам необходимы и с которыми вы работаете, где первый параметр это название какое вам захочется, а 2й параметр это стандартная строка для подключения через sqlplus
instance_list = [["DB1", "user/pass@tnsname"], ["DB2", "user/pass@tnsname"]]

class OracleExecuteListCommand(sublime_plugin.WindowCommand):
    def run(self, *args, **kwargs):
        self.window.show_quick_panel(instance_list, self._quick_panel_callback)
    def _quick_panel_callback(self, index):
        if (index > -1):
            self.window.run_command("oracle_exec", {"dsn": instance_list[index][1]})

Выглядит это следующим образом.



Таким же образом можно выполнят и простые SQL запросы. Единственное для этого необходимо сделать настройки sqlplus, для этого можно попробовать использовать login.sql, который должен срабатывать каждый раз при подключении через sqlplus. Я же не стал этого делать я просто сделал snippet на необходимые мне команды или вообще можно держать один файл для этих целей где уже все записано заранее.



Итог


В качестве итога я получил быстрый, легкий, бесплатный, кроссплатформенный и легко расширяемый инструмент для разработки PL/SQL, который так же отлично вписывается в правила на работе.

P.S.: Я понимаю что есть недостатки у данной “сборки”, однако для меня они не критичны, да и если побороть свою лень можно дописывать и дальше.

Комментарии (11)


  1. AlanDenton
    02.12.2015 13:41

    очень интересно было прочитать Вашу статью. спасибо :)

    “Тяжеловесность” каждой IDE, это выражается не только в размере дистрибутива, но и общими ощущениями, наличием множества не нужных функций

    можно с Вами поспорить… как насчет Database Explorer...? его полноценной реализации в Sublime нет. А это очень важный компонент интерфейса для удобной разработки.

    Большинство приемлемых IDE являются платными, или условно бесплатными с ограниченным функционалом

    Готов с Вами не согласиться… Например русская dbForge бесплатная для некоммерческого использования и в учебных целях. А если нужна коммерческая лицензия, то проблем с ее получением для русскоязычной аудитории никогда не было.

    И еще один вопрос… Вы в будущем планируете сделать похожий плагин для SQL Server. Я бы с радостью попробовал :)


    1. meiko
      02.12.2015 14:38

      Что касается Database Explorer — то я как таковой не использую, если вы про список все процедур, пакетов, таблиц и т.д. За почти 10 лет работы с ораклом ни разу не возникало острой необходимости, всегда можно написать скрипт типа select * from all_objects where…
      dbForge — пробовал, но софтина имеет несколько как раз тех недостатков которые я перечислял в самом начале статьи.
      По SQL Server не планирую, т.к. с ним работал эпизодически. Там есть тоже консольная утилита isql что ли называется, то можно попробовать так же прикрутить вместо sqlplus.


  1. Ruslan_Y
    02.12.2015 14:23

    Вообще-то Sublime Text платный, бесплатна только его пробная версия (пруф).
    Самый большой минус — отсутствие встроенного отладчика процедур/функций, еще, видимо, нужна ручная работа при добавлении новых объектов в БД? Придется дергать скрипт выгрузки списка для подсветки каждый раз при добавлении чего-то нового. В целом же подход довольно интересен, спасибо.


    1. meiko
      02.12.2015 14:47

      Да, я и подзабыл про лицензию sublime text :)
      Про ручную работу, да, или добавлять объекты в руки или дергать скрипт, как я написал в конце что есть недостатки, но для меня они не значительны, да и та же жаба постоянно дергает запросы к метаданным для получения данных об объектах БД.


  1. Edro
    02.12.2015 14:29

    Спасибо за статью.
    Аналогично, использую sublime text для PL/SQL разработки, но деплою через жабу, т.к. это несколько удобнее. Сейчас буду прокачивать среду :)
    У нас в БД несколько тысяч объектов, нет инфы о производительности подсветки в таком случае?

    Хотелось бы дополнить: чтобы быстро настроить голый ST для работы с PL/SQL можно воспользоваться такой последовательностью:
    Установить Package Control https://packagecontrol.io/installation
    Установить пакет Oracle PL SQL https://packagecontrol.io/packages/Oracle%20PL%20SQL


    1. meiko
      02.12.2015 14:42

      По производительности:

      select count(*) 
        from all_objects
       where owner = user
         and object_type in ('TABLE', 'VIEW')
       order by object_name
      

      сейчас вернул у меня 5506, тормозов в Sublime не замечено.
      А я наоборот почти отказался от жабы, в ней удобно только смотреть план запроса и чудо кнопка F4 — когда надо быстренько сделать reverse engenniring


      1. Edro
        02.12.2015 15:00

        Еще удобно просто селект выполнять, все-таки выхлоп SQL*Plus не всегда удобно читать. А при включении в запрос поля rowid можно подправить значения в таблице прямо через результат запроса.
        Еще иногда требуется экспорт в файл и генерация SQL Statements на основе результата запроса.


  1. bormotov
    02.12.2015 21:35
    +1

    следующий шаг: прицепить ко встроенному питону cx_Oracle и перенести наиболее популярные запросы в плагин, зацепить на хоткей. А может и db explorer написать.


  1. zloyreznic
    03.12.2015 10:44

    Подскажите, кто работает с postgresql
    Какие средства разработки используете?
    Очень хочу научиться писать функции на sql
    Спасибо


    1. ploop
      03.12.2015 11:27

      Для начала вполне достаточно pgAdmin III


  1. mgramin
    06.12.2015 22:13

    Если будет интересно как у нас организована структура, SVN, выпуск версий, обновление клиентов и т.д. с учетом того что мы пишем фактически только на SQL и PL/SQL, то могу попробовать написать на эту тему статью
    +1