Pull to refresh

Sublime text для PL/SQL разработчика

Reading time 6 min
Views 23K
Хотелось рассказать о том, как многими любимый 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.: Я понимаю что есть недостатки у данной “сборки”, однако для меня они не критичны, да и если побороть свою лень можно дописывать и дальше.
Tags:
Hubs:
+9
Comments 11
Comments Comments 11

Articles