Skip to content

Commit e03bfc9

Browse files
committed
fix: Implement robust SQL identifier quoting
This addresses a potential issue where JSON keys containing double quotes could lead to SQL syntax errors during table creation, alteration, or data insertion. Introduced a quoteIdentifier helper function and applied it consistently.
1 parent cd7aab3 commit e03bfc9

File tree

1 file changed

+17
-6
lines changed

1 file changed

+17
-6
lines changed

main.go

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,12 @@ func openDatabase(dbPath string) (*sql.DB, error) {
110110
return db, nil
111111
}
112112

113+
// quoteIdentifier はSQLiteの識別子を正しく引用符で囲みます。
114+
// 識別子内の二重引用符は二重にエスケープされます。
115+
func quoteIdentifier(name string) string {
116+
return `"` + strings.ReplaceAll(name, `"`, `""`) + `"`
117+
}
118+
113119
func inferSchema(data []map[string]interface{}) map[string]string {
114120
columnTypes := make(map[string]string)
115121
for _, row := range data {
@@ -157,10 +163,10 @@ func setupTable(db *sql.DB, tableName string, data []map[string]interface{}) ([]
157163
if !tableExists {
158164
var columns []string
159165
for name, colType := range inferredSchema {
160-
columns = append(columns, fmt.Sprintf("\"%s\" %s", name, colType))
166+
columns = append(columns, fmt.Sprintf("%s %s", quoteIdentifier(name), colType))
161167
}
162168
sort.Strings(columns) // Ensure consistent order for CREATE TABLE
163-
createQuery := fmt.Sprintf("CREATE TABLE \"%s\" (%s)", tableName, strings.Join(columns, ", "))
169+
createQuery := fmt.Sprintf("CREATE TABLE %s (%s)", quoteIdentifier(tableName), strings.Join(columns, ", "))
164170
_, err := db.Exec(createQuery)
165171
if err != nil {
166172
return nil, fmt.Errorf("failed to create table: %w", err)
@@ -170,8 +176,7 @@ func setupTable(db *sql.DB, tableName string, data []map[string]interface{}) ([]
170176
// Use string concatenation for PRAGMA to avoid any Sprintf formatting issues.
171177
// Table names can't be parameterized in PRAGMA statements.
172178
pragmaQuery := "PRAGMA table_info(" + `"` + strings.ReplaceAll(tableName, `"`, `""`) + `"` + ")"
173-
174-
rows, err := db.Query(pragmaQuery)
179+
rows, err := db.Query(pragmaQuery)
175180
if err != nil {
176181
return nil, fmt.Errorf("failed to get existing table info: %w", err)
177182
}
@@ -193,7 +198,7 @@ rows, err := db.Query(pragmaQuery)
193198

194199
for colName, colType := range inferredSchema {
195200
if !existingColumns[colName] {
196-
alterQuery := fmt.Sprintf("ALTER TABLE \"%s\" ADD COLUMN \"%s\" %s", tableName, colName, colType)
201+
alterQuery := fmt.Sprintf("ALTER TABLE %s ADD COLUMN %s %s", quoteIdentifier(tableName), quoteIdentifier(colName), colType)
197202
_, err := db.Exec(alterQuery)
198203
if err != nil {
199204
return nil, fmt.Errorf("failed to add column '%s': %w", colName, err)
@@ -219,7 +224,13 @@ func insertData(db *sql.DB, tableName string, columns []string, data []map[strin
219224
placeholders := strings.Repeat("?,", len(columns))
220225
placeholders = placeholders[:len(placeholders)-1]
221226

222-
query := fmt.Sprintf("INSERT INTO \"%s\" (%s) VALUES (%s)", tableName, "\""+strings.Join(columns, "\", \"")+"\"", placeholders)
227+
// Build the quoted column names for the INSERT statement
228+
quotedColumns := make([]string, len(columns))
229+
for i, col := range columns {
230+
quotedColumns[i] = quoteIdentifier(col)
231+
}
232+
233+
query := fmt.Sprintf("INSERT INTO %s (%s) VALUES (%s)", quoteIdentifier(tableName), strings.Join(quotedColumns, ", "), placeholders)
223234

224235
tx, err := db.Begin()
225236
if err != nil {

0 commit comments

Comments
 (0)