7af6cdf2f6
- EXEC(...) в T-SQL склеивает только строки и переменные: REPLACE/QUOTENAME внутри давали ошибку 102, и SQL Server отклонял весь скрипт (.06.4–.06.6). Команда входа собирается в @sql заранее; тест ловит вызовы функций внутри EXEC; живая проверка синтаксиса на SQL Server без выполнения (SET PARSEONLY) — TestDepoSetupScriptParseLive. - «Логин bj / Пароль bj» и в способе «Дать логин администратора»: на общем сервере bj_user может быть занят другим bj — подготовка сменила бы ему пароль. Предупреждение. - Показ скрипта на странице ничего не сохраняет. Логин и пароль из выданного скрипта и из «Проверить подключение» хранятся черновиком (DepoNewUser/DepoNewPass) и становятся рабочими только после успешного входа: службы bj с неверным паролем за минуты блокировали логин на сервере (CHECK_POLICY) — у всех, кто им пользуется. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014FsEKyJrYF69Cj9ZXzFLRi
68 lines
3.0 KiB
Go
68 lines
3.0 KiB
Go
package lkgateway
|
|
|
|
import (
|
|
"context"
|
|
"os"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
// Синтаксис скрипта подготовки DEPO на настоящем SQL Server — без выполнения (SET PARSEONLY ON: сервер только
|
|
// разбирает текст). BJ_DEPO_PARSE_CFG=<копия setup.json с подключением к DEPO> go test -run TestDepoSetupScriptParseLive.
|
|
// Для надёжности база в скрипте — заведомо несуществующая: даже без PARSEONLY скрипт остановился бы до изменений.
|
|
func TestDepoSetupScriptParseLive(t *testing.T) {
|
|
cfg := os.Getenv("BJ_DEPO_PARSE_CFG")
|
|
if cfg == "" {
|
|
t.Skip("BJ_DEPO_PARSE_CFG не задан")
|
|
}
|
|
rc, err := NewRuntimeConfig(cfg)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
f := rc.Snapshot().Fancy
|
|
if f.IsPostgres() || f.Server == "" {
|
|
t.Skip("в настройках нет SQL Server DEPO")
|
|
}
|
|
ctx, cancel := context.WithTimeout(context.Background(), 45*time.Second)
|
|
defer cancel()
|
|
db, err := fancyOpen(f, "")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer db.Close()
|
|
conn, err := db.Conn(ctx)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer conn.Close()
|
|
if _, err := conn.ExecContext(ctx, "SET PARSEONLY ON"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
// режим действует: ошибка, поднятая командой, не возникает — значит, ничего не выполняется
|
|
if _, err := conn.ExecContext(ctx, "RAISERROR(N'parseonly-probe', 16, 1)"); err != nil {
|
|
t.Fatalf("SET PARSEONLY не действует — дальше не идём: %s", quikErrorDetail(err))
|
|
}
|
|
// и ловит ровно ту ошибку, что была в выпусках .06.4–.06.6: вызов функции внутри EXEC(...)
|
|
if _, err := conn.ExecContext(ctx, "DECLARE @p nvarchar(10) = N'a'; EXEC(N'SELECT ' + REPLACE(@p, N'a', N'1'))"); err == nil {
|
|
t.Fatal("разбор не заметил функцию внутри EXEC(...) — проверка ничего не стоит")
|
|
}
|
|
const nodb, login, pass = "BJ_PARSE_CHECK_NO_SUCH_DB", "bj_parse_check", "Xk7pQ2mN'9vR4tL8w"
|
|
for _, agent := range []bool{true, false} {
|
|
if _, err := conn.ExecContext(ctx, depoSetupScript(f, nodb, login, pass, agent)); err != nil {
|
|
t.Fatalf("скрипт (задание Agent: %v): %s", agent, quikErrorDetail(err))
|
|
}
|
|
}
|
|
// команды, которые скрипт собирает и выполняет через EXEC, — по отдельности
|
|
stmts := []string{
|
|
"CREATE LOGIN [" + login + "] WITH PASSWORD = N'" + sqlStr(pass) + "', CHECK_POLICY = ON, DEFAULT_DATABASE = [" + nodb + "]",
|
|
"ALTER LOGIN [" + login + "] WITH PASSWORD = N'" + sqlStr(pass) + "'",
|
|
}
|
|
stmts = append(stmts, depoTablesDDL(false)...)
|
|
stmts = append(stmts, depoTablesGrantSQL(false, login)...)
|
|
for _, q := range stmts {
|
|
if _, err := conn.ExecContext(ctx, q); err != nil {
|
|
t.Fatalf("%s → %s", depoStmtHead(q), quikErrorDetail(err))
|
|
}
|
|
}
|
|
}
|