mirror of
https://github.com/Icinga/icingaweb2-module-director.git
synced 2025-08-30 06:08:10 +02:00
commit
ddcc8953b8
@ -7,6 +7,7 @@ use Icinga\Module\Director\Forms\DirectorDatalistForm;
|
||||
use Icinga\Module\Director\Objects\DirectorDatalist;
|
||||
use Icinga\Module\Director\Web\Controller\ActionController;
|
||||
use Icinga\Module\Director\Web\Table\CustomvarTable;
|
||||
use Icinga\Module\Director\Web\Table\DatafieldCategoryTable;
|
||||
use Icinga\Module\Director\Web\Table\DatafieldTable;
|
||||
use Icinga\Module\Director\Web\Table\DatalistEntryTable;
|
||||
use Icinga\Module\Director\Web\Table\DatalistTable;
|
||||
@ -74,6 +75,24 @@ class DataController extends ActionController
|
||||
(new DatafieldTable($this->db()))->renderTo($this);
|
||||
}
|
||||
|
||||
public function fieldcategoriesAction()
|
||||
{
|
||||
$this->setAutorefreshInterval(10);
|
||||
$this->tabs(new DataTabs())->activate('datafieldcategory');
|
||||
$this->addTitle($this->translate('Data Field Categories'));
|
||||
$this->actions()->add(Link::create(
|
||||
$this->translate('Add'),
|
||||
'director/datafieldcategory/add',
|
||||
null,
|
||||
[
|
||||
'class' => 'icon-plus',
|
||||
'data-base-target' => '_next',
|
||||
]
|
||||
));
|
||||
|
||||
(new DatafieldCategoryTable($this->db()))->renderTo($this);
|
||||
}
|
||||
|
||||
public function varsAction()
|
||||
{
|
||||
$this->tabs(new DataTabs())->activate('customvars');
|
||||
|
46
application/controllers/DatafieldcategoryController.php
Normal file
46
application/controllers/DatafieldcategoryController.php
Normal file
@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
namespace Icinga\Module\Director\Controllers;
|
||||
|
||||
use Icinga\Module\Director\Forms\DirectorDatafieldCategoryForm;
|
||||
use Icinga\Module\Director\Web\Controller\ActionController;
|
||||
|
||||
class DatafieldcategoryController extends ActionController
|
||||
{
|
||||
public function addAction()
|
||||
{
|
||||
$this->indexAction();
|
||||
}
|
||||
|
||||
public function editAction()
|
||||
{
|
||||
$this->indexAction();
|
||||
}
|
||||
|
||||
public function indexAction()
|
||||
{
|
||||
$edit = false;
|
||||
|
||||
if ($name = $this->params->get('name')) {
|
||||
$edit = true;
|
||||
}
|
||||
|
||||
$form = DirectorDatafieldCategoryForm::load()
|
||||
->setDb($this->db());
|
||||
|
||||
if ($edit) {
|
||||
$form->loadObject($name);
|
||||
$this->addTitle(
|
||||
$this->translate('Modify %s'),
|
||||
$form->getObject()->category_name
|
||||
);
|
||||
$this->addSingleTab($this->translate('Edit a Category'));
|
||||
} else {
|
||||
$this->addTitle($this->translate('Add a new Data Field Category'));
|
||||
$this->addSingleTab($this->translate('New Category'));
|
||||
}
|
||||
|
||||
$form->handleRequest();
|
||||
$this->content()->add($form);
|
||||
}
|
||||
}
|
36
application/forms/DirectorDatafieldCategoryForm.php
Normal file
36
application/forms/DirectorDatafieldCategoryForm.php
Normal file
@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace Icinga\Module\Director\Forms;
|
||||
|
||||
use Icinga\Module\Director\Web\Form\DirectorObjectForm;
|
||||
|
||||
class DirectorDatafieldCategoryForm extends DirectorObjectForm
|
||||
{
|
||||
protected $objectName = 'Data field category';
|
||||
|
||||
protected $listUrl = 'director/data/fieldcategories';
|
||||
|
||||
public function setup()
|
||||
{
|
||||
$this->addHtmlHint(
|
||||
$this->translate(
|
||||
'Data field categories allow to structure Data Fields. Fields with'
|
||||
. ' a category will be shown grouped by category.'
|
||||
)
|
||||
);
|
||||
|
||||
$this->addElement('text', 'category_name', [
|
||||
'label' => $this->translate('Category name'),
|
||||
'description' => $this->translate(
|
||||
'The unique name of the category used for grouping your custom Data Fields.'
|
||||
),
|
||||
'required' => true,
|
||||
]);
|
||||
|
||||
$this->addElement('text', 'description', [
|
||||
'label' => $this->translate('Description'),
|
||||
]);
|
||||
|
||||
$this->setButtons();
|
||||
}
|
||||
}
|
@ -164,6 +164,11 @@ class DirectorDatafieldForm extends DirectorObjectForm
|
||||
'rows' => '3',
|
||||
));
|
||||
|
||||
$this->addElement('select', 'category_id', [
|
||||
'label' => $this->translate('Data Field Category'),
|
||||
'multiOptions' => $this->optionalEnum($this->enumCategpories()),
|
||||
]);
|
||||
|
||||
$error = false;
|
||||
try {
|
||||
$types = $this->enumDataTypes();
|
||||
@ -285,4 +290,12 @@ class DirectorDatafieldForm extends DirectorObjectForm
|
||||
|
||||
return $enum;
|
||||
}
|
||||
|
||||
protected function enumCategpories()
|
||||
{
|
||||
$db = $this->getDb()->getDbAdapter();
|
||||
return $db->fetchPairs(
|
||||
$db->select()->from('director_datafield_category', ['id', 'category_name'])
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace Icinga\Module\Director\Dashboard\Dashlet;
|
||||
|
||||
class DatafieldCategoryDashlet extends Dashlet
|
||||
{
|
||||
protected $icon = 'th-list';
|
||||
|
||||
public function getTitle()
|
||||
{
|
||||
return $this->translate('Data Field Categories');
|
||||
}
|
||||
|
||||
public function getSummary()
|
||||
{
|
||||
return $this->translate(
|
||||
'Categories bring structure to your Data Fields'
|
||||
);
|
||||
}
|
||||
|
||||
public function getUrl()
|
||||
{
|
||||
return 'director/data/fieldcategories';
|
||||
}
|
||||
|
||||
public function listRequiredPermissions()
|
||||
{
|
||||
return array('director/admin');
|
||||
}
|
||||
}
|
@ -4,11 +4,12 @@ namespace Icinga\Module\Director\Dashboard;
|
||||
|
||||
class DataDashboard extends Dashboard
|
||||
{
|
||||
protected $dashletNames = array(
|
||||
protected $dashletNames = [
|
||||
'Datafield',
|
||||
'DatafieldCategory',
|
||||
'Datalist',
|
||||
'Customvar'
|
||||
);
|
||||
];
|
||||
|
||||
public function getTitle()
|
||||
{
|
||||
|
@ -11,6 +11,9 @@ class FieldSpec
|
||||
/** @var string */
|
||||
protected $varName;
|
||||
|
||||
/** @var string */
|
||||
protected $category;
|
||||
|
||||
/** @var string */
|
||||
protected $caption;
|
||||
|
||||
@ -46,13 +49,14 @@ class FieldSpec
|
||||
{
|
||||
return DirectorDatafield::create([
|
||||
'varname' => $this->getVarName(),
|
||||
'category' => $this->getCategory(),
|
||||
'caption' => $this->getCaption(),
|
||||
'description' => $this->getDescription(),
|
||||
'datatype' => $this->getDataType(),
|
||||
'format' => $this->getFormat(),
|
||||
'var_filter' => $this->getVarFilter(),
|
||||
'icinga_type' => $object->getShortTableName(),
|
||||
'object_id' => $object->get('id')
|
||||
'object_id' => $object->get('id'),
|
||||
]);
|
||||
}
|
||||
|
||||
@ -181,4 +185,22 @@ class FieldSpec
|
||||
$this->format = $format;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getCategory()
|
||||
{
|
||||
return $this->category;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $category
|
||||
* @return FieldSpec
|
||||
*/
|
||||
public function setCategory($category)
|
||||
{
|
||||
$this->category = $category;
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
@ -19,19 +19,27 @@ class DirectorDatafield extends DbObjectWithSettings
|
||||
|
||||
protected $autoincKeyName = 'id';
|
||||
|
||||
protected $defaultProperties = array(
|
||||
protected $defaultProperties = [
|
||||
'id' => null,
|
||||
'category_id' => null,
|
||||
'varname' => null,
|
||||
'caption' => null,
|
||||
'description' => null,
|
||||
'datatype' => null,
|
||||
'format' => null,
|
||||
);
|
||||
];
|
||||
|
||||
protected $relations = [
|
||||
'category' => 'DirectorDatafieldCategory'
|
||||
];
|
||||
|
||||
protected $settingsTable = 'director_datafield_setting';
|
||||
|
||||
protected $settingsRemoteId = 'datafield_id';
|
||||
|
||||
/** @var DirectorDatafieldCategory|null */
|
||||
private $category;
|
||||
|
||||
private $object;
|
||||
|
||||
public static function fromDbRow($row, Db $connection)
|
||||
@ -53,6 +61,53 @@ class DirectorDatafield extends DbObjectWithSettings
|
||||
return $obj;
|
||||
}
|
||||
|
||||
public function hasCategory()
|
||||
{
|
||||
return $this->category !== null || $this->get('category_id') !== null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return DirectorDatafieldCategory|null
|
||||
* @throws \Icinga\Exception\NotFoundError
|
||||
*/
|
||||
public function getCategory()
|
||||
{
|
||||
if ($this->category) {
|
||||
return $this->category;
|
||||
} elseif ($id = $this->get('category_id')) {
|
||||
return DirectorDatafieldCategory::loadWithAutoIncId($id, $this->getConnection());
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public function getCategoryName()
|
||||
{
|
||||
$category = $this->getCategory();
|
||||
if ($this->category === null) {
|
||||
return null;
|
||||
} else {
|
||||
return $category->get('category_name');
|
||||
}
|
||||
}
|
||||
|
||||
public function setCategory($category)
|
||||
{
|
||||
if ($category === null) {
|
||||
$this->category = null;
|
||||
$this->set('category_id', null);
|
||||
} elseif ($category instanceof DirectorDatafieldCategory) {
|
||||
if ($category->hasBeenLoadedFromDb()) {
|
||||
$this->set('category_id', $category->get('id'));
|
||||
}
|
||||
$this->category = $category;
|
||||
} else {
|
||||
$this->setCategory(DirectorDatafieldCategory::load($category, $this->getConnection()));
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return object
|
||||
* @throws \Icinga\Exception\NotFoundError
|
||||
|
20
library/Director/Objects/DirectorDatafieldCategory.php
Normal file
20
library/Director/Objects/DirectorDatafieldCategory.php
Normal file
@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace Icinga\Module\Director\Objects;
|
||||
|
||||
use Icinga\Module\Director\Data\Db\DbObject;
|
||||
|
||||
class DirectorDatafieldCategory extends DbObject
|
||||
{
|
||||
protected $table = 'director_datafield_category';
|
||||
|
||||
protected $keyName = 'category_name';
|
||||
|
||||
protected $autoincKeyName = 'id';
|
||||
|
||||
protected $defaultProperties = [
|
||||
'id' => null,
|
||||
'category_name' => null,
|
||||
'description' => null,
|
||||
];
|
||||
}
|
@ -9,6 +9,7 @@ use Icinga\Data\Filter\FilterExpression;
|
||||
use Icinga\Exception\IcingaException;
|
||||
use Icinga\Module\Director\Hook\HostFieldHook;
|
||||
use Icinga\Module\Director\Hook\ServiceFieldHook;
|
||||
use Icinga\Module\Director\Objects\DirectorDatafieldCategory;
|
||||
use Icinga\Module\Director\Objects\IcingaCommand;
|
||||
use Icinga\Module\Director\Objects\IcingaHost;
|
||||
use Icinga\Module\Director\Objects\IcingaObject;
|
||||
@ -33,6 +34,7 @@ class IcingaObjectFieldLoader
|
||||
/** @var \Zend_Db_Adapter_Abstract */
|
||||
protected $db;
|
||||
|
||||
/** @var DirectorDatafield[] */
|
||||
protected $fields;
|
||||
|
||||
protected $elements;
|
||||
@ -219,13 +221,51 @@ class IcingaObjectFieldLoader
|
||||
$form->addElement($element);
|
||||
}
|
||||
|
||||
if (! empty($elements)) {
|
||||
$form->addElementsToGroup(
|
||||
$elements,
|
||||
'custom_fields',
|
||||
50,
|
||||
$form->translate('Custom properties')
|
||||
);
|
||||
$this->attachGroupElements($elements, $form);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ZfElement[] $elements
|
||||
* @param DirectorObjectForm $form
|
||||
*/
|
||||
protected function attachGroupElements(array $elements, DirectorObjectForm $form)
|
||||
{
|
||||
$categories = [];
|
||||
$categoriesFetchedById = [];
|
||||
foreach ($this->fields as $key => $field) {
|
||||
if ($id = $field->get('category_id')) {
|
||||
if (isset($categoriesFetchedById[$id])) {
|
||||
$category = $categoriesFetchedById[$id];
|
||||
} else {
|
||||
$category = DirectorDatafieldCategory::loadWithAutoIncId($id, $form->getDb());
|
||||
$categoriesFetchedById[$id] = $category;
|
||||
}
|
||||
} elseif ($field->hasCategory()) {
|
||||
$category = $field->getCategory();
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
$categories[$key] = $category;
|
||||
}
|
||||
$prioIdx = \array_flip(\array_keys($categories));
|
||||
|
||||
foreach ($elements as $key => $element) {
|
||||
if (isset($categories[$key])) {
|
||||
$category = $categories[$key];
|
||||
$form->addElementsToGroup(
|
||||
[$element],
|
||||
'custom_fields:' . $category->get('category_name'),
|
||||
51 + $prioIdx[$key],
|
||||
$category->get('category_name')
|
||||
);
|
||||
} else {
|
||||
$form->addElementsToGroup(
|
||||
[$element],
|
||||
'custom_fields',
|
||||
50,
|
||||
$form->translate('Custom properties')
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -491,6 +531,7 @@ class IcingaObjectFieldLoader
|
||||
'var_filter' => 'f.var_filter',
|
||||
'is_required' => 'f.is_required',
|
||||
'id' => 'df.id',
|
||||
'category_id' => 'df.category_id',
|
||||
'varname' => 'df.varname',
|
||||
'caption' => 'df.caption',
|
||||
'description' => 'df.description',
|
||||
|
66
library/Director/Web/Table/DatafieldCategoryTable.php
Normal file
66
library/Director/Web/Table/DatafieldCategoryTable.php
Normal file
@ -0,0 +1,66 @@
|
||||
<?php
|
||||
|
||||
namespace Icinga\Module\Director\Web\Table;
|
||||
|
||||
use gipfl\IcingaWeb2\Link;
|
||||
use gipfl\IcingaWeb2\Table\ZfQueryBasedTable;
|
||||
use ipl\Html\Html;
|
||||
use Zend_Db_Adapter_Abstract as ZfDbAdapter;
|
||||
use Zend_Db_Select as ZfDbSelect;
|
||||
|
||||
class DatafieldCategoryTable extends ZfQueryBasedTable
|
||||
{
|
||||
protected $searchColumns = array(
|
||||
'dfc.varname',
|
||||
'dfc.caption',
|
||||
);
|
||||
|
||||
public function getColumns()
|
||||
{
|
||||
return array(
|
||||
'id' => 'dfc.id',
|
||||
'category_name' => 'dfc.category_name',
|
||||
'description' => 'dfc.description',
|
||||
'assigned_fields' => 'COUNT(df.id)',
|
||||
);
|
||||
}
|
||||
|
||||
public function renderRow($row)
|
||||
{
|
||||
$main = [Link::create(
|
||||
$row->category_name,
|
||||
'director/datafieldcategory/edit',
|
||||
['name' => $row->category_name]
|
||||
)];
|
||||
|
||||
if (strlen($row->description)) {
|
||||
$main[] = Html::tag('br');
|
||||
$main[] = Html::tag('small', $row->description);
|
||||
}
|
||||
return $this::tr([
|
||||
$this::td($main),
|
||||
$this::td($row->assigned_fields)
|
||||
]);
|
||||
}
|
||||
|
||||
public function getColumnsToBeRendered()
|
||||
{
|
||||
return array(
|
||||
$this->translate('Category Name'),
|
||||
$this->translate('# Used'),
|
||||
);
|
||||
}
|
||||
|
||||
public function prepareQuery()
|
||||
{
|
||||
$db = $this->db();
|
||||
return $db->select()->from(
|
||||
['dfc' => 'director_datafield_category'],
|
||||
$this->getColumns()
|
||||
)->joinLeft(
|
||||
['df' => 'director_datafield'],
|
||||
'df.category_id = dfc.id',
|
||||
[]
|
||||
)->group('dfc.id')->group('dfc.category_name')->order('category_name ASC');
|
||||
}
|
||||
}
|
@ -20,6 +20,9 @@ class DataTabs extends Tabs
|
||||
$this->add('datafield', [
|
||||
'label' => $this->translate('Data fields'),
|
||||
'url' => 'director/data/fields'
|
||||
])->add('datafieldcategory', [
|
||||
'label' => $this->translate('Data field categories'),
|
||||
'url' => 'director/data/fieldcategories'
|
||||
])->add('datalist', [
|
||||
'label' => $this->translate('Data lists'),
|
||||
'url' => 'director/data/lists'
|
||||
|
21
schema/mysql-migrations/upgrade_168.sql
Normal file
21
schema/mysql-migrations/upgrade_168.sql
Normal file
@ -0,0 +1,21 @@
|
||||
CREATE TABLE director_datafield_category (
|
||||
id INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
category_name VARCHAR(255) NOT NULL,
|
||||
description TEXT DEFAULT NULL,
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE KEY category_name (category_name)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
ALTER TABLE director_datafield
|
||||
ADD COLUMN category_id INT(10) UNSIGNED DEFAULT NULL AFTER id,
|
||||
ADD CONSTRAINT director_datafield_category
|
||||
FOREIGN KEY category (category_id)
|
||||
REFERENCES director_datafield_category (id)
|
||||
ON DELETE RESTRICT
|
||||
ON UPDATE CASCADE
|
||||
;
|
||||
|
||||
|
||||
INSERT INTO director_schema_migration
|
||||
(schema_version, migration_time)
|
||||
VALUES (168, NOW());
|
@ -179,8 +179,17 @@ CREATE TABLE director_datalist_entry (
|
||||
ON UPDATE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
CREATE TABLE director_datafield_category (
|
||||
id INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
category_name VARCHAR(255) NOT NULL,
|
||||
description TEXT DEFAULT NULL,
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE KEY category_name (category_name)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
CREATE TABLE director_datafield (
|
||||
id INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
category_id INT(10) UNSIGNED DEFAULT NULL,
|
||||
varname VARCHAR(64) NOT NULL COLLATE utf8_bin,
|
||||
caption VARCHAR(255) NOT NULL,
|
||||
description TEXT DEFAULT NULL,
|
||||
@ -188,7 +197,12 @@ CREATE TABLE director_datafield (
|
||||
-- datatype_param? multiple ones?
|
||||
format enum ('string', 'json', 'expression'),
|
||||
PRIMARY KEY (id),
|
||||
KEY search_idx (varname)
|
||||
KEY search_idx (varname),
|
||||
CONSTRAINT director_datalist_value_datalist
|
||||
FOREIGN KEY category (category_id)
|
||||
REFERENCES director_datafield_category (id)
|
||||
ON DELETE RESTRICT
|
||||
ON UPDATE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
CREATE TABLE director_datafield_setting (
|
||||
@ -1869,4 +1883,4 @@ CREATE TABLE icinga_scheduled_downtime_range (
|
||||
|
||||
INSERT INTO director_schema_migration
|
||||
(schema_version, migration_time)
|
||||
VALUES (167, NOW());
|
||||
VALUES (168, NOW());
|
||||
|
25
schema/pgsql-migrations/upgrade_168.sql
Normal file
25
schema/pgsql-migrations/upgrade_168.sql
Normal file
@ -0,0 +1,25 @@
|
||||
|
||||
CREATE TABLE director_datafield_category (
|
||||
id serial,
|
||||
category_name character varying(255) NOT NULL,
|
||||
description text DEFAULT NULL,
|
||||
PRIMARY KEY (id)
|
||||
);
|
||||
|
||||
CREATE UNIQUE INDEX datafield_category_name ON director_datafield_category (category_name);
|
||||
|
||||
|
||||
ALTER TABLE director_datafield
|
||||
ADD COLUMN category_id integer DEFAULT NULL,
|
||||
ADD CONSTRAINT director_datafield_category
|
||||
FOREIGN KEY (category_id)
|
||||
REFERENCES director_datafield_category (id)
|
||||
ON DELETE RESTRICT
|
||||
ON UPDATE CASCADE;
|
||||
|
||||
CREATE INDEX datafield_category ON director_datafield (category_id);
|
||||
|
||||
|
||||
INSERT INTO director_schema_migration
|
||||
(schema_version, migration_time)
|
||||
VALUES (168, NOW());
|
@ -248,18 +248,35 @@ CREATE TABLE director_datalist_entry (
|
||||
CREATE INDEX datalist_entry_datalist ON director_datalist_entry (list_id);
|
||||
|
||||
|
||||
CREATE TABLE director_datafield_category (
|
||||
id serial,
|
||||
category_name character varying(255) NOT NULL,
|
||||
description text DEFAULT NULL,
|
||||
PRIMARY KEY (id)
|
||||
);
|
||||
|
||||
CREATE UNIQUE INDEX datafield_category_name ON director_datafield_category (category_name);
|
||||
|
||||
|
||||
CREATE TABLE director_datafield (
|
||||
id serial,
|
||||
category_id integer DEFAULT NULL,
|
||||
varname character varying(64) NOT NULL,
|
||||
caption character varying(255) NOT NULL,
|
||||
description text DEFAULT NULL,
|
||||
datatype character varying(255) NOT NULL,
|
||||
-- datatype_param? multiple ones?
|
||||
format enum_property_format,
|
||||
PRIMARY KEY (id)
|
||||
PRIMARY KEY (id),
|
||||
CONSTRAINT director_datafield_category
|
||||
FOREIGN KEY (category_id)
|
||||
REFERENCES director_datafield_category (id)
|
||||
ON DELETE RESTRICT
|
||||
ON UPDATE CASCADE
|
||||
);
|
||||
|
||||
CREATE INDEX search_idx ON director_datafield (varname);
|
||||
CREATE INDEX datafield_category ON director_datafield (category_id);
|
||||
|
||||
|
||||
CREATE TABLE director_datafield_setting (
|
||||
@ -2182,4 +2199,4 @@ COMMENT ON COLUMN icinga_scheduled_downtime_range.merge_behaviour IS 'set -> = {
|
||||
|
||||
INSERT INTO director_schema_migration
|
||||
(schema_version, migration_time)
|
||||
VALUES (167, NOW());
|
||||
VALUES (168, NOW());
|
||||
|
Loading…
x
Reference in New Issue
Block a user