Page Menu
Home
Musing Studio
Search
Configure Global Search
Log In
Files
F12217149
create.go
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
5 KB
Subscribers
None
create.go
View Options
/*
* Copyright © 2019-2020 A Bunch Tell LLC.
*
* This file is part of WriteFreely.
*
* WriteFreely is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, included
* in the LICENSE file in this source code package.
*/
package
db
import
(
"fmt"
"strings"
)
type
ColumnType
int
type
OptionalInt
struct
{
Set
bool
Value
int
}
type
OptionalString
struct
{
Set
bool
Value
string
}
type
SQLBuilder
interface
{
ToSQL
()
(
string
,
error
)
}
type
Column
struct
{
Dialect
DialectType
Name
string
Nullable
bool
Default
OptionalString
Type
ColumnType
Size
OptionalInt
PrimaryKey
bool
}
type
CreateTableSqlBuilder
struct
{
Dialect
DialectType
Name
string
IfNotExists
bool
ColumnOrder
[]
string
Columns
map
[
string
]
*
Column
Constraints
[]
string
}
const
(
ColumnTypeBool
ColumnType
=
iota
ColumnTypeSmallInt
ColumnType
=
iota
ColumnTypeInteger
ColumnType
=
iota
ColumnTypeChar
ColumnType
=
iota
ColumnTypeVarChar
ColumnType
=
iota
ColumnTypeText
ColumnType
=
iota
ColumnTypeDateTime
ColumnType
=
iota
)
var
_
SQLBuilder
=
&
CreateTableSqlBuilder
{}
var
UnsetSize
OptionalInt
=
OptionalInt
{
Set
:
false
,
Value
:
0
}
var
UnsetDefault
OptionalString
=
OptionalString
{
Set
:
false
,
Value
:
""
}
func
(
d
ColumnType
)
Format
(
dialect
DialectType
,
size
OptionalInt
)
(
string
,
error
)
{
if
dialect
!=
DialectMySQL
&&
dialect
!=
DialectSQLite
{
return
""
,
fmt
.
Errorf
(
"unsupported column type %d for dialect %d and size %v"
,
d
,
dialect
,
size
)
}
switch
d
{
case
ColumnTypeSmallInt
:
{
if
dialect
==
DialectSQLite
{
return
"INTEGER"
,
nil
}
mod
:=
""
if
size
.
Set
{
mod
=
fmt
.
Sprintf
(
"(%d)"
,
size
.
Value
)
}
return
"SMALLINT"
+
mod
,
nil
}
case
ColumnTypeInteger
:
{
if
dialect
==
DialectSQLite
{
return
"INTEGER"
,
nil
}
mod
:=
""
if
size
.
Set
{
mod
=
fmt
.
Sprintf
(
"(%d)"
,
size
.
Value
)
}
return
"INT"
+
mod
,
nil
}
case
ColumnTypeChar
:
{
if
dialect
==
DialectSQLite
{
return
"TEXT"
,
nil
}
mod
:=
""
if
size
.
Set
{
mod
=
fmt
.
Sprintf
(
"(%d)"
,
size
.
Value
)
}
return
"CHAR"
+
mod
,
nil
}
case
ColumnTypeVarChar
:
{
if
dialect
==
DialectSQLite
{
return
"TEXT"
,
nil
}
mod
:=
""
if
size
.
Set
{
mod
=
fmt
.
Sprintf
(
"(%d)"
,
size
.
Value
)
}
return
"VARCHAR"
+
mod
,
nil
}
case
ColumnTypeBool
:
{
if
dialect
==
DialectSQLite
{
return
"INTEGER"
,
nil
}
return
"TINYINT(1)"
,
nil
}
case
ColumnTypeDateTime
:
return
"DATETIME"
,
nil
case
ColumnTypeText
:
return
"TEXT"
,
nil
}
return
""
,
fmt
.
Errorf
(
"unsupported column type %d for dialect %d and size %v"
,
d
,
dialect
,
size
)
}
func
(
c
*
Column
)
SetName
(
name
string
)
*
Column
{
c
.
Name
=
name
return
c
}
func
(
c
*
Column
)
SetNullable
(
nullable
bool
)
*
Column
{
c
.
Nullable
=
nullable
return
c
}
func
(
c
*
Column
)
SetPrimaryKey
(
pk
bool
)
*
Column
{
c
.
PrimaryKey
=
pk
return
c
}
func
(
c
*
Column
)
SetDefault
(
value
string
)
*
Column
{
c
.
Default
=
OptionalString
{
Set
:
true
,
Value
:
value
}
return
c
}
func
(
c
*
Column
)
SetDefaultCurrentTimestamp
()
*
Column
{
def
:=
"NOW()"
if
c
.
Dialect
==
DialectSQLite
{
def
=
"CURRENT_TIMESTAMP"
}
c
.
Default
=
OptionalString
{
Set
:
true
,
Value
:
def
}
return
c
}
func
(
c
*
Column
)
SetType
(
t
ColumnType
)
*
Column
{
c
.
Type
=
t
return
c
}
func
(
c
*
Column
)
SetSize
(
size
int
)
*
Column
{
c
.
Size
=
OptionalInt
{
Set
:
true
,
Value
:
size
}
return
c
}
func
(
c
*
Column
)
String
()
(
string
,
error
)
{
var
str
strings
.
Builder
str
.
WriteString
(
c
.
Name
)
str
.
WriteString
(
" "
)
typeStr
,
err
:=
c
.
Type
.
Format
(
c
.
Dialect
,
c
.
Size
)
if
err
!=
nil
{
return
""
,
err
}
str
.
WriteString
(
typeStr
)
if
!
c
.
Nullable
{
str
.
WriteString
(
" NOT NULL"
)
}
if
c
.
Default
.
Set
{
str
.
WriteString
(
" DEFAULT "
)
val
:=
c
.
Default
.
Value
if
val
==
""
{
val
=
"''"
}
str
.
WriteString
(
val
)
}
if
c
.
PrimaryKey
{
str
.
WriteString
(
" PRIMARY KEY"
)
}
return
str
.
String
(),
nil
}
func
(
b
*
CreateTableSqlBuilder
)
Column
(
column
*
Column
)
*
CreateTableSqlBuilder
{
if
b
.
Columns
==
nil
{
b
.
Columns
=
make
(
map
[
string
]
*
Column
)
}
b
.
Columns
[
column
.
Name
]
=
column
b
.
ColumnOrder
=
append
(
b
.
ColumnOrder
,
column
.
Name
)
return
b
}
func
(
b
*
CreateTableSqlBuilder
)
UniqueConstraint
(
columns
...
string
)
*
CreateTableSqlBuilder
{
for
_
,
column
:=
range
columns
{
if
_
,
ok
:=
b
.
Columns
[
column
];
!
ok
{
// This fails silently.
return
b
}
}
b
.
Constraints
=
append
(
b
.
Constraints
,
fmt
.
Sprintf
(
"UNIQUE(%s)"
,
strings
.
Join
(
columns
,
","
)))
return
b
}
func
(
b
*
CreateTableSqlBuilder
)
SetIfNotExists
(
ine
bool
)
*
CreateTableSqlBuilder
{
b
.
IfNotExists
=
ine
return
b
}
func
(
b
*
CreateTableSqlBuilder
)
ToSQL
()
(
string
,
error
)
{
var
str
strings
.
Builder
str
.
WriteString
(
"CREATE TABLE "
)
if
b
.
IfNotExists
{
str
.
WriteString
(
"IF NOT EXISTS "
)
}
str
.
WriteString
(
b
.
Name
)
var
things
[]
string
for
_
,
columnName
:=
range
b
.
ColumnOrder
{
column
,
ok
:=
b
.
Columns
[
columnName
]
if
!
ok
{
return
""
,
fmt
.
Errorf
(
"column not found: %s"
,
columnName
)
}
columnStr
,
err
:=
column
.
String
()
if
err
!=
nil
{
return
""
,
err
}
things
=
append
(
things
,
columnStr
)
}
for
_
,
constraint
:=
range
b
.
Constraints
{
things
=
append
(
things
,
constraint
)
}
if
thingLen
:=
len
(
things
);
thingLen
>
0
{
str
.
WriteString
(
" ( "
)
for
i
,
thing
:=
range
things
{
str
.
WriteString
(
thing
)
if
i
<
thingLen
-
1
{
str
.
WriteString
(
", "
)
}
}
str
.
WriteString
(
" )"
)
}
return
str
.
String
(),
nil
}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Thu, Oct 30, 1:46 AM (2 h, 48 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
3460212
Attached To
rWF WriteFreely
Event Timeline
Log In to Comment