embulk-input-dynamodb 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/master.yml +34 -0
- data/.github/workflows/test.yml +30 -0
- data/.scalafmt.conf +5 -0
- data/CHANGELOG.md +49 -0
- data/README.md +204 -54
- data/build.gradle +53 -44
- data/example/config-deprecated.yml +20 -0
- data/example/config-query-as-json.yml +18 -0
- data/example/config-query.yml +22 -0
- data/example/config-scan.yml +18 -0
- data/example/prepare_dynamodb_table.sh +67 -0
- data/gradle/wrapper/gradle-wrapper.jar +0 -0
- data/gradle/wrapper/gradle-wrapper.properties +1 -2
- data/gradlew +67 -48
- data/gradlew.bat +20 -10
- data/{test/run_dynamodb_local.sh → run_dynamodb_local.sh} +2 -1
- data/settings.gradle +1 -0
- data/src/main/scala/org/embulk/input/dynamodb/DeprecatedDynamodbInputPlugin.scala +73 -0
- data/src/main/scala/org/embulk/input/dynamodb/DynamodbInputPlugin.scala +76 -25
- data/src/main/scala/org/embulk/input/dynamodb/PluginTask.scala +132 -32
- data/src/main/scala/org/embulk/input/dynamodb/aws/Aws.scala +44 -0
- data/src/main/scala/org/embulk/input/dynamodb/aws/AwsClientConfiguration.scala +37 -0
- data/src/main/scala/org/embulk/input/dynamodb/aws/AwsCredentials.scala +240 -0
- data/src/main/scala/org/embulk/input/dynamodb/aws/AwsDynamodbConfiguration.scala +35 -0
- data/src/main/scala/org/embulk/input/dynamodb/aws/AwsEndpointConfiguration.scala +79 -0
- data/src/main/scala/org/embulk/input/dynamodb/aws/HttpProxy.scala +61 -0
- data/src/main/scala/org/embulk/input/dynamodb/deprecated/AttributeValueHelper.scala +72 -0
- data/src/main/scala/org/embulk/input/dynamodb/{Filter.scala → deprecated/Filter.scala} +3 -3
- data/src/main/scala/org/embulk/input/dynamodb/{FilterConfig.scala → deprecated/FilterConfig.scala} +13 -13
- data/src/main/scala/org/embulk/input/dynamodb/{ope → deprecated/ope}/AbstractOperation.scala +36 -18
- data/src/main/scala/org/embulk/input/dynamodb/{ope → deprecated/ope}/QueryOperation.scala +21 -13
- data/src/main/scala/org/embulk/input/dynamodb/{ope → deprecated/ope}/ScanOperation.scala +20 -13
- data/src/main/scala/org/embulk/input/dynamodb/item/DynamodbAttributeValue.scala +154 -0
- data/src/main/scala/org/embulk/input/dynamodb/item/DynamodbAttributeValueEmbulkTypeTransformable.scala +245 -0
- data/src/main/scala/org/embulk/input/dynamodb/item/DynamodbAttributeValueType.scala +33 -0
- data/src/main/scala/org/embulk/input/dynamodb/item/DynamodbItemColumnVisitor.scala +50 -0
- data/src/main/scala/org/embulk/input/dynamodb/item/DynamodbItemConsumer.scala +40 -0
- data/src/main/scala/org/embulk/input/dynamodb/item/DynamodbItemIterator.scala +19 -0
- data/src/main/scala/org/embulk/input/dynamodb/item/DynamodbItemReader.scala +64 -0
- data/src/main/scala/org/embulk/input/dynamodb/item/DynamodbItemSchema.scala +135 -0
- data/src/main/scala/org/embulk/input/dynamodb/operation/AbstractDynamodbOperation.scala +169 -0
- data/src/main/scala/org/embulk/input/dynamodb/operation/DynamodbOperationProxy.scala +59 -0
- data/src/main/scala/org/embulk/input/dynamodb/operation/DynamodbQueryOperation.scala +72 -0
- data/src/main/scala/org/embulk/input/dynamodb/operation/DynamodbScanOperation.scala +93 -0
- data/src/main/scala/org/embulk/input/dynamodb/operation/EmbulkDynamodbOperation.scala +15 -0
- data/src/main/scala/org/embulk/input/dynamodb/package.scala +4 -9
- data/src/test/scala/org/embulk/input/dynamodb/AttributeValueHelperTest.scala +245 -101
- data/src/test/scala/org/embulk/input/dynamodb/AwsCredentialsTest.scala +150 -97
- data/src/test/scala/org/embulk/input/dynamodb/DynamodbQueryOperationTest.scala +188 -0
- data/src/test/scala/org/embulk/input/dynamodb/DynamodbScanOperationTest.scala +181 -0
- data/src/test/scala/org/embulk/input/dynamodb/testutil/EmbulkTestBase.scala +85 -0
- metadata +73 -49
- data/circle.yml +0 -16
- data/config/checkstyle/checkstyle.xml +0 -128
- data/config/checkstyle/default.xml +0 -108
- data/src/main/scala/org/embulk/input/dynamodb/AttributeValueHelper.scala +0 -41
- data/src/main/scala/org/embulk/input/dynamodb/AwsCredentials.scala +0 -63
- data/src/main/scala/org/embulk/input/dynamodb/DynamoDBClient.scala +0 -23
- data/src/test/resources/yaml/authMethodBasic.yml +0 -21
- data/src/test/resources/yaml/authMethodBasic_Error.yml +0 -19
- data/src/test/resources/yaml/authMethodEnv.yml +0 -19
- data/src/test/resources/yaml/authMethodProfile.yml +0 -20
- data/src/test/resources/yaml/dynamodb-local-query.yml +0 -25
- data/src/test/resources/yaml/dynamodb-local-scan.yml +0 -23
- data/src/test/resources/yaml/notSetAuthMethod.yml +0 -20
- data/src/test/scala/org/embulk/input/dynamodb/ope/QueryOperationTest.scala +0 -83
- data/src/test/scala/org/embulk/input/dynamodb/ope/ScanOperationTest.scala +0 -83
- data/test/create_table.sh +0 -16
- data/test/put_items.sh +0 -25
@@ -1,28 +1,35 @@
|
|
1
|
-
package org.embulk.input.dynamodb.ope
|
1
|
+
package org.embulk.input.dynamodb.deprecated.ope
|
2
2
|
|
3
3
|
import java.util.{List => JList, Map => JMap}
|
4
4
|
|
5
|
-
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient
|
6
|
-
import com.amazonaws.services.dynamodbv2.model.{
|
5
|
+
import com.amazonaws.services.dynamodbv2.{AmazonDynamoDB, AmazonDynamoDBClient}
|
6
|
+
import com.amazonaws.services.dynamodbv2.model.{
|
7
|
+
AttributeValue,
|
8
|
+
Condition,
|
9
|
+
ScanRequest,
|
10
|
+
ScanResult
|
11
|
+
}
|
7
12
|
import org.embulk.input.dynamodb.PluginTask
|
8
13
|
import org.embulk.spi.{BufferAllocator, PageBuilder, PageOutput, Schema}
|
9
14
|
|
10
|
-
import scala.
|
15
|
+
import scala.jdk.CollectionConverters._
|
16
|
+
|
17
|
+
class ScanOperation(client: AmazonDynamoDB) extends AbstractOperation {
|
11
18
|
|
12
|
-
class ScanOperation(client: AmazonDynamoDBClient) extends AbstractOperation {
|
13
19
|
override def execute(
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
{
|
20
|
+
task: PluginTask,
|
21
|
+
schema: Schema,
|
22
|
+
output: PageOutput
|
23
|
+
): Unit = {
|
18
24
|
val allocator: BufferAllocator = task.getBufferAllocator
|
19
25
|
val pageBuilder: PageBuilder = new PageBuilder(allocator, schema, output)
|
20
26
|
|
21
|
-
val attributes: JList[String] =
|
27
|
+
val attributes: JList[String] =
|
28
|
+
schema.getColumns.asScala.map(_.getName).asJava
|
22
29
|
val scanFilter: JMap[String, Condition] = createFilters(task).asJava
|
23
30
|
var evaluateKey: JMap[String, AttributeValue] = null
|
24
31
|
|
25
|
-
val scanLimit: Long
|
32
|
+
val scanLimit: Long = task.getScanLimit
|
26
33
|
val recordLimit: Long = task.getRecordLimit
|
27
34
|
var recordCount: Long = 0
|
28
35
|
|
@@ -42,9 +49,9 @@ class ScanOperation(client: AmazonDynamoDBClient) extends AbstractOperation {
|
|
42
49
|
val result: ScanResult = client.scan(request)
|
43
50
|
evaluateKey = result.getLastEvaluatedKey
|
44
51
|
|
45
|
-
val items = result.getItems.asScala.map(_.asScala.toMap)
|
52
|
+
val items = result.getItems.asScala.map(_.asScala.toMap).toSeq
|
46
53
|
recordCount += write(pageBuilder, schema, items)
|
47
|
-
} while(evaluateKey != null && (recordLimit == 0 || recordLimit > recordCount))
|
54
|
+
} while (evaluateKey != null && (recordLimit == 0 || recordLimit > recordCount))
|
48
55
|
|
49
56
|
pageBuilder.finish()
|
50
57
|
}
|
@@ -0,0 +1,154 @@
|
|
1
|
+
package org.embulk.input.dynamodb.item
|
2
|
+
|
3
|
+
import java.nio.ByteBuffer
|
4
|
+
import java.nio.charset.StandardCharsets
|
5
|
+
import java.util.{Optional, List => JList, Map => JMap}
|
6
|
+
|
7
|
+
import com.amazonaws.services.dynamodbv2.model.AttributeValue
|
8
|
+
import org.embulk.config.{Config, ConfigDefault, Task => EmbulkTask}
|
9
|
+
|
10
|
+
import scala.jdk.CollectionConverters._
|
11
|
+
import scala.util.chaining._
|
12
|
+
|
13
|
+
/**
|
14
|
+
* TODO: I want to bind directly `org.embulk.config.Config`` to `com.amazonaws.services.dynamodbv2.model.AttributeValue`.
|
15
|
+
* Should I implement `com.amazonaws.transform.JsonUnmarshallerContext`?
|
16
|
+
**/
|
17
|
+
object DynamodbAttributeValue {
|
18
|
+
|
19
|
+
trait Task extends EmbulkTask {
|
20
|
+
|
21
|
+
@Config("S")
|
22
|
+
@ConfigDefault("null")
|
23
|
+
def getS: Optional[String]
|
24
|
+
|
25
|
+
@Config("N")
|
26
|
+
@ConfigDefault("null")
|
27
|
+
def getN: Optional[String]
|
28
|
+
|
29
|
+
@Config("B")
|
30
|
+
@ConfigDefault("null")
|
31
|
+
def getB: Optional[String]
|
32
|
+
|
33
|
+
@Config("SS")
|
34
|
+
@ConfigDefault("null")
|
35
|
+
def getSS: Optional[JList[String]]
|
36
|
+
|
37
|
+
@Config("NS")
|
38
|
+
@ConfigDefault("null")
|
39
|
+
def getNS: Optional[JList[String]]
|
40
|
+
|
41
|
+
@Config("BS")
|
42
|
+
@ConfigDefault("null")
|
43
|
+
def getBS: Optional[JList[String]]
|
44
|
+
|
45
|
+
@Config("M")
|
46
|
+
@ConfigDefault("null")
|
47
|
+
def getM: Optional[JMap[String, DynamodbAttributeValue.Task]]
|
48
|
+
|
49
|
+
@Config("L")
|
50
|
+
@ConfigDefault("null")
|
51
|
+
def getL: Optional[JList[DynamodbAttributeValue.Task]]
|
52
|
+
|
53
|
+
@Config("NULL")
|
54
|
+
@ConfigDefault("null")
|
55
|
+
def getNULL: Optional[Boolean]
|
56
|
+
|
57
|
+
@Config("BOOL")
|
58
|
+
@ConfigDefault("null")
|
59
|
+
def getBOOL: Optional[Boolean]
|
60
|
+
}
|
61
|
+
|
62
|
+
def apply(task: Task): DynamodbAttributeValue = {
|
63
|
+
val original = new AttributeValue()
|
64
|
+
.tap(a => task.getS.ifPresent(v => a.setS(v)))
|
65
|
+
.tap(a => task.getN.ifPresent(v => a.setN(v)))
|
66
|
+
.tap { a =>
|
67
|
+
task.getB.ifPresent { v =>
|
68
|
+
a.setB(ByteBuffer.wrap(v.getBytes(StandardCharsets.UTF_8)))
|
69
|
+
}
|
70
|
+
}
|
71
|
+
.tap(a => task.getSS.ifPresent(v => a.setSS(v)))
|
72
|
+
.tap(a => task.getNS.ifPresent(v => a.setNS(v)))
|
73
|
+
.tap { a =>
|
74
|
+
task.getBS.ifPresent { v =>
|
75
|
+
a.setBS(
|
76
|
+
v.asScala
|
77
|
+
.map(e => ByteBuffer.wrap(e.getBytes(StandardCharsets.UTF_8)))
|
78
|
+
.asJava
|
79
|
+
)
|
80
|
+
}
|
81
|
+
}
|
82
|
+
.tap { a =>
|
83
|
+
task.getM.ifPresent { v =>
|
84
|
+
a.setM(v.asScala.map(x => (x._1, apply(x._2).getOriginal)).asJava)
|
85
|
+
}
|
86
|
+
}
|
87
|
+
.tap(a =>
|
88
|
+
task.getL.ifPresent(v =>
|
89
|
+
a.setL(v.asScala.map(apply).map(_.getOriginal).asJava)
|
90
|
+
)
|
91
|
+
)
|
92
|
+
.tap(a => task.getNULL.ifPresent(v => a.setNULL(v)))
|
93
|
+
.tap(a => task.getBOOL.ifPresent(v => a.setBOOL(v)))
|
94
|
+
new DynamodbAttributeValue(original)
|
95
|
+
}
|
96
|
+
|
97
|
+
def apply(original: AttributeValue): DynamodbAttributeValue = {
|
98
|
+
new DynamodbAttributeValue(original)
|
99
|
+
}
|
100
|
+
|
101
|
+
def apply(item: Map[String, AttributeValue]): DynamodbAttributeValue = {
|
102
|
+
val original = new AttributeValue().withM(item.asJava)
|
103
|
+
new DynamodbAttributeValue(original)
|
104
|
+
}
|
105
|
+
}
|
106
|
+
|
107
|
+
class DynamodbAttributeValue(original: AttributeValue) {
|
108
|
+
|
109
|
+
require(
|
110
|
+
message =
|
111
|
+
s"Invalid AttributeValue: ${original} which must have 1 attribute value.",
|
112
|
+
requirement = {
|
113
|
+
Seq(hasS, hasN, hasB, hasSS, hasNS, hasBS, hasM, hasL, hasNULL, hasBOOL)
|
114
|
+
.count(has => has) == 1
|
115
|
+
}
|
116
|
+
)
|
117
|
+
|
118
|
+
def getOriginal: AttributeValue = original
|
119
|
+
def isNull: Boolean = Option[Boolean](getOriginal.getNULL).getOrElse(false)
|
120
|
+
def hasS: Boolean = Option(getOriginal.getS).isDefined
|
121
|
+
def hasN: Boolean = Option(getOriginal.getN).isDefined
|
122
|
+
def hasB: Boolean = Option(getOriginal.getB).isDefined
|
123
|
+
def hasSS: Boolean = Option(getOriginal.getSS).isDefined
|
124
|
+
def hasNS: Boolean = Option(getOriginal.getNS).isDefined
|
125
|
+
def hasBS: Boolean = Option(getOriginal.getBS).isDefined
|
126
|
+
def hasM: Boolean = Option(getOriginal.getM).isDefined
|
127
|
+
def hasL: Boolean = Option(getOriginal.getL).isDefined
|
128
|
+
def hasNULL: Boolean = Option(getOriginal.getNULL).isDefined
|
129
|
+
def hasBOOL: Boolean = Option(getOriginal.getBOOL).isDefined
|
130
|
+
def getS: String = getOriginal.getS
|
131
|
+
def getN: String = getOriginal.getN
|
132
|
+
def getB: ByteBuffer = getOriginal.getB
|
133
|
+
def getSS: JList[String] = getOriginal.getSS
|
134
|
+
def getNS: JList[String] = getOriginal.getNS
|
135
|
+
def getBS: JList[ByteBuffer] = getOriginal.getBS
|
136
|
+
def getM: JMap[String, AttributeValue] = getOriginal.getM
|
137
|
+
def getL: JList[AttributeValue] = getOriginal.getL
|
138
|
+
def getNULL: Boolean = getOriginal.getNULL
|
139
|
+
def getBOOL: Boolean = getOriginal.getBOOL
|
140
|
+
|
141
|
+
def getType: DynamodbAttributeValueType = {
|
142
|
+
if (hasS) return DynamodbAttributeValueType.S
|
143
|
+
if (hasN) return DynamodbAttributeValueType.N
|
144
|
+
if (hasB) return DynamodbAttributeValueType.B
|
145
|
+
if (hasSS) return DynamodbAttributeValueType.SS
|
146
|
+
if (hasNS) return DynamodbAttributeValueType.NS
|
147
|
+
if (hasBS) return DynamodbAttributeValueType.BS
|
148
|
+
if (hasM) return DynamodbAttributeValueType.M
|
149
|
+
if (hasL) return DynamodbAttributeValueType.L
|
150
|
+
if (hasNULL) return DynamodbAttributeValueType.NULL
|
151
|
+
if (hasBOOL) return DynamodbAttributeValueType.BOOL
|
152
|
+
DynamodbAttributeValueType.UNKNOWN
|
153
|
+
}
|
154
|
+
}
|
@@ -0,0 +1,245 @@
|
|
1
|
+
package org.embulk.input.dynamodb.item
|
2
|
+
|
3
|
+
import java.nio.ByteBuffer
|
4
|
+
import java.nio.charset.StandardCharsets
|
5
|
+
|
6
|
+
import org.embulk.input.dynamodb.logger
|
7
|
+
import org.embulk.spi.time.{Timestamp, TimestampParser}
|
8
|
+
import org.msgpack.value.{Value, ValueFactory}
|
9
|
+
|
10
|
+
import scala.jdk.CollectionConverters._
|
11
|
+
import scala.util.chaining._
|
12
|
+
|
13
|
+
object DynamodbAttributeValueEmbulkTypeTransformable {
|
14
|
+
|
15
|
+
val TRUTHY_STRINGS: Set[String] = Set(
|
16
|
+
"true",
|
17
|
+
"True",
|
18
|
+
"TRUE",
|
19
|
+
"yes",
|
20
|
+
"Yes",
|
21
|
+
"YES",
|
22
|
+
"t",
|
23
|
+
"T",
|
24
|
+
"y",
|
25
|
+
"Y",
|
26
|
+
"on",
|
27
|
+
"On",
|
28
|
+
"ON",
|
29
|
+
"1"
|
30
|
+
)
|
31
|
+
|
32
|
+
val FALSY_STRINGS: Set[String] = Set(
|
33
|
+
"false",
|
34
|
+
"False",
|
35
|
+
"FALSE",
|
36
|
+
"no",
|
37
|
+
"No",
|
38
|
+
"NO",
|
39
|
+
"f",
|
40
|
+
"F",
|
41
|
+
"n",
|
42
|
+
"N",
|
43
|
+
"off",
|
44
|
+
"Off",
|
45
|
+
"OFF",
|
46
|
+
"0"
|
47
|
+
)
|
48
|
+
}
|
49
|
+
|
50
|
+
case class DynamodbAttributeValueEmbulkTypeTransformable(
|
51
|
+
attributeValue: DynamodbAttributeValue,
|
52
|
+
typeEnforcer: Option[DynamodbAttributeValueType] = None,
|
53
|
+
timestampParser: Option[TimestampParser] = None
|
54
|
+
) {
|
55
|
+
|
56
|
+
private def fromAttributeValueType: DynamodbAttributeValueType =
|
57
|
+
typeEnforcer.getOrElse(attributeValue.getType)
|
58
|
+
|
59
|
+
private def convertNAsLongOrDouble(n: String): Either[Long, Double] = {
|
60
|
+
n.toLongOption match {
|
61
|
+
case Some(l) => Left(l)
|
62
|
+
case None => Right(n.toDouble)
|
63
|
+
}
|
64
|
+
}
|
65
|
+
|
66
|
+
private def convertBAsString(b: ByteBuffer): String = {
|
67
|
+
new String(b.array(), StandardCharsets.UTF_8)
|
68
|
+
}
|
69
|
+
|
70
|
+
private def hasAttributeValueType: Boolean = {
|
71
|
+
fromAttributeValueType.equals(attributeValue.getType)
|
72
|
+
}
|
73
|
+
|
74
|
+
def asMessagePack: Option[Value] = {
|
75
|
+
if (!hasAttributeValueType) return None
|
76
|
+
if (attributeValue.isNull) return None
|
77
|
+
|
78
|
+
Option(fromAttributeValueType match {
|
79
|
+
case DynamodbAttributeValueType.S =>
|
80
|
+
ValueFactory.newString(attributeValue.getS)
|
81
|
+
case DynamodbAttributeValueType.N =>
|
82
|
+
convertNAsLongOrDouble(attributeValue.getN) match {
|
83
|
+
case Left(v) => ValueFactory.newInteger(v)
|
84
|
+
case Right(v) => ValueFactory.newFloat(v)
|
85
|
+
}
|
86
|
+
case DynamodbAttributeValueType.B =>
|
87
|
+
ValueFactory.newBinary(attributeValue.getB.array())
|
88
|
+
case DynamodbAttributeValueType.SS =>
|
89
|
+
ValueFactory.newArray(
|
90
|
+
attributeValue.getSS.asScala.map(ValueFactory.newString).asJava
|
91
|
+
)
|
92
|
+
case DynamodbAttributeValueType.NS =>
|
93
|
+
ValueFactory.newArray(
|
94
|
+
attributeValue.getNS.asScala
|
95
|
+
.map(convertNAsLongOrDouble(_) match {
|
96
|
+
case Left(v) => ValueFactory.newInteger(v)
|
97
|
+
case Right(v) => ValueFactory.newFloat(v)
|
98
|
+
})
|
99
|
+
.asJava
|
100
|
+
)
|
101
|
+
case DynamodbAttributeValueType.BS =>
|
102
|
+
ValueFactory.newArray(
|
103
|
+
attributeValue.getBS.asScala
|
104
|
+
.map(b => ValueFactory.newBinary(b.array()))
|
105
|
+
.asJava
|
106
|
+
)
|
107
|
+
case DynamodbAttributeValueType.M =>
|
108
|
+
ValueFactory
|
109
|
+
.newMapBuilder()
|
110
|
+
.tap { builder =>
|
111
|
+
attributeValue.getM.asScala.foreach { x =>
|
112
|
+
builder.put(
|
113
|
+
ValueFactory.newString(x._1),
|
114
|
+
DynamodbAttributeValueEmbulkTypeTransformable(
|
115
|
+
DynamodbAttributeValue(x._2)
|
116
|
+
).asMessagePack.getOrElse(ValueFactory.newNil())
|
117
|
+
)
|
118
|
+
}
|
119
|
+
}
|
120
|
+
.build()
|
121
|
+
case DynamodbAttributeValueType.L =>
|
122
|
+
ValueFactory.newArray(
|
123
|
+
attributeValue.getL.asScala.map { av =>
|
124
|
+
DynamodbAttributeValueEmbulkTypeTransformable(
|
125
|
+
DynamodbAttributeValue(av)
|
126
|
+
).asMessagePack.getOrElse(ValueFactory.newNil())
|
127
|
+
}.asJava
|
128
|
+
)
|
129
|
+
case DynamodbAttributeValueType.BOOL =>
|
130
|
+
ValueFactory.newBoolean(attributeValue.getBOOL)
|
131
|
+
case _ =>
|
132
|
+
logger.warn(
|
133
|
+
s"Unsupported AttributeValue: ${attributeValue.getOriginal.toString}"
|
134
|
+
)
|
135
|
+
return None
|
136
|
+
})
|
137
|
+
}
|
138
|
+
|
139
|
+
def asBoolean: Option[Boolean] = {
|
140
|
+
if (!hasAttributeValueType) return None
|
141
|
+
if (attributeValue.isNull) return None
|
142
|
+
|
143
|
+
Option(fromAttributeValueType match {
|
144
|
+
case DynamodbAttributeValueType.S =>
|
145
|
+
if (DynamodbAttributeValueEmbulkTypeTransformable.TRUTHY_STRINGS
|
146
|
+
.contains(attributeValue.getS)) true
|
147
|
+
else if (DynamodbAttributeValueEmbulkTypeTransformable.FALSY_STRINGS
|
148
|
+
.contains(attributeValue.getS)) false
|
149
|
+
else return None
|
150
|
+
case DynamodbAttributeValueType.N =>
|
151
|
+
convertNAsLongOrDouble(attributeValue.getN) match {
|
152
|
+
case Left(v) => v > 0
|
153
|
+
case Right(v) => v > 0.0
|
154
|
+
}
|
155
|
+
case DynamodbAttributeValueType.B =>
|
156
|
+
val s = convertBAsString(attributeValue.getB)
|
157
|
+
if (DynamodbAttributeValueEmbulkTypeTransformable.TRUTHY_STRINGS
|
158
|
+
.contains(s))
|
159
|
+
true
|
160
|
+
else if (DynamodbAttributeValueEmbulkTypeTransformable.FALSY_STRINGS
|
161
|
+
.contains(s)) false
|
162
|
+
else return None
|
163
|
+
case DynamodbAttributeValueType.BOOL => attributeValue.getBOOL
|
164
|
+
case unsupported =>
|
165
|
+
logger.debug(s"cannot convert ${unsupported.toString} as boolean.")
|
166
|
+
return None
|
167
|
+
})
|
168
|
+
}
|
169
|
+
|
170
|
+
def asLong: Option[Long] = {
|
171
|
+
if (!hasAttributeValueType) return None
|
172
|
+
if (attributeValue.isNull) return None
|
173
|
+
|
174
|
+
Option(fromAttributeValueType match {
|
175
|
+
case DynamodbAttributeValueType.S =>
|
176
|
+
convertNAsLongOrDouble(attributeValue.getS) match {
|
177
|
+
case Left(v) => v
|
178
|
+
case Right(v) => v.toLong
|
179
|
+
}
|
180
|
+
case DynamodbAttributeValueType.N =>
|
181
|
+
convertNAsLongOrDouble(attributeValue.getN) match {
|
182
|
+
case Left(v) => v
|
183
|
+
case Right(v) => v.toLong
|
184
|
+
}
|
185
|
+
case DynamodbAttributeValueType.B =>
|
186
|
+
convertNAsLongOrDouble(convertBAsString(attributeValue.getB)) match {
|
187
|
+
case Left(v) => v
|
188
|
+
case Right(v) => v.toLong
|
189
|
+
}
|
190
|
+
case DynamodbAttributeValueType.BOOL =>
|
191
|
+
if (attributeValue.getBOOL) 1L
|
192
|
+
else 0L
|
193
|
+
case unsupported =>
|
194
|
+
logger.debug(s"cannot convert ${unsupported.toString} as long.")
|
195
|
+
return None
|
196
|
+
})
|
197
|
+
}
|
198
|
+
|
199
|
+
def asDouble: Option[Double] = {
|
200
|
+
if (!hasAttributeValueType) return None
|
201
|
+
if (attributeValue.isNull) return None
|
202
|
+
|
203
|
+
fromAttributeValueType match {
|
204
|
+
case DynamodbAttributeValueType.S => attributeValue.getS.toDoubleOption
|
205
|
+
case DynamodbAttributeValueType.N => attributeValue.getN.toDoubleOption
|
206
|
+
case DynamodbAttributeValueType.B =>
|
207
|
+
convertBAsString(attributeValue.getB).toDoubleOption
|
208
|
+
case DynamodbAttributeValueType.BOOL =>
|
209
|
+
Option(
|
210
|
+
if (attributeValue.getBOOL) 1.0d
|
211
|
+
else 0.0d
|
212
|
+
)
|
213
|
+
case unsupported =>
|
214
|
+
logger.debug(s"cannot convert ${unsupported.toString} as double.")
|
215
|
+
None
|
216
|
+
}
|
217
|
+
}
|
218
|
+
|
219
|
+
def asString: Option[String] = {
|
220
|
+
if (!hasAttributeValueType) return None
|
221
|
+
if (attributeValue.isNull) return None
|
222
|
+
|
223
|
+
Option(fromAttributeValueType match {
|
224
|
+
case DynamodbAttributeValueType.S => attributeValue.getS
|
225
|
+
case DynamodbAttributeValueType.N => attributeValue.getN
|
226
|
+
case DynamodbAttributeValueType.B => convertBAsString(attributeValue.getB)
|
227
|
+
case DynamodbAttributeValueType.SS => asMessagePack.map(_.toJson).get
|
228
|
+
case DynamodbAttributeValueType.NS => asMessagePack.map(_.toJson).get
|
229
|
+
case DynamodbAttributeValueType.BS => asMessagePack.map(_.toJson).get
|
230
|
+
case DynamodbAttributeValueType.M => asMessagePack.map(_.toJson).get
|
231
|
+
case DynamodbAttributeValueType.L => asMessagePack.map(_.toJson).get
|
232
|
+
case DynamodbAttributeValueType.BOOL => attributeValue.getBOOL.toString
|
233
|
+
case _ =>
|
234
|
+
logger.warn(
|
235
|
+
s"Unsupported AttributeValue: ${attributeValue.getOriginal.toString}"
|
236
|
+
)
|
237
|
+
return None
|
238
|
+
})
|
239
|
+
}
|
240
|
+
|
241
|
+
def asTimestamp: Option[Timestamp] = {
|
242
|
+
timestampParser.flatMap(p => asString.map(p.parse))
|
243
|
+
}
|
244
|
+
|
245
|
+
}
|