-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.go
More file actions
136 lines (113 loc) · 2.77 KB
/
Copy pathmain.go
File metadata and controls
136 lines (113 loc) · 2.77 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
package main
import (
"bufio"
"flag"
"fmt"
"log"
"net"
"os"
"sqlrepl/internal/client"
"sqlrepl/internal/database"
"sqlrepl/internal/protocol"
)
const (
defaultListenAddress = 8080
)
var (
// Flags
dbType = flag.String("t", "", "Database type (oracle, mysql, postgres, sqlite3)")
dbConnString = flag.String("c", "", "Database connection string")
listenAddress = flag.Int("p", defaultListenAddress, "Address to listen on in server mode")
)
func main() {
flag.Parse()
args := flag.Args()
// Check for positional arguments for interactive mode
if len(args) == 2 {
runInteractive(args[0], args[1])
return
}
// Use flags if provided
if *dbType != "" && *dbConnString != "" {
runInteractive(*dbType, *dbConnString)
return
}
// Run in server mode if no flags are provided
if len(args) == 0 {
runServer(*listenAddress)
return
}
// Otherwise, print usage
fmt.Println("Usage:")
fmt.Println(" sqlrepl <dbtype> <connstring> (Interactive mode)")
fmt.Println(" sqlrepl -p <port> (Server mode)")
flag.PrintDefaults()
os.Exit(1)
}
func runInteractive(dbType, dbConnString string) {
dbconn := database.Connection{}
err := dbconn.Connect(dbType, dbConnString)
if err != nil {
log.Fatalf("Error connecting to database: %v", err)
}
defer dbconn.Close()
fmt.Println("Connected. Enter SQL queries (or 'exit' to quit):")
scanner := bufio.NewScanner(os.Stdin)
for {
fmt.Print("> ")
if !scanner.Scan() {
break // Exit on Ctrl+D
}
query := scanner.Text()
if query == "exit" {
break
}
result := dbconn.Query(query)
if result == nil {
log.Printf("Result returned from executeQuery was nil: %v", err)
return
}
printQueryResult(result) // Helper function to format and print result
}
if err := scanner.Err(); err != nil {
log.Println("Error reading input:", err)
}
}
func runServer(listenAddress int) {
listener, err := net.Listen("tcp", fmt.Sprintf(":%d", listenAddress))
if err != nil {
log.Fatalf("Error listening: %v", err)
}
defer listener.Close()
fmt.Printf("SQL REPL server listening on %d\n", listenAddress)
for {
conn, err := listener.Accept()
if err != nil {
log.Printf("Error accepting connection: %v", err)
continue
}
log.Printf("Accepted connection from %s\n", conn.RemoteAddr().String())
go client.Handle(conn) // Delegate to client handler (modified)
}
}
func printQueryResult(result *protocol.QueryResult) {
if result.Error != "" {
fmt.Println("Error:", result.Error)
return
}
if len(result.Columns) > 0 {
for _, col := range result.Columns {
fmt.Printf("%s\t", col)
}
fmt.Println()
}
for _, row := range result.Rows {
for i := range result.Columns {
fmt.Printf("%v\t", row.Values[i])
}
fmt.Println()
}
if result.Message != "" {
fmt.Println(result.Message)
}
}