Commit 9f34266c authored by platyhouse's avatar platyhouse

# --edit 옵션 동작 변경 및 ptyMysqlQuery 도구 추가

## 공통 스크립트 가이드라인 변경

### --edit 옵션 동작 수정
- CLAUDE.md, README.md: --edit 옵션이 기존 스크립트 파일 대신 설정 파일(~/.pty[Service]Config.ini)을 편집하도록 변경
- CLAUDE.md: --edit 구현 패턴 코드 예시 업데이트

## ptyMysqlBackup 개선

### 압축 옵션 기본값 변경
- ptyMysqlBackup: --tgz 옵션을 --no-tgz로 변경하여 기본값으로 tgz 압축 사용
- CLAUDE.md: ptyMysqlBackup 옵션 설명 업데이트

### 데이터베이스 연결 개선
- ptyMysqlBackup: '*' 패턴 사용 시 database 설정 없이 연결하도록 수정

## ptyMysqlConfig 라이브러리 개선

- ptyLibrary_PHP/mysql/ptyMysqlConfig.php: connect() 메서드에 $useDatabase 파라미터 추가하여 database 설정 사용 여부 제어 가능

## ptyMysqlInfo 개선

- ptyMysqlInfo: database 설정 없이 서버 전체 정보 조회하도록 수정
- ptyMysqlInfo: null 병합 연산자(??)를 PHP 5.6 호환 isset() 삼항 연산자로 변경

## ptyMysqlRestore 개선

- ptyMysqlRestore: database 설정 없이 연결하여 여러 DB에 복원 가능하도록 수정

## ptyMysqlQuery 신규 추가

- ptyMysqlQuery: MySQL 쿼리 실행 CLI 도구 신규 생성
- 다양한 출력 형식 지원: key:value(기본값), --table, --json, --dump, --csv, --markdown
- --database 옵션으로 INI 설정과 별도로 데이터베이스 지정 가능
- PHP 5.6 호환성 유지 (mb_ord 폴리필 포함)
parent 33844aa5
......@@ -35,7 +35,7 @@ require_once __DIR__ . '/ptyLibrary_PHP/ai/ptyAIConfig.php'; // AI API
|------|------|:--------:|
| `--help` | 도움말 출력 | O |
| `--verbose` | 상세 로그 출력 | O |
| `--edit` | 스크립트를 에디터로 열기 | O |
| `--edit` | 설정 파일을 에디터로 열기 | O |
| `--dry-run` | 실제 실행 없이 대상/결과 미리보기 | O (데이터 변경 스크립트) |
### 옵션 처리 우선순위 (중요!)
......@@ -47,7 +47,7 @@ require_once __DIR__ . '/ptyLibrary_PHP/ai/ptyAIConfig.php'; // AI API
// 옵션 처리 우선순위
// ============================================================
// 1. --help : 최우선! 인자 검증/연결 없이 즉시 도움말 출력
// 2. --edit : 스크립트 편집 (인자 없이도 동작)
// 2. --edit : 설정 파일 편집 (인자 없이도 동작)
// 3. 필수 인자 검증
// 4. 서비스 연결 및 비즈니스 로직
// ============================================================
......@@ -59,10 +59,11 @@ if (isset($options['help'])) {
exit(0);
}
// 2. --edit: 스크립트 편집
// 2. --edit: 설정 파일 편집
if (isset($options['edit'])) {
$editor = getenv('EDITOR') ?: 'vi';
passthru("$editor " . escapeshellarg(__FILE__));
$configFile = getenv('HOME') . '/.pty[Service]Config.ini';
passthru("$editor " . escapeshellarg($configFile));
exit(0);
}
......@@ -153,7 +154,7 @@ if (isset($options['help'])) {
echo "옵션:\n";
echo " --dry-run 실제 실행 없이 대상 목록만 출력\n";
echo " --verbose 상세 로그 출력\n";
echo " --edit 이 스크립트를 에디터로 열기\n";
echo " --edit 설정 파일을 에디터로 열기\n";
echo " --help 도움말 출력\n";
echo "\n";
// 설정 파일 예시 출력 (해당 시)
......@@ -162,11 +163,12 @@ if (isset($options['help'])) {
}
// ============================================================
// 2. --edit: 스크립트 편집
// 2. --edit: 설정 파일 편집
// ============================================================
if (isset($options['edit'])) {
$editor = getenv('EDITOR') ?: 'vi';
passthru("$editor " . escapeshellarg(__FILE__));
$configFile = getenv('HOME') . '/.pty[Service]Config.ini';
passthru("$editor " . escapeshellarg($configFile));
exit(0);
}
......@@ -243,10 +245,11 @@ if ($dryRun) {
### --edit 구현 패턴
```php
// 도움말 처리보다 먼저 위치 (인자 없이도 동작해야 함)
// 도움말 처리 이후에 위치 (인자 없이도 동작해야 함)
if (isset($options['edit'])) {
$editor = getenv('EDITOR') ?: 'vi';
passthru("$editor " . escapeshellarg(__FILE__));
$configFile = getenv('HOME') . '/.pty[Service]Config.ini'; // 서비스별 설정 파일
passthru("$editor " . escapeshellarg($configFile));
exit(0);
}
```
......@@ -819,7 +822,7 @@ mysqldump를 사용하여 테이블을 백업합니다.
./ptyMysqlBackup mydb users --output=/backup # 지정 경로에 저장
./ptyMysqlBackup '*' '*' --dry-run # 백업 대상만 미리보기
./ptyMysqlBackup '*' '*' --ignore-x=false # x_ 접두사 포함 전체 백업
./ptyMysqlBackup mydb users --tgz # mydb.users.tgz 생성 (압축)
./ptyMysqlBackup mydb users --no-tgz # mydb.users.sql 생성 (압축 안 함)
```
**옵션:**
......@@ -829,13 +832,13 @@ mysqldump를 사용하여 테이블을 백업합니다.
| `--mysql=섹션명` | INI 파일 섹션 | `default` |
| `--output=경로` | 출력 디렉토리 | `.` |
| `--ignore-x=true\|false` | x_ 접두사 DB/테이블 무시 | `true` |
| `--tgz` | 백업 후 .tgz로 압축 (원본 .sql 삭제) | - |
| `--no-tgz` | .tgz 압축 안 함 | 압축 사용 |
| `--dry-run` | 실제 백업 없이 대상 목록만 출력 | - |
| `--verbose` | 상세 로그 출력 | - |
| `--edit` | 스크립트를 에디터로 열기 | - |
**백업 파일:**
- 파일명 형식: `{database}.{table}.sql` 또는 `{database}.{table}.tgz` (--tgz 사용 시)
- 파일명 형식: `{database}.{table}.tgz` (기본값) 또는 `{database}.{table}.sql` (--no-tgz 사용 시)
- 파일 헤더에 백업 시간, 실행 명령어 포함
- `x_` 접두사 DB/테이블은 기본 스킵 (`--ignore-x=false`로 포함 가능)
......
......@@ -221,7 +221,7 @@ ptyCronBuild 'ptyRun "php /path/to/script.php" --max-run-time=10' --daily-10min
|------|------|
| `--help` | 도움말 출력 |
| `--verbose` | 상세 로그 출력 |
| `--edit` | 스크립트를 에디터로 열기 |
| `--edit` | 설정 파일을 에디터로 열기 |
| `--dry-run` | 실제 실행 없이 미리보기 (데이터 변경 스크립트) |
서비스별 섹션 지정:
......
......@@ -87,10 +87,11 @@ class ptyMysqlConfig
* mysqli 연결 생성
*
* @param string $section INI 파일 섹션명 (기본값: default)
* @param bool $useDatabase database 설정 사용 여부 (기본값: true)
* @return array [connection => mysqli, config => array]
* @throws \Exception 연결 실패 시
*/
public static function connect($section = 'default')
public static function connect($section = 'default', $useDatabase = true)
{
$config = self::load($section);
......@@ -98,7 +99,7 @@ class ptyMysqlConfig
$config['host'],
$config['username'],
$config['password'],
$config['database']
$useDatabase ? $config['database'] : null
);
if (!$connection) {
......
......@@ -24,7 +24,7 @@ $verbose = isset($options['verbose']);
$outputDir = isset($options['output']) ? $options['output'] : '.';
$ignoreX = (isset($options['ignore-x']) ? $options['ignore-x'] : 'true') !== 'false'; // 기본값: true
$dryRun = isset($options['dry-run']);
$useTgz = isset($options['tgz']);
$useTgz = !isset($options['no-tgz']); // 기본값: tgz 압축 사용
// --edit 옵션: 스크립트 편집
if (isset($options['edit'])) {
......@@ -46,7 +46,7 @@ if (count($positionalArgs) < 2 || isset($options['help'])) {
echo " --mysql=섹션명 INI 파일 섹션 (기본값: default)\n";
echo " --output=경로 출력 디렉토리 (기본값: 현재 디렉토리)\n";
echo " --ignore-x=true|false x_ 접두사 DB/테이블 무시 (기본값: true)\n";
echo " --tgz 백업 후 .tgz로 압축 (원본 .sql 삭제)\n";
echo " --no-tgz .tgz 압축 안 함 (기본값: 압축)\n";
echo " --dry-run 실제 백업 없이 대상 목록만 출력\n";
echo " --verbose 상세 로그 출력\n";
echo " --edit 이 스크립트를 에디터로 열기\n";
......@@ -59,7 +59,7 @@ if (count($positionalArgs) < 2 || isset($options['help'])) {
echo " {$argv[0]} mydb users --output=/backup # /backup/mydb.users.sql 생성\n";
echo " {$argv[0]} mydb users --mysql=production # production 섹션 사용\n";
echo " {$argv[0]} '*' '*' --ignore-x=false # x_ 접두사 포함 전체 백업\n";
echo " {$argv[0]} mydb users --tgz # mydb.users.tgz 생성 (압축)\n";
echo " {$argv[0]} mydb users --no-tgz # mydb.users.sql 생성 (압축 안 함)\n";
echo "\n";
echo "기본 mysqldump 옵션:\n";
echo " --default-character-set=utf8mb4\n";
......@@ -204,8 +204,9 @@ function formatBytes($bytes) {
}
try {
// MySQL 연결
$conn = ptyMysqlConfig::connect($mysqlSection);
// MySQL 연결 (* 패턴일 경우 database 설정 무시)
$useDatabase = ($dbPattern !== '*');
$conn = ptyMysqlConfig::connect($mysqlSection, $useDatabase);
$connection = $conn['connection'];
$config = $conn['config'];
......
......@@ -18,7 +18,7 @@ require_once __DIR__ . '/ptyLibrary_PHP/mysql/ptyMysqlConfig.php';
$parsed = ptyCliOptionParser::parse($argv);
$positionalArgs = $parsed['positional'];
$options = $parsed['options'];
$mysqlSection = $options['mysql'] ?? 'default';
$mysqlSection = isset($options['mysql']) ? $options['mysql'] : 'default';
// 도움말
if (isset($options['help'])) {
......@@ -83,8 +83,8 @@ function formatUptime($seconds) {
}
try {
// MySQL 연결
$conn = ptyMysqlConfig::connect($mysqlSection);
// MySQL 연결 (database 설정 무시 - 서버 전체 정보 조회)
$conn = ptyMysqlConfig::connect($mysqlSection, false);
$connection = $conn['connection'];
$config = $conn['config'];
......@@ -256,9 +256,9 @@ try {
$userCount = 0;
while ($row = mysqli_fetch_assoc($result)) {
$userCount++;
$locked = $row['account_locked'] ?? 'N';
$expired = $row['password_expired'] ?? 'N';
$hasPw = $row['has_password'] ?? '-';
$locked = isset($row['account_locked']) ? $row['account_locked'] : 'N';
$expired = isset($row['password_expired']) ? $row['password_expired'] : 'N';
$hasPw = isset($row['has_password']) ? $row['has_password'] : '-';
$lockedColor = ($locked === 'Y') ? $RED : $GREEN;
$expiredColor = ($expired === 'Y') ? $RED : $GREEN;
......@@ -293,10 +293,10 @@ try {
while ($row = mysqli_fetch_assoc($result)) {
$processCount++;
$host = substr($row['Host'], 0, 20);
$db = $row['db'] ?? '-';
$state = $row['State'] ?? '-';
$command = $row['Command'] ?? '-';
$info = $row['Info'] ?? null;
$db = isset($row['db']) ? $row['db'] : '-';
$state = isset($row['State']) ? $row['State'] : '-';
$command = isset($row['Command']) ? $row['Command'] : '-';
$info = isset($row['Info']) ? $row['Info'] : null;
printf(" %-7s %-12s %-20s %-12s %-6s %-10s %-20s\n",
$row['Id'],
......@@ -388,7 +388,7 @@ try {
$result = mysqli_query($connection, "SHOW VARIABLES WHERE Variable_name IN ('" . implode("','", array_keys($moreVars)) . "')");
while ($row = mysqli_fetch_assoc($result)) {
$varName = $row['Variable_name'];
$label = $moreVars[$varName] ?? $varName;
$label = isset($moreVars[$varName]) ? $moreVars[$varName] : $varName;
$value = $row['Value'];
// 바이트 값 포맷팅
......
#!/usr/bin/env php
<?php
/**
* ptyMysqlQuery
*
* MySQL 쿼리 실행 도구
* 설정 파일: ~/.ptyMysqlConfig.ini
*
* Usage: ./ptyMysqlQuery "SQL" [options]
*/
namespace platyFramework;
require_once __DIR__ . '/ptyLibrary_PHP/cli/ptyCliOptionParser.php';
require_once __DIR__ . '/ptyLibrary_PHP/mysql/ptyMysqlConfig.php';
// 인자 파싱
$parsed = ptyCliOptionParser::parse($argv);
$positionalArgs = $parsed['positional'];
$options = $parsed['options'];
$mysqlSection = isset($options['mysql']) ? $options['mysql'] : 'default';
$verbose = isset($options['verbose']);
$showTable = isset($options['table']);
$showJson = isset($options['json']);
$showDump = isset($options['dump']);
$showCsv = isset($options['csv']);
$showMarkdown = isset($options['markdown']);
// ============================================================
// 1. --help: 최우선 처리
// ============================================================
if (isset($options['help'])) {
echo "사용법: {$argv[0]} \"SQL\" [옵션]\n";
echo "\n";
echo "인자:\n";
echo " SQL 실행할 SQL 쿼리\n";
echo "\n";
echo "옵션:\n";
echo " --mysql=섹션명 INI 파일 섹션 (기본값: default)\n";
echo " --database=DB명 데이터베이스 지정 (미지정시 INI 설정 사용)\n";
echo " --table 테이블 형태로 출력 (기본값: key:value 형태)\n";
echo " --json JSON 형태로 출력\n";
echo " --dump INSERT INTO SQL 형태로 출력\n";
echo " --csv CSV 형태로 출력\n";
echo " --markdown Markdown 테이블 형태로 출력\n";
echo " --verbose 상세 로그 출력\n";
echo " --edit 설정 파일을 에디터로 열기\n";
echo " --help 도움말 출력\n";
echo "\n";
echo "예시:\n";
echo " {$argv[0]} \"SELECT * FROM users LIMIT 10\"\n";
echo " {$argv[0]} \"SELECT * FROM users\" --table\n";
echo " {$argv[0]} \"SELECT * FROM users\" --json\n";
echo " {$argv[0]} \"SELECT * FROM users\" --dump\n";
echo " {$argv[0]} \"SELECT * FROM users\" --csv\n";
echo " {$argv[0]} \"SELECT * FROM users\" --markdown\n";
echo " {$argv[0]} \"SELECT * FROM users\" --mysql=production\n";
echo " {$argv[0]} \"SELECT * FROM users\" --database=mydb\n";
echo " {$argv[0]} \"SHOW TABLES\"\n";
echo " {$argv[0]} \"DESCRIBE users\"\n";
echo "\n";
echo "설정 파일: ~/.ptyMysqlConfig.ini\n";
echo ptyMysqlConfig::getConfigExample() . "\n";
exit(0);
}
// ============================================================
// 2. --edit: 설정 파일 편집
// ============================================================
if (isset($options['edit'])) {
$editor = getenv('EDITOR') ? getenv('EDITOR') : 'vi';
$configFile = getenv('HOME') . '/.ptyMysqlConfig.ini';
passthru("$editor " . escapeshellarg($configFile));
exit(0);
}
// ============================================================
// 3. 필수 인자 검증
// ============================================================
if (count($positionalArgs) < 1) {
echo "Error: SQL 쿼리가 필요합니다.\n";
echo "도움말: {$argv[0]} --help\n";
exit(1);
}
$sql = $positionalArgs[0];
// ANSI 색상 코드
$RED = "\033[1;31m";
$GREEN = "\033[1;32m";
$YELLOW = "\033[1;33m";
$CYAN = "\033[1;36m";
$MAGENTA = "\033[1;35m";
$RESET = "\033[0m";
// 한글 포함 문자열 너비 계산
function getDisplayWidth($str) {
$width = 0;
$len = mb_strlen($str, 'UTF-8');
for ($i = 0; $i < $len; $i++) {
$char = mb_substr($str, $i, 1, 'UTF-8');
$ord = mb_ord($char, 'UTF-8');
// CJK 문자 범위 (한글, 한자, 일본어 등)
if ($ord >= 0x1100 && $ord <= 0x11FF || // 한글 자모
$ord >= 0x3000 && $ord <= 0x9FFF || // CJK
$ord >= 0xAC00 && $ord <= 0xD7AF || // 한글 음절
$ord >= 0xF900 && $ord <= 0xFAFF || // CJK 호환
$ord >= 0xFF00 && $ord <= 0xFFEF) { // 전각 문자
$width += 2;
} else {
$width += 1;
}
}
return $width;
}
// mb_ord 폴리필 (PHP 7.2 미만)
if (!function_exists('mb_ord')) {
function mb_ord($char, $encoding = 'UTF-8') {
$result = unpack('N', mb_convert_encoding($char, 'UCS-4BE', $encoding));
return $result[1];
}
}
// 문자열 패딩 (한글 지원)
function padString($str, $width, $align = 'left') {
$displayWidth = getDisplayWidth($str);
$padding = $width - $displayWidth;
if ($padding <= 0) {
return $str;
}
if ($align === 'right') {
return str_repeat(' ', $padding) . $str;
}
return $str . str_repeat(' ', $padding);
}
// 값 포맷팅 (NULL, 긴 문자열 처리)
function formatValue($value, $maxLen = 100) {
if ($value === null) {
return 'NULL';
}
$value = str_replace(array("\r\n", "\r", "\n"), ' ', $value);
if (mb_strlen($value) > $maxLen) {
return mb_substr($value, 0, $maxLen - 3) . '...';
}
return $value;
}
// 테이블 형태 출력 함수
function printAsTable($rows, $columns, $colors) {
extract($colors);
$widths = array();
foreach ($columns as $col) {
$widths[$col] = getDisplayWidth($col);
}
foreach ($rows as $row) {
foreach ($columns as $col) {
$value = formatValue($row[$col], 50);
$w = getDisplayWidth($value);
if ($w > $widths[$col]) {
$widths[$col] = $w;
}
}
}
// 최대 너비 제한
foreach ($widths as $col => $w) {
if ($w > 50) {
$widths[$col] = 50;
}
}
// 헤더 출력
$headerLine = "";
$separatorLine = "";
foreach ($columns as $col) {
$headerLine .= padString($col, $widths[$col]) . " ";
$separatorLine .= str_repeat("-", $widths[$col]) . " ";
}
echo "{$CYAN}" . rtrim($headerLine) . "{$RESET}\n";
echo rtrim($separatorLine) . "\n";
// 데이터 출력
foreach ($rows as $row) {
$line = "";
foreach ($columns as $col) {
$value = formatValue($row[$col], 50);
if ($row[$col] === null) {
$line .= "{$MAGENTA}" . padString($value, $widths[$col]) . "{$RESET} ";
} else {
$line .= padString($value, $widths[$col]) . " ";
}
}
echo rtrim($line) . "\n";
}
}
// CSV 형태 출력 함수
function printAsCsv($rows, $columns) {
// 헤더
$header = array();
foreach ($columns as $col) {
$header[] = '"' . str_replace('"', '""', $col) . '"';
}
echo implode(',', $header) . "\n";
// 데이터
foreach ($rows as $row) {
$values = array();
foreach ($columns as $col) {
$value = $row[$col];
if ($value === null) {
$values[] = '';
} else {
$values[] = '"' . str_replace('"', '""', $value) . '"';
}
}
echo implode(',', $values) . "\n";
}
}
// Markdown 테이블 형태 출력 함수
function printAsMarkdown($rows, $columns) {
// 헤더
echo '| ' . implode(' | ', $columns) . " |\n";
// 구분선
$separators = array();
foreach ($columns as $col) {
$separators[] = '---';
}
echo '| ' . implode(' | ', $separators) . " |\n";
// 데이터
foreach ($rows as $row) {
$values = array();
foreach ($columns as $col) {
$value = $row[$col];
if ($value === null) {
$values[] = 'NULL';
} else {
// 파이프와 줄바꿈 이스케이프
$value = str_replace(array('|', "\n", "\r"), array('\\|', ' ', ''), $value);
$values[] = $value;
}
}
echo '| ' . implode(' | ', $values) . " |\n";
}
}
// INSERT INTO SQL 형태 출력 함수
function printAsDump($rows, $columns, $tableName, $connection) {
foreach ($rows as $row) {
$values = array();
foreach ($columns as $col) {
$value = $row[$col];
if ($value === null) {
$values[] = 'NULL';
} else {
$values[] = "'" . mysqli_real_escape_string($connection, $value) . "'";
}
}
$sql = "INSERT INTO `" . $tableName . "` (`" . implode("`, `", $columns) . "`) VALUES (" . implode(", ", $values) . ");";
echo $sql . "\n";
}
}
// SQL에서 테이블명 추출
function extractTableName($sql) {
// SELECT ... FROM table_name 패턴
if (preg_match('/\bFROM\s+[`"]?(\w+)[`"]?/i', $sql, $matches)) {
return $matches[1];
}
return 'table_name';
}
// key:value 형태 출력 함수
function printAsKeyValue($rows, $columns, $colors) {
extract($colors);
// 컬럼명 최대 너비 계산
$maxKeyWidth = 0;
foreach ($columns as $col) {
$w = getDisplayWidth($col);
if ($w > $maxKeyWidth) {
$maxKeyWidth = $w;
}
}
$rowNum = 0;
foreach ($rows as $row) {
$rowNum++;
// 행 구분선
if ($rowNum > 1) {
echo "\n";
}
// 행 번호 (여러 행일 때만)
if (count($rows) > 1) {
echo "{$YELLOW}--- [$rowNum] ---{$RESET}\n";
}
foreach ($columns as $col) {
$value = $row[$col];
$formattedValue = formatValue($value);
$paddedKey = padString($col, $maxKeyWidth);
if ($value === null) {
echo "{$CYAN}{$paddedKey}{$RESET}: {$MAGENTA}{$formattedValue}{$RESET}\n";
} else {
echo "{$CYAN}{$paddedKey}{$RESET}: {$formattedValue}\n";
}
}
}
}
try {
// MySQL 설정 로드
$config = ptyMysqlConfig::load($mysqlSection);
// --database 옵션이 있으면 우선 사용
$database = isset($options['database']) ? $options['database'] : $config['database'];
// 연결
$connection = mysqli_connect(
$config['host'],
$config['username'],
$config['password'],
$database
);
if (!$connection) {
throw new \Exception("MySQL 연결 실패: " . mysqli_connect_error());
}
if (!empty($config['charset'])) {
mysqli_set_charset($connection, $config['charset']);
}
// 데이터 출력 모드가 아닐 때만 정보 표시
$dataOnlyMode = $showJson || $showDump || $showCsv || $showMarkdown;
if (!$dataOnlyMode) {
echo "{$CYAN}Section:{$RESET} {$mysqlSection}";
echo " {$CYAN}Host:{$RESET} {$config['host']}";
echo " {$CYAN}Database:{$RESET} " . ($database ? $database : '(none)') . "\n";
echo "{$CYAN}SQL:{$RESET} $sql\n";
echo str_repeat("-", 60) . "\n";
}
// 쿼리 실행
$startTime = microtime(true);
$result = mysqli_query($connection, $sql);
$endTime = microtime(true);
$elapsed = ($endTime - $startTime) * 1000; // ms
if ($result === false) {
throw new \Exception("쿼리 실행 실패: " . mysqli_error($connection));
}
// SELECT 등 결과셋이 있는 경우
if ($result instanceof \mysqli_result) {
$rows = array();
while ($row = mysqli_fetch_assoc($result)) {
$rows[] = $row;
}
$rowCount = count($rows);
if ($rowCount === 0) {
echo "{$YELLOW}결과 없음{$RESET}\n";
} else {
$columns = array_keys($rows[0]);
$colors = array(
'RED' => $RED,
'GREEN' => $GREEN,
'YELLOW' => $YELLOW,
'CYAN' => $CYAN,
'MAGENTA' => $MAGENTA,
'RESET' => $RESET
);
if ($showJson) {
// JSON 출력 (아래에서 처리)
} elseif ($showDump) {
$tableName = extractTableName($sql);
printAsDump($rows, $columns, $tableName, $connection);
} elseif ($showCsv) {
printAsCsv($rows, $columns);
} elseif ($showMarkdown) {
printAsMarkdown($rows, $columns);
} elseif ($showTable) {
printAsTable($rows, $columns, $colors);
} else {
printAsKeyValue($rows, $columns, $colors);
}
}
mysqli_free_result($result);
// JSON 출력
if ($showJson) {
$output = array(
'rows' => $rows,
'count' => $rowCount,
'elapsed_ms' => round($elapsed, 2)
);
echo json_encode($output, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT) . "\n";
} elseif ($showDump || $showCsv || $showMarkdown) {
// dump/csv/markdown 모드는 데이터만 출력
} else {
echo "\n";
echo "{$GREEN}$rowCount{$RESET}";
// 실행 시간 출력
if ($elapsed < 1000) {
$elapsedStr = sprintf("%.2f ms", $elapsed);
} else {
$elapsedStr = sprintf("%.2f sec", $elapsed / 1000);
}
echo " ({$CYAN}$elapsedStr{$RESET})\n";
}
} else {
// INSERT, UPDATE, DELETE 등
$affectedRows = mysqli_affected_rows($connection);
if ($showJson) {
$output = array(
'affected_rows' => $affectedRows,
'elapsed_ms' => round($elapsed, 2)
);
echo json_encode($output, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT) . "\n";
} else {
echo "{$GREEN}$affectedRows 행 영향 받음{$RESET}";
// 실행 시간 출력
if ($elapsed < 1000) {
$elapsedStr = sprintf("%.2f ms", $elapsed);
} else {
$elapsedStr = sprintf("%.2f sec", $elapsed / 1000);
}
echo " ({$CYAN}$elapsedStr{$RESET})\n";
}
}
mysqli_close($connection);
} catch (\Exception $e) {
echo "{$RED}Error:{$RESET} " . $e->getMessage() . "\n";
exit(1);
}
......@@ -234,8 +234,8 @@ function restoreFile($host, $user, $password, $dbName, $tableName, $sqlFile, $ve
}
try {
// MySQL 연결 (DB 목록 조회용)
$conn = ptyMysqlConfig::connect($mysqlSection);
// MySQL 연결 (database 설정 무시 - 여러 DB에 복원 가능)
$conn = ptyMysqlConfig::connect($mysqlSection, false);
$connection = $conn['connection'];
$config = $conn['config'];
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment