|
| 1 | +package sqlparser |
| 2 | + |
| 3 | +import ( |
| 4 | + "fmt" |
| 5 | + "github.com/viant/parsly" |
| 6 | + "github.com/viant/sqlparser/index" |
| 7 | + "strings" |
| 8 | +) |
| 9 | + |
| 10 | +// ParseDropIndex parses drop table |
| 11 | +func ParseDropIndex(SQL string) (*index.Drop, error) { |
| 12 | + result := &index.Drop{} |
| 13 | + SQL = removeSQLComments(SQL) |
| 14 | + cursor := parsly.NewCursor("", []byte(SQL), 0) |
| 15 | + err := parseDropIndex(cursor, result) |
| 16 | + if err != nil { |
| 17 | + return result, fmt.Errorf("%s", SQL) |
| 18 | + } |
| 19 | + return result, err |
| 20 | +} |
| 21 | + |
| 22 | +func parseDropIndex(cursor *parsly.Cursor, dest *index.Drop) error { |
| 23 | + match := cursor.MatchAfterOptional(whitespaceMatcher, dropIndexMatcher) |
| 24 | + if match.Code != dropIndexToken { |
| 25 | + return cursor.NewError(createMatcher) |
| 26 | + } |
| 27 | + if match = cursor.MatchOne(whitespaceMatcher); match.Code != whitespaceCode { |
| 28 | + return cursor.NewError(whitespaceMatcher) |
| 29 | + } |
| 30 | + if match = cursor.MatchOne(ifExistsMatcher); match.Code == ifExistsToken { |
| 31 | + dest.IfExists = true |
| 32 | + } |
| 33 | + match = cursor.MatchAfterOptional(whitespaceMatcher, identifierMatcher) |
| 34 | + if match.Code != identifierCode { |
| 35 | + return cursor.NewError(ifNotExistsMatcher) |
| 36 | + } |
| 37 | + dest.Name = match.Text(cursor) |
| 38 | + match = cursor.MatchAfterOptional(whitespaceMatcher, onKeywordMatcher) |
| 39 | + if match.Code != onKeyword { |
| 40 | + return cursor.NewError(ifNotExistsMatcher) |
| 41 | + } |
| 42 | + match = cursor.MatchAfterOptional(whitespaceMatcher, selectorMatcher) |
| 43 | + if match.Code == selectorTokenCode { |
| 44 | + selector := match.Text(cursor) |
| 45 | + if index := strings.Index(selector, "."); index != -1 { |
| 46 | + dest.Schema = selector[0:index] |
| 47 | + dest.Table = selector[index+1:] |
| 48 | + } else { |
| 49 | + dest.Table = selector |
| 50 | + } |
| 51 | + } |
| 52 | + return nil |
| 53 | +} |
| 54 | + |
| 55 | +// ParseCreateIndex parses create table |
| 56 | +func ParseCreateIndex(SQL string) (*index.Create, error) { |
| 57 | + result := &index.Create{} |
| 58 | + SQL = removeSQLComments(SQL) |
| 59 | + result.Spec.SQL = SQL |
| 60 | + cursor := parsly.NewCursor("", []byte(SQL), 0) |
| 61 | + err := parseCreateIndex(cursor, result) |
| 62 | + if err != nil { |
| 63 | + return result, fmt.Errorf("%s", SQL) |
| 64 | + } |
| 65 | + return result, err |
| 66 | +} |
| 67 | + |
| 68 | +func parseCreateIndex(cursor *parsly.Cursor, dest *index.Create) error { |
| 69 | + match := cursor.MatchAfterOptional(whitespaceMatcher, createMatcher) |
| 70 | + if match.Code != createToken { |
| 71 | + return cursor.NewError(createMatcher) |
| 72 | + } |
| 73 | + if match = cursor.MatchOne(whitespaceMatcher); match.Code != whitespaceCode { |
| 74 | + return cursor.NewError(whitespaceMatcher) |
| 75 | + } |
| 76 | + |
| 77 | + if match = cursor.MatchOne(ifNotExistsMatcher); match.Code == ifNotExistsToken { |
| 78 | + dest.IfDoesExists = true |
| 79 | + } |
| 80 | + |
| 81 | + match = cursor.MatchAfterOptional(whitespaceMatcher, indexMatcher) |
| 82 | + if match.Code == indexToken { |
| 83 | + match = cursor.MatchAfterOptional(whitespaceMatcher, identifierMatcher) |
| 84 | + if match.Code != identifierCode { |
| 85 | + return cursor.NewError(ifNotExistsMatcher) |
| 86 | + } |
| 87 | + dest.Spec.Name = match.Text(cursor) |
| 88 | + |
| 89 | + } else { |
| 90 | + match = cursor.MatchAfterOptional(whitespaceMatcher, identifierMatcher) |
| 91 | + if match.Code != identifierCode { |
| 92 | + return cursor.NewError(ifNotExistsMatcher) |
| 93 | + } |
| 94 | + dest.Spec.Type = match.Text(cursor) |
| 95 | + match = cursor.MatchAfterOptional(whitespaceMatcher, indexMatcher) |
| 96 | + if match.Code != indexToken { |
| 97 | + return cursor.NewError(indexMatcher) |
| 98 | + } |
| 99 | + match = cursor.MatchAfterOptional(whitespaceMatcher, identifierMatcher) |
| 100 | + if match.Code != identifierCode { |
| 101 | + return cursor.NewError(ifNotExistsMatcher) |
| 102 | + } |
| 103 | + dest.Spec.Name = match.Text(cursor) |
| 104 | + } |
| 105 | + |
| 106 | + match = cursor.MatchAfterOptional(whitespaceMatcher, onKeywordMatcher) |
| 107 | + if match.Code != onKeyword { |
| 108 | + return cursor.NewError(parenthesesMatcher) |
| 109 | + } |
| 110 | + |
| 111 | + match = cursor.MatchAfterOptional(whitespaceMatcher, selectorMatcher) |
| 112 | + if match.Code != selectorTokenCode { |
| 113 | + return cursor.NewError(selectorMatcher) |
| 114 | + |
| 115 | + } |
| 116 | + selector := match.Text(cursor) |
| 117 | + if index := strings.Index(selector, "."); index != -1 { |
| 118 | + dest.Spec.Schema = selector[0:index] |
| 119 | + dest.Spec.Table = selector[index+1:] |
| 120 | + } else { |
| 121 | + dest.Spec.Table = selector |
| 122 | + } |
| 123 | + |
| 124 | + match = cursor.MatchAfterOptional(whitespaceMatcher, parenthesesMatcher) |
| 125 | + if match.Code != parenthesesCode { |
| 126 | + return cursor.NewError(parenthesesMatcher) |
| 127 | + } |
| 128 | + columnSpec := match.Text(cursor) |
| 129 | + pos := cursor.Pos |
| 130 | + columnCursor := parsly.NewCursor(cursor.Path, []byte(columnSpec[1:len(columnSpec)-1]), pos) |
| 131 | + |
| 132 | + return parseIndexColumnSpec(dest, match, columnCursor) |
| 133 | +} |
| 134 | + |
| 135 | +func parseIndexColumnSpec(dest *index.Create, match *parsly.TokenMatch, cursor *parsly.Cursor) error { |
| 136 | + for { |
| 137 | + col := &index.ColumnSpec{} |
| 138 | + dest.Spec.Columns = append(dest.Spec.Columns, col) |
| 139 | + match = cursor.MatchAfterOptional(whitespaceMatcher, identifierMatcher) |
| 140 | + if match.Code != identifierCode { |
| 141 | + return cursor.NewError(ifNotExistsMatcher) |
| 142 | + } |
| 143 | + col.Name = match.Text(cursor) |
| 144 | + match = cursor.MatchAfterOptional(whitespaceMatcher, nextMatcher) |
| 145 | + if match.Code != nextCode { |
| 146 | + break |
| 147 | + } |
| 148 | + } |
| 149 | + return nil |
| 150 | +} |
0 commit comments