предисловие
Мастурбировал большую часть времениPython
, который также включает преобразование таблицы базы данных вPython
серединаORM
обрамленныйModel
, но мы не нашли подходящего инструмента для этой бессмысленной "ручной работы", поэтому каждый раз, когда мы создаем новую таблицу, каждый пишет ее вручную в соответствии со своей структурой таблицы.Model
.
Одна-две таблицы — это хорошо, раз приходится писать больше 10 таблиц, только ты знаешь, что такое боль, на этот раз лозунг программиста еще раз подтвердил, что весь бессмысленный ручной труд со временем будет заменен компьютерами.
intellij plugin
Поскольку готового инструмента нет, напишите его сами, эффект демонстрации следующий:
Учитывая, что мы в основном используемPyCharm
развитие, простоjetbrains
также обеспечиваетSDK
для разработки плагинов, поэтомуUI
Нет необходимости считать уровень.
Процесс использования очень прост, просто нужно импортироватьDDL
заявление может быть сгенерированоPython
нужныйModel
код.
Например, импортируйте следующий DDL:
CREATE TABLE `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`userName` varchar(20) DEFAULT NULL COMMENT '用户名',
`password` varchar(100) DEFAULT NULL COMMENT '密码',
`roleId` int(11) DEFAULT NULL COMMENT '角色ID',
PRIMARY KEY (`id`),
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8
Генерируется соответствующий код Python:
class User(db.Model):
__tablename__ = 'user'
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
userName = db.Column(db.String) # 用户名
password = db.Column(db.String) # 密码
roleId = db.Column(db.Integer) # 角色ID
Лексический анализ
Тщательное сравнение исходного файла и целевого кода позволит легко выяснить правила, не более чем проанализировать имя таблицы, поле и атрибуты поля (будь то первичный ключ, тип, длина) и, наконец, преобразовать это кPython
Требуемый шаблон может быть.
До того, как я начал, я думал, что это очень просто, не более чем разбор строки, но на самом деле я обнаружил, что это не так, в основном это следующие проблемы:
- Как определить имя таблицы?
- Точно так же, как определить имя поля, но также должны быть связаны тип, длина и комментарий поля.
- Как определить первичный ключ?
Подводя итог, можно сказать, что как идентифицировать ключевую информацию в строке с помощью ряда правил, это также то, что делает сервер MySQL.
Прежде чем мы начнем парсить DDL, давайте посмотрим, как парсит следующий простой скрипт:
x = 20
Согласно нашему обычному опыту разработки, это утверждение разделено на следующие части:
-
x
представляет собой переменную -
=
Указывает обозначение присваивания -
20
Указывает результат задания
Таким образом, результатом нашего разбора этого скрипта должно быть:
VAR x
GE =
VAL 100
Этот процесс синтаксического анализа называется «лексическим синтаксическим анализом» в принципе компиляции, и вы можете слышать его编译原理
Эти слова большие (у меня тоже); только что для скрипта мы могли бы написать очень простой лексер для получения такого результата.
переход состояния
Прежде чем начать снова, подумайте об идее, вы можете видеть это в результатах выше, черезVAR
представлять переменные,GE
Указывает символ присваивания "=",VAL
Обозначает результат выполнения задания, и теперь нам нужно сосредоточиться на запоминании этих трех состояний.
При последовательном чтении разбора символов программа переключается между этими состояниями, как показано ниже:
- По умолчанию это начальное состояние.
- Введите, если символ является буквой
VAR
государство. - Введите, когда символ является знаком "="
GE
государство.
Точно так же, когда эти состояния не удовлетворены, он вернется в исходное состояние, чтобы снова подтвердить новое состояние.
Просто смотреть на картинку немного абстрактно, давайте посмотрим непосредственно на основной код:
public class Result{
public TokenType tokenType ;
public StringBuilder text = new StringBuilder();
}
Во-первых, определяется класс результатов для сбора окончательных результатов синтаксического анализа.TokenType
Это соответствует трем состояниям на рисунке, которые просто представлены значениями перечисления.
public enum TokenType {
INIT,
VAR,
GE,
VAL
}
Первая соответствует первой картинке: состояние инициализации.
Необходимо определить символ для текущего анализируемого символаTokenType
:
В соответствии с процессом, описанным на рисунке, достаточно оценить текущий символ и указать состояние.
Тогда это соответствует второй картинке: переходу между состояниями.
войдут разныеcase
,в различныхcase
чтобы определить, должен ли он переходить в другие состояния (вводINIT
состояние будет восстановлено после состояния).
Например:x = 20
:
Предпочтительный войдетVAR
состояние, то следующим символом является пробел, естественно повторно входящий в начальное состояние в строке 38, в результате чего следующий символ определяется снова=
ВойтиGE
государство.
когда сценарийab = 30
:
Первый символ a также является записьюVAR
состояние, второй символ b, который по-прежнему является буквой, поэтому введите строку 36, состояние не изменится, и в то же время будет добавлен символ b; последующие шаги такие же, как в предыдущем примере.
Больше говорить бесполезно, предлагаю вам провести одиночный тест самостоятельно и вы поймете:GitHub.com/crossover J я…
DDL-разбор
После завершения простого анализа взглянитеDDL
Как следует парсить такой скрипт:
CREATE TABLE `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`userName` varchar(20) DEFAULT NULL COMMENT '用户名',
`password` varchar(100) DEFAULT NULL COMMENT '密码',
`roleId` int(11) DEFAULT NULL COMMENT '角色ID',
PRIMARY KEY (`id`),
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8
Принцип аналогичен, во-первых, мы должны увидеть закон (то есть грамматику):
- Имя таблицы является первой строкой оператора и заканчивается
CREATE TABLE
начало. - Информация о каждом поле (имя, тип, длина, примечание) начинается с символа «`» и заканчивается «,».
- Первичные ключи — это поля, начинающиеся со строки PRIMART, начиная с
)
конец.
В соответствии с типом данных, которые нам нужно проанализировать, я определяю это перечисление здесь:
Затем сделайте оценочное назначение при инициализации типа:
Поскольку необходимо проанализировать много данных, здесь, естественно, больше условий суждения.
Рекурсивный разбор
Таргетинг наDDL
Правила грамматики, здесь нам все еще нужна специальная обработка, например, как ассоциировать при разборе информации о конкретных полях?
Например:
`userName` varchar(20) DEFAULT NULL COMMENT '用户名',
`password` varchar(100) DEFAULT NULL COMMENT '密码',
Данные, которые мы проанализировали здесь, должны иметь отношение отображения:
Следовательно, мы можем анализировать следующее поле только после того, как вся информация одного поля будет проанализирована и сопоставлена.
Итак, здесь я использую рекурсивный способ анализа (не обязательно лучший, каждый может предложить лучшее решение).
} else if (value == '`' && pStatus == Status.BASE_INIT) {
result.tokenType = DDLTokenType.FI;
result.text.append(value);
}
Если текущим символом является символ "`", установите статус в "FI" (FieldInfo) и введите рекурсивную обработку, когда он преобразуется в символ ",".
Можно понять, что этот кусок строки извлекается и обрабатывается отдельно:
`userName` varchar(20) DEFAULT NULL COMMENT '用户名',
Затем рекурсивно вызовите текущий метод, чтобы снова проанализировать этот символ, а затем проанализировать его в соответствии с правилами имени поля, типа, длины и комментария.
В то же время, поскольку есть рекурсия, необходимо связать данные подрекурсии, поэтому я добавил к возвращаемому результату новый.pid
поле, это также легко понять.
Значение по умолчанию — 0. После рекурсии оно будет увеличиваться на +1, чтобы гарантировать, что данные каждой рекурсии уникальны.
Используйте тот же метод, чтобы сначала извлечь всю строку при анализе первичного ключа:
PRIMARY KEY (`id`)
Просто "Р" в начале и ")" в конце.
} else if (value == 'P' && pStatus == Status.BASE_INIT) {
result.tokenType = DDLTokenType.P_K;
result.text.append(value);
}
Он также рекурсивно анализирует всю строку и переключает состояние во время рекурсивного процесса.P_K ---> P_K_V
Наконец получить первичный ключ.
Итак, сравнив только что абзацDDL
Результаты анализа следующие:
Таким образом, каждое поле также передаетсяpid
Образовались дифференцированные ассоциации.
Так что теперь нам просто нужно инкапсулировать этот лексер, чтобы обеспечить простойAPI
чтобы получить данные в таблице.
Суммировать
На данный момент все содержимое всего лексического парсера завершено.Хотя реализация - это небольшая функция, но я сам потратил много времени.Среди них просто рассмотрение принципа компиляции - головная боль.
Но это только верхушка айсберга всей точки знания скомпилированного языка.Есть также ряд содержания, такого как синтаксис, семантика, промежуточный и целевой код, все из которых труднее пережевывать.
На самом деле, я считаю, что большинство людей думают так же, как и я, это дело слишком низкоуровневое и скучное, и мало кто действительно работает в этой области, так что вы делаете с этим временем?
Так что я тоже решил отказаться от ямы после завершения этого.
Ха-ха, шучу, может быть, я смогу реализовать язык программирования в своей жизни, и у меня будет немного капитала, когда я состарюсь и буду хвастаться своим сыном.
Все адреса исходного кода и плагинов этой статьи:
После прочтения не забудьте поставить лайк и поделиться одним щелчком мыши.