webv2/api/sequence.go (158 lines of code) (raw):

package api import ( "encoding/json" "fmt" "io/ioutil" "net/http" "strings" "github.com/GoogleCloudPlatform/spanner-migration-tool/common/constants" "github.com/GoogleCloudPlatform/spanner-migration-tool/internal" "github.com/GoogleCloudPlatform/spanner-migration-tool/spanner/ddl" "github.com/GoogleCloudPlatform/spanner-migration-tool/webv2/session" "github.com/GoogleCloudPlatform/spanner-migration-tool/webv2/utilities" ) func AddNewSequence(w http.ResponseWriter, r *http.Request) { fmt.Println("request started", "method", r.Method, "path", r.URL.Path) reqBody, err := ioutil.ReadAll(r.Body) if err != nil { fmt.Println("request's body Read Error") http.Error(w, fmt.Sprintf("Body Read Error : %v", err), http.StatusInternalServerError) } seq := ddl.Sequence{} err = json.Unmarshal(reqBody, &seq) if err != nil { fmt.Println("request's Body parse error") http.Error(w, fmt.Sprintf("Request Body parse error : %v", err), http.StatusBadRequest) return } seq.ColumnsUsingSeq = make(map[string][]string) sessionState := session.GetSessionState() sessionState.Conv.ConvLock.Lock() defer sessionState.Conv.ConvLock.Unlock() if ok, _ := utilities.CheckSpannerNamesValidity([]string{seq.Name}); !ok { http.Error(w, fmt.Sprintf("Sequence Name is not valid: %v", seq.Name), http.StatusBadRequest) return } // Check that the new names are not already used by existing tables, secondary indexes, sequence or foreign key constraints. if ok, err := utilities.CanRename([]string{seq.Name}, ""); !ok { http.Error(w, err.Error(), http.StatusBadRequest) return } spSequences := sessionState.Conv.SpSequences seq.Id = internal.GenerateSequenceId() sessionState.Conv.UsedNames[strings.ToLower(seq.Name)] = true spSequences[seq.Id] = seq sessionState.Conv.SpSequences = spSequences convm := session.ConvWithMetadata{ SessionMetadata: sessionState.SessionMetadata, Conv: *sessionState.Conv, } w.WriteHeader(http.StatusOK) json.NewEncoder(w).Encode(convm) } func UpdateSequence(w http.ResponseWriter, r *http.Request) { fmt.Println("request started", "method", r.Method, "path", r.URL.Path) reqBody, err := ioutil.ReadAll(r.Body) if err != nil { fmt.Println("request's body Read Error") http.Error(w, fmt.Sprintf("Body Read Error : %v", err), http.StatusInternalServerError) } newSeq := ddl.Sequence{} err = json.Unmarshal(reqBody, &newSeq) if err != nil { fmt.Println("request's Body parse error") http.Error(w, fmt.Sprintf("Request Body parse error : %v", err), http.StatusBadRequest) return } sessionState := session.GetSessionState() sessionState.Conv.ConvLock.Lock() defer sessionState.Conv.ConvLock.Unlock() spSequences := sessionState.Conv.SpSequences for i, seq := range spSequences { if seq.Id == newSeq.Id { newSeq.ColumnsUsingSeq = spSequences[i].ColumnsUsingSeq spSequences[i] = newSeq break } } sessionState.Conv.SpSequences = spSequences convm := session.ConvWithMetadata{ SessionMetadata: sessionState.SessionMetadata, Conv: *sessionState.Conv, } w.WriteHeader(http.StatusOK) json.NewEncoder(w).Encode(convm) } func DropSequence(w http.ResponseWriter, r *http.Request) { sequenceId := r.FormValue("sequence") sessionState := session.GetSessionState() sessionState.Conv.ConvLock.Lock() defer sessionState.Conv.ConvLock.Unlock() if sessionState.Conv == nil || sessionState.Driver == "" { http.Error(w, "Schema is not converted or Driver is not configured properly. Please retry converting the database to Spanner.", http.StatusNotFound) return } spSequence := sessionState.Conv.SpSequences if sequenceId == "" { http.Error(w, "Sequence name is empty", http.StatusBadRequest) } if _, seqExists := spSequence[sequenceId]; !seqExists { http.Error(w, "Sequence doesn't exist", http.StatusBadRequest) } updatedTables := dropSequenceHelper(spSequence[sequenceId].ColumnsUsingSeq, sessionState.Conv.SpSchema) sessionState.Conv.SpSchema = updatedTables sequenceName := getSequenceName(sequenceId, spSequence) usedNames := sessionState.Conv.UsedNames delete(usedNames, sequenceName) delete(spSequence, sequenceId) sessionState.Conv.SpSequences = spSequence convm := session.ConvWithMetadata{ SessionMetadata: sessionState.SessionMetadata, Conv: *sessionState.Conv, } w.WriteHeader(http.StatusOK) json.NewEncoder(w).Encode(convm) } func dropSequenceHelper(columnsUsingSeq map[string][]string, tables ddl.Schema) ddl.Schema { for tableName, columns := range columnsUsingSeq { for _, colId := range columns { columnDef := tables[tableName].ColDefs[colId] columnDef.AutoGen = ddl.AutoGenCol{} tables[tableName].ColDefs[colId] = columnDef } } return tables } func GetSequenceDDL(w http.ResponseWriter, r *http.Request) { sessionState := session.GetSessionState() sessionState.Conv.ConvLock.Lock() defer sessionState.Conv.ConvLock.Unlock() conv := sessionState.Conv seqDDL := make(map[string]string) for seqName, seq := range sessionState.Conv.SpSequences { var sDdl string switch sessionState.Dialect { case constants.POSTGRES: sDdl = seq.PGPrintSequence(ddl.Config{ProtectIds: false, SpDialect: conv.SpDialect}) default: sDdl = seq.PrintSequence(ddl.Config{ProtectIds: false, SpDialect: conv.SpDialect}) } seqDDL[seqName] = sDdl } w.WriteHeader(http.StatusOK) json.NewEncoder(w).Encode(seqDDL) } func GetSequenceKind(w http.ResponseWriter, r *http.Request) { sequenceKind := []string{ "BIT REVERSED POSITIVE", } w.WriteHeader(http.StatusOK) json.NewEncoder(w).Encode(sequenceKind) } func getSequenceName(sequenceId string, spSequences map[string]ddl.Sequence) string { for seqId, seq := range spSequences { if seqId == sequenceId { return seq.Name } } return "" }