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

feat: [#280] Implement Sqlserver driver #726

Merged
merged 6 commits into from
Nov 18, 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
216 changes: 216 additions & 0 deletions database/schema/grammars/sqlserver.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,216 @@
package grammars

import (
"fmt"
"slices"
"strings"

"github.com/goravel/framework/contracts/database"
"github.com/goravel/framework/contracts/database/schema"
"github.com/goravel/framework/database/schema/constants"
)

type Sqlserver struct {
attributeCommands []string
modifiers []func(schema.Blueprint, schema.ColumnDefinition) string
serials []string
wrap *Wrap
}

func NewSqlserver(tablePrefix string) *Sqlserver {
sqlserver := &Sqlserver{
attributeCommands: []string{constants.CommandComment},
serials: []string{"bigInteger", "integer", "mediumInteger", "smallInteger", "tinyInteger"},
wrap: NewWrap(database.DriverSqlserver, tablePrefix),
}
sqlserver.modifiers = []func(schema.Blueprint, schema.ColumnDefinition) string{
sqlserver.ModifyDefault,
sqlserver.ModifyIncrement,
sqlserver.ModifyNullable,
}

return sqlserver
}

func (r *Sqlserver) CompileAdd(blueprint schema.Blueprint, command *schema.Command) string {
return fmt.Sprintf("alter table %s add %s", r.wrap.Table(blueprint.GetTableName()), r.getColumn(blueprint, command.Column))
}

func (r *Sqlserver) CompileCreate(blueprint schema.Blueprint) string {
return fmt.Sprintf("create table %s (%s)", r.wrap.Table(blueprint.GetTableName()), strings.Join(r.getColumns(blueprint), ", "))
}

func (r *Sqlserver) CompileDropAllDomains(domains []string) string {
return ""

Check warning on line 44 in database/schema/grammars/sqlserver.go

View check run for this annotation

Codecov / codecov/patch

database/schema/grammars/sqlserver.go#L43-L44

Added lines #L43 - L44 were not covered by tests
}

func (r *Sqlserver) CompileDropAllForeignKeys() string {
return `DECLARE @sql NVARCHAR(MAX) = N'';
SELECT @sql += 'ALTER TABLE '
+ QUOTENAME(OBJECT_SCHEMA_NAME(parent_object_id)) + '.' + + QUOTENAME(OBJECT_NAME(parent_object_id))
hwbrzzl marked this conversation as resolved.
Show resolved Hide resolved
+ ' DROP CONSTRAINT ' + QUOTENAME(name) + ';'
FROM sys.foreign_keys;

EXEC sp_executesql @sql;`

Check warning on line 54 in database/schema/grammars/sqlserver.go

View check run for this annotation

Codecov / codecov/patch

database/schema/grammars/sqlserver.go#L47-L54

Added lines #L47 - L54 were not covered by tests
}

func (r *Sqlserver) CompileDropAllTables(tables []string) string {
return "EXEC sp_msforeachtable 'DROP TABLE ?'"

Check warning on line 58 in database/schema/grammars/sqlserver.go

View check run for this annotation

Codecov / codecov/patch

database/schema/grammars/sqlserver.go#L57-L58

Added lines #L57 - L58 were not covered by tests
}
hwbrzzl marked this conversation as resolved.
Show resolved Hide resolved

func (r *Sqlserver) CompileDropAllTypes(types []string) string {
return ""

Check warning on line 62 in database/schema/grammars/sqlserver.go

View check run for this annotation

Codecov / codecov/patch

database/schema/grammars/sqlserver.go#L61-L62

Added lines #L61 - L62 were not covered by tests
}

func (r *Sqlserver) CompileDropAllViews(views []string) string {
return `DECLARE @sql NVARCHAR(MAX) = N'';
SELECT @sql += 'DROP VIEW ' + QUOTENAME(OBJECT_SCHEMA_NAME(object_id)) + '.' + QUOTENAME(name) + ';'
FROM sys.views;

EXEC sp_executesql @sql;`

Check warning on line 70 in database/schema/grammars/sqlserver.go

View check run for this annotation

Codecov / codecov/patch

database/schema/grammars/sqlserver.go#L65-L70

Added lines #L65 - L70 were not covered by tests
}

func (r *Sqlserver) CompileDropIfExists(blueprint schema.Blueprint) string {
table := r.wrap.Table(blueprint.GetTableName())

return fmt.Sprintf("if object_id(%s, 'U') is not null drop table %s", r.wrap.Quote(table), table)
hwbrzzl marked this conversation as resolved.
Show resolved Hide resolved
}

func (r *Sqlserver) CompileForeign(blueprint schema.Blueprint, command *schema.Command) string {
sql := fmt.Sprintf("alter table %s add constraint %s foreign key (%s) references %s (%s)",
r.wrap.Table(blueprint.GetTableName()),
r.wrap.Column(command.Index),
r.wrap.Columnize(command.Columns),
r.wrap.Table(command.On),
r.wrap.Columnize(command.References))
if command.OnDelete != "" {
sql += " on delete " + command.OnDelete
}
if command.OnUpdate != "" {
sql += " on update " + command.OnUpdate
}

return sql
}

func (r *Sqlserver) CompileIndex(blueprint schema.Blueprint, command *schema.Command) string {
return fmt.Sprintf("create index %s on %s (%s)",
r.wrap.Column(command.Index),
r.wrap.Table(blueprint.GetTableName()),
r.wrap.Columnize(command.Columns),
)
}

func (r *Sqlserver) CompileIndexes(schema, table string) string {
newSchema := "schema_name()"
if schema != "" {
newSchema = r.wrap.Quote(schema)
}

Check warning on line 108 in database/schema/grammars/sqlserver.go

View check run for this annotation

Codecov / codecov/patch

database/schema/grammars/sqlserver.go#L104-L108

Added lines #L104 - L108 were not covered by tests

return fmt.Sprintf(
"select idx.name as name, string_agg(col.name, ',') within group (order by idxcol.key_ordinal) as columns, "+
"idx.type_desc as [type], idx.is_unique as [unique], idx.is_primary_key as [primary] "+
"from sys.indexes as idx "+
"join sys.tables as tbl on idx.object_id = tbl.object_id "+
"join sys.schemas as scm on tbl.schema_id = scm.schema_id "+
"join sys.index_columns as idxcol on idx.object_id = idxcol.object_id and idx.index_id = idxcol.index_id "+
"join sys.columns as col on idxcol.object_id = col.object_id and idxcol.column_id = col.column_id "+
"where tbl.name = %s and scm.name = %s "+
"group by idx.name, idx.type_desc, idx.is_unique, idx.is_primary_key",
r.wrap.Quote(table),
newSchema,
)

Check warning on line 122 in database/schema/grammars/sqlserver.go

View check run for this annotation

Codecov / codecov/patch

database/schema/grammars/sqlserver.go#L110-L122

Added lines #L110 - L122 were not covered by tests
}

func (r *Sqlserver) CompilePrimary(blueprint schema.Blueprint, command *schema.Command) string {
return fmt.Sprintf("alter table %s add constraint %s primary key (%s)",
r.wrap.Table(blueprint.GetTableName()),
r.wrap.Column(command.Index),
r.wrap.Columnize(command.Columns))
}

func (r *Sqlserver) CompileTables(database string) string {
return "select t.name as name, schema_name(t.schema_id) as [schema], sum(u.total_pages) * 8 * 1024 as size " +
"from sys.tables as t " +
"join sys.partitions as p on p.object_id = t.object_id " +
"join sys.allocation_units as u on u.container_id = p.hobt_id " +
"group by t.name, t.schema_id " +
"order by t.name"

Check warning on line 138 in database/schema/grammars/sqlserver.go

View check run for this annotation

Codecov / codecov/patch

database/schema/grammars/sqlserver.go#L132-L138

Added lines #L132 - L138 were not covered by tests
}

func (r *Sqlserver) CompileTypes() string {
return ""

Check warning on line 142 in database/schema/grammars/sqlserver.go

View check run for this annotation

Codecov / codecov/patch

database/schema/grammars/sqlserver.go#L141-L142

Added lines #L141 - L142 were not covered by tests
}

func (r *Sqlserver) CompileViews(database string) string {
return "select name, schema_name(v.schema_id) as [schema], definition from sys.views as v " +
"inner join sys.sql_modules as m on v.object_id = m.object_id " +
"order by name"

Check warning on line 148 in database/schema/grammars/sqlserver.go

View check run for this annotation

Codecov / codecov/patch

database/schema/grammars/sqlserver.go#L145-L148

Added lines #L145 - L148 were not covered by tests
}

func (r *Sqlserver) GetAttributeCommands() []string {
return r.attributeCommands

Check warning on line 152 in database/schema/grammars/sqlserver.go

View check run for this annotation

Codecov / codecov/patch

database/schema/grammars/sqlserver.go#L151-L152

Added lines #L151 - L152 were not covered by tests
}

func (r *Sqlserver) ModifyDefault(blueprint schema.Blueprint, column schema.ColumnDefinition) string {
if column.GetDefault() != nil {
return fmt.Sprintf(" default %s", getDefaultValue(column.GetDefault()))
}

return ""
}

func (r *Sqlserver) ModifyNullable(blueprint schema.Blueprint, column schema.ColumnDefinition) string {
if column.GetNullable() {
return " null"
} else {
return " not null"
}
}

func (r *Sqlserver) ModifyIncrement(blueprint schema.Blueprint, column schema.ColumnDefinition) string {
if slices.Contains(r.serials, column.GetType()) && column.GetAutoIncrement() {
if blueprint.HasCommand("primary") {
return " identity"
}

Check warning on line 175 in database/schema/grammars/sqlserver.go

View check run for this annotation

Codecov / codecov/patch

database/schema/grammars/sqlserver.go#L174-L175

Added lines #L174 - L175 were not covered by tests
return " identity primary key"
}

return ""
}

func (r *Sqlserver) TypeBigInteger(column schema.ColumnDefinition) string {
return "bigint"

Check warning on line 183 in database/schema/grammars/sqlserver.go

View check run for this annotation

Codecov / codecov/patch

database/schema/grammars/sqlserver.go#L182-L183

Added lines #L182 - L183 were not covered by tests
}

func (r *Sqlserver) TypeInteger(column schema.ColumnDefinition) string {
return "int"
}

func (r *Sqlserver) TypeString(column schema.ColumnDefinition) string {
length := column.GetLength()
if length > 0 {
return fmt.Sprintf("nvarchar(%d)", length)
}

return "nvarchar(255)"
}

func (r *Sqlserver) getColumns(blueprint schema.Blueprint) []string {
var columns []string
for _, column := range blueprint.GetAddedColumns() {
columns = append(columns, r.getColumn(blueprint, column))
}

return columns
}

func (r *Sqlserver) getColumn(blueprint schema.Blueprint, column schema.ColumnDefinition) string {
sql := fmt.Sprintf("%s %s", r.wrap.Column(column.GetName()), getType(r, column))

for _, modifier := range r.modifiers {
sql += modifier(blueprint, column)
}

return sql
}
Loading
Loading