mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-10-31 21:28:11 +09:00 
			
		
		
		
	* Upgrade xorm to v1.0.0 * small nit * Fix tests * Update xorm * Update xorm * fix go.sum * fix test * Fix bug when dump * Fix bug * update xorm to latest * Fix migration test * update xorm to latest * Fix import order * Use xorm tag
		
			
				
	
	
		
			850 lines
		
	
	
		
			27 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			850 lines
		
	
	
		
			27 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| // Copyright 2015 The Xorm Authors. All rights reserved.
 | |
| // Use of this source code is governed by a BSD-style
 | |
| // license that can be found in the LICENSE file.
 | |
| 
 | |
| package dialects
 | |
| 
 | |
| import (
 | |
| 	"context"
 | |
| 	"errors"
 | |
| 	"fmt"
 | |
| 	"regexp"
 | |
| 	"strconv"
 | |
| 	"strings"
 | |
| 
 | |
| 	"xorm.io/xorm/core"
 | |
| 	"xorm.io/xorm/schemas"
 | |
| )
 | |
| 
 | |
| var (
 | |
| 	oracleReservedWords = map[string]bool{
 | |
| 		"ACCESS":                    true,
 | |
| 		"ACCOUNT":                   true,
 | |
| 		"ACTIVATE":                  true,
 | |
| 		"ADD":                       true,
 | |
| 		"ADMIN":                     true,
 | |
| 		"ADVISE":                    true,
 | |
| 		"AFTER":                     true,
 | |
| 		"ALL":                       true,
 | |
| 		"ALL_ROWS":                  true,
 | |
| 		"ALLOCATE":                  true,
 | |
| 		"ALTER":                     true,
 | |
| 		"ANALYZE":                   true,
 | |
| 		"AND":                       true,
 | |
| 		"ANY":                       true,
 | |
| 		"ARCHIVE":                   true,
 | |
| 		"ARCHIVELOG":                true,
 | |
| 		"ARRAY":                     true,
 | |
| 		"AS":                        true,
 | |
| 		"ASC":                       true,
 | |
| 		"AT":                        true,
 | |
| 		"AUDIT":                     true,
 | |
| 		"AUTHENTICATED":             true,
 | |
| 		"AUTHORIZATION":             true,
 | |
| 		"AUTOEXTEND":                true,
 | |
| 		"AUTOMATIC":                 true,
 | |
| 		"BACKUP":                    true,
 | |
| 		"BECOME":                    true,
 | |
| 		"BEFORE":                    true,
 | |
| 		"BEGIN":                     true,
 | |
| 		"BETWEEN":                   true,
 | |
| 		"BFILE":                     true,
 | |
| 		"BITMAP":                    true,
 | |
| 		"BLOB":                      true,
 | |
| 		"BLOCK":                     true,
 | |
| 		"BODY":                      true,
 | |
| 		"BY":                        true,
 | |
| 		"CACHE":                     true,
 | |
| 		"CACHE_INSTANCES":           true,
 | |
| 		"CANCEL":                    true,
 | |
| 		"CASCADE":                   true,
 | |
| 		"CAST":                      true,
 | |
| 		"CFILE":                     true,
 | |
| 		"CHAINED":                   true,
 | |
| 		"CHANGE":                    true,
 | |
| 		"CHAR":                      true,
 | |
| 		"CHAR_CS":                   true,
 | |
| 		"CHARACTER":                 true,
 | |
| 		"CHECK":                     true,
 | |
| 		"CHECKPOINT":                true,
 | |
| 		"CHOOSE":                    true,
 | |
| 		"CHUNK":                     true,
 | |
| 		"CLEAR":                     true,
 | |
| 		"CLOB":                      true,
 | |
| 		"CLONE":                     true,
 | |
| 		"CLOSE":                     true,
 | |
| 		"CLOSE_CACHED_OPEN_CURSORS": true,
 | |
| 		"CLUSTER":                   true,
 | |
| 		"COALESCE":                  true,
 | |
| 		"COLUMN":                    true,
 | |
| 		"COLUMNS":                   true,
 | |
| 		"COMMENT":                   true,
 | |
| 		"COMMIT":                    true,
 | |
| 		"COMMITTED":                 true,
 | |
| 		"COMPATIBILITY":             true,
 | |
| 		"COMPILE":                   true,
 | |
| 		"COMPLETE":                  true,
 | |
| 		"COMPOSITE_LIMIT":           true,
 | |
| 		"COMPRESS":                  true,
 | |
| 		"COMPUTE":                   true,
 | |
| 		"CONNECT":                   true,
 | |
| 		"CONNECT_TIME":              true,
 | |
| 		"CONSTRAINT":                true,
 | |
| 		"CONSTRAINTS":               true,
 | |
| 		"CONTENTS":                  true,
 | |
| 		"CONTINUE":                  true,
 | |
| 		"CONTROLFILE":               true,
 | |
| 		"CONVERT":                   true,
 | |
| 		"COST":                      true,
 | |
| 		"CPU_PER_CALL":              true,
 | |
| 		"CPU_PER_SESSION":           true,
 | |
| 		"CREATE":                    true,
 | |
| 		"CURRENT":                   true,
 | |
| 		"CURRENT_SCHEMA":            true,
 | |
| 		"CURREN_USER":               true,
 | |
| 		"CURSOR":                    true,
 | |
| 		"CYCLE":                     true,
 | |
| 		"DANGLING":                  true,
 | |
| 		"DATABASE":                  true,
 | |
| 		"DATAFILE":                  true,
 | |
| 		"DATAFILES":                 true,
 | |
| 		"DATAOBJNO":                 true,
 | |
| 		"DATE":                      true,
 | |
| 		"DBA":                       true,
 | |
| 		"DBHIGH":                    true,
 | |
| 		"DBLOW":                     true,
 | |
| 		"DBMAC":                     true,
 | |
| 		"DEALLOCATE":                true,
 | |
| 		"DEBUG":                     true,
 | |
| 		"DEC":                       true,
 | |
| 		"DECIMAL":                   true,
 | |
| 		"DECLARE":                   true,
 | |
| 		"DEFAULT":                   true,
 | |
| 		"DEFERRABLE":                true,
 | |
| 		"DEFERRED":                  true,
 | |
| 		"DEGREE":                    true,
 | |
| 		"DELETE":                    true,
 | |
| 		"DEREF":                     true,
 | |
| 		"DESC":                      true,
 | |
| 		"DIRECTORY":                 true,
 | |
| 		"DISABLE":                   true,
 | |
| 		"DISCONNECT":                true,
 | |
| 		"DISMOUNT":                  true,
 | |
| 		"DISTINCT":                  true,
 | |
| 		"DISTRIBUTED":               true,
 | |
| 		"DML":                       true,
 | |
| 		"DOUBLE":                    true,
 | |
| 		"DROP":                      true,
 | |
| 		"DUMP":                      true,
 | |
| 		"EACH":                      true,
 | |
| 		"ELSE":                      true,
 | |
| 		"ENABLE":                    true,
 | |
| 		"END":                       true,
 | |
| 		"ENFORCE":                   true,
 | |
| 		"ENTRY":                     true,
 | |
| 		"ESCAPE":                    true,
 | |
| 		"EXCEPT":                    true,
 | |
| 		"EXCEPTIONS":                true,
 | |
| 		"EXCHANGE":                  true,
 | |
| 		"EXCLUDING":                 true,
 | |
| 		"EXCLUSIVE":                 true,
 | |
| 		"EXECUTE":                   true,
 | |
| 		"EXISTS":                    true,
 | |
| 		"EXPIRE":                    true,
 | |
| 		"EXPLAIN":                   true,
 | |
| 		"EXTENT":                    true,
 | |
| 		"EXTENTS":                   true,
 | |
| 		"EXTERNALLY":                true,
 | |
| 		"FAILED_LOGIN_ATTEMPTS":     true,
 | |
| 		"FALSE":                     true,
 | |
| 		"FAST":                      true,
 | |
| 		"FILE":                      true,
 | |
| 		"FIRST_ROWS":                true,
 | |
| 		"FLAGGER":                   true,
 | |
| 		"FLOAT":                     true,
 | |
| 		"FLOB":                      true,
 | |
| 		"FLUSH":                     true,
 | |
| 		"FOR":                       true,
 | |
| 		"FORCE":                     true,
 | |
| 		"FOREIGN":                   true,
 | |
| 		"FREELIST":                  true,
 | |
| 		"FREELISTS":                 true,
 | |
| 		"FROM":                      true,
 | |
| 		"FULL":                      true,
 | |
| 		"FUNCTION":                  true,
 | |
| 		"GLOBAL":                    true,
 | |
| 		"GLOBALLY":                  true,
 | |
| 		"GLOBAL_NAME":               true,
 | |
| 		"GRANT":                     true,
 | |
| 		"GROUP":                     true,
 | |
| 		"GROUPS":                    true,
 | |
| 		"HASH":                      true,
 | |
| 		"HASHKEYS":                  true,
 | |
| 		"HAVING":                    true,
 | |
| 		"HEADER":                    true,
 | |
| 		"HEAP":                      true,
 | |
| 		"IDENTIFIED":                true,
 | |
| 		"IDGENERATORS":              true,
 | |
| 		"IDLE_TIME":                 true,
 | |
| 		"IF":                        true,
 | |
| 		"IMMEDIATE":                 true,
 | |
| 		"IN":                        true,
 | |
| 		"INCLUDING":                 true,
 | |
| 		"INCREMENT":                 true,
 | |
| 		"INDEX":                     true,
 | |
| 		"INDEXED":                   true,
 | |
| 		"INDEXES":                   true,
 | |
| 		"INDICATOR":                 true,
 | |
| 		"IND_PARTITION":             true,
 | |
| 		"INITIAL":                   true,
 | |
| 		"INITIALLY":                 true,
 | |
| 		"INITRANS":                  true,
 | |
| 		"INSERT":                    true,
 | |
| 		"INSTANCE":                  true,
 | |
| 		"INSTANCES":                 true,
 | |
| 		"INSTEAD":                   true,
 | |
| 		"INT":                       true,
 | |
| 		"INTEGER":                   true,
 | |
| 		"INTERMEDIATE":              true,
 | |
| 		"INTERSECT":                 true,
 | |
| 		"INTO":                      true,
 | |
| 		"IS":                        true,
 | |
| 		"ISOLATION":                 true,
 | |
| 		"ISOLATION_LEVEL":           true,
 | |
| 		"KEEP":                      true,
 | |
| 		"KEY":                       true,
 | |
| 		"KILL":                      true,
 | |
| 		"LABEL":                     true,
 | |
| 		"LAYER":                     true,
 | |
| 		"LESS":                      true,
 | |
| 		"LEVEL":                     true,
 | |
| 		"LIBRARY":                   true,
 | |
| 		"LIKE":                      true,
 | |
| 		"LIMIT":                     true,
 | |
| 		"LINK":                      true,
 | |
| 		"LIST":                      true,
 | |
| 		"LOB":                       true,
 | |
| 		"LOCAL":                     true,
 | |
| 		"LOCK":                      true,
 | |
| 		"LOCKED":                    true,
 | |
| 		"LOG":                       true,
 | |
| 		"LOGFILE":                   true,
 | |
| 		"LOGGING":                   true,
 | |
| 		"LOGICAL_READS_PER_CALL":    true,
 | |
| 		"LOGICAL_READS_PER_SESSION": true,
 | |
| 		"LONG":                      true,
 | |
| 		"MANAGE":                    true,
 | |
| 		"MASTER":                    true,
 | |
| 		"MAX":                       true,
 | |
| 		"MAXARCHLOGS":               true,
 | |
| 		"MAXDATAFILES":              true,
 | |
| 		"MAXEXTENTS":                true,
 | |
| 		"MAXINSTANCES":              true,
 | |
| 		"MAXLOGFILES":               true,
 | |
| 		"MAXLOGHISTORY":             true,
 | |
| 		"MAXLOGMEMBERS":             true,
 | |
| 		"MAXSIZE":                   true,
 | |
| 		"MAXTRANS":                  true,
 | |
| 		"MAXVALUE":                  true,
 | |
| 		"MIN":                       true,
 | |
| 		"MEMBER":                    true,
 | |
| 		"MINIMUM":                   true,
 | |
| 		"MINEXTENTS":                true,
 | |
| 		"MINUS":                     true,
 | |
| 		"MINVALUE":                  true,
 | |
| 		"MLSLABEL":                  true,
 | |
| 		"MLS_LABEL_FORMAT":          true,
 | |
| 		"MODE":                      true,
 | |
| 		"MODIFY":                    true,
 | |
| 		"MOUNT":                     true,
 | |
| 		"MOVE":                      true,
 | |
| 		"MTS_DISPATCHERS":           true,
 | |
| 		"MULTISET":                  true,
 | |
| 		"NATIONAL":                  true,
 | |
| 		"NCHAR":                     true,
 | |
| 		"NCHAR_CS":                  true,
 | |
| 		"NCLOB":                     true,
 | |
| 		"NEEDED":                    true,
 | |
| 		"NESTED":                    true,
 | |
| 		"NETWORK":                   true,
 | |
| 		"NEW":                       true,
 | |
| 		"NEXT":                      true,
 | |
| 		"NOARCHIVELOG":              true,
 | |
| 		"NOAUDIT":                   true,
 | |
| 		"NOCACHE":                   true,
 | |
| 		"NOCOMPRESS":                true,
 | |
| 		"NOCYCLE":                   true,
 | |
| 		"NOFORCE":                   true,
 | |
| 		"NOLOGGING":                 true,
 | |
| 		"NOMAXVALUE":                true,
 | |
| 		"NOMINVALUE":                true,
 | |
| 		"NONE":                      true,
 | |
| 		"NOORDER":                   true,
 | |
| 		"NOOVERRIDE":                true,
 | |
| 		"NOPARALLEL":                true,
 | |
| 		"NOREVERSE":                 true,
 | |
| 		"NORMAL":                    true,
 | |
| 		"NOSORT":                    true,
 | |
| 		"NOT":                       true,
 | |
| 		"NOTHING":                   true,
 | |
| 		"NOWAIT":                    true,
 | |
| 		"NULL":                      true,
 | |
| 		"NUMBER":                    true,
 | |
| 		"NUMERIC":                   true,
 | |
| 		"NVARCHAR2":                 true,
 | |
| 		"OBJECT":                    true,
 | |
| 		"OBJNO":                     true,
 | |
| 		"OBJNO_REUSE":               true,
 | |
| 		"OF":                        true,
 | |
| 		"OFF":                       true,
 | |
| 		"OFFLINE":                   true,
 | |
| 		"OID":                       true,
 | |
| 		"OIDINDEX":                  true,
 | |
| 		"OLD":                       true,
 | |
| 		"ON":                        true,
 | |
| 		"ONLINE":                    true,
 | |
| 		"ONLY":                      true,
 | |
| 		"OPCODE":                    true,
 | |
| 		"OPEN":                      true,
 | |
| 		"OPTIMAL":                   true,
 | |
| 		"OPTIMIZER_GOAL":            true,
 | |
| 		"OPTION":                    true,
 | |
| 		"OR":                        true,
 | |
| 		"ORDER":                     true,
 | |
| 		"ORGANIZATION":              true,
 | |
| 		"OSLABEL":                   true,
 | |
| 		"OVERFLOW":                  true,
 | |
| 		"OWN":                       true,
 | |
| 		"PACKAGE":                   true,
 | |
| 		"PARALLEL":                  true,
 | |
| 		"PARTITION":                 true,
 | |
| 		"PASSWORD":                  true,
 | |
| 		"PASSWORD_GRACE_TIME":       true,
 | |
| 		"PASSWORD_LIFE_TIME":        true,
 | |
| 		"PASSWORD_LOCK_TIME":        true,
 | |
| 		"PASSWORD_REUSE_MAX":        true,
 | |
| 		"PASSWORD_REUSE_TIME":       true,
 | |
| 		"PASSWORD_VERIFY_FUNCTION":  true,
 | |
| 		"PCTFREE":                   true,
 | |
| 		"PCTINCREASE":               true,
 | |
| 		"PCTTHRESHOLD":              true,
 | |
| 		"PCTUSED":                   true,
 | |
| 		"PCTVERSION":                true,
 | |
| 		"PERCENT":                   true,
 | |
| 		"PERMANENT":                 true,
 | |
| 		"PLAN":                      true,
 | |
| 		"PLSQL_DEBUG":               true,
 | |
| 		"POST_TRANSACTION":          true,
 | |
| 		"PRECISION":                 true,
 | |
| 		"PRESERVE":                  true,
 | |
| 		"PRIMARY":                   true,
 | |
| 		"PRIOR":                     true,
 | |
| 		"PRIVATE":                   true,
 | |
| 		"PRIVATE_SGA":               true,
 | |
| 		"PRIVILEGE":                 true,
 | |
| 		"PRIVILEGES":                true,
 | |
| 		"PROCEDURE":                 true,
 | |
| 		"PROFILE":                   true,
 | |
| 		"PUBLIC":                    true,
 | |
| 		"PURGE":                     true,
 | |
| 		"QUEUE":                     true,
 | |
| 		"QUOTA":                     true,
 | |
| 		"RANGE":                     true,
 | |
| 		"RAW":                       true,
 | |
| 		"RBA":                       true,
 | |
| 		"READ":                      true,
 | |
| 		"READUP":                    true,
 | |
| 		"REAL":                      true,
 | |
| 		"REBUILD":                   true,
 | |
| 		"RECOVER":                   true,
 | |
| 		"RECOVERABLE":               true,
 | |
| 		"RECOVERY":                  true,
 | |
| 		"REF":                       true,
 | |
| 		"REFERENCES":                true,
 | |
| 		"REFERENCING":               true,
 | |
| 		"REFRESH":                   true,
 | |
| 		"RENAME":                    true,
 | |
| 		"REPLACE":                   true,
 | |
| 		"RESET":                     true,
 | |
| 		"RESETLOGS":                 true,
 | |
| 		"RESIZE":                    true,
 | |
| 		"RESOURCE":                  true,
 | |
| 		"RESTRICTED":                true,
 | |
| 		"RETURN":                    true,
 | |
| 		"RETURNING":                 true,
 | |
| 		"REUSE":                     true,
 | |
| 		"REVERSE":                   true,
 | |
| 		"REVOKE":                    true,
 | |
| 		"ROLE":                      true,
 | |
| 		"ROLES":                     true,
 | |
| 		"ROLLBACK":                  true,
 | |
| 		"ROW":                       true,
 | |
| 		"ROWID":                     true,
 | |
| 		"ROWNUM":                    true,
 | |
| 		"ROWS":                      true,
 | |
| 		"RULE":                      true,
 | |
| 		"SAMPLE":                    true,
 | |
| 		"SAVEPOINT":                 true,
 | |
| 		"SB4":                       true,
 | |
| 		"SCAN_INSTANCES":            true,
 | |
| 		"SCHEMA":                    true,
 | |
| 		"SCN":                       true,
 | |
| 		"SCOPE":                     true,
 | |
| 		"SD_ALL":                    true,
 | |
| 		"SD_INHIBIT":                true,
 | |
| 		"SD_SHOW":                   true,
 | |
| 		"SEGMENT":                   true,
 | |
| 		"SEG_BLOCK":                 true,
 | |
| 		"SEG_FILE":                  true,
 | |
| 		"SELECT":                    true,
 | |
| 		"SEQUENCE":                  true,
 | |
| 		"SERIALIZABLE":              true,
 | |
| 		"SESSION":                   true,
 | |
| 		"SESSION_CACHED_CURSORS":    true,
 | |
| 		"SESSIONS_PER_USER":         true,
 | |
| 		"SET":                       true,
 | |
| 		"SHARE":                     true,
 | |
| 		"SHARED":                    true,
 | |
| 		"SHARED_POOL":               true,
 | |
| 		"SHRINK":                    true,
 | |
| 		"SIZE":                      true,
 | |
| 		"SKIP":                      true,
 | |
| 		"SKIP_UNUSABLE_INDEXES":     true,
 | |
| 		"SMALLINT":                  true,
 | |
| 		"SNAPSHOT":                  true,
 | |
| 		"SOME":                      true,
 | |
| 		"SORT":                      true,
 | |
| 		"SPECIFICATION":             true,
 | |
| 		"SPLIT":                     true,
 | |
| 		"SQL_TRACE":                 true,
 | |
| 		"STANDBY":                   true,
 | |
| 		"START":                     true,
 | |
| 		"STATEMENT_ID":              true,
 | |
| 		"STATISTICS":                true,
 | |
| 		"STOP":                      true,
 | |
| 		"STORAGE":                   true,
 | |
| 		"STORE":                     true,
 | |
| 		"STRUCTURE":                 true,
 | |
| 		"SUCCESSFUL":                true,
 | |
| 		"SWITCH":                    true,
 | |
| 		"SYS_OP_ENFORCE_NOT_NULL$":  true,
 | |
| 		"SYS_OP_NTCIMG$":            true,
 | |
| 		"SYNONYM":                   true,
 | |
| 		"SYSDATE":                   true,
 | |
| 		"SYSDBA":                    true,
 | |
| 		"SYSOPER":                   true,
 | |
| 		"SYSTEM":                    true,
 | |
| 		"TABLE":                     true,
 | |
| 		"TABLES":                    true,
 | |
| 		"TABLESPACE":                true,
 | |
| 		"TABLESPACE_NO":             true,
 | |
| 		"TABNO":                     true,
 | |
| 		"TEMPORARY":                 true,
 | |
| 		"THAN":                      true,
 | |
| 		"THE":                       true,
 | |
| 		"THEN":                      true,
 | |
| 		"THREAD":                    true,
 | |
| 		"TIMESTAMP":                 true,
 | |
| 		"TIME":                      true,
 | |
| 		"TO":                        true,
 | |
| 		"TOPLEVEL":                  true,
 | |
| 		"TRACE":                     true,
 | |
| 		"TRACING":                   true,
 | |
| 		"TRANSACTION":               true,
 | |
| 		"TRANSITIONAL":              true,
 | |
| 		"TRIGGER":                   true,
 | |
| 		"TRIGGERS":                  true,
 | |
| 		"TRUE":                      true,
 | |
| 		"TRUNCATE":                  true,
 | |
| 		"TX":                        true,
 | |
| 		"TYPE":                      true,
 | |
| 		"UB2":                       true,
 | |
| 		"UBA":                       true,
 | |
| 		"UID":                       true,
 | |
| 		"UNARCHIVED":                true,
 | |
| 		"UNDO":                      true,
 | |
| 		"UNION":                     true,
 | |
| 		"UNIQUE":                    true,
 | |
| 		"UNLIMITED":                 true,
 | |
| 		"UNLOCK":                    true,
 | |
| 		"UNRECOVERABLE":             true,
 | |
| 		"UNTIL":                     true,
 | |
| 		"UNUSABLE":                  true,
 | |
| 		"UNUSED":                    true,
 | |
| 		"UPDATABLE":                 true,
 | |
| 		"UPDATE":                    true,
 | |
| 		"USAGE":                     true,
 | |
| 		"USE":                       true,
 | |
| 		"USER":                      true,
 | |
| 		"USING":                     true,
 | |
| 		"VALIDATE":                  true,
 | |
| 		"VALIDATION":                true,
 | |
| 		"VALUE":                     true,
 | |
| 		"VALUES":                    true,
 | |
| 		"VARCHAR":                   true,
 | |
| 		"VARCHAR2":                  true,
 | |
| 		"VARYING":                   true,
 | |
| 		"VIEW":                      true,
 | |
| 		"WHEN":                      true,
 | |
| 		"WHENEVER":                  true,
 | |
| 		"WHERE":                     true,
 | |
| 		"WITH":                      true,
 | |
| 		"WITHOUT":                   true,
 | |
| 		"WORK":                      true,
 | |
| 		"WRITE":                     true,
 | |
| 		"WRITEDOWN":                 true,
 | |
| 		"WRITEUP":                   true,
 | |
| 		"XID":                       true,
 | |
| 		"YEAR":                      true,
 | |
| 		"ZONE":                      true,
 | |
| 	}
 | |
| 
 | |
| 	oracleQuoter = schemas.Quoter{'[', ']', schemas.AlwaysReserve}
 | |
| )
 | |
| 
 | |
| type oracle struct {
 | |
| 	Base
 | |
| }
 | |
| 
 | |
| func (db *oracle) Init(d *core.DB, uri *URI) error {
 | |
| 	db.quoter = oracleQuoter
 | |
| 	return db.Base.Init(d, db, uri)
 | |
| }
 | |
| 
 | |
| func (db *oracle) SQLType(c *schemas.Column) string {
 | |
| 	var res string
 | |
| 	switch t := c.SQLType.Name; t {
 | |
| 	case schemas.Bit, schemas.TinyInt, schemas.SmallInt, schemas.MediumInt, schemas.Int, schemas.Integer, schemas.BigInt, schemas.Bool, schemas.Serial, schemas.BigSerial:
 | |
| 		res = "NUMBER"
 | |
| 	case schemas.Binary, schemas.VarBinary, schemas.Blob, schemas.TinyBlob, schemas.MediumBlob, schemas.LongBlob, schemas.Bytea:
 | |
| 		return schemas.Blob
 | |
| 	case schemas.Time, schemas.DateTime, schemas.TimeStamp:
 | |
| 		res = schemas.TimeStamp
 | |
| 	case schemas.TimeStampz:
 | |
| 		res = "TIMESTAMP WITH TIME ZONE"
 | |
| 	case schemas.Float, schemas.Double, schemas.Numeric, schemas.Decimal:
 | |
| 		res = "NUMBER"
 | |
| 	case schemas.Text, schemas.MediumText, schemas.LongText, schemas.Json:
 | |
| 		res = "CLOB"
 | |
| 	case schemas.Char, schemas.Varchar, schemas.TinyText:
 | |
| 		res = "VARCHAR2"
 | |
| 	default:
 | |
| 		res = t
 | |
| 	}
 | |
| 
 | |
| 	hasLen1 := (c.Length > 0)
 | |
| 	hasLen2 := (c.Length2 > 0)
 | |
| 
 | |
| 	if hasLen2 {
 | |
| 		res += "(" + strconv.Itoa(c.Length) + "," + strconv.Itoa(c.Length2) + ")"
 | |
| 	} else if hasLen1 {
 | |
| 		res += "(" + strconv.Itoa(c.Length) + ")"
 | |
| 	}
 | |
| 	return res
 | |
| }
 | |
| 
 | |
| func (db *oracle) AutoIncrStr() string {
 | |
| 	return "AUTO_INCREMENT"
 | |
| }
 | |
| 
 | |
| func (db *oracle) IsReserved(name string) bool {
 | |
| 	_, ok := oracleReservedWords[strings.ToUpper(name)]
 | |
| 	return ok
 | |
| }
 | |
| 
 | |
| func (db *oracle) DropTableSQL(tableName string) (string, bool) {
 | |
| 	return fmt.Sprintf("DROP TABLE `%s`", tableName), false
 | |
| }
 | |
| 
 | |
| func (db *oracle) CreateTableSQL(table *schemas.Table, tableName string) ([]string, bool) {
 | |
| 	var sql = "CREATE TABLE "
 | |
| 	if tableName == "" {
 | |
| 		tableName = table.Name
 | |
| 	}
 | |
| 
 | |
| 	quoter := db.Quoter()
 | |
| 	sql += quoter.Quote(tableName) + " ("
 | |
| 
 | |
| 	pkList := table.PrimaryKeys
 | |
| 
 | |
| 	for _, colName := range table.ColumnsSeq() {
 | |
| 		col := table.GetColumn(colName)
 | |
| 		/*if col.IsPrimaryKey && len(pkList) == 1 {
 | |
| 			sql += col.String(b.dialect)
 | |
| 		} else {*/
 | |
| 		sql += db.StringNoPk(col)
 | |
| 		// }
 | |
| 		sql = strings.TrimSpace(sql)
 | |
| 		sql += ", "
 | |
| 	}
 | |
| 
 | |
| 	if len(pkList) > 0 {
 | |
| 		sql += "PRIMARY KEY ( "
 | |
| 		sql += quoter.Join(pkList, ",")
 | |
| 		sql += " ), "
 | |
| 	}
 | |
| 
 | |
| 	sql = sql[:len(sql)-2] + ")"
 | |
| 	return []string{sql}, false
 | |
| }
 | |
| 
 | |
| func (db *oracle) SetQuotePolicy(quotePolicy QuotePolicy) {
 | |
| 	switch quotePolicy {
 | |
| 	case QuotePolicyNone:
 | |
| 		var q = oracleQuoter
 | |
| 		q.IsReserved = schemas.AlwaysNoReserve
 | |
| 		db.quoter = q
 | |
| 	case QuotePolicyReserved:
 | |
| 		var q = oracleQuoter
 | |
| 		q.IsReserved = db.IsReserved
 | |
| 		db.quoter = q
 | |
| 	case QuotePolicyAlways:
 | |
| 		fallthrough
 | |
| 	default:
 | |
| 		db.quoter = oracleQuoter
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func (db *oracle) IndexCheckSQL(tableName, idxName string) (string, []interface{}) {
 | |
| 	args := []interface{}{tableName, idxName}
 | |
| 	return `SELECT INDEX_NAME FROM USER_INDEXES ` +
 | |
| 		`WHERE TABLE_NAME = :1 AND INDEX_NAME = :2`, args
 | |
| }
 | |
| 
 | |
| func (db *oracle) IsTableExist(ctx context.Context, tableName string) (bool, error) {
 | |
| 	return db.HasRecords(ctx, `SELECT table_name FROM user_tables WHERE table_name = :1`, tableName)
 | |
| }
 | |
| 
 | |
| func (db *oracle) IsColumnExist(ctx context.Context, tableName, colName string) (bool, error) {
 | |
| 	args := []interface{}{tableName, colName}
 | |
| 	query := "SELECT column_name FROM USER_TAB_COLUMNS WHERE table_name = :1" +
 | |
| 		" AND column_name = :2"
 | |
| 	return db.HasRecords(ctx, query, args...)
 | |
| }
 | |
| 
 | |
| func (db *oracle) GetColumns(ctx context.Context, tableName string) ([]string, map[string]*schemas.Column, error) {
 | |
| 	args := []interface{}{tableName}
 | |
| 	s := "SELECT column_name,data_default,data_type,data_length,data_precision,data_scale," +
 | |
| 		"nullable FROM USER_TAB_COLUMNS WHERE table_name = :1"
 | |
| 
 | |
| 	rows, err := db.DB().QueryContext(ctx, s, args...)
 | |
| 	if err != nil {
 | |
| 		return nil, nil, err
 | |
| 	}
 | |
| 	defer rows.Close()
 | |
| 
 | |
| 	cols := make(map[string]*schemas.Column)
 | |
| 	colSeq := make([]string, 0)
 | |
| 	for rows.Next() {
 | |
| 		col := new(schemas.Column)
 | |
| 		col.Indexes = make(map[string]int)
 | |
| 
 | |
| 		var colName, colDefault, nullable, dataType, dataPrecision, dataScale *string
 | |
| 		var dataLen int
 | |
| 
 | |
| 		err = rows.Scan(&colName, &colDefault, &dataType, &dataLen, &dataPrecision,
 | |
| 			&dataScale, &nullable)
 | |
| 		if err != nil {
 | |
| 			return nil, nil, err
 | |
| 		}
 | |
| 
 | |
| 		col.Name = strings.Trim(*colName, `" `)
 | |
| 		if colDefault != nil {
 | |
| 			col.Default = *colDefault
 | |
| 			col.DefaultIsEmpty = false
 | |
| 		}
 | |
| 
 | |
| 		if *nullable == "Y" {
 | |
| 			col.Nullable = true
 | |
| 		} else {
 | |
| 			col.Nullable = false
 | |
| 		}
 | |
| 
 | |
| 		var ignore bool
 | |
| 
 | |
| 		var dt string
 | |
| 		var len1, len2 int
 | |
| 		dts := strings.Split(*dataType, "(")
 | |
| 		dt = dts[0]
 | |
| 		if len(dts) > 1 {
 | |
| 			lens := strings.Split(dts[1][:len(dts[1])-1], ",")
 | |
| 			if len(lens) > 1 {
 | |
| 				len1, _ = strconv.Atoi(lens[0])
 | |
| 				len2, _ = strconv.Atoi(lens[1])
 | |
| 			} else {
 | |
| 				len1, _ = strconv.Atoi(lens[0])
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		switch dt {
 | |
| 		case "VARCHAR2":
 | |
| 			col.SQLType = schemas.SQLType{Name: schemas.Varchar, DefaultLength: len1, DefaultLength2: len2}
 | |
| 		case "NVARCHAR2":
 | |
| 			col.SQLType = schemas.SQLType{Name: schemas.NVarchar, DefaultLength: len1, DefaultLength2: len2}
 | |
| 		case "TIMESTAMP WITH TIME ZONE":
 | |
| 			col.SQLType = schemas.SQLType{Name: schemas.TimeStampz, DefaultLength: 0, DefaultLength2: 0}
 | |
| 		case "NUMBER":
 | |
| 			col.SQLType = schemas.SQLType{Name: schemas.Double, DefaultLength: len1, DefaultLength2: len2}
 | |
| 		case "LONG", "LONG RAW":
 | |
| 			col.SQLType = schemas.SQLType{Name: schemas.Text, DefaultLength: 0, DefaultLength2: 0}
 | |
| 		case "RAW":
 | |
| 			col.SQLType = schemas.SQLType{Name: schemas.Binary, DefaultLength: 0, DefaultLength2: 0}
 | |
| 		case "ROWID":
 | |
| 			col.SQLType = schemas.SQLType{Name: schemas.Varchar, DefaultLength: 18, DefaultLength2: 0}
 | |
| 		case "AQ$_SUBSCRIBERS":
 | |
| 			ignore = true
 | |
| 		default:
 | |
| 			col.SQLType = schemas.SQLType{Name: strings.ToUpper(dt), DefaultLength: len1, DefaultLength2: len2}
 | |
| 		}
 | |
| 
 | |
| 		if ignore {
 | |
| 			continue
 | |
| 		}
 | |
| 
 | |
| 		if _, ok := schemas.SqlTypes[col.SQLType.Name]; !ok {
 | |
| 			return nil, nil, fmt.Errorf("Unknown colType %v %v", *dataType, col.SQLType)
 | |
| 		}
 | |
| 
 | |
| 		col.Length = dataLen
 | |
| 
 | |
| 		if col.SQLType.IsText() || col.SQLType.IsTime() {
 | |
| 			if !col.DefaultIsEmpty {
 | |
| 				col.Default = "'" + col.Default + "'"
 | |
| 			}
 | |
| 		}
 | |
| 		cols[col.Name] = col
 | |
| 		colSeq = append(colSeq, col.Name)
 | |
| 	}
 | |
| 
 | |
| 	return colSeq, cols, nil
 | |
| }
 | |
| 
 | |
| func (db *oracle) GetTables(ctx context.Context) ([]*schemas.Table, error) {
 | |
| 	args := []interface{}{}
 | |
| 	s := "SELECT table_name FROM user_tables"
 | |
| 
 | |
| 	rows, err := db.DB().QueryContext(ctx, s, args...)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	defer rows.Close()
 | |
| 
 | |
| 	tables := make([]*schemas.Table, 0)
 | |
| 	for rows.Next() {
 | |
| 		table := schemas.NewEmptyTable()
 | |
| 		err = rows.Scan(&table.Name)
 | |
| 		if err != nil {
 | |
| 			return nil, err
 | |
| 		}
 | |
| 
 | |
| 		tables = append(tables, table)
 | |
| 	}
 | |
| 	return tables, nil
 | |
| }
 | |
| 
 | |
| func (db *oracle) GetIndexes(ctx context.Context, tableName string) (map[string]*schemas.Index, error) {
 | |
| 	args := []interface{}{tableName}
 | |
| 	s := "SELECT t.column_name,i.uniqueness,i.index_name FROM user_ind_columns t,user_indexes i " +
 | |
| 		"WHERE t.index_name = i.index_name and t.table_name = i.table_name and t.table_name =:1"
 | |
| 
 | |
| 	rows, err := db.DB().QueryContext(ctx, s, args...)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	defer rows.Close()
 | |
| 
 | |
| 	indexes := make(map[string]*schemas.Index, 0)
 | |
| 	for rows.Next() {
 | |
| 		var indexType int
 | |
| 		var indexName, colName, uniqueness string
 | |
| 
 | |
| 		err = rows.Scan(&colName, &uniqueness, &indexName)
 | |
| 		if err != nil {
 | |
| 			return nil, err
 | |
| 		}
 | |
| 
 | |
| 		indexName = strings.Trim(indexName, `" `)
 | |
| 
 | |
| 		var isRegular bool
 | |
| 		if strings.HasPrefix(indexName, "IDX_"+tableName) || strings.HasPrefix(indexName, "UQE_"+tableName) {
 | |
| 			indexName = indexName[5+len(tableName):]
 | |
| 			isRegular = true
 | |
| 		}
 | |
| 
 | |
| 		if uniqueness == "UNIQUE" {
 | |
| 			indexType = schemas.UniqueType
 | |
| 		} else {
 | |
| 			indexType = schemas.IndexType
 | |
| 		}
 | |
| 
 | |
| 		var index *schemas.Index
 | |
| 		var ok bool
 | |
| 		if index, ok = indexes[indexName]; !ok {
 | |
| 			index = new(schemas.Index)
 | |
| 			index.Type = indexType
 | |
| 			index.Name = indexName
 | |
| 			index.IsRegular = isRegular
 | |
| 			indexes[indexName] = index
 | |
| 		}
 | |
| 		index.AddColumn(colName)
 | |
| 	}
 | |
| 	return indexes, nil
 | |
| }
 | |
| 
 | |
| func (db *oracle) Filters() []Filter {
 | |
| 	return []Filter{
 | |
| 		&SeqFilter{Prefix: ":", Start: 1},
 | |
| 	}
 | |
| }
 | |
| 
 | |
| type goracleDriver struct {
 | |
| }
 | |
| 
 | |
| func (cfg *goracleDriver) Parse(driverName, dataSourceName string) (*URI, error) {
 | |
| 	db := &URI{DBType: schemas.ORACLE}
 | |
| 	dsnPattern := regexp.MustCompile(
 | |
| 		`^(?:(?P<user>.*?)(?::(?P<passwd>.*))?@)?` + // [user[:password]@]
 | |
| 			`(?:(?P<net>[^\(]*)(?:\((?P<addr>[^\)]*)\))?)?` + // [net[(addr)]]
 | |
| 			`\/(?P<dbname>.*?)` + // /dbname
 | |
| 			`(?:\?(?P<params>[^\?]*))?$`) // [?param1=value1¶mN=valueN]
 | |
| 	matches := dsnPattern.FindStringSubmatch(dataSourceName)
 | |
| 	// tlsConfigRegister := make(map[string]*tls.Config)
 | |
| 	names := dsnPattern.SubexpNames()
 | |
| 
 | |
| 	for i, match := range matches {
 | |
| 		switch names[i] {
 | |
| 		case "dbname":
 | |
| 			db.DBName = match
 | |
| 		}
 | |
| 	}
 | |
| 	if db.DBName == "" {
 | |
| 		return nil, errors.New("dbname is empty")
 | |
| 	}
 | |
| 	return db, nil
 | |
| }
 | |
| 
 | |
| type oci8Driver struct {
 | |
| }
 | |
| 
 | |
| // dataSourceName=user/password@ipv4:port/dbname
 | |
| // dataSourceName=user/password@[ipv6]:port/dbname
 | |
| func (p *oci8Driver) Parse(driverName, dataSourceName string) (*URI, error) {
 | |
| 	db := &URI{DBType: schemas.ORACLE}
 | |
| 	dsnPattern := regexp.MustCompile(
 | |
| 		`^(?P<user>.*)\/(?P<password>.*)@` + // user:password@
 | |
| 			`(?P<net>.*)` + // ip:port
 | |
| 			`\/(?P<dbname>.*)`) // dbname
 | |
| 	matches := dsnPattern.FindStringSubmatch(dataSourceName)
 | |
| 	names := dsnPattern.SubexpNames()
 | |
| 	for i, match := range matches {
 | |
| 		switch names[i] {
 | |
| 		case "dbname":
 | |
| 			db.DBName = match
 | |
| 		}
 | |
| 	}
 | |
| 	if db.DBName == "" {
 | |
| 		return nil, errors.New("dbname is empty")
 | |
| 	}
 | |
| 	return db, nil
 | |
| }
 |