Реализация мультиметодов для вашего драйвера¶
Реализация мультиметодов позволяет вам воспользоваться преимуществами существующего кода драйвера Glarus BI, расширив эти методы для работы с вашей конкретной базой данных.
Давайте сначала сосредоточимся на основном файле драйвера для нашего Fox Pro '98 src/metabase/driver/foxpro98.clj
. Взгляните на этот пример кода:
;; Define a namespace for the driver
(ns com.mycompany.metabase.driver.foxpro98
(:require [metabase.driver :as driver]))
;; Can you include a different method here as an example?
(defmethod driver/display-name :foxpro98 [_]
"Visual FoxPro '98")
Давайте пройдёмся по каждому блоку кода.
Пространства имён драйверов¶
;; Define a namespace for the driver
(ns com.mycompany.metabase.driver.foxpro98
(:require [metabase.driver :as driver]))
Каждый драйвер Glarus BI находится в своём собственном пространстве имён¶
В данном случае это пространство имён com.mycompany.metabase.driver.foxpro98.
Все основные драйверы Glarus BI находятся в пространствах имён metabase.driver.<name-goes-here>
. Вероятно, лучше использовать имена, соответствующие соглашениям об именовании пакетов Java.
Многие драйверы разбиты на дополнительные пространства имён¶
Особенно крупные драйверы. Обычно драйвер имеет пространство имён query-processor
(например, com.mycompany.metabase.driver.foxpro98.query-processor
), которое содержит логику для преобразования запросов MBQL (запросов, созданных с помощью графического конструктора запросов Glarus BI) в собственные запросы (например, SQL). Процессор запросов часто является самой сложной частью драйвера, поэтому разделение этой логики может упростить работу с ним. Некоторые драйверы также имеют отдельное пространство имён sync
, в котором есть реализации методов, используемых Glarus BI для синхронизации базы данных.
Инициализация драйвера¶
Все драйверы могут включать дополнительный код, который будет выполняться один раз (и только один раз) с использованием metabase.driver/initialize!
, когда Glarus BI инициализирует драйвер, то есть до того, как драйвер впервые установит соединение с базой данных. (На самом деле Glarus BI использует metabase.driver/initialize!
для ленивой загрузки драйвера.) Есть лишь несколько случаев, когда вы должны использовать metabase.driver/initialize
, например, для выделения ресурсов или установки определённых системных свойств.
Мультиметоды metabase.driver
¶
Пространство имён metabase.driver
определяет ряд мультиметодов, а драйверы предоставляют для них реализации, как в нашем примере:
Все четыре основные функции драйвера Glarus BI, описанные выше, реализуются с помощью мультиметодов. Эти методы отправляют ключевое слово драйвера, в нашем случае :foxpro98
. На самом деле, это то, чем является драйвер Glarus BI — ключевое слово! Здесь нет классов или объектов — только одно ключевое слово.
Вы можете просмотреть пространство имён metabase.driver
для получения полного списка мультиметодов, которые вы могли бы реализовать. Прочтите строку документации для каждого метода и решите, нужно ли вам его реализовать. Большинство методов являются необязательными.
Список доступных мультиметодов драйвера¶
Чтобы быстро просмотреть список всех мультиметодов драйвера, вы можете запустить команду
которая отобразит список всех пространств имён драйверов и мультиметодов (sql
, sql-jdbc
, тестовых расширений и других).
Если вы также хотите увидеть строки документации для методов, запустите:
Родительские драйверы¶
Многие драйверы совместно используют детали реализации, и написание полных реализаций для методов синхронизации и т.п. потребовало бы большого количества повторяющегося кода. Таким образом, многие функции высокого уровня частично или полностью реализованы в общих «родительских» драйверах, таких как наиболее распространённый родитель :sql-jdbc
. «Родительский» драйвер аналогичен суперклассу в объектно-ориентированном программировании.
Вы можете определить родителя драйвера, указав его в манифесте плагина.
Родители, такие как :sql-jdbc
, задуманы как общий абстрактный "базовый класс" для драйверов, которые могут использовать большую часть своей реализации; в случае :sql-jdbc
он предназначен для драйверов на основе SQL, которые под капотом используют драйвер JDBC. :sql-jdbc
и другие родительские компоненты предоставляют реализации для многих методов, необходимых для реализации четырёх основных функций. драйвера Glarus BI. На самом деле, :sql-jdbc
предоставляет реализации таких вещей, как driver/execute-prepared-statement!
, поэтому драйверу, использующему его в качестве родителя, не нужно предоставлять его самому. Однако различные родительские драйверы определяют свои собственные мультиметоды для реализации.
Известные родительские драйверы¶
:sql-jdbc
можно использовать в качестве родителя для баз данных на основе SQL с драйвером JDBC.:sql-jdbc
реализует большинство из четырёх основных функций, но вместо этого вы должны реализовать мультиметодыsql-jdbc
, найденные в пространствах имёнmetabase.driver.sql-jdbc.*
, а также некоторые методыmetabase. driver.sql.*
пространства имён.:sql
сам является родителем:sql-jdbc
; его можно использовать для баз данных на основе SQL, которые не имеют драйвер JDBC, например BigQuery.:sql
реализует значительную часть функциональности драйвера, но вы должны реализовать некоторые методы из пространств имёнmetabase.driver.sql.*
, чтобы использовать его.- Драйверы, использующие API Google, такие как BigQuery и Google Analytics, могут использовать драйвер
:google
в качестве родителя. - Некоторые драйверы используют другие "конкретные" драйверы в качестве своих родителей. Например,
:redshift
использует:postgres
в качестве родителя, предоставляя реализации методов только для переопределения методов postgres, где это необходимо.
Вызов реализации родительского драйвера¶
Вы можете получить реализацию родительского драйвера для метода, используя get-method
:
(defmethod driver/mbql->native :bigquery [driver query]
((get-method driver/mbql-native :sql) driver query))
Это эквивалент вызова super.someMethod()
в объектно-ориентированном программировании.
Вы должны передать аргумент драйвера родительской реализации как есть, чтобы все методы, вызываемые этим методом, использовали правильную реализацию. Вот два способа вызова родительских методов, которых вам следует избегать:
(defmethod driver/mbql->native :bigquery [_ query]
;; BAD! If :sql's implementation of mbql->native calls any other methods, it won't use the :bigquery implementation
((get-method driver/mbql->native :sql) :sql query))
также избегать:
(defmethod driver/mbql->native :bigquery [_ query]
;; BAD! If someone else creates a driver using :bigquery as a parent, any methods called by :sql's implementation
;; of mbql->native will use :bigquery method implementations instead of custom ones for that driver
((get-method driver/mbql->native :sql) :bigquery query))
Несколько родителей¶
Внимательные читатели возможно заметили, что BigQuery упоминается как имеющий как :sql
, так и :google
в качестве родителя. Это множественное наследование разрешено и даже крайне полезно! Вы можете определить драйвер с несколькими родителями следующим образом:
В некоторых случаях оба родителя могут предоставить реализацию метода; чтобы исправить эту двусмысленность, просто предоставьте реализацию для своего драйвера и передайте её предпочтительной реализации родительского драйвера, как описано выше.
Для драйверов, поставляемых в виде подключаемого модуля, вы должны зарегистрировать методы в манифесте подключаемого модуля.
Работа с драйвером из REPL и в CIDER¶
Необходимость устанавливать metabase-core
локально и создавать драйверы uberjar была бы неприятной, особенно если вам приходилось повторять это, чтобы проверить каждое изменение. К счастью, вы можете запускать команды, как если бы всё было частью одного гигантского проекта:
Чтобы начать работу с драйвером в REPL, выполните:
Вам нужно будет пересобрать драйвер и установить его в каталог ./plugins
, а также перезапустить Glarus BI после внесения изменений.