You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

oracle.go 27KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849
  1. // Copyright 2015 The Xorm Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package dialects
  5. import (
  6. "context"
  7. "errors"
  8. "fmt"
  9. "regexp"
  10. "strconv"
  11. "strings"
  12. "xorm.io/xorm/core"
  13. "xorm.io/xorm/schemas"
  14. )
  15. var (
  16. oracleReservedWords = map[string]bool{
  17. "ACCESS": true,
  18. "ACCOUNT": true,
  19. "ACTIVATE": true,
  20. "ADD": true,
  21. "ADMIN": true,
  22. "ADVISE": true,
  23. "AFTER": true,
  24. "ALL": true,
  25. "ALL_ROWS": true,
  26. "ALLOCATE": true,
  27. "ALTER": true,
  28. "ANALYZE": true,
  29. "AND": true,
  30. "ANY": true,
  31. "ARCHIVE": true,
  32. "ARCHIVELOG": true,
  33. "ARRAY": true,
  34. "AS": true,
  35. "ASC": true,
  36. "AT": true,
  37. "AUDIT": true,
  38. "AUTHENTICATED": true,
  39. "AUTHORIZATION": true,
  40. "AUTOEXTEND": true,
  41. "AUTOMATIC": true,
  42. "BACKUP": true,
  43. "BECOME": true,
  44. "BEFORE": true,
  45. "BEGIN": true,
  46. "BETWEEN": true,
  47. "BFILE": true,
  48. "BITMAP": true,
  49. "BLOB": true,
  50. "BLOCK": true,
  51. "BODY": true,
  52. "BY": true,
  53. "CACHE": true,
  54. "CACHE_INSTANCES": true,
  55. "CANCEL": true,
  56. "CASCADE": true,
  57. "CAST": true,
  58. "CFILE": true,
  59. "CHAINED": true,
  60. "CHANGE": true,
  61. "CHAR": true,
  62. "CHAR_CS": true,
  63. "CHARACTER": true,
  64. "CHECK": true,
  65. "CHECKPOINT": true,
  66. "CHOOSE": true,
  67. "CHUNK": true,
  68. "CLEAR": true,
  69. "CLOB": true,
  70. "CLONE": true,
  71. "CLOSE": true,
  72. "CLOSE_CACHED_OPEN_CURSORS": true,
  73. "CLUSTER": true,
  74. "COALESCE": true,
  75. "COLUMN": true,
  76. "COLUMNS": true,
  77. "COMMENT": true,
  78. "COMMIT": true,
  79. "COMMITTED": true,
  80. "COMPATIBILITY": true,
  81. "COMPILE": true,
  82. "COMPLETE": true,
  83. "COMPOSITE_LIMIT": true,
  84. "COMPRESS": true,
  85. "COMPUTE": true,
  86. "CONNECT": true,
  87. "CONNECT_TIME": true,
  88. "CONSTRAINT": true,
  89. "CONSTRAINTS": true,
  90. "CONTENTS": true,
  91. "CONTINUE": true,
  92. "CONTROLFILE": true,
  93. "CONVERT": true,
  94. "COST": true,
  95. "CPU_PER_CALL": true,
  96. "CPU_PER_SESSION": true,
  97. "CREATE": true,
  98. "CURRENT": true,
  99. "CURRENT_SCHEMA": true,
  100. "CURREN_USER": true,
  101. "CURSOR": true,
  102. "CYCLE": true,
  103. "DANGLING": true,
  104. "DATABASE": true,
  105. "DATAFILE": true,
  106. "DATAFILES": true,
  107. "DATAOBJNO": true,
  108. "DATE": true,
  109. "DBA": true,
  110. "DBHIGH": true,
  111. "DBLOW": true,
  112. "DBMAC": true,
  113. "DEALLOCATE": true,
  114. "DEBUG": true,
  115. "DEC": true,
  116. "DECIMAL": true,
  117. "DECLARE": true,
  118. "DEFAULT": true,
  119. "DEFERRABLE": true,
  120. "DEFERRED": true,
  121. "DEGREE": true,
  122. "DELETE": true,
  123. "DEREF": true,
  124. "DESC": true,
  125. "DIRECTORY": true,
  126. "DISABLE": true,
  127. "DISCONNECT": true,
  128. "DISMOUNT": true,
  129. "DISTINCT": true,
  130. "DISTRIBUTED": true,
  131. "DML": true,
  132. "DOUBLE": true,
  133. "DROP": true,
  134. "DUMP": true,
  135. "EACH": true,
  136. "ELSE": true,
  137. "ENABLE": true,
  138. "END": true,
  139. "ENFORCE": true,
  140. "ENTRY": true,
  141. "ESCAPE": true,
  142. "EXCEPT": true,
  143. "EXCEPTIONS": true,
  144. "EXCHANGE": true,
  145. "EXCLUDING": true,
  146. "EXCLUSIVE": true,
  147. "EXECUTE": true,
  148. "EXISTS": true,
  149. "EXPIRE": true,
  150. "EXPLAIN": true,
  151. "EXTENT": true,
  152. "EXTENTS": true,
  153. "EXTERNALLY": true,
  154. "FAILED_LOGIN_ATTEMPTS": true,
  155. "FALSE": true,
  156. "FAST": true,
  157. "FILE": true,
  158. "FIRST_ROWS": true,
  159. "FLAGGER": true,
  160. "FLOAT": true,
  161. "FLOB": true,
  162. "FLUSH": true,
  163. "FOR": true,
  164. "FORCE": true,
  165. "FOREIGN": true,
  166. "FREELIST": true,
  167. "FREELISTS": true,
  168. "FROM": true,
  169. "FULL": true,
  170. "FUNCTION": true,
  171. "GLOBAL": true,
  172. "GLOBALLY": true,
  173. "GLOBAL_NAME": true,
  174. "GRANT": true,
  175. "GROUP": true,
  176. "GROUPS": true,
  177. "HASH": true,
  178. "HASHKEYS": true,
  179. "HAVING": true,
  180. "HEADER": true,
  181. "HEAP": true,
  182. "IDENTIFIED": true,
  183. "IDGENERATORS": true,
  184. "IDLE_TIME": true,
  185. "IF": true,
  186. "IMMEDIATE": true,
  187. "IN": true,
  188. "INCLUDING": true,
  189. "INCREMENT": true,
  190. "INDEX": true,
  191. "INDEXED": true,
  192. "INDEXES": true,
  193. "INDICATOR": true,
  194. "IND_PARTITION": true,
  195. "INITIAL": true,
  196. "INITIALLY": true,
  197. "INITRANS": true,
  198. "INSERT": true,
  199. "INSTANCE": true,
  200. "INSTANCES": true,
  201. "INSTEAD": true,
  202. "INT": true,
  203. "INTEGER": true,
  204. "INTERMEDIATE": true,
  205. "INTERSECT": true,
  206. "INTO": true,
  207. "IS": true,
  208. "ISOLATION": true,
  209. "ISOLATION_LEVEL": true,
  210. "KEEP": true,
  211. "KEY": true,
  212. "KILL": true,
  213. "LABEL": true,
  214. "LAYER": true,
  215. "LESS": true,
  216. "LEVEL": true,
  217. "LIBRARY": true,
  218. "LIKE": true,
  219. "LIMIT": true,
  220. "LINK": true,
  221. "LIST": true,
  222. "LOB": true,
  223. "LOCAL": true,
  224. "LOCK": true,
  225. "LOCKED": true,
  226. "LOG": true,
  227. "LOGFILE": true,
  228. "LOGGING": true,
  229. "LOGICAL_READS_PER_CALL": true,
  230. "LOGICAL_READS_PER_SESSION": true,
  231. "LONG": true,
  232. "MANAGE": true,
  233. "MASTER": true,
  234. "MAX": true,
  235. "MAXARCHLOGS": true,
  236. "MAXDATAFILES": true,
  237. "MAXEXTENTS": true,
  238. "MAXINSTANCES": true,
  239. "MAXLOGFILES": true,
  240. "MAXLOGHISTORY": true,
  241. "MAXLOGMEMBERS": true,
  242. "MAXSIZE": true,
  243. "MAXTRANS": true,
  244. "MAXVALUE": true,
  245. "MIN": true,
  246. "MEMBER": true,
  247. "MINIMUM": true,
  248. "MINEXTENTS": true,
  249. "MINUS": true,
  250. "MINVALUE": true,
  251. "MLSLABEL": true,
  252. "MLS_LABEL_FORMAT": true,
  253. "MODE": true,
  254. "MODIFY": true,
  255. "MOUNT": true,
  256. "MOVE": true,
  257. "MTS_DISPATCHERS": true,
  258. "MULTISET": true,
  259. "NATIONAL": true,
  260. "NCHAR": true,
  261. "NCHAR_CS": true,
  262. "NCLOB": true,
  263. "NEEDED": true,
  264. "NESTED": true,
  265. "NETWORK": true,
  266. "NEW": true,
  267. "NEXT": true,
  268. "NOARCHIVELOG": true,
  269. "NOAUDIT": true,
  270. "NOCACHE": true,
  271. "NOCOMPRESS": true,
  272. "NOCYCLE": true,
  273. "NOFORCE": true,
  274. "NOLOGGING": true,
  275. "NOMAXVALUE": true,
  276. "NOMINVALUE": true,
  277. "NONE": true,
  278. "NOORDER": true,
  279. "NOOVERRIDE": true,
  280. "NOPARALLEL": true,
  281. "NOREVERSE": true,
  282. "NORMAL": true,
  283. "NOSORT": true,
  284. "NOT": true,
  285. "NOTHING": true,
  286. "NOWAIT": true,
  287. "NULL": true,
  288. "NUMBER": true,
  289. "NUMERIC": true,
  290. "NVARCHAR2": true,
  291. "OBJECT": true,
  292. "OBJNO": true,
  293. "OBJNO_REUSE": true,
  294. "OF": true,
  295. "OFF": true,
  296. "OFFLINE": true,
  297. "OID": true,
  298. "OIDINDEX": true,
  299. "OLD": true,
  300. "ON": true,
  301. "ONLINE": true,
  302. "ONLY": true,
  303. "OPCODE": true,
  304. "OPEN": true,
  305. "OPTIMAL": true,
  306. "OPTIMIZER_GOAL": true,
  307. "OPTION": true,
  308. "OR": true,
  309. "ORDER": true,
  310. "ORGANIZATION": true,
  311. "OSLABEL": true,
  312. "OVERFLOW": true,
  313. "OWN": true,
  314. "PACKAGE": true,
  315. "PARALLEL": true,
  316. "PARTITION": true,
  317. "PASSWORD": true,
  318. "PASSWORD_GRACE_TIME": true,
  319. "PASSWORD_LIFE_TIME": true,
  320. "PASSWORD_LOCK_TIME": true,
  321. "PASSWORD_REUSE_MAX": true,
  322. "PASSWORD_REUSE_TIME": true,
  323. "PASSWORD_VERIFY_FUNCTION": true,
  324. "PCTFREE": true,
  325. "PCTINCREASE": true,
  326. "PCTTHRESHOLD": true,
  327. "PCTUSED": true,
  328. "PCTVERSION": true,
  329. "PERCENT": true,
  330. "PERMANENT": true,
  331. "PLAN": true,
  332. "PLSQL_DEBUG": true,
  333. "POST_TRANSACTION": true,
  334. "PRECISION": true,
  335. "PRESERVE": true,
  336. "PRIMARY": true,
  337. "PRIOR": true,
  338. "PRIVATE": true,
  339. "PRIVATE_SGA": true,
  340. "PRIVILEGE": true,
  341. "PRIVILEGES": true,
  342. "PROCEDURE": true,
  343. "PROFILE": true,
  344. "PUBLIC": true,
  345. "PURGE": true,
  346. "QUEUE": true,
  347. "QUOTA": true,
  348. "RANGE": true,
  349. "RAW": true,
  350. "RBA": true,
  351. "READ": true,
  352. "READUP": true,
  353. "REAL": true,
  354. "REBUILD": true,
  355. "RECOVER": true,
  356. "RECOVERABLE": true,
  357. "RECOVERY": true,
  358. "REF": true,
  359. "REFERENCES": true,
  360. "REFERENCING": true,
  361. "REFRESH": true,
  362. "RENAME": true,
  363. "REPLACE": true,
  364. "RESET": true,
  365. "RESETLOGS": true,
  366. "RESIZE": true,
  367. "RESOURCE": true,
  368. "RESTRICTED": true,
  369. "RETURN": true,
  370. "RETURNING": true,
  371. "REUSE": true,
  372. "REVERSE": true,
  373. "REVOKE": true,
  374. "ROLE": true,
  375. "ROLES": true,
  376. "ROLLBACK": true,
  377. "ROW": true,
  378. "ROWID": true,
  379. "ROWNUM": true,
  380. "ROWS": true,
  381. "RULE": true,
  382. "SAMPLE": true,
  383. "SAVEPOINT": true,
  384. "SB4": true,
  385. "SCAN_INSTANCES": true,
  386. "SCHEMA": true,
  387. "SCN": true,
  388. "SCOPE": true,
  389. "SD_ALL": true,
  390. "SD_INHIBIT": true,
  391. "SD_SHOW": true,
  392. "SEGMENT": true,
  393. "SEG_BLOCK": true,
  394. "SEG_FILE": true,
  395. "SELECT": true,
  396. "SEQUENCE": true,
  397. "SERIALIZABLE": true,
  398. "SESSION": true,
  399. "SESSION_CACHED_CURSORS": true,
  400. "SESSIONS_PER_USER": true,
  401. "SET": true,
  402. "SHARE": true,
  403. "SHARED": true,
  404. "SHARED_POOL": true,
  405. "SHRINK": true,
  406. "SIZE": true,
  407. "SKIP": true,
  408. "SKIP_UNUSABLE_INDEXES": true,
  409. "SMALLINT": true,
  410. "SNAPSHOT": true,
  411. "SOME": true,
  412. "SORT": true,
  413. "SPECIFICATION": true,
  414. "SPLIT": true,
  415. "SQL_TRACE": true,
  416. "STANDBY": true,
  417. "START": true,
  418. "STATEMENT_ID": true,
  419. "STATISTICS": true,
  420. "STOP": true,
  421. "STORAGE": true,
  422. "STORE": true,
  423. "STRUCTURE": true,
  424. "SUCCESSFUL": true,
  425. "SWITCH": true,
  426. "SYS_OP_ENFORCE_NOT_NULL$": true,
  427. "SYS_OP_NTCIMG$": true,
  428. "SYNONYM": true,
  429. "SYSDATE": true,
  430. "SYSDBA": true,
  431. "SYSOPER": true,
  432. "SYSTEM": true,
  433. "TABLE": true,
  434. "TABLES": true,
  435. "TABLESPACE": true,
  436. "TABLESPACE_NO": true,
  437. "TABNO": true,
  438. "TEMPORARY": true,
  439. "THAN": true,
  440. "THE": true,
  441. "THEN": true,
  442. "THREAD": true,
  443. "TIMESTAMP": true,
  444. "TIME": true,
  445. "TO": true,
  446. "TOPLEVEL": true,
  447. "TRACE": true,
  448. "TRACING": true,
  449. "TRANSACTION": true,
  450. "TRANSITIONAL": true,
  451. "TRIGGER": true,
  452. "TRIGGERS": true,
  453. "TRUE": true,
  454. "TRUNCATE": true,
  455. "TX": true,
  456. "TYPE": true,
  457. "UB2": true,
  458. "UBA": true,
  459. "UID": true,
  460. "UNARCHIVED": true,
  461. "UNDO": true,
  462. "UNION": true,
  463. "UNIQUE": true,
  464. "UNLIMITED": true,
  465. "UNLOCK": true,
  466. "UNRECOVERABLE": true,
  467. "UNTIL": true,
  468. "UNUSABLE": true,
  469. "UNUSED": true,
  470. "UPDATABLE": true,
  471. "UPDATE": true,
  472. "USAGE": true,
  473. "USE": true,
  474. "USER": true,
  475. "USING": true,
  476. "VALIDATE": true,
  477. "VALIDATION": true,
  478. "VALUE": true,
  479. "VALUES": true,
  480. "VARCHAR": true,
  481. "VARCHAR2": true,
  482. "VARYING": true,
  483. "VIEW": true,
  484. "WHEN": true,
  485. "WHENEVER": true,
  486. "WHERE": true,
  487. "WITH": true,
  488. "WITHOUT": true,
  489. "WORK": true,
  490. "WRITE": true,
  491. "WRITEDOWN": true,
  492. "WRITEUP": true,
  493. "XID": true,
  494. "YEAR": true,
  495. "ZONE": true,
  496. }
  497. oracleQuoter = schemas.Quoter{'[', ']', schemas.AlwaysReserve}
  498. )
  499. type oracle struct {
  500. Base
  501. }
  502. func (db *oracle) Init(uri *URI) error {
  503. db.quoter = oracleQuoter
  504. return db.Base.Init(db, uri)
  505. }
  506. func (db *oracle) SQLType(c *schemas.Column) string {
  507. var res string
  508. switch t := c.SQLType.Name; t {
  509. case schemas.Bit, schemas.TinyInt, schemas.SmallInt, schemas.MediumInt, schemas.Int, schemas.Integer, schemas.BigInt, schemas.Bool, schemas.Serial, schemas.BigSerial:
  510. res = "NUMBER"
  511. case schemas.Binary, schemas.VarBinary, schemas.Blob, schemas.TinyBlob, schemas.MediumBlob, schemas.LongBlob, schemas.Bytea:
  512. return schemas.Blob
  513. case schemas.Time, schemas.DateTime, schemas.TimeStamp:
  514. res = schemas.TimeStamp
  515. case schemas.TimeStampz:
  516. res = "TIMESTAMP WITH TIME ZONE"
  517. case schemas.Float, schemas.Double, schemas.Numeric, schemas.Decimal:
  518. res = "NUMBER"
  519. case schemas.Text, schemas.MediumText, schemas.LongText, schemas.Json:
  520. res = "CLOB"
  521. case schemas.Char, schemas.Varchar, schemas.TinyText:
  522. res = "VARCHAR2"
  523. default:
  524. res = t
  525. }
  526. hasLen1 := (c.Length > 0)
  527. hasLen2 := (c.Length2 > 0)
  528. if hasLen2 {
  529. res += "(" + strconv.Itoa(c.Length) + "," + strconv.Itoa(c.Length2) + ")"
  530. } else if hasLen1 {
  531. res += "(" + strconv.Itoa(c.Length) + ")"
  532. }
  533. return res
  534. }
  535. func (db *oracle) AutoIncrStr() string {
  536. return "AUTO_INCREMENT"
  537. }
  538. func (db *oracle) IsReserved(name string) bool {
  539. _, ok := oracleReservedWords[strings.ToUpper(name)]
  540. return ok
  541. }
  542. func (db *oracle) DropTableSQL(tableName string) (string, bool) {
  543. return fmt.Sprintf("DROP TABLE `%s`", tableName), false
  544. }
  545. func (db *oracle) CreateTableSQL(table *schemas.Table, tableName string) ([]string, bool) {
  546. var sql = "CREATE TABLE "
  547. if tableName == "" {
  548. tableName = table.Name
  549. }
  550. quoter := db.Quoter()
  551. sql += quoter.Quote(tableName) + " ("
  552. pkList := table.PrimaryKeys
  553. for _, colName := range table.ColumnsSeq() {
  554. col := table.GetColumn(colName)
  555. /*if col.IsPrimaryKey && len(pkList) == 1 {
  556. sql += col.String(b.dialect)
  557. } else {*/
  558. sql += db.StringNoPk(col)
  559. // }
  560. sql = strings.TrimSpace(sql)
  561. sql += ", "
  562. }
  563. if len(pkList) > 0 {
  564. sql += "PRIMARY KEY ( "
  565. sql += quoter.Join(pkList, ",")
  566. sql += " ), "
  567. }
  568. sql = sql[:len(sql)-2] + ")"
  569. return []string{sql}, false
  570. }
  571. func (db *oracle) SetQuotePolicy(quotePolicy QuotePolicy) {
  572. switch quotePolicy {
  573. case QuotePolicyNone:
  574. var q = oracleQuoter
  575. q.IsReserved = schemas.AlwaysNoReserve
  576. db.quoter = q
  577. case QuotePolicyReserved:
  578. var q = oracleQuoter
  579. q.IsReserved = db.IsReserved
  580. db.quoter = q
  581. case QuotePolicyAlways:
  582. fallthrough
  583. default:
  584. db.quoter = oracleQuoter
  585. }
  586. }
  587. func (db *oracle) IndexCheckSQL(tableName, idxName string) (string, []interface{}) {
  588. args := []interface{}{tableName, idxName}
  589. return `SELECT INDEX_NAME FROM USER_INDEXES ` +
  590. `WHERE TABLE_NAME = :1 AND INDEX_NAME = :2`, args
  591. }
  592. func (db *oracle) IsTableExist(queryer core.Queryer, ctx context.Context, tableName string) (bool, error) {
  593. return db.HasRecords(queryer, ctx, `SELECT table_name FROM user_tables WHERE table_name = :1`, tableName)
  594. }
  595. func (db *oracle) IsColumnExist(queryer core.Queryer, ctx context.Context, tableName, colName string) (bool, error) {
  596. args := []interface{}{tableName, colName}
  597. query := "SELECT column_name FROM USER_TAB_COLUMNS WHERE table_name = :1" +
  598. " AND column_name = :2"
  599. return db.HasRecords(queryer, ctx, query, args...)
  600. }
  601. func (db *oracle) GetColumns(queryer core.Queryer, ctx context.Context, tableName string) ([]string, map[string]*schemas.Column, error) {
  602. args := []interface{}{tableName}
  603. s := "SELECT column_name,data_default,data_type,data_length,data_precision,data_scale," +
  604. "nullable FROM USER_TAB_COLUMNS WHERE table_name = :1"
  605. rows, err := queryer.QueryContext(ctx, s, args...)
  606. if err != nil {
  607. return nil, nil, err
  608. }
  609. defer rows.Close()
  610. cols := make(map[string]*schemas.Column)
  611. colSeq := make([]string, 0)
  612. for rows.Next() {
  613. col := new(schemas.Column)
  614. col.Indexes = make(map[string]int)
  615. var colName, colDefault, nullable, dataType, dataPrecision, dataScale *string
  616. var dataLen int
  617. err = rows.Scan(&colName, &colDefault, &dataType, &dataLen, &dataPrecision,
  618. &dataScale, &nullable)
  619. if err != nil {
  620. return nil, nil, err
  621. }
  622. col.Name = strings.Trim(*colName, `" `)
  623. if colDefault != nil {
  624. col.Default = *colDefault
  625. col.DefaultIsEmpty = false
  626. }
  627. if *nullable == "Y" {
  628. col.Nullable = true
  629. } else {
  630. col.Nullable = false
  631. }
  632. var ignore bool
  633. var dt string
  634. var len1, len2 int
  635. dts := strings.Split(*dataType, "(")
  636. dt = dts[0]
  637. if len(dts) > 1 {
  638. lens := strings.Split(dts[1][:len(dts[1])-1], ",")
  639. if len(lens) > 1 {
  640. len1, _ = strconv.Atoi(lens[0])
  641. len2, _ = strconv.Atoi(lens[1])
  642. } else {
  643. len1, _ = strconv.Atoi(lens[0])
  644. }
  645. }
  646. switch dt {
  647. case "VARCHAR2":
  648. col.SQLType = schemas.SQLType{Name: schemas.Varchar, DefaultLength: len1, DefaultLength2: len2}
  649. case "NVARCHAR2":
  650. col.SQLType = schemas.SQLType{Name: schemas.NVarchar, DefaultLength: len1, DefaultLength2: len2}
  651. case "TIMESTAMP WITH TIME ZONE":
  652. col.SQLType = schemas.SQLType{Name: schemas.TimeStampz, DefaultLength: 0, DefaultLength2: 0}
  653. case "NUMBER":
  654. col.SQLType = schemas.SQLType{Name: schemas.Double, DefaultLength: len1, DefaultLength2: len2}
  655. case "LONG", "LONG RAW":
  656. col.SQLType = schemas.SQLType{Name: schemas.Text, DefaultLength: 0, DefaultLength2: 0}
  657. case "RAW":
  658. col.SQLType = schemas.SQLType{Name: schemas.Binary, DefaultLength: 0, DefaultLength2: 0}
  659. case "ROWID":
  660. col.SQLType = schemas.SQLType{Name: schemas.Varchar, DefaultLength: 18, DefaultLength2: 0}
  661. case "AQ$_SUBSCRIBERS":
  662. ignore = true
  663. default:
  664. col.SQLType = schemas.SQLType{Name: strings.ToUpper(dt), DefaultLength: len1, DefaultLength2: len2}
  665. }
  666. if ignore {
  667. continue
  668. }
  669. if _, ok := schemas.SqlTypes[col.SQLType.Name]; !ok {
  670. return nil, nil, fmt.Errorf("Unknown colType %v %v", *dataType, col.SQLType)
  671. }
  672. col.Length = dataLen
  673. if col.SQLType.IsText() || col.SQLType.IsTime() {
  674. if !col.DefaultIsEmpty {
  675. col.Default = "'" + col.Default + "'"
  676. }
  677. }
  678. cols[col.Name] = col
  679. colSeq = append(colSeq, col.Name)
  680. }
  681. return colSeq, cols, nil
  682. }
  683. func (db *oracle) GetTables(queryer core.Queryer, ctx context.Context) ([]*schemas.Table, error) {
  684. args := []interface{}{}
  685. s := "SELECT table_name FROM user_tables"
  686. rows, err := queryer.QueryContext(ctx, s, args...)
  687. if err != nil {
  688. return nil, err
  689. }
  690. defer rows.Close()
  691. tables := make([]*schemas.Table, 0)
  692. for rows.Next() {
  693. table := schemas.NewEmptyTable()
  694. err = rows.Scan(&table.Name)
  695. if err != nil {
  696. return nil, err
  697. }
  698. tables = append(tables, table)
  699. }
  700. return tables, nil
  701. }
  702. func (db *oracle) GetIndexes(queryer core.Queryer, ctx context.Context, tableName string) (map[string]*schemas.Index, error) {
  703. args := []interface{}{tableName}
  704. s := "SELECT t.column_name,i.uniqueness,i.index_name FROM user_ind_columns t,user_indexes i " +
  705. "WHERE t.index_name = i.index_name and t.table_name = i.table_name and t.table_name =:1"
  706. rows, err := queryer.QueryContext(ctx, s, args...)
  707. if err != nil {
  708. return nil, err
  709. }
  710. defer rows.Close()
  711. indexes := make(map[string]*schemas.Index, 0)
  712. for rows.Next() {
  713. var indexType int
  714. var indexName, colName, uniqueness string
  715. err = rows.Scan(&colName, &uniqueness, &indexName)
  716. if err != nil {
  717. return nil, err
  718. }
  719. indexName = strings.Trim(indexName, `" `)
  720. var isRegular bool
  721. if strings.HasPrefix(indexName, "IDX_"+tableName) || strings.HasPrefix(indexName, "UQE_"+tableName) {
  722. indexName = indexName[5+len(tableName):]
  723. isRegular = true
  724. }
  725. if uniqueness == "UNIQUE" {
  726. indexType = schemas.UniqueType
  727. } else {
  728. indexType = schemas.IndexType
  729. }
  730. var index *schemas.Index
  731. var ok bool
  732. if index, ok = indexes[indexName]; !ok {
  733. index = new(schemas.Index)
  734. index.Type = indexType
  735. index.Name = indexName
  736. index.IsRegular = isRegular
  737. indexes[indexName] = index
  738. }
  739. index.AddColumn(colName)
  740. }
  741. return indexes, nil
  742. }
  743. func (db *oracle) Filters() []Filter {
  744. return []Filter{
  745. &SeqFilter{Prefix: ":", Start: 1},
  746. }
  747. }
  748. type goracleDriver struct {
  749. }
  750. func (cfg *goracleDriver) Parse(driverName, dataSourceName string) (*URI, error) {
  751. db := &URI{DBType: schemas.ORACLE}
  752. dsnPattern := regexp.MustCompile(
  753. `^(?:(?P<user>.*?)(?::(?P<passwd>.*))?@)?` + // [user[:password]@]
  754. `(?:(?P<net>[^\(]*)(?:\((?P<addr>[^\)]*)\))?)?` + // [net[(addr)]]
  755. `\/(?P<dbname>.*?)` + // /dbname
  756. `(?:\?(?P<params>[^\?]*))?$`) // [?param1=value1&paramN=valueN]
  757. matches := dsnPattern.FindStringSubmatch(dataSourceName)
  758. // tlsConfigRegister := make(map[string]*tls.Config)
  759. names := dsnPattern.SubexpNames()
  760. for i, match := range matches {
  761. switch names[i] {
  762. case "dbname":
  763. db.DBName = match
  764. }
  765. }
  766. if db.DBName == "" {
  767. return nil, errors.New("dbname is empty")
  768. }
  769. return db, nil
  770. }
  771. type oci8Driver struct {
  772. }
  773. // dataSourceName=user/password@ipv4:port/dbname
  774. // dataSourceName=user/password@[ipv6]:port/dbname
  775. func (p *oci8Driver) Parse(driverName, dataSourceName string) (*URI, error) {
  776. db := &URI{DBType: schemas.ORACLE}
  777. dsnPattern := regexp.MustCompile(
  778. `^(?P<user>.*)\/(?P<password>.*)@` + // user:password@
  779. `(?P<net>.*)` + // ip:port
  780. `\/(?P<dbname>.*)`) // dbname
  781. matches := dsnPattern.FindStringSubmatch(dataSourceName)
  782. names := dsnPattern.SubexpNames()
  783. for i, match := range matches {
  784. switch names[i] {
  785. case "dbname":
  786. db.DBName = match
  787. }
  788. }
  789. if db.DBName == "" && len(matches) != 0 {
  790. return nil, errors.New("dbname is empty")
  791. }
  792. return db, nil
  793. }