5
5
// You can obtain one at https://github.com/gogf/gf.
6
6
//
7
7
// Note:
8
- // 1. It needs manually import: _ "github.com/mattn /go-oci8 "
8
+ // 1. It needs manually import: _ "github.com/sijms /go-ora/v2 "
9
9
// 2. It does not support Save/Replace features.
10
10
// 3. It does not support LastInsertId.
11
11
@@ -16,12 +16,7 @@ import (
16
16
"context"
17
17
"database/sql"
18
18
"fmt"
19
- "reflect"
20
- "strconv"
21
- "strings"
22
- "time"
23
-
24
- _ "github.com/mattn/go-oci8"
19
+ gora "github.com/sijms/go-ora/v2"
25
20
26
21
"github.com/gogf/gf/v2/container/gmap"
27
22
"github.com/gogf/gf/v2/database/gdb"
@@ -30,6 +25,8 @@ import (
30
25
"github.com/gogf/gf/v2/text/gregex"
31
26
"github.com/gogf/gf/v2/text/gstr"
32
27
"github.com/gogf/gf/v2/util/gconv"
28
+ "strconv"
29
+ "strings"
33
30
)
34
31
35
32
// Driver is the driver for oracle database.
@@ -65,20 +62,26 @@ func (d *Driver) New(core *gdb.Core, node *gdb.ConfigNode) (gdb.DB, error) {
65
62
func (d * Driver ) Open (config * gdb.ConfigNode ) (db * sql.DB , err error ) {
66
63
var (
67
64
source string
68
- underlyingDriverName = "oci8 "
65
+ underlyingDriverName = "oracle "
69
66
)
70
- // [username/[password]@]host[:port][/service_name][?param1=value1&...¶mN=valueN]
67
+
68
+ options := map [string ]string {
69
+ "CONNECTION TIMEOUT" : "60" ,
70
+ "PREFETCH_ROWS" : "25" ,
71
+ }
72
+
73
+ if config .Debug {
74
+ options ["TRACE FILE" ] = "oracle_trace.log"
75
+ }
76
+ // [username:[password]@]host[:port][/service_name][?param1=value1&...¶mN=valueN]
71
77
if config .Link != "" {
72
78
source = config .Link
73
79
// Custom changing the schema in runtime.
74
80
if config .Name != "" {
75
81
source , _ = gregex .ReplaceString (`@(.+?)/([\w\.\-]+)+` , "@$1/" + config .Name , source )
76
82
}
77
83
} else {
78
- source = fmt .Sprintf (
79
- "%s/%s@%s:%s/%s" ,
80
- config .User , config .Pass , config .Host , config .Port , config .Name ,
81
- )
84
+ source = gora .BuildUrl (config .Host , gconv .Int (config .Port ), config .Name , config .User , config .Pass , options )
82
85
}
83
86
84
87
if db , err = sql .Open (underlyingDriverName , source ); err != nil {
@@ -99,8 +102,8 @@ func (d *Driver) FilteredLink() string {
99
102
return ""
100
103
}
101
104
s , _ := gregex .ReplaceString (
102
- `(.+?)\s*/ \s*(.+)\s*@\s*(.+)\s*:\s*(\d+)\s*/\s*(.+)` ,
103
- `$1/ xxx@$3:$4/$5` ,
105
+ `(.+?)\s*: \s*(.+)\s*@\s*(.+)\s*:\s*(\d+)\s*/\s*(.+)` ,
106
+ `$1: xxx@$3:$4/$5` ,
104
107
linkInfo ,
105
108
)
106
109
return s
@@ -124,16 +127,7 @@ func (d *Driver) DoFilter(ctx context.Context, link gdb.Link, sql string, args [
124
127
return fmt .Sprintf (":v%d" , index )
125
128
})
126
129
newSql , _ = gregex .ReplaceString ("\" " , "" , newSql )
127
- // Handle string datetime argument.
128
- for i , v := range args {
129
- if reflect .TypeOf (v ).Kind () == reflect .String {
130
- valueStr := gconv .String (v )
131
- if gregex .IsMatchString (`^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$` , valueStr ) {
132
- // args[i] = fmt.Sprintf(`TO_DATE('%s','yyyy-MM-dd HH:MI:SS')`, valueStr)
133
- args [i ], _ = time .ParseInLocation ("2006-01-02 15:04:05" , valueStr , time .Local )
134
- }
135
- }
136
- }
130
+
137
131
newSql = d .parseSql (newSql )
138
132
newArgs = args
139
133
return
@@ -168,16 +162,24 @@ func (d *Driver) parseSql(sql string) string {
168
162
strings .EqualFold (queryExpr [3 ], "LIMIT" ) == false {
169
163
break
170
164
}
171
- first , limit := 0 , 0
165
+ page , limit := 0 , 0
172
166
for i := 1 ; i < len (allMatch [index ]); i ++ {
173
167
if len (strings .TrimSpace (allMatch [index ][i ])) == 0 {
174
168
continue
175
169
}
176
170
177
171
if strings .HasPrefix (allMatch [index ][i ], "LIMIT" ) {
178
172
if allMatch [index ][i + 2 ] != "" {
179
- first , _ = strconv .Atoi (allMatch [index ][i + 1 ])
173
+ page , _ = strconv .Atoi (allMatch [index ][i + 1 ])
180
174
limit , _ = strconv .Atoi (allMatch [index ][i + 2 ])
175
+
176
+ if page <= 0 {
177
+ page = 1
178
+ }
179
+
180
+ limit = (page / limit + 1 ) * limit
181
+
182
+ page , _ = strconv .Atoi (allMatch [index ][i + 1 ])
181
183
} else {
182
184
limit , _ = strconv .Atoi (allMatch [index ][i + 1 ])
183
185
}
@@ -187,8 +189,8 @@ func (d *Driver) parseSql(sql string) string {
187
189
sql = fmt .Sprintf (
188
190
"SELECT * FROM " +
189
191
"(SELECT GFORM.*, ROWNUM ROWNUM_ FROM (%s %s) GFORM WHERE ROWNUM <= %d)" +
190
- " WHERE ROWNUM_ >= %d" ,
191
- queryExpr [1 ], queryExpr [2 ], limit , first ,
192
+ " WHERE ROWNUM_ > %d" ,
193
+ queryExpr [1 ], queryExpr [2 ], limit , page ,
192
194
)
193
195
}
194
196
return sql
@@ -241,7 +243,7 @@ SELECT
241
243
CASE DATA_TYPE
242
244
WHEN 'NUMBER' THEN DATA_TYPE||'('||DATA_PRECISION||','||DATA_SCALE||')'
243
245
WHEN 'FLOAT' THEN DATA_TYPE||'('||DATA_PRECISION||','||DATA_SCALE||')'
244
- ELSE DATA_TYPE||'('||DATA_LENGTH||')' END AS TYPE
246
+ ELSE DATA_TYPE||'('||DATA_LENGTH||')' END AS TYPE,NULLABLE
245
247
FROM USER_TAB_COLUMNS WHERE TABLE_NAME = '%s' ORDER BY COLUMN_ID` ,
246
248
strings .ToUpper (table ),
247
249
)
@@ -256,10 +258,16 @@ FROM USER_TAB_COLUMNS WHERE TABLE_NAME = '%s' ORDER BY COLUMN_ID`,
256
258
}
257
259
fields = make (map [string ]* gdb.TableField )
258
260
for i , m := range result {
259
- fields [strings .ToLower (m ["FIELD" ].String ())] = & gdb.TableField {
261
+ isNull := false
262
+ if m ["NULLABLE" ].String () == "Y" {
263
+ isNull = true
264
+ }
265
+
266
+ fields [m ["FIELD" ].String ()] = & gdb.TableField {
260
267
Index : i ,
261
- Name : strings .ToLower (m ["FIELD" ].String ()),
262
- Type : strings .ToLower (m ["TYPE" ].String ()),
268
+ Name : m ["FIELD" ].String (),
269
+ Type : m ["TYPE" ].String (),
270
+ Null : isNull ,
263
271
}
264
272
}
265
273
return fields
@@ -288,10 +296,10 @@ func (d *Driver) DoInsert(
288
296
) (result sql.Result , err error ) {
289
297
switch option .InsertOption {
290
298
case gdb .InsertOptionSave :
291
- return nil , gerror .NewCode (gcode .CodeNotSupported , `Save operation is not supported by mssql driver` )
299
+ return nil , gerror .NewCode (gcode .CodeNotSupported , `Save operation is not supported by oracle driver` )
292
300
293
301
case gdb .InsertOptionReplace :
294
- return nil , gerror .NewCode (gcode .CodeNotSupported , `Replace operation is not supported by mssql driver` )
302
+ return nil , gerror .NewCode (gcode .CodeNotSupported , `Replace operation is not supported by oracle driver` )
295
303
}
296
304
297
305
var (
0 commit comments