Skip to content

Commit 3736e70

Browse files
committed
change unrelated code back
1 parent c4f7bf3 commit 3736e70

File tree

17 files changed

+143
-201
lines changed

17 files changed

+143
-201
lines changed

sql/catalyst/src/main/antlr4/org/apache/spark/sql/catalyst/parser/SqlBase.g4

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -764,8 +764,7 @@ errorCapturingMultiUnitsInterval
764764
;
765765

766766
multiUnitsInterval
767-
: {!ansi}? STRING
768-
| (intervalValue intervalUnit)+
767+
: (intervalValue intervalUnit)+
769768
;
770769

771770
errorCapturingUnitToUnitInterval

sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/TimeWindow.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ object TimeWindow {
103103
* precision.
104104
*/
105105
private def getIntervalInMicroSeconds(interval: String): Long = {
106-
val cal = IntervalUtils.fromString(interval)
106+
val cal = IntervalUtils.fromMultiUnitsString(interval)
107107
if (cal.months != 0) {
108108
throw new IllegalArgumentException(
109109
s"Intervals greater than a month is not supported ($interval).")

sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/parser/AstBuilder.scala

Lines changed: 20 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1775,7 +1775,7 @@ class AstBuilder(conf: SQLConf) extends SqlBaseBaseVisitor[AnyRef] with Logging
17751775
toLiteral(stringToTimestamp(_, zoneId), TimestampType)
17761776
case "INTERVAL" =>
17771777
val interval = try {
1778-
IntervalUtils.fromString(value)
1778+
IntervalUtils.fromMultiUnitsString(value)
17791779
} catch {
17801780
case e: IllegalArgumentException =>
17811781
val ex = new ParseException("Cannot parse the INTERVAL value: " + value, ctx)
@@ -1959,23 +1959,21 @@ class AstBuilder(conf: SQLConf) extends SqlBaseBaseVisitor[AnyRef] with Logging
19591959
*/
19601960
override def visitMultiUnitsInterval(ctx: MultiUnitsIntervalContext): CalendarInterval = {
19611961
withOrigin(ctx) {
1962-
try {
1963-
if (ctx.STRING() != null) {
1964-
val str = string(ctx.STRING()).trim.toLowerCase(Locale.ROOT)
1965-
IntervalUtils.fromMultiUnitsString(str)
1962+
val units = ctx.intervalUnit().asScala.map { unit =>
1963+
val u = unit.getText.toLowerCase(Locale.ROOT)
1964+
// Handle plural forms, e.g: yearS/monthS/weekS/dayS/hourS/minuteS/hourS/...
1965+
if (u.endsWith("s")) u.substring(0, u.length - 1) else u
1966+
}.toArray
1967+
1968+
val values = ctx.intervalValue().asScala.map { value =>
1969+
if (value.STRING() != null) {
1970+
string(value.STRING())
19661971
} else {
1967-
val units = ctx.intervalUnit().asScala.map { unit =>
1968-
IntervalUnit.fromString(unit.getText)
1969-
}.toArray
1970-
val values = ctx.intervalValue().asScala.map { value =>
1971-
if (value.STRING() != null) {
1972-
string(value.STRING())
1973-
} else {
1974-
value.getText
1975-
}
1976-
}.toArray
1977-
IntervalUtils.fromUnitStrings(units, values)
1972+
value.getText
19781973
}
1974+
}.toArray
1975+
try {
1976+
IntervalUtils.fromUnitStrings(units, values)
19791977
} catch {
19801978
case i: IllegalArgumentException =>
19811979
val e = new ParseException(i.getMessage, ctx)
@@ -2000,17 +1998,17 @@ class AstBuilder(conf: SQLConf) extends SqlBaseBaseVisitor[AnyRef] with Logging
20001998
case ("year", "month") =>
20011999
IntervalUtils.fromYearMonthString(value)
20022000
case ("day", "hour") =>
2003-
IntervalUtils.fromDayTimeString(value, IntervalUnit.DAY, IntervalUnit.HOUR)
2001+
IntervalUtils.fromDayTimeString(value, "day", "hour")
20042002
case ("day", "minute") =>
2005-
IntervalUtils.fromDayTimeString(value, IntervalUnit.DAY, IntervalUnit.MINUTE)
2003+
IntervalUtils.fromDayTimeString(value, "day", "minute")
20062004
case ("day", "second") =>
2007-
IntervalUtils.fromDayTimeString(value, IntervalUnit.DAY, IntervalUnit.SECOND)
2005+
IntervalUtils.fromDayTimeString(value, "day", "second")
20082006
case ("hour", "minute") =>
2009-
IntervalUtils.fromDayTimeString(value, IntervalUnit.HOUR, IntervalUnit.MINUTE)
2007+
IntervalUtils.fromDayTimeString(value, "hour", "minute")
20102008
case ("hour", "second") =>
2011-
IntervalUtils.fromDayTimeString(value, IntervalUnit.HOUR, IntervalUnit.SECOND)
2009+
IntervalUtils.fromDayTimeString(value, "hour", "second")
20122010
case ("minute", "second") =>
2013-
IntervalUtils.fromDayTimeString(value, IntervalUnit.MINUTE, IntervalUnit.SECOND)
2011+
IntervalUtils.fromDayTimeString(value, "minute", "second")
20142012
case _ =>
20152013
throw new ParseException(s"Intervals FROM $from TO $to are not supported.", ctx)
20162014
}

sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/util/IntervalUtils.scala

Lines changed: 55 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -17,18 +17,15 @@
1717

1818
package org.apache.spark.sql.catalyst.util
1919

20-
import java.util.Locale
2120
import java.util.concurrent.TimeUnit
2221

2322
import scala.util.control.NonFatal
2423

25-
import org.apache.spark.sql.catalyst.parser.{CatalystSqlParser, ParseException}
2624
import org.apache.spark.sql.catalyst.util.DateTimeConstants._
2725
import org.apache.spark.sql.types.Decimal
2826
import org.apache.spark.unsafe.types.{CalendarInterval, UTF8String}
2927

3028
object IntervalUtils {
31-
import IntervalUnit._
3229

3330
def getYears(interval: CalendarInterval): Int = {
3431
interval.months / MONTHS_PER_YEAR
@@ -87,42 +84,14 @@ object IntervalUtils {
8784
Decimal(result, 18, 6)
8885
}
8986

90-
/**
91-
* Converts a string to [[CalendarInterval]] case-insensitively.
92-
*
93-
* @throws IllegalArgumentException if the input string is not in valid interval format.
94-
*/
95-
def fromString(str: String): CalendarInterval = {
96-
if (str == null) throw new IllegalArgumentException("Interval string cannot be null")
97-
try {
98-
CatalystSqlParser.parseInterval(str)
99-
} catch {
100-
case e: ParseException =>
101-
val ex = new IllegalArgumentException(s"Invalid interval string: $str\n" + e.message)
102-
ex.setStackTrace(e.getStackTrace)
103-
throw ex
104-
}
105-
}
106-
107-
/**
108-
* A safe version of `fromString`. It returns null for invalid input string.
109-
*/
110-
def safeFromString(str: String): CalendarInterval = {
111-
try {
112-
fromString(str)
113-
} catch {
114-
case _: IllegalArgumentException => null
115-
}
116-
}
117-
11887
private def toLongWithRange(
119-
fieldName: IntervalUnit,
88+
fieldName: String,
12089
s: String,
12190
minValue: Long,
12291
maxValue: Long): Long = {
12392
val result = if (s == null) 0L else s.toLong
12493
require(minValue <= result && result <= maxValue,
125-
s"${fieldName.toString} $result outside range [$minValue, $maxValue]")
94+
s"$fieldName $result outside range [$minValue, $maxValue]")
12695

12796
result
12897
}
@@ -138,8 +107,8 @@ object IntervalUtils {
138107
require(input != null, "Interval year-month string must be not null")
139108
def toInterval(yearStr: String, monthStr: String): CalendarInterval = {
140109
try {
141-
val years = toLongWithRange(YEAR, yearStr, 0, Integer.MAX_VALUE).toInt
142-
val months = toLongWithRange(MONTH, monthStr, 0, 11).toInt
110+
val years = toLongWithRange("year", yearStr, 0, Integer.MAX_VALUE).toInt
111+
val months = toLongWithRange("month", monthStr, 0, 11).toInt
143112
val totalMonths = Math.addExact(Math.multiplyExact(years, 12), months)
144113
new CalendarInterval(totalMonths, 0, 0)
145114
} catch {
@@ -166,7 +135,7 @@ object IntervalUtils {
166135
* adapted from HiveIntervalDayTime.valueOf
167136
*/
168137
def fromDayTimeString(s: String): CalendarInterval = {
169-
fromDayTimeString(s, DAY, SECOND)
138+
fromDayTimeString(s, "day", "second")
170139
}
171140

172141
private val dayTimePattern =
@@ -181,7 +150,7 @@ object IntervalUtils {
181150
* - HOUR TO (MINUTE|SECOND)
182151
* - MINUTE TO SECOND
183152
*/
184-
def fromDayTimeString(input: String, from: IntervalUnit, to: IntervalUnit): CalendarInterval = {
153+
def fromDayTimeString(input: String, from: String, to: String): CalendarInterval = {
185154
require(input != null, "Interval day-time string must be not null")
186155
assert(input.length == input.trim.length)
187156
val m = dayTimePattern.pattern.matcher(input)
@@ -192,33 +161,33 @@ object IntervalUtils {
192161
val days = if (m.group(2) == null) {
193162
0
194163
} else {
195-
toLongWithRange(DAY, m.group(3), 0, Integer.MAX_VALUE).toInt
164+
toLongWithRange("day", m.group(3), 0, Integer.MAX_VALUE).toInt
196165
}
197166
var hours: Long = 0L
198167
var minutes: Long = 0L
199168
var seconds: Long = 0L
200-
if (m.group(5) != null || from == MINUTE) { // 'HH:mm:ss' or 'mm:ss minute'
201-
hours = toLongWithRange(HOUR, m.group(5), 0, 23)
202-
minutes = toLongWithRange(MINUTE, m.group(6), 0, 59)
203-
seconds = toLongWithRange(SECOND, m.group(7), 0, 59)
169+
if (m.group(5) != null || from == "minute") { // 'HH:mm:ss' or 'mm:ss minute'
170+
hours = toLongWithRange("hour", m.group(5), 0, 23)
171+
minutes = toLongWithRange("minute", m.group(6), 0, 59)
172+
seconds = toLongWithRange("second", m.group(7), 0, 59)
204173
} else if (m.group(8) != null) { // 'mm:ss.nn'
205-
minutes = toLongWithRange(MINUTE, m.group(6), 0, 59)
206-
seconds = toLongWithRange(SECOND, m.group(7), 0, 59)
174+
minutes = toLongWithRange("minute", m.group(6), 0, 59)
175+
seconds = toLongWithRange("second", m.group(7), 0, 59)
207176
} else { // 'HH:mm'
208-
hours = toLongWithRange(HOUR, m.group(6), 0, 23)
209-
minutes = toLongWithRange(SECOND, m.group(7), 0, 59)
177+
hours = toLongWithRange("hour", m.group(6), 0, 23)
178+
minutes = toLongWithRange("second", m.group(7), 0, 59)
210179
}
211180
// Hive allow nanosecond precision interval
212181
var secondsFraction = parseNanos(m.group(9), seconds < 0)
213182
to match {
214-
case HOUR =>
183+
case "hour" =>
215184
minutes = 0
216185
seconds = 0
217186
secondsFraction = 0
218-
case MINUTE =>
187+
case "minute" =>
219188
seconds = 0
220189
secondsFraction = 0
221-
case SECOND =>
190+
case "second" =>
222191
// No-op
223192
case _ =>
224193
throw new IllegalArgumentException(
@@ -236,21 +205,40 @@ object IntervalUtils {
236205
}
237206
}
238207

208+
private val isYear: String => Boolean =
209+
y => """y((r)|(rs)|(ear)|(ears))?""".r.pattern.matcher(y).matches()
210+
private val isMonth: String => Boolean =
211+
mon => """mon((s)|(th)|(ths))?""".r.pattern.matcher(mon).matches()
212+
private val isWeek: String => Boolean =
213+
w => """w((eek)|(eeks))?""".r.pattern.matcher(w).matches()
214+
private val isDay: String => Boolean =
215+
d => """d((ay)|(ays))?""".r.pattern.matcher(d).matches()
216+
private val isHour: String => Boolean =
217+
h => """h((r)|(rs)|(our)|(ours))?""".r.pattern.matcher(h).matches()
218+
private val isMinute: String => Boolean =
219+
m => """m((in)|(ins)|(inute)|(inutes))?""".r.pattern.matcher(m).matches()
220+
private val isSecond: String => Boolean =
221+
s => """s((ec)|(ecs)|(econd)|(econds))?""".r.pattern.matcher(s).matches()
222+
private val isMs: String => Boolean =
223+
ms => """(ms((ec)|(ecs)|(econds))?|(millisecond)[s]?)""".r.pattern.matcher(ms).matches()
224+
private val isUs: String => Boolean =
225+
us => """(us((ec)|(ecs)|(econds))?|(microsecond)[s]?)""".r.pattern.matcher(us).matches()
226+
239227
/**
240228
* Converts a string with multiple value unit pairs to [[CalendarInterval]] case-insensitively.
241229
*
242230
* @throws IllegalArgumentException if the input string is not in valid interval format.
243231
*/
244232
def fromMultiUnitsString(str: String): CalendarInterval = {
245233
if (str == null) throw new IllegalArgumentException("Interval multi unit string cannot be null")
234+
var months: Int = 0
235+
var days: Int = 0
236+
var us: Long = 0L
237+
var array = """-\s+""".r.replaceAllIn(str.stripPrefix("interval "), "-")
238+
.split("\\s+").filter(_ != "+").toList
239+
require(array.length % 2 == 0, "Interval string should be value and unit pairs")
246240

247241
try {
248-
var months: Int = 0
249-
var days: Int = 0
250-
var us: Long = 0L
251-
var array = """-\s+""".r.replaceAllIn(str.stripPrefix("interval "), "-")
252-
.split("\\s+").filter(_ != "+").toList
253-
require(array.length % 2 == 0, "Interval string should be value and unit pairs")
254242
while (array.nonEmpty) {
255243
array match {
256244
case valueStr :: unit :: tail =>
@@ -287,7 +275,7 @@ object IntervalUtils {
287275
}
288276
}
289277

290-
def fromUnitStrings(units: Array[IntervalUnit], fields: Array[String]): CalendarInterval = {
278+
def fromUnitStrings(units: Array[String], fields: Array[String]): CalendarInterval = {
291279
assert(units.length == fields.length)
292280
var months: Int = 0
293281
var days: Int = 0
@@ -296,26 +284,26 @@ object IntervalUtils {
296284
while (i < units.length) {
297285
try {
298286
units(i) match {
299-
case YEAR =>
287+
case "year" =>
300288
months = Math.addExact(months, Math.multiplyExact(fields(i).toInt, 12))
301-
case MONTH =>
289+
case "month" =>
302290
months = Math.addExact(months, fields(i).toInt)
303-
case WEEK =>
291+
case "week" =>
304292
days = Math.addExact(days, Math.multiplyExact(fields(i).toInt, 7))
305-
case DAY =>
293+
case "day" =>
306294
days = Math.addExact(days, fields(i).toInt)
307-
case HOUR =>
295+
case "hour" =>
308296
val hoursUs = Math.multiplyExact(fields(i).toLong, MICROS_PER_HOUR)
309297
microseconds = Math.addExact(microseconds, hoursUs)
310-
case MINUTE =>
298+
case "minute" =>
311299
val minutesUs = Math.multiplyExact(fields(i).toLong, MICROS_PER_MINUTE)
312300
microseconds = Math.addExact(microseconds, minutesUs)
313-
case SECOND =>
301+
case "second" =>
314302
microseconds = Math.addExact(microseconds, parseSecondNano(fields(i)))
315-
case MILLISECOND =>
303+
case "millisecond" =>
316304
val millisUs = Math.multiplyExact(fields(i).toLong, MICROS_PER_MILLIS)
317305
microseconds = Math.addExact(microseconds, millisUs)
318-
case MICROSECOND =>
306+
case "microsecond" =>
319307
microseconds = Math.addExact(microseconds, fields(i).toLong)
320308
}
321309
} catch {
@@ -334,7 +322,7 @@ object IntervalUtils {
334322
val alignedStr = if (nanosStr.length < maxNanosLen) {
335323
(nanosStr + "000000000").substring(0, maxNanosLen)
336324
} else nanosStr
337-
val nanos = toLongWithRange(NANOSECOND, alignedStr, 0L, 999999999L)
325+
val nanos = toLongWithRange("nanosecond", alignedStr, 0L, 999999999L)
338326
val micros = nanos / NANOS_PER_MICROS
339327
if (isNegative) -micros else micros
340328
} else {
@@ -348,7 +336,7 @@ object IntervalUtils {
348336
private def parseSecondNano(secondNano: String): Long = {
349337
def parseSeconds(secondsStr: String): Long = {
350338
toLongWithRange(
351-
SECOND,
339+
"second",
352340
secondsStr,
353341
Long.MinValue / MICROS_PER_SECOND,
354342
Long.MaxValue / MICROS_PER_SECOND) * MICROS_PER_SECOND
@@ -651,39 +639,3 @@ object IntervalUtils {
651639
result
652640
}
653641
}
654-
655-
object IntervalUnit extends Enumeration {
656-
type IntervalUnit = Value
657-
658-
val YEAR, MONTH, WEEK, DAY, HOUR, MINUTE, SECOND, MILLISECOND, MICROSECOND, NANOSECOND = Value
659-
660-
def fromString(unit: String): IntervalUnit = unit.toLowerCase(Locale.ROOT) match {
661-
case "year" | "years" => YEAR
662-
case "month" | "months" => MONTH
663-
case "week" | "weeks" => WEEK
664-
case "day" | "days" => DAY
665-
case "hour" | "hours" => HOUR
666-
case "minute" | "minutes" => MINUTE
667-
case "second" | "seconds" => SECOND
668-
case "millisecond" | "milliseconds" => MILLISECOND
669-
case "microsecond" | "microseconds" => MICROSECOND
670-
case u => throw new IllegalArgumentException(s"Invalid interval unit: $u")
671-
}
672-
673-
val isYear: String => Boolean =
674-
y => """y((r)|(rs)|(ear)|(ears))?""".r.pattern.matcher(y).matches()
675-
val isMonth: String => Boolean =
676-
mon => """mon((s)|(th)|(ths))?""".r.pattern.matcher(mon).matches()
677-
val isWeek: String => Boolean = w => """w((eek)|(eeks))?""".r.pattern.matcher(w).matches()
678-
val isDay: String => Boolean = d => """d((ay)|(ays))?""".r.pattern.matcher(d).matches()
679-
val isHour: String => Boolean =
680-
h => """h((r)|(rs)|(our)|(ours))?""".r.pattern.matcher(h).matches()
681-
val isMinute: String => Boolean =
682-
m => """m((in)|(ins)|(inute)|(inutes))?""".r.pattern.matcher(m).matches()
683-
val isSecond: String => Boolean =
684-
s => """s((ec)|(ecs)|(econd)|(econds))?""".r.pattern.matcher(s).matches()
685-
val isMs: String => Boolean =
686-
ms => """(ms((ec)|(ecs)|(econds))?|(millisecond)[s]?)""".r.pattern.matcher(ms).matches()
687-
val isUs: String => Boolean =
688-
us => """(us((ec)|(ecs)|(econds))?|(microsecond)[s]?)""".r.pattern.matcher(us).matches()
689-
}

0 commit comments

Comments
 (0)