DEPO Firebird: путь к базе — и строкой подключения Fancy целиком (база на другом компьютере)
Поле пути в мастере и в «Таблицах обмена» принимает строку подключения из настройки Fancy: «сервер:путь», «сервер/порт:путь», «\\сервер\D:\путь», «\\сервер\D$\путь», «inet://сервер:порт/путь» — адрес и порт bj берёт из неё (в мастере поля заполняются сразу при вставке). Сетевая папка «\\сервер\папка\…» — ошибка с подсказкой: Firebird открывает базу только на своём диске, адрес — компьютер с сервером Firebird. Проверено мастером на копии базы: пустой адрес + «127.0.0.1/3050:путь» — подготовка и BJ_PING. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Q7eREaYwUt1i4fNLZcGnjn
This commit is contained in:
@@ -13,7 +13,10 @@
|
|||||||
## Установка из bj
|
## Установка из bj
|
||||||
|
|
||||||
Мастер настройки bj, шаг «Учёт DEPO» → СУБД «Firebird» (27.10.2026): адрес сервера, порт 3050, путь к файлу базы
|
Мастер настройки bj, шаг «Учёт DEPO» → СУБД «Firebird» (27.10.2026): адрес сервера, порт 3050, путь к файлу базы
|
||||||
на сервере (как в подключении Fancy) или псевдоним. «Дать логин администратора» — SYSDBA, разово, не сохраняется:
|
или псевдоним. База обычно на другом компьютере: адрес — компьютер, где работает сервер Firebird (bj подключается
|
||||||
|
к нему по сети), путь — на его диске. Можно вставить строку подключения Fancy целиком — `10.0.0.5:D:\Fancy\DEPO.GDB`,
|
||||||
|
`сервер/3050:…`, `\\сервер\D:\…`, `\\сервер\D$\…`, `inet://сервер:порт/…`: адрес и порт bj возьмёт из неё.
|
||||||
|
Сетевую папку (`\\сервер\папка\…`) Firebird как базу не открывает — bj подскажет, что указать. «Дать логин администратора» — SYSDBA, разово, не сохраняется:
|
||||||
bj проверит базу и функции Fancy (UDF), создаст логин bj `SYSDBA_BJ`, таблицы обмена, оператора Fancy для bj,
|
bj проверит базу и функции Fancy (UDF), создаст логин bj `SYSDBA_BJ`, таблицы обмена, оператора Fancy для bj,
|
||||||
кодировщик M2M, определит привязки `FTV_M2M_SETTINGS`, поставит процедуры и права и проверит обработку
|
кодировщик M2M, определит привязки `FTV_M2M_SETTINGS`, поставит процедуры и права и проверит обработку
|
||||||
(`BJ_PING`). «Получить скрипт» — то же одним файлом для isql (WIN1251). Встроенные в bj копии этих файлов —
|
(`BJ_PING`). «Получить скрипт» — то же одним файлом для isql (WIN1251). Встроенные в bj копии этих файлов —
|
||||||
|
|||||||
@@ -77,7 +77,25 @@ func (h *setupHandlers) saveFancyDepoTables(w http.ResponseWriter, r *http.Reque
|
|||||||
}
|
}
|
||||||
s := h.rc.Snapshot().Fancy
|
s := h.rc.Snapshot().Fancy
|
||||||
db := strings.TrimSpace(r.FormValue("depo_database"))
|
db := strings.TrimSpace(r.FormValue("depo_database"))
|
||||||
if db != "" && !validDBName(db) {
|
if s.IsFirebird() && db != "" { // путь к базе на сервере Firebird или строка подключения Fancy целиком
|
||||||
|
host, p, path, err := fbSplitConn(db)
|
||||||
|
if err != nil {
|
||||||
|
setupFlash(w, r, "Таблицы DEPO: "+err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !validFBPath(path) {
|
||||||
|
setupFlash(w, r, "Таблицы DEPO: путь к базе — без кавычек, ; ? и #")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if host != "" && (host != s.Server || (p != 0 && p != s.Port)) {
|
||||||
|
s.Server = host
|
||||||
|
if p != 0 {
|
||||||
|
s.Port = p
|
||||||
|
}
|
||||||
|
s.DepoJobCheck, s.DepoJobCheckOK = "", false
|
||||||
|
}
|
||||||
|
db = path
|
||||||
|
} else if db != "" && !validDBName(db) {
|
||||||
setupFlash(w, r, "Таблицы DEPO: имя базы — только латинские буквы/цифры/_, начинать с буквы")
|
setupFlash(w, r, "Таблицы DEPO: имя базы — только латинские буквы/цифры/_, начинать с буквы")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -468,3 +468,50 @@ func fbErr(orig, sent string, err error) error {
|
|||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
fbDriveRe = regexp.MustCompile(`^[A-Za-z]:[\\/]`)
|
||||||
|
fbHostRe = regexp.MustCompile(`^([A-Za-z0-9._\-]{2,}|\[[0-9A-Fa-f:]+\])(?:/(\d{1,5}))?:(.+)$`)
|
||||||
|
fbUNCRe = regexp.MustCompile(`^\\\\([^\\/]+)[\\/](.+)$`)
|
||||||
|
fbAdmShRe = regexp.MustCompile(`^([A-Za-z])\$[\\/](.*)$`)
|
||||||
|
fbInetURLRe = regexp.MustCompile(`(?i)^inet[46]?://([^/:]+)(?::(\d{1,5}))?/(.+)$`)
|
||||||
|
)
|
||||||
|
|
||||||
|
// fbSplitConn — строка подключения Fancy к базе Firebird целиком: «сервер:путь», «сервер/порт:путь»,
|
||||||
|
// «\\сервер\D:\путь», «\\сервер\D$\путь», «inet://сервер:порт/путь». База обычно на другом компьютере — на
|
||||||
|
// том, где работает сервер Firebird; bj подключается к нему по сети, а путь — на диске этого компьютера.
|
||||||
|
// host="" — указан только путь (сервер — в отдельном поле). Сетевую папку (\\сервер\папка\…) Firebird не
|
||||||
|
// открывает — ошибка с подсказкой.
|
||||||
|
func fbSplitConn(s string) (host string, port int, path string, err error) {
|
||||||
|
s = strings.TrimSpace(s)
|
||||||
|
switch {
|
||||||
|
case fbDriveRe.MatchString(s) || strings.HasPrefix(s, "/") || !strings.ContainsAny(s, `:\/`):
|
||||||
|
return "", 0, s, nil // путь на сервере или псевдоним
|
||||||
|
case fbInetURLRe.MatchString(s):
|
||||||
|
m := fbInetURLRe.FindStringSubmatch(s)
|
||||||
|
port, _ = strconv.Atoi(m[2])
|
||||||
|
path = m[3]
|
||||||
|
if !fbDriveRe.MatchString(path) && !strings.ContainsAny(path, `\/`) { // inet://host/alias
|
||||||
|
return m[1], port, path, nil
|
||||||
|
}
|
||||||
|
if !fbDriveRe.MatchString(path) {
|
||||||
|
path = "/" + path
|
||||||
|
}
|
||||||
|
return m[1], port, path, nil
|
||||||
|
case fbUNCRe.MatchString(s):
|
||||||
|
m := fbUNCRe.FindStringSubmatch(s)
|
||||||
|
rest := m[2]
|
||||||
|
if fbDriveRe.MatchString(rest) { // \\сервер\D:\путь — так Fancy пишет подключение по именованным каналам
|
||||||
|
return m[1], 0, rest, nil
|
||||||
|
}
|
||||||
|
if a := fbAdmShRe.FindStringSubmatch(rest); a != nil { // \\сервер\D$\путь — административный общий ресурс
|
||||||
|
return m[1], 0, strings.ToUpper(a[1]) + `:\` + a[2], nil
|
||||||
|
}
|
||||||
|
return "", 0, "", fmt.Errorf("%s — сетевая папка: Firebird не открывает базы по сети как файл. Укажите компьютер %s в поле «Адрес сервера» (на нём должен работать сервер Firebird), а путь — на его диске, например D:\\Fancy\\DEPO.GDB, — как в подключении Fancy", s, m[1])
|
||||||
|
case fbHostRe.MatchString(s):
|
||||||
|
m := fbHostRe.FindStringSubmatch(s)
|
||||||
|
port, _ = strconv.Atoi(m[2])
|
||||||
|
return strings.Trim(m[1], "[]"), port, m[3], nil
|
||||||
|
}
|
||||||
|
return "", 0, s, nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -115,3 +115,31 @@ func TestFBScriptsMatchDeploy(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestFBSplitConn(t *testing.T) {
|
||||||
|
cases := []struct {
|
||||||
|
in, host string
|
||||||
|
port int
|
||||||
|
path string
|
||||||
|
bad bool
|
||||||
|
}{
|
||||||
|
{`D:\Fancy\Bases\DEPO.GDB`, "", 0, `D:\Fancy\Bases\DEPO.GDB`, false},
|
||||||
|
{`/var/db/depo.fdb`, "", 0, `/var/db/depo.fdb`, false},
|
||||||
|
{`DEPO`, "", 0, `DEPO`, false},
|
||||||
|
{`10.0.0.5:D:\Fancy\Bases\DEPO.GDB`, "10.0.0.5", 0, `D:\Fancy\Bases\DEPO.GDB`, false},
|
||||||
|
{`srv-depo/3051:D:\Show Depo\Bases\SPI_DEPO.GDB`, "srv-depo", 3051, `D:\Show Depo\Bases\SPI_DEPO.GDB`, false},
|
||||||
|
{`fbsrv:/var/db/depo.fdb`, "fbsrv", 0, `/var/db/depo.fdb`, false},
|
||||||
|
{`fbsrv:DEPO`, "fbsrv", 0, `DEPO`, false},
|
||||||
|
{`\\SRV-DEPO\D:\Fancy\DEPO.GDB`, "SRV-DEPO", 0, `D:\Fancy\DEPO.GDB`, false},
|
||||||
|
{`\\SRV-DEPO\d$\Fancy\DEPO.GDB`, "SRV-DEPO", 0, `D:\Fancy\DEPO.GDB`, false},
|
||||||
|
{`inet://10.0.0.5:3050/D:\Fancy\DEPO.GDB`, "10.0.0.5", 3050, `D:\Fancy\DEPO.GDB`, false},
|
||||||
|
{`inet://10.0.0.5/depo`, "10.0.0.5", 0, `depo`, false},
|
||||||
|
{`\\SRV-DEPO\Bases\DEPO.GDB`, "", 0, "", true},
|
||||||
|
}
|
||||||
|
for _, c := range cases {
|
||||||
|
h, p, path, err := fbSplitConn(c.in)
|
||||||
|
if (err != nil) != c.bad || h != c.host || p != c.port || path != c.path {
|
||||||
|
t.Errorf("fbSplitConn(%q) = %q, %d, %q, %v", c.in, h, p, path, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -308,7 +308,7 @@ func registerIgateAdmin(mux *http.ServeMux, rc *RuntimeConfig) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
depoDB := strings.TrimSpace(r.FormValue("depo_db"))
|
depoDB := strings.TrimSpace(r.FormValue("depo_db"))
|
||||||
if depoDB != "" && !validDBName(depoDB) {
|
if depoDB != "" && !validDBName(depoDB) && !(s.Fancy.IsFirebird() && validFBPath(depoDB)) { // у Firebird — путь к базе
|
||||||
jsonOut(w, map[string]any{"ok": false, "error": "имя базы DEPO — латинские буквы, цифры и _"})
|
jsonOut(w, map[string]any{"ok": false, "error": "имя базы DEPO — латинские буквы, цифры и _"})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -156,10 +156,10 @@
|
|||||||
<div class="dq-grid dq-srv">
|
<div class="dq-grid dq-srv">
|
||||||
<label>Адрес сервера<input type="text" name="server" data-need="адрес сервера DEPO" value="{{.Settings.Fancy.Server}}" placeholder="IP-адрес или имя\экземпляр" required autofocus spellcheck="false"></label>
|
<label>Адрес сервера<input type="text" name="server" data-need="адрес сервера DEPO" value="{{.Settings.Fancy.Server}}" placeholder="IP-адрес или имя\экземпляр" required autofocus spellcheck="false"></label>
|
||||||
<label>Порт<input type="text" name="port" value="{{if .Settings.Fancy.Port}}{{.Settings.Fancy.Port}}{{else if $pg}}5432{{else if $fb}}3050{{else}}1433{{end}}" inputmode="numeric"></label>
|
<label>Порт<input type="text" name="port" value="{{if .Settings.Fancy.Port}}{{.Settings.Fancy.Port}}{{else if $pg}}5432{{else if $fb}}3050{{else}}1433{{end}}" inputmode="numeric"></label>
|
||||||
<label><span data-nofb>Имя базы</span><span data-fb>Путь к базе</span><input type="text" name="depo_database" data-need="имя базы DEPO" value="{{.Settings.Fancy.DepoDatabase}}" placeholder="{{if $fb}}D:\Fancy\DEPO.GDB или псевдоним{{else}}как называется на сервере{{end}}" required {{if not $fb}}pattern="[A-Za-z][A-Za-z0-9_]*" {{end}}title="латинские буквы, цифры и _, начинается с буквы" spellcheck="false"></label>
|
<label><span data-nofb>Имя базы</span><span data-fb>Путь к базе</span><input type="text" name="depo_database" data-need="имя базы DEPO" value="{{.Settings.Fancy.DepoDatabase}}" placeholder="{{if $fb}}D:\Fancy\DEPO.GDB или 10.0.0.5:D:\Fancy\DEPO.GDB{{else}}как называется на сервере{{end}}" required {{if not $fb}}pattern="[A-Za-z][A-Za-z0-9_]*" {{end}}title="латинские буквы, цифры и _, начинается с буквы" spellcheck="false"></label>
|
||||||
</div>
|
</div>
|
||||||
<p class="dq-note" data-nofb>Точное имя базы учёта DEPO — bj будет работать только с ней. Перед подготовкой bj проверит, что в ней есть учётные таблицы DEPO, и в чужую базу ничего не запишет.</p>
|
<p class="dq-note" data-nofb>Точное имя базы учёта DEPO — bj будет работать только с ней. Перед подготовкой bj проверит, что в ней есть учётные таблицы DEPO, и в чужую базу ничего не запишет.</p>
|
||||||
<p class="dq-note" data-fb>Путь к файлу базы учёта на сервере Firebird — как в подключении Fancy (например, <span class="dq-mono">D:\Fancy\Bases\DEPO.GDB</span>), или её псевдоним из aliases.conf. Перед подготовкой bj проверит, что это база DEPO и функции Fancy на сервере доступны.</p>
|
<p class="dq-note" data-fb>База обычно на другом компьютере: «Адрес сервера» — компьютер, где работает сервер Firebird, путь — на его диске (например, <span class="dq-mono">D:\Fancy\Bases\DEPO.GDB</span>) или псевдоним из aliases.conf. Можно вставить строку подключения из настройки Fancy целиком — <span class="dq-mono">10.0.0.5:D:\Fancy\Bases\DEPO.GDB</span>, адрес и порт bj возьмёт из неё. Сетевую папку (\\компьютер\папка) Firebird не открывает. Перед подготовкой bj проверит, что это база DEPO и функции Fancy на сервере доступны.</p>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section class="dq-s">
|
<section class="dq-s">
|
||||||
@@ -247,7 +247,7 @@
|
|||||||
if(['1433','5432','3050'].indexOf(f.port.value)>=0) f.port.value={mssql:'1433',postgres:'5432',firebird:'3050'}[t];
|
if(['1433','5432','3050'].indexOf(f.port.value)>=0) f.port.value={mssql:'1433',postgres:'5432',firebird:'3050'}[t];
|
||||||
f.admin_user.placeholder=pg?'postgres':fb?'SYSDBA':'sa';
|
f.admin_user.placeholder=pg?'postgres':fb?'SYSDBA':'sa';
|
||||||
var dbi=f.depo_database; // Firebird: путь к файлу базы или псевдоним, а не имя
|
var dbi=f.depo_database; // Firebird: путь к файлу базы или псевдоним, а не имя
|
||||||
if(fb){ dbi.removeAttribute('pattern'); dbi.placeholder='D:\\Fancy\\DEPO.GDB или псевдоним'; }
|
if(fb){ dbi.removeAttribute('pattern'); dbi.placeholder='D:\\Fancy\\DEPO.GDB или 10.0.0.5:D:\\Fancy\\DEPO.GDB'; }
|
||||||
else { dbi.setAttribute('pattern','[A-Za-z][A-Za-z0-9_]*'); dbi.placeholder='как называется на сервере'; }
|
else { dbi.setAttribute('pattern','[A-Za-z][A-Za-z0-9_]*'); dbi.placeholder='как называется на сервере'; }
|
||||||
if(fb&&f.bj_user.value==='bj_user') f.bj_user.value='SYSDBA_BJ'; else if(!fb&&f.bj_user.value==='SYSDBA_BJ') f.bj_user.value='bj_user';
|
if(fb&&f.bj_user.value==='bj_user') f.bj_user.value='SYSDBA_BJ'; else if(!fb&&f.bj_user.value==='SYSDBA_BJ') f.bj_user.value='bj_user';
|
||||||
var jn=f.depo_job_name, dbv=(f.depo_database.value||'').trim(); // имя задания — по базе, пока не поправили руками
|
var jn=f.depo_job_name, dbv=(f.depo_database.value||'').trim(); // имя задания — по базе, пока не поправили руками
|
||||||
@@ -270,6 +270,14 @@
|
|||||||
else { pre.textContent=''; pre.dataset.msg=x.t.trim().replace(/^./,function(c){return c.toUpperCase()})+' — скрипт появится здесь.'; } })
|
else { pre.textContent=''; pre.dataset.msg=x.t.trim().replace(/^./,function(c){return c.toUpperCase()})+' — скрипт появится здесь.'; } })
|
||||||
.catch(function(){ if(my!==seq) return; last=''; pre.classList.remove('dq-busy'); pre.textContent=''; pre.dataset.msg='Не получилось собрать скрипт — обновите страницу.'; });
|
.catch(function(){ if(my!==seq) return; last=''; pre.classList.remove('dq-busy'); pre.textContent=''; pre.dataset.msg='Не получилось собрать скрипт — обновите страницу.'; });
|
||||||
}
|
}
|
||||||
|
function splitFB(){ // строка подключения Fancy целиком: «сервер[/порт]:путь», «\\сервер\D:\путь», «\\сервер\D$\путь»
|
||||||
|
if(f.db_type.value!=='firebird') return;
|
||||||
|
var v=f.depo_database.value.trim(), m;
|
||||||
|
if(/^[A-Za-z]:[\\/]/.test(v)) return;
|
||||||
|
if((m=/^\\\\([^\\/]+)[\\/]([A-Za-z]):?\$?[\\/](.*)$/.exec(v))){ f.server.value=m[1]; f.depo_database.value=m[2].toUpperCase()+':\\'+m[3]; return; }
|
||||||
|
if((m=/^([A-Za-z0-9._-]{2,})(?:\/(\d{1,5}))?:(.+)$/.exec(v))){ f.server.value=m[1]; if(m[2]) f.port.value=m[2]; f.depo_database.value=m[3]; }
|
||||||
|
}
|
||||||
|
f.depo_database.addEventListener('change', function(){ splitFB(); changed(); });
|
||||||
function changed(){ sync(); clearTimeout(timer); timer=setTimeout(load, 350); }
|
function changed(){ sync(); clearTimeout(timer); timer=setTimeout(load, 350); }
|
||||||
f.depo_job_name.addEventListener('input', function(){ this.dataset.auto=this.value.trim()?'0':'1'; });
|
f.depo_job_name.addEventListener('input', function(){ this.dataset.auto=this.value.trim()?'0':'1'; });
|
||||||
f.addEventListener('input', changed); f.addEventListener('change', changed);
|
f.addEventListener('input', changed); f.addEventListener('change', changed);
|
||||||
|
|||||||
@@ -35,7 +35,7 @@
|
|||||||
<form method="post" action="/admin/setup/fancy/depo-tables" style="margin-top:10px;display:grid;gap:10px;max-width:720px">
|
<form method="post" action="/admin/setup/fancy/depo-tables" style="margin-top:10px;display:grid;gap:10px;max-width:720px">
|
||||||
<input type="hidden" name="section" value="sec-fancy-depo-tables">
|
<input type="hidden" name="section" value="sec-fancy-depo-tables">
|
||||||
<label>База DEPO
|
<label>База DEPO
|
||||||
<input type="text" name="depo_database" value="{{.Settings.Fancy.DepoDatabase}}" placeholder="{{.DepoTables.DB}}" pattern="[A-Za-z][A-Za-z0-9_]*" style="width:100%"></label>
|
<input type="text" name="depo_database" value="{{.Settings.Fancy.DepoDatabase}}" placeholder="{{if .Settings.Fancy.IsFirebird}}D:\Fancy\Bases\DEPO.GDB или 10.0.0.5:D:\Fancy\Bases\DEPO.GDB{{else}}{{.DepoTables.DB}}{{end}}" {{if not .Settings.Fancy.IsFirebird}}pattern="[A-Za-z][A-Za-z0-9_]*" {{end}}style="width:100%"></label>
|
||||||
<label>Признак ИИС в названии брокерского договора <span class="muted" style="font-weight:400">(с чего начинается номер договора ИИС в DEPO; несколько — через запятую)</span>
|
<label>Признак ИИС в названии брокерского договора <span class="muted" style="font-weight:400">(с чего начинается номер договора ИИС в DEPO; несколько — через запятую)</span>
|
||||||
<input type="text" name="iis_contract_marker" value="{{.Settings.Fancy.IISContractMarker}}" placeholder="БРИИС" style="width:100%"></label>
|
<input type="text" name="iis_contract_marker" value="{{.Settings.Fancy.IISContractMarker}}" placeholder="БРИИС" style="width:100%"></label>
|
||||||
<label style="display:flex;gap:8px;align-items:flex-start;font-weight:600"><input type="radio" name="depo_tables_mode" value="auto" {{if eq .Settings.Fancy.DepoTablesMode "auto"}}checked{{end}}> <span>Создаёт bj <span class="muted" style="font-weight:400">— вводите логин с правами на создание таблиц в базе DEPO. Он используется один раз и не сохраняется; bj заодно выдаст права своему логину.</span></span></label>
|
<label style="display:flex;gap:8px;align-items:flex-start;font-weight:600"><input type="radio" name="depo_tables_mode" value="auto" {{if eq .Settings.Fancy.DepoTablesMode "auto"}}checked{{end}}> <span>Создаёт bj <span class="muted" style="font-weight:400">— вводите логин с правами на создание таблиц в базе DEPO. Он используется один раз и не сохраняется; bj заодно выдаст права своему логину.</span></span></label>
|
||||||
|
|||||||
@@ -248,10 +248,20 @@ func (h *setupHandlers) depoSetupForm(r *http.Request) (FancyMSSQLSettings, stri
|
|||||||
return s, "", agent, "укажите имя базы DEPO — как она называется на сервере"
|
return s, "", agent, "укажите имя базы DEPO — как она называется на сервере"
|
||||||
}
|
}
|
||||||
if dbType == "firebird" {
|
if dbType == "firebird" {
|
||||||
if !validFBPath(db) {
|
host, p, path, err := fbSplitConn(db) // строка подключения Fancy целиком: «сервер:путь» — сервер из неё
|
||||||
|
if err != nil {
|
||||||
|
return s, "", agent, err.Error()
|
||||||
|
}
|
||||||
|
if host != "" {
|
||||||
|
s.Server = host
|
||||||
|
if p != 0 {
|
||||||
|
s.Port = p
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !validFBPath(path) {
|
||||||
return s, "", agent, "путь к базе DEPO — без кавычек, ; ? и #"
|
return s, "", agent, "путь к базе DEPO — без кавычек, ; ? и #"
|
||||||
}
|
}
|
||||||
return s, db, agent, ""
|
return s, path, agent, ""
|
||||||
}
|
}
|
||||||
if !validDBName(db) {
|
if !validDBName(db) {
|
||||||
return s, "", agent, "имя базы DEPO — только латинские буквы, цифры и _, начинается с буквы"
|
return s, "", agent, "имя базы DEPO — только латинские буквы, цифры и _, начинается с буквы"
|
||||||
|
|||||||
Reference in New Issue
Block a user