Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added create table Interface in ISQL #14

Merged
merged 4 commits into from
May 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,36 @@ func main() {
response = append(response, table)
}
fmt.Println(response)

table := types.Table{
Name: "user",
Columns: []types.Column{
{
Name: "id",
Type: "int",
IsNullable: "NO",
DefaultValue: sql.NullString{String: "", Valid: false},
IsPrimary: true,
IsUnique: sql.NullString{String: "YES", Valid: true},
},
{
Name: "name",
Type: "varchar(255)",
IsNullable: "NO",
DefaultValue: sql.NullString{String: "", Valid: false},
IsPrimary: false,
IsUnique: sql.NullString{String: "NO", Valid: true},
},
{
Name: "age",
Type: "int",
IsNullable: "YES",
},
},
}

query := client.GenerateCreateTableQuery(table)
fmt.Println(query)
}

```
Expand All @@ -90,6 +120,11 @@ docker run -d --name postgres \
postgres:13.2-alpine
```

- Set Password in env variable
```bash
export DB_PASSWORD=root
```

- To inspect and execute queries in Postgres database, Create a main.go file and adding the below example into it.

```
Expand Down Expand Up @@ -148,6 +183,10 @@ go run main.go

- To inspect and execute queries in snowflake database, Create a main.go file and adding the below example into it.

- Set Password in env variable
```bash
export DB_PASSWORD=<DB_PASSWORD>
```

```
package main
Expand Down
51 changes: 51 additions & 0 deletions databases/bigquery/bigquery.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"database/sql"
"encoding/json"
"fmt"
"strings"

"cloud.google.com/go/bigquery"
"github.com/thesaas-company/xray/config"
Expand Down Expand Up @@ -145,3 +146,53 @@ func (b *BigQuery) Tables(Dataset string) ([]string, error) {

return tables, nil
}

func (b *BigQuery) GenerateCreateTableQuery(table types.Table) string {

query := "CREATE TABLE " + table.Dataset + "." + table.Name + " ("
for i, column := range table.Columns {
colType := strings.ToUpper(column.Type)
query += column.Name + " " + convertTypeToBigQuery(colType)

if column.IsPrimary {
query += " OPTIONS (description = 'Primary key') GENERATED BY DEFAULT AS IDENTITY"
}

if column.DefaultValue.Valid {
query += fmt.Sprintf(" OPTIONS (description = 'Default value: %s')", column.DefaultValue.String)
}

if column.IsUnique.String == "YES" && !column.IsPrimary {
query += " OPTIONS (description = 'Unique constraint')"
}

if i < len(table.Columns)-1 {
query += ", "
}
}
query += ");"
return query
}

func convertTypeToBigQuery(dataType string) string {
// Map column types to BigQuery equivalents
switch dataType {
case "INT":
return "INT64"
case "VARCHAR(255)", "TEXT":
return "STRING"
case "INTEGER":
return "INT64"
case "FLOAT":
return "FLOAT64"
case "BOOLEAN":
return "BOOL"
case "DATE":
return "DATE"
case "DATETIME", "TIMESTAMP":
return "TIMESTAMP"
// Add more type conversions as needed
default:
return dataType
}
}
50 changes: 50 additions & 0 deletions databases/bigquery/bigquery_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package bigquery

import (
"database/sql"
"fmt"
"testing"

Expand Down Expand Up @@ -32,6 +33,11 @@ func (m *MockBigQuery) Tables(dataset string) ([]string, error) {
return args.Get(0).([]string), args.Error(1)
}

func (m *MockBigQuery) GenerateCreateTableQuery(table types.Table) string {
args := m.Called(table)
return args.Get(0).(string)
}

// TestBigQuery_Schema is a unit test function that tests the Schema method of the BigQuery struct.
// It creates a mock instance of BigQuery, sets the expected return values, and calls the method under test.
// It then asserts the expected return values and checks if the method was called with the correct arguments.
Expand Down Expand Up @@ -113,3 +119,47 @@ func TestBigQuery_Tables(t *testing.T) {
mockBigQuery.AssertCalled(t, "Tables", "dataset")
fmt.Println(expectedTables, actualTables)
}

func TestGenerateCreateTableQuery(t *testing.T) {
table := types.Table{
Name: "user",
Dataset: "Datasherlocks",
Columns: []types.Column{
{
Name: "id",
Type: "int",
IsNullable: "NO",
DefaultValue: sql.NullString{String: "", Valid: false},
IsPrimary: true,
IsUnique: sql.NullString{String: "YES", Valid: true},
},
{
Name: "name",
Type: "VARCHAR(255)",
IsNullable: "NO",
DefaultValue: sql.NullString{String: "", Valid: false},
IsPrimary: false,
IsUnique: sql.NullString{String: "YES", Valid: true},
},
{
Name: "age",
Type: "INT",
IsNullable: "YES",
},
},
}

// Create a new instance of the mock
mockBigQuery := new(MockBigQuery)

// Set the expected return values
expectedQuery := "CREATE TABLE Datasherlocks.user (id int PRIMARY KEY, name VARCHAR(255) UNIQUE, age INT);"

mockBigQuery.On("GenerateCreateTableQuery", table).Return(expectedQuery)

// Call the method under test
query := mockBigQuery.GenerateCreateTableQuery(table)

// Assert the expected return values
assert.Equal(t, expectedQuery, query)
}
30 changes: 30 additions & 0 deletions databases/mysql/mysql.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"encoding/json"
"fmt"
"os"
"strings"

_ "github.com/go-sql-driver/mysql"
"github.com/thesaas-company/xray/config"
Expand Down Expand Up @@ -173,6 +174,35 @@ func (m *MySQL) Tables(databaseName string) ([]string, error) {
return tables, nil
}

// GenerateCreateTableQuery generates a SQL query to create a table with the same structure as the input table.
func (m *MySQL) GenerateCreateTableQuery(table types.Table) string {
query := "CREATE TABLE " + table.Name + " ("
for i, column := range table.Columns {
colType := strings.ToUpper(column.Type)
query += column.Name + " " + colType
if column.AutoIncrement {
query += " AUTO_INCREMENT"
}
if column.IsPrimary {
query += " PRIMARY KEY"
}
if column.DefaultValue.Valid {
query += " DEFAULT " + column.DefaultValue.String
}
if column.IsUnique.String == "YES" && !column.IsPrimary {
query += " UNIQUE"
}
if column.IsNullable == "NO" && !column.IsPrimary {
query += " NOT NULL"
}
if i < len(table.Columns)-1 {
query += ", "
}
}
query += ")"
return query
}

// Create a new MySQL connection URL with the given configuration.
func dbURLMySQL(dbConfig *config.Config) string {
return fmt.Sprintf(
Expand Down
47 changes: 47 additions & 0 deletions databases/mysql/mysql_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,3 +119,50 @@ func TestGetTableName(t *testing.T) {
t.Errorf("there were unfulfilled expectations: %s", err)
}
}

func TestGenerateCreateTablequery(t *testing.T) {
db, mock := MockDB()
defer db.Close()

table := types.Table{
Name: "user",
Columns: []types.Column{
{
Name: "id",
Type: "int",
IsNullable: "NO",
DefaultValue: sql.NullString{String: "", Valid: false},
IsPrimary: true,
IsUnique: sql.NullString{String: "YES", Valid: true},
},
{
Name: "name",
Type: "varchar(255)",
IsNullable: "NO",
DefaultValue: sql.NullString{String: "", Valid: false},
IsPrimary: false,
IsUnique: sql.NullString{String: "NO", Valid: true},
},
{
Name: "age",
Type: "int",
IsNullable: "YES",
},
},
}

m := &MySQL{Client: db}
query := m.GenerateCreateTableQuery(table)

fmt.Printf("Create table query: %s\n", query)

expectedQuery := "CREATE TABLE user (id INT PRIMARY KEY, name VARCHAR(255) NOT NULL, age INT)"
if query != expectedQuery {
t.Errorf("Expected '%s', but got '%s'", expectedQuery, query)
}

if err := mock.ExpectationsWereMet(); err != nil {
t.Errorf("there were unfulfilled expectations: %s", err)
}

}
25 changes: 25 additions & 0 deletions databases/postgres/postgres.go
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,31 @@ func (p *Postgres) Tables(databaseName string) ([]string, error) {
return tables, nil
}

func (p *Postgres) GenerateCreateTableQuery(table types.Table) string {
query := `CREATE TABLE "` + table.Name + `" (`
for i, col := range table.Columns {
colType := strings.ToUpper(col.Type)
query += col.Name + " " + colType
if col.IsPrimary {
query += " PRIMARY KEY"
}
if col.DefaultValue.Valid {
query += " DEFAULT " + col.DefaultValue.String
}
if col.IsUnique.String == "YES" {
query += " UNIQUE"
}
if col.IsNullable == "NO" {
query += " NOT NULL"
}
if i < len(table.Columns)-1 {
query += ", "
}
}
query += ");"
return query
}

// TableToString returns a string representation of a table.
// It is used for debugging purposes.

Expand Down
46 changes: 46 additions & 0 deletions databases/postgres/postgres_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,3 +126,49 @@ func TestGetTableName(t *testing.T) {
t.Errorf("there were unfulfilled expectations: %s", err)
}
}

func TestGenerateCreateTablequery(t *testing.T) {
db, mock := MockDB()
defer db.Close()

table := types.Table{
Name: "user",
Columns: []types.Column{
{
Name: "id",
Type: "SERIAL",
IsNullable: "NO",
DefaultValue: sql.NullString{String: "", Valid: false},
IsPrimary: true,
IsUnique: sql.NullString{String: "YES", Valid: true},
},
{
Name: "name",
Type: "VARCHAR(255)",
IsNullable: "NO",
DefaultValue: sql.NullString{String: "", Valid: false},
IsPrimary: false,
IsUnique: sql.NullString{String: "NO", Valid: true},
},
{
Name: "age",
Type: "INTEGER",
IsNullable: "YES",
},
},
}

p := Postgres{Client: db}
query := p.GenerateCreateTableQuery(table)

fmt.Printf("Create table query: %v\n", query)

expectedQuery := `CREATE TABLE "user" (id SERIAL PRIMARY KEY UNIQUE NOT NULL, name VARCHAR(255) NOT NULL, age INTEGER);`
if query != expectedQuery {
t.Errorf("Expected '%s', but got '%s'", expectedQuery, query)
}

if err := mock.ExpectationsWereMet(); err != nil {
t.Errorf("There were unfulfilled expectations: %s", err)
}
}
Loading
Loading