diff --git a/dataset/copy-csv-dos-style-newline/copy_csv.cypher b/dataset/copy-csv-dos-style-newline/copy_csv.cypher deleted file mode 100644 index acc0b5a65a..0000000000 --- a/dataset/copy-csv-dos-style-newline/copy_csv.cypher +++ /dev/null @@ -1 +0,0 @@ -COPY person FROM "dataset/copy-csv-dos-style-newline/vPerson.csv" \ No newline at end of file diff --git a/dataset/copy-csv-empty-lists-test/copy_csv.cypher b/dataset/copy-csv-empty-lists-test/copy_csv.cypher deleted file mode 100644 index b46af92d3b..0000000000 --- a/dataset/copy-csv-empty-lists-test/copy_csv.cypher +++ /dev/null @@ -1 +0,0 @@ -COPY person FROM "dataset/copy-csv-empty-lists-test/vPerson.csv" \ No newline at end of file diff --git a/dataset/copy-csv-fault-tests/long-string/copy_csv.cypher b/dataset/copy-csv-fault-tests/long-string/copy_csv.cypher deleted file mode 100644 index 9d3442544d..0000000000 --- a/dataset/copy-csv-fault-tests/long-string/copy_csv.cypher +++ /dev/null @@ -1 +0,0 @@ -COPY person FROM "dataset/copy-csv-fault-tests/long-string/vPerson.csv" \ No newline at end of file diff --git a/dataset/copy-csv-fault-tests/rel-table-multiplicity-violation/copy_csv.cypher b/dataset/copy-csv-fault-tests/rel-table-multiplicity-violation/copy_csv.cypher deleted file mode 100644 index ee6dfcea30..0000000000 --- a/dataset/copy-csv-fault-tests/rel-table-multiplicity-violation/copy_csv.cypher +++ /dev/null @@ -1 +0,0 @@ -COPY person FROM "dataset/copy-csv-fault-tests/rel-table-multiplicity-violation/vPerson.csv" \ No newline at end of file diff --git a/dataset/copy-csv-node-property-test/copy_csv.cypher b/dataset/copy-csv-node-property-test/copy_csv.cypher deleted file mode 100644 index 886eae721f..0000000000 --- a/dataset/copy-csv-node-property-test/copy_csv.cypher +++ /dev/null @@ -1 +0,0 @@ -COPY person FROM "dataset/copy-csv-node-property-test/vPerson.csv" \ No newline at end of file diff --git a/dataset/copy-csv-special-char-test/copy_csv.cypher b/dataset/copy-csv-special-char-test/copy_csv.cypher deleted file mode 100644 index 7935832123..0000000000 --- a/dataset/copy-csv-special-char-test/copy_csv.cypher +++ /dev/null @@ -1,3 +0,0 @@ -COPY person FROM "dataset/copy-csv-special-char-test/vPerson.csv" (ESCAPE = "#", QUOTE = "-", DELIM="|"); -COPY organisation FROM "dataset/copy-csv-special-char-test/vOrganisation.csv" (ESCAPE = "#", QUOTE = "=", DELIM=","); -COPY workAt FROM "dataset/copy-csv-special-char-test/eWorkAt.csv" (ESCAPE = "#", QUOTE = "=", DELIM="|"); \ No newline at end of file diff --git a/dataset/copy-dos-style-newline/copy.cypher b/dataset/copy-dos-style-newline/copy.cypher new file mode 100644 index 0000000000..e4390d9030 --- /dev/null +++ b/dataset/copy-dos-style-newline/copy.cypher @@ -0,0 +1 @@ +COPY person FROM "dataset/copy-dos-style-newline/vPerson.csv" diff --git a/dataset/copy-csv-dos-style-newline/schema.cypher b/dataset/copy-dos-style-newline/schema.cypher similarity index 100% rename from dataset/copy-csv-dos-style-newline/schema.cypher rename to dataset/copy-dos-style-newline/schema.cypher diff --git a/dataset/copy-csv-dos-style-newline/vPerson.csv b/dataset/copy-dos-style-newline/vPerson.csv similarity index 100% rename from dataset/copy-csv-dos-style-newline/vPerson.csv rename to dataset/copy-dos-style-newline/vPerson.csv diff --git a/dataset/copy-empty-lists-test/copy.cypher b/dataset/copy-empty-lists-test/copy.cypher new file mode 100644 index 0000000000..195eeac14c --- /dev/null +++ b/dataset/copy-empty-lists-test/copy.cypher @@ -0,0 +1 @@ +COPY person FROM "dataset/copy-empty-lists-test/vPerson.csv" diff --git a/dataset/copy-csv-empty-lists-test/schema.cypher b/dataset/copy-empty-lists-test/schema.cypher similarity index 100% rename from dataset/copy-csv-empty-lists-test/schema.cypher rename to dataset/copy-empty-lists-test/schema.cypher diff --git a/dataset/copy-csv-empty-lists-test/vPerson.csv b/dataset/copy-empty-lists-test/vPerson.csv similarity index 100% rename from dataset/copy-csv-empty-lists-test/vPerson.csv rename to dataset/copy-empty-lists-test/vPerson.csv diff --git a/dataset/copy-csv-fault-tests/duplicate-ids/copy_csv.cypher b/dataset/copy-fault-tests/duplicate-ids/copy.cypher similarity index 100% rename from dataset/copy-csv-fault-tests/duplicate-ids/copy_csv.cypher rename to dataset/copy-fault-tests/duplicate-ids/copy.cypher diff --git a/dataset/copy-csv-fault-tests/duplicate-ids/schema.cypher b/dataset/copy-fault-tests/duplicate-ids/schema.cypher similarity index 100% rename from dataset/copy-csv-fault-tests/duplicate-ids/schema.cypher rename to dataset/copy-fault-tests/duplicate-ids/schema.cypher diff --git a/dataset/copy-csv-fault-tests/duplicate-ids/vPerson.csv b/dataset/copy-fault-tests/duplicate-ids/vPerson.csv similarity index 100% rename from dataset/copy-csv-fault-tests/duplicate-ids/vPerson.csv rename to dataset/copy-fault-tests/duplicate-ids/vPerson.csv diff --git a/dataset/copy-fault-tests/long-string/copy.cypher b/dataset/copy-fault-tests/long-string/copy.cypher new file mode 100644 index 0000000000..6589fd6f2a --- /dev/null +++ b/dataset/copy-fault-tests/long-string/copy.cypher @@ -0,0 +1 @@ +COPY person FROM "dataset/copy-fault-tests/long-string/vPerson.csv" diff --git a/dataset/copy-csv-fault-tests/long-string/readme.txt b/dataset/copy-fault-tests/long-string/readme.txt similarity index 100% rename from dataset/copy-csv-fault-tests/long-string/readme.txt rename to dataset/copy-fault-tests/long-string/readme.txt diff --git a/dataset/copy-csv-fault-tests/long-string/schema.cypher b/dataset/copy-fault-tests/long-string/schema.cypher similarity index 100% rename from dataset/copy-csv-fault-tests/long-string/schema.cypher rename to dataset/copy-fault-tests/long-string/schema.cypher diff --git a/dataset/copy-csv-fault-tests/long-string/vPerson.csv b/dataset/copy-fault-tests/long-string/vPerson.csv similarity index 100% rename from dataset/copy-csv-fault-tests/long-string/vPerson.csv rename to dataset/copy-fault-tests/long-string/vPerson.csv diff --git a/dataset/copy-fault-tests/rel-table-multiplicity-violation/copy.cypher b/dataset/copy-fault-tests/rel-table-multiplicity-violation/copy.cypher new file mode 100644 index 0000000000..d5d80897f4 --- /dev/null +++ b/dataset/copy-fault-tests/rel-table-multiplicity-violation/copy.cypher @@ -0,0 +1 @@ +COPY person FROM "dataset/copy-fault-tests/rel-table-multiplicity-violation/vPerson.csv" diff --git a/dataset/copy-csv-fault-tests/rel-table-multiplicity-violation/eKnows.csv b/dataset/copy-fault-tests/rel-table-multiplicity-violation/eKnows.csv similarity index 100% rename from dataset/copy-csv-fault-tests/rel-table-multiplicity-violation/eKnows.csv rename to dataset/copy-fault-tests/rel-table-multiplicity-violation/eKnows.csv diff --git a/dataset/copy-csv-fault-tests/rel-table-multiplicity-violation/eMatches.csv b/dataset/copy-fault-tests/rel-table-multiplicity-violation/eMatches.csv similarity index 100% rename from dataset/copy-csv-fault-tests/rel-table-multiplicity-violation/eMatches.csv rename to dataset/copy-fault-tests/rel-table-multiplicity-violation/eMatches.csv diff --git a/dataset/copy-csv-fault-tests/rel-table-multiplicity-violation/eTeaches.csv b/dataset/copy-fault-tests/rel-table-multiplicity-violation/eTeaches.csv similarity index 100% rename from dataset/copy-csv-fault-tests/rel-table-multiplicity-violation/eTeaches.csv rename to dataset/copy-fault-tests/rel-table-multiplicity-violation/eTeaches.csv diff --git a/dataset/copy-csv-fault-tests/rel-table-multiplicity-violation/schema.cypher b/dataset/copy-fault-tests/rel-table-multiplicity-violation/schema.cypher similarity index 100% rename from dataset/copy-csv-fault-tests/rel-table-multiplicity-violation/schema.cypher rename to dataset/copy-fault-tests/rel-table-multiplicity-violation/schema.cypher diff --git a/dataset/copy-csv-fault-tests/rel-table-multiplicity-violation/vPerson.csv b/dataset/copy-fault-tests/rel-table-multiplicity-violation/vPerson.csv similarity index 100% rename from dataset/copy-csv-fault-tests/rel-table-multiplicity-violation/vPerson.csv rename to dataset/copy-fault-tests/rel-table-multiplicity-violation/vPerson.csv diff --git a/dataset/copy-csv-fault-tests/wrong-header/eKnowsMissingColumn.csv b/dataset/copy-fault-tests/wrong-header/eKnowsMissingColumn.csv similarity index 100% rename from dataset/copy-csv-fault-tests/wrong-header/eKnowsMissingColumn.csv rename to dataset/copy-fault-tests/wrong-header/eKnowsMissingColumn.csv diff --git a/dataset/copy-csv-fault-tests/wrong-header/eKnowsWrongColumnName.csv b/dataset/copy-fault-tests/wrong-header/eKnowsWrongColumnName.csv similarity index 100% rename from dataset/copy-csv-fault-tests/wrong-header/eKnowsWrongColumnName.csv rename to dataset/copy-fault-tests/wrong-header/eKnowsWrongColumnName.csv diff --git a/dataset/copy-csv-fault-tests/wrong-header/vPerson.csv b/dataset/copy-fault-tests/wrong-header/vPerson.csv similarity index 100% rename from dataset/copy-csv-fault-tests/wrong-header/vPerson.csv rename to dataset/copy-fault-tests/wrong-header/vPerson.csv diff --git a/dataset/copy-csv-fault-tests/wrong-header/vPersonMissingColumn.csv b/dataset/copy-fault-tests/wrong-header/vPersonMissingColumn.csv similarity index 100% rename from dataset/copy-csv-fault-tests/wrong-header/vPersonMissingColumn.csv rename to dataset/copy-fault-tests/wrong-header/vPersonMissingColumn.csv diff --git a/dataset/copy-csv-fault-tests/wrong-header/vPersonWrongColumnName.csv b/dataset/copy-fault-tests/wrong-header/vPersonWrongColumnName.csv similarity index 100% rename from dataset/copy-csv-fault-tests/wrong-header/vPersonWrongColumnName.csv rename to dataset/copy-fault-tests/wrong-header/vPersonWrongColumnName.csv diff --git a/dataset/copy-node-property-test/copy.cypher b/dataset/copy-node-property-test/copy.cypher new file mode 100644 index 0000000000..3beebf00a6 --- /dev/null +++ b/dataset/copy-node-property-test/copy.cypher @@ -0,0 +1 @@ +COPY person FROM "dataset/copy-node-property-test/vPerson.csv" diff --git a/dataset/copy-csv-node-property-test/readme.txt b/dataset/copy-node-property-test/readme.txt similarity index 100% rename from dataset/copy-csv-node-property-test/readme.txt rename to dataset/copy-node-property-test/readme.txt diff --git a/dataset/copy-csv-node-property-test/schema.cypher b/dataset/copy-node-property-test/schema.cypher similarity index 100% rename from dataset/copy-csv-node-property-test/schema.cypher rename to dataset/copy-node-property-test/schema.cypher diff --git a/dataset/copy-csv-node-property-test/vPerson.csv b/dataset/copy-node-property-test/vPerson.csv similarity index 100% rename from dataset/copy-csv-node-property-test/vPerson.csv rename to dataset/copy-node-property-test/vPerson.csv diff --git a/dataset/copy-special-char-test/copy.cypher b/dataset/copy-special-char-test/copy.cypher new file mode 100644 index 0000000000..39a0e199a8 --- /dev/null +++ b/dataset/copy-special-char-test/copy.cypher @@ -0,0 +1,3 @@ +COPY person FROM "dataset/copy-special-char-test/vPerson.csv" (ESCAPE = "#", QUOTE = "-", DELIM="|"); +COPY organisation FROM "dataset/copy-special-char-test/vOrganisation.csv" (ESCAPE = "#", QUOTE = "=", DELIM=","); +COPY workAt FROM "dataset/copy-special-char-test/eWorkAt.csv" (ESCAPE = "#", QUOTE = "=", DELIM="|"); \ No newline at end of file diff --git a/dataset/copy-csv-special-char-test/eWorkAt.csv b/dataset/copy-special-char-test/eWorkAt.csv similarity index 100% rename from dataset/copy-csv-special-char-test/eWorkAt.csv rename to dataset/copy-special-char-test/eWorkAt.csv diff --git a/dataset/copy-csv-special-char-test/schema.cypher b/dataset/copy-special-char-test/schema.cypher similarity index 100% rename from dataset/copy-csv-special-char-test/schema.cypher rename to dataset/copy-special-char-test/schema.cypher diff --git a/dataset/copy-csv-special-char-test/vOrganisation.csv b/dataset/copy-special-char-test/vOrganisation.csv similarity index 100% rename from dataset/copy-csv-special-char-test/vOrganisation.csv rename to dataset/copy-special-char-test/vOrganisation.csv diff --git a/dataset/copy-csv-special-char-test/vPerson.csv b/dataset/copy-special-char-test/vPerson.csv similarity index 100% rename from dataset/copy-csv-special-char-test/vPerson.csv rename to dataset/copy-special-char-test/vPerson.csv diff --git a/dataset/copy-test/node/arrow/copy_csv.cypher b/dataset/copy-test/node/arrow/copy.cypher similarity index 100% rename from dataset/copy-test/node/arrow/copy_csv.cypher rename to dataset/copy-test/node/arrow/copy.cypher diff --git a/dataset/copy-test/node/csv/copy_csv.cypher b/dataset/copy-test/node/csv/copy.cypher similarity index 100% rename from dataset/copy-test/node/csv/copy_csv.cypher rename to dataset/copy-test/node/csv/copy.cypher diff --git a/dataset/copy-test/node/parquet/copy_csv.cypher b/dataset/copy-test/node/parquet/copy.cypher similarity index 100% rename from dataset/copy-test/node/parquet/copy_csv.cypher rename to dataset/copy-test/node/parquet/copy.cypher diff --git a/dataset/demo-db/copy_csv.cypher b/dataset/demo-db/copy.cypher similarity index 100% rename from dataset/demo-db/copy_csv.cypher rename to dataset/demo-db/copy.cypher diff --git a/dataset/empty-db/copy_csv.cypher b/dataset/empty-db/copy.cypher similarity index 100% rename from dataset/empty-db/copy_csv.cypher rename to dataset/empty-db/copy.cypher diff --git a/dataset/hash-index-test/int64-pk-test/copy_csv.cypher b/dataset/hash-index-test/int64-pk-test/copy.cypher similarity index 100% rename from dataset/hash-index-test/int64-pk-test/copy_csv.cypher rename to dataset/hash-index-test/int64-pk-test/copy.cypher diff --git a/dataset/hash-index-test/string-pk-test/copy_csv.cypher b/dataset/hash-index-test/string-pk-test/copy.cypher similarity index 100% rename from dataset/hash-index-test/string-pk-test/copy_csv.cypher rename to dataset/hash-index-test/string-pk-test/copy.cypher diff --git a/dataset/long-string-pk-tests/copy_csv.cypher b/dataset/long-string-pk-tests/copy.cypher similarity index 100% rename from dataset/long-string-pk-tests/copy_csv.cypher rename to dataset/long-string-pk-tests/copy.cypher diff --git a/dataset/long-string-pk-tests/eKnows.csv b/dataset/long-string-pk-tests/eKnows.csv index 0d4bcea895..cb78ebb26c 100644 --- a/dataset/long-string-pk-tests/eKnows.csv +++ b/dataset/long-string-pk-tests/eKnows.csv @@ -1 +1 @@ -AAAAAAAAAAAAAAAAAAAA,Bob \ No newline at end of file +AAAAAAAAAAAAAAAAAAAA,Bob diff --git a/dataset/node-insertion-deletion-tests/int64-pk/copy_csv.cypher b/dataset/node-insertion-deletion-tests/int64-pk/copy.cypher similarity index 100% rename from dataset/node-insertion-deletion-tests/int64-pk/copy_csv.cypher rename to dataset/node-insertion-deletion-tests/int64-pk/copy.cypher diff --git a/dataset/node-insertion-deletion-tests/string-pk/copy_csv.cypher b/dataset/node-insertion-deletion-tests/string-pk/copy.cypher similarity index 100% rename from dataset/node-insertion-deletion-tests/string-pk/copy_csv.cypher rename to dataset/node-insertion-deletion-tests/string-pk/copy.cypher diff --git a/dataset/non-empty-disk-array-db/copy_csv.cypher b/dataset/non-empty-disk-array-db/copy.cypher similarity index 100% rename from dataset/non-empty-disk-array-db/copy_csv.cypher rename to dataset/non-empty-disk-array-db/copy.cypher diff --git a/dataset/order-by-tests/copy_csv.cypher b/dataset/order-by-tests/copy.cypher similarity index 100% rename from dataset/order-by-tests/copy_csv.cypher rename to dataset/order-by-tests/copy.cypher diff --git a/dataset/primary-key-tests/string-pk-tests/eKnows.csv b/dataset/primary-key-tests/string-pk-tests/eKnows.csv index 3dc2703e4a..35cfb5915a 100644 --- a/dataset/primary-key-tests/string-pk-tests/eKnows.csv +++ b/dataset/primary-key-tests/string-pk-tests/eKnows.csv @@ -1 +1 @@ -Alice,Bob \ No newline at end of file +Alice,Bob diff --git a/dataset/read-list-tests/2-bytes-per-edge/copy_csv.cypher b/dataset/read-list-tests/2-bytes-per-edge/copy.cypher similarity index 100% rename from dataset/read-list-tests/2-bytes-per-edge/copy_csv.cypher rename to dataset/read-list-tests/2-bytes-per-edge/copy.cypher diff --git a/dataset/read-list-tests/3-bytes-per-edge/copy_csv.cypher b/dataset/read-list-tests/3-bytes-per-edge/copy.cypher similarity index 100% rename from dataset/read-list-tests/3-bytes-per-edge/copy_csv.cypher rename to dataset/read-list-tests/3-bytes-per-edge/copy.cypher diff --git a/dataset/read-list-tests/4-bytes-per-edge/copy_csv.cypher b/dataset/read-list-tests/4-bytes-per-edge/copy.cypher similarity index 100% rename from dataset/read-list-tests/4-bytes-per-edge/copy_csv.cypher rename to dataset/read-list-tests/4-bytes-per-edge/copy.cypher diff --git a/dataset/read-list-tests/5-bytes-per-edge/copy_csv.cypher b/dataset/read-list-tests/5-bytes-per-edge/copy.cypher similarity index 100% rename from dataset/read-list-tests/5-bytes-per-edge/copy_csv.cypher rename to dataset/read-list-tests/5-bytes-per-edge/copy.cypher diff --git a/dataset/read-list-tests/large-list-sub-query-tests/copy_csv.cypher b/dataset/read-list-tests/large-list-sub-query-tests/copy.cypher similarity index 100% rename from dataset/read-list-tests/large-list-sub-query-tests/copy_csv.cypher rename to dataset/read-list-tests/large-list-sub-query-tests/copy.cypher diff --git a/dataset/rel-insertion-tests/copy_csv.cypher b/dataset/rel-insertion-tests/copy.cypher similarity index 100% rename from dataset/rel-insertion-tests/copy_csv.cypher rename to dataset/rel-insertion-tests/copy.cypher diff --git a/dataset/rel-insertion-tests/eKnows.csv b/dataset/rel-insertion-tests/eKnows.csv index 949ea394a0..385c33e35b 100644 --- a/dataset/rel-insertion-tests/eKnows.csv +++ b/dataset/rel-insertion-tests/eKnows.csv @@ -1,2551 +1,2551 @@ -person,0,person,1,0,"300030003000",["300030003000"] -person,0,person,2,3,"2999",["2999"] -person,0,person,3,6,"299829982998",["299829982998"] -person,0,person,4,9,"2997",["2997"] -person,0,person,5,12,"299629962996",["299629962996"] -person,0,person,6,15,"2995",["2995"] -person,0,person,7,18,"299429942994",["299429942994"] -person,0,person,8,21,"2993",["2993"] -person,0,person,9,24,"299229922992",["299229922992"] -person,0,person,10,27,"2991",["2991"] -person,0,person,11,30,"299029902990",["299029902990"] -person,0,person,12,33,"2989",["2989"] -person,0,person,13,36,"298829882988",["298829882988"] -person,0,person,14,39,"2987",["2987"] -person,0,person,15,42,"298629862986",["298629862986"] -person,0,person,16,45,"2985",["2985"] -person,0,person,17,48,"298429842984",["298429842984"] -person,0,person,18,51,"2983",["2983"] -person,0,person,19,54,"298229822982",["298229822982"] -person,0,person,20,57,"2981",["2981"] -person,0,person,21,60,"298029802980",["298029802980"] -person,0,person,22,63,"2979",["2979"] -person,0,person,23,66,"297829782978",["297829782978"] -person,0,person,24,69,"2977",["2977"] -person,0,person,25,72,"297629762976",["297629762976"] -person,0,person,26,75,"2975",["2975"] -person,0,person,27,78,"297429742974",["297429742974"] -person,0,person,28,81,"2973",["2973"] -person,0,person,29,84,"297229722972",["297229722972"] -person,0,person,30,87,"2971",["2971"] -person,0,person,31,90,"297029702970",["297029702970"] -person,0,person,32,93,"2969",["2969"] -person,0,person,33,96,"296829682968",["296829682968"] -person,0,person,34,99,"2967",["2967"] -person,0,person,35,102,"296629662966",["296629662966"] -person,0,person,36,105,"2965",["2965"] -person,0,person,37,108,"296429642964",["296429642964"] -person,0,person,38,111,"2963",["2963"] -person,0,person,39,114,"296229622962",["296229622962"] -person,0,person,40,117,"2961",["2961"] -person,0,person,41,120,"296029602960",["296029602960"] -person,0,person,42,123,"2959",["2959"] -person,0,person,43,126,"295829582958",["295829582958"] -person,0,person,44,129,"2957",["2957"] -person,0,person,45,132,"295629562956",["295629562956"] -person,0,person,46,135,"2955",["2955"] -person,0,person,47,138,"295429542954",["295429542954"] -person,0,person,48,141,"2953",["2953"] -person,0,person,49,144,"295229522952",["295229522952"] -person,0,person,50,147,"2951",["2951"] -person,0,person,51,150,"295029502950",["295029502950"] -person,0,person,52,153,"2949",["2949"] -person,0,person,53,156,"294829482948",["294829482948"] -person,0,person,54,159,"2947",["2947"] -person,0,person,55,162,"294629462946",["294629462946"] -person,0,person,56,165,"2945",["2945"] -person,0,person,57,168,"294429442944",["294429442944"] -person,0,person,58,171,"2943",["2943"] -person,0,person,59,174,"294229422942",["294229422942"] -person,0,person,60,177,"2941",["2941"] -person,0,person,61,180,"294029402940",["294029402940"] -person,0,person,62,183,"2939",["2939"] -person,0,person,63,186,"293829382938",["293829382938"] -person,0,person,64,189,"2937",["2937"] -person,0,person,65,192,"293629362936",["293629362936"] -person,0,person,66,195,"2935",["2935"] -person,0,person,67,198,"293429342934",["293429342934"] -person,0,person,68,201,"2933",["2933"] -person,0,person,69,204,"293229322932",["293229322932"] -person,0,person,70,207,"2931",["2931"] -person,0,person,71,210,"293029302930",["293029302930"] -person,0,person,72,213,"2929",["2929"] -person,0,person,73,216,"292829282928",["292829282928"] -person,0,person,74,219,"2927",["2927"] -person,0,person,75,222,"292629262926",["292629262926"] -person,0,person,76,225,"2925",["2925"] -person,0,person,77,228,"292429242924",["292429242924"] -person,0,person,78,231,"2923",["2923"] -person,0,person,79,234,"292229222922",["292229222922"] -person,0,person,80,237,"2921",["2921"] -person,0,person,81,240,"292029202920",["292029202920"] -person,0,person,82,243,"2919",["2919"] -person,0,person,83,246,"291829182918",["291829182918"] -person,0,person,84,249,"2917",["2917"] -person,0,person,85,252,"291629162916",["291629162916"] -person,0,person,86,255,"2915",["2915"] -person,0,person,87,258,"291429142914",["291429142914"] -person,0,person,88,261,"2913",["2913"] -person,0,person,89,264,"291229122912",["291229122912"] -person,0,person,90,267,"2911",["2911"] -person,0,person,91,270,"291029102910",["291029102910"] -person,0,person,92,273,"2909",["2909"] -person,0,person,93,276,"290829082908",["290829082908"] -person,0,person,94,279,"2907",["2907"] -person,0,person,95,282,"290629062906",["290629062906"] -person,0,person,96,285,"2905",["2905"] -person,0,person,97,288,"290429042904",["290429042904"] -person,0,person,98,291,"2903",["2903"] -person,0,person,99,294,"290229022902",["290229022902"] -person,0,person,100,297,"2901",["2901"] -person,0,person,101,300,"290029002900",["290029002900"] -person,0,person,102,303,"2899",["2899"] -person,0,person,103,306,"289828982898",["289828982898"] -person,0,person,104,309,"2897",["2897"] -person,0,person,105,312,"289628962896",["289628962896"] -person,0,person,106,315,"2895",["2895"] -person,0,person,107,318,"289428942894",["289428942894"] -person,0,person,108,321,"2893",["2893"] -person,0,person,109,324,"289228922892",["289228922892"] -person,0,person,110,327,"2891",["2891"] -person,0,person,111,330,"289028902890",["289028902890"] -person,0,person,112,333,"2889",["2889"] -person,0,person,113,336,"288828882888",["288828882888"] -person,0,person,114,339,"2887",["2887"] -person,0,person,115,342,"288628862886",["288628862886"] -person,0,person,116,345,"2885",["2885"] -person,0,person,117,348,"288428842884",["288428842884"] -person,0,person,118,351,"2883",["2883"] -person,0,person,119,354,"288228822882",["288228822882"] -person,0,person,120,357,"2881",["2881"] -person,0,person,121,360,"288028802880",["288028802880"] -person,0,person,122,363,"2879",["2879"] -person,0,person,123,366,"287828782878",["287828782878"] -person,0,person,124,369,"2877",["2877"] -person,0,person,125,372,"287628762876",["287628762876"] -person,0,person,126,375,"2875",["2875"] -person,0,person,127,378,"287428742874",["287428742874"] -person,0,person,128,381,"2873",["2873"] -person,0,person,129,384,"287228722872",["287228722872"] -person,0,person,130,387,"2871",["2871"] -person,0,person,131,390,"287028702870",["287028702870"] -person,0,person,132,393,"2869",["2869"] -person,0,person,133,396,"286828682868",["286828682868"] -person,0,person,134,399,"2867",["2867"] -person,0,person,135,402,"286628662866",["286628662866"] -person,0,person,136,405,"2865",["2865"] -person,0,person,137,408,"286428642864",["286428642864"] -person,0,person,138,411,"2863",["2863"] -person,0,person,139,414,"286228622862",["286228622862"] -person,0,person,140,417,"2861",["2861"] -person,0,person,141,420,"286028602860",["286028602860"] -person,0,person,142,423,"2859",["2859"] -person,0,person,143,426,"285828582858",["285828582858"] -person,0,person,144,429,"2857",["2857"] -person,0,person,145,432,"285628562856",["285628562856"] -person,0,person,146,435,"2855",["2855"] -person,0,person,147,438,"285428542854",["285428542854"] -person,0,person,148,441,"2853",["2853"] -person,0,person,149,444,"285228522852",["285228522852"] -person,0,person,150,447,"2851",["2851"] -person,0,person,151,450,"285028502850",["285028502850"] -person,0,person,152,453,"2849",["2849"] -person,0,person,153,456,"284828482848",["284828482848"] -person,0,person,154,459,"2847",["2847"] -person,0,person,155,462,"284628462846",["284628462846"] -person,0,person,156,465,"2845",["2845"] -person,0,person,157,468,"284428442844",["284428442844"] -person,0,person,158,471,"2843",["2843"] -person,0,person,159,474,"284228422842",["284228422842"] -person,0,person,160,477,"2841",["2841"] -person,0,person,161,480,"284028402840",["284028402840"] -person,0,person,162,483,"2839",["2839"] -person,0,person,163,486,"283828382838",["283828382838"] -person,0,person,164,489,"2837",["2837"] -person,0,person,165,492,"283628362836",["283628362836"] -person,0,person,166,495,"2835",["2835"] -person,0,person,167,498,"283428342834",["283428342834"] -person,0,person,168,501,"2833",["2833"] -person,0,person,169,504,"283228322832",["283228322832"] -person,0,person,170,507,"2831",["2831"] -person,0,person,171,510,"283028302830",["283028302830"] -person,0,person,172,513,"2829",["2829"] -person,0,person,173,516,"282828282828",["282828282828"] -person,0,person,174,519,"2827",["2827"] -person,0,person,175,522,"282628262826",["282628262826"] -person,0,person,176,525,"2825",["2825"] -person,0,person,177,528,"282428242824",["282428242824"] -person,0,person,178,531,"2823",["2823"] -person,0,person,179,534,"282228222822",["282228222822"] -person,0,person,180,537,"2821",["2821"] -person,0,person,181,540,"282028202820",["282028202820"] -person,0,person,182,543,"2819",["2819"] -person,0,person,183,546,"281828182818",["281828182818"] -person,0,person,184,549,"2817",["2817"] -person,0,person,185,552,"281628162816",["281628162816"] -person,0,person,186,555,"2815",["2815"] -person,0,person,187,558,"281428142814",["281428142814"] -person,0,person,188,561,"2813",["2813"] -person,0,person,189,564,"281228122812",["281228122812"] -person,0,person,190,567,"2811",["2811"] -person,0,person,191,570,"281028102810",["281028102810"] -person,0,person,192,573,"2809",["2809"] -person,0,person,193,576,"280828082808",["280828082808"] -person,0,person,194,579,"2807",["2807"] -person,0,person,195,582,"280628062806",["280628062806"] -person,0,person,196,585,"2805",["2805"] -person,0,person,197,588,"280428042804",["280428042804"] -person,0,person,198,591,"2803",["2803"] -person,0,person,199,594,"280228022802",["280228022802"] -person,0,person,200,597,"2801",["2801"] -person,0,person,201,600,"280028002800",["280028002800"] -person,0,person,202,603,"2799",["2799"] -person,0,person,203,606,"279827982798",["279827982798"] -person,0,person,204,609,"2797",["2797"] -person,0,person,205,612,"279627962796",["279627962796"] -person,0,person,206,615,"2795",["2795"] -person,0,person,207,618,"279427942794",["279427942794"] -person,0,person,208,621,"2793",["2793"] -person,0,person,209,624,"279227922792",["279227922792"] -person,0,person,210,627,"2791",["2791"] -person,0,person,211,630,"279027902790",["279027902790"] -person,0,person,212,633,"2789",["2789"] -person,0,person,213,636,"278827882788",["278827882788"] -person,0,person,214,639,"2787",["2787"] -person,0,person,215,642,"278627862786",["278627862786"] -person,0,person,216,645,"2785",["2785"] -person,0,person,217,648,"278427842784",["278427842784"] -person,0,person,218,651,"2783",["2783"] -person,0,person,219,654,"278227822782",["278227822782"] -person,0,person,220,657,"2781",["2781"] -person,0,person,221,660,"278027802780",["278027802780"] -person,0,person,222,663,"2779",["2779"] -person,0,person,223,666,"277827782778",["277827782778"] -person,0,person,224,669,"2777",["2777"] -person,0,person,225,672,"277627762776",["277627762776"] -person,0,person,226,675,"2775",["2775"] -person,0,person,227,678,"277427742774",["277427742774"] -person,0,person,228,681,"2773",["2773"] -person,0,person,229,684,"277227722772",["277227722772"] -person,0,person,230,687,"2771",["2771"] -person,0,person,231,690,"277027702770",["277027702770"] -person,0,person,232,693,"2769",["2769"] -person,0,person,233,696,"276827682768",["276827682768"] -person,0,person,234,699,"2767",["2767"] -person,0,person,235,702,"276627662766",["276627662766"] -person,0,person,236,705,"2765",["2765"] -person,0,person,237,708,"276427642764",["276427642764"] -person,0,person,238,711,"2763",["2763"] -person,0,person,239,714,"276227622762",["276227622762"] -person,0,person,240,717,"2761",["2761"] -person,0,person,241,720,"276027602760",["276027602760"] -person,0,person,242,723,"2759",["2759"] -person,0,person,243,726,"275827582758",["275827582758"] -person,0,person,244,729,"2757",["2757"] -person,0,person,245,732,"275627562756",["275627562756"] -person,0,person,246,735,"2755",["2755"] -person,0,person,247,738,"275427542754",["275427542754"] -person,0,person,248,741,"2753",["2753"] -person,0,person,249,744,"275227522752",["275227522752"] -person,0,person,250,747,"2751",["2751"] -person,0,person,251,750,"275027502750",["275027502750"] -person,0,person,252,753,"2749",["2749"] -person,0,person,253,756,"274827482748",["274827482748"] -person,0,person,254,759,"2747",["2747"] -person,0,person,255,762,"274627462746",["274627462746"] -person,0,person,256,765,"2745",["2745"] -person,0,person,257,768,"274427442744",["274427442744"] -person,0,person,258,771,"2743",["2743"] -person,0,person,259,774,"274227422742",["274227422742"] -person,0,person,260,777,"2741",["2741"] -person,0,person,261,780,"274027402740",["274027402740"] -person,0,person,262,783,"2739",["2739"] -person,0,person,263,786,"273827382738",["273827382738"] -person,0,person,264,789,"2737",["2737"] -person,0,person,265,792,"273627362736",["273627362736"] -person,0,person,266,795,"2735",["2735"] -person,0,person,267,798,"273427342734",["273427342734"] -person,0,person,268,801,"2733",["2733"] -person,0,person,269,804,"273227322732",["273227322732"] -person,0,person,270,807,"2731",["2731"] -person,0,person,271,810,"273027302730",["273027302730"] -person,0,person,272,813,"2729",["2729"] -person,0,person,273,816,"272827282728",["272827282728"] -person,0,person,274,819,"2727",["2727"] -person,0,person,275,822,"272627262726",["272627262726"] -person,0,person,276,825,"2725",["2725"] -person,0,person,277,828,"272427242724",["272427242724"] -person,0,person,278,831,"2723",["2723"] -person,0,person,279,834,"272227222722",["272227222722"] -person,0,person,280,837,"2721",["2721"] -person,0,person,281,840,"272027202720",["272027202720"] -person,0,person,282,843,"2719",["2719"] -person,0,person,283,846,"271827182718",["271827182718"] -person,0,person,284,849,"2717",["2717"] -person,0,person,285,852,"271627162716",["271627162716"] -person,0,person,286,855,"2715",["2715"] -person,0,person,287,858,"271427142714",["271427142714"] -person,0,person,288,861,"2713",["2713"] -person,0,person,289,864,"271227122712",["271227122712"] -person,0,person,290,867,"2711",["2711"] -person,0,person,291,870,"271027102710",["271027102710"] -person,0,person,292,873,"2709",["2709"] -person,0,person,293,876,"270827082708",["270827082708"] -person,0,person,294,879,"2707",["2707"] -person,0,person,295,882,"270627062706",["270627062706"] -person,0,person,296,885,"2705",["2705"] -person,0,person,297,888,"270427042704",["270427042704"] -person,0,person,298,891,"2703",["2703"] -person,0,person,299,894,"270227022702",["270227022702"] -person,0,person,300,897,"2701",["2701"] -person,0,person,301,900,"270027002700",["270027002700"] -person,0,person,302,903,"2699",["2699"] -person,0,person,303,906,"269826982698",["269826982698"] -person,0,person,304,909,"2697",["2697"] -person,0,person,305,912,"269626962696",["269626962696"] -person,0,person,306,915,"2695",["2695"] -person,0,person,307,918,"269426942694",["269426942694"] -person,0,person,308,921,"2693",["2693"] -person,0,person,309,924,"269226922692",["269226922692"] -person,0,person,310,927,"2691",["2691"] -person,0,person,311,930,"269026902690",["269026902690"] -person,0,person,312,933,"2689",["2689"] -person,0,person,313,936,"268826882688",["268826882688"] -person,0,person,314,939,"2687",["2687"] -person,0,person,315,942,"268626862686",["268626862686"] -person,0,person,316,945,"2685",["2685"] -person,0,person,317,948,"268426842684",["268426842684"] -person,0,person,318,951,"2683",["2683"] -person,0,person,319,954,"268226822682",["268226822682"] -person,0,person,320,957,"2681",["2681"] -person,0,person,321,960,"268026802680",["268026802680"] -person,0,person,322,963,"2679",["2679"] -person,0,person,323,966,"267826782678",["267826782678"] -person,0,person,324,969,"2677",["2677"] -person,0,person,325,972,"267626762676",["267626762676"] -person,0,person,326,975,"2675",["2675"] -person,0,person,327,978,"267426742674",["267426742674"] -person,0,person,328,981,"2673",["2673"] -person,0,person,329,984,"267226722672",["267226722672"] -person,0,person,330,987,"2671",["2671"] -person,0,person,331,990,"267026702670",["267026702670"] -person,0,person,332,993,"2669",["2669"] -person,0,person,333,996,"266826682668",["266826682668"] -person,0,person,334,999,"2667",["2667"] -person,0,person,335,1002,"266626662666",["266626662666"] -person,0,person,336,1005,"2665",["2665"] -person,0,person,337,1008,"266426642664",["266426642664"] -person,0,person,338,1011,"2663",["2663"] -person,0,person,339,1014,"266226622662",["266226622662"] -person,0,person,340,1017,"2661",["2661"] -person,0,person,341,1020,"266026602660",["266026602660"] -person,0,person,342,1023,"2659",["2659"] -person,0,person,343,1026,"265826582658",["265826582658"] -person,0,person,344,1029,"2657",["2657"] -person,0,person,345,1032,"265626562656",["265626562656"] -person,0,person,346,1035,"2655",["2655"] -person,0,person,347,1038,"265426542654",["265426542654"] -person,0,person,348,1041,"2653",["2653"] -person,0,person,349,1044,"265226522652",["265226522652"] -person,0,person,350,1047,"2651",["2651"] -person,0,person,351,1050,"265026502650",["265026502650"] -person,0,person,352,1053,"2649",["2649"] -person,0,person,353,1056,"264826482648",["264826482648"] -person,0,person,354,1059,"2647",["2647"] -person,0,person,355,1062,"264626462646",["264626462646"] -person,0,person,356,1065,"2645",["2645"] -person,0,person,357,1068,"264426442644",["264426442644"] -person,0,person,358,1071,"2643",["2643"] -person,0,person,359,1074,"264226422642",["264226422642"] -person,0,person,360,1077,"2641",["2641"] -person,0,person,361,1080,"264026402640",["264026402640"] -person,0,person,362,1083,"2639",["2639"] -person,0,person,363,1086,"263826382638",["263826382638"] -person,0,person,364,1089,"2637",["2637"] -person,0,person,365,1092,"263626362636",["263626362636"] -person,0,person,366,1095,"2635",["2635"] -person,0,person,367,1098,"263426342634",["263426342634"] -person,0,person,368,1101,"2633",["2633"] -person,0,person,369,1104,"263226322632",["263226322632"] -person,0,person,370,1107,"2631",["2631"] -person,0,person,371,1110,"263026302630",["263026302630"] -person,0,person,372,1113,"2629",["2629"] -person,0,person,373,1116,"262826282628",["262826282628"] -person,0,person,374,1119,"2627",["2627"] -person,0,person,375,1122,"262626262626",["262626262626"] -person,0,person,376,1125,"2625",["2625"] -person,0,person,377,1128,"262426242624",["262426242624"] -person,0,person,378,1131,"2623",["2623"] -person,0,person,379,1134,"262226222622",["262226222622"] -person,0,person,380,1137,"2621",["2621"] -person,0,person,381,1140,"262026202620",["262026202620"] -person,0,person,382,1143,"2619",["2619"] -person,0,person,383,1146,"261826182618",["261826182618"] -person,0,person,384,1149,"2617",["2617"] -person,0,person,385,1152,"261626162616",["261626162616"] -person,0,person,386,1155,"2615",["2615"] -person,0,person,387,1158,"261426142614",["261426142614"] -person,0,person,388,1161,"2613",["2613"] -person,0,person,389,1164,"261226122612",["261226122612"] -person,0,person,390,1167,"2611",["2611"] -person,0,person,391,1170,"261026102610",["261026102610"] -person,0,person,392,1173,"2609",["2609"] -person,0,person,393,1176,"260826082608",["260826082608"] -person,0,person,394,1179,"2607",["2607"] -person,0,person,395,1182,"260626062606",["260626062606"] -person,0,person,396,1185,"2605",["2605"] -person,0,person,397,1188,"260426042604",["260426042604"] -person,0,person,398,1191,"2603",["2603"] -person,0,person,399,1194,"260226022602",["260226022602"] -person,0,person,400,1197,"2601",["2601"] -person,0,person,401,1200,"260026002600",["260026002600"] -person,0,person,402,1203,"2599",["2599"] -person,0,person,403,1206,"259825982598",["259825982598"] -person,0,person,404,1209,"2597",["2597"] -person,0,person,405,1212,"259625962596",["259625962596"] -person,0,person,406,1215,"2595",["2595"] -person,0,person,407,1218,"259425942594",["259425942594"] -person,0,person,408,1221,"2593",["2593"] -person,0,person,409,1224,"259225922592",["259225922592"] -person,0,person,410,1227,"2591",["2591"] -person,0,person,411,1230,"259025902590",["259025902590"] -person,0,person,412,1233,"2589",["2589"] -person,0,person,413,1236,"258825882588",["258825882588"] -person,0,person,414,1239,"2587",["2587"] -person,0,person,415,1242,"258625862586",["258625862586"] -person,0,person,416,1245,"2585",["2585"] -person,0,person,417,1248,"258425842584",["258425842584"] -person,0,person,418,1251,"2583",["2583"] -person,0,person,419,1254,"258225822582",["258225822582"] -person,0,person,420,1257,"2581",["2581"] -person,0,person,421,1260,"258025802580",["258025802580"] -person,0,person,422,1263,"2579",["2579"] -person,0,person,423,1266,"257825782578",["257825782578"] -person,0,person,424,1269,"2577",["2577"] -person,0,person,425,1272,"257625762576",["257625762576"] -person,0,person,426,1275,"2575",["2575"] -person,0,person,427,1278,"257425742574",["257425742574"] -person,0,person,428,1281,"2573",["2573"] -person,0,person,429,1284,"257225722572",["257225722572"] -person,0,person,430,1287,"2571",["2571"] -person,0,person,431,1290,"257025702570",["257025702570"] -person,0,person,432,1293,"2569",["2569"] -person,0,person,433,1296,"256825682568",["256825682568"] -person,0,person,434,1299,"2567",["2567"] -person,0,person,435,1302,"256625662566",["256625662566"] -person,0,person,436,1305,"2565",["2565"] -person,0,person,437,1308,"256425642564",["256425642564"] -person,0,person,438,1311,"2563",["2563"] -person,0,person,439,1314,"256225622562",["256225622562"] -person,0,person,440,1317,"2561",["2561"] -person,0,person,441,1320,"256025602560",["256025602560"] -person,0,person,442,1323,"2559",["2559"] -person,0,person,443,1326,"255825582558",["255825582558"] -person,0,person,444,1329,"2557",["2557"] -person,0,person,445,1332,"255625562556",["255625562556"] -person,0,person,446,1335,"2555",["2555"] -person,0,person,447,1338,"255425542554",["255425542554"] -person,0,person,448,1341,"2553",["2553"] -person,0,person,449,1344,"255225522552",["255225522552"] -person,0,person,450,1347,"2551",["2551"] -person,0,person,451,1350,"255025502550",["255025502550"] -person,0,person,452,1353,"2549",["2549"] -person,0,person,453,1356,"254825482548",["254825482548"] -person,0,person,454,1359,"2547",["2547"] -person,0,person,455,1362,"254625462546",["254625462546"] -person,0,person,456,1365,"2545",["2545"] -person,0,person,457,1368,"254425442544",["254425442544"] -person,0,person,458,1371,"2543",["2543"] -person,0,person,459,1374,"254225422542",["254225422542"] -person,0,person,460,1377,"2541",["2541"] -person,0,person,461,1380,"254025402540",["254025402540"] -person,0,person,462,1383,"2539",["2539"] -person,0,person,463,1386,"253825382538",["253825382538"] -person,0,person,464,1389,"2537",["2537"] -person,0,person,465,1392,"253625362536",["253625362536"] -person,0,person,466,1395,"2535",["2535"] -person,0,person,467,1398,"253425342534",["253425342534"] -person,0,person,468,1401,"2533",["2533"] -person,0,person,469,1404,"253225322532",["253225322532"] -person,0,person,470,1407,"2531",["2531"] -person,0,person,471,1410,"253025302530",["253025302530"] -person,0,person,472,1413,"2529",["2529"] -person,0,person,473,1416,"252825282528",["252825282528"] -person,0,person,474,1419,"2527",["2527"] -person,0,person,475,1422,"252625262526",["252625262526"] -person,0,person,476,1425,"2525",["2525"] -person,0,person,477,1428,"252425242524",["252425242524"] -person,0,person,478,1431,"2523",["2523"] -person,0,person,479,1434,"252225222522",["252225222522"] -person,0,person,480,1437,"2521",["2521"] -person,0,person,481,1440,"252025202520",["252025202520"] -person,0,person,482,1443,"2519",["2519"] -person,0,person,483,1446,"251825182518",["251825182518"] -person,0,person,484,1449,"2517",["2517"] -person,0,person,485,1452,"251625162516",["251625162516"] -person,0,person,486,1455,"2515",["2515"] -person,0,person,487,1458,"251425142514",["251425142514"] -person,0,person,488,1461,"2513",["2513"] -person,0,person,489,1464,"251225122512",["251225122512"] -person,0,person,490,1467,"2511",["2511"] -person,0,person,491,1470,"251025102510",["251025102510"] -person,0,person,492,1473,"2509",["2509"] -person,0,person,493,1476,"250825082508",["250825082508"] -person,0,person,494,1479,"2507",["2507"] -person,0,person,495,1482,"250625062506",["250625062506"] -person,0,person,496,1485,"2505",["2505"] -person,0,person,497,1488,"250425042504",["250425042504"] -person,0,person,498,1491,"2503",["2503"] -person,0,person,499,1494,"250225022502",["250225022502"] -person,0,person,500,1497,"2501",["2501"] -person,0,person,501,1500,"250025002500",["250025002500"] -person,0,person,502,1503,"2499",["2499"] -person,0,person,503,1506,"249824982498",["249824982498"] -person,0,person,504,1509,"2497",["2497"] -person,0,person,505,1512,"249624962496",["249624962496"] -person,0,person,506,1515,"2495",["2495"] -person,0,person,507,1518,"249424942494",["249424942494"] -person,0,person,508,1521,"2493",["2493"] -person,0,person,509,1524,"249224922492",["249224922492"] -person,0,person,510,1527,"2491",["2491"] -person,0,person,511,1530,"249024902490",["249024902490"] -person,0,person,512,1533,"2489",["2489"] -person,0,person,513,1536,"248824882488",["248824882488"] -person,0,person,514,1539,"2487",["2487"] -person,0,person,515,1542,"248624862486",["248624862486"] -person,0,person,516,1545,"2485",["2485"] -person,0,person,517,1548,"248424842484",["248424842484"] -person,0,person,518,1551,"2483",["2483"] -person,0,person,519,1554,"248224822482",["248224822482"] -person,0,person,520,1557,"2481",["2481"] -person,0,person,521,1560,"248024802480",["248024802480"] -person,0,person,522,1563,"2479",["2479"] -person,0,person,523,1566,"247824782478",["247824782478"] -person,0,person,524,1569,"2477",["2477"] -person,0,person,525,1572,"247624762476",["247624762476"] -person,0,person,526,1575,"2475",["2475"] -person,0,person,527,1578,"247424742474",["247424742474"] -person,0,person,528,1581,"2473",["2473"] -person,0,person,529,1584,"247224722472",["247224722472"] -person,0,person,530,1587,"2471",["2471"] -person,0,person,531,1590,"247024702470",["247024702470"] -person,0,person,532,1593,"2469",["2469"] -person,0,person,533,1596,"246824682468",["246824682468"] -person,0,person,534,1599,"2467",["2467"] -person,0,person,535,1602,"246624662466",["246624662466"] -person,0,person,536,1605,"2465",["2465"] -person,0,person,537,1608,"246424642464",["246424642464"] -person,0,person,538,1611,"2463",["2463"] -person,0,person,539,1614,"246224622462",["246224622462"] -person,0,person,540,1617,"2461",["2461"] -person,0,person,541,1620,"246024602460",["246024602460"] -person,0,person,542,1623,"2459",["2459"] -person,0,person,543,1626,"245824582458",["245824582458"] -person,0,person,544,1629,"2457",["2457"] -person,0,person,545,1632,"245624562456",["245624562456"] -person,0,person,546,1635,"2455",["2455"] -person,0,person,547,1638,"245424542454",["245424542454"] -person,0,person,548,1641,"2453",["2453"] -person,0,person,549,1644,"245224522452",["245224522452"] -person,0,person,550,1647,"2451",["2451"] -person,0,person,551,1650,"245024502450",["245024502450"] -person,0,person,552,1653,"2449",["2449"] -person,0,person,553,1656,"244824482448",["244824482448"] -person,0,person,554,1659,"2447",["2447"] -person,0,person,555,1662,"244624462446",["244624462446"] -person,0,person,556,1665,"2445",["2445"] -person,0,person,557,1668,"244424442444",["244424442444"] -person,0,person,558,1671,"2443",["2443"] -person,0,person,559,1674,"244224422442",["244224422442"] -person,0,person,560,1677,"2441",["2441"] -person,0,person,561,1680,"244024402440",["244024402440"] -person,0,person,562,1683,"2439",["2439"] -person,0,person,563,1686,"243824382438",["243824382438"] -person,0,person,564,1689,"2437",["2437"] -person,0,person,565,1692,"243624362436",["243624362436"] -person,0,person,566,1695,"2435",["2435"] -person,0,person,567,1698,"243424342434",["243424342434"] -person,0,person,568,1701,"2433",["2433"] -person,0,person,569,1704,"243224322432",["243224322432"] -person,0,person,570,1707,"2431",["2431"] -person,0,person,571,1710,"243024302430",["243024302430"] -person,0,person,572,1713,"2429",["2429"] -person,0,person,573,1716,"242824282428",["242824282428"] -person,0,person,574,1719,"2427",["2427"] -person,0,person,575,1722,"242624262426",["242624262426"] -person,0,person,576,1725,"2425",["2425"] -person,0,person,577,1728,"242424242424",["242424242424"] -person,0,person,578,1731,"2423",["2423"] -person,0,person,579,1734,"242224222422",["242224222422"] -person,0,person,580,1737,"2421",["2421"] -person,0,person,581,1740,"242024202420",["242024202420"] -person,0,person,582,1743,"2419",["2419"] -person,0,person,583,1746,"241824182418",["241824182418"] -person,0,person,584,1749,"2417",["2417"] -person,0,person,585,1752,"241624162416",["241624162416"] -person,0,person,586,1755,"2415",["2415"] -person,0,person,587,1758,"241424142414",["241424142414"] -person,0,person,588,1761,"2413",["2413"] -person,0,person,589,1764,"241224122412",["241224122412"] -person,0,person,590,1767,"2411",["2411"] -person,0,person,591,1770,"241024102410",["241024102410"] -person,0,person,592,1773,"2409",["2409"] -person,0,person,593,1776,"240824082408",["240824082408"] -person,0,person,594,1779,"2407",["2407"] -person,0,person,595,1782,"240624062406",["240624062406"] -person,0,person,596,1785,"2405",["2405"] -person,0,person,597,1788,"240424042404",["240424042404"] -person,0,person,598,1791,"2403",["2403"] -person,0,person,599,1794,"240224022402",["240224022402"] -person,0,person,600,1797,"2401",["2401"] -person,0,person,601,1800,"240024002400",["240024002400"] -person,0,person,602,1803,"2399",["2399"] -person,0,person,603,1806,"239823982398",["239823982398"] -person,0,person,604,1809,"2397",["2397"] -person,0,person,605,1812,"239623962396",["239623962396"] -person,0,person,606,1815,"2395",["2395"] -person,0,person,607,1818,"239423942394",["239423942394"] -person,0,person,608,1821,"2393",["2393"] -person,0,person,609,1824,"239223922392",["239223922392"] -person,0,person,610,1827,"2391",["2391"] -person,0,person,611,1830,"239023902390",["239023902390"] -person,0,person,612,1833,"2389",["2389"] -person,0,person,613,1836,"238823882388",["238823882388"] -person,0,person,614,1839,"2387",["2387"] -person,0,person,615,1842,"238623862386",["238623862386"] -person,0,person,616,1845,"2385",["2385"] -person,0,person,617,1848,"238423842384",["238423842384"] -person,0,person,618,1851,"2383",["2383"] -person,0,person,619,1854,"238223822382",["238223822382"] -person,0,person,620,1857,"2381",["2381"] -person,0,person,621,1860,"238023802380",["238023802380"] -person,0,person,622,1863,"2379",["2379"] -person,0,person,623,1866,"237823782378",["237823782378"] -person,0,person,624,1869,"2377",["2377"] -person,0,person,625,1872,"237623762376",["237623762376"] -person,0,person,626,1875,"2375",["2375"] -person,0,person,627,1878,"237423742374",["237423742374"] -person,0,person,628,1881,"2373",["2373"] -person,0,person,629,1884,"237223722372",["237223722372"] -person,0,person,630,1887,"2371",["2371"] -person,0,person,631,1890,"237023702370",["237023702370"] -person,0,person,632,1893,"2369",["2369"] -person,0,person,633,1896,"236823682368",["236823682368"] -person,0,person,634,1899,"2367",["2367"] -person,0,person,635,1902,"236623662366",["236623662366"] -person,0,person,636,1905,"2365",["2365"] -person,0,person,637,1908,"236423642364",["236423642364"] -person,0,person,638,1911,"2363",["2363"] -person,0,person,639,1914,"236223622362",["236223622362"] -person,0,person,640,1917,"2361",["2361"] -person,0,person,641,1920,"236023602360",["236023602360"] -person,0,person,642,1923,"2359",["2359"] -person,0,person,643,1926,"235823582358",["235823582358"] -person,0,person,644,1929,"2357",["2357"] -person,0,person,645,1932,"235623562356",["235623562356"] -person,0,person,646,1935,"2355",["2355"] -person,0,person,647,1938,"235423542354",["235423542354"] -person,0,person,648,1941,"2353",["2353"] -person,0,person,649,1944,"235223522352",["235223522352"] -person,0,person,650,1947,"2351",["2351"] -person,0,person,651,1950,"235023502350",["235023502350"] -person,0,person,652,1953,"2349",["2349"] -person,0,person,653,1956,"234823482348",["234823482348"] -person,0,person,654,1959,"2347",["2347"] -person,0,person,655,1962,"234623462346",["234623462346"] -person,0,person,656,1965,"2345",["2345"] -person,0,person,657,1968,"234423442344",["234423442344"] -person,0,person,658,1971,"2343",["2343"] -person,0,person,659,1974,"234223422342",["234223422342"] -person,0,person,660,1977,"2341",["2341"] -person,0,person,661,1980,"234023402340",["234023402340"] -person,0,person,662,1983,"2339",["2339"] -person,0,person,663,1986,"233823382338",["233823382338"] -person,0,person,664,1989,"2337",["2337"] -person,0,person,665,1992,"233623362336",["233623362336"] -person,0,person,666,1995,"2335",["2335"] -person,0,person,667,1998,"233423342334",["233423342334"] -person,0,person,668,2001,"2333",["2333"] -person,0,person,669,2004,"233223322332",["233223322332"] -person,0,person,670,2007,"2331",["2331"] -person,0,person,671,2010,"233023302330",["233023302330"] -person,0,person,672,2013,"2329",["2329"] -person,0,person,673,2016,"232823282328",["232823282328"] -person,0,person,674,2019,"2327",["2327"] -person,0,person,675,2022,"232623262326",["232623262326"] -person,0,person,676,2025,"2325",["2325"] -person,0,person,677,2028,"232423242324",["232423242324"] -person,0,person,678,2031,"2323",["2323"] -person,0,person,679,2034,"232223222322",["232223222322"] -person,0,person,680,2037,"2321",["2321"] -person,0,person,681,2040,"232023202320",["232023202320"] -person,0,person,682,2043,"2319",["2319"] -person,0,person,683,2046,"231823182318",["231823182318"] -person,0,person,684,2049,"2317",["2317"] -person,0,person,685,2052,"231623162316",["231623162316"] -person,0,person,686,2055,"2315",["2315"] -person,0,person,687,2058,"231423142314",["231423142314"] -person,0,person,688,2061,"2313",["2313"] -person,0,person,689,2064,"231223122312",["231223122312"] -person,0,person,690,2067,"2311",["2311"] -person,0,person,691,2070,"231023102310",["231023102310"] -person,0,person,692,2073,"2309",["2309"] -person,0,person,693,2076,"230823082308",["230823082308"] -person,0,person,694,2079,"2307",["2307"] -person,0,person,695,2082,"230623062306",["230623062306"] -person,0,person,696,2085,"2305",["2305"] -person,0,person,697,2088,"230423042304",["230423042304"] -person,0,person,698,2091,"2303",["2303"] -person,0,person,699,2094,"230223022302",["230223022302"] -person,0,person,700,2097,"2301",["2301"] -person,0,person,701,2100,"230023002300",["230023002300"] -person,0,person,702,2103,"2299",["2299"] -person,0,person,703,2106,"229822982298",["229822982298"] -person,0,person,704,2109,"2297",["2297"] -person,0,person,705,2112,"229622962296",["229622962296"] -person,0,person,706,2115,"2295",["2295"] -person,0,person,707,2118,"229422942294",["229422942294"] -person,0,person,708,2121,"2293",["2293"] -person,0,person,709,2124,"229222922292",["229222922292"] -person,0,person,710,2127,"2291",["2291"] -person,0,person,711,2130,"229022902290",["229022902290"] -person,0,person,712,2133,"2289",["2289"] -person,0,person,713,2136,"228822882288",["228822882288"] -person,0,person,714,2139,"2287",["2287"] -person,0,person,715,2142,"228622862286",["228622862286"] -person,0,person,716,2145,"2285",["2285"] -person,0,person,717,2148,"228422842284",["228422842284"] -person,0,person,718,2151,"2283",["2283"] -person,0,person,719,2154,"228222822282",["228222822282"] -person,0,person,720,2157,"2281",["2281"] -person,0,person,721,2160,"228022802280",["228022802280"] -person,0,person,722,2163,"2279",["2279"] -person,0,person,723,2166,"227822782278",["227822782278"] -person,0,person,724,2169,"2277",["2277"] -person,0,person,725,2172,"227622762276",["227622762276"] -person,0,person,726,2175,"2275",["2275"] -person,0,person,727,2178,"227422742274",["227422742274"] -person,0,person,728,2181,"2273",["2273"] -person,0,person,729,2184,"227222722272",["227222722272"] -person,0,person,730,2187,"2271",["2271"] -person,0,person,731,2190,"227022702270",["227022702270"] -person,0,person,732,2193,"2269",["2269"] -person,0,person,733,2196,"226822682268",["226822682268"] -person,0,person,734,2199,"2267",["2267"] -person,0,person,735,2202,"226622662266",["226622662266"] -person,0,person,736,2205,"2265",["2265"] -person,0,person,737,2208,"226422642264",["226422642264"] -person,0,person,738,2211,"2263",["2263"] -person,0,person,739,2214,"226222622262",["226222622262"] -person,0,person,740,2217,"2261",["2261"] -person,0,person,741,2220,"226022602260",["226022602260"] -person,0,person,742,2223,"2259",["2259"] -person,0,person,743,2226,"225822582258",["225822582258"] -person,0,person,744,2229,"2257",["2257"] -person,0,person,745,2232,"225622562256",["225622562256"] -person,0,person,746,2235,"2255",["2255"] -person,0,person,747,2238,"225422542254",["225422542254"] -person,0,person,748,2241,"2253",["2253"] -person,0,person,749,2244,"225222522252",["225222522252"] -person,0,person,750,2247,"2251",["2251"] -person,0,person,751,2250,"225022502250",["225022502250"] -person,0,person,752,2253,"2249",["2249"] -person,0,person,753,2256,"224822482248",["224822482248"] -person,0,person,754,2259,"2247",["2247"] -person,0,person,755,2262,"224622462246",["224622462246"] -person,0,person,756,2265,"2245",["2245"] -person,0,person,757,2268,"224422442244",["224422442244"] -person,0,person,758,2271,"2243",["2243"] -person,0,person,759,2274,"224222422242",["224222422242"] -person,0,person,760,2277,"2241",["2241"] -person,0,person,761,2280,"224022402240",["224022402240"] -person,0,person,762,2283,"2239",["2239"] -person,0,person,763,2286,"223822382238",["223822382238"] -person,0,person,764,2289,"2237",["2237"] -person,0,person,765,2292,"223622362236",["223622362236"] -person,0,person,766,2295,"2235",["2235"] -person,0,person,767,2298,"223422342234",["223422342234"] -person,0,person,768,2301,"2233",["2233"] -person,0,person,769,2304,"223222322232",["223222322232"] -person,0,person,770,2307,"2231",["2231"] -person,0,person,771,2310,"223022302230",["223022302230"] -person,0,person,772,2313,"2229",["2229"] -person,0,person,773,2316,"222822282228",["222822282228"] -person,0,person,774,2319,"2227",["2227"] -person,0,person,775,2322,"222622262226",["222622262226"] -person,0,person,776,2325,"2225",["2225"] -person,0,person,777,2328,"222422242224",["222422242224"] -person,0,person,778,2331,"2223",["2223"] -person,0,person,779,2334,"222222222222",["222222222222"] -person,0,person,780,2337,"2221",["2221"] -person,0,person,781,2340,"222022202220",["222022202220"] -person,0,person,782,2343,"2219",["2219"] -person,0,person,783,2346,"221822182218",["221822182218"] -person,0,person,784,2349,"2217",["2217"] -person,0,person,785,2352,"221622162216",["221622162216"] -person,0,person,786,2355,"2215",["2215"] -person,0,person,787,2358,"221422142214",["221422142214"] -person,0,person,788,2361,"2213",["2213"] -person,0,person,789,2364,"221222122212",["221222122212"] -person,0,person,790,2367,"2211",["2211"] -person,0,person,791,2370,"221022102210",["221022102210"] -person,0,person,792,2373,"2209",["2209"] -person,0,person,793,2376,"220822082208",["220822082208"] -person,0,person,794,2379,"2207",["2207"] -person,0,person,795,2382,"220622062206",["220622062206"] -person,0,person,796,2385,"2205",["2205"] -person,0,person,797,2388,"220422042204",["220422042204"] -person,0,person,798,2391,"2203",["2203"] -person,0,person,799,2394,"220222022202",["220222022202"] -person,0,person,800,2397,"2201",["2201"] -person,0,person,801,2400,"220022002200",["220022002200"] -person,0,person,802,2403,"2199",["2199"] -person,0,person,803,2406,"219821982198",["219821982198"] -person,0,person,804,2409,"2197",["2197"] -person,0,person,805,2412,"219621962196",["219621962196"] -person,0,person,806,2415,"2195",["2195"] -person,0,person,807,2418,"219421942194",["219421942194"] -person,0,person,808,2421,"2193",["2193"] -person,0,person,809,2424,"219221922192",["219221922192"] -person,0,person,810,2427,"2191",["2191"] -person,0,person,811,2430,"219021902190",["219021902190"] -person,0,person,812,2433,"2189",["2189"] -person,0,person,813,2436,"218821882188",["218821882188"] -person,0,person,814,2439,"2187",["2187"] -person,0,person,815,2442,"218621862186",["218621862186"] -person,0,person,816,2445,"2185",["2185"] -person,0,person,817,2448,"218421842184",["218421842184"] -person,0,person,818,2451,"2183",["2183"] -person,0,person,819,2454,"218221822182",["218221822182"] -person,0,person,820,2457,"2181",["2181"] -person,0,person,821,2460,"218021802180",["218021802180"] -person,0,person,822,2463,"2179",["2179"] -person,0,person,823,2466,"217821782178",["217821782178"] -person,0,person,824,2469,"2177",["2177"] -person,0,person,825,2472,"217621762176",["217621762176"] -person,0,person,826,2475,"2175",["2175"] -person,0,person,827,2478,"217421742174",["217421742174"] -person,0,person,828,2481,"2173",["2173"] -person,0,person,829,2484,"217221722172",["217221722172"] -person,0,person,830,2487,"2171",["2171"] -person,0,person,831,2490,"217021702170",["217021702170"] -person,0,person,832,2493,"2169",["2169"] -person,0,person,833,2496,"216821682168",["216821682168"] -person,0,person,834,2499,"2167",["2167"] -person,0,person,835,2502,"216621662166",["216621662166"] -person,0,person,836,2505,"2165",["2165"] -person,0,person,837,2508,"216421642164",["216421642164"] -person,0,person,838,2511,"2163",["2163"] -person,0,person,839,2514,"216221622162",["216221622162"] -person,0,person,840,2517,"2161",["2161"] -person,0,person,841,2520,"216021602160",["216021602160"] -person,0,person,842,2523,"2159",["2159"] -person,0,person,843,2526,"215821582158",["215821582158"] -person,0,person,844,2529,"2157",["2157"] -person,0,person,845,2532,"215621562156",["215621562156"] -person,0,person,846,2535,"2155",["2155"] -person,0,person,847,2538,"215421542154",["215421542154"] -person,0,person,848,2541,"2153",["2153"] -person,0,person,849,2544,"215221522152",["215221522152"] -person,0,person,850,2547,"2151",["2151"] -person,0,person,851,2550,"215021502150",["215021502150"] -person,0,person,852,2553,"2149",["2149"] -person,0,person,853,2556,"214821482148",["214821482148"] -person,0,person,854,2559,"2147",["2147"] -person,0,person,855,2562,"214621462146",["214621462146"] -person,0,person,856,2565,"2145",["2145"] -person,0,person,857,2568,"214421442144",["214421442144"] -person,0,person,858,2571,"2143",["2143"] -person,0,person,859,2574,"214221422142",["214221422142"] -person,0,person,860,2577,"2141",["2141"] -person,0,person,861,2580,"214021402140",["214021402140"] -person,0,person,862,2583,"2139",["2139"] -person,0,person,863,2586,"213821382138",["213821382138"] -person,0,person,864,2589,"2137",["2137"] -person,0,person,865,2592,"213621362136",["213621362136"] -person,0,person,866,2595,"2135",["2135"] -person,0,person,867,2598,"213421342134",["213421342134"] -person,0,person,868,2601,"2133",["2133"] -person,0,person,869,2604,"213221322132",["213221322132"] -person,0,person,870,2607,"2131",["2131"] -person,0,person,871,2610,"213021302130",["213021302130"] -person,0,person,872,2613,"2129",["2129"] -person,0,person,873,2616,"212821282128",["212821282128"] -person,0,person,874,2619,"2127",["2127"] -person,0,person,875,2622,"212621262126",["212621262126"] -person,0,person,876,2625,"2125",["2125"] -person,0,person,877,2628,"212421242124",["212421242124"] -person,0,person,878,2631,"2123",["2123"] -person,0,person,879,2634,"212221222122",["212221222122"] -person,0,person,880,2637,"2121",["2121"] -person,0,person,881,2640,"212021202120",["212021202120"] -person,0,person,882,2643,"2119",["2119"] -person,0,person,883,2646,"211821182118",["211821182118"] -person,0,person,884,2649,"2117",["2117"] -person,0,person,885,2652,"211621162116",["211621162116"] -person,0,person,886,2655,"2115",["2115"] -person,0,person,887,2658,"211421142114",["211421142114"] -person,0,person,888,2661,"2113",["2113"] -person,0,person,889,2664,"211221122112",["211221122112"] -person,0,person,890,2667,"2111",["2111"] -person,0,person,891,2670,"211021102110",["211021102110"] -person,0,person,892,2673,"2109",["2109"] -person,0,person,893,2676,"210821082108",["210821082108"] -person,0,person,894,2679,"2107",["2107"] -person,0,person,895,2682,"210621062106",["210621062106"] -person,0,person,896,2685,"2105",["2105"] -person,0,person,897,2688,"210421042104",["210421042104"] -person,0,person,898,2691,"2103",["2103"] -person,0,person,899,2694,"210221022102",["210221022102"] -person,0,person,900,2697,"2101",["2101"] -person,0,person,901,2700,"210021002100",["210021002100"] -person,0,person,902,2703,"2099",["2099"] -person,0,person,903,2706,"209820982098",["209820982098"] -person,0,person,904,2709,"2097",["2097"] -person,0,person,905,2712,"209620962096",["209620962096"] -person,0,person,906,2715,"2095",["2095"] -person,0,person,907,2718,"209420942094",["209420942094"] -person,0,person,908,2721,"2093",["2093"] -person,0,person,909,2724,"209220922092",["209220922092"] -person,0,person,910,2727,"2091",["2091"] -person,0,person,911,2730,"209020902090",["209020902090"] -person,0,person,912,2733,"2089",["2089"] -person,0,person,913,2736,"208820882088",["208820882088"] -person,0,person,914,2739,"2087",["2087"] -person,0,person,915,2742,"208620862086",["208620862086"] -person,0,person,916,2745,"2085",["2085"] -person,0,person,917,2748,"208420842084",["208420842084"] -person,0,person,918,2751,"2083",["2083"] -person,0,person,919,2754,"208220822082",["208220822082"] -person,0,person,920,2757,"2081",["2081"] -person,0,person,921,2760,"208020802080",["208020802080"] -person,0,person,922,2763,"2079",["2079"] -person,0,person,923,2766,"207820782078",["207820782078"] -person,0,person,924,2769,"2077",["2077"] -person,0,person,925,2772,"207620762076",["207620762076"] -person,0,person,926,2775,"2075",["2075"] -person,0,person,927,2778,"207420742074",["207420742074"] -person,0,person,928,2781,"2073",["2073"] -person,0,person,929,2784,"207220722072",["207220722072"] -person,0,person,930,2787,"2071",["2071"] -person,0,person,931,2790,"207020702070",["207020702070"] -person,0,person,932,2793,"2069",["2069"] -person,0,person,933,2796,"206820682068",["206820682068"] -person,0,person,934,2799,"2067",["2067"] -person,0,person,935,2802,"206620662066",["206620662066"] -person,0,person,936,2805,"2065",["2065"] -person,0,person,937,2808,"206420642064",["206420642064"] -person,0,person,938,2811,"2063",["2063"] -person,0,person,939,2814,"206220622062",["206220622062"] -person,0,person,940,2817,"2061",["2061"] -person,0,person,941,2820,"206020602060",["206020602060"] -person,0,person,942,2823,"2059",["2059"] -person,0,person,943,2826,"205820582058",["205820582058"] -person,0,person,944,2829,"2057",["2057"] -person,0,person,945,2832,"205620562056",["205620562056"] -person,0,person,946,2835,"2055",["2055"] -person,0,person,947,2838,"205420542054",["205420542054"] -person,0,person,948,2841,"2053",["2053"] -person,0,person,949,2844,"205220522052",["205220522052"] -person,0,person,950,2847,"2051",["2051"] -person,0,person,951,2850,"205020502050",["205020502050"] -person,0,person,952,2853,"2049",["2049"] -person,0,person,953,2856,"204820482048",["204820482048"] -person,0,person,954,2859,"2047",["2047"] -person,0,person,955,2862,"204620462046",["204620462046"] -person,0,person,956,2865,"2045",["2045"] -person,0,person,957,2868,"204420442044",["204420442044"] -person,0,person,958,2871,"2043",["2043"] -person,0,person,959,2874,"204220422042",["204220422042"] -person,0,person,960,2877,"2041",["2041"] -person,0,person,961,2880,"204020402040",["204020402040"] -person,0,person,962,2883,"2039",["2039"] -person,0,person,963,2886,"203820382038",["203820382038"] -person,0,person,964,2889,"2037",["2037"] -person,0,person,965,2892,"203620362036",["203620362036"] -person,0,person,966,2895,"2035",["2035"] -person,0,person,967,2898,"203420342034",["203420342034"] -person,0,person,968,2901,"2033",["2033"] -person,0,person,969,2904,"203220322032",["203220322032"] -person,0,person,970,2907,"2031",["2031"] -person,0,person,971,2910,"203020302030",["203020302030"] -person,0,person,972,2913,"2029",["2029"] -person,0,person,973,2916,"202820282028",["202820282028"] -person,0,person,974,2919,"2027",["2027"] -person,0,person,975,2922,"202620262026",["202620262026"] -person,0,person,976,2925,"2025",["2025"] -person,0,person,977,2928,"202420242024",["202420242024"] -person,0,person,978,2931,"2023",["2023"] -person,0,person,979,2934,"202220222022",["202220222022"] -person,0,person,980,2937,"2021",["2021"] -person,0,person,981,2940,"202020202020",["202020202020"] -person,0,person,982,2943,"2019",["2019"] -person,0,person,983,2946,"201820182018",["201820182018"] -person,0,person,984,2949,"2017",["2017"] -person,0,person,985,2952,"201620162016",["201620162016"] -person,0,person,986,2955,"2015",["2015"] -person,0,person,987,2958,"201420142014",["201420142014"] -person,0,person,988,2961,"2013",["2013"] -person,0,person,989,2964,"201220122012",["201220122012"] -person,0,person,990,2967,"2011",["2011"] -person,0,person,991,2970,"201020102010",["201020102010"] -person,0,person,992,2973,"2009",["2009"] -person,0,person,993,2976,"200820082008",["200820082008"] -person,0,person,994,2979,"2007",["2007"] -person,0,person,995,2982,"200620062006",["200620062006"] -person,0,person,996,2985,"2005",["2005"] -person,0,person,997,2988,"200420042004",["200420042004"] -person,0,person,998,2991,"2003",["2003"] -person,0,person,999,2994,"200220022002",["200220022002"] -person,0,person,1000,2997,"2001",["2001"] -person,0,person,1001,3000,"200020002000",["200020002000"] -person,0,person,1002,3003,"1999",["1999"] -person,0,person,1003,3006,"199819981998",["199819981998"] -person,0,person,1004,3009,"1997",["1997"] -person,0,person,1005,3012,"199619961996",["199619961996"] -person,0,person,1006,3015,"1995",["1995"] -person,0,person,1007,3018,"199419941994",["199419941994"] -person,0,person,1008,3021,"1993",["1993"] -person,0,person,1009,3024,"199219921992",["199219921992"] -person,0,person,1010,3027,"1991",["1991"] -person,0,person,1011,3030,"199019901990",["199019901990"] -person,0,person,1012,3033,"1989",["1989"] -person,0,person,1013,3036,"198819881988",["198819881988"] -person,0,person,1014,3039,"1987",["1987"] -person,0,person,1015,3042,"198619861986",["198619861986"] -person,0,person,1016,3045,"1985",["1985"] -person,0,person,1017,3048,"198419841984",["198419841984"] -person,0,person,1018,3051,"1983",["1983"] -person,0,person,1019,3054,"198219821982",["198219821982"] -person,0,person,1020,3057,"1981",["1981"] -person,0,person,1021,3060,"198019801980",["198019801980"] -person,0,person,1022,3063,"1979",["1979"] -person,0,person,1023,3066,"197819781978",["197819781978"] -person,0,person,1024,3069,"1977",["1977"] -person,0,person,1025,3072,"197619761976",["197619761976"] -person,0,person,1026,3075,"1975",["1975"] -person,0,person,1027,3078,"197419741974",["197419741974"] -person,0,person,1028,3081,"1973",["1973"] -person,0,person,1029,3084,"197219721972",["197219721972"] -person,0,person,1030,3087,"1971",["1971"] -person,0,person,1031,3090,"197019701970",["197019701970"] -person,0,person,1032,3093,"1969",["1969"] -person,0,person,1033,3096,"196819681968",["196819681968"] -person,0,person,1034,3099,"1967",["1967"] -person,0,person,1035,3102,"196619661966",["196619661966"] -person,0,person,1036,3105,"1965",["1965"] -person,0,person,1037,3108,"196419641964",["196419641964"] -person,0,person,1038,3111,"1963",["1963"] -person,0,person,1039,3114,"196219621962",["196219621962"] -person,0,person,1040,3117,"1961",["1961"] -person,0,person,1041,3120,"196019601960",["196019601960"] -person,0,person,1042,3123,"1959",["1959"] -person,0,person,1043,3126,"195819581958",["195819581958"] -person,0,person,1044,3129,"1957",["1957"] -person,0,person,1045,3132,"195619561956",["195619561956"] -person,0,person,1046,3135,"1955",["1955"] -person,0,person,1047,3138,"195419541954",["195419541954"] -person,0,person,1048,3141,"1953",["1953"] -person,0,person,1049,3144,"195219521952",["195219521952"] -person,0,person,1050,3147,"1951",["1951"] -person,0,person,1051,3150,"195019501950",["195019501950"] -person,0,person,1052,3153,"1949",["1949"] -person,0,person,1053,3156,"194819481948",["194819481948"] -person,0,person,1054,3159,"1947",["1947"] -person,0,person,1055,3162,"194619461946",["194619461946"] -person,0,person,1056,3165,"1945",["1945"] -person,0,person,1057,3168,"194419441944",["194419441944"] -person,0,person,1058,3171,"1943",["1943"] -person,0,person,1059,3174,"194219421942",["194219421942"] -person,0,person,1060,3177,"1941",["1941"] -person,0,person,1061,3180,"194019401940",["194019401940"] -person,0,person,1062,3183,"1939",["1939"] -person,0,person,1063,3186,"193819381938",["193819381938"] -person,0,person,1064,3189,"1937",["1937"] -person,0,person,1065,3192,"193619361936",["193619361936"] -person,0,person,1066,3195,"1935",["1935"] -person,0,person,1067,3198,"193419341934",["193419341934"] -person,0,person,1068,3201,"1933",["1933"] -person,0,person,1069,3204,"193219321932",["193219321932"] -person,0,person,1070,3207,"1931",["1931"] -person,0,person,1071,3210,"193019301930",["193019301930"] -person,0,person,1072,3213,"1929",["1929"] -person,0,person,1073,3216,"192819281928",["192819281928"] -person,0,person,1074,3219,"1927",["1927"] -person,0,person,1075,3222,"192619261926",["192619261926"] -person,0,person,1076,3225,"1925",["1925"] -person,0,person,1077,3228,"192419241924",["192419241924"] -person,0,person,1078,3231,"1923",["1923"] -person,0,person,1079,3234,"192219221922",["192219221922"] -person,0,person,1080,3237,"1921",["1921"] -person,0,person,1081,3240,"192019201920",["192019201920"] -person,0,person,1082,3243,"1919",["1919"] -person,0,person,1083,3246,"191819181918",["191819181918"] -person,0,person,1084,3249,"1917",["1917"] -person,0,person,1085,3252,"191619161916",["191619161916"] -person,0,person,1086,3255,"1915",["1915"] -person,0,person,1087,3258,"191419141914",["191419141914"] -person,0,person,1088,3261,"1913",["1913"] -person,0,person,1089,3264,"191219121912",["191219121912"] -person,0,person,1090,3267,"1911",["1911"] -person,0,person,1091,3270,"191019101910",["191019101910"] -person,0,person,1092,3273,"1909",["1909"] -person,0,person,1093,3276,"190819081908",["190819081908"] -person,0,person,1094,3279,"1907",["1907"] -person,0,person,1095,3282,"190619061906",["190619061906"] -person,0,person,1096,3285,"1905",["1905"] -person,0,person,1097,3288,"190419041904",["190419041904"] -person,0,person,1098,3291,"1903",["1903"] -person,0,person,1099,3294,"190219021902",["190219021902"] -person,0,person,1100,3297,"1901",["1901"] -person,0,person,1101,3300,"190019001900",["190019001900"] -person,0,person,1102,3303,"1899",["1899"] -person,0,person,1103,3306,"189818981898",["189818981898"] -person,0,person,1104,3309,"1897",["1897"] -person,0,person,1105,3312,"189618961896",["189618961896"] -person,0,person,1106,3315,"1895",["1895"] -person,0,person,1107,3318,"189418941894",["189418941894"] -person,0,person,1108,3321,"1893",["1893"] -person,0,person,1109,3324,"189218921892",["189218921892"] -person,0,person,1110,3327,"1891",["1891"] -person,0,person,1111,3330,"189018901890",["189018901890"] -person,0,person,1112,3333,"1889",["1889"] -person,0,person,1113,3336,"188818881888",["188818881888"] -person,0,person,1114,3339,"1887",["1887"] -person,0,person,1115,3342,"188618861886",["188618861886"] -person,0,person,1116,3345,"1885",["1885"] -person,0,person,1117,3348,"188418841884",["188418841884"] -person,0,person,1118,3351,"1883",["1883"] -person,0,person,1119,3354,"188218821882",["188218821882"] -person,0,person,1120,3357,"1881",["1881"] -person,0,person,1121,3360,"188018801880",["188018801880"] -person,0,person,1122,3363,"1879",["1879"] -person,0,person,1123,3366,"187818781878",["187818781878"] -person,0,person,1124,3369,"1877",["1877"] -person,0,person,1125,3372,"187618761876",["187618761876"] -person,0,person,1126,3375,"1875",["1875"] -person,0,person,1127,3378,"187418741874",["187418741874"] -person,0,person,1128,3381,"1873",["1873"] -person,0,person,1129,3384,"187218721872",["187218721872"] -person,0,person,1130,3387,"1871",["1871"] -person,0,person,1131,3390,"187018701870",["187018701870"] -person,0,person,1132,3393,"1869",["1869"] -person,0,person,1133,3396,"186818681868",["186818681868"] -person,0,person,1134,3399,"1867",["1867"] -person,0,person,1135,3402,"186618661866",["186618661866"] -person,0,person,1136,3405,"1865",["1865"] -person,0,person,1137,3408,"186418641864",["186418641864"] -person,0,person,1138,3411,"1863",["1863"] -person,0,person,1139,3414,"186218621862",["186218621862"] -person,0,person,1140,3417,"1861",["1861"] -person,0,person,1141,3420,"186018601860",["186018601860"] -person,0,person,1142,3423,"1859",["1859"] -person,0,person,1143,3426,"185818581858",["185818581858"] -person,0,person,1144,3429,"1857",["1857"] -person,0,person,1145,3432,"185618561856",["185618561856"] -person,0,person,1146,3435,"1855",["1855"] -person,0,person,1147,3438,"185418541854",["185418541854"] -person,0,person,1148,3441,"1853",["1853"] -person,0,person,1149,3444,"185218521852",["185218521852"] -person,0,person,1150,3447,"1851",["1851"] -person,0,person,1151,3450,"185018501850",["185018501850"] -person,0,person,1152,3453,"1849",["1849"] -person,0,person,1153,3456,"184818481848",["184818481848"] -person,0,person,1154,3459,"1847",["1847"] -person,0,person,1155,3462,"184618461846",["184618461846"] -person,0,person,1156,3465,"1845",["1845"] -person,0,person,1157,3468,"184418441844",["184418441844"] -person,0,person,1158,3471,"1843",["1843"] -person,0,person,1159,3474,"184218421842",["184218421842"] -person,0,person,1160,3477,"1841",["1841"] -person,0,person,1161,3480,"184018401840",["184018401840"] -person,0,person,1162,3483,"1839",["1839"] -person,0,person,1163,3486,"183818381838",["183818381838"] -person,0,person,1164,3489,"1837",["1837"] -person,0,person,1165,3492,"183618361836",["183618361836"] -person,0,person,1166,3495,"1835",["1835"] -person,0,person,1167,3498,"183418341834",["183418341834"] -person,0,person,1168,3501,"1833",["1833"] -person,0,person,1169,3504,"183218321832",["183218321832"] -person,0,person,1170,3507,"1831",["1831"] -person,0,person,1171,3510,"183018301830",["183018301830"] -person,0,person,1172,3513,"1829",["1829"] -person,0,person,1173,3516,"182818281828",["182818281828"] -person,0,person,1174,3519,"1827",["1827"] -person,0,person,1175,3522,"182618261826",["182618261826"] -person,0,person,1176,3525,"1825",["1825"] -person,0,person,1177,3528,"182418241824",["182418241824"] -person,0,person,1178,3531,"1823",["1823"] -person,0,person,1179,3534,"182218221822",["182218221822"] -person,0,person,1180,3537,"1821",["1821"] -person,0,person,1181,3540,"182018201820",["182018201820"] -person,0,person,1182,3543,"1819",["1819"] -person,0,person,1183,3546,"181818181818",["181818181818"] -person,0,person,1184,3549,"1817",["1817"] -person,0,person,1185,3552,"181618161816",["181618161816"] -person,0,person,1186,3555,"1815",["1815"] -person,0,person,1187,3558,"181418141814",["181418141814"] -person,0,person,1188,3561,"1813",["1813"] -person,0,person,1189,3564,"181218121812",["181218121812"] -person,0,person,1190,3567,"1811",["1811"] -person,0,person,1191,3570,"181018101810",["181018101810"] -person,0,person,1192,3573,"1809",["1809"] -person,0,person,1193,3576,"180818081808",["180818081808"] -person,0,person,1194,3579,"1807",["1807"] -person,0,person,1195,3582,"180618061806",["180618061806"] -person,0,person,1196,3585,"1805",["1805"] -person,0,person,1197,3588,"180418041804",["180418041804"] -person,0,person,1198,3591,"1803",["1803"] -person,0,person,1199,3594,"180218021802",["180218021802"] -person,0,person,1200,3597,"1801",["1801"] -person,0,person,1201,3600,"180018001800",["180018001800"] -person,0,person,1202,3603,"1799",["1799"] -person,0,person,1203,3606,"179817981798",["179817981798"] -person,0,person,1204,3609,"1797",["1797"] -person,0,person,1205,3612,"179617961796",["179617961796"] -person,0,person,1206,3615,"1795",["1795"] -person,0,person,1207,3618,"179417941794",["179417941794"] -person,0,person,1208,3621,"1793",["1793"] -person,0,person,1209,3624,"179217921792",["179217921792"] -person,0,person,1210,3627,"1791",["1791"] -person,0,person,1211,3630,"179017901790",["179017901790"] -person,0,person,1212,3633,"1789",["1789"] -person,0,person,1213,3636,"178817881788",["178817881788"] -person,0,person,1214,3639,"1787",["1787"] -person,0,person,1215,3642,"178617861786",["178617861786"] -person,0,person,1216,3645,"1785",["1785"] -person,0,person,1217,3648,"178417841784",["178417841784"] -person,0,person,1218,3651,"1783",["1783"] -person,0,person,1219,3654,"178217821782",["178217821782"] -person,0,person,1220,3657,"1781",["1781"] -person,0,person,1221,3660,"178017801780",["178017801780"] -person,0,person,1222,3663,"1779",["1779"] -person,0,person,1223,3666,"177817781778",["177817781778"] -person,0,person,1224,3669,"1777",["1777"] -person,0,person,1225,3672,"177617761776",["177617761776"] -person,0,person,1226,3675,"1775",["1775"] -person,0,person,1227,3678,"177417741774",["177417741774"] -person,0,person,1228,3681,"1773",["1773"] -person,0,person,1229,3684,"177217721772",["177217721772"] -person,0,person,1230,3687,"1771",["1771"] -person,0,person,1231,3690,"177017701770",["177017701770"] -person,0,person,1232,3693,"1769",["1769"] -person,0,person,1233,3696,"176817681768",["176817681768"] -person,0,person,1234,3699,"1767",["1767"] -person,0,person,1235,3702,"176617661766",["176617661766"] -person,0,person,1236,3705,"1765",["1765"] -person,0,person,1237,3708,"176417641764",["176417641764"] -person,0,person,1238,3711,"1763",["1763"] -person,0,person,1239,3714,"176217621762",["176217621762"] -person,0,person,1240,3717,"1761",["1761"] -person,0,person,1241,3720,"176017601760",["176017601760"] -person,0,person,1242,3723,"1759",["1759"] -person,0,person,1243,3726,"175817581758",["175817581758"] -person,0,person,1244,3729,"1757",["1757"] -person,0,person,1245,3732,"175617561756",["175617561756"] -person,0,person,1246,3735,"1755",["1755"] -person,0,person,1247,3738,"175417541754",["175417541754"] -person,0,person,1248,3741,"1753",["1753"] -person,0,person,1249,3744,"175217521752",["175217521752"] -person,0,person,1250,3747,"1751",["1751"] -person,0,person,1251,3750,"175017501750",["175017501750"] -person,0,person,1252,3753,"1749",["1749"] -person,0,person,1253,3756,"174817481748",["174817481748"] -person,0,person,1254,3759,"1747",["1747"] -person,0,person,1255,3762,"174617461746",["174617461746"] -person,0,person,1256,3765,"1745",["1745"] -person,0,person,1257,3768,"174417441744",["174417441744"] -person,0,person,1258,3771,"1743",["1743"] -person,0,person,1259,3774,"174217421742",["174217421742"] -person,0,person,1260,3777,"1741",["1741"] -person,0,person,1261,3780,"174017401740",["174017401740"] -person,0,person,1262,3783,"1739",["1739"] -person,0,person,1263,3786,"173817381738",["173817381738"] -person,0,person,1264,3789,"1737",["1737"] -person,0,person,1265,3792,"173617361736",["173617361736"] -person,0,person,1266,3795,"1735",["1735"] -person,0,person,1267,3798,"173417341734",["173417341734"] -person,0,person,1268,3801,"1733",["1733"] -person,0,person,1269,3804,"173217321732",["173217321732"] -person,0,person,1270,3807,"1731",["1731"] -person,0,person,1271,3810,"173017301730",["173017301730"] -person,0,person,1272,3813,"1729",["1729"] -person,0,person,1273,3816,"172817281728",["172817281728"] -person,0,person,1274,3819,"1727",["1727"] -person,0,person,1275,3822,"172617261726",["172617261726"] -person,0,person,1276,3825,"1725",["1725"] -person,0,person,1277,3828,"172417241724",["172417241724"] -person,0,person,1278,3831,"1723",["1723"] -person,0,person,1279,3834,"172217221722",["172217221722"] -person,0,person,1280,3837,"1721",["1721"] -person,0,person,1281,3840,"172017201720",["172017201720"] -person,0,person,1282,3843,"1719",["1719"] -person,0,person,1283,3846,"171817181718",["171817181718"] -person,0,person,1284,3849,"1717",["1717"] -person,0,person,1285,3852,"171617161716",["171617161716"] -person,0,person,1286,3855,"1715",["1715"] -person,0,person,1287,3858,"171417141714",["171417141714"] -person,0,person,1288,3861,"1713",["1713"] -person,0,person,1289,3864,"171217121712",["171217121712"] -person,0,person,1290,3867,"1711",["1711"] -person,0,person,1291,3870,"171017101710",["171017101710"] -person,0,person,1292,3873,"1709",["1709"] -person,0,person,1293,3876,"170817081708",["170817081708"] -person,0,person,1294,3879,"1707",["1707"] -person,0,person,1295,3882,"170617061706",["170617061706"] -person,0,person,1296,3885,"1705",["1705"] -person,0,person,1297,3888,"170417041704",["170417041704"] -person,0,person,1298,3891,"1703",["1703"] -person,0,person,1299,3894,"170217021702",["170217021702"] -person,0,person,1300,3897,"1701",["1701"] -person,0,person,1301,3900,"170017001700",["170017001700"] -person,0,person,1302,3903,"1699",["1699"] -person,0,person,1303,3906,"169816981698",["169816981698"] -person,0,person,1304,3909,"1697",["1697"] -person,0,person,1305,3912,"169616961696",["169616961696"] -person,0,person,1306,3915,"1695",["1695"] -person,0,person,1307,3918,"169416941694",["169416941694"] -person,0,person,1308,3921,"1693",["1693"] -person,0,person,1309,3924,"169216921692",["169216921692"] -person,0,person,1310,3927,"1691",["1691"] -person,0,person,1311,3930,"169016901690",["169016901690"] -person,0,person,1312,3933,"1689",["1689"] -person,0,person,1313,3936,"168816881688",["168816881688"] -person,0,person,1314,3939,"1687",["1687"] -person,0,person,1315,3942,"168616861686",["168616861686"] -person,0,person,1316,3945,"1685",["1685"] -person,0,person,1317,3948,"168416841684",["168416841684"] -person,0,person,1318,3951,"1683",["1683"] -person,0,person,1319,3954,"168216821682",["168216821682"] -person,0,person,1320,3957,"1681",["1681"] -person,0,person,1321,3960,"168016801680",["168016801680"] -person,0,person,1322,3963,"1679",["1679"] -person,0,person,1323,3966,"167816781678",["167816781678"] -person,0,person,1324,3969,"1677",["1677"] -person,0,person,1325,3972,"167616761676",["167616761676"] -person,0,person,1326,3975,"1675",["1675"] -person,0,person,1327,3978,"167416741674",["167416741674"] -person,0,person,1328,3981,"1673",["1673"] -person,0,person,1329,3984,"167216721672",["167216721672"] -person,0,person,1330,3987,"1671",["1671"] -person,0,person,1331,3990,"167016701670",["167016701670"] -person,0,person,1332,3993,"1669",["1669"] -person,0,person,1333,3996,"166816681668",["166816681668"] -person,0,person,1334,3999,"1667",["1667"] -person,0,person,1335,4002,"166616661666",["166616661666"] -person,0,person,1336,4005,"1665",["1665"] -person,0,person,1337,4008,"166416641664",["166416641664"] -person,0,person,1338,4011,"1663",["1663"] -person,0,person,1339,4014,"166216621662",["166216621662"] -person,0,person,1340,4017,"1661",["1661"] -person,0,person,1341,4020,"166016601660",["166016601660"] -person,0,person,1342,4023,"1659",["1659"] -person,0,person,1343,4026,"165816581658",["165816581658"] -person,0,person,1344,4029,"1657",["1657"] -person,0,person,1345,4032,"165616561656",["165616561656"] -person,0,person,1346,4035,"1655",["1655"] -person,0,person,1347,4038,"165416541654",["165416541654"] -person,0,person,1348,4041,"1653",["1653"] -person,0,person,1349,4044,"165216521652",["165216521652"] -person,0,person,1350,4047,"1651",["1651"] -person,0,person,1351,4050,"165016501650",["165016501650"] -person,0,person,1352,4053,"1649",["1649"] -person,0,person,1353,4056,"164816481648",["164816481648"] -person,0,person,1354,4059,"1647",["1647"] -person,0,person,1355,4062,"164616461646",["164616461646"] -person,0,person,1356,4065,"1645",["1645"] -person,0,person,1357,4068,"164416441644",["164416441644"] -person,0,person,1358,4071,"1643",["1643"] -person,0,person,1359,4074,"164216421642",["164216421642"] -person,0,person,1360,4077,"1641",["1641"] -person,0,person,1361,4080,"164016401640",["164016401640"] -person,0,person,1362,4083,"1639",["1639"] -person,0,person,1363,4086,"163816381638",["163816381638"] -person,0,person,1364,4089,"1637",["1637"] -person,0,person,1365,4092,"163616361636",["163616361636"] -person,0,person,1366,4095,"1635",["1635"] -person,0,person,1367,4098,"163416341634",["163416341634"] -person,0,person,1368,4101,"1633",["1633"] -person,0,person,1369,4104,"163216321632",["163216321632"] -person,0,person,1370,4107,"1631",["1631"] -person,0,person,1371,4110,"163016301630",["163016301630"] -person,0,person,1372,4113,"1629",["1629"] -person,0,person,1373,4116,"162816281628",["162816281628"] -person,0,person,1374,4119,"1627",["1627"] -person,0,person,1375,4122,"162616261626",["162616261626"] -person,0,person,1376,4125,"1625",["1625"] -person,0,person,1377,4128,"162416241624",["162416241624"] -person,0,person,1378,4131,"1623",["1623"] -person,0,person,1379,4134,"162216221622",["162216221622"] -person,0,person,1380,4137,"1621",["1621"] -person,0,person,1381,4140,"162016201620",["162016201620"] -person,0,person,1382,4143,"1619",["1619"] -person,0,person,1383,4146,"161816181618",["161816181618"] -person,0,person,1384,4149,"1617",["1617"] -person,0,person,1385,4152,"161616161616",["161616161616"] -person,0,person,1386,4155,"1615",["1615"] -person,0,person,1387,4158,"161416141614",["161416141614"] -person,0,person,1388,4161,"1613",["1613"] -person,0,person,1389,4164,"161216121612",["161216121612"] -person,0,person,1390,4167,"1611",["1611"] -person,0,person,1391,4170,"161016101610",["161016101610"] -person,0,person,1392,4173,"1609",["1609"] -person,0,person,1393,4176,"160816081608",["160816081608"] -person,0,person,1394,4179,"1607",["1607"] -person,0,person,1395,4182,"160616061606",["160616061606"] -person,0,person,1396,4185,"1605",["1605"] -person,0,person,1397,4188,"160416041604",["160416041604"] -person,0,person,1398,4191,"1603",["1603"] -person,0,person,1399,4194,"160216021602",["160216021602"] -person,0,person,1400,4197,"1601",["1601"] -person,0,person,1401,4200,"160016001600",["160016001600"] -person,0,person,1402,4203,"1599",["1599"] -person,0,person,1403,4206,"159815981598",["159815981598"] -person,0,person,1404,4209,"1597",["1597"] -person,0,person,1405,4212,"159615961596",["159615961596"] -person,0,person,1406,4215,"1595",["1595"] -person,0,person,1407,4218,"159415941594",["159415941594"] -person,0,person,1408,4221,"1593",["1593"] -person,0,person,1409,4224,"159215921592",["159215921592"] -person,0,person,1410,4227,"1591",["1591"] -person,0,person,1411,4230,"159015901590",["159015901590"] -person,0,person,1412,4233,"1589",["1589"] -person,0,person,1413,4236,"158815881588",["158815881588"] -person,0,person,1414,4239,"1587",["1587"] -person,0,person,1415,4242,"158615861586",["158615861586"] -person,0,person,1416,4245,"1585",["1585"] -person,0,person,1417,4248,"158415841584",["158415841584"] -person,0,person,1418,4251,"1583",["1583"] -person,0,person,1419,4254,"158215821582",["158215821582"] -person,0,person,1420,4257,"1581",["1581"] -person,0,person,1421,4260,"158015801580",["158015801580"] -person,0,person,1422,4263,"1579",["1579"] -person,0,person,1423,4266,"157815781578",["157815781578"] -person,0,person,1424,4269,"1577",["1577"] -person,0,person,1425,4272,"157615761576",["157615761576"] -person,0,person,1426,4275,"1575",["1575"] -person,0,person,1427,4278,"157415741574",["157415741574"] -person,0,person,1428,4281,"1573",["1573"] -person,0,person,1429,4284,"157215721572",["157215721572"] -person,0,person,1430,4287,"1571",["1571"] -person,0,person,1431,4290,"157015701570",["157015701570"] -person,0,person,1432,4293,"1569",["1569"] -person,0,person,1433,4296,"156815681568",["156815681568"] -person,0,person,1434,4299,"1567",["1567"] -person,0,person,1435,4302,"156615661566",["156615661566"] -person,0,person,1436,4305,"1565",["1565"] -person,0,person,1437,4308,"156415641564",["156415641564"] -person,0,person,1438,4311,"1563",["1563"] -person,0,person,1439,4314,"156215621562",["156215621562"] -person,0,person,1440,4317,"1561",["1561"] -person,0,person,1441,4320,"156015601560",["156015601560"] -person,0,person,1442,4323,"1559",["1559"] -person,0,person,1443,4326,"155815581558",["155815581558"] -person,0,person,1444,4329,"1557",["1557"] -person,0,person,1445,4332,"155615561556",["155615561556"] -person,0,person,1446,4335,"1555",["1555"] -person,0,person,1447,4338,"155415541554",["155415541554"] -person,0,person,1448,4341,"1553",["1553"] -person,0,person,1449,4344,"155215521552",["155215521552"] -person,0,person,1450,4347,"1551",["1551"] -person,0,person,1451,4350,"155015501550",["155015501550"] -person,0,person,1452,4353,"1549",["1549"] -person,0,person,1453,4356,"154815481548",["154815481548"] -person,0,person,1454,4359,"1547",["1547"] -person,0,person,1455,4362,"154615461546",["154615461546"] -person,0,person,1456,4365,"1545",["1545"] -person,0,person,1457,4368,"154415441544",["154415441544"] -person,0,person,1458,4371,"1543",["1543"] -person,0,person,1459,4374,"154215421542",["154215421542"] -person,0,person,1460,4377,"1541",["1541"] -person,0,person,1461,4380,"154015401540",["154015401540"] -person,0,person,1462,4383,"1539",["1539"] -person,0,person,1463,4386,"153815381538",["153815381538"] -person,0,person,1464,4389,"1537",["1537"] -person,0,person,1465,4392,"153615361536",["153615361536"] -person,0,person,1466,4395,"1535",["1535"] -person,0,person,1467,4398,"153415341534",["153415341534"] -person,0,person,1468,4401,"1533",["1533"] -person,0,person,1469,4404,"153215321532",["153215321532"] -person,0,person,1470,4407,"1531",["1531"] -person,0,person,1471,4410,"153015301530",["153015301530"] -person,0,person,1472,4413,"1529",["1529"] -person,0,person,1473,4416,"152815281528",["152815281528"] -person,0,person,1474,4419,"1527",["1527"] -person,0,person,1475,4422,"152615261526",["152615261526"] -person,0,person,1476,4425,"1525",["1525"] -person,0,person,1477,4428,"152415241524",["152415241524"] -person,0,person,1478,4431,"1523",["1523"] -person,0,person,1479,4434,"152215221522",["152215221522"] -person,0,person,1480,4437,"1521",["1521"] -person,0,person,1481,4440,"152015201520",["152015201520"] -person,0,person,1482,4443,"1519",["1519"] -person,0,person,1483,4446,"151815181518",["151815181518"] -person,0,person,1484,4449,"1517",["1517"] -person,0,person,1485,4452,"151615161516",["151615161516"] -person,0,person,1486,4455,"1515",["1515"] -person,0,person,1487,4458,"151415141514",["151415141514"] -person,0,person,1488,4461,"1513",["1513"] -person,0,person,1489,4464,"151215121512",["151215121512"] -person,0,person,1490,4467,"1511",["1511"] -person,0,person,1491,4470,"151015101510",["151015101510"] -person,0,person,1492,4473,"1509",["1509"] -person,0,person,1493,4476,"150815081508",["150815081508"] -person,0,person,1494,4479,"1507",["1507"] -person,0,person,1495,4482,"150615061506",["150615061506"] -person,0,person,1496,4485,"1505",["1505"] -person,0,person,1497,4488,"150415041504",["150415041504"] -person,0,person,1498,4491,"1503",["1503"] -person,0,person,1499,4494,"150215021502",["150215021502"] -person,0,person,1500,4497,"1501",["1501"] -person,0,person,1501,4500,"150015001500",["150015001500"] -person,0,person,1502,4503,"1499",["1499"] -person,0,person,1503,4506,"149814981498",["149814981498"] -person,0,person,1504,4509,"1497",["1497"] -person,0,person,1505,4512,"149614961496",["149614961496"] -person,0,person,1506,4515,"1495",["1495"] -person,0,person,1507,4518,"149414941494",["149414941494"] -person,0,person,1508,4521,"1493",["1493"] -person,0,person,1509,4524,"149214921492",["149214921492"] -person,0,person,1510,4527,"1491",["1491"] -person,0,person,1511,4530,"149014901490",["149014901490"] -person,0,person,1512,4533,"1489",["1489"] -person,0,person,1513,4536,"148814881488",["148814881488"] -person,0,person,1514,4539,"1487",["1487"] -person,0,person,1515,4542,"148614861486",["148614861486"] -person,0,person,1516,4545,"1485",["1485"] -person,0,person,1517,4548,"148414841484",["148414841484"] -person,0,person,1518,4551,"1483",["1483"] -person,0,person,1519,4554,"148214821482",["148214821482"] -person,0,person,1520,4557,"1481",["1481"] -person,0,person,1521,4560,"148014801480",["148014801480"] -person,0,person,1522,4563,"1479",["1479"] -person,0,person,1523,4566,"147814781478",["147814781478"] -person,0,person,1524,4569,"1477",["1477"] -person,0,person,1525,4572,"147614761476",["147614761476"] -person,0,person,1526,4575,"1475",["1475"] -person,0,person,1527,4578,"147414741474",["147414741474"] -person,0,person,1528,4581,"1473",["1473"] -person,0,person,1529,4584,"147214721472",["147214721472"] -person,0,person,1530,4587,"1471",["1471"] -person,0,person,1531,4590,"147014701470",["147014701470"] -person,0,person,1532,4593,"1469",["1469"] -person,0,person,1533,4596,"146814681468",["146814681468"] -person,0,person,1534,4599,"1467",["1467"] -person,0,person,1535,4602,"146614661466",["146614661466"] -person,0,person,1536,4605,"1465",["1465"] -person,0,person,1537,4608,"146414641464",["146414641464"] -person,0,person,1538,4611,"1463",["1463"] -person,0,person,1539,4614,"146214621462",["146214621462"] -person,0,person,1540,4617,"1461",["1461"] -person,0,person,1541,4620,"146014601460",["146014601460"] -person,0,person,1542,4623,"1459",["1459"] -person,0,person,1543,4626,"145814581458",["145814581458"] -person,0,person,1544,4629,"1457",["1457"] -person,0,person,1545,4632,"145614561456",["145614561456"] -person,0,person,1546,4635,"1455",["1455"] -person,0,person,1547,4638,"145414541454",["145414541454"] -person,0,person,1548,4641,"1453",["1453"] -person,0,person,1549,4644,"145214521452",["145214521452"] -person,0,person,1550,4647,"1451",["1451"] -person,0,person,1551,4650,"145014501450",["145014501450"] -person,0,person,1552,4653,"1449",["1449"] -person,0,person,1553,4656,"144814481448",["144814481448"] -person,0,person,1554,4659,"1447",["1447"] -person,0,person,1555,4662,"144614461446",["144614461446"] -person,0,person,1556,4665,"1445",["1445"] -person,0,person,1557,4668,"144414441444",["144414441444"] -person,0,person,1558,4671,"1443",["1443"] -person,0,person,1559,4674,"144214421442",["144214421442"] -person,0,person,1560,4677,"1441",["1441"] -person,0,person,1561,4680,"144014401440",["144014401440"] -person,0,person,1562,4683,"1439",["1439"] -person,0,person,1563,4686,"143814381438",["143814381438"] -person,0,person,1564,4689,"1437",["1437"] -person,0,person,1565,4692,"143614361436",["143614361436"] -person,0,person,1566,4695,"1435",["1435"] -person,0,person,1567,4698,"143414341434",["143414341434"] -person,0,person,1568,4701,"1433",["1433"] -person,0,person,1569,4704,"143214321432",["143214321432"] -person,0,person,1570,4707,"1431",["1431"] -person,0,person,1571,4710,"143014301430",["143014301430"] -person,0,person,1572,4713,"1429",["1429"] -person,0,person,1573,4716,"142814281428",["142814281428"] -person,0,person,1574,4719,"1427",["1427"] -person,0,person,1575,4722,"142614261426",["142614261426"] -person,0,person,1576,4725,"1425",["1425"] -person,0,person,1577,4728,"142414241424",["142414241424"] -person,0,person,1578,4731,"1423",["1423"] -person,0,person,1579,4734,"142214221422",["142214221422"] -person,0,person,1580,4737,"1421",["1421"] -person,0,person,1581,4740,"142014201420",["142014201420"] -person,0,person,1582,4743,"1419",["1419"] -person,0,person,1583,4746,"141814181418",["141814181418"] -person,0,person,1584,4749,"1417",["1417"] -person,0,person,1585,4752,"141614161416",["141614161416"] -person,0,person,1586,4755,"1415",["1415"] -person,0,person,1587,4758,"141414141414",["141414141414"] -person,0,person,1588,4761,"1413",["1413"] -person,0,person,1589,4764,"141214121412",["141214121412"] -person,0,person,1590,4767,"1411",["1411"] -person,0,person,1591,4770,"141014101410",["141014101410"] -person,0,person,1592,4773,"1409",["1409"] -person,0,person,1593,4776,"140814081408",["140814081408"] -person,0,person,1594,4779,"1407",["1407"] -person,0,person,1595,4782,"140614061406",["140614061406"] -person,0,person,1596,4785,"1405",["1405"] -person,0,person,1597,4788,"140414041404",["140414041404"] -person,0,person,1598,4791,"1403",["1403"] -person,0,person,1599,4794,"140214021402",["140214021402"] -person,0,person,1600,4797,"1401",["1401"] -person,0,person,1601,4800,"140014001400",["140014001400"] -person,0,person,1602,4803,"1399",["1399"] -person,0,person,1603,4806,"139813981398",["139813981398"] -person,0,person,1604,4809,"1397",["1397"] -person,0,person,1605,4812,"139613961396",["139613961396"] -person,0,person,1606,4815,"1395",["1395"] -person,0,person,1607,4818,"139413941394",["139413941394"] -person,0,person,1608,4821,"1393",["1393"] -person,0,person,1609,4824,"139213921392",["139213921392"] -person,0,person,1610,4827,"1391",["1391"] -person,0,person,1611,4830,"139013901390",["139013901390"] -person,0,person,1612,4833,"1389",["1389"] -person,0,person,1613,4836,"138813881388",["138813881388"] -person,0,person,1614,4839,"1387",["1387"] -person,0,person,1615,4842,"138613861386",["138613861386"] -person,0,person,1616,4845,"1385",["1385"] -person,0,person,1617,4848,"138413841384",["138413841384"] -person,0,person,1618,4851,"1383",["1383"] -person,0,person,1619,4854,"138213821382",["138213821382"] -person,0,person,1620,4857,"1381",["1381"] -person,0,person,1621,4860,"138013801380",["138013801380"] -person,0,person,1622,4863,"1379",["1379"] -person,0,person,1623,4866,"137813781378",["137813781378"] -person,0,person,1624,4869,"1377",["1377"] -person,0,person,1625,4872,"137613761376",["137613761376"] -person,0,person,1626,4875,"1375",["1375"] -person,0,person,1627,4878,"137413741374",["137413741374"] -person,0,person,1628,4881,"1373",["1373"] -person,0,person,1629,4884,"137213721372",["137213721372"] -person,0,person,1630,4887,"1371",["1371"] -person,0,person,1631,4890,"137013701370",["137013701370"] -person,0,person,1632,4893,"1369",["1369"] -person,0,person,1633,4896,"136813681368",["136813681368"] -person,0,person,1634,4899,"1367",["1367"] -person,0,person,1635,4902,"136613661366",["136613661366"] -person,0,person,1636,4905,"1365",["1365"] -person,0,person,1637,4908,"136413641364",["136413641364"] -person,0,person,1638,4911,"1363",["1363"] -person,0,person,1639,4914,"136213621362",["136213621362"] -person,0,person,1640,4917,"1361",["1361"] -person,0,person,1641,4920,"136013601360",["136013601360"] -person,0,person,1642,4923,"1359",["1359"] -person,0,person,1643,4926,"135813581358",["135813581358"] -person,0,person,1644,4929,"1357",["1357"] -person,0,person,1645,4932,"135613561356",["135613561356"] -person,0,person,1646,4935,"1355",["1355"] -person,0,person,1647,4938,"135413541354",["135413541354"] -person,0,person,1648,4941,"1353",["1353"] -person,0,person,1649,4944,"135213521352",["135213521352"] -person,0,person,1650,4947,"1351",["1351"] -person,0,person,1651,4950,"135013501350",["135013501350"] -person,0,person,1652,4953,"1349",["1349"] -person,0,person,1653,4956,"134813481348",["134813481348"] -person,0,person,1654,4959,"1347",["1347"] -person,0,person,1655,4962,"134613461346",["134613461346"] -person,0,person,1656,4965,"1345",["1345"] -person,0,person,1657,4968,"134413441344",["134413441344"] -person,0,person,1658,4971,"1343",["1343"] -person,0,person,1659,4974,"134213421342",["134213421342"] -person,0,person,1660,4977,"1341",["1341"] -person,0,person,1661,4980,"134013401340",["134013401340"] -person,0,person,1662,4983,"1339",["1339"] -person,0,person,1663,4986,"133813381338",["133813381338"] -person,0,person,1664,4989,"1337",["1337"] -person,0,person,1665,4992,"133613361336",["133613361336"] -person,0,person,1666,4995,"1335",["1335"] -person,0,person,1667,4998,"133413341334",["133413341334"] -person,0,person,1668,5001,"1333",["1333"] -person,0,person,1669,5004,"133213321332",["133213321332"] -person,0,person,1670,5007,"1331",["1331"] -person,0,person,1671,5010,"133013301330",["133013301330"] -person,0,person,1672,5013,"1329",["1329"] -person,0,person,1673,5016,"132813281328",["132813281328"] -person,0,person,1674,5019,"1327",["1327"] -person,0,person,1675,5022,"132613261326",["132613261326"] -person,0,person,1676,5025,"1325",["1325"] -person,0,person,1677,5028,"132413241324",["132413241324"] -person,0,person,1678,5031,"1323",["1323"] -person,0,person,1679,5034,"132213221322",["132213221322"] -person,0,person,1680,5037,"1321",["1321"] -person,0,person,1681,5040,"132013201320",["132013201320"] -person,0,person,1682,5043,"1319",["1319"] -person,0,person,1683,5046,"131813181318",["131813181318"] -person,0,person,1684,5049,"1317",["1317"] -person,0,person,1685,5052,"131613161316",["131613161316"] -person,0,person,1686,5055,"1315",["1315"] -person,0,person,1687,5058,"131413141314",["131413141314"] -person,0,person,1688,5061,"1313",["1313"] -person,0,person,1689,5064,"131213121312",["131213121312"] -person,0,person,1690,5067,"1311",["1311"] -person,0,person,1691,5070,"131013101310",["131013101310"] -person,0,person,1692,5073,"1309",["1309"] -person,0,person,1693,5076,"130813081308",["130813081308"] -person,0,person,1694,5079,"1307",["1307"] -person,0,person,1695,5082,"130613061306",["130613061306"] -person,0,person,1696,5085,"1305",["1305"] -person,0,person,1697,5088,"130413041304",["130413041304"] -person,0,person,1698,5091,"1303",["1303"] -person,0,person,1699,5094,"130213021302",["130213021302"] -person,0,person,1700,5097,"1301",["1301"] -person,0,person,1701,5100,"130013001300",["130013001300"] -person,0,person,1702,5103,"1299",["1299"] -person,0,person,1703,5106,"129812981298",["129812981298"] -person,0,person,1704,5109,"1297",["1297"] -person,0,person,1705,5112,"129612961296",["129612961296"] -person,0,person,1706,5115,"1295",["1295"] -person,0,person,1707,5118,"129412941294",["129412941294"] -person,0,person,1708,5121,"1293",["1293"] -person,0,person,1709,5124,"129212921292",["129212921292"] -person,0,person,1710,5127,"1291",["1291"] -person,0,person,1711,5130,"129012901290",["129012901290"] -person,0,person,1712,5133,"1289",["1289"] -person,0,person,1713,5136,"128812881288",["128812881288"] -person,0,person,1714,5139,"1287",["1287"] -person,0,person,1715,5142,"128612861286",["128612861286"] -person,0,person,1716,5145,"1285",["1285"] -person,0,person,1717,5148,"128412841284",["128412841284"] -person,0,person,1718,5151,"1283",["1283"] -person,0,person,1719,5154,"128212821282",["128212821282"] -person,0,person,1720,5157,"1281",["1281"] -person,0,person,1721,5160,"128012801280",["128012801280"] -person,0,person,1722,5163,"1279",["1279"] -person,0,person,1723,5166,"127812781278",["127812781278"] -person,0,person,1724,5169,"1277",["1277"] -person,0,person,1725,5172,"127612761276",["127612761276"] -person,0,person,1726,5175,"1275",["1275"] -person,0,person,1727,5178,"127412741274",["127412741274"] -person,0,person,1728,5181,"1273",["1273"] -person,0,person,1729,5184,"127212721272",["127212721272"] -person,0,person,1730,5187,"1271",["1271"] -person,0,person,1731,5190,"127012701270",["127012701270"] -person,0,person,1732,5193,"1269",["1269"] -person,0,person,1733,5196,"126812681268",["126812681268"] -person,0,person,1734,5199,"1267",["1267"] -person,0,person,1735,5202,"126612661266",["126612661266"] -person,0,person,1736,5205,"1265",["1265"] -person,0,person,1737,5208,"126412641264",["126412641264"] -person,0,person,1738,5211,"1263",["1263"] -person,0,person,1739,5214,"126212621262",["126212621262"] -person,0,person,1740,5217,"1261",["1261"] -person,0,person,1741,5220,"126012601260",["126012601260"] -person,0,person,1742,5223,"1259",["1259"] -person,0,person,1743,5226,"125812581258",["125812581258"] -person,0,person,1744,5229,"1257",["1257"] -person,0,person,1745,5232,"125612561256",["125612561256"] -person,0,person,1746,5235,"1255",["1255"] -person,0,person,1747,5238,"125412541254",["125412541254"] -person,0,person,1748,5241,"1253",["1253"] -person,0,person,1749,5244,"125212521252",["125212521252"] -person,0,person,1750,5247,"1251",["1251"] -person,0,person,1751,5250,"125012501250",["125012501250"] -person,0,person,1752,5253,"1249",["1249"] -person,0,person,1753,5256,"124812481248",["124812481248"] -person,0,person,1754,5259,"1247",["1247"] -person,0,person,1755,5262,"124612461246",["124612461246"] -person,0,person,1756,5265,"1245",["1245"] -person,0,person,1757,5268,"124412441244",["124412441244"] -person,0,person,1758,5271,"1243",["1243"] -person,0,person,1759,5274,"124212421242",["124212421242"] -person,0,person,1760,5277,"1241",["1241"] -person,0,person,1761,5280,"124012401240",["124012401240"] -person,0,person,1762,5283,"1239",["1239"] -person,0,person,1763,5286,"123812381238",["123812381238"] -person,0,person,1764,5289,"1237",["1237"] -person,0,person,1765,5292,"123612361236",["123612361236"] -person,0,person,1766,5295,"1235",["1235"] -person,0,person,1767,5298,"123412341234",["123412341234"] -person,0,person,1768,5301,"1233",["1233"] -person,0,person,1769,5304,"123212321232",["123212321232"] -person,0,person,1770,5307,"1231",["1231"] -person,0,person,1771,5310,"123012301230",["123012301230"] -person,0,person,1772,5313,"1229",["1229"] -person,0,person,1773,5316,"122812281228",["122812281228"] -person,0,person,1774,5319,"1227",["1227"] -person,0,person,1775,5322,"122612261226",["122612261226"] -person,0,person,1776,5325,"1225",["1225"] -person,0,person,1777,5328,"122412241224",["122412241224"] -person,0,person,1778,5331,"1223",["1223"] -person,0,person,1779,5334,"122212221222",["122212221222"] -person,0,person,1780,5337,"1221",["1221"] -person,0,person,1781,5340,"122012201220",["122012201220"] -person,0,person,1782,5343,"1219",["1219"] -person,0,person,1783,5346,"121812181218",["121812181218"] -person,0,person,1784,5349,"1217",["1217"] -person,0,person,1785,5352,"121612161216",["121612161216"] -person,0,person,1786,5355,"1215",["1215"] -person,0,person,1787,5358,"121412141214",["121412141214"] -person,0,person,1788,5361,"1213",["1213"] -person,0,person,1789,5364,"121212121212",["121212121212"] -person,0,person,1790,5367,"1211",["1211"] -person,0,person,1791,5370,"121012101210",["121012101210"] -person,0,person,1792,5373,"1209",["1209"] -person,0,person,1793,5376,"120812081208",["120812081208"] -person,0,person,1794,5379,"1207",["1207"] -person,0,person,1795,5382,"120612061206",["120612061206"] -person,0,person,1796,5385,"1205",["1205"] -person,0,person,1797,5388,"120412041204",["120412041204"] -person,0,person,1798,5391,"1203",["1203"] -person,0,person,1799,5394,"120212021202",["120212021202"] -person,0,person,1800,5397,"1201",["1201"] -person,0,person,1801,5400,"120012001200",["120012001200"] -person,0,person,1802,5403,"1199",["1199"] -person,0,person,1803,5406,"119811981198",["119811981198"] -person,0,person,1804,5409,"1197",["1197"] -person,0,person,1805,5412,"119611961196",["119611961196"] -person,0,person,1806,5415,"1195",["1195"] -person,0,person,1807,5418,"119411941194",["119411941194"] -person,0,person,1808,5421,"1193",["1193"] -person,0,person,1809,5424,"119211921192",["119211921192"] -person,0,person,1810,5427,"1191",["1191"] -person,0,person,1811,5430,"119011901190",["119011901190"] -person,0,person,1812,5433,"1189",["1189"] -person,0,person,1813,5436,"118811881188",["118811881188"] -person,0,person,1814,5439,"1187",["1187"] -person,0,person,1815,5442,"118611861186",["118611861186"] -person,0,person,1816,5445,"1185",["1185"] -person,0,person,1817,5448,"118411841184",["118411841184"] -person,0,person,1818,5451,"1183",["1183"] -person,0,person,1819,5454,"118211821182",["118211821182"] -person,0,person,1820,5457,"1181",["1181"] -person,0,person,1821,5460,"118011801180",["118011801180"] -person,0,person,1822,5463,"1179",["1179"] -person,0,person,1823,5466,"117811781178",["117811781178"] -person,0,person,1824,5469,"1177",["1177"] -person,0,person,1825,5472,"117611761176",["117611761176"] -person,0,person,1826,5475,"1175",["1175"] -person,0,person,1827,5478,"117411741174",["117411741174"] -person,0,person,1828,5481,"1173",["1173"] -person,0,person,1829,5484,"117211721172",["117211721172"] -person,0,person,1830,5487,"1171",["1171"] -person,0,person,1831,5490,"117011701170",["117011701170"] -person,0,person,1832,5493,"1169",["1169"] -person,0,person,1833,5496,"116811681168",["116811681168"] -person,0,person,1834,5499,"1167",["1167"] -person,0,person,1835,5502,"116611661166",["116611661166"] -person,0,person,1836,5505,"1165",["1165"] -person,0,person,1837,5508,"116411641164",["116411641164"] -person,0,person,1838,5511,"1163",["1163"] -person,0,person,1839,5514,"116211621162",["116211621162"] -person,0,person,1840,5517,"1161",["1161"] -person,0,person,1841,5520,"116011601160",["116011601160"] -person,0,person,1842,5523,"1159",["1159"] -person,0,person,1843,5526,"115811581158",["115811581158"] -person,0,person,1844,5529,"1157",["1157"] -person,0,person,1845,5532,"115611561156",["115611561156"] -person,0,person,1846,5535,"1155",["1155"] -person,0,person,1847,5538,"115411541154",["115411541154"] -person,0,person,1848,5541,"1153",["1153"] -person,0,person,1849,5544,"115211521152",["115211521152"] -person,0,person,1850,5547,"1151",["1151"] -person,0,person,1851,5550,"115011501150",["115011501150"] -person,0,person,1852,5553,"1149",["1149"] -person,0,person,1853,5556,"114811481148",["114811481148"] -person,0,person,1854,5559,"1147",["1147"] -person,0,person,1855,5562,"114611461146",["114611461146"] -person,0,person,1856,5565,"1145",["1145"] -person,0,person,1857,5568,"114411441144",["114411441144"] -person,0,person,1858,5571,"1143",["1143"] -person,0,person,1859,5574,"114211421142",["114211421142"] -person,0,person,1860,5577,"1141",["1141"] -person,0,person,1861,5580,"114011401140",["114011401140"] -person,0,person,1862,5583,"1139",["1139"] -person,0,person,1863,5586,"113811381138",["113811381138"] -person,0,person,1864,5589,"1137",["1137"] -person,0,person,1865,5592,"113611361136",["113611361136"] -person,0,person,1866,5595,"1135",["1135"] -person,0,person,1867,5598,"113411341134",["113411341134"] -person,0,person,1868,5601,"1133",["1133"] -person,0,person,1869,5604,"113211321132",["113211321132"] -person,0,person,1870,5607,"1131",["1131"] -person,0,person,1871,5610,"113011301130",["113011301130"] -person,0,person,1872,5613,"1129",["1129"] -person,0,person,1873,5616,"112811281128",["112811281128"] -person,0,person,1874,5619,"1127",["1127"] -person,0,person,1875,5622,"112611261126",["112611261126"] -person,0,person,1876,5625,"1125",["1125"] -person,0,person,1877,5628,"112411241124",["112411241124"] -person,0,person,1878,5631,"1123",["1123"] -person,0,person,1879,5634,"112211221122",["112211221122"] -person,0,person,1880,5637,"1121",["1121"] -person,0,person,1881,5640,"112011201120",["112011201120"] -person,0,person,1882,5643,"1119",["1119"] -person,0,person,1883,5646,"111811181118",["111811181118"] -person,0,person,1884,5649,"1117",["1117"] -person,0,person,1885,5652,"111611161116",["111611161116"] -person,0,person,1886,5655,"1115",["1115"] -person,0,person,1887,5658,"111411141114",["111411141114"] -person,0,person,1888,5661,"1113",["1113"] -person,0,person,1889,5664,"111211121112",["111211121112"] -person,0,person,1890,5667,"1111",["1111"] -person,0,person,1891,5670,"111011101110",["111011101110"] -person,0,person,1892,5673,"1109",["1109"] -person,0,person,1893,5676,"110811081108",["110811081108"] -person,0,person,1894,5679,"1107",["1107"] -person,0,person,1895,5682,"110611061106",["110611061106"] -person,0,person,1896,5685,"1105",["1105"] -person,0,person,1897,5688,"110411041104",["110411041104"] -person,0,person,1898,5691,"1103",["1103"] -person,0,person,1899,5694,"110211021102",["110211021102"] -person,0,person,1900,5697,"1101",["1101"] -person,0,person,1901,5700,"110011001100",["110011001100"] -person,0,person,1902,5703,"1099",["1099"] -person,0,person,1903,5706,"109810981098",["109810981098"] -person,0,person,1904,5709,"1097",["1097"] -person,0,person,1905,5712,"109610961096",["109610961096"] -person,0,person,1906,5715,"1095",["1095"] -person,0,person,1907,5718,"109410941094",["109410941094"] -person,0,person,1908,5721,"1093",["1093"] -person,0,person,1909,5724,"109210921092",["109210921092"] -person,0,person,1910,5727,"1091",["1091"] -person,0,person,1911,5730,"109010901090",["109010901090"] -person,0,person,1912,5733,"1089",["1089"] -person,0,person,1913,5736,"108810881088",["108810881088"] -person,0,person,1914,5739,"1087",["1087"] -person,0,person,1915,5742,"108610861086",["108610861086"] -person,0,person,1916,5745,"1085",["1085"] -person,0,person,1917,5748,"108410841084",["108410841084"] -person,0,person,1918,5751,"1083",["1083"] -person,0,person,1919,5754,"108210821082",["108210821082"] -person,0,person,1920,5757,"1081",["1081"] -person,0,person,1921,5760,"108010801080",["108010801080"] -person,0,person,1922,5763,"1079",["1079"] -person,0,person,1923,5766,"107810781078",["107810781078"] -person,0,person,1924,5769,"1077",["1077"] -person,0,person,1925,5772,"107610761076",["107610761076"] -person,0,person,1926,5775,"1075",["1075"] -person,0,person,1927,5778,"107410741074",["107410741074"] -person,0,person,1928,5781,"1073",["1073"] -person,0,person,1929,5784,"107210721072",["107210721072"] -person,0,person,1930,5787,"1071",["1071"] -person,0,person,1931,5790,"107010701070",["107010701070"] -person,0,person,1932,5793,"1069",["1069"] -person,0,person,1933,5796,"106810681068",["106810681068"] -person,0,person,1934,5799,"1067",["1067"] -person,0,person,1935,5802,"106610661066",["106610661066"] -person,0,person,1936,5805,"1065",["1065"] -person,0,person,1937,5808,"106410641064",["106410641064"] -person,0,person,1938,5811,"1063",["1063"] -person,0,person,1939,5814,"106210621062",["106210621062"] -person,0,person,1940,5817,"1061",["1061"] -person,0,person,1941,5820,"106010601060",["106010601060"] -person,0,person,1942,5823,"1059",["1059"] -person,0,person,1943,5826,"105810581058",["105810581058"] -person,0,person,1944,5829,"1057",["1057"] -person,0,person,1945,5832,"105610561056",["105610561056"] -person,0,person,1946,5835,"1055",["1055"] -person,0,person,1947,5838,"105410541054",["105410541054"] -person,0,person,1948,5841,"1053",["1053"] -person,0,person,1949,5844,"105210521052",["105210521052"] -person,0,person,1950,5847,"1051",["1051"] -person,0,person,1951,5850,"105010501050",["105010501050"] -person,0,person,1952,5853,"1049",["1049"] -person,0,person,1953,5856,"104810481048",["104810481048"] -person,0,person,1954,5859,"1047",["1047"] -person,0,person,1955,5862,"104610461046",["104610461046"] -person,0,person,1956,5865,"1045",["1045"] -person,0,person,1957,5868,"104410441044",["104410441044"] -person,0,person,1958,5871,"1043",["1043"] -person,0,person,1959,5874,"104210421042",["104210421042"] -person,0,person,1960,5877,"1041",["1041"] -person,0,person,1961,5880,"104010401040",["104010401040"] -person,0,person,1962,5883,"1039",["1039"] -person,0,person,1963,5886,"103810381038",["103810381038"] -person,0,person,1964,5889,"1037",["1037"] -person,0,person,1965,5892,"103610361036",["103610361036"] -person,0,person,1966,5895,"1035",["1035"] -person,0,person,1967,5898,"103410341034",["103410341034"] -person,0,person,1968,5901,"1033",["1033"] -person,0,person,1969,5904,"103210321032",["103210321032"] -person,0,person,1970,5907,"1031",["1031"] -person,0,person,1971,5910,"103010301030",["103010301030"] -person,0,person,1972,5913,"1029",["1029"] -person,0,person,1973,5916,"102810281028",["102810281028"] -person,0,person,1974,5919,"1027",["1027"] -person,0,person,1975,5922,"102610261026",["102610261026"] -person,0,person,1976,5925,"1025",["1025"] -person,0,person,1977,5928,"102410241024",["102410241024"] -person,0,person,1978,5931,"1023",["1023"] -person,0,person,1979,5934,"102210221022",["102210221022"] -person,0,person,1980,5937,"1021",["1021"] -person,0,person,1981,5940,"102010201020",["102010201020"] -person,0,person,1982,5943,"1019",["1019"] -person,0,person,1983,5946,"101810181018",["101810181018"] -person,0,person,1984,5949,"1017",["1017"] -person,0,person,1985,5952,"101610161016",["101610161016"] -person,0,person,1986,5955,"1015",["1015"] -person,0,person,1987,5958,"101410141014",["101410141014"] -person,0,person,1988,5961,"1013",["1013"] -person,0,person,1989,5964,"101210121012",["101210121012"] -person,0,person,1990,5967,"1011",["1011"] -person,0,person,1991,5970,"101010101010",["101010101010"] -person,0,person,1992,5973,"1009",["1009"] -person,0,person,1993,5976,"100810081008",["100810081008"] -person,0,person,1994,5979,"1007",["1007"] -person,0,person,1995,5982,"100610061006",["100610061006"] -person,0,person,1996,5985,"1005",["1005"] -person,0,person,1997,5988,"100410041004",["100410041004"] -person,0,person,1998,5991,"1003",["1003"] -person,0,person,1999,5994,"100210021002",["100210021002"] -person,0,person,2000,5997,"1001",["1001"] -person,0,person,2001,6000,"100010001000",["100010001000"] -person,0,person,2002,6003,"999",["999"] -person,0,person,2003,6006,"998998998",["998998998"] -person,0,person,2004,6009,"997",["997"] -person,0,person,2005,6012,"996996996",["996996996"] -person,0,person,2006,6015,"995",["995"] -person,0,person,2007,6018,"994994994",["994994994"] -person,0,person,2008,6021,"993",["993"] -person,0,person,2009,6024,"992992992",["992992992"] -person,0,person,2010,6027,"991",["991"] -person,0,person,2011,6030,"990990990",["990990990"] -person,0,person,2012,6033,"989",["989"] -person,0,person,2013,6036,"988988988",["988988988"] -person,0,person,2014,6039,"987",["987"] -person,0,person,2015,6042,"986986986",["986986986"] -person,0,person,2016,6045,"985",["985"] -person,0,person,2017,6048,"984984984",["984984984"] -person,0,person,2018,6051,"983",["983"] -person,0,person,2019,6054,"982982982",["982982982"] -person,0,person,2020,6057,"981",["981"] -person,0,person,2021,6060,"980980980",["980980980"] -person,0,person,2022,6063,"979",["979"] -person,0,person,2023,6066,"978978978",["978978978"] -person,0,person,2024,6069,"977",["977"] -person,0,person,2025,6072,"976976976",["976976976"] -person,0,person,2026,6075,"975",["975"] -person,0,person,2027,6078,"974974974",["974974974"] -person,0,person,2028,6081,"973",["973"] -person,0,person,2029,6084,"972972972",["972972972"] -person,0,person,2030,6087,"971",["971"] -person,0,person,2031,6090,"970970970",["970970970"] -person,0,person,2032,6093,"969",["969"] -person,0,person,2033,6096,"968968968",["968968968"] -person,0,person,2034,6099,"967",["967"] -person,0,person,2035,6102,"966966966",["966966966"] -person,0,person,2036,6105,"965",["965"] -person,0,person,2037,6108,"964964964",["964964964"] -person,0,person,2038,6111,"963",["963"] -person,0,person,2039,6114,"962962962",["962962962"] -person,0,person,2040,6117,"961",["961"] -person,0,person,2041,6120,"960960960",["960960960"] -person,0,person,2042,6123,"959",["959"] -person,0,person,2043,6126,"958958958",["958958958"] -person,0,person,2044,6129,"957",["957"] -person,0,person,2045,6132,"956956956",["956956956"] -person,0,person,2046,6135,"955",["955"] -person,0,person,2047,6138,"954954954",["954954954"] -person,0,person,2048,6141,"953",["953"] -person,0,person,2049,6144,"952952952",["952952952"] -person,0,person,2050,6147,"951",["951"] -person,0,person,2051,6150,"950950950",["950950950"] -person,0,person,2052,6153,"949",["949"] -person,0,person,2053,6156,"948948948",["948948948"] -person,0,person,2054,6159,"947",["947"] -person,0,person,2055,6162,"946946946",["946946946"] -person,0,person,2056,6165,"945",["945"] -person,0,person,2057,6168,"944944944",["944944944"] -person,0,person,2058,6171,"943",["943"] -person,0,person,2059,6174,"942942942",["942942942"] -person,0,person,2060,6177,"941",["941"] -person,0,person,2061,6180,"940940940",["940940940"] -person,0,person,2062,6183,"939",["939"] -person,0,person,2063,6186,"938938938",["938938938"] -person,0,person,2064,6189,"937",["937"] -person,0,person,2065,6192,"936936936",["936936936"] -person,0,person,2066,6195,"935",["935"] -person,0,person,2067,6198,"934934934",["934934934"] -person,0,person,2068,6201,"933",["933"] -person,0,person,2069,6204,"932932932",["932932932"] -person,0,person,2070,6207,"931",["931"] -person,0,person,2071,6210,"930930930",["930930930"] -person,0,person,2072,6213,"929",["929"] -person,0,person,2073,6216,"928928928",["928928928"] -person,0,person,2074,6219,"927",["927"] -person,0,person,2075,6222,"926926926",["926926926"] -person,0,person,2076,6225,"925",["925"] -person,0,person,2077,6228,"924924924",["924924924"] -person,0,person,2078,6231,"923",["923"] -person,0,person,2079,6234,"922922922",["922922922"] -person,0,person,2080,6237,"921",["921"] -person,0,person,2081,6240,"920920920",["920920920"] -person,0,person,2082,6243,"919",["919"] -person,0,person,2083,6246,"918918918",["918918918"] -person,0,person,2084,6249,"917",["917"] -person,0,person,2085,6252,"916916916",["916916916"] -person,0,person,2086,6255,"915",["915"] -person,0,person,2087,6258,"914914914",["914914914"] -person,0,person,2088,6261,"913",["913"] -person,0,person,2089,6264,"912912912",["912912912"] -person,0,person,2090,6267,"911",["911"] -person,0,person,2091,6270,"910910910",["910910910"] -person,0,person,2092,6273,"909",["909"] -person,0,person,2093,6276,"908908908",["908908908"] -person,0,person,2094,6279,"907",["907"] -person,0,person,2095,6282,"906906906",["906906906"] -person,0,person,2096,6285,"905",["905"] -person,0,person,2097,6288,"904904904",["904904904"] -person,0,person,2098,6291,"903",["903"] -person,0,person,2099,6294,"902902902",["902902902"] -person,0,person,2100,6297,"901",["901"] -person,0,person,2101,6300,"900900900",["900900900"] -person,0,person,2102,6303,"899",["899"] -person,0,person,2103,6306,"898898898",["898898898"] -person,0,person,2104,6309,"897",["897"] -person,0,person,2105,6312,"896896896",["896896896"] -person,0,person,2106,6315,"895",["895"] -person,0,person,2107,6318,"894894894",["894894894"] -person,0,person,2108,6321,"893",["893"] -person,0,person,2109,6324,"892892892",["892892892"] -person,0,person,2110,6327,"891",["891"] -person,0,person,2111,6330,"890890890",["890890890"] -person,0,person,2112,6333,"889",["889"] -person,0,person,2113,6336,"888888888",["888888888"] -person,0,person,2114,6339,"887",["887"] -person,0,person,2115,6342,"886886886",["886886886"] -person,0,person,2116,6345,"885",["885"] -person,0,person,2117,6348,"884884884",["884884884"] -person,0,person,2118,6351,"883",["883"] -person,0,person,2119,6354,"882882882",["882882882"] -person,0,person,2120,6357,"881",["881"] -person,0,person,2121,6360,"880880880",["880880880"] -person,0,person,2122,6363,"879",["879"] -person,0,person,2123,6366,"878878878",["878878878"] -person,0,person,2124,6369,"877",["877"] -person,0,person,2125,6372,"876876876",["876876876"] -person,0,person,2126,6375,"875",["875"] -person,0,person,2127,6378,"874874874",["874874874"] -person,0,person,2128,6381,"873",["873"] -person,0,person,2129,6384,"872872872",["872872872"] -person,0,person,2130,6387,"871",["871"] -person,0,person,2131,6390,"870870870",["870870870"] -person,0,person,2132,6393,"869",["869"] -person,0,person,2133,6396,"868868868",["868868868"] -person,0,person,2134,6399,"867",["867"] -person,0,person,2135,6402,"866866866",["866866866"] -person,0,person,2136,6405,"865",["865"] -person,0,person,2137,6408,"864864864",["864864864"] -person,0,person,2138,6411,"863",["863"] -person,0,person,2139,6414,"862862862",["862862862"] -person,0,person,2140,6417,"861",["861"] -person,0,person,2141,6420,"860860860",["860860860"] -person,0,person,2142,6423,"859",["859"] -person,0,person,2143,6426,"858858858",["858858858"] -person,0,person,2144,6429,"857",["857"] -person,0,person,2145,6432,"856856856",["856856856"] -person,0,person,2146,6435,"855",["855"] -person,0,person,2147,6438,"854854854",["854854854"] -person,0,person,2148,6441,"853",["853"] -person,0,person,2149,6444,"852852852",["852852852"] -person,0,person,2150,6447,"851",["851"] -person,0,person,2151,6450,"850850850",["850850850"] -person,0,person,2152,6453,"849",["849"] -person,0,person,2153,6456,"848848848",["848848848"] -person,0,person,2154,6459,"847",["847"] -person,0,person,2155,6462,"846846846",["846846846"] -person,0,person,2156,6465,"845",["845"] -person,0,person,2157,6468,"844844844",["844844844"] -person,0,person,2158,6471,"843",["843"] -person,0,person,2159,6474,"842842842",["842842842"] -person,0,person,2160,6477,"841",["841"] -person,0,person,2161,6480,"840840840",["840840840"] -person,0,person,2162,6483,"839",["839"] -person,0,person,2163,6486,"838838838",["838838838"] -person,0,person,2164,6489,"837",["837"] -person,0,person,2165,6492,"836836836",["836836836"] -person,0,person,2166,6495,"835",["835"] -person,0,person,2167,6498,"834834834",["834834834"] -person,0,person,2168,6501,"833",["833"] -person,0,person,2169,6504,"832832832",["832832832"] -person,0,person,2170,6507,"831",["831"] -person,0,person,2171,6510,"830830830",["830830830"] -person,0,person,2172,6513,"829",["829"] -person,0,person,2173,6516,"828828828",["828828828"] -person,0,person,2174,6519,"827",["827"] -person,0,person,2175,6522,"826826826",["826826826"] -person,0,person,2176,6525,"825",["825"] -person,0,person,2177,6528,"824824824",["824824824"] -person,0,person,2178,6531,"823",["823"] -person,0,person,2179,6534,"822822822",["822822822"] -person,0,person,2180,6537,"821",["821"] -person,0,person,2181,6540,"820820820",["820820820"] -person,0,person,2182,6543,"819",["819"] -person,0,person,2183,6546,"818818818",["818818818"] -person,0,person,2184,6549,"817",["817"] -person,0,person,2185,6552,"816816816",["816816816"] -person,0,person,2186,6555,"815",["815"] -person,0,person,2187,6558,"814814814",["814814814"] -person,0,person,2188,6561,"813",["813"] -person,0,person,2189,6564,"812812812",["812812812"] -person,0,person,2190,6567,"811",["811"] -person,0,person,2191,6570,"810810810",["810810810"] -person,0,person,2192,6573,"809",["809"] -person,0,person,2193,6576,"808808808",["808808808"] -person,0,person,2194,6579,"807",["807"] -person,0,person,2195,6582,"806806806",["806806806"] -person,0,person,2196,6585,"805",["805"] -person,0,person,2197,6588,"804804804",["804804804"] -person,0,person,2198,6591,"803",["803"] -person,0,person,2199,6594,"802802802",["802802802"] -person,0,person,2200,6597,"801",["801"] -person,0,person,2201,6600,"800800800",["800800800"] -person,0,person,2202,6603,"799",["799"] -person,0,person,2203,6606,"798798798",["798798798"] -person,0,person,2204,6609,"797",["797"] -person,0,person,2205,6612,"796796796",["796796796"] -person,0,person,2206,6615,"795",["795"] -person,0,person,2207,6618,"794794794",["794794794"] -person,0,person,2208,6621,"793",["793"] -person,0,person,2209,6624,"792792792",["792792792"] -person,0,person,2210,6627,"791",["791"] -person,0,person,2211,6630,"790790790",["790790790"] -person,0,person,2212,6633,"789",["789"] -person,0,person,2213,6636,"788788788",["788788788"] -person,0,person,2214,6639,"787",["787"] -person,0,person,2215,6642,"786786786",["786786786"] -person,0,person,2216,6645,"785",["785"] -person,0,person,2217,6648,"784784784",["784784784"] -person,0,person,2218,6651,"783",["783"] -person,0,person,2219,6654,"782782782",["782782782"] -person,0,person,2220,6657,"781",["781"] -person,0,person,2221,6660,"780780780",["780780780"] -person,0,person,2222,6663,"779",["779"] -person,0,person,2223,6666,"778778778",["778778778"] -person,0,person,2224,6669,"777",["777"] -person,0,person,2225,6672,"776776776",["776776776"] -person,0,person,2226,6675,"775",["775"] -person,0,person,2227,6678,"774774774",["774774774"] -person,0,person,2228,6681,"773",["773"] -person,0,person,2229,6684,"772772772",["772772772"] -person,0,person,2230,6687,"771",["771"] -person,0,person,2231,6690,"770770770",["770770770"] -person,0,person,2232,6693,"769",["769"] -person,0,person,2233,6696,"768768768",["768768768"] -person,0,person,2234,6699,"767",["767"] -person,0,person,2235,6702,"766766766",["766766766"] -person,0,person,2236,6705,"765",["765"] -person,0,person,2237,6708,"764764764",["764764764"] -person,0,person,2238,6711,"763",["763"] -person,0,person,2239,6714,"762762762",["762762762"] -person,0,person,2240,6717,"761",["761"] -person,0,person,2241,6720,"760760760",["760760760"] -person,0,person,2242,6723,"759",["759"] -person,0,person,2243,6726,"758758758",["758758758"] -person,0,person,2244,6729,"757",["757"] -person,0,person,2245,6732,"756756756",["756756756"] -person,0,person,2246,6735,"755",["755"] -person,0,person,2247,6738,"754754754",["754754754"] -person,0,person,2248,6741,"753",["753"] -person,0,person,2249,6744,"752752752",["752752752"] -person,0,person,2250,6747,"751",["751"] -person,0,person,2251,6750,"750750750",["750750750"] -person,0,person,2252,6753,"749",["749"] -person,0,person,2253,6756,"748748748",["748748748"] -person,0,person,2254,6759,"747",["747"] -person,0,person,2255,6762,"746746746",["746746746"] -person,0,person,2256,6765,"745",["745"] -person,0,person,2257,6768,"744744744",["744744744"] -person,0,person,2258,6771,"743",["743"] -person,0,person,2259,6774,"742742742",["742742742"] -person,0,person,2260,6777,"741",["741"] -person,0,person,2261,6780,"740740740",["740740740"] -person,0,person,2262,6783,"739",["739"] -person,0,person,2263,6786,"738738738",["738738738"] -person,0,person,2264,6789,"737",["737"] -person,0,person,2265,6792,"736736736",["736736736"] -person,0,person,2266,6795,"735",["735"] -person,0,person,2267,6798,"734734734",["734734734"] -person,0,person,2268,6801,"733",["733"] -person,0,person,2269,6804,"732732732",["732732732"] -person,0,person,2270,6807,"731",["731"] -person,0,person,2271,6810,"730730730",["730730730"] -person,0,person,2272,6813,"729",["729"] -person,0,person,2273,6816,"728728728",["728728728"] -person,0,person,2274,6819,"727",["727"] -person,0,person,2275,6822,"726726726",["726726726"] -person,0,person,2276,6825,"725",["725"] -person,0,person,2277,6828,"724724724",["724724724"] -person,0,person,2278,6831,"723",["723"] -person,0,person,2279,6834,"722722722",["722722722"] -person,0,person,2280,6837,"721",["721"] -person,0,person,2281,6840,"720720720",["720720720"] -person,0,person,2282,6843,"719",["719"] -person,0,person,2283,6846,"718718718",["718718718"] -person,0,person,2284,6849,"717",["717"] -person,0,person,2285,6852,"716716716",["716716716"] -person,0,person,2286,6855,"715",["715"] -person,0,person,2287,6858,"714714714",["714714714"] -person,0,person,2288,6861,"713",["713"] -person,0,person,2289,6864,"712712712",["712712712"] -person,0,person,2290,6867,"711",["711"] -person,0,person,2291,6870,"710710710",["710710710"] -person,0,person,2292,6873,"709",["709"] -person,0,person,2293,6876,"708708708",["708708708"] -person,0,person,2294,6879,"707",["707"] -person,0,person,2295,6882,"706706706",["706706706"] -person,0,person,2296,6885,"705",["705"] -person,0,person,2297,6888,"704704704",["704704704"] -person,0,person,2298,6891,"703",["703"] -person,0,person,2299,6894,"702702702",["702702702"] -person,0,person,2300,6897,"701",["701"] -person,0,person,2301,6900,"700700700",["700700700"] -person,0,person,2302,6903,"699",["699"] -person,0,person,2303,6906,"698698698",["698698698"] -person,0,person,2304,6909,"697",["697"] -person,0,person,2305,6912,"696696696",["696696696"] -person,0,person,2306,6915,"695",["695"] -person,0,person,2307,6918,"694694694",["694694694"] -person,0,person,2308,6921,"693",["693"] -person,0,person,2309,6924,"692692692",["692692692"] -person,0,person,2310,6927,"691",["691"] -person,0,person,2311,6930,"690690690",["690690690"] -person,0,person,2312,6933,"689",["689"] -person,0,person,2313,6936,"688688688",["688688688"] -person,0,person,2314,6939,"687",["687"] -person,0,person,2315,6942,"686686686",["686686686"] -person,0,person,2316,6945,"685",["685"] -person,0,person,2317,6948,"684684684",["684684684"] -person,0,person,2318,6951,"683",["683"] -person,0,person,2319,6954,"682682682",["682682682"] -person,0,person,2320,6957,"681",["681"] -person,0,person,2321,6960,"680680680",["680680680"] -person,0,person,2322,6963,"679",["679"] -person,0,person,2323,6966,"678678678",["678678678"] -person,0,person,2324,6969,"677",["677"] -person,0,person,2325,6972,"676676676",["676676676"] -person,0,person,2326,6975,"675",["675"] -person,0,person,2327,6978,"674674674",["674674674"] -person,0,person,2328,6981,"673",["673"] -person,0,person,2329,6984,"672672672",["672672672"] -person,0,person,2330,6987,"671",["671"] -person,0,person,2331,6990,"670670670",["670670670"] -person,0,person,2332,6993,"669",["669"] -person,0,person,2333,6996,"668668668",["668668668"] -person,0,person,2334,6999,"667",["667"] -person,0,person,2335,7002,"666666666",["666666666"] -person,0,person,2336,7005,"665",["665"] -person,0,person,2337,7008,"664664664",["664664664"] -person,0,person,2338,7011,"663",["663"] -person,0,person,2339,7014,"662662662",["662662662"] -person,0,person,2340,7017,"661",["661"] -person,0,person,2341,7020,"660660660",["660660660"] -person,0,person,2342,7023,"659",["659"] -person,0,person,2343,7026,"658658658",["658658658"] -person,0,person,2344,7029,"657",["657"] -person,0,person,2345,7032,"656656656",["656656656"] -person,0,person,2346,7035,"655",["655"] -person,0,person,2347,7038,"654654654",["654654654"] -person,0,person,2348,7041,"653",["653"] -person,0,person,2349,7044,"652652652",["652652652"] -person,0,person,2350,7047,"651",["651"] -person,0,person,2351,7050,"650650650",["650650650"] -person,0,person,2352,7053,"649",["649"] -person,0,person,2353,7056,"648648648",["648648648"] -person,0,person,2354,7059,"647",["647"] -person,0,person,2355,7062,"646646646",["646646646"] -person,0,person,2356,7065,"645",["645"] -person,0,person,2357,7068,"644644644",["644644644"] -person,0,person,2358,7071,"643",["643"] -person,0,person,2359,7074,"642642642",["642642642"] -person,0,person,2360,7077,"641",["641"] -person,0,person,2361,7080,"640640640",["640640640"] -person,0,person,2362,7083,"639",["639"] -person,0,person,2363,7086,"638638638",["638638638"] -person,0,person,2364,7089,"637",["637"] -person,0,person,2365,7092,"636636636",["636636636"] -person,0,person,2366,7095,"635",["635"] -person,0,person,2367,7098,"634634634",["634634634"] -person,0,person,2368,7101,"633",["633"] -person,0,person,2369,7104,"632632632",["632632632"] -person,0,person,2370,7107,"631",["631"] -person,0,person,2371,7110,"630630630",["630630630"] -person,0,person,2372,7113,"629",["629"] -person,0,person,2373,7116,"628628628",["628628628"] -person,0,person,2374,7119,"627",["627"] -person,0,person,2375,7122,"626626626",["626626626"] -person,0,person,2376,7125,"625",["625"] -person,0,person,2377,7128,"624624624",["624624624"] -person,0,person,2378,7131,"623",["623"] -person,0,person,2379,7134,"622622622",["622622622"] -person,0,person,2380,7137,"621",["621"] -person,0,person,2381,7140,"620620620",["620620620"] -person,0,person,2382,7143,"619",["619"] -person,0,person,2383,7146,"618618618",["618618618"] -person,0,person,2384,7149,"617",["617"] -person,0,person,2385,7152,"616616616",["616616616"] -person,0,person,2386,7155,"615",["615"] -person,0,person,2387,7158,"614614614",["614614614"] -person,0,person,2388,7161,"613",["613"] -person,0,person,2389,7164,"612612612",["612612612"] -person,0,person,2390,7167,"611",["611"] -person,0,person,2391,7170,"610610610",["610610610"] -person,0,person,2392,7173,"609",["609"] -person,0,person,2393,7176,"608608608",["608608608"] -person,0,person,2394,7179,"607",["607"] -person,0,person,2395,7182,"606606606",["606606606"] -person,0,person,2396,7185,"605",["605"] -person,0,person,2397,7188,"604604604",["604604604"] -person,0,person,2398,7191,"603",["603"] -person,0,person,2399,7194,"602602602",["602602602"] -person,0,person,2400,7197,"601",["601"] -person,0,person,2401,7200,"600600600",["600600600"] -person,0,person,2402,7203,"599",["599"] -person,0,person,2403,7206,"598598598",["598598598"] -person,0,person,2404,7209,"597",["597"] -person,0,person,2405,7212,"596596596",["596596596"] -person,0,person,2406,7215,"595",["595"] -person,0,person,2407,7218,"594594594",["594594594"] -person,0,person,2408,7221,"593",["593"] -person,0,person,2409,7224,"592592592",["592592592"] -person,0,person,2410,7227,"591",["591"] -person,0,person,2411,7230,"590590590",["590590590"] -person,0,person,2412,7233,"589",["589"] -person,0,person,2413,7236,"588588588",["588588588"] -person,0,person,2414,7239,"587",["587"] -person,0,person,2415,7242,"586586586",["586586586"] -person,0,person,2416,7245,"585",["585"] -person,0,person,2417,7248,"584584584",["584584584"] -person,0,person,2418,7251,"583",["583"] -person,0,person,2419,7254,"582582582",["582582582"] -person,0,person,2420,7257,"581",["581"] -person,0,person,2421,7260,"580580580",["580580580"] -person,0,person,2422,7263,"579",["579"] -person,0,person,2423,7266,"578578578",["578578578"] -person,0,person,2424,7269,"577",["577"] -person,0,person,2425,7272,"576576576",["576576576"] -person,0,person,2426,7275,"575",["575"] -person,0,person,2427,7278,"574574574",["574574574"] -person,0,person,2428,7281,"573",["573"] -person,0,person,2429,7284,"572572572",["572572572"] -person,0,person,2430,7287,"571",["571"] -person,0,person,2431,7290,"570570570",["570570570"] -person,0,person,2432,7293,"569",["569"] -person,0,person,2433,7296,"568568568",["568568568"] -person,0,person,2434,7299,"567",["567"] -person,0,person,2435,7302,"566566566",["566566566"] -person,0,person,2436,7305,"565",["565"] -person,0,person,2437,7308,"564564564",["564564564"] -person,0,person,2438,7311,"563",["563"] -person,0,person,2439,7314,"562562562",["562562562"] -person,0,person,2440,7317,"561",["561"] -person,0,person,2441,7320,"560560560",["560560560"] -person,0,person,2442,7323,"559",["559"] -person,0,person,2443,7326,"558558558",["558558558"] -person,0,person,2444,7329,"557",["557"] -person,0,person,2445,7332,"556556556",["556556556"] -person,0,person,2446,7335,"555",["555"] -person,0,person,2447,7338,"554554554",["554554554"] -person,0,person,2448,7341,"553",["553"] -person,0,person,2449,7344,"552552552",["552552552"] -person,0,person,2450,7347,"551",["551"] -person,0,person,2451,7350,"550550550",["550550550"] -person,0,person,2452,7353,"549",["549"] -person,0,person,2453,7356,"548548548",["548548548"] -person,0,person,2454,7359,"547",["547"] -person,0,person,2455,7362,"546546546",["546546546"] -person,0,person,2456,7365,"545",["545"] -person,0,person,2457,7368,"544544544",["544544544"] -person,0,person,2458,7371,"543",["543"] -person,0,person,2459,7374,"542542542",["542542542"] -person,0,person,2460,7377,"541",["541"] -person,0,person,2461,7380,"540540540",["540540540"] -person,0,person,2462,7383,"539",["539"] -person,0,person,2463,7386,"538538538",["538538538"] -person,0,person,2464,7389,"537",["537"] -person,0,person,2465,7392,"536536536",["536536536"] -person,0,person,2466,7395,"535",["535"] -person,0,person,2467,7398,"534534534",["534534534"] -person,0,person,2468,7401,"533",["533"] -person,0,person,2469,7404,"532532532",["532532532"] -person,0,person,2470,7407,"531",["531"] -person,0,person,2471,7410,"530530530",["530530530"] -person,0,person,2472,7413,"529",["529"] -person,0,person,2473,7416,"528528528",["528528528"] -person,0,person,2474,7419,"527",["527"] -person,0,person,2475,7422,"526526526",["526526526"] -person,0,person,2476,7425,"525",["525"] -person,0,person,2477,7428,"524524524",["524524524"] -person,0,person,2478,7431,"523",["523"] -person,0,person,2479,7434,"522522522",["522522522"] -person,0,person,2480,7437,"521",["521"] -person,0,person,2481,7440,"520520520",["520520520"] -person,0,person,2482,7443,"519",["519"] -person,0,person,2483,7446,"518518518",["518518518"] -person,0,person,2484,7449,"517",["517"] -person,0,person,2485,7452,"516516516",["516516516"] -person,0,person,2486,7455,"515",["515"] -person,0,person,2487,7458,"514514514",["514514514"] -person,0,person,2488,7461,"513",["513"] -person,0,person,2489,7464,"512512512",["512512512"] -person,0,person,2490,7467,"511",["511"] -person,0,person,2491,7470,"510510510",["510510510"] -person,0,person,2492,7473,"509",["509"] -person,0,person,2493,7476,"508508508",["508508508"] -person,0,person,2494,7479,"507",["507"] -person,0,person,2495,7482,"506506506",["506506506"] -person,0,person,2496,7485,"505",["505"] -person,0,person,2497,7488,"504504504",["504504504"] -person,0,person,2498,7491,"503",["503"] -person,0,person,2499,7494,"502502502",["502502502"] -person,0,person,2500,7497,"501",["501"] -animal,0,person,0,0,"100010001000",["100010001000"] -animal,1,person,0,1,"999",["999"] -animal,2,person,0,2,"998998998",["998998998"] -animal,3,person,0,3,"997",["997"] -animal,4,person,0,4,"996996996",["996996996"] -animal,5,person,0,5,"995",["995"] -animal,6,person,0,6,"994994994",["994994994"] -animal,7,person,0,7,"993",["993"] -animal,8,person,0,8,"992992992",["992992992"] -animal,9,person,0,9,"991",["991"] -animal,10,person,0,10,"990990990",["990990990"] -animal,11,person,0,11,"989",["989"] -animal,12,person,0,12,"988988988",["988988988"] -animal,13,person,0,13,"987",["987"] -animal,14,person,0,14,"986986986",["986986986"] -animal,15,person,0,15,"985",["985"] -animal,16,person,0,16,"984984984",["984984984"] -animal,17,person,0,17,"983",["983"] -animal,18,person,0,18,"982982982",["982982982"] -animal,19,person,0,19,"981",["981"] -animal,20,person,0,20,"980980980",["980980980"] -animal,21,person,0,21,"979",["979"] -animal,22,person,0,22,"978978978",["978978978"] -animal,23,person,0,23,"977",["977"] -animal,24,person,0,24,"976976976",["976976976"] -animal,25,person,0,25,"975",["975"] -animal,26,person,0,26,"974974974",["974974974"] -animal,27,person,0,27,"973",["973"] -animal,28,person,0,28,"972972972",["972972972"] -animal,29,person,0,29,"971",["971"] -animal,30,person,0,30,"970970970",["970970970"] -animal,31,person,0,31,"969",["969"] -animal,32,person,0,32,"968968968",["968968968"] -animal,33,person,0,33,"967",["967"] -animal,34,person,0,34,"966966966",["966966966"] -animal,35,person,0,35,"965",["965"] -animal,36,person,0,36,"964964964",["964964964"] -animal,37,person,0,37,"963",["963"] -animal,38,person,0,38,"962962962",["962962962"] -animal,39,person,0,39,"961",["961"] -animal,40,person,0,40,"960960960",["960960960"] -animal,41,person,0,41,"959",["959"] -animal,42,person,0,42,"958958958",["958958958"] -animal,43,person,0,43,"957",["957"] -animal,44,person,0,44,"956956956",["956956956"] -animal,45,person,0,45,"955",["955"] -animal,46,person,0,46,"954954954",["954954954"] -animal,47,person,0,47,"953",["953"] -animal,48,person,0,48,"952952952",["952952952"] -animal,49,person,0,49,"951",["951"] -animal,50,person,0,50,"950950950",["950950950"] +person,0,person,1,0,300030003000,"[300030003000]" +person,0,person,2,3,2999,"[2999]" +person,0,person,3,6,299829982998,"[299829982998]" +person,0,person,4,9,2997,"[2997]" +person,0,person,5,12,299629962996,"[299629962996]" +person,0,person,6,15,2995,"[2995]" +person,0,person,7,18,299429942994,"[299429942994]" +person,0,person,8,21,2993,"[2993]" +person,0,person,9,24,299229922992,"[299229922992]" +person,0,person,10,27,2991,"[2991]" +person,0,person,11,30,299029902990,"[299029902990]" +person,0,person,12,33,2989,"[2989]" +person,0,person,13,36,298829882988,"[298829882988]" +person,0,person,14,39,2987,"[2987]" +person,0,person,15,42,298629862986,"[298629862986]" +person,0,person,16,45,2985,"[2985]" +person,0,person,17,48,298429842984,"[298429842984]" +person,0,person,18,51,2983,"[2983]" +person,0,person,19,54,298229822982,"[298229822982]" +person,0,person,20,57,2981,"[2981]" +person,0,person,21,60,298029802980,"[298029802980]" +person,0,person,22,63,2979,"[2979]" +person,0,person,23,66,297829782978,"[297829782978]" +person,0,person,24,69,2977,"[2977]" +person,0,person,25,72,297629762976,"[297629762976]" +person,0,person,26,75,2975,"[2975]" +person,0,person,27,78,297429742974,"[297429742974]" +person,0,person,28,81,2973,"[2973]" +person,0,person,29,84,297229722972,"[297229722972]" +person,0,person,30,87,2971,"[2971]" +person,0,person,31,90,297029702970,"[297029702970]" +person,0,person,32,93,2969,"[2969]" +person,0,person,33,96,296829682968,"[296829682968]" +person,0,person,34,99,2967,"[2967]" +person,0,person,35,102,296629662966,"[296629662966]" +person,0,person,36,105,2965,"[2965]" +person,0,person,37,108,296429642964,"[296429642964]" +person,0,person,38,111,2963,"[2963]" +person,0,person,39,114,296229622962,"[296229622962]" +person,0,person,40,117,2961,"[2961]" +person,0,person,41,120,296029602960,"[296029602960]" +person,0,person,42,123,2959,"[2959]" +person,0,person,43,126,295829582958,"[295829582958]" +person,0,person,44,129,2957,"[2957]" +person,0,person,45,132,295629562956,"[295629562956]" +person,0,person,46,135,2955,"[2955]" +person,0,person,47,138,295429542954,"[295429542954]" +person,0,person,48,141,2953,"[2953]" +person,0,person,49,144,295229522952,"[295229522952]" +person,0,person,50,147,2951,"[2951]" +person,0,person,51,150,295029502950,"[295029502950]" +person,0,person,52,153,2949,"[2949]" +person,0,person,53,156,294829482948,"[294829482948]" +person,0,person,54,159,2947,"[2947]" +person,0,person,55,162,294629462946,"[294629462946]" +person,0,person,56,165,2945,"[2945]" +person,0,person,57,168,294429442944,"[294429442944]" +person,0,person,58,171,2943,"[2943]" +person,0,person,59,174,294229422942,"[294229422942]" +person,0,person,60,177,2941,"[2941]" +person,0,person,61,180,294029402940,"[294029402940]" +person,0,person,62,183,2939,"[2939]" +person,0,person,63,186,293829382938,"[293829382938]" +person,0,person,64,189,2937,"[2937]" +person,0,person,65,192,293629362936,"[293629362936]" +person,0,person,66,195,2935,"[2935]" +person,0,person,67,198,293429342934,"[293429342934]" +person,0,person,68,201,2933,"[2933]" +person,0,person,69,204,293229322932,"[293229322932]" +person,0,person,70,207,2931,"[2931]" +person,0,person,71,210,293029302930,"[293029302930]" +person,0,person,72,213,2929,"[2929]" +person,0,person,73,216,292829282928,"[292829282928]" +person,0,person,74,219,2927,"[2927]" +person,0,person,75,222,292629262926,"[292629262926]" +person,0,person,76,225,2925,"[2925]" +person,0,person,77,228,292429242924,"[292429242924]" +person,0,person,78,231,2923,"[2923]" +person,0,person,79,234,292229222922,"[292229222922]" +person,0,person,80,237,2921,"[2921]" +person,0,person,81,240,292029202920,"[292029202920]" +person,0,person,82,243,2919,"[2919]" +person,0,person,83,246,291829182918,"[291829182918]" +person,0,person,84,249,2917,"[2917]" +person,0,person,85,252,291629162916,"[291629162916]" +person,0,person,86,255,2915,"[2915]" +person,0,person,87,258,291429142914,"[291429142914]" +person,0,person,88,261,2913,"[2913]" +person,0,person,89,264,291229122912,"[291229122912]" +person,0,person,90,267,2911,"[2911]" +person,0,person,91,270,291029102910,"[291029102910]" +person,0,person,92,273,2909,"[2909]" +person,0,person,93,276,290829082908,"[290829082908]" +person,0,person,94,279,2907,"[2907]" +person,0,person,95,282,290629062906,"[290629062906]" +person,0,person,96,285,2905,"[2905]" +person,0,person,97,288,290429042904,"[290429042904]" +person,0,person,98,291,2903,"[2903]" +person,0,person,99,294,290229022902,"[290229022902]" +person,0,person,100,297,2901,"[2901]" +person,0,person,101,300,290029002900,"[290029002900]" +person,0,person,102,303,2899,"[2899]" +person,0,person,103,306,289828982898,"[289828982898]" +person,0,person,104,309,2897,"[2897]" +person,0,person,105,312,289628962896,"[289628962896]" +person,0,person,106,315,2895,"[2895]" +person,0,person,107,318,289428942894,"[289428942894]" +person,0,person,108,321,2893,"[2893]" +person,0,person,109,324,289228922892,"[289228922892]" +person,0,person,110,327,2891,"[2891]" +person,0,person,111,330,289028902890,"[289028902890]" +person,0,person,112,333,2889,"[2889]" +person,0,person,113,336,288828882888,"[288828882888]" +person,0,person,114,339,2887,"[2887]" +person,0,person,115,342,288628862886,"[288628862886]" +person,0,person,116,345,2885,"[2885]" +person,0,person,117,348,288428842884,"[288428842884]" +person,0,person,118,351,2883,"[2883]" +person,0,person,119,354,288228822882,"[288228822882]" +person,0,person,120,357,2881,"[2881]" +person,0,person,121,360,288028802880,"[288028802880]" +person,0,person,122,363,2879,"[2879]" +person,0,person,123,366,287828782878,"[287828782878]" +person,0,person,124,369,2877,"[2877]" +person,0,person,125,372,287628762876,"[287628762876]" +person,0,person,126,375,2875,"[2875]" +person,0,person,127,378,287428742874,"[287428742874]" +person,0,person,128,381,2873,"[2873]" +person,0,person,129,384,287228722872,"[287228722872]" +person,0,person,130,387,2871,"[2871]" +person,0,person,131,390,287028702870,"[287028702870]" +person,0,person,132,393,2869,"[2869]" +person,0,person,133,396,286828682868,"[286828682868]" +person,0,person,134,399,2867,"[2867]" +person,0,person,135,402,286628662866,"[286628662866]" +person,0,person,136,405,2865,"[2865]" +person,0,person,137,408,286428642864,"[286428642864]" +person,0,person,138,411,2863,"[2863]" +person,0,person,139,414,286228622862,"[286228622862]" +person,0,person,140,417,2861,"[2861]" +person,0,person,141,420,286028602860,"[286028602860]" +person,0,person,142,423,2859,"[2859]" +person,0,person,143,426,285828582858,"[285828582858]" +person,0,person,144,429,2857,"[2857]" +person,0,person,145,432,285628562856,"[285628562856]" +person,0,person,146,435,2855,"[2855]" +person,0,person,147,438,285428542854,"[285428542854]" +person,0,person,148,441,2853,"[2853]" +person,0,person,149,444,285228522852,"[285228522852]" +person,0,person,150,447,2851,"[2851]" +person,0,person,151,450,285028502850,"[285028502850]" +person,0,person,152,453,2849,"[2849]" +person,0,person,153,456,284828482848,"[284828482848]" +person,0,person,154,459,2847,"[2847]" +person,0,person,155,462,284628462846,"[284628462846]" +person,0,person,156,465,2845,"[2845]" +person,0,person,157,468,284428442844,"[284428442844]" +person,0,person,158,471,2843,"[2843]" +person,0,person,159,474,284228422842,"[284228422842]" +person,0,person,160,477,2841,"[2841]" +person,0,person,161,480,284028402840,"[284028402840]" +person,0,person,162,483,2839,"[2839]" +person,0,person,163,486,283828382838,"[283828382838]" +person,0,person,164,489,2837,"[2837]" +person,0,person,165,492,283628362836,"[283628362836]" +person,0,person,166,495,2835,"[2835]" +person,0,person,167,498,283428342834,"[283428342834]" +person,0,person,168,501,2833,"[2833]" +person,0,person,169,504,283228322832,"[283228322832]" +person,0,person,170,507,2831,"[2831]" +person,0,person,171,510,283028302830,"[283028302830]" +person,0,person,172,513,2829,"[2829]" +person,0,person,173,516,282828282828,"[282828282828]" +person,0,person,174,519,2827,"[2827]" +person,0,person,175,522,282628262826,"[282628262826]" +person,0,person,176,525,2825,"[2825]" +person,0,person,177,528,282428242824,"[282428242824]" +person,0,person,178,531,2823,"[2823]" +person,0,person,179,534,282228222822,"[282228222822]" +person,0,person,180,537,2821,"[2821]" +person,0,person,181,540,282028202820,"[282028202820]" +person,0,person,182,543,2819,"[2819]" +person,0,person,183,546,281828182818,"[281828182818]" +person,0,person,184,549,2817,"[2817]" +person,0,person,185,552,281628162816,"[281628162816]" +person,0,person,186,555,2815,"[2815]" +person,0,person,187,558,281428142814,"[281428142814]" +person,0,person,188,561,2813,"[2813]" +person,0,person,189,564,281228122812,"[281228122812]" +person,0,person,190,567,2811,"[2811]" +person,0,person,191,570,281028102810,"[281028102810]" +person,0,person,192,573,2809,"[2809]" +person,0,person,193,576,280828082808,"[280828082808]" +person,0,person,194,579,2807,"[2807]" +person,0,person,195,582,280628062806,"[280628062806]" +person,0,person,196,585,2805,"[2805]" +person,0,person,197,588,280428042804,"[280428042804]" +person,0,person,198,591,2803,"[2803]" +person,0,person,199,594,280228022802,"[280228022802]" +person,0,person,200,597,2801,"[2801]" +person,0,person,201,600,280028002800,"[280028002800]" +person,0,person,202,603,2799,"[2799]" +person,0,person,203,606,279827982798,"[279827982798]" +person,0,person,204,609,2797,"[2797]" +person,0,person,205,612,279627962796,"[279627962796]" +person,0,person,206,615,2795,"[2795]" +person,0,person,207,618,279427942794,"[279427942794]" +person,0,person,208,621,2793,"[2793]" +person,0,person,209,624,279227922792,"[279227922792]" +person,0,person,210,627,2791,"[2791]" +person,0,person,211,630,279027902790,"[279027902790]" +person,0,person,212,633,2789,"[2789]" +person,0,person,213,636,278827882788,"[278827882788]" +person,0,person,214,639,2787,"[2787]" +person,0,person,215,642,278627862786,"[278627862786]" +person,0,person,216,645,2785,"[2785]" +person,0,person,217,648,278427842784,"[278427842784]" +person,0,person,218,651,2783,"[2783]" +person,0,person,219,654,278227822782,"[278227822782]" +person,0,person,220,657,2781,"[2781]" +person,0,person,221,660,278027802780,"[278027802780]" +person,0,person,222,663,2779,"[2779]" +person,0,person,223,666,277827782778,"[277827782778]" +person,0,person,224,669,2777,"[2777]" +person,0,person,225,672,277627762776,"[277627762776]" +person,0,person,226,675,2775,"[2775]" +person,0,person,227,678,277427742774,"[277427742774]" +person,0,person,228,681,2773,"[2773]" +person,0,person,229,684,277227722772,"[277227722772]" +person,0,person,230,687,2771,"[2771]" +person,0,person,231,690,277027702770,"[277027702770]" +person,0,person,232,693,2769,"[2769]" +person,0,person,233,696,276827682768,"[276827682768]" +person,0,person,234,699,2767,"[2767]" +person,0,person,235,702,276627662766,"[276627662766]" +person,0,person,236,705,2765,"[2765]" +person,0,person,237,708,276427642764,"[276427642764]" +person,0,person,238,711,2763,"[2763]" +person,0,person,239,714,276227622762,"[276227622762]" +person,0,person,240,717,2761,"[2761]" +person,0,person,241,720,276027602760,"[276027602760]" +person,0,person,242,723,2759,"[2759]" +person,0,person,243,726,275827582758,"[275827582758]" +person,0,person,244,729,2757,"[2757]" +person,0,person,245,732,275627562756,"[275627562756]" +person,0,person,246,735,2755,"[2755]" +person,0,person,247,738,275427542754,"[275427542754]" +person,0,person,248,741,2753,"[2753]" +person,0,person,249,744,275227522752,"[275227522752]" +person,0,person,250,747,2751,"[2751]" +person,0,person,251,750,275027502750,"[275027502750]" +person,0,person,252,753,2749,"[2749]" +person,0,person,253,756,274827482748,"[274827482748]" +person,0,person,254,759,2747,"[2747]" +person,0,person,255,762,274627462746,"[274627462746]" +person,0,person,256,765,2745,"[2745]" +person,0,person,257,768,274427442744,"[274427442744]" +person,0,person,258,771,2743,"[2743]" +person,0,person,259,774,274227422742,"[274227422742]" +person,0,person,260,777,2741,"[2741]" +person,0,person,261,780,274027402740,"[274027402740]" +person,0,person,262,783,2739,"[2739]" +person,0,person,263,786,273827382738,"[273827382738]" +person,0,person,264,789,2737,"[2737]" +person,0,person,265,792,273627362736,"[273627362736]" +person,0,person,266,795,2735,"[2735]" +person,0,person,267,798,273427342734,"[273427342734]" +person,0,person,268,801,2733,"[2733]" +person,0,person,269,804,273227322732,"[273227322732]" +person,0,person,270,807,2731,"[2731]" +person,0,person,271,810,273027302730,"[273027302730]" +person,0,person,272,813,2729,"[2729]" +person,0,person,273,816,272827282728,"[272827282728]" +person,0,person,274,819,2727,"[2727]" +person,0,person,275,822,272627262726,"[272627262726]" +person,0,person,276,825,2725,"[2725]" +person,0,person,277,828,272427242724,"[272427242724]" +person,0,person,278,831,2723,"[2723]" +person,0,person,279,834,272227222722,"[272227222722]" +person,0,person,280,837,2721,"[2721]" +person,0,person,281,840,272027202720,"[272027202720]" +person,0,person,282,843,2719,"[2719]" +person,0,person,283,846,271827182718,"[271827182718]" +person,0,person,284,849,2717,"[2717]" +person,0,person,285,852,271627162716,"[271627162716]" +person,0,person,286,855,2715,"[2715]" +person,0,person,287,858,271427142714,"[271427142714]" +person,0,person,288,861,2713,"[2713]" +person,0,person,289,864,271227122712,"[271227122712]" +person,0,person,290,867,2711,"[2711]" +person,0,person,291,870,271027102710,"[271027102710]" +person,0,person,292,873,2709,"[2709]" +person,0,person,293,876,270827082708,"[270827082708]" +person,0,person,294,879,2707,"[2707]" +person,0,person,295,882,270627062706,"[270627062706]" +person,0,person,296,885,2705,"[2705]" +person,0,person,297,888,270427042704,"[270427042704]" +person,0,person,298,891,2703,"[2703]" +person,0,person,299,894,270227022702,"[270227022702]" +person,0,person,300,897,2701,"[2701]" +person,0,person,301,900,270027002700,"[270027002700]" +person,0,person,302,903,2699,"[2699]" +person,0,person,303,906,269826982698,"[269826982698]" +person,0,person,304,909,2697,"[2697]" +person,0,person,305,912,269626962696,"[269626962696]" +person,0,person,306,915,2695,"[2695]" +person,0,person,307,918,269426942694,"[269426942694]" +person,0,person,308,921,2693,"[2693]" +person,0,person,309,924,269226922692,"[269226922692]" +person,0,person,310,927,2691,"[2691]" +person,0,person,311,930,269026902690,"[269026902690]" +person,0,person,312,933,2689,"[2689]" +person,0,person,313,936,268826882688,"[268826882688]" +person,0,person,314,939,2687,"[2687]" +person,0,person,315,942,268626862686,"[268626862686]" +person,0,person,316,945,2685,"[2685]" +person,0,person,317,948,268426842684,"[268426842684]" +person,0,person,318,951,2683,"[2683]" +person,0,person,319,954,268226822682,"[268226822682]" +person,0,person,320,957,2681,"[2681]" +person,0,person,321,960,268026802680,"[268026802680]" +person,0,person,322,963,2679,"[2679]" +person,0,person,323,966,267826782678,"[267826782678]" +person,0,person,324,969,2677,"[2677]" +person,0,person,325,972,267626762676,"[267626762676]" +person,0,person,326,975,2675,"[2675]" +person,0,person,327,978,267426742674,"[267426742674]" +person,0,person,328,981,2673,"[2673]" +person,0,person,329,984,267226722672,"[267226722672]" +person,0,person,330,987,2671,"[2671]" +person,0,person,331,990,267026702670,"[267026702670]" +person,0,person,332,993,2669,"[2669]" +person,0,person,333,996,266826682668,"[266826682668]" +person,0,person,334,999,2667,"[2667]" +person,0,person,335,1002,266626662666,"[266626662666]" +person,0,person,336,1005,2665,"[2665]" +person,0,person,337,1008,266426642664,"[266426642664]" +person,0,person,338,1011,2663,"[2663]" +person,0,person,339,1014,266226622662,"[266226622662]" +person,0,person,340,1017,2661,"[2661]" +person,0,person,341,1020,266026602660,"[266026602660]" +person,0,person,342,1023,2659,"[2659]" +person,0,person,343,1026,265826582658,"[265826582658]" +person,0,person,344,1029,2657,"[2657]" +person,0,person,345,1032,265626562656,"[265626562656]" +person,0,person,346,1035,2655,"[2655]" +person,0,person,347,1038,265426542654,"[265426542654]" +person,0,person,348,1041,2653,"[2653]" +person,0,person,349,1044,265226522652,"[265226522652]" +person,0,person,350,1047,2651,"[2651]" +person,0,person,351,1050,265026502650,"[265026502650]" +person,0,person,352,1053,2649,"[2649]" +person,0,person,353,1056,264826482648,"[264826482648]" +person,0,person,354,1059,2647,"[2647]" +person,0,person,355,1062,264626462646,"[264626462646]" +person,0,person,356,1065,2645,"[2645]" +person,0,person,357,1068,264426442644,"[264426442644]" +person,0,person,358,1071,2643,"[2643]" +person,0,person,359,1074,264226422642,"[264226422642]" +person,0,person,360,1077,2641,"[2641]" +person,0,person,361,1080,264026402640,"[264026402640]" +person,0,person,362,1083,2639,"[2639]" +person,0,person,363,1086,263826382638,"[263826382638]" +person,0,person,364,1089,2637,"[2637]" +person,0,person,365,1092,263626362636,"[263626362636]" +person,0,person,366,1095,2635,"[2635]" +person,0,person,367,1098,263426342634,"[263426342634]" +person,0,person,368,1101,2633,"[2633]" +person,0,person,369,1104,263226322632,"[263226322632]" +person,0,person,370,1107,2631,"[2631]" +person,0,person,371,1110,263026302630,"[263026302630]" +person,0,person,372,1113,2629,"[2629]" +person,0,person,373,1116,262826282628,"[262826282628]" +person,0,person,374,1119,2627,"[2627]" +person,0,person,375,1122,262626262626,"[262626262626]" +person,0,person,376,1125,2625,"[2625]" +person,0,person,377,1128,262426242624,"[262426242624]" +person,0,person,378,1131,2623,"[2623]" +person,0,person,379,1134,262226222622,"[262226222622]" +person,0,person,380,1137,2621,"[2621]" +person,0,person,381,1140,262026202620,"[262026202620]" +person,0,person,382,1143,2619,"[2619]" +person,0,person,383,1146,261826182618,"[261826182618]" +person,0,person,384,1149,2617,"[2617]" +person,0,person,385,1152,261626162616,"[261626162616]" +person,0,person,386,1155,2615,"[2615]" +person,0,person,387,1158,261426142614,"[261426142614]" +person,0,person,388,1161,2613,"[2613]" +person,0,person,389,1164,261226122612,"[261226122612]" +person,0,person,390,1167,2611,"[2611]" +person,0,person,391,1170,261026102610,"[261026102610]" +person,0,person,392,1173,2609,"[2609]" +person,0,person,393,1176,260826082608,"[260826082608]" +person,0,person,394,1179,2607,"[2607]" +person,0,person,395,1182,260626062606,"[260626062606]" +person,0,person,396,1185,2605,"[2605]" +person,0,person,397,1188,260426042604,"[260426042604]" +person,0,person,398,1191,2603,"[2603]" +person,0,person,399,1194,260226022602,"[260226022602]" +person,0,person,400,1197,2601,"[2601]" +person,0,person,401,1200,260026002600,"[260026002600]" +person,0,person,402,1203,2599,"[2599]" +person,0,person,403,1206,259825982598,"[259825982598]" +person,0,person,404,1209,2597,"[2597]" +person,0,person,405,1212,259625962596,"[259625962596]" +person,0,person,406,1215,2595,"[2595]" +person,0,person,407,1218,259425942594,"[259425942594]" +person,0,person,408,1221,2593,"[2593]" +person,0,person,409,1224,259225922592,"[259225922592]" +person,0,person,410,1227,2591,"[2591]" +person,0,person,411,1230,259025902590,"[259025902590]" +person,0,person,412,1233,2589,"[2589]" +person,0,person,413,1236,258825882588,"[258825882588]" +person,0,person,414,1239,2587,"[2587]" +person,0,person,415,1242,258625862586,"[258625862586]" +person,0,person,416,1245,2585,"[2585]" +person,0,person,417,1248,258425842584,"[258425842584]" +person,0,person,418,1251,2583,"[2583]" +person,0,person,419,1254,258225822582,"[258225822582]" +person,0,person,420,1257,2581,"[2581]" +person,0,person,421,1260,258025802580,"[258025802580]" +person,0,person,422,1263,2579,"[2579]" +person,0,person,423,1266,257825782578,"[257825782578]" +person,0,person,424,1269,2577,"[2577]" +person,0,person,425,1272,257625762576,"[257625762576]" +person,0,person,426,1275,2575,"[2575]" +person,0,person,427,1278,257425742574,"[257425742574]" +person,0,person,428,1281,2573,"[2573]" +person,0,person,429,1284,257225722572,"[257225722572]" +person,0,person,430,1287,2571,"[2571]" +person,0,person,431,1290,257025702570,"[257025702570]" +person,0,person,432,1293,2569,"[2569]" +person,0,person,433,1296,256825682568,"[256825682568]" +person,0,person,434,1299,2567,"[2567]" +person,0,person,435,1302,256625662566,"[256625662566]" +person,0,person,436,1305,2565,"[2565]" +person,0,person,437,1308,256425642564,"[256425642564]" +person,0,person,438,1311,2563,"[2563]" +person,0,person,439,1314,256225622562,"[256225622562]" +person,0,person,440,1317,2561,"[2561]" +person,0,person,441,1320,256025602560,"[256025602560]" +person,0,person,442,1323,2559,"[2559]" +person,0,person,443,1326,255825582558,"[255825582558]" +person,0,person,444,1329,2557,"[2557]" +person,0,person,445,1332,255625562556,"[255625562556]" +person,0,person,446,1335,2555,"[2555]" +person,0,person,447,1338,255425542554,"[255425542554]" +person,0,person,448,1341,2553,"[2553]" +person,0,person,449,1344,255225522552,"[255225522552]" +person,0,person,450,1347,2551,"[2551]" +person,0,person,451,1350,255025502550,"[255025502550]" +person,0,person,452,1353,2549,"[2549]" +person,0,person,453,1356,254825482548,"[254825482548]" +person,0,person,454,1359,2547,"[2547]" +person,0,person,455,1362,254625462546,"[254625462546]" +person,0,person,456,1365,2545,"[2545]" +person,0,person,457,1368,254425442544,"[254425442544]" +person,0,person,458,1371,2543,"[2543]" +person,0,person,459,1374,254225422542,"[254225422542]" +person,0,person,460,1377,2541,"[2541]" +person,0,person,461,1380,254025402540,"[254025402540]" +person,0,person,462,1383,2539,"[2539]" +person,0,person,463,1386,253825382538,"[253825382538]" +person,0,person,464,1389,2537,"[2537]" +person,0,person,465,1392,253625362536,"[253625362536]" +person,0,person,466,1395,2535,"[2535]" +person,0,person,467,1398,253425342534,"[253425342534]" +person,0,person,468,1401,2533,"[2533]" +person,0,person,469,1404,253225322532,"[253225322532]" +person,0,person,470,1407,2531,"[2531]" +person,0,person,471,1410,253025302530,"[253025302530]" +person,0,person,472,1413,2529,"[2529]" +person,0,person,473,1416,252825282528,"[252825282528]" +person,0,person,474,1419,2527,"[2527]" +person,0,person,475,1422,252625262526,"[252625262526]" +person,0,person,476,1425,2525,"[2525]" +person,0,person,477,1428,252425242524,"[252425242524]" +person,0,person,478,1431,2523,"[2523]" +person,0,person,479,1434,252225222522,"[252225222522]" +person,0,person,480,1437,2521,"[2521]" +person,0,person,481,1440,252025202520,"[252025202520]" +person,0,person,482,1443,2519,"[2519]" +person,0,person,483,1446,251825182518,"[251825182518]" +person,0,person,484,1449,2517,"[2517]" +person,0,person,485,1452,251625162516,"[251625162516]" +person,0,person,486,1455,2515,"[2515]" +person,0,person,487,1458,251425142514,"[251425142514]" +person,0,person,488,1461,2513,"[2513]" +person,0,person,489,1464,251225122512,"[251225122512]" +person,0,person,490,1467,2511,"[2511]" +person,0,person,491,1470,251025102510,"[251025102510]" +person,0,person,492,1473,2509,"[2509]" +person,0,person,493,1476,250825082508,"[250825082508]" +person,0,person,494,1479,2507,"[2507]" +person,0,person,495,1482,250625062506,"[250625062506]" +person,0,person,496,1485,2505,"[2505]" +person,0,person,497,1488,250425042504,"[250425042504]" +person,0,person,498,1491,2503,"[2503]" +person,0,person,499,1494,250225022502,"[250225022502]" +person,0,person,500,1497,2501,"[2501]" +person,0,person,501,1500,250025002500,"[250025002500]" +person,0,person,502,1503,2499,"[2499]" +person,0,person,503,1506,249824982498,"[249824982498]" +person,0,person,504,1509,2497,"[2497]" +person,0,person,505,1512,249624962496,"[249624962496]" +person,0,person,506,1515,2495,"[2495]" +person,0,person,507,1518,249424942494,"[249424942494]" +person,0,person,508,1521,2493,"[2493]" +person,0,person,509,1524,249224922492,"[249224922492]" +person,0,person,510,1527,2491,"[2491]" +person,0,person,511,1530,249024902490,"[249024902490]" +person,0,person,512,1533,2489,"[2489]" +person,0,person,513,1536,248824882488,"[248824882488]" +person,0,person,514,1539,2487,"[2487]" +person,0,person,515,1542,248624862486,"[248624862486]" +person,0,person,516,1545,2485,"[2485]" +person,0,person,517,1548,248424842484,"[248424842484]" +person,0,person,518,1551,2483,"[2483]" +person,0,person,519,1554,248224822482,"[248224822482]" +person,0,person,520,1557,2481,"[2481]" +person,0,person,521,1560,248024802480,"[248024802480]" +person,0,person,522,1563,2479,"[2479]" +person,0,person,523,1566,247824782478,"[247824782478]" +person,0,person,524,1569,2477,"[2477]" +person,0,person,525,1572,247624762476,"[247624762476]" +person,0,person,526,1575,2475,"[2475]" +person,0,person,527,1578,247424742474,"[247424742474]" +person,0,person,528,1581,2473,"[2473]" +person,0,person,529,1584,247224722472,"[247224722472]" +person,0,person,530,1587,2471,"[2471]" +person,0,person,531,1590,247024702470,"[247024702470]" +person,0,person,532,1593,2469,"[2469]" +person,0,person,533,1596,246824682468,"[246824682468]" +person,0,person,534,1599,2467,"[2467]" +person,0,person,535,1602,246624662466,"[246624662466]" +person,0,person,536,1605,2465,"[2465]" +person,0,person,537,1608,246424642464,"[246424642464]" +person,0,person,538,1611,2463,"[2463]" +person,0,person,539,1614,246224622462,"[246224622462]" +person,0,person,540,1617,2461,"[2461]" +person,0,person,541,1620,246024602460,"[246024602460]" +person,0,person,542,1623,2459,"[2459]" +person,0,person,543,1626,245824582458,"[245824582458]" +person,0,person,544,1629,2457,"[2457]" +person,0,person,545,1632,245624562456,"[245624562456]" +person,0,person,546,1635,2455,"[2455]" +person,0,person,547,1638,245424542454,"[245424542454]" +person,0,person,548,1641,2453,"[2453]" +person,0,person,549,1644,245224522452,"[245224522452]" +person,0,person,550,1647,2451,"[2451]" +person,0,person,551,1650,245024502450,"[245024502450]" +person,0,person,552,1653,2449,"[2449]" +person,0,person,553,1656,244824482448,"[244824482448]" +person,0,person,554,1659,2447,"[2447]" +person,0,person,555,1662,244624462446,"[244624462446]" +person,0,person,556,1665,2445,"[2445]" +person,0,person,557,1668,244424442444,"[244424442444]" +person,0,person,558,1671,2443,"[2443]" +person,0,person,559,1674,244224422442,"[244224422442]" +person,0,person,560,1677,2441,"[2441]" +person,0,person,561,1680,244024402440,"[244024402440]" +person,0,person,562,1683,2439,"[2439]" +person,0,person,563,1686,243824382438,"[243824382438]" +person,0,person,564,1689,2437,"[2437]" +person,0,person,565,1692,243624362436,"[243624362436]" +person,0,person,566,1695,2435,"[2435]" +person,0,person,567,1698,243424342434,"[243424342434]" +person,0,person,568,1701,2433,"[2433]" +person,0,person,569,1704,243224322432,"[243224322432]" +person,0,person,570,1707,2431,"[2431]" +person,0,person,571,1710,243024302430,"[243024302430]" +person,0,person,572,1713,2429,"[2429]" +person,0,person,573,1716,242824282428,"[242824282428]" +person,0,person,574,1719,2427,"[2427]" +person,0,person,575,1722,242624262426,"[242624262426]" +person,0,person,576,1725,2425,"[2425]" +person,0,person,577,1728,242424242424,"[242424242424]" +person,0,person,578,1731,2423,"[2423]" +person,0,person,579,1734,242224222422,"[242224222422]" +person,0,person,580,1737,2421,"[2421]" +person,0,person,581,1740,242024202420,"[242024202420]" +person,0,person,582,1743,2419,"[2419]" +person,0,person,583,1746,241824182418,"[241824182418]" +person,0,person,584,1749,2417,"[2417]" +person,0,person,585,1752,241624162416,"[241624162416]" +person,0,person,586,1755,2415,"[2415]" +person,0,person,587,1758,241424142414,"[241424142414]" +person,0,person,588,1761,2413,"[2413]" +person,0,person,589,1764,241224122412,"[241224122412]" +person,0,person,590,1767,2411,"[2411]" +person,0,person,591,1770,241024102410,"[241024102410]" +person,0,person,592,1773,2409,"[2409]" +person,0,person,593,1776,240824082408,"[240824082408]" +person,0,person,594,1779,2407,"[2407]" +person,0,person,595,1782,240624062406,"[240624062406]" +person,0,person,596,1785,2405,"[2405]" +person,0,person,597,1788,240424042404,"[240424042404]" +person,0,person,598,1791,2403,"[2403]" +person,0,person,599,1794,240224022402,"[240224022402]" +person,0,person,600,1797,2401,"[2401]" +person,0,person,601,1800,240024002400,"[240024002400]" +person,0,person,602,1803,2399,"[2399]" +person,0,person,603,1806,239823982398,"[239823982398]" +person,0,person,604,1809,2397,"[2397]" +person,0,person,605,1812,239623962396,"[239623962396]" +person,0,person,606,1815,2395,"[2395]" +person,0,person,607,1818,239423942394,"[239423942394]" +person,0,person,608,1821,2393,"[2393]" +person,0,person,609,1824,239223922392,"[239223922392]" +person,0,person,610,1827,2391,"[2391]" +person,0,person,611,1830,239023902390,"[239023902390]" +person,0,person,612,1833,2389,"[2389]" +person,0,person,613,1836,238823882388,"[238823882388]" +person,0,person,614,1839,2387,"[2387]" +person,0,person,615,1842,238623862386,"[238623862386]" +person,0,person,616,1845,2385,"[2385]" +person,0,person,617,1848,238423842384,"[238423842384]" +person,0,person,618,1851,2383,"[2383]" +person,0,person,619,1854,238223822382,"[238223822382]" +person,0,person,620,1857,2381,"[2381]" +person,0,person,621,1860,238023802380,"[238023802380]" +person,0,person,622,1863,2379,"[2379]" +person,0,person,623,1866,237823782378,"[237823782378]" +person,0,person,624,1869,2377,"[2377]" +person,0,person,625,1872,237623762376,"[237623762376]" +person,0,person,626,1875,2375,"[2375]" +person,0,person,627,1878,237423742374,"[237423742374]" +person,0,person,628,1881,2373,"[2373]" +person,0,person,629,1884,237223722372,"[237223722372]" +person,0,person,630,1887,2371,"[2371]" +person,0,person,631,1890,237023702370,"[237023702370]" +person,0,person,632,1893,2369,"[2369]" +person,0,person,633,1896,236823682368,"[236823682368]" +person,0,person,634,1899,2367,"[2367]" +person,0,person,635,1902,236623662366,"[236623662366]" +person,0,person,636,1905,2365,"[2365]" +person,0,person,637,1908,236423642364,"[236423642364]" +person,0,person,638,1911,2363,"[2363]" +person,0,person,639,1914,236223622362,"[236223622362]" +person,0,person,640,1917,2361,"[2361]" +person,0,person,641,1920,236023602360,"[236023602360]" +person,0,person,642,1923,2359,"[2359]" +person,0,person,643,1926,235823582358,"[235823582358]" +person,0,person,644,1929,2357,"[2357]" +person,0,person,645,1932,235623562356,"[235623562356]" +person,0,person,646,1935,2355,"[2355]" +person,0,person,647,1938,235423542354,"[235423542354]" +person,0,person,648,1941,2353,"[2353]" +person,0,person,649,1944,235223522352,"[235223522352]" +person,0,person,650,1947,2351,"[2351]" +person,0,person,651,1950,235023502350,"[235023502350]" +person,0,person,652,1953,2349,"[2349]" +person,0,person,653,1956,234823482348,"[234823482348]" +person,0,person,654,1959,2347,"[2347]" +person,0,person,655,1962,234623462346,"[234623462346]" +person,0,person,656,1965,2345,"[2345]" +person,0,person,657,1968,234423442344,"[234423442344]" +person,0,person,658,1971,2343,"[2343]" +person,0,person,659,1974,234223422342,"[234223422342]" +person,0,person,660,1977,2341,"[2341]" +person,0,person,661,1980,234023402340,"[234023402340]" +person,0,person,662,1983,2339,"[2339]" +person,0,person,663,1986,233823382338,"[233823382338]" +person,0,person,664,1989,2337,"[2337]" +person,0,person,665,1992,233623362336,"[233623362336]" +person,0,person,666,1995,2335,"[2335]" +person,0,person,667,1998,233423342334,"[233423342334]" +person,0,person,668,2001,2333,"[2333]" +person,0,person,669,2004,233223322332,"[233223322332]" +person,0,person,670,2007,2331,"[2331]" +person,0,person,671,2010,233023302330,"[233023302330]" +person,0,person,672,2013,2329,"[2329]" +person,0,person,673,2016,232823282328,"[232823282328]" +person,0,person,674,2019,2327,"[2327]" +person,0,person,675,2022,232623262326,"[232623262326]" +person,0,person,676,2025,2325,"[2325]" +person,0,person,677,2028,232423242324,"[232423242324]" +person,0,person,678,2031,2323,"[2323]" +person,0,person,679,2034,232223222322,"[232223222322]" +person,0,person,680,2037,2321,"[2321]" +person,0,person,681,2040,232023202320,"[232023202320]" +person,0,person,682,2043,2319,"[2319]" +person,0,person,683,2046,231823182318,"[231823182318]" +person,0,person,684,2049,2317,"[2317]" +person,0,person,685,2052,231623162316,"[231623162316]" +person,0,person,686,2055,2315,"[2315]" +person,0,person,687,2058,231423142314,"[231423142314]" +person,0,person,688,2061,2313,"[2313]" +person,0,person,689,2064,231223122312,"[231223122312]" +person,0,person,690,2067,2311,"[2311]" +person,0,person,691,2070,231023102310,"[231023102310]" +person,0,person,692,2073,2309,"[2309]" +person,0,person,693,2076,230823082308,"[230823082308]" +person,0,person,694,2079,2307,"[2307]" +person,0,person,695,2082,230623062306,"[230623062306]" +person,0,person,696,2085,2305,"[2305]" +person,0,person,697,2088,230423042304,"[230423042304]" +person,0,person,698,2091,2303,"[2303]" +person,0,person,699,2094,230223022302,"[230223022302]" +person,0,person,700,2097,2301,"[2301]" +person,0,person,701,2100,230023002300,"[230023002300]" +person,0,person,702,2103,2299,"[2299]" +person,0,person,703,2106,229822982298,"[229822982298]" +person,0,person,704,2109,2297,"[2297]" +person,0,person,705,2112,229622962296,"[229622962296]" +person,0,person,706,2115,2295,"[2295]" +person,0,person,707,2118,229422942294,"[229422942294]" +person,0,person,708,2121,2293,"[2293]" +person,0,person,709,2124,229222922292,"[229222922292]" +person,0,person,710,2127,2291,"[2291]" +person,0,person,711,2130,229022902290,"[229022902290]" +person,0,person,712,2133,2289,"[2289]" +person,0,person,713,2136,228822882288,"[228822882288]" +person,0,person,714,2139,2287,"[2287]" +person,0,person,715,2142,228622862286,"[228622862286]" +person,0,person,716,2145,2285,"[2285]" +person,0,person,717,2148,228422842284,"[228422842284]" +person,0,person,718,2151,2283,"[2283]" +person,0,person,719,2154,228222822282,"[228222822282]" +person,0,person,720,2157,2281,"[2281]" +person,0,person,721,2160,228022802280,"[228022802280]" +person,0,person,722,2163,2279,"[2279]" +person,0,person,723,2166,227822782278,"[227822782278]" +person,0,person,724,2169,2277,"[2277]" +person,0,person,725,2172,227622762276,"[227622762276]" +person,0,person,726,2175,2275,"[2275]" +person,0,person,727,2178,227422742274,"[227422742274]" +person,0,person,728,2181,2273,"[2273]" +person,0,person,729,2184,227222722272,"[227222722272]" +person,0,person,730,2187,2271,"[2271]" +person,0,person,731,2190,227022702270,"[227022702270]" +person,0,person,732,2193,2269,"[2269]" +person,0,person,733,2196,226822682268,"[226822682268]" +person,0,person,734,2199,2267,"[2267]" +person,0,person,735,2202,226622662266,"[226622662266]" +person,0,person,736,2205,2265,"[2265]" +person,0,person,737,2208,226422642264,"[226422642264]" +person,0,person,738,2211,2263,"[2263]" +person,0,person,739,2214,226222622262,"[226222622262]" +person,0,person,740,2217,2261,"[2261]" +person,0,person,741,2220,226022602260,"[226022602260]" +person,0,person,742,2223,2259,"[2259]" +person,0,person,743,2226,225822582258,"[225822582258]" +person,0,person,744,2229,2257,"[2257]" +person,0,person,745,2232,225622562256,"[225622562256]" +person,0,person,746,2235,2255,"[2255]" +person,0,person,747,2238,225422542254,"[225422542254]" +person,0,person,748,2241,2253,"[2253]" +person,0,person,749,2244,225222522252,"[225222522252]" +person,0,person,750,2247,2251,"[2251]" +person,0,person,751,2250,225022502250,"[225022502250]" +person,0,person,752,2253,2249,"[2249]" +person,0,person,753,2256,224822482248,"[224822482248]" +person,0,person,754,2259,2247,"[2247]" +person,0,person,755,2262,224622462246,"[224622462246]" +person,0,person,756,2265,2245,"[2245]" +person,0,person,757,2268,224422442244,"[224422442244]" +person,0,person,758,2271,2243,"[2243]" +person,0,person,759,2274,224222422242,"[224222422242]" +person,0,person,760,2277,2241,"[2241]" +person,0,person,761,2280,224022402240,"[224022402240]" +person,0,person,762,2283,2239,"[2239]" +person,0,person,763,2286,223822382238,"[223822382238]" +person,0,person,764,2289,2237,"[2237]" +person,0,person,765,2292,223622362236,"[223622362236]" +person,0,person,766,2295,2235,"[2235]" +person,0,person,767,2298,223422342234,"[223422342234]" +person,0,person,768,2301,2233,"[2233]" +person,0,person,769,2304,223222322232,"[223222322232]" +person,0,person,770,2307,2231,"[2231]" +person,0,person,771,2310,223022302230,"[223022302230]" +person,0,person,772,2313,2229,"[2229]" +person,0,person,773,2316,222822282228,"[222822282228]" +person,0,person,774,2319,2227,"[2227]" +person,0,person,775,2322,222622262226,"[222622262226]" +person,0,person,776,2325,2225,"[2225]" +person,0,person,777,2328,222422242224,"[222422242224]" +person,0,person,778,2331,2223,"[2223]" +person,0,person,779,2334,222222222222,"[222222222222]" +person,0,person,780,2337,2221,"[2221]" +person,0,person,781,2340,222022202220,"[222022202220]" +person,0,person,782,2343,2219,"[2219]" +person,0,person,783,2346,221822182218,"[221822182218]" +person,0,person,784,2349,2217,"[2217]" +person,0,person,785,2352,221622162216,"[221622162216]" +person,0,person,786,2355,2215,"[2215]" +person,0,person,787,2358,221422142214,"[221422142214]" +person,0,person,788,2361,2213,"[2213]" +person,0,person,789,2364,221222122212,"[221222122212]" +person,0,person,790,2367,2211,"[2211]" +person,0,person,791,2370,221022102210,"[221022102210]" +person,0,person,792,2373,2209,"[2209]" +person,0,person,793,2376,220822082208,"[220822082208]" +person,0,person,794,2379,2207,"[2207]" +person,0,person,795,2382,220622062206,"[220622062206]" +person,0,person,796,2385,2205,"[2205]" +person,0,person,797,2388,220422042204,"[220422042204]" +person,0,person,798,2391,2203,"[2203]" +person,0,person,799,2394,220222022202,"[220222022202]" +person,0,person,800,2397,2201,"[2201]" +person,0,person,801,2400,220022002200,"[220022002200]" +person,0,person,802,2403,2199,"[2199]" +person,0,person,803,2406,219821982198,"[219821982198]" +person,0,person,804,2409,2197,"[2197]" +person,0,person,805,2412,219621962196,"[219621962196]" +person,0,person,806,2415,2195,"[2195]" +person,0,person,807,2418,219421942194,"[219421942194]" +person,0,person,808,2421,2193,"[2193]" +person,0,person,809,2424,219221922192,"[219221922192]" +person,0,person,810,2427,2191,"[2191]" +person,0,person,811,2430,219021902190,"[219021902190]" +person,0,person,812,2433,2189,"[2189]" +person,0,person,813,2436,218821882188,"[218821882188]" +person,0,person,814,2439,2187,"[2187]" +person,0,person,815,2442,218621862186,"[218621862186]" +person,0,person,816,2445,2185,"[2185]" +person,0,person,817,2448,218421842184,"[218421842184]" +person,0,person,818,2451,2183,"[2183]" +person,0,person,819,2454,218221822182,"[218221822182]" +person,0,person,820,2457,2181,"[2181]" +person,0,person,821,2460,218021802180,"[218021802180]" +person,0,person,822,2463,2179,"[2179]" +person,0,person,823,2466,217821782178,"[217821782178]" +person,0,person,824,2469,2177,"[2177]" +person,0,person,825,2472,217621762176,"[217621762176]" +person,0,person,826,2475,2175,"[2175]" +person,0,person,827,2478,217421742174,"[217421742174]" +person,0,person,828,2481,2173,"[2173]" +person,0,person,829,2484,217221722172,"[217221722172]" +person,0,person,830,2487,2171,"[2171]" +person,0,person,831,2490,217021702170,"[217021702170]" +person,0,person,832,2493,2169,"[2169]" +person,0,person,833,2496,216821682168,"[216821682168]" +person,0,person,834,2499,2167,"[2167]" +person,0,person,835,2502,216621662166,"[216621662166]" +person,0,person,836,2505,2165,"[2165]" +person,0,person,837,2508,216421642164,"[216421642164]" +person,0,person,838,2511,2163,"[2163]" +person,0,person,839,2514,216221622162,"[216221622162]" +person,0,person,840,2517,2161,"[2161]" +person,0,person,841,2520,216021602160,"[216021602160]" +person,0,person,842,2523,2159,"[2159]" +person,0,person,843,2526,215821582158,"[215821582158]" +person,0,person,844,2529,2157,"[2157]" +person,0,person,845,2532,215621562156,"[215621562156]" +person,0,person,846,2535,2155,"[2155]" +person,0,person,847,2538,215421542154,"[215421542154]" +person,0,person,848,2541,2153,"[2153]" +person,0,person,849,2544,215221522152,"[215221522152]" +person,0,person,850,2547,2151,"[2151]" +person,0,person,851,2550,215021502150,"[215021502150]" +person,0,person,852,2553,2149,"[2149]" +person,0,person,853,2556,214821482148,"[214821482148]" +person,0,person,854,2559,2147,"[2147]" +person,0,person,855,2562,214621462146,"[214621462146]" +person,0,person,856,2565,2145,"[2145]" +person,0,person,857,2568,214421442144,"[214421442144]" +person,0,person,858,2571,2143,"[2143]" +person,0,person,859,2574,214221422142,"[214221422142]" +person,0,person,860,2577,2141,"[2141]" +person,0,person,861,2580,214021402140,"[214021402140]" +person,0,person,862,2583,2139,"[2139]" +person,0,person,863,2586,213821382138,"[213821382138]" +person,0,person,864,2589,2137,"[2137]" +person,0,person,865,2592,213621362136,"[213621362136]" +person,0,person,866,2595,2135,"[2135]" +person,0,person,867,2598,213421342134,"[213421342134]" +person,0,person,868,2601,2133,"[2133]" +person,0,person,869,2604,213221322132,"[213221322132]" +person,0,person,870,2607,2131,"[2131]" +person,0,person,871,2610,213021302130,"[213021302130]" +person,0,person,872,2613,2129,"[2129]" +person,0,person,873,2616,212821282128,"[212821282128]" +person,0,person,874,2619,2127,"[2127]" +person,0,person,875,2622,212621262126,"[212621262126]" +person,0,person,876,2625,2125,"[2125]" +person,0,person,877,2628,212421242124,"[212421242124]" +person,0,person,878,2631,2123,"[2123]" +person,0,person,879,2634,212221222122,"[212221222122]" +person,0,person,880,2637,2121,"[2121]" +person,0,person,881,2640,212021202120,"[212021202120]" +person,0,person,882,2643,2119,"[2119]" +person,0,person,883,2646,211821182118,"[211821182118]" +person,0,person,884,2649,2117,"[2117]" +person,0,person,885,2652,211621162116,"[211621162116]" +person,0,person,886,2655,2115,"[2115]" +person,0,person,887,2658,211421142114,"[211421142114]" +person,0,person,888,2661,2113,"[2113]" +person,0,person,889,2664,211221122112,"[211221122112]" +person,0,person,890,2667,2111,"[2111]" +person,0,person,891,2670,211021102110,"[211021102110]" +person,0,person,892,2673,2109,"[2109]" +person,0,person,893,2676,210821082108,"[210821082108]" +person,0,person,894,2679,2107,"[2107]" +person,0,person,895,2682,210621062106,"[210621062106]" +person,0,person,896,2685,2105,"[2105]" +person,0,person,897,2688,210421042104,"[210421042104]" +person,0,person,898,2691,2103,"[2103]" +person,0,person,899,2694,210221022102,"[210221022102]" +person,0,person,900,2697,2101,"[2101]" +person,0,person,901,2700,210021002100,"[210021002100]" +person,0,person,902,2703,2099,"[2099]" +person,0,person,903,2706,209820982098,"[209820982098]" +person,0,person,904,2709,2097,"[2097]" +person,0,person,905,2712,209620962096,"[209620962096]" +person,0,person,906,2715,2095,"[2095]" +person,0,person,907,2718,209420942094,"[209420942094]" +person,0,person,908,2721,2093,"[2093]" +person,0,person,909,2724,209220922092,"[209220922092]" +person,0,person,910,2727,2091,"[2091]" +person,0,person,911,2730,209020902090,"[209020902090]" +person,0,person,912,2733,2089,"[2089]" +person,0,person,913,2736,208820882088,"[208820882088]" +person,0,person,914,2739,2087,"[2087]" +person,0,person,915,2742,208620862086,"[208620862086]" +person,0,person,916,2745,2085,"[2085]" +person,0,person,917,2748,208420842084,"[208420842084]" +person,0,person,918,2751,2083,"[2083]" +person,0,person,919,2754,208220822082,"[208220822082]" +person,0,person,920,2757,2081,"[2081]" +person,0,person,921,2760,208020802080,"[208020802080]" +person,0,person,922,2763,2079,"[2079]" +person,0,person,923,2766,207820782078,"[207820782078]" +person,0,person,924,2769,2077,"[2077]" +person,0,person,925,2772,207620762076,"[207620762076]" +person,0,person,926,2775,2075,"[2075]" +person,0,person,927,2778,207420742074,"[207420742074]" +person,0,person,928,2781,2073,"[2073]" +person,0,person,929,2784,207220722072,"[207220722072]" +person,0,person,930,2787,2071,"[2071]" +person,0,person,931,2790,207020702070,"[207020702070]" +person,0,person,932,2793,2069,"[2069]" +person,0,person,933,2796,206820682068,"[206820682068]" +person,0,person,934,2799,2067,"[2067]" +person,0,person,935,2802,206620662066,"[206620662066]" +person,0,person,936,2805,2065,"[2065]" +person,0,person,937,2808,206420642064,"[206420642064]" +person,0,person,938,2811,2063,"[2063]" +person,0,person,939,2814,206220622062,"[206220622062]" +person,0,person,940,2817,2061,"[2061]" +person,0,person,941,2820,206020602060,"[206020602060]" +person,0,person,942,2823,2059,"[2059]" +person,0,person,943,2826,205820582058,"[205820582058]" +person,0,person,944,2829,2057,"[2057]" +person,0,person,945,2832,205620562056,"[205620562056]" +person,0,person,946,2835,2055,"[2055]" +person,0,person,947,2838,205420542054,"[205420542054]" +person,0,person,948,2841,2053,"[2053]" +person,0,person,949,2844,205220522052,"[205220522052]" +person,0,person,950,2847,2051,"[2051]" +person,0,person,951,2850,205020502050,"[205020502050]" +person,0,person,952,2853,2049,"[2049]" +person,0,person,953,2856,204820482048,"[204820482048]" +person,0,person,954,2859,2047,"[2047]" +person,0,person,955,2862,204620462046,"[204620462046]" +person,0,person,956,2865,2045,"[2045]" +person,0,person,957,2868,204420442044,"[204420442044]" +person,0,person,958,2871,2043,"[2043]" +person,0,person,959,2874,204220422042,"[204220422042]" +person,0,person,960,2877,2041,"[2041]" +person,0,person,961,2880,204020402040,"[204020402040]" +person,0,person,962,2883,2039,"[2039]" +person,0,person,963,2886,203820382038,"[203820382038]" +person,0,person,964,2889,2037,"[2037]" +person,0,person,965,2892,203620362036,"[203620362036]" +person,0,person,966,2895,2035,"[2035]" +person,0,person,967,2898,203420342034,"[203420342034]" +person,0,person,968,2901,2033,"[2033]" +person,0,person,969,2904,203220322032,"[203220322032]" +person,0,person,970,2907,2031,"[2031]" +person,0,person,971,2910,203020302030,"[203020302030]" +person,0,person,972,2913,2029,"[2029]" +person,0,person,973,2916,202820282028,"[202820282028]" +person,0,person,974,2919,2027,"[2027]" +person,0,person,975,2922,202620262026,"[202620262026]" +person,0,person,976,2925,2025,"[2025]" +person,0,person,977,2928,202420242024,"[202420242024]" +person,0,person,978,2931,2023,"[2023]" +person,0,person,979,2934,202220222022,"[202220222022]" +person,0,person,980,2937,2021,"[2021]" +person,0,person,981,2940,202020202020,"[202020202020]" +person,0,person,982,2943,2019,"[2019]" +person,0,person,983,2946,201820182018,"[201820182018]" +person,0,person,984,2949,2017,"[2017]" +person,0,person,985,2952,201620162016,"[201620162016]" +person,0,person,986,2955,2015,"[2015]" +person,0,person,987,2958,201420142014,"[201420142014]" +person,0,person,988,2961,2013,"[2013]" +person,0,person,989,2964,201220122012,"[201220122012]" +person,0,person,990,2967,2011,"[2011]" +person,0,person,991,2970,201020102010,"[201020102010]" +person,0,person,992,2973,2009,"[2009]" +person,0,person,993,2976,200820082008,"[200820082008]" +person,0,person,994,2979,2007,"[2007]" +person,0,person,995,2982,200620062006,"[200620062006]" +person,0,person,996,2985,2005,"[2005]" +person,0,person,997,2988,200420042004,"[200420042004]" +person,0,person,998,2991,2003,"[2003]" +person,0,person,999,2994,200220022002,"[200220022002]" +person,0,person,1000,2997,2001,"[2001]" +person,0,person,1001,3000,200020002000,"[200020002000]" +person,0,person,1002,3003,1999,"[1999]" +person,0,person,1003,3006,199819981998,"[199819981998]" +person,0,person,1004,3009,1997,"[1997]" +person,0,person,1005,3012,199619961996,"[199619961996]" +person,0,person,1006,3015,1995,"[1995]" +person,0,person,1007,3018,199419941994,"[199419941994]" +person,0,person,1008,3021,1993,"[1993]" +person,0,person,1009,3024,199219921992,"[199219921992]" +person,0,person,1010,3027,1991,"[1991]" +person,0,person,1011,3030,199019901990,"[199019901990]" +person,0,person,1012,3033,1989,"[1989]" +person,0,person,1013,3036,198819881988,"[198819881988]" +person,0,person,1014,3039,1987,"[1987]" +person,0,person,1015,3042,198619861986,"[198619861986]" +person,0,person,1016,3045,1985,"[1985]" +person,0,person,1017,3048,198419841984,"[198419841984]" +person,0,person,1018,3051,1983,"[1983]" +person,0,person,1019,3054,198219821982,"[198219821982]" +person,0,person,1020,3057,1981,"[1981]" +person,0,person,1021,3060,198019801980,"[198019801980]" +person,0,person,1022,3063,1979,"[1979]" +person,0,person,1023,3066,197819781978,"[197819781978]" +person,0,person,1024,3069,1977,"[1977]" +person,0,person,1025,3072,197619761976,"[197619761976]" +person,0,person,1026,3075,1975,"[1975]" +person,0,person,1027,3078,197419741974,"[197419741974]" +person,0,person,1028,3081,1973,"[1973]" +person,0,person,1029,3084,197219721972,"[197219721972]" +person,0,person,1030,3087,1971,"[1971]" +person,0,person,1031,3090,197019701970,"[197019701970]" +person,0,person,1032,3093,1969,"[1969]" +person,0,person,1033,3096,196819681968,"[196819681968]" +person,0,person,1034,3099,1967,"[1967]" +person,0,person,1035,3102,196619661966,"[196619661966]" +person,0,person,1036,3105,1965,"[1965]" +person,0,person,1037,3108,196419641964,"[196419641964]" +person,0,person,1038,3111,1963,"[1963]" +person,0,person,1039,3114,196219621962,"[196219621962]" +person,0,person,1040,3117,1961,"[1961]" +person,0,person,1041,3120,196019601960,"[196019601960]" +person,0,person,1042,3123,1959,"[1959]" +person,0,person,1043,3126,195819581958,"[195819581958]" +person,0,person,1044,3129,1957,"[1957]" +person,0,person,1045,3132,195619561956,"[195619561956]" +person,0,person,1046,3135,1955,"[1955]" +person,0,person,1047,3138,195419541954,"[195419541954]" +person,0,person,1048,3141,1953,"[1953]" +person,0,person,1049,3144,195219521952,"[195219521952]" +person,0,person,1050,3147,1951,"[1951]" +person,0,person,1051,3150,195019501950,"[195019501950]" +person,0,person,1052,3153,1949,"[1949]" +person,0,person,1053,3156,194819481948,"[194819481948]" +person,0,person,1054,3159,1947,"[1947]" +person,0,person,1055,3162,194619461946,"[194619461946]" +person,0,person,1056,3165,1945,"[1945]" +person,0,person,1057,3168,194419441944,"[194419441944]" +person,0,person,1058,3171,1943,"[1943]" +person,0,person,1059,3174,194219421942,"[194219421942]" +person,0,person,1060,3177,1941,"[1941]" +person,0,person,1061,3180,194019401940,"[194019401940]" +person,0,person,1062,3183,1939,"[1939]" +person,0,person,1063,3186,193819381938,"[193819381938]" +person,0,person,1064,3189,1937,"[1937]" +person,0,person,1065,3192,193619361936,"[193619361936]" +person,0,person,1066,3195,1935,"[1935]" +person,0,person,1067,3198,193419341934,"[193419341934]" +person,0,person,1068,3201,1933,"[1933]" +person,0,person,1069,3204,193219321932,"[193219321932]" +person,0,person,1070,3207,1931,"[1931]" +person,0,person,1071,3210,193019301930,"[193019301930]" +person,0,person,1072,3213,1929,"[1929]" +person,0,person,1073,3216,192819281928,"[192819281928]" +person,0,person,1074,3219,1927,"[1927]" +person,0,person,1075,3222,192619261926,"[192619261926]" +person,0,person,1076,3225,1925,"[1925]" +person,0,person,1077,3228,192419241924,"[192419241924]" +person,0,person,1078,3231,1923,"[1923]" +person,0,person,1079,3234,192219221922,"[192219221922]" +person,0,person,1080,3237,1921,"[1921]" +person,0,person,1081,3240,192019201920,"[192019201920]" +person,0,person,1082,3243,1919,"[1919]" +person,0,person,1083,3246,191819181918,"[191819181918]" +person,0,person,1084,3249,1917,"[1917]" +person,0,person,1085,3252,191619161916,"[191619161916]" +person,0,person,1086,3255,1915,"[1915]" +person,0,person,1087,3258,191419141914,"[191419141914]" +person,0,person,1088,3261,1913,"[1913]" +person,0,person,1089,3264,191219121912,"[191219121912]" +person,0,person,1090,3267,1911,"[1911]" +person,0,person,1091,3270,191019101910,"[191019101910]" +person,0,person,1092,3273,1909,"[1909]" +person,0,person,1093,3276,190819081908,"[190819081908]" +person,0,person,1094,3279,1907,"[1907]" +person,0,person,1095,3282,190619061906,"[190619061906]" +person,0,person,1096,3285,1905,"[1905]" +person,0,person,1097,3288,190419041904,"[190419041904]" +person,0,person,1098,3291,1903,"[1903]" +person,0,person,1099,3294,190219021902,"[190219021902]" +person,0,person,1100,3297,1901,"[1901]" +person,0,person,1101,3300,190019001900,"[190019001900]" +person,0,person,1102,3303,1899,"[1899]" +person,0,person,1103,3306,189818981898,"[189818981898]" +person,0,person,1104,3309,1897,"[1897]" +person,0,person,1105,3312,189618961896,"[189618961896]" +person,0,person,1106,3315,1895,"[1895]" +person,0,person,1107,3318,189418941894,"[189418941894]" +person,0,person,1108,3321,1893,"[1893]" +person,0,person,1109,3324,189218921892,"[189218921892]" +person,0,person,1110,3327,1891,"[1891]" +person,0,person,1111,3330,189018901890,"[189018901890]" +person,0,person,1112,3333,1889,"[1889]" +person,0,person,1113,3336,188818881888,"[188818881888]" +person,0,person,1114,3339,1887,"[1887]" +person,0,person,1115,3342,188618861886,"[188618861886]" +person,0,person,1116,3345,1885,"[1885]" +person,0,person,1117,3348,188418841884,"[188418841884]" +person,0,person,1118,3351,1883,"[1883]" +person,0,person,1119,3354,188218821882,"[188218821882]" +person,0,person,1120,3357,1881,"[1881]" +person,0,person,1121,3360,188018801880,"[188018801880]" +person,0,person,1122,3363,1879,"[1879]" +person,0,person,1123,3366,187818781878,"[187818781878]" +person,0,person,1124,3369,1877,"[1877]" +person,0,person,1125,3372,187618761876,"[187618761876]" +person,0,person,1126,3375,1875,"[1875]" +person,0,person,1127,3378,187418741874,"[187418741874]" +person,0,person,1128,3381,1873,"[1873]" +person,0,person,1129,3384,187218721872,"[187218721872]" +person,0,person,1130,3387,1871,"[1871]" +person,0,person,1131,3390,187018701870,"[187018701870]" +person,0,person,1132,3393,1869,"[1869]" +person,0,person,1133,3396,186818681868,"[186818681868]" +person,0,person,1134,3399,1867,"[1867]" +person,0,person,1135,3402,186618661866,"[186618661866]" +person,0,person,1136,3405,1865,"[1865]" +person,0,person,1137,3408,186418641864,"[186418641864]" +person,0,person,1138,3411,1863,"[1863]" +person,0,person,1139,3414,186218621862,"[186218621862]" +person,0,person,1140,3417,1861,"[1861]" +person,0,person,1141,3420,186018601860,"[186018601860]" +person,0,person,1142,3423,1859,"[1859]" +person,0,person,1143,3426,185818581858,"[185818581858]" +person,0,person,1144,3429,1857,"[1857]" +person,0,person,1145,3432,185618561856,"[185618561856]" +person,0,person,1146,3435,1855,"[1855]" +person,0,person,1147,3438,185418541854,"[185418541854]" +person,0,person,1148,3441,1853,"[1853]" +person,0,person,1149,3444,185218521852,"[185218521852]" +person,0,person,1150,3447,1851,"[1851]" +person,0,person,1151,3450,185018501850,"[185018501850]" +person,0,person,1152,3453,1849,"[1849]" +person,0,person,1153,3456,184818481848,"[184818481848]" +person,0,person,1154,3459,1847,"[1847]" +person,0,person,1155,3462,184618461846,"[184618461846]" +person,0,person,1156,3465,1845,"[1845]" +person,0,person,1157,3468,184418441844,"[184418441844]" +person,0,person,1158,3471,1843,"[1843]" +person,0,person,1159,3474,184218421842,"[184218421842]" +person,0,person,1160,3477,1841,"[1841]" +person,0,person,1161,3480,184018401840,"[184018401840]" +person,0,person,1162,3483,1839,"[1839]" +person,0,person,1163,3486,183818381838,"[183818381838]" +person,0,person,1164,3489,1837,"[1837]" +person,0,person,1165,3492,183618361836,"[183618361836]" +person,0,person,1166,3495,1835,"[1835]" +person,0,person,1167,3498,183418341834,"[183418341834]" +person,0,person,1168,3501,1833,"[1833]" +person,0,person,1169,3504,183218321832,"[183218321832]" +person,0,person,1170,3507,1831,"[1831]" +person,0,person,1171,3510,183018301830,"[183018301830]" +person,0,person,1172,3513,1829,"[1829]" +person,0,person,1173,3516,182818281828,"[182818281828]" +person,0,person,1174,3519,1827,"[1827]" +person,0,person,1175,3522,182618261826,"[182618261826]" +person,0,person,1176,3525,1825,"[1825]" +person,0,person,1177,3528,182418241824,"[182418241824]" +person,0,person,1178,3531,1823,"[1823]" +person,0,person,1179,3534,182218221822,"[182218221822]" +person,0,person,1180,3537,1821,"[1821]" +person,0,person,1181,3540,182018201820,"[182018201820]" +person,0,person,1182,3543,1819,"[1819]" +person,0,person,1183,3546,181818181818,"[181818181818]" +person,0,person,1184,3549,1817,"[1817]" +person,0,person,1185,3552,181618161816,"[181618161816]" +person,0,person,1186,3555,1815,"[1815]" +person,0,person,1187,3558,181418141814,"[181418141814]" +person,0,person,1188,3561,1813,"[1813]" +person,0,person,1189,3564,181218121812,"[181218121812]" +person,0,person,1190,3567,1811,"[1811]" +person,0,person,1191,3570,181018101810,"[181018101810]" +person,0,person,1192,3573,1809,"[1809]" +person,0,person,1193,3576,180818081808,"[180818081808]" +person,0,person,1194,3579,1807,"[1807]" +person,0,person,1195,3582,180618061806,"[180618061806]" +person,0,person,1196,3585,1805,"[1805]" +person,0,person,1197,3588,180418041804,"[180418041804]" +person,0,person,1198,3591,1803,"[1803]" +person,0,person,1199,3594,180218021802,"[180218021802]" +person,0,person,1200,3597,1801,"[1801]" +person,0,person,1201,3600,180018001800,"[180018001800]" +person,0,person,1202,3603,1799,"[1799]" +person,0,person,1203,3606,179817981798,"[179817981798]" +person,0,person,1204,3609,1797,"[1797]" +person,0,person,1205,3612,179617961796,"[179617961796]" +person,0,person,1206,3615,1795,"[1795]" +person,0,person,1207,3618,179417941794,"[179417941794]" +person,0,person,1208,3621,1793,"[1793]" +person,0,person,1209,3624,179217921792,"[179217921792]" +person,0,person,1210,3627,1791,"[1791]" +person,0,person,1211,3630,179017901790,"[179017901790]" +person,0,person,1212,3633,1789,"[1789]" +person,0,person,1213,3636,178817881788,"[178817881788]" +person,0,person,1214,3639,1787,"[1787]" +person,0,person,1215,3642,178617861786,"[178617861786]" +person,0,person,1216,3645,1785,"[1785]" +person,0,person,1217,3648,178417841784,"[178417841784]" +person,0,person,1218,3651,1783,"[1783]" +person,0,person,1219,3654,178217821782,"[178217821782]" +person,0,person,1220,3657,1781,"[1781]" +person,0,person,1221,3660,178017801780,"[178017801780]" +person,0,person,1222,3663,1779,"[1779]" +person,0,person,1223,3666,177817781778,"[177817781778]" +person,0,person,1224,3669,1777,"[1777]" +person,0,person,1225,3672,177617761776,"[177617761776]" +person,0,person,1226,3675,1775,"[1775]" +person,0,person,1227,3678,177417741774,"[177417741774]" +person,0,person,1228,3681,1773,"[1773]" +person,0,person,1229,3684,177217721772,"[177217721772]" +person,0,person,1230,3687,1771,"[1771]" +person,0,person,1231,3690,177017701770,"[177017701770]" +person,0,person,1232,3693,1769,"[1769]" +person,0,person,1233,3696,176817681768,"[176817681768]" +person,0,person,1234,3699,1767,"[1767]" +person,0,person,1235,3702,176617661766,"[176617661766]" +person,0,person,1236,3705,1765,"[1765]" +person,0,person,1237,3708,176417641764,"[176417641764]" +person,0,person,1238,3711,1763,"[1763]" +person,0,person,1239,3714,176217621762,"[176217621762]" +person,0,person,1240,3717,1761,"[1761]" +person,0,person,1241,3720,176017601760,"[176017601760]" +person,0,person,1242,3723,1759,"[1759]" +person,0,person,1243,3726,175817581758,"[175817581758]" +person,0,person,1244,3729,1757,"[1757]" +person,0,person,1245,3732,175617561756,"[175617561756]" +person,0,person,1246,3735,1755,"[1755]" +person,0,person,1247,3738,175417541754,"[175417541754]" +person,0,person,1248,3741,1753,"[1753]" +person,0,person,1249,3744,175217521752,"[175217521752]" +person,0,person,1250,3747,1751,"[1751]" +person,0,person,1251,3750,175017501750,"[175017501750]" +person,0,person,1252,3753,1749,"[1749]" +person,0,person,1253,3756,174817481748,"[174817481748]" +person,0,person,1254,3759,1747,"[1747]" +person,0,person,1255,3762,174617461746,"[174617461746]" +person,0,person,1256,3765,1745,"[1745]" +person,0,person,1257,3768,174417441744,"[174417441744]" +person,0,person,1258,3771,1743,"[1743]" +person,0,person,1259,3774,174217421742,"[174217421742]" +person,0,person,1260,3777,1741,"[1741]" +person,0,person,1261,3780,174017401740,"[174017401740]" +person,0,person,1262,3783,1739,"[1739]" +person,0,person,1263,3786,173817381738,"[173817381738]" +person,0,person,1264,3789,1737,"[1737]" +person,0,person,1265,3792,173617361736,"[173617361736]" +person,0,person,1266,3795,1735,"[1735]" +person,0,person,1267,3798,173417341734,"[173417341734]" +person,0,person,1268,3801,1733,"[1733]" +person,0,person,1269,3804,173217321732,"[173217321732]" +person,0,person,1270,3807,1731,"[1731]" +person,0,person,1271,3810,173017301730,"[173017301730]" +person,0,person,1272,3813,1729,"[1729]" +person,0,person,1273,3816,172817281728,"[172817281728]" +person,0,person,1274,3819,1727,"[1727]" +person,0,person,1275,3822,172617261726,"[172617261726]" +person,0,person,1276,3825,1725,"[1725]" +person,0,person,1277,3828,172417241724,"[172417241724]" +person,0,person,1278,3831,1723,"[1723]" +person,0,person,1279,3834,172217221722,"[172217221722]" +person,0,person,1280,3837,1721,"[1721]" +person,0,person,1281,3840,172017201720,"[172017201720]" +person,0,person,1282,3843,1719,"[1719]" +person,0,person,1283,3846,171817181718,"[171817181718]" +person,0,person,1284,3849,1717,"[1717]" +person,0,person,1285,3852,171617161716,"[171617161716]" +person,0,person,1286,3855,1715,"[1715]" +person,0,person,1287,3858,171417141714,"[171417141714]" +person,0,person,1288,3861,1713,"[1713]" +person,0,person,1289,3864,171217121712,"[171217121712]" +person,0,person,1290,3867,1711,"[1711]" +person,0,person,1291,3870,171017101710,"[171017101710]" +person,0,person,1292,3873,1709,"[1709]" +person,0,person,1293,3876,170817081708,"[170817081708]" +person,0,person,1294,3879,1707,"[1707]" +person,0,person,1295,3882,170617061706,"[170617061706]" +person,0,person,1296,3885,1705,"[1705]" +person,0,person,1297,3888,170417041704,"[170417041704]" +person,0,person,1298,3891,1703,"[1703]" +person,0,person,1299,3894,170217021702,"[170217021702]" +person,0,person,1300,3897,1701,"[1701]" +person,0,person,1301,3900,170017001700,"[170017001700]" +person,0,person,1302,3903,1699,"[1699]" +person,0,person,1303,3906,169816981698,"[169816981698]" +person,0,person,1304,3909,1697,"[1697]" +person,0,person,1305,3912,169616961696,"[169616961696]" +person,0,person,1306,3915,1695,"[1695]" +person,0,person,1307,3918,169416941694,"[169416941694]" +person,0,person,1308,3921,1693,"[1693]" +person,0,person,1309,3924,169216921692,"[169216921692]" +person,0,person,1310,3927,1691,"[1691]" +person,0,person,1311,3930,169016901690,"[169016901690]" +person,0,person,1312,3933,1689,"[1689]" +person,0,person,1313,3936,168816881688,"[168816881688]" +person,0,person,1314,3939,1687,"[1687]" +person,0,person,1315,3942,168616861686,"[168616861686]" +person,0,person,1316,3945,1685,"[1685]" +person,0,person,1317,3948,168416841684,"[168416841684]" +person,0,person,1318,3951,1683,"[1683]" +person,0,person,1319,3954,168216821682,"[168216821682]" +person,0,person,1320,3957,1681,"[1681]" +person,0,person,1321,3960,168016801680,"[168016801680]" +person,0,person,1322,3963,1679,"[1679]" +person,0,person,1323,3966,167816781678,"[167816781678]" +person,0,person,1324,3969,1677,"[1677]" +person,0,person,1325,3972,167616761676,"[167616761676]" +person,0,person,1326,3975,1675,"[1675]" +person,0,person,1327,3978,167416741674,"[167416741674]" +person,0,person,1328,3981,1673,"[1673]" +person,0,person,1329,3984,167216721672,"[167216721672]" +person,0,person,1330,3987,1671,"[1671]" +person,0,person,1331,3990,167016701670,"[167016701670]" +person,0,person,1332,3993,1669,"[1669]" +person,0,person,1333,3996,166816681668,"[166816681668]" +person,0,person,1334,3999,1667,"[1667]" +person,0,person,1335,4002,166616661666,"[166616661666]" +person,0,person,1336,4005,1665,"[1665]" +person,0,person,1337,4008,166416641664,"[166416641664]" +person,0,person,1338,4011,1663,"[1663]" +person,0,person,1339,4014,166216621662,"[166216621662]" +person,0,person,1340,4017,1661,"[1661]" +person,0,person,1341,4020,166016601660,"[166016601660]" +person,0,person,1342,4023,1659,"[1659]" +person,0,person,1343,4026,165816581658,"[165816581658]" +person,0,person,1344,4029,1657,"[1657]" +person,0,person,1345,4032,165616561656,"[165616561656]" +person,0,person,1346,4035,1655,"[1655]" +person,0,person,1347,4038,165416541654,"[165416541654]" +person,0,person,1348,4041,1653,"[1653]" +person,0,person,1349,4044,165216521652,"[165216521652]" +person,0,person,1350,4047,1651,"[1651]" +person,0,person,1351,4050,165016501650,"[165016501650]" +person,0,person,1352,4053,1649,"[1649]" +person,0,person,1353,4056,164816481648,"[164816481648]" +person,0,person,1354,4059,1647,"[1647]" +person,0,person,1355,4062,164616461646,"[164616461646]" +person,0,person,1356,4065,1645,"[1645]" +person,0,person,1357,4068,164416441644,"[164416441644]" +person,0,person,1358,4071,1643,"[1643]" +person,0,person,1359,4074,164216421642,"[164216421642]" +person,0,person,1360,4077,1641,"[1641]" +person,0,person,1361,4080,164016401640,"[164016401640]" +person,0,person,1362,4083,1639,"[1639]" +person,0,person,1363,4086,163816381638,"[163816381638]" +person,0,person,1364,4089,1637,"[1637]" +person,0,person,1365,4092,163616361636,"[163616361636]" +person,0,person,1366,4095,1635,"[1635]" +person,0,person,1367,4098,163416341634,"[163416341634]" +person,0,person,1368,4101,1633,"[1633]" +person,0,person,1369,4104,163216321632,"[163216321632]" +person,0,person,1370,4107,1631,"[1631]" +person,0,person,1371,4110,163016301630,"[163016301630]" +person,0,person,1372,4113,1629,"[1629]" +person,0,person,1373,4116,162816281628,"[162816281628]" +person,0,person,1374,4119,1627,"[1627]" +person,0,person,1375,4122,162616261626,"[162616261626]" +person,0,person,1376,4125,1625,"[1625]" +person,0,person,1377,4128,162416241624,"[162416241624]" +person,0,person,1378,4131,1623,"[1623]" +person,0,person,1379,4134,162216221622,"[162216221622]" +person,0,person,1380,4137,1621,"[1621]" +person,0,person,1381,4140,162016201620,"[162016201620]" +person,0,person,1382,4143,1619,"[1619]" +person,0,person,1383,4146,161816181618,"[161816181618]" +person,0,person,1384,4149,1617,"[1617]" +person,0,person,1385,4152,161616161616,"[161616161616]" +person,0,person,1386,4155,1615,"[1615]" +person,0,person,1387,4158,161416141614,"[161416141614]" +person,0,person,1388,4161,1613,"[1613]" +person,0,person,1389,4164,161216121612,"[161216121612]" +person,0,person,1390,4167,1611,"[1611]" +person,0,person,1391,4170,161016101610,"[161016101610]" +person,0,person,1392,4173,1609,"[1609]" +person,0,person,1393,4176,160816081608,"[160816081608]" +person,0,person,1394,4179,1607,"[1607]" +person,0,person,1395,4182,160616061606,"[160616061606]" +person,0,person,1396,4185,1605,"[1605]" +person,0,person,1397,4188,160416041604,"[160416041604]" +person,0,person,1398,4191,1603,"[1603]" +person,0,person,1399,4194,160216021602,"[160216021602]" +person,0,person,1400,4197,1601,"[1601]" +person,0,person,1401,4200,160016001600,"[160016001600]" +person,0,person,1402,4203,1599,"[1599]" +person,0,person,1403,4206,159815981598,"[159815981598]" +person,0,person,1404,4209,1597,"[1597]" +person,0,person,1405,4212,159615961596,"[159615961596]" +person,0,person,1406,4215,1595,"[1595]" +person,0,person,1407,4218,159415941594,"[159415941594]" +person,0,person,1408,4221,1593,"[1593]" +person,0,person,1409,4224,159215921592,"[159215921592]" +person,0,person,1410,4227,1591,"[1591]" +person,0,person,1411,4230,159015901590,"[159015901590]" +person,0,person,1412,4233,1589,"[1589]" +person,0,person,1413,4236,158815881588,"[158815881588]" +person,0,person,1414,4239,1587,"[1587]" +person,0,person,1415,4242,158615861586,"[158615861586]" +person,0,person,1416,4245,1585,"[1585]" +person,0,person,1417,4248,158415841584,"[158415841584]" +person,0,person,1418,4251,1583,"[1583]" +person,0,person,1419,4254,158215821582,"[158215821582]" +person,0,person,1420,4257,1581,"[1581]" +person,0,person,1421,4260,158015801580,"[158015801580]" +person,0,person,1422,4263,1579,"[1579]" +person,0,person,1423,4266,157815781578,"[157815781578]" +person,0,person,1424,4269,1577,"[1577]" +person,0,person,1425,4272,157615761576,"[157615761576]" +person,0,person,1426,4275,1575,"[1575]" +person,0,person,1427,4278,157415741574,"[157415741574]" +person,0,person,1428,4281,1573,"[1573]" +person,0,person,1429,4284,157215721572,"[157215721572]" +person,0,person,1430,4287,1571,"[1571]" +person,0,person,1431,4290,157015701570,"[157015701570]" +person,0,person,1432,4293,1569,"[1569]" +person,0,person,1433,4296,156815681568,"[156815681568]" +person,0,person,1434,4299,1567,"[1567]" +person,0,person,1435,4302,156615661566,"[156615661566]" +person,0,person,1436,4305,1565,"[1565]" +person,0,person,1437,4308,156415641564,"[156415641564]" +person,0,person,1438,4311,1563,"[1563]" +person,0,person,1439,4314,156215621562,"[156215621562]" +person,0,person,1440,4317,1561,"[1561]" +person,0,person,1441,4320,156015601560,"[156015601560]" +person,0,person,1442,4323,1559,"[1559]" +person,0,person,1443,4326,155815581558,"[155815581558]" +person,0,person,1444,4329,1557,"[1557]" +person,0,person,1445,4332,155615561556,"[155615561556]" +person,0,person,1446,4335,1555,"[1555]" +person,0,person,1447,4338,155415541554,"[155415541554]" +person,0,person,1448,4341,1553,"[1553]" +person,0,person,1449,4344,155215521552,"[155215521552]" +person,0,person,1450,4347,1551,"[1551]" +person,0,person,1451,4350,155015501550,"[155015501550]" +person,0,person,1452,4353,1549,"[1549]" +person,0,person,1453,4356,154815481548,"[154815481548]" +person,0,person,1454,4359,1547,"[1547]" +person,0,person,1455,4362,154615461546,"[154615461546]" +person,0,person,1456,4365,1545,"[1545]" +person,0,person,1457,4368,154415441544,"[154415441544]" +person,0,person,1458,4371,1543,"[1543]" +person,0,person,1459,4374,154215421542,"[154215421542]" +person,0,person,1460,4377,1541,"[1541]" +person,0,person,1461,4380,154015401540,"[154015401540]" +person,0,person,1462,4383,1539,"[1539]" +person,0,person,1463,4386,153815381538,"[153815381538]" +person,0,person,1464,4389,1537,"[1537]" +person,0,person,1465,4392,153615361536,"[153615361536]" +person,0,person,1466,4395,1535,"[1535]" +person,0,person,1467,4398,153415341534,"[153415341534]" +person,0,person,1468,4401,1533,"[1533]" +person,0,person,1469,4404,153215321532,"[153215321532]" +person,0,person,1470,4407,1531,"[1531]" +person,0,person,1471,4410,153015301530,"[153015301530]" +person,0,person,1472,4413,1529,"[1529]" +person,0,person,1473,4416,152815281528,"[152815281528]" +person,0,person,1474,4419,1527,"[1527]" +person,0,person,1475,4422,152615261526,"[152615261526]" +person,0,person,1476,4425,1525,"[1525]" +person,0,person,1477,4428,152415241524,"[152415241524]" +person,0,person,1478,4431,1523,"[1523]" +person,0,person,1479,4434,152215221522,"[152215221522]" +person,0,person,1480,4437,1521,"[1521]" +person,0,person,1481,4440,152015201520,"[152015201520]" +person,0,person,1482,4443,1519,"[1519]" +person,0,person,1483,4446,151815181518,"[151815181518]" +person,0,person,1484,4449,1517,"[1517]" +person,0,person,1485,4452,151615161516,"[151615161516]" +person,0,person,1486,4455,1515,"[1515]" +person,0,person,1487,4458,151415141514,"[151415141514]" +person,0,person,1488,4461,1513,"[1513]" +person,0,person,1489,4464,151215121512,"[151215121512]" +person,0,person,1490,4467,1511,"[1511]" +person,0,person,1491,4470,151015101510,"[151015101510]" +person,0,person,1492,4473,1509,"[1509]" +person,0,person,1493,4476,150815081508,"[150815081508]" +person,0,person,1494,4479,1507,"[1507]" +person,0,person,1495,4482,150615061506,"[150615061506]" +person,0,person,1496,4485,1505,"[1505]" +person,0,person,1497,4488,150415041504,"[150415041504]" +person,0,person,1498,4491,1503,"[1503]" +person,0,person,1499,4494,150215021502,"[150215021502]" +person,0,person,1500,4497,1501,"[1501]" +person,0,person,1501,4500,150015001500,"[150015001500]" +person,0,person,1502,4503,1499,"[1499]" +person,0,person,1503,4506,149814981498,"[149814981498]" +person,0,person,1504,4509,1497,"[1497]" +person,0,person,1505,4512,149614961496,"[149614961496]" +person,0,person,1506,4515,1495,"[1495]" +person,0,person,1507,4518,149414941494,"[149414941494]" +person,0,person,1508,4521,1493,"[1493]" +person,0,person,1509,4524,149214921492,"[149214921492]" +person,0,person,1510,4527,1491,"[1491]" +person,0,person,1511,4530,149014901490,"[149014901490]" +person,0,person,1512,4533,1489,"[1489]" +person,0,person,1513,4536,148814881488,"[148814881488]" +person,0,person,1514,4539,1487,"[1487]" +person,0,person,1515,4542,148614861486,"[148614861486]" +person,0,person,1516,4545,1485,"[1485]" +person,0,person,1517,4548,148414841484,"[148414841484]" +person,0,person,1518,4551,1483,"[1483]" +person,0,person,1519,4554,148214821482,"[148214821482]" +person,0,person,1520,4557,1481,"[1481]" +person,0,person,1521,4560,148014801480,"[148014801480]" +person,0,person,1522,4563,1479,"[1479]" +person,0,person,1523,4566,147814781478,"[147814781478]" +person,0,person,1524,4569,1477,"[1477]" +person,0,person,1525,4572,147614761476,"[147614761476]" +person,0,person,1526,4575,1475,"[1475]" +person,0,person,1527,4578,147414741474,"[147414741474]" +person,0,person,1528,4581,1473,"[1473]" +person,0,person,1529,4584,147214721472,"[147214721472]" +person,0,person,1530,4587,1471,"[1471]" +person,0,person,1531,4590,147014701470,"[147014701470]" +person,0,person,1532,4593,1469,"[1469]" +person,0,person,1533,4596,146814681468,"[146814681468]" +person,0,person,1534,4599,1467,"[1467]" +person,0,person,1535,4602,146614661466,"[146614661466]" +person,0,person,1536,4605,1465,"[1465]" +person,0,person,1537,4608,146414641464,"[146414641464]" +person,0,person,1538,4611,1463,"[1463]" +person,0,person,1539,4614,146214621462,"[146214621462]" +person,0,person,1540,4617,1461,"[1461]" +person,0,person,1541,4620,146014601460,"[146014601460]" +person,0,person,1542,4623,1459,"[1459]" +person,0,person,1543,4626,145814581458,"[145814581458]" +person,0,person,1544,4629,1457,"[1457]" +person,0,person,1545,4632,145614561456,"[145614561456]" +person,0,person,1546,4635,1455,"[1455]" +person,0,person,1547,4638,145414541454,"[145414541454]" +person,0,person,1548,4641,1453,"[1453]" +person,0,person,1549,4644,145214521452,"[145214521452]" +person,0,person,1550,4647,1451,"[1451]" +person,0,person,1551,4650,145014501450,"[145014501450]" +person,0,person,1552,4653,1449,"[1449]" +person,0,person,1553,4656,144814481448,"[144814481448]" +person,0,person,1554,4659,1447,"[1447]" +person,0,person,1555,4662,144614461446,"[144614461446]" +person,0,person,1556,4665,1445,"[1445]" +person,0,person,1557,4668,144414441444,"[144414441444]" +person,0,person,1558,4671,1443,"[1443]" +person,0,person,1559,4674,144214421442,"[144214421442]" +person,0,person,1560,4677,1441,"[1441]" +person,0,person,1561,4680,144014401440,"[144014401440]" +person,0,person,1562,4683,1439,"[1439]" +person,0,person,1563,4686,143814381438,"[143814381438]" +person,0,person,1564,4689,1437,"[1437]" +person,0,person,1565,4692,143614361436,"[143614361436]" +person,0,person,1566,4695,1435,"[1435]" +person,0,person,1567,4698,143414341434,"[143414341434]" +person,0,person,1568,4701,1433,"[1433]" +person,0,person,1569,4704,143214321432,"[143214321432]" +person,0,person,1570,4707,1431,"[1431]" +person,0,person,1571,4710,143014301430,"[143014301430]" +person,0,person,1572,4713,1429,"[1429]" +person,0,person,1573,4716,142814281428,"[142814281428]" +person,0,person,1574,4719,1427,"[1427]" +person,0,person,1575,4722,142614261426,"[142614261426]" +person,0,person,1576,4725,1425,"[1425]" +person,0,person,1577,4728,142414241424,"[142414241424]" +person,0,person,1578,4731,1423,"[1423]" +person,0,person,1579,4734,142214221422,"[142214221422]" +person,0,person,1580,4737,1421,"[1421]" +person,0,person,1581,4740,142014201420,"[142014201420]" +person,0,person,1582,4743,1419,"[1419]" +person,0,person,1583,4746,141814181418,"[141814181418]" +person,0,person,1584,4749,1417,"[1417]" +person,0,person,1585,4752,141614161416,"[141614161416]" +person,0,person,1586,4755,1415,"[1415]" +person,0,person,1587,4758,141414141414,"[141414141414]" +person,0,person,1588,4761,1413,"[1413]" +person,0,person,1589,4764,141214121412,"[141214121412]" +person,0,person,1590,4767,1411,"[1411]" +person,0,person,1591,4770,141014101410,"[141014101410]" +person,0,person,1592,4773,1409,"[1409]" +person,0,person,1593,4776,140814081408,"[140814081408]" +person,0,person,1594,4779,1407,"[1407]" +person,0,person,1595,4782,140614061406,"[140614061406]" +person,0,person,1596,4785,1405,"[1405]" +person,0,person,1597,4788,140414041404,"[140414041404]" +person,0,person,1598,4791,1403,"[1403]" +person,0,person,1599,4794,140214021402,"[140214021402]" +person,0,person,1600,4797,1401,"[1401]" +person,0,person,1601,4800,140014001400,"[140014001400]" +person,0,person,1602,4803,1399,"[1399]" +person,0,person,1603,4806,139813981398,"[139813981398]" +person,0,person,1604,4809,1397,"[1397]" +person,0,person,1605,4812,139613961396,"[139613961396]" +person,0,person,1606,4815,1395,"[1395]" +person,0,person,1607,4818,139413941394,"[139413941394]" +person,0,person,1608,4821,1393,"[1393]" +person,0,person,1609,4824,139213921392,"[139213921392]" +person,0,person,1610,4827,1391,"[1391]" +person,0,person,1611,4830,139013901390,"[139013901390]" +person,0,person,1612,4833,1389,"[1389]" +person,0,person,1613,4836,138813881388,"[138813881388]" +person,0,person,1614,4839,1387,"[1387]" +person,0,person,1615,4842,138613861386,"[138613861386]" +person,0,person,1616,4845,1385,"[1385]" +person,0,person,1617,4848,138413841384,"[138413841384]" +person,0,person,1618,4851,1383,"[1383]" +person,0,person,1619,4854,138213821382,"[138213821382]" +person,0,person,1620,4857,1381,"[1381]" +person,0,person,1621,4860,138013801380,"[138013801380]" +person,0,person,1622,4863,1379,"[1379]" +person,0,person,1623,4866,137813781378,"[137813781378]" +person,0,person,1624,4869,1377,"[1377]" +person,0,person,1625,4872,137613761376,"[137613761376]" +person,0,person,1626,4875,1375,"[1375]" +person,0,person,1627,4878,137413741374,"[137413741374]" +person,0,person,1628,4881,1373,"[1373]" +person,0,person,1629,4884,137213721372,"[137213721372]" +person,0,person,1630,4887,1371,"[1371]" +person,0,person,1631,4890,137013701370,"[137013701370]" +person,0,person,1632,4893,1369,"[1369]" +person,0,person,1633,4896,136813681368,"[136813681368]" +person,0,person,1634,4899,1367,"[1367]" +person,0,person,1635,4902,136613661366,"[136613661366]" +person,0,person,1636,4905,1365,"[1365]" +person,0,person,1637,4908,136413641364,"[136413641364]" +person,0,person,1638,4911,1363,"[1363]" +person,0,person,1639,4914,136213621362,"[136213621362]" +person,0,person,1640,4917,1361,"[1361]" +person,0,person,1641,4920,136013601360,"[136013601360]" +person,0,person,1642,4923,1359,"[1359]" +person,0,person,1643,4926,135813581358,"[135813581358]" +person,0,person,1644,4929,1357,"[1357]" +person,0,person,1645,4932,135613561356,"[135613561356]" +person,0,person,1646,4935,1355,"[1355]" +person,0,person,1647,4938,135413541354,"[135413541354]" +person,0,person,1648,4941,1353,"[1353]" +person,0,person,1649,4944,135213521352,"[135213521352]" +person,0,person,1650,4947,1351,"[1351]" +person,0,person,1651,4950,135013501350,"[135013501350]" +person,0,person,1652,4953,1349,"[1349]" +person,0,person,1653,4956,134813481348,"[134813481348]" +person,0,person,1654,4959,1347,"[1347]" +person,0,person,1655,4962,134613461346,"[134613461346]" +person,0,person,1656,4965,1345,"[1345]" +person,0,person,1657,4968,134413441344,"[134413441344]" +person,0,person,1658,4971,1343,"[1343]" +person,0,person,1659,4974,134213421342,"[134213421342]" +person,0,person,1660,4977,1341,"[1341]" +person,0,person,1661,4980,134013401340,"[134013401340]" +person,0,person,1662,4983,1339,"[1339]" +person,0,person,1663,4986,133813381338,"[133813381338]" +person,0,person,1664,4989,1337,"[1337]" +person,0,person,1665,4992,133613361336,"[133613361336]" +person,0,person,1666,4995,1335,"[1335]" +person,0,person,1667,4998,133413341334,"[133413341334]" +person,0,person,1668,5001,1333,"[1333]" +person,0,person,1669,5004,133213321332,"[133213321332]" +person,0,person,1670,5007,1331,"[1331]" +person,0,person,1671,5010,133013301330,"[133013301330]" +person,0,person,1672,5013,1329,"[1329]" +person,0,person,1673,5016,132813281328,"[132813281328]" +person,0,person,1674,5019,1327,"[1327]" +person,0,person,1675,5022,132613261326,"[132613261326]" +person,0,person,1676,5025,1325,"[1325]" +person,0,person,1677,5028,132413241324,"[132413241324]" +person,0,person,1678,5031,1323,"[1323]" +person,0,person,1679,5034,132213221322,"[132213221322]" +person,0,person,1680,5037,1321,"[1321]" +person,0,person,1681,5040,132013201320,"[132013201320]" +person,0,person,1682,5043,1319,"[1319]" +person,0,person,1683,5046,131813181318,"[131813181318]" +person,0,person,1684,5049,1317,"[1317]" +person,0,person,1685,5052,131613161316,"[131613161316]" +person,0,person,1686,5055,1315,"[1315]" +person,0,person,1687,5058,131413141314,"[131413141314]" +person,0,person,1688,5061,1313,"[1313]" +person,0,person,1689,5064,131213121312,"[131213121312]" +person,0,person,1690,5067,1311,"[1311]" +person,0,person,1691,5070,131013101310,"[131013101310]" +person,0,person,1692,5073,1309,"[1309]" +person,0,person,1693,5076,130813081308,"[130813081308]" +person,0,person,1694,5079,1307,"[1307]" +person,0,person,1695,5082,130613061306,"[130613061306]" +person,0,person,1696,5085,1305,"[1305]" +person,0,person,1697,5088,130413041304,"[130413041304]" +person,0,person,1698,5091,1303,"[1303]" +person,0,person,1699,5094,130213021302,"[130213021302]" +person,0,person,1700,5097,1301,"[1301]" +person,0,person,1701,5100,130013001300,"[130013001300]" +person,0,person,1702,5103,1299,"[1299]" +person,0,person,1703,5106,129812981298,"[129812981298]" +person,0,person,1704,5109,1297,"[1297]" +person,0,person,1705,5112,129612961296,"[129612961296]" +person,0,person,1706,5115,1295,"[1295]" +person,0,person,1707,5118,129412941294,"[129412941294]" +person,0,person,1708,5121,1293,"[1293]" +person,0,person,1709,5124,129212921292,"[129212921292]" +person,0,person,1710,5127,1291,"[1291]" +person,0,person,1711,5130,129012901290,"[129012901290]" +person,0,person,1712,5133,1289,"[1289]" +person,0,person,1713,5136,128812881288,"[128812881288]" +person,0,person,1714,5139,1287,"[1287]" +person,0,person,1715,5142,128612861286,"[128612861286]" +person,0,person,1716,5145,1285,"[1285]" +person,0,person,1717,5148,128412841284,"[128412841284]" +person,0,person,1718,5151,1283,"[1283]" +person,0,person,1719,5154,128212821282,"[128212821282]" +person,0,person,1720,5157,1281,"[1281]" +person,0,person,1721,5160,128012801280,"[128012801280]" +person,0,person,1722,5163,1279,"[1279]" +person,0,person,1723,5166,127812781278,"[127812781278]" +person,0,person,1724,5169,1277,"[1277]" +person,0,person,1725,5172,127612761276,"[127612761276]" +person,0,person,1726,5175,1275,"[1275]" +person,0,person,1727,5178,127412741274,"[127412741274]" +person,0,person,1728,5181,1273,"[1273]" +person,0,person,1729,5184,127212721272,"[127212721272]" +person,0,person,1730,5187,1271,"[1271]" +person,0,person,1731,5190,127012701270,"[127012701270]" +person,0,person,1732,5193,1269,"[1269]" +person,0,person,1733,5196,126812681268,"[126812681268]" +person,0,person,1734,5199,1267,"[1267]" +person,0,person,1735,5202,126612661266,"[126612661266]" +person,0,person,1736,5205,1265,"[1265]" +person,0,person,1737,5208,126412641264,"[126412641264]" +person,0,person,1738,5211,1263,"[1263]" +person,0,person,1739,5214,126212621262,"[126212621262]" +person,0,person,1740,5217,1261,"[1261]" +person,0,person,1741,5220,126012601260,"[126012601260]" +person,0,person,1742,5223,1259,"[1259]" +person,0,person,1743,5226,125812581258,"[125812581258]" +person,0,person,1744,5229,1257,"[1257]" +person,0,person,1745,5232,125612561256,"[125612561256]" +person,0,person,1746,5235,1255,"[1255]" +person,0,person,1747,5238,125412541254,"[125412541254]" +person,0,person,1748,5241,1253,"[1253]" +person,0,person,1749,5244,125212521252,"[125212521252]" +person,0,person,1750,5247,1251,"[1251]" +person,0,person,1751,5250,125012501250,"[125012501250]" +person,0,person,1752,5253,1249,"[1249]" +person,0,person,1753,5256,124812481248,"[124812481248]" +person,0,person,1754,5259,1247,"[1247]" +person,0,person,1755,5262,124612461246,"[124612461246]" +person,0,person,1756,5265,1245,"[1245]" +person,0,person,1757,5268,124412441244,"[124412441244]" +person,0,person,1758,5271,1243,"[1243]" +person,0,person,1759,5274,124212421242,"[124212421242]" +person,0,person,1760,5277,1241,"[1241]" +person,0,person,1761,5280,124012401240,"[124012401240]" +person,0,person,1762,5283,1239,"[1239]" +person,0,person,1763,5286,123812381238,"[123812381238]" +person,0,person,1764,5289,1237,"[1237]" +person,0,person,1765,5292,123612361236,"[123612361236]" +person,0,person,1766,5295,1235,"[1235]" +person,0,person,1767,5298,123412341234,"[123412341234]" +person,0,person,1768,5301,1233,"[1233]" +person,0,person,1769,5304,123212321232,"[123212321232]" +person,0,person,1770,5307,1231,"[1231]" +person,0,person,1771,5310,123012301230,"[123012301230]" +person,0,person,1772,5313,1229,"[1229]" +person,0,person,1773,5316,122812281228,"[122812281228]" +person,0,person,1774,5319,1227,"[1227]" +person,0,person,1775,5322,122612261226,"[122612261226]" +person,0,person,1776,5325,1225,"[1225]" +person,0,person,1777,5328,122412241224,"[122412241224]" +person,0,person,1778,5331,1223,"[1223]" +person,0,person,1779,5334,122212221222,"[122212221222]" +person,0,person,1780,5337,1221,"[1221]" +person,0,person,1781,5340,122012201220,"[122012201220]" +person,0,person,1782,5343,1219,"[1219]" +person,0,person,1783,5346,121812181218,"[121812181218]" +person,0,person,1784,5349,1217,"[1217]" +person,0,person,1785,5352,121612161216,"[121612161216]" +person,0,person,1786,5355,1215,"[1215]" +person,0,person,1787,5358,121412141214,"[121412141214]" +person,0,person,1788,5361,1213,"[1213]" +person,0,person,1789,5364,121212121212,"[121212121212]" +person,0,person,1790,5367,1211,"[1211]" +person,0,person,1791,5370,121012101210,"[121012101210]" +person,0,person,1792,5373,1209,"[1209]" +person,0,person,1793,5376,120812081208,"[120812081208]" +person,0,person,1794,5379,1207,"[1207]" +person,0,person,1795,5382,120612061206,"[120612061206]" +person,0,person,1796,5385,1205,"[1205]" +person,0,person,1797,5388,120412041204,"[120412041204]" +person,0,person,1798,5391,1203,"[1203]" +person,0,person,1799,5394,120212021202,"[120212021202]" +person,0,person,1800,5397,1201,"[1201]" +person,0,person,1801,5400,120012001200,"[120012001200]" +person,0,person,1802,5403,1199,"[1199]" +person,0,person,1803,5406,119811981198,"[119811981198]" +person,0,person,1804,5409,1197,"[1197]" +person,0,person,1805,5412,119611961196,"[119611961196]" +person,0,person,1806,5415,1195,"[1195]" +person,0,person,1807,5418,119411941194,"[119411941194]" +person,0,person,1808,5421,1193,"[1193]" +person,0,person,1809,5424,119211921192,"[119211921192]" +person,0,person,1810,5427,1191,"[1191]" +person,0,person,1811,5430,119011901190,"[119011901190]" +person,0,person,1812,5433,1189,"[1189]" +person,0,person,1813,5436,118811881188,"[118811881188]" +person,0,person,1814,5439,1187,"[1187]" +person,0,person,1815,5442,118611861186,"[118611861186]" +person,0,person,1816,5445,1185,"[1185]" +person,0,person,1817,5448,118411841184,"[118411841184]" +person,0,person,1818,5451,1183,"[1183]" +person,0,person,1819,5454,118211821182,"[118211821182]" +person,0,person,1820,5457,1181,"[1181]" +person,0,person,1821,5460,118011801180,"[118011801180]" +person,0,person,1822,5463,1179,"[1179]" +person,0,person,1823,5466,117811781178,"[117811781178]" +person,0,person,1824,5469,1177,"[1177]" +person,0,person,1825,5472,117611761176,"[117611761176]" +person,0,person,1826,5475,1175,"[1175]" +person,0,person,1827,5478,117411741174,"[117411741174]" +person,0,person,1828,5481,1173,"[1173]" +person,0,person,1829,5484,117211721172,"[117211721172]" +person,0,person,1830,5487,1171,"[1171]" +person,0,person,1831,5490,117011701170,"[117011701170]" +person,0,person,1832,5493,1169,"[1169]" +person,0,person,1833,5496,116811681168,"[116811681168]" +person,0,person,1834,5499,1167,"[1167]" +person,0,person,1835,5502,116611661166,"[116611661166]" +person,0,person,1836,5505,1165,"[1165]" +person,0,person,1837,5508,116411641164,"[116411641164]" +person,0,person,1838,5511,1163,"[1163]" +person,0,person,1839,5514,116211621162,"[116211621162]" +person,0,person,1840,5517,1161,"[1161]" +person,0,person,1841,5520,116011601160,"[116011601160]" +person,0,person,1842,5523,1159,"[1159]" +person,0,person,1843,5526,115811581158,"[115811581158]" +person,0,person,1844,5529,1157,"[1157]" +person,0,person,1845,5532,115611561156,"[115611561156]" +person,0,person,1846,5535,1155,"[1155]" +person,0,person,1847,5538,115411541154,"[115411541154]" +person,0,person,1848,5541,1153,"[1153]" +person,0,person,1849,5544,115211521152,"[115211521152]" +person,0,person,1850,5547,1151,"[1151]" +person,0,person,1851,5550,115011501150,"[115011501150]" +person,0,person,1852,5553,1149,"[1149]" +person,0,person,1853,5556,114811481148,"[114811481148]" +person,0,person,1854,5559,1147,"[1147]" +person,0,person,1855,5562,114611461146,"[114611461146]" +person,0,person,1856,5565,1145,"[1145]" +person,0,person,1857,5568,114411441144,"[114411441144]" +person,0,person,1858,5571,1143,"[1143]" +person,0,person,1859,5574,114211421142,"[114211421142]" +person,0,person,1860,5577,1141,"[1141]" +person,0,person,1861,5580,114011401140,"[114011401140]" +person,0,person,1862,5583,1139,"[1139]" +person,0,person,1863,5586,113811381138,"[113811381138]" +person,0,person,1864,5589,1137,"[1137]" +person,0,person,1865,5592,113611361136,"[113611361136]" +person,0,person,1866,5595,1135,"[1135]" +person,0,person,1867,5598,113411341134,"[113411341134]" +person,0,person,1868,5601,1133,"[1133]" +person,0,person,1869,5604,113211321132,"[113211321132]" +person,0,person,1870,5607,1131,"[1131]" +person,0,person,1871,5610,113011301130,"[113011301130]" +person,0,person,1872,5613,1129,"[1129]" +person,0,person,1873,5616,112811281128,"[112811281128]" +person,0,person,1874,5619,1127,"[1127]" +person,0,person,1875,5622,112611261126,"[112611261126]" +person,0,person,1876,5625,1125,"[1125]" +person,0,person,1877,5628,112411241124,"[112411241124]" +person,0,person,1878,5631,1123,"[1123]" +person,0,person,1879,5634,112211221122,"[112211221122]" +person,0,person,1880,5637,1121,"[1121]" +person,0,person,1881,5640,112011201120,"[112011201120]" +person,0,person,1882,5643,1119,"[1119]" +person,0,person,1883,5646,111811181118,"[111811181118]" +person,0,person,1884,5649,1117,"[1117]" +person,0,person,1885,5652,111611161116,"[111611161116]" +person,0,person,1886,5655,1115,"[1115]" +person,0,person,1887,5658,111411141114,"[111411141114]" +person,0,person,1888,5661,1113,"[1113]" +person,0,person,1889,5664,111211121112,"[111211121112]" +person,0,person,1890,5667,1111,"[1111]" +person,0,person,1891,5670,111011101110,"[111011101110]" +person,0,person,1892,5673,1109,"[1109]" +person,0,person,1893,5676,110811081108,"[110811081108]" +person,0,person,1894,5679,1107,"[1107]" +person,0,person,1895,5682,110611061106,"[110611061106]" +person,0,person,1896,5685,1105,"[1105]" +person,0,person,1897,5688,110411041104,"[110411041104]" +person,0,person,1898,5691,1103,"[1103]" +person,0,person,1899,5694,110211021102,"[110211021102]" +person,0,person,1900,5697,1101,"[1101]" +person,0,person,1901,5700,110011001100,"[110011001100]" +person,0,person,1902,5703,1099,"[1099]" +person,0,person,1903,5706,109810981098,"[109810981098]" +person,0,person,1904,5709,1097,"[1097]" +person,0,person,1905,5712,109610961096,"[109610961096]" +person,0,person,1906,5715,1095,"[1095]" +person,0,person,1907,5718,109410941094,"[109410941094]" +person,0,person,1908,5721,1093,"[1093]" +person,0,person,1909,5724,109210921092,"[109210921092]" +person,0,person,1910,5727,1091,"[1091]" +person,0,person,1911,5730,109010901090,"[109010901090]" +person,0,person,1912,5733,1089,"[1089]" +person,0,person,1913,5736,108810881088,"[108810881088]" +person,0,person,1914,5739,1087,"[1087]" +person,0,person,1915,5742,108610861086,"[108610861086]" +person,0,person,1916,5745,1085,"[1085]" +person,0,person,1917,5748,108410841084,"[108410841084]" +person,0,person,1918,5751,1083,"[1083]" +person,0,person,1919,5754,108210821082,"[108210821082]" +person,0,person,1920,5757,1081,"[1081]" +person,0,person,1921,5760,108010801080,"[108010801080]" +person,0,person,1922,5763,1079,"[1079]" +person,0,person,1923,5766,107810781078,"[107810781078]" +person,0,person,1924,5769,1077,"[1077]" +person,0,person,1925,5772,107610761076,"[107610761076]" +person,0,person,1926,5775,1075,"[1075]" +person,0,person,1927,5778,107410741074,"[107410741074]" +person,0,person,1928,5781,1073,"[1073]" +person,0,person,1929,5784,107210721072,"[107210721072]" +person,0,person,1930,5787,1071,"[1071]" +person,0,person,1931,5790,107010701070,"[107010701070]" +person,0,person,1932,5793,1069,"[1069]" +person,0,person,1933,5796,106810681068,"[106810681068]" +person,0,person,1934,5799,1067,"[1067]" +person,0,person,1935,5802,106610661066,"[106610661066]" +person,0,person,1936,5805,1065,"[1065]" +person,0,person,1937,5808,106410641064,"[106410641064]" +person,0,person,1938,5811,1063,"[1063]" +person,0,person,1939,5814,106210621062,"[106210621062]" +person,0,person,1940,5817,1061,"[1061]" +person,0,person,1941,5820,106010601060,"[106010601060]" +person,0,person,1942,5823,1059,"[1059]" +person,0,person,1943,5826,105810581058,"[105810581058]" +person,0,person,1944,5829,1057,"[1057]" +person,0,person,1945,5832,105610561056,"[105610561056]" +person,0,person,1946,5835,1055,"[1055]" +person,0,person,1947,5838,105410541054,"[105410541054]" +person,0,person,1948,5841,1053,"[1053]" +person,0,person,1949,5844,105210521052,"[105210521052]" +person,0,person,1950,5847,1051,"[1051]" +person,0,person,1951,5850,105010501050,"[105010501050]" +person,0,person,1952,5853,1049,"[1049]" +person,0,person,1953,5856,104810481048,"[104810481048]" +person,0,person,1954,5859,1047,"[1047]" +person,0,person,1955,5862,104610461046,"[104610461046]" +person,0,person,1956,5865,1045,"[1045]" +person,0,person,1957,5868,104410441044,"[104410441044]" +person,0,person,1958,5871,1043,"[1043]" +person,0,person,1959,5874,104210421042,"[104210421042]" +person,0,person,1960,5877,1041,"[1041]" +person,0,person,1961,5880,104010401040,"[104010401040]" +person,0,person,1962,5883,1039,"[1039]" +person,0,person,1963,5886,103810381038,"[103810381038]" +person,0,person,1964,5889,1037,"[1037]" +person,0,person,1965,5892,103610361036,"[103610361036]" +person,0,person,1966,5895,1035,"[1035]" +person,0,person,1967,5898,103410341034,"[103410341034]" +person,0,person,1968,5901,1033,"[1033]" +person,0,person,1969,5904,103210321032,"[103210321032]" +person,0,person,1970,5907,1031,"[1031]" +person,0,person,1971,5910,103010301030,"[103010301030]" +person,0,person,1972,5913,1029,"[1029]" +person,0,person,1973,5916,102810281028,"[102810281028]" +person,0,person,1974,5919,1027,"[1027]" +person,0,person,1975,5922,102610261026,"[102610261026]" +person,0,person,1976,5925,1025,"[1025]" +person,0,person,1977,5928,102410241024,"[102410241024]" +person,0,person,1978,5931,1023,"[1023]" +person,0,person,1979,5934,102210221022,"[102210221022]" +person,0,person,1980,5937,1021,"[1021]" +person,0,person,1981,5940,102010201020,"[102010201020]" +person,0,person,1982,5943,1019,"[1019]" +person,0,person,1983,5946,101810181018,"[101810181018]" +person,0,person,1984,5949,1017,"[1017]" +person,0,person,1985,5952,101610161016,"[101610161016]" +person,0,person,1986,5955,1015,"[1015]" +person,0,person,1987,5958,101410141014,"[101410141014]" +person,0,person,1988,5961,1013,"[1013]" +person,0,person,1989,5964,101210121012,"[101210121012]" +person,0,person,1990,5967,1011,"[1011]" +person,0,person,1991,5970,101010101010,"[101010101010]" +person,0,person,1992,5973,1009,"[1009]" +person,0,person,1993,5976,100810081008,"[100810081008]" +person,0,person,1994,5979,1007,"[1007]" +person,0,person,1995,5982,100610061006,"[100610061006]" +person,0,person,1996,5985,1005,"[1005]" +person,0,person,1997,5988,100410041004,"[100410041004]" +person,0,person,1998,5991,1003,"[1003]" +person,0,person,1999,5994,100210021002,"[100210021002]" +person,0,person,2000,5997,1001,"[1001]" +person,0,person,2001,6000,100010001000,"[100010001000]" +person,0,person,2002,6003,999,"[999]" +person,0,person,2003,6006,998998998,"[998998998]" +person,0,person,2004,6009,997,"[997]" +person,0,person,2005,6012,996996996,"[996996996]" +person,0,person,2006,6015,995,"[995]" +person,0,person,2007,6018,994994994,"[994994994]" +person,0,person,2008,6021,993,"[993]" +person,0,person,2009,6024,992992992,"[992992992]" +person,0,person,2010,6027,991,"[991]" +person,0,person,2011,6030,990990990,"[990990990]" +person,0,person,2012,6033,989,"[989]" +person,0,person,2013,6036,988988988,"[988988988]" +person,0,person,2014,6039,987,"[987]" +person,0,person,2015,6042,986986986,"[986986986]" +person,0,person,2016,6045,985,"[985]" +person,0,person,2017,6048,984984984,"[984984984]" +person,0,person,2018,6051,983,"[983]" +person,0,person,2019,6054,982982982,"[982982982]" +person,0,person,2020,6057,981,"[981]" +person,0,person,2021,6060,980980980,"[980980980]" +person,0,person,2022,6063,979,"[979]" +person,0,person,2023,6066,978978978,"[978978978]" +person,0,person,2024,6069,977,"[977]" +person,0,person,2025,6072,976976976,"[976976976]" +person,0,person,2026,6075,975,"[975]" +person,0,person,2027,6078,974974974,"[974974974]" +person,0,person,2028,6081,973,"[973]" +person,0,person,2029,6084,972972972,"[972972972]" +person,0,person,2030,6087,971,"[971]" +person,0,person,2031,6090,970970970,"[970970970]" +person,0,person,2032,6093,969,"[969]" +person,0,person,2033,6096,968968968,"[968968968]" +person,0,person,2034,6099,967,"[967]" +person,0,person,2035,6102,966966966,"[966966966]" +person,0,person,2036,6105,965,"[965]" +person,0,person,2037,6108,964964964,"[964964964]" +person,0,person,2038,6111,963,"[963]" +person,0,person,2039,6114,962962962,"[962962962]" +person,0,person,2040,6117,961,"[961]" +person,0,person,2041,6120,960960960,"[960960960]" +person,0,person,2042,6123,959,"[959]" +person,0,person,2043,6126,958958958,"[958958958]" +person,0,person,2044,6129,957,"[957]" +person,0,person,2045,6132,956956956,"[956956956]" +person,0,person,2046,6135,955,"[955]" +person,0,person,2047,6138,954954954,"[954954954]" +person,0,person,2048,6141,953,"[953]" +person,0,person,2049,6144,952952952,"[952952952]" +person,0,person,2050,6147,951,"[951]" +person,0,person,2051,6150,950950950,"[950950950]" +person,0,person,2052,6153,949,"[949]" +person,0,person,2053,6156,948948948,"[948948948]" +person,0,person,2054,6159,947,"[947]" +person,0,person,2055,6162,946946946,"[946946946]" +person,0,person,2056,6165,945,"[945]" +person,0,person,2057,6168,944944944,"[944944944]" +person,0,person,2058,6171,943,"[943]" +person,0,person,2059,6174,942942942,"[942942942]" +person,0,person,2060,6177,941,"[941]" +person,0,person,2061,6180,940940940,"[940940940]" +person,0,person,2062,6183,939,"[939]" +person,0,person,2063,6186,938938938,"[938938938]" +person,0,person,2064,6189,937,"[937]" +person,0,person,2065,6192,936936936,"[936936936]" +person,0,person,2066,6195,935,"[935]" +person,0,person,2067,6198,934934934,"[934934934]" +person,0,person,2068,6201,933,"[933]" +person,0,person,2069,6204,932932932,"[932932932]" +person,0,person,2070,6207,931,"[931]" +person,0,person,2071,6210,930930930,"[930930930]" +person,0,person,2072,6213,929,"[929]" +person,0,person,2073,6216,928928928,"[928928928]" +person,0,person,2074,6219,927,"[927]" +person,0,person,2075,6222,926926926,"[926926926]" +person,0,person,2076,6225,925,"[925]" +person,0,person,2077,6228,924924924,"[924924924]" +person,0,person,2078,6231,923,"[923]" +person,0,person,2079,6234,922922922,"[922922922]" +person,0,person,2080,6237,921,"[921]" +person,0,person,2081,6240,920920920,"[920920920]" +person,0,person,2082,6243,919,"[919]" +person,0,person,2083,6246,918918918,"[918918918]" +person,0,person,2084,6249,917,"[917]" +person,0,person,2085,6252,916916916,"[916916916]" +person,0,person,2086,6255,915,"[915]" +person,0,person,2087,6258,914914914,"[914914914]" +person,0,person,2088,6261,913,"[913]" +person,0,person,2089,6264,912912912,"[912912912]" +person,0,person,2090,6267,911,"[911]" +person,0,person,2091,6270,910910910,"[910910910]" +person,0,person,2092,6273,909,"[909]" +person,0,person,2093,6276,908908908,"[908908908]" +person,0,person,2094,6279,907,"[907]" +person,0,person,2095,6282,906906906,"[906906906]" +person,0,person,2096,6285,905,"[905]" +person,0,person,2097,6288,904904904,"[904904904]" +person,0,person,2098,6291,903,"[903]" +person,0,person,2099,6294,902902902,"[902902902]" +person,0,person,2100,6297,901,"[901]" +person,0,person,2101,6300,900900900,"[900900900]" +person,0,person,2102,6303,899,"[899]" +person,0,person,2103,6306,898898898,"[898898898]" +person,0,person,2104,6309,897,"[897]" +person,0,person,2105,6312,896896896,"[896896896]" +person,0,person,2106,6315,895,"[895]" +person,0,person,2107,6318,894894894,"[894894894]" +person,0,person,2108,6321,893,"[893]" +person,0,person,2109,6324,892892892,"[892892892]" +person,0,person,2110,6327,891,"[891]" +person,0,person,2111,6330,890890890,"[890890890]" +person,0,person,2112,6333,889,"[889]" +person,0,person,2113,6336,888888888,"[888888888]" +person,0,person,2114,6339,887,"[887]" +person,0,person,2115,6342,886886886,"[886886886]" +person,0,person,2116,6345,885,"[885]" +person,0,person,2117,6348,884884884,"[884884884]" +person,0,person,2118,6351,883,"[883]" +person,0,person,2119,6354,882882882,"[882882882]" +person,0,person,2120,6357,881,"[881]" +person,0,person,2121,6360,880880880,"[880880880]" +person,0,person,2122,6363,879,"[879]" +person,0,person,2123,6366,878878878,"[878878878]" +person,0,person,2124,6369,877,"[877]" +person,0,person,2125,6372,876876876,"[876876876]" +person,0,person,2126,6375,875,"[875]" +person,0,person,2127,6378,874874874,"[874874874]" +person,0,person,2128,6381,873,"[873]" +person,0,person,2129,6384,872872872,"[872872872]" +person,0,person,2130,6387,871,"[871]" +person,0,person,2131,6390,870870870,"[870870870]" +person,0,person,2132,6393,869,"[869]" +person,0,person,2133,6396,868868868,"[868868868]" +person,0,person,2134,6399,867,"[867]" +person,0,person,2135,6402,866866866,"[866866866]" +person,0,person,2136,6405,865,"[865]" +person,0,person,2137,6408,864864864,"[864864864]" +person,0,person,2138,6411,863,"[863]" +person,0,person,2139,6414,862862862,"[862862862]" +person,0,person,2140,6417,861,"[861]" +person,0,person,2141,6420,860860860,"[860860860]" +person,0,person,2142,6423,859,"[859]" +person,0,person,2143,6426,858858858,"[858858858]" +person,0,person,2144,6429,857,"[857]" +person,0,person,2145,6432,856856856,"[856856856]" +person,0,person,2146,6435,855,"[855]" +person,0,person,2147,6438,854854854,"[854854854]" +person,0,person,2148,6441,853,"[853]" +person,0,person,2149,6444,852852852,"[852852852]" +person,0,person,2150,6447,851,"[851]" +person,0,person,2151,6450,850850850,"[850850850]" +person,0,person,2152,6453,849,"[849]" +person,0,person,2153,6456,848848848,"[848848848]" +person,0,person,2154,6459,847,"[847]" +person,0,person,2155,6462,846846846,"[846846846]" +person,0,person,2156,6465,845,"[845]" +person,0,person,2157,6468,844844844,"[844844844]" +person,0,person,2158,6471,843,"[843]" +person,0,person,2159,6474,842842842,"[842842842]" +person,0,person,2160,6477,841,"[841]" +person,0,person,2161,6480,840840840,"[840840840]" +person,0,person,2162,6483,839,"[839]" +person,0,person,2163,6486,838838838,"[838838838]" +person,0,person,2164,6489,837,"[837]" +person,0,person,2165,6492,836836836,"[836836836]" +person,0,person,2166,6495,835,"[835]" +person,0,person,2167,6498,834834834,"[834834834]" +person,0,person,2168,6501,833,"[833]" +person,0,person,2169,6504,832832832,"[832832832]" +person,0,person,2170,6507,831,"[831]" +person,0,person,2171,6510,830830830,"[830830830]" +person,0,person,2172,6513,829,"[829]" +person,0,person,2173,6516,828828828,"[828828828]" +person,0,person,2174,6519,827,"[827]" +person,0,person,2175,6522,826826826,"[826826826]" +person,0,person,2176,6525,825,"[825]" +person,0,person,2177,6528,824824824,"[824824824]" +person,0,person,2178,6531,823,"[823]" +person,0,person,2179,6534,822822822,"[822822822]" +person,0,person,2180,6537,821,"[821]" +person,0,person,2181,6540,820820820,"[820820820]" +person,0,person,2182,6543,819,"[819]" +person,0,person,2183,6546,818818818,"[818818818]" +person,0,person,2184,6549,817,"[817]" +person,0,person,2185,6552,816816816,"[816816816]" +person,0,person,2186,6555,815,"[815]" +person,0,person,2187,6558,814814814,"[814814814]" +person,0,person,2188,6561,813,"[813]" +person,0,person,2189,6564,812812812,"[812812812]" +person,0,person,2190,6567,811,"[811]" +person,0,person,2191,6570,810810810,"[810810810]" +person,0,person,2192,6573,809,"[809]" +person,0,person,2193,6576,808808808,"[808808808]" +person,0,person,2194,6579,807,"[807]" +person,0,person,2195,6582,806806806,"[806806806]" +person,0,person,2196,6585,805,"[805]" +person,0,person,2197,6588,804804804,"[804804804]" +person,0,person,2198,6591,803,"[803]" +person,0,person,2199,6594,802802802,"[802802802]" +person,0,person,2200,6597,801,"[801]" +person,0,person,2201,6600,800800800,"[800800800]" +person,0,person,2202,6603,799,"[799]" +person,0,person,2203,6606,798798798,"[798798798]" +person,0,person,2204,6609,797,"[797]" +person,0,person,2205,6612,796796796,"[796796796]" +person,0,person,2206,6615,795,"[795]" +person,0,person,2207,6618,794794794,"[794794794]" +person,0,person,2208,6621,793,"[793]" +person,0,person,2209,6624,792792792,"[792792792]" +person,0,person,2210,6627,791,"[791]" +person,0,person,2211,6630,790790790,"[790790790]" +person,0,person,2212,6633,789,"[789]" +person,0,person,2213,6636,788788788,"[788788788]" +person,0,person,2214,6639,787,"[787]" +person,0,person,2215,6642,786786786,"[786786786]" +person,0,person,2216,6645,785,"[785]" +person,0,person,2217,6648,784784784,"[784784784]" +person,0,person,2218,6651,783,"[783]" +person,0,person,2219,6654,782782782,"[782782782]" +person,0,person,2220,6657,781,"[781]" +person,0,person,2221,6660,780780780,"[780780780]" +person,0,person,2222,6663,779,"[779]" +person,0,person,2223,6666,778778778,"[778778778]" +person,0,person,2224,6669,777,"[777]" +person,0,person,2225,6672,776776776,"[776776776]" +person,0,person,2226,6675,775,"[775]" +person,0,person,2227,6678,774774774,"[774774774]" +person,0,person,2228,6681,773,"[773]" +person,0,person,2229,6684,772772772,"[772772772]" +person,0,person,2230,6687,771,"[771]" +person,0,person,2231,6690,770770770,"[770770770]" +person,0,person,2232,6693,769,"[769]" +person,0,person,2233,6696,768768768,"[768768768]" +person,0,person,2234,6699,767,"[767]" +person,0,person,2235,6702,766766766,"[766766766]" +person,0,person,2236,6705,765,"[765]" +person,0,person,2237,6708,764764764,"[764764764]" +person,0,person,2238,6711,763,"[763]" +person,0,person,2239,6714,762762762,"[762762762]" +person,0,person,2240,6717,761,"[761]" +person,0,person,2241,6720,760760760,"[760760760]" +person,0,person,2242,6723,759,"[759]" +person,0,person,2243,6726,758758758,"[758758758]" +person,0,person,2244,6729,757,"[757]" +person,0,person,2245,6732,756756756,"[756756756]" +person,0,person,2246,6735,755,"[755]" +person,0,person,2247,6738,754754754,"[754754754]" +person,0,person,2248,6741,753,"[753]" +person,0,person,2249,6744,752752752,"[752752752]" +person,0,person,2250,6747,751,"[751]" +person,0,person,2251,6750,750750750,"[750750750]" +person,0,person,2252,6753,749,"[749]" +person,0,person,2253,6756,748748748,"[748748748]" +person,0,person,2254,6759,747,"[747]" +person,0,person,2255,6762,746746746,"[746746746]" +person,0,person,2256,6765,745,"[745]" +person,0,person,2257,6768,744744744,"[744744744]" +person,0,person,2258,6771,743,"[743]" +person,0,person,2259,6774,742742742,"[742742742]" +person,0,person,2260,6777,741,"[741]" +person,0,person,2261,6780,740740740,"[740740740]" +person,0,person,2262,6783,739,"[739]" +person,0,person,2263,6786,738738738,"[738738738]" +person,0,person,2264,6789,737,"[737]" +person,0,person,2265,6792,736736736,"[736736736]" +person,0,person,2266,6795,735,"[735]" +person,0,person,2267,6798,734734734,"[734734734]" +person,0,person,2268,6801,733,"[733]" +person,0,person,2269,6804,732732732,"[732732732]" +person,0,person,2270,6807,731,"[731]" +person,0,person,2271,6810,730730730,"[730730730]" +person,0,person,2272,6813,729,"[729]" +person,0,person,2273,6816,728728728,"[728728728]" +person,0,person,2274,6819,727,"[727]" +person,0,person,2275,6822,726726726,"[726726726]" +person,0,person,2276,6825,725,"[725]" +person,0,person,2277,6828,724724724,"[724724724]" +person,0,person,2278,6831,723,"[723]" +person,0,person,2279,6834,722722722,"[722722722]" +person,0,person,2280,6837,721,"[721]" +person,0,person,2281,6840,720720720,"[720720720]" +person,0,person,2282,6843,719,"[719]" +person,0,person,2283,6846,718718718,"[718718718]" +person,0,person,2284,6849,717,"[717]" +person,0,person,2285,6852,716716716,"[716716716]" +person,0,person,2286,6855,715,"[715]" +person,0,person,2287,6858,714714714,"[714714714]" +person,0,person,2288,6861,713,"[713]" +person,0,person,2289,6864,712712712,"[712712712]" +person,0,person,2290,6867,711,"[711]" +person,0,person,2291,6870,710710710,"[710710710]" +person,0,person,2292,6873,709,"[709]" +person,0,person,2293,6876,708708708,"[708708708]" +person,0,person,2294,6879,707,"[707]" +person,0,person,2295,6882,706706706,"[706706706]" +person,0,person,2296,6885,705,"[705]" +person,0,person,2297,6888,704704704,"[704704704]" +person,0,person,2298,6891,703,"[703]" +person,0,person,2299,6894,702702702,"[702702702]" +person,0,person,2300,6897,701,"[701]" +person,0,person,2301,6900,700700700,"[700700700]" +person,0,person,2302,6903,699,"[699]" +person,0,person,2303,6906,698698698,"[698698698]" +person,0,person,2304,6909,697,"[697]" +person,0,person,2305,6912,696696696,"[696696696]" +person,0,person,2306,6915,695,"[695]" +person,0,person,2307,6918,694694694,"[694694694]" +person,0,person,2308,6921,693,"[693]" +person,0,person,2309,6924,692692692,"[692692692]" +person,0,person,2310,6927,691,"[691]" +person,0,person,2311,6930,690690690,"[690690690]" +person,0,person,2312,6933,689,"[689]" +person,0,person,2313,6936,688688688,"[688688688]" +person,0,person,2314,6939,687,"[687]" +person,0,person,2315,6942,686686686,"[686686686]" +person,0,person,2316,6945,685,"[685]" +person,0,person,2317,6948,684684684,"[684684684]" +person,0,person,2318,6951,683,"[683]" +person,0,person,2319,6954,682682682,"[682682682]" +person,0,person,2320,6957,681,"[681]" +person,0,person,2321,6960,680680680,"[680680680]" +person,0,person,2322,6963,679,"[679]" +person,0,person,2323,6966,678678678,"[678678678]" +person,0,person,2324,6969,677,"[677]" +person,0,person,2325,6972,676676676,"[676676676]" +person,0,person,2326,6975,675,"[675]" +person,0,person,2327,6978,674674674,"[674674674]" +person,0,person,2328,6981,673,"[673]" +person,0,person,2329,6984,672672672,"[672672672]" +person,0,person,2330,6987,671,"[671]" +person,0,person,2331,6990,670670670,"[670670670]" +person,0,person,2332,6993,669,"[669]" +person,0,person,2333,6996,668668668,"[668668668]" +person,0,person,2334,6999,667,"[667]" +person,0,person,2335,7002,666666666,"[666666666]" +person,0,person,2336,7005,665,"[665]" +person,0,person,2337,7008,664664664,"[664664664]" +person,0,person,2338,7011,663,"[663]" +person,0,person,2339,7014,662662662,"[662662662]" +person,0,person,2340,7017,661,"[661]" +person,0,person,2341,7020,660660660,"[660660660]" +person,0,person,2342,7023,659,"[659]" +person,0,person,2343,7026,658658658,"[658658658]" +person,0,person,2344,7029,657,"[657]" +person,0,person,2345,7032,656656656,"[656656656]" +person,0,person,2346,7035,655,"[655]" +person,0,person,2347,7038,654654654,"[654654654]" +person,0,person,2348,7041,653,"[653]" +person,0,person,2349,7044,652652652,"[652652652]" +person,0,person,2350,7047,651,"[651]" +person,0,person,2351,7050,650650650,"[650650650]" +person,0,person,2352,7053,649,"[649]" +person,0,person,2353,7056,648648648,"[648648648]" +person,0,person,2354,7059,647,"[647]" +person,0,person,2355,7062,646646646,"[646646646]" +person,0,person,2356,7065,645,"[645]" +person,0,person,2357,7068,644644644,"[644644644]" +person,0,person,2358,7071,643,"[643]" +person,0,person,2359,7074,642642642,"[642642642]" +person,0,person,2360,7077,641,"[641]" +person,0,person,2361,7080,640640640,"[640640640]" +person,0,person,2362,7083,639,"[639]" +person,0,person,2363,7086,638638638,"[638638638]" +person,0,person,2364,7089,637,"[637]" +person,0,person,2365,7092,636636636,"[636636636]" +person,0,person,2366,7095,635,"[635]" +person,0,person,2367,7098,634634634,"[634634634]" +person,0,person,2368,7101,633,"[633]" +person,0,person,2369,7104,632632632,"[632632632]" +person,0,person,2370,7107,631,"[631]" +person,0,person,2371,7110,630630630,"[630630630]" +person,0,person,2372,7113,629,"[629]" +person,0,person,2373,7116,628628628,"[628628628]" +person,0,person,2374,7119,627,"[627]" +person,0,person,2375,7122,626626626,"[626626626]" +person,0,person,2376,7125,625,"[625]" +person,0,person,2377,7128,624624624,"[624624624]" +person,0,person,2378,7131,623,"[623]" +person,0,person,2379,7134,622622622,"[622622622]" +person,0,person,2380,7137,621,"[621]" +person,0,person,2381,7140,620620620,"[620620620]" +person,0,person,2382,7143,619,"[619]" +person,0,person,2383,7146,618618618,"[618618618]" +person,0,person,2384,7149,617,"[617]" +person,0,person,2385,7152,616616616,"[616616616]" +person,0,person,2386,7155,615,"[615]" +person,0,person,2387,7158,614614614,"[614614614]" +person,0,person,2388,7161,613,"[613]" +person,0,person,2389,7164,612612612,"[612612612]" +person,0,person,2390,7167,611,"[611]" +person,0,person,2391,7170,610610610,"[610610610]" +person,0,person,2392,7173,609,"[609]" +person,0,person,2393,7176,608608608,"[608608608]" +person,0,person,2394,7179,607,"[607]" +person,0,person,2395,7182,606606606,"[606606606]" +person,0,person,2396,7185,605,"[605]" +person,0,person,2397,7188,604604604,"[604604604]" +person,0,person,2398,7191,603,"[603]" +person,0,person,2399,7194,602602602,"[602602602]" +person,0,person,2400,7197,601,"[601]" +person,0,person,2401,7200,600600600,"[600600600]" +person,0,person,2402,7203,599,"[599]" +person,0,person,2403,7206,598598598,"[598598598]" +person,0,person,2404,7209,597,"[597]" +person,0,person,2405,7212,596596596,"[596596596]" +person,0,person,2406,7215,595,"[595]" +person,0,person,2407,7218,594594594,"[594594594]" +person,0,person,2408,7221,593,"[593]" +person,0,person,2409,7224,592592592,"[592592592]" +person,0,person,2410,7227,591,"[591]" +person,0,person,2411,7230,590590590,"[590590590]" +person,0,person,2412,7233,589,"[589]" +person,0,person,2413,7236,588588588,"[588588588]" +person,0,person,2414,7239,587,"[587]" +person,0,person,2415,7242,586586586,"[586586586]" +person,0,person,2416,7245,585,"[585]" +person,0,person,2417,7248,584584584,"[584584584]" +person,0,person,2418,7251,583,"[583]" +person,0,person,2419,7254,582582582,"[582582582]" +person,0,person,2420,7257,581,"[581]" +person,0,person,2421,7260,580580580,"[580580580]" +person,0,person,2422,7263,579,"[579]" +person,0,person,2423,7266,578578578,"[578578578]" +person,0,person,2424,7269,577,"[577]" +person,0,person,2425,7272,576576576,"[576576576]" +person,0,person,2426,7275,575,"[575]" +person,0,person,2427,7278,574574574,"[574574574]" +person,0,person,2428,7281,573,"[573]" +person,0,person,2429,7284,572572572,"[572572572]" +person,0,person,2430,7287,571,"[571]" +person,0,person,2431,7290,570570570,"[570570570]" +person,0,person,2432,7293,569,"[569]" +person,0,person,2433,7296,568568568,"[568568568]" +person,0,person,2434,7299,567,"[567]" +person,0,person,2435,7302,566566566,"[566566566]" +person,0,person,2436,7305,565,"[565]" +person,0,person,2437,7308,564564564,"[564564564]" +person,0,person,2438,7311,563,"[563]" +person,0,person,2439,7314,562562562,"[562562562]" +person,0,person,2440,7317,561,"[561]" +person,0,person,2441,7320,560560560,"[560560560]" +person,0,person,2442,7323,559,"[559]" +person,0,person,2443,7326,558558558,"[558558558]" +person,0,person,2444,7329,557,"[557]" +person,0,person,2445,7332,556556556,"[556556556]" +person,0,person,2446,7335,555,"[555]" +person,0,person,2447,7338,554554554,"[554554554]" +person,0,person,2448,7341,553,"[553]" +person,0,person,2449,7344,552552552,"[552552552]" +person,0,person,2450,7347,551,"[551]" +person,0,person,2451,7350,550550550,"[550550550]" +person,0,person,2452,7353,549,"[549]" +person,0,person,2453,7356,548548548,"[548548548]" +person,0,person,2454,7359,547,"[547]" +person,0,person,2455,7362,546546546,"[546546546]" +person,0,person,2456,7365,545,"[545]" +person,0,person,2457,7368,544544544,"[544544544]" +person,0,person,2458,7371,543,"[543]" +person,0,person,2459,7374,542542542,"[542542542]" +person,0,person,2460,7377,541,"[541]" +person,0,person,2461,7380,540540540,"[540540540]" +person,0,person,2462,7383,539,"[539]" +person,0,person,2463,7386,538538538,"[538538538]" +person,0,person,2464,7389,537,"[537]" +person,0,person,2465,7392,536536536,"[536536536]" +person,0,person,2466,7395,535,"[535]" +person,0,person,2467,7398,534534534,"[534534534]" +person,0,person,2468,7401,533,"[533]" +person,0,person,2469,7404,532532532,"[532532532]" +person,0,person,2470,7407,531,"[531]" +person,0,person,2471,7410,530530530,"[530530530]" +person,0,person,2472,7413,529,"[529]" +person,0,person,2473,7416,528528528,"[528528528]" +person,0,person,2474,7419,527,"[527]" +person,0,person,2475,7422,526526526,"[526526526]" +person,0,person,2476,7425,525,"[525]" +person,0,person,2477,7428,524524524,"[524524524]" +person,0,person,2478,7431,523,"[523]" +person,0,person,2479,7434,522522522,"[522522522]" +person,0,person,2480,7437,521,"[521]" +person,0,person,2481,7440,520520520,"[520520520]" +person,0,person,2482,7443,519,"[519]" +person,0,person,2483,7446,518518518,"[518518518]" +person,0,person,2484,7449,517,"[517]" +person,0,person,2485,7452,516516516,"[516516516]" +person,0,person,2486,7455,515,"[515]" +person,0,person,2487,7458,514514514,"[514514514]" +person,0,person,2488,7461,513,"[513]" +person,0,person,2489,7464,512512512,"[512512512]" +person,0,person,2490,7467,511,"[511]" +person,0,person,2491,7470,510510510,"[510510510]" +person,0,person,2492,7473,509,"[509]" +person,0,person,2493,7476,508508508,"[508508508]" +person,0,person,2494,7479,507,"[507]" +person,0,person,2495,7482,506506506,"[506506506]" +person,0,person,2496,7485,505,"[505]" +person,0,person,2497,7488,504504504,"[504504504]" +person,0,person,2498,7491,503,"[503]" +person,0,person,2499,7494,502502502,"[502502502]" +person,0,person,2500,7497,501,"[501]" +animal,0,person,0,0,100010001000,"[100010001000]" +animal,1,person,0,1,999,"[999]" +animal,2,person,0,2,998998998,"[998998998]" +animal,3,person,0,3,997,"[997]" +animal,4,person,0,4,996996996,"[996996996]" +animal,5,person,0,5,995,"[995]" +animal,6,person,0,6,994994994,"[994994994]" +animal,7,person,0,7,993,"[993]" +animal,8,person,0,8,992992992,"[992992992]" +animal,9,person,0,9,991,"[991]" +animal,10,person,0,10,990990990,"[990990990]" +animal,11,person,0,11,989,"[989]" +animal,12,person,0,12,988988988,"[988988988]" +animal,13,person,0,13,987,"[987]" +animal,14,person,0,14,986986986,"[986986986]" +animal,15,person,0,15,985,"[985]" +animal,16,person,0,16,984984984,"[984984984]" +animal,17,person,0,17,983,"[983]" +animal,18,person,0,18,982982982,"[982982982]" +animal,19,person,0,19,981,"[981]" +animal,20,person,0,20,980980980,"[980980980]" +animal,21,person,0,21,979,"[979]" +animal,22,person,0,22,978978978,"[978978978]" +animal,23,person,0,23,977,"[977]" +animal,24,person,0,24,976976976,"[976976976]" +animal,25,person,0,25,975,"[975]" +animal,26,person,0,26,974974974,"[974974974]" +animal,27,person,0,27,973,"[973]" +animal,28,person,0,28,972972972,"[972972972]" +animal,29,person,0,29,971,"[971]" +animal,30,person,0,30,970970970,"[970970970]" +animal,31,person,0,31,969,"[969]" +animal,32,person,0,32,968968968,"[968968968]" +animal,33,person,0,33,967,"[967]" +animal,34,person,0,34,966966966,"[966966966]" +animal,35,person,0,35,965,"[965]" +animal,36,person,0,36,964964964,"[964964964]" +animal,37,person,0,37,963,"[963]" +animal,38,person,0,38,962962962,"[962962962]" +animal,39,person,0,39,961,"[961]" +animal,40,person,0,40,960960960,"[960960960]" +animal,41,person,0,41,959,"[959]" +animal,42,person,0,42,958958958,"[958958958]" +animal,43,person,0,43,957,"[957]" +animal,44,person,0,44,956956956,"[956956956]" +animal,45,person,0,45,955,"[955]" +animal,46,person,0,46,954954954,"[954954954]" +animal,47,person,0,47,953,"[953]" +animal,48,person,0,48,952952952,"[952952952]" +animal,49,person,0,49,951,"[951]" +animal,50,person,0,50,950950950,"[950950950]" diff --git a/dataset/tinysnb/copy_csv.cypher b/dataset/tinysnb/copy.cypher similarity index 89% rename from dataset/tinysnb/copy_csv.cypher rename to dataset/tinysnb/copy.cypher index 97389c065f..5eace39c5f 100644 --- a/dataset/tinysnb/copy_csv.cypher +++ b/dataset/tinysnb/copy.cypher @@ -6,4 +6,4 @@ COPY studyAt FROM "dataset/tinysnb/eStudyAt.csv" (HEADER=true); COPY workAt FROM "dataset/tinysnb/eWorkAt.csv" COPY meets FROM "dataset/tinysnb/eMeets.csv" COPY mixed FROM "dataset/tinysnb/eMixed.csv" -COPY marries FROM "dataset/tinysnb/eMarries.csv" \ No newline at end of file +COPY marries FROM "dataset/tinysnb/eMarries.csv" diff --git a/dataset/tinysnb/eKnows.csv b/dataset/tinysnb/eKnows.csv index c5c2fea479..9db49100ae 100644 --- a/dataset/tinysnb/eKnows.csv +++ b/dataset/tinysnb/eKnows.csv @@ -1,14 +1,14 @@ -0,2,2021-06-30,1986-10-21 21:08:31.521,10 years 5 months 13 hours 24 us,[rnme,m8sihsdnf2990nfiwf] -0,3,2021-06-30,1946-08-25 19:07:22,20 years 30 days 48 hours,[njnojppo9u0jkmf,fjiojioh9h9h89hph] -0,5,2021-06-30,2012-12-11 20:07:22,10 days,[ioji232,jifhe8w99u43434] -2,0,2021-06-30,1946-08-25 19:07:22,10 years 5 months 13 hours 24 us,[2huh9y89fsfw23,23nsihufhw723] -2,3,1950-05-14,1946-08-25 19:07:22,23 minutes,[fwehu9h9832wewew,23u9h989sdfsss] -2,5,1950-05-14,2012-12-11 20:07:22,20 years 30 days 48 hours,[fwh9y81232uisuiehuf,ewnuihxy8dyf232] -3,0,2021-06-30,2002-07-31 11:42:53.12342,30 hours 40 days,[fnioh8323aeweae34d,osd89e2ejshuih12] -3,2,1950-05-14,2007-02-12 12:11:42.123,28 minutes 30 milliseconds,[fwh983-sdjisdfji,ioh89y32r2huir] -3,5,2000-01-01,1998-10-02 13:09:22.423,300 milliseconds,[psh989823oaaioe,nuiuah1nosndfisf] -5,0,2021-06-30,1936-11-02 11:02:01,480us,[fwewe] -5,2,1950-05-14,1982-11-11 13:12:05.123,23 minutes,[fewh9182912e3,h9y8y89soidfsf,nuhudf78w78efw,hioshe0f9023sdsd] -5,3,2000-01-01,1999-04-21 15:12:11.42,48 hours 52 milliseconds,[23h9sdslnfowhu2932,shuhf98922323sf] -7,8,1905-12-12,2025-01-01 11:22:33.52,47 minutes 58 seconds,[ahu2333333333333,12weeeeeeeeeeeeeeeeee] -7,9,1905-12-12,2020-03-01 12:11:41.6552,47 minutes 58 seconds,[peweeeeeeeeeeeeeeeee,kowje9w0eweeeeeeeee] +0,2,2021-06-30,1986-10-21 21:08:31.521,10 years 5 months 13 hours 24 us,"[rnme,m8sihsdnf2990nfiwf]" +0,3,2021-06-30,1946-08-25 19:07:22,20 years 30 days 48 hours,"[njnojppo9u0jkmf,fjiojioh9h9h89hph]" +0,5,2021-06-30,2012-12-11 20:07:22,10 days,"[ioji232,jifhe8w99u43434]" +2,0,2021-06-30,1946-08-25 19:07:22,10 years 5 months 13 hours 24 us,"[2huh9y89fsfw23,23nsihufhw723]" +2,3,1950-05-14,1946-08-25 19:07:22,23 minutes,"[fwehu9h9832wewew,23u9h989sdfsss]" +2,5,1950-05-14,2012-12-11 20:07:22,20 years 30 days 48 hours,"[fwh9y81232uisuiehuf,ewnuihxy8dyf232]" +3,0,2021-06-30,2002-07-31 11:42:53.12342,30 hours 40 days,"[fnioh8323aeweae34d,osd89e2ejshuih12]" +3,2,1950-05-14,2007-02-12 12:11:42.123,28 minutes 30 milliseconds,"[fwh983-sdjisdfji,ioh89y32r2huir]" +3,5,2000-01-01,1998-10-02 13:09:22.423,300 milliseconds,"[psh989823oaaioe,nuiuah1nosndfisf]" +5,0,2021-06-30,1936-11-02 11:02:01,480us,"[fwewe]" +5,2,1950-05-14,1982-11-11 13:12:05.123,23 minutes,"[fewh9182912e3,h9y8y89soidfsf,nuhudf78w78efw,hioshe0f9023sdsd]" +5,3,2000-01-01,1999-04-21 15:12:11.42,48 hours 52 milliseconds,"[23h9sdslnfowhu2932,shuhf98922323sf]" +7,8,1905-12-12,2025-01-01 11:22:33.52,47 minutes 58 seconds,"[ahu2333333333333,12weeeeeeeeeeeeeeeeee]" +7,9,1905-12-12,2020-03-01 12:11:41.6552,47 minutes 58 seconds,"[peweeeeeeeeeeeeeeeee,kowje9w0eweeeeeeeee]" diff --git a/dataset/tinysnb/eMarries.csv b/dataset/tinysnb/eMarries.csv index 1d17a519d0..9c24ddda0c 100644 --- a/dataset/tinysnb/eMarries.csv +++ b/dataset/tinysnb/eMarries.csv @@ -1,3 +1,3 @@ -0,2,["toronto"], +0,2,"[toronto]", 3,5,,"long long long string" -7,8,["vancouver"],"short str" +7,8,"[vancouver]","short str" diff --git a/dataset/tinysnb/eStudyAt.csv b/dataset/tinysnb/eStudyAt.csv index bf96081f02..296d17889f 100644 --- a/dataset/tinysnb/eStudyAt.csv +++ b/dataset/tinysnb/eStudyAt.csv @@ -1,4 +1,4 @@ from,to,YEAR,Places -0,1,2021,[wwAewsdndweusd,wek] -2,1,2020,[anew,jsdnwusklklklwewsd] -8,1,2020,[awndsnjwejwen,isuhuwennjnuhuhuwewe] +0,1,2021,"[wwAewsdndweusd,wek]" +2,1,2020,"[anew,jsdnwusklklklwewsd]" +8,1,2020,"[awndsnjwejwen,isuhuwennjnuhuhuwewe]" diff --git a/src/binder/bind/CMakeLists.txt b/src/binder/bind/CMakeLists.txt index 66677f330d..bd9b06dd06 100644 --- a/src/binder/bind/CMakeLists.txt +++ b/src/binder/bind/CMakeLists.txt @@ -1,7 +1,7 @@ add_library( kuzu_binder_bind OBJECT - bind_copy_csv.cpp + bind_copy.cpp bind_ddl.cpp bind_graph_pattern.cpp bind_projection_clause.cpp diff --git a/src/binder/bind/bind_copy_csv.cpp b/src/binder/bind/bind_copy.cpp similarity index 92% rename from src/binder/bind/bind_copy_csv.cpp rename to src/binder/bind/bind_copy.cpp index b2f9bad6c2..98c3bb1e9a 100644 --- a/src/binder/bind/bind_copy_csv.cpp +++ b/src/binder/bind/bind_copy.cpp @@ -1,12 +1,12 @@ #include "binder/binder.h" -#include "binder/copy_csv/bound_copy_csv.h" +#include "binder/copy/bound_copy.h" #include "binder/expression/literal_expression.h" #include "parser/copy_csv/copy_csv.h" namespace kuzu { namespace binder { -unique_ptr Binder::bindCopyCSV(const Statement& statement) { +unique_ptr Binder::bindCopy(const Statement& statement) { auto& copyCSV = (CopyCSV&)statement; auto catalogContent = catalog.getReadOnlyVersion(); auto tableName = copyCSV.getTableName(); @@ -16,7 +16,7 @@ unique_ptr Binder::bindCopyCSV(const Statement& statement) { catalogContent->getRelTableIDFromName(tableName); auto filePath = copyCSV.getCSVFileName(); auto csvReaderConfig = bindParsingOptions(copyCSV.getParsingOptions()); - return make_unique(CSVDescription(filePath, csvReaderConfig), tableID, tableName); + return make_unique(CopyDescription(filePath, csvReaderConfig), tableID, tableName); } CSVReaderConfig Binder::bindParsingOptions( @@ -57,7 +57,7 @@ void Binder::bindStringParsingOptions( if (optionName == "ESCAPE") { csvReaderConfig.escapeChar = parsingOptionValue; } else if (optionName == "DELIM") { - csvReaderConfig.tokenSeparator = parsingOptionValue; + csvReaderConfig.delimiter = parsingOptionValue; } else if (optionName == "QUOTE") { csvReaderConfig.quoteChar = parsingOptionValue; } else if (optionName == "LIST_BEGIN") { diff --git a/src/binder/binder.cpp b/src/binder/binder.cpp index f6e13d3d2d..12be96f04f 100644 --- a/src/binder/binder.cpp +++ b/src/binder/binder.cpp @@ -15,7 +15,7 @@ unique_ptr Binder::bind(const Statement& statement) { return bindDropTable(statement); } case StatementType::COPY_CSV: { - return bindCopyCSV(statement); + return bindCopy(statement); } case StatementType::DROP_PROPERTY: { return bindDropProperty(statement); @@ -165,8 +165,8 @@ void Binder::validateTableExist(const Catalog& _catalog, string& tableName) { } bool Binder::validateStringParsingOptionName(string& parsingOptionName) { - for (auto i = 0; i < size(CopyCSVConfig::STRING_CSV_PARSING_OPTIONS); i++) { - if (parsingOptionName == CopyCSVConfig::STRING_CSV_PARSING_OPTIONS[i]) { + for (auto i = 0; i < size(CopyConfig::STRING_CSV_PARSING_OPTIONS); i++) { + if (parsingOptionName == CopyConfig::STRING_CSV_PARSING_OPTIONS[i]) { return true; } } diff --git a/src/common/csv_reader/csv_reader.cpp b/src/common/csv_reader/csv_reader.cpp index b254ba475f..aa2ca65fae 100644 --- a/src/common/csv_reader/csv_reader.cpp +++ b/src/common/csv_reader/csv_reader.cpp @@ -13,8 +13,8 @@ namespace common { CSVReader::CSVReader(const string& fName, const CSVReaderConfig& config, uint64_t blockId) : CSVReader{fName, config} { - readingBlockStartOffset = CopyCSVConfig::CSV_READING_BLOCK_SIZE * blockId; - readingBlockEndOffset = CopyCSVConfig::CSV_READING_BLOCK_SIZE * (blockId + 1); + readingBlockStartOffset = CopyConfig::CSV_READING_BLOCK_SIZE * blockId; + readingBlockEndOffset = CopyConfig::CSV_READING_BLOCK_SIZE * (blockId + 1); auto isBeginningOfLine = false; if (0 == readingBlockStartOffset) { isBeginningOfLine = true; @@ -166,7 +166,7 @@ bool CSVReader::hasNextToken() { string lineStr; while (true) { if (isQuotedString) { - // ignore tokenSeparator and new line character here + // ignore delimiter and new line character here if (config.quoteChar == line[linePtrEnd]) { break; } else if (config.escapeChar == line[linePtrEnd]) { @@ -174,7 +174,7 @@ bool CSVReader::hasNextToken() { linePtrEnd++; } } else if (isList) { - // ignore tokenSeparator and new line character here + // ignore delimiter and new line character here if (config.listBeginChar == line[linePtrEnd]) { linePtrEnd++; nestedListLevel++; @@ -184,7 +184,7 @@ bool CSVReader::hasNextToken() { if (nestedListLevel == 0) { break; } - } else if (config.tokenSeparator == line[linePtrEnd] || '\n' == line[linePtrEnd] || + } else if (config.delimiter == line[linePtrEnd] || '\n' == line[linePtrEnd] || linePtrEnd == lineLen) { break; } @@ -207,7 +207,7 @@ bool CSVReader::hasNextToken() { bool CSVReader::hasNextTokenOrError() { if (!hasNextToken()) { - throw CSVReaderException( + throw ReaderException( StringUtils::string_format("CSV Reader was expecting more tokens but the line does not " "have any tokens left. Last token: %s", line + linePtrStart)); @@ -244,7 +244,7 @@ char* CSVReader::getString() { } else if (unicodeType == UnicodeType::UNICODE) { return Utf8Proc::normalize(strVal, strlen(strVal)); } else { - throw CSVReaderException("Invalid UTF-8 character encountered."); + throw ReaderException("Invalid UTF-8 character encountered."); } } @@ -298,15 +298,15 @@ Literal CSVReader::getList(const DataType& dataType) { result.listVal.emplace_back(listCSVReader.getList(*dataType.childType)); } break; default: - throw CSVReaderException("Unsupported data type " + - Types::dataTypeToString(dataType.childType->typeID) + - " inside LIST"); + throw ReaderException("Unsupported data type " + + Types::dataTypeToString(dataType.childType->typeID) + + " inside LIST"); } } } auto numBytesOfOverflow = result.listVal.size() * Types::getDataTypeSize(dataType.typeID); if (numBytesOfOverflow >= DEFAULT_PAGE_SIZE) { - throw CSVReaderException(StringUtils::string_format( + throw ReaderException(StringUtils::string_format( "Maximum num bytes of a LIST is %d. Input list's num bytes is %d.", DEFAULT_PAGE_SIZE, numBytesOfOverflow)); } @@ -321,9 +321,74 @@ void CSVReader::setNextTokenIsProcessed() { void CSVReader::openFile(const string& fName) { fd = fopen(fName.c_str(), "r"); if (nullptr == fd) { - throw CSVReaderException("Cannot open file: " + fName); + throw ReaderException("Cannot open file: " + fName); } } +CopyDescription::CopyDescription(const string& filePath, CSVReaderConfig csvReaderConfig) + : filePath{filePath}, csvReaderConfig{nullptr}, fileType{FileType::CSV} { + setFileType(filePath); + if (fileType == FileType::CSV) { + this->csvReaderConfig = make_unique(csvReaderConfig); + } +} + +CopyDescription::CopyDescription(const CopyDescription& copyDescription) + : filePath{copyDescription.filePath}, csvReaderConfig{nullptr}, fileType{ + copyDescription.fileType} { + if (fileType == FileType::CSV) { + this->csvReaderConfig = make_unique(*copyDescription.csvReaderConfig); + } +} + +string CopyDescription::getFileTypeName(FileType fileType) { + switch (fileType) { + case FileType::CSV: + return "csv"; + + case FileType::ARROW: + return "arrow"; + + case FileType::PARQUET: + return "parquet"; + } +} + +string CopyDescription::getFileTypeSuffix(FileType fileType) { + return "." + getFileTypeName(fileType); +} + +void CopyDescription::setFileType(string const& fileName) { + auto csvSuffix = getFileTypeSuffix(FileType::CSV); + auto arrowSuffix = getFileTypeSuffix(FileType::ARROW); + auto parquetSuffix = getFileTypeSuffix(FileType::PARQUET); + + if (fileName.length() >= csvSuffix.length()) { + if (!fileName.compare( + fileName.length() - csvSuffix.length(), csvSuffix.length(), csvSuffix)) { + fileType = FileType::CSV; + return; + } + } + + if (fileName.length() >= arrowSuffix.length()) { + if (!fileName.compare( + fileName.length() - arrowSuffix.length(), arrowSuffix.length(), arrowSuffix)) { + fileType = FileType::ARROW; + return; + } + } + + if (fileName.length() >= parquetSuffix.length()) { + if (!fileName.compare(fileName.length() - parquetSuffix.length(), parquetSuffix.length(), + parquetSuffix)) { + fileType = FileType::PARQUET; + return; + } + } + + throw CopyException("Unsupported file type: " + fileName); +} + } // namespace common } // namespace kuzu diff --git a/src/include/binder/binder.h b/src/include/binder/binder.h index ebd0b6dc97..497972c048 100644 --- a/src/include/binder/binder.h +++ b/src/include/binder/binder.h @@ -52,7 +52,7 @@ class Binder { property_id_t bindPropertyName(TableSchema* tableSchema, const string& propertyName); /*** bind copy csv ***/ - unique_ptr bindCopyCSV(const Statement& statement); + unique_ptr bindCopy(const Statement& statement); CSVReaderConfig bindParsingOptions( const unordered_map>* parsingOptions); diff --git a/src/include/binder/copy_csv/bound_copy_csv.h b/src/include/binder/copy/bound_copy.h similarity index 64% rename from src/include/binder/copy_csv/bound_copy_csv.h rename to src/include/binder/copy/bound_copy.h index d9f328ebe9..2d4968f337 100644 --- a/src/include/binder/copy_csv/bound_copy_csv.h +++ b/src/include/binder/copy/bound_copy.h @@ -13,22 +13,22 @@ using namespace kuzu::catalog; namespace kuzu { namespace binder { -class BoundCopyCSV : public BoundStatement { +class BoundCopy : public BoundStatement { public: - BoundCopyCSV(CSVDescription csvDescription, table_id_t tableID, string tableName) + BoundCopy(CopyDescription copyDescription, table_id_t tableID, string tableName) : BoundStatement{StatementType::COPY_CSV, BoundStatementResult::createSingleStringColumnResult()}, - csvDescription{std::move(csvDescription)}, tableID{tableID}, tableName{ - std::move(tableName)} {} + copyDescription{std::move(copyDescription)}, tableID{tableID}, tableName{std::move( + tableName)} {} - inline CSVDescription getCSVDescription() const { return csvDescription; } + inline CopyDescription getCopyDescription() const { return copyDescription; } inline table_id_t getTableID() const { return tableID; } inline string getTableName() const { return tableName; } private: - CSVDescription csvDescription; + CopyDescription copyDescription; table_id_t tableID; string tableName; }; diff --git a/src/include/common/configs.h b/src/include/common/configs.h index 5912cfd016..8006c6f135 100644 --- a/src/include/common/configs.h +++ b/src/include/common/configs.h @@ -83,8 +83,8 @@ struct HashIndexConfig { static constexpr uint8_t SLOT_CAPACITY = (uint64_t)1 << SLOT_CAPACITY_LOG_2; }; -struct CopyCSVConfig { - // Size (in bytes) of the chunks to be read in InMemNode/RelCSVCopier +struct CopyConfig { + // Size (in bytes) of the chunks to be read in Node/Rel Copier static constexpr uint64_t CSV_READING_BLOCK_SIZE = 1 << 23; // Number of tasks to be assigned in a batch when reading files. @@ -96,12 +96,12 @@ struct CopyCSVConfig { // Default configuration for csv file parsing static constexpr const char* STRING_CSV_PARSING_OPTIONS[5] = { "ESCAPE", "DELIM", "QUOTE", "LIST_BEGIN", "LIST_END"}; - static constexpr char DEFAULT_ESCAPE_CHAR = '\\'; - static constexpr char DEFAULT_TOKEN_SEPARATOR = ','; - static constexpr char DEFAULT_QUOTE_CHAR = '"'; - static constexpr char DEFAULT_LIST_BEGIN_CHAR = '['; - static constexpr char DEFAULT_LIST_END_CHAR = ']'; - static constexpr bool DEFAULT_HAS_HEADER = false; + static constexpr char DEFAULT_CSV_ESCAPE_CHAR = '\\'; + static constexpr char DEFAULT_CSV_DELIMITER = ','; + static constexpr char DEFAULT_CSV_QUOTE_CHAR = '"'; + static constexpr char DEFAULT_CSV_LIST_BEGIN_CHAR = '['; + static constexpr char DEFAULT_CSV_LIST_END_CHAR = ']'; + static constexpr bool DEFAULT_CSV_HAS_HEADER = false; }; struct EnumeratorKnobs { diff --git a/src/include/common/csv_reader/csv_reader.h b/src/include/common/csv_reader/csv_reader.h index 862d511d5a..22b3e8e51e 100644 --- a/src/include/common/csv_reader/csv_reader.h +++ b/src/include/common/csv_reader/csv_reader.h @@ -15,26 +15,37 @@ namespace common { struct CSVReaderConfig { CSVReaderConfig() - : escapeChar{CopyCSVConfig::DEFAULT_ESCAPE_CHAR}, - tokenSeparator{CopyCSVConfig::DEFAULT_TOKEN_SEPARATOR}, - quoteChar{CopyCSVConfig::DEFAULT_QUOTE_CHAR}, - listBeginChar{CopyCSVConfig::DEFAULT_LIST_BEGIN_CHAR}, - listEndChar{CopyCSVConfig::DEFAULT_LIST_END_CHAR}, - hasHeader{CopyCSVConfig::DEFAULT_HAS_HEADER} {} + : escapeChar{CopyConfig::DEFAULT_CSV_ESCAPE_CHAR}, + delimiter{CopyConfig::DEFAULT_CSV_DELIMITER}, + quoteChar{CopyConfig::DEFAULT_CSV_QUOTE_CHAR}, + listBeginChar{CopyConfig::DEFAULT_CSV_LIST_BEGIN_CHAR}, + listEndChar{CopyConfig::DEFAULT_CSV_LIST_END_CHAR}, + hasHeader{CopyConfig::DEFAULT_CSV_HAS_HEADER} {} char escapeChar; - char tokenSeparator; + char delimiter; char quoteChar; char listBeginChar; char listEndChar; bool hasHeader; }; -struct CSVDescription { - CSVDescription(const string filePath, const CSVReaderConfig csvReaderConfig) - : filePath{move(filePath)}, csvReaderConfig{move(csvReaderConfig)} {} +struct CopyDescription { + CopyDescription(const string& filePath, CSVReaderConfig csvReaderConfig); + + CopyDescription(const CopyDescription& copyDescription); + + enum class FileType { CSV, ARROW, PARQUET }; + + static string getFileTypeName(FileType fileType); + + static string getFileTypeSuffix(FileType fileType); + + void setFileType(string const& fileName); + const string filePath; - const CSVReaderConfig csvReaderConfig; + unique_ptr csvReaderConfig; + FileType fileType; }; // TODO(Guodong): we should add a csv reader test to test edge cases and error messages. diff --git a/src/include/common/exception.h b/src/include/common/exception.h index 8d4fb36b24..142949b4d2 100644 --- a/src/include/common/exception.h +++ b/src/include/common/exception.h @@ -42,14 +42,14 @@ class ConversionException : public Exception { explicit ConversionException(const string& msg) : Exception(msg){}; }; -class CSVReaderException : public Exception { +class ReaderException : public Exception { public: - explicit CSVReaderException(const string& msg) : Exception("CSVReader exception: " + msg){}; + explicit ReaderException(const string& msg) : Exception("Reader exception: " + msg){}; }; -class CopyCSVException : public Exception { +class CopyException : public Exception { public: - explicit CopyCSVException(const string& msg) : Exception("CopyCSV exception: " + msg){}; + explicit CopyException(const string& msg) : Exception("Copy exception: " + msg){}; }; class CatalogException : public Exception { diff --git a/src/include/planner/logical_plan/logical_operator/logical_copy_csv.h b/src/include/planner/logical_plan/logical_operator/logical_copy.h similarity index 61% rename from src/include/planner/logical_plan/logical_operator/logical_copy_csv.h rename to src/include/planner/logical_plan/logical_operator/logical_copy.h index fbd474a496..aac2619294 100644 --- a/src/include/planner/logical_plan/logical_operator/logical_copy_csv.h +++ b/src/include/planner/logical_plan/logical_operator/logical_copy.h @@ -9,27 +9,27 @@ namespace planner { using namespace kuzu::catalog; -class LogicalCopyCSV : public LogicalOperator { +class LogicalCopy : public LogicalOperator { public: - LogicalCopyCSV(CSVDescription csvDescription, table_id_t tableID, string tableName) + LogicalCopy(CopyDescription copyDescription, table_id_t tableID, string tableName) : LogicalOperator{LogicalOperatorType::COPY_CSV}, - csvDescription{std::move(csvDescription)}, tableID{tableID}, tableName{tableName} {} + copyDescription{std::move(copyDescription)}, tableID{tableID}, tableName{tableName} {} inline void computeSchema() override { createEmptySchema(); } inline string getExpressionsForPrinting() const override { return tableName; } - inline CSVDescription getCSVDescription() const { return csvDescription; } + inline CopyDescription getCopyDescription() const { return copyDescription; } inline table_id_t getTableID() const { return tableID; } inline unique_ptr copy() override { - return make_unique(csvDescription, tableID, tableName); + return make_unique(copyDescription, tableID, tableName); } private: - CSVDescription csvDescription; + CopyDescription copyDescription; table_id_t tableID; // Used for printing only. string tableName; diff --git a/src/include/planner/planner.h b/src/include/planner/planner.h index de302f2c39..2196395956 100644 --- a/src/include/planner/planner.h +++ b/src/include/planner/planner.h @@ -24,7 +24,7 @@ class Planner { static unique_ptr planDropProperty(const BoundStatement& statement); - static unique_ptr planCopyCSV(const BoundStatement& statement); + static unique_ptr planCopy(const BoundStatement& statement); }; } // namespace planner diff --git a/src/include/processor/mapper/plan_mapper.h b/src/include/processor/mapper/plan_mapper.h index 835d8c7430..6334c0c008 100644 --- a/src/include/processor/mapper/plan_mapper.h +++ b/src/include/processor/mapper/plan_mapper.h @@ -69,7 +69,7 @@ class PlanMapper { LogicalOperator* logicalOperator); unique_ptr mapLogicalCreateRelTableToPhysical( LogicalOperator* logicalOperator); - unique_ptr mapLogicalCopyCSVToPhysical(LogicalOperator* logicalOperator); + unique_ptr mapLogicalCopyToPhysical(LogicalOperator* logicalOperator); unique_ptr mapLogicalDropTableToPhysical(LogicalOperator* logicalOperator); unique_ptr mapLogicalDropPropertyToPhysical(LogicalOperator* logicalOperator); diff --git a/src/include/processor/operator/copy_csv/copy_csv.h b/src/include/processor/operator/copy/copy.h similarity index 81% rename from src/include/processor/operator/copy_csv/copy_csv.h rename to src/include/processor/operator/copy/copy.h index abc31264d3..144e27eb9e 100644 --- a/src/include/processor/operator/copy_csv/copy_csv.h +++ b/src/include/processor/operator/copy/copy.h @@ -10,12 +10,12 @@ using namespace kuzu::catalog; namespace kuzu { namespace processor { -class CopyCSV : public PhysicalOperator { +class Copy : public PhysicalOperator { public: - CopyCSV(PhysicalOperatorType operatorType, Catalog* catalog, CSVDescription csvDescription, + Copy(PhysicalOperatorType operatorType, Catalog* catalog, CopyDescription copyDescription, table_id_t tableID, WAL* wal, uint32_t id, const string& paramsString) : PhysicalOperator{operatorType, id, paramsString}, catalog{catalog}, - csvDescription{std::move(csvDescription)}, tableID{tableID}, wal{wal} {} + copyDescription{std::move(copyDescription)}, tableID{tableID}, wal{wal} {} inline bool isSource() const override { return true; } @@ -37,7 +37,7 @@ class CopyCSV : public PhysicalOperator { protected: Catalog* catalog; - CSVDescription csvDescription; + CopyDescription copyDescription; table_id_t tableID; WAL* wal; }; diff --git a/src/include/processor/operator/copy_csv/copy_node_csv.h b/src/include/processor/operator/copy/copy_node.h similarity index 56% rename from src/include/processor/operator/copy_csv/copy_node_csv.h rename to src/include/processor/operator/copy/copy_node.h index 74b870781f..a49b834ee5 100644 --- a/src/include/processor/operator/copy_csv/copy_node_csv.h +++ b/src/include/processor/operator/copy/copy_node.h @@ -1,22 +1,22 @@ #pragma once -#include "processor/operator/copy_csv/copy_csv.h" +#include "processor/operator/copy/copy.h" #include "storage/store/nodes_store.h" namespace kuzu { namespace processor { -class CopyNodeCSV : public CopyCSV { +class CopyNode : public Copy { public: - CopyNodeCSV(Catalog* catalog, CSVDescription csvDescription, table_id_t tableID, WAL* wal, + CopyNode(Catalog* catalog, CopyDescription copyDescription, table_id_t tableID, WAL* wal, NodesStatisticsAndDeletedIDs* nodesStatistics, uint32_t id, const string& paramsString) - : CopyCSV{PhysicalOperatorType::COPY_NODE_CSV, catalog, std::move(csvDescription), tableID, - wal, id, paramsString}, + : Copy{PhysicalOperatorType::COPY_NODE, catalog, std::move(copyDescription), tableID, wal, + id, paramsString}, nodesStatistics{nodesStatistics} {} unique_ptr clone() override { - return make_unique( - catalog, csvDescription, tableID, wal, nodesStatistics, id, paramsString); + return make_unique( + catalog, copyDescription, tableID, wal, nodesStatistics, id, paramsString); } protected: diff --git a/src/include/processor/operator/copy_csv/copy_rel_csv.h b/src/include/processor/operator/copy/copy_rel.h similarity index 64% rename from src/include/processor/operator/copy_csv/copy_rel_csv.h rename to src/include/processor/operator/copy/copy_rel.h index a2f85248bd..536a1308a5 100644 --- a/src/include/processor/operator/copy_csv/copy_rel_csv.h +++ b/src/include/processor/operator/copy/copy_rel.h @@ -1,22 +1,22 @@ #pragma once -#include "processor/operator/copy_csv/copy_csv.h" +#include "processor/operator/copy/copy.h" #include "storage/store/rels_store.h" namespace kuzu { namespace processor { -class CopyRelCSV : public CopyCSV { +class CopyRel : public Copy { public: - CopyRelCSV(Catalog* catalog, CSVDescription csvDescription, table_id_t tableID, WAL* wal, + CopyRel(Catalog* catalog, CopyDescription copyDescription, table_id_t tableID, WAL* wal, NodesStatisticsAndDeletedIDs* nodesStatistics, RelsStatistics* relsStatistics, uint32_t id, const string& paramsString) - : CopyCSV{PhysicalOperatorType::COPY_REL_CSV, catalog, std::move(csvDescription), tableID, - wal, id, paramsString}, + : Copy{PhysicalOperatorType::COPY_REL, catalog, std::move(copyDescription), tableID, wal, + id, paramsString}, nodesStatistics{nodesStatistics}, relsStatistics{relsStatistics} {} unique_ptr clone() override { - return make_unique(catalog, csvDescription, tableID, wal, nodesStatistics, + return make_unique(catalog, copyDescription, tableID, wal, nodesStatistics, relsStatistics, id, paramsString); } diff --git a/src/include/processor/operator/physical_operator.h b/src/include/processor/operator/physical_operator.h index 0f6d9943cd..96b1320921 100644 --- a/src/include/processor/operator/physical_operator.h +++ b/src/include/processor/operator/physical_operator.h @@ -11,8 +11,8 @@ namespace processor { enum class PhysicalOperatorType : uint8_t { AGGREGATE, AGGREGATE_SCAN, - COPY_NODE_CSV, - COPY_REL_CSV, + COPY_NODE, + COPY_REL, CREATE_NODE, CREATE_NODE_TABLE, CREATE_REL, diff --git a/src/include/processor/physical_plan.h b/src/include/processor/physical_plan.h index 8d5f37b515..9514c31ec1 100644 --- a/src/include/processor/physical_plan.h +++ b/src/include/processor/physical_plan.h @@ -12,9 +12,9 @@ class PhysicalPlan { explicit PhysicalPlan(unique_ptr lastOperator) : lastOperator{std::move(lastOperator)} {} - inline bool isCopyCSV() const { - return lastOperator->getOperatorType() == PhysicalOperatorType::COPY_NODE_CSV || - lastOperator->getOperatorType() == PhysicalOperatorType::COPY_REL_CSV; + inline bool isCopy() const { + return lastOperator->getOperatorType() == PhysicalOperatorType::COPY_NODE || + lastOperator->getOperatorType() == PhysicalOperatorType::COPY_REL; } public: diff --git a/src/include/storage/copy_arrow/copy_node_arrow.h b/src/include/storage/copy_arrow/copy_node_arrow.h new file mode 100644 index 0000000000..5c4e40d979 --- /dev/null +++ b/src/include/storage/copy_arrow/copy_node_arrow.h @@ -0,0 +1,61 @@ +#pragma once + +#include "copy_structures_arrow.h" +#include "storage/index/hash_index_builder.h" +#include "storage/store/nodes_statistics_and_deleted_ids.h" + +namespace kuzu { +namespace storage { + +class CopyNodeArrow : public CopyStructuresArrow { + +public: + CopyNodeArrow(CopyDescription& copyDescription, string outputDirectory, + TaskScheduler& taskScheduler, Catalog& catalog, table_id_t tableID, + NodesStatisticsAndDeletedIDs* nodesStatisticsAndDeletedIDs); + + ~CopyNodeArrow() override = default; + + uint64_t copy(); + + void saveToFile() override; + +private: + void initializeColumnsAndList(); + + template + arrow::Status populateColumns(); + + template + arrow::Status populateColumnsFromCSV(unique_ptr>& pkIndex); + + template + arrow::Status populateColumnsFromArrow(unique_ptr>& pkIndex); + + template + arrow::Status populateColumnsFromParquet(unique_ptr>& pkIndex); + + template + static void putPropsOfLineIntoColumns(vector>& columns, + vector& overflowCursors, const std::vector>& arrow_columns, + uint64_t nodeOffset, uint64_t bufferOffset, CopyDescription& copyDescription); + + template + static void populatePKIndex(InMemColumn* column, HashIndexBuilder* pkIndex, + node_offset_t startOffset, uint64_t numValues); + + // Concurrent tasks. + // Note that primaryKeyPropertyIdx is *NOT* the property ID of the primary key property. + template + static arrow::Status batchPopulateColumnsTask(uint64_t primaryKeyPropertyIdx, uint64_t blockId, + uint64_t offsetStart, HashIndexBuilder* pkIndex, CopyNodeArrow* copier, + const vector>& batchColumns, CopyDescription& copyDescription); + +private: + NodeTableSchema* nodeTableSchema; + vector> columns; + NodesStatisticsAndDeletedIDs* nodesStatisticsAndDeletedIDs; +}; + +} // namespace storage +} // namespace kuzu diff --git a/src/include/storage/in_mem_csv_copier/in_mem_rel_csv_copier.h b/src/include/storage/copy_arrow/copy_rel_arrow.h similarity index 70% rename from src/include/storage/in_mem_csv_copier/in_mem_rel_csv_copier.h rename to src/include/storage/copy_arrow/copy_rel_arrow.h index 2f9c400873..16c361dd32 100644 --- a/src/include/storage/in_mem_csv_copier/in_mem_rel_csv_copier.h +++ b/src/include/storage/copy_arrow/copy_rel_arrow.h @@ -1,6 +1,6 @@ #pragma once -#include "in_mem_structures_copier.h" +#include "copy_structures_arrow.h" #include "storage/index/hash_index.h" #include "storage/store/rels_statistics.h" @@ -13,30 +13,47 @@ using table_adj_in_mem_lists_map_t = unordered_map>>; -class InMemRelCSVCopier : public InMemStructuresCopier { +class CopyRelArrow : public CopyStructuresArrow { public: - InMemRelCSVCopier(CSVDescription& csvDescription, string outputDirectory, + CopyRelArrow(CopyDescription& copyDescription, string outputDirectory, TaskScheduler& taskScheduler, Catalog& catalog, map maxNodeOffsetsPerNodeTable, BufferManager* bufferManager, table_id_t tableID, RelsStatistics* relsStatistics); - ~InMemRelCSVCopier() override = default; + ~CopyRelArrow() override = default; uint64_t copy(); void saveToFile() override; + enum class PopulateTaskType { populateAdjColumnsAndCountRelsInAdjListsTask, populateListsTask }; + + static std::string getTaskTypeName(PopulateTaskType populateTaskType); + private: - void countLinesPerBlock(); void initializeColumnsAndLists(); + void initializeColumns(RelDirection relDirection); + void initializeLists(RelDirection relDirection); + void initAdjListsHeaders(); + void initListsMetadata(); + arrow::Status executePopulateTask(PopulateTaskType populateTaskType); + + arrow::Status populateFromCSV(PopulateTaskType populateTaskType); + + arrow::Status populateFromArrow(PopulateTaskType populateTaskType); + + arrow::Status populateFromParquet(PopulateTaskType populateTaskType); + void populateAdjColumnsAndCountRelsInAdjLists(); + void populateLists(); + // We store rel properties with overflows, e.g., strings or lists, in // InMemColumn/ListsWithOverflowFile (e.g., InMemStringLists). When loading these properties // from csv, we first save the overflow pointers of the ku_list_t or ku_string_t in temporary @@ -53,34 +70,48 @@ class InMemRelCSVCopier : public InMemStructuresCopier { // disk. void sortAndCopyOverflowValues(); - static void inferTableIDsAndOffsets(CSVReader& reader, vector& nodeIDs, - vector& nodeIDTypes, + template + static void inferTableIDsAndOffsets(const vector>& batchColumns, + vector& nodeIDs, vector& nodeIDTypes, const map>& pkIndexes, Transaction* transaction, - const Catalog& catalog, vector requireToReadTableLabels); - static void putPropsOfLineIntoColumns(InMemRelCSVCopier* copier, - vector& inMemOverflowFileCursors, CSVReader& reader, - const vector& nodeIDs); - static void putPropsOfLineIntoLists(InMemRelCSVCopier* copier, - vector& inMemOverflowFileCursors, CSVReader& reader, - const vector& nodeIDs, const vector& reversePos); + const Catalog& catalog, vector requireToReadTableLabels, int64_t blockOffset, + int64_t& colIndex); + + template + static void putPropsOfLineIntoColumns(CopyRelArrow* copier, + vector& inMemOverflowFileCursors, const vector>& batchColumns, + const vector& nodeIDs, int64_t blockOffset, int64_t& colIndex, + CopyDescription& copyDescription); + + template + static void putPropsOfLineIntoLists(CopyRelArrow* copier, + vector& inMemOverflowFileCursors, const vector>& batchColumns, + const vector& nodeIDs, const vector& reversePos, int64_t blockOffset, + int64_t& colIndex, CopyDescription& copyDescription); + static void copyStringOverflowFromUnorderedToOrderedPages(ku_string_t* kuStr, PageByteCursor& unorderedOverflowCursor, PageByteCursor& orderedOverflowCursor, InMemOverflowFile* unorderedOverflowFile, InMemOverflowFile* orderedOverflowFile); + static void copyListOverflowFromUnorderedToOrderedPages(ku_list_t* kuList, const DataType& dataType, PageByteCursor& unorderedOverflowCursor, PageByteCursor& orderedOverflowCursor, InMemOverflowFile* unorderedOverflowFile, InMemOverflowFile* orderedOverflowFile); - static void skipFirstRowIfNecessary( - uint64_t blockId, const CSVDescription& csvDescription, CSVReader& reader); // Concurrent tasks. - static void populateAdjColumnsAndCountRelsInAdjListsTask( - uint64_t blockId, uint64_t blockStartRelID, InMemRelCSVCopier* copier); - static void populateListsTask( - uint64_t blockId, uint64_t blockStartRelID, InMemRelCSVCopier* copier); + template + static void populateAdjColumnsAndCountRelsInAdjListsTask(uint64_t blockId, + uint64_t blockStartRelID, CopyRelArrow* copier, const vector>& batchColumns, + CopyDescription& copyDescription); + + template + static void populateListsTask(uint64_t blockId, uint64_t blockStartRelID, CopyRelArrow* copier, + const vector>& batchColumns, CopyDescription& copyDescription); + static void sortOverflowValuesOfPropertyColumnTask(const DataType& dataType, node_offset_t offsetStart, node_offset_t offsetEnd, InMemColumn* propertyColumn, InMemOverflowFile* unorderedInMemOverflowFile, InMemOverflowFile* orderedInMemOverflowFile); + static void sortOverflowValuesOfPropertyListsTask(const DataType& dataType, node_offset_t offsetStart, node_offset_t offsetEnd, InMemAdjLists* adjLists, InMemLists* propertyLists, InMemOverflowFile* unorderedInMemOverflowFile, diff --git a/src/include/storage/in_mem_csv_copier/in_mem_structures_copier.h b/src/include/storage/copy_arrow/copy_structures_arrow.h similarity index 56% rename from src/include/storage/in_mem_csv_copier/in_mem_structures_copier.h rename to src/include/storage/copy_arrow/copy_structures_arrow.h index b3f11957d0..12634c68b2 100644 --- a/src/include/storage/in_mem_csv_copier/in_mem_structures_copier.h +++ b/src/include/storage/copy_arrow/copy_structures_arrow.h @@ -6,36 +6,42 @@ #include "common/task_system/task_scheduler.h" #include "storage/in_mem_storage_structure/in_mem_column.h" #include "storage/in_mem_storage_structure/in_mem_lists.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include namespace kuzu { namespace storage { using namespace kuzu::catalog; -class InMemStructuresCopier { +class CopyStructuresArrow { protected: - InMemStructuresCopier(CSVDescription& csvDescription, string outputDirectory, + CopyStructuresArrow(CopyDescription& copyDescription, string outputDirectory, TaskScheduler& taskScheduler, Catalog& catalog); - virtual ~InMemStructuresCopier() = default; + virtual ~CopyStructuresArrow() = default; public: virtual void saveToFile() = 0; protected: - void calculateNumBlocks(const string& filePath, string tableName); - - uint64_t calculateNumRows(bool hasHeader); - - // Concurrent tasks - static void countNumLinesPerBlockTask( - const string& fName, uint64_t blockId, InMemStructuresCopier* copier); // Initializes (in listHeadersBuilder) the header of each list in a Lists structure, from the // listSizes. ListSizes is used to determine if the list is small or large, based on which, // information is encoded in the 4 byte header. static void calculateListHeadersTask(node_offset_t numNodes, uint32_t elementSize, atomic_uint64_vec_t* listSizes, ListHeadersBuilder* listHeadersBuilder, const shared_ptr& logger); + // Initializes Metadata information of a Lists structure, that is chunksPagesMap and // largeListsPagesMap, using listSizes and listHeadersBuilder. // **Note that this file also allocates the in-memory pages of the InMemFile that will actually @@ -45,14 +51,37 @@ class InMemStructuresCopier { ListHeadersBuilder* listHeadersBuilder, InMemLists* inMemList, bool hasNULLBytes, const shared_ptr& logger); + void countNumLines(const std::string& filePath); + + arrow::Status countNumLinesCSV(std::string const& filePath); + + arrow::Status countNumLinesArrow(std::string const& filePath); + + arrow::Status countNumLinesParquet(std::string const& filePath); + + arrow::Status initCSVReader( + shared_ptr& csv_streaming_reader, const std::string& filePath); + + arrow::Status initArrowReader(std::shared_ptr& ipc_reader, + const std::string& filePath); + + arrow::Status initParquetReader( + std::unique_ptr& reader, const std::string& filePath); + + static Literal getArrowList(string& l, int64_t from, int64_t to, const DataType& dataType, + CopyDescription& CopyDescription); + + static void throwCopyExceptionIfNotOK(const arrow::Status& status); + protected: shared_ptr logger; - CSVDescription& csvDescription; + CopyDescription& copyDescription; string outputDirectory; uint64_t numBlocks; vector numLinesPerBlock; TaskScheduler& taskScheduler; Catalog& catalog; + uint64_t numRows; }; } // namespace storage diff --git a/src/include/storage/copy_arrow/copy_task.h b/src/include/storage/copy_arrow/copy_task.h new file mode 100644 index 0000000000..bed0007809 --- /dev/null +++ b/src/include/storage/copy_arrow/copy_task.h @@ -0,0 +1,40 @@ +#pragma once + +#include "common/task_system/task.h" + +namespace kuzu { +namespace storage { + +class CopyTask : public Task { +public: + // CopyCSV tasks are intended to be tasks on which only 1 thread works. + CopyTask() : Task(1){}; +}; + +template +class ParameterizedCopyTask : public CopyTask { +public: + ParameterizedCopyTask(F&& func) : f(func){}; + void run() override { f(); } + +private: + F f; +}; + +class CopyTaskFactory { + +private: + template + static shared_ptr createCopyTaskInternal(F&& f) { + return std::shared_ptr(new ParameterizedCopyTask(std::forward(f))); + }; + +public: + template + static shared_ptr createCopyTask(F function, Args&&... args) { + return std::shared_ptr( + createCopyTaskInternal(std::move(bind(function, args...)))); + }; +}; +} // namespace storage +} // namespace kuzu diff --git a/src/include/storage/in_mem_csv_copier/copy_csv_task.h b/src/include/storage/in_mem_csv_copier/copy_csv_task.h deleted file mode 100644 index 12f87c4445..0000000000 --- a/src/include/storage/in_mem_csv_copier/copy_csv_task.h +++ /dev/null @@ -1,40 +0,0 @@ -#pragma once - -#include "common/task_system/task.h" - -namespace kuzu { -namespace storage { - -class CopyCSVTask : public Task { -public: - // CopyCSV tasks are intended to be tasks on which only 1 thread works. - CopyCSVTask() : Task(1){}; -}; - -template -class ParameterizedCopyCSVTask : public CopyCSVTask { -public: - ParameterizedCopyCSVTask(F&& func) : f(func){}; - void run() override { f(); } - -private: - F f; -}; - -class CopyCSVTaskFactory { - -private: - template - static shared_ptr createCopyCSVTaskInternal(F&& f) { - return std::shared_ptr(new ParameterizedCopyCSVTask(std::forward(f))); - }; - -public: - template - static shared_ptr createCopyCSVTask(F function, Args&&... args) { - return std::shared_ptr( - createCopyCSVTaskInternal(move(bind(function, args...)))); - }; -}; -} // namespace storage -} // namespace kuzu diff --git a/src/include/storage/in_mem_csv_copier/in_mem_arrow_node_copier.h b/src/include/storage/in_mem_csv_copier/in_mem_arrow_node_copier.h deleted file mode 100644 index b2221c45b4..0000000000 --- a/src/include/storage/in_mem_csv_copier/in_mem_arrow_node_copier.h +++ /dev/null @@ -1,104 +0,0 @@ -#pragma once - -#include "in_mem_structures_copier.h" -#include "storage/index/hash_index_builder.h" -#include "storage/store/nodes_statistics_and_deleted_ids.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace kuzu { -namespace storage { - -class InMemArrowNodeCopier : public InMemStructuresCopier { - -public: - InMemArrowNodeCopier(CSVDescription& csvDescription, string outputDirectory, - TaskScheduler& taskScheduler, Catalog& catalog, table_id_t tableID, - NodesStatisticsAndDeletedIDs* nodesStatisticsAndDeletedIDs); - - ~InMemArrowNodeCopier() override = default; - - uint64_t copy(); - - void saveToFile() override; - - enum class FileTypes { CSV, ARROW, PARQUET }; - - static std::string getFileTypeName(FileTypes fileTypes); - - static std::string getFileTypeSuffix(FileTypes fileTypes); - -private: - void setFileType(std::string const& fileName); - - void countNumLines(const std::string& filePath); - - arrow::Status countNumLinesCSV(std::string const& filePath); - - arrow::Status countNumLinesArrow(std::string const& filePath); - - arrow::Status countNumLinesParquet(std::string const& filePath); - - void initializeColumnsAndList(); - - template - arrow::Status populateColumns(); - - template - arrow::Status populateColumnsFromCSV(unique_ptr>& pkIndex); - - template - arrow::Status populateColumnsFromArrow(unique_ptr>& pkIndex); - - template - arrow::Status populateColumnsFromParquet(unique_ptr>& pkIndex); - - template - static void putPropsOfLineIntoColumns(vector>& columns, - vector& overflowCursors, const std::vector>& arrow_columns, - uint64_t nodeOffset, uint64_t bufferOffset, char delimiter); - - template - static void populatePKIndex(InMemColumn* column, HashIndexBuilder* pkIndex, - node_offset_t startOffset, uint64_t numValues); - - // Concurrent tasks. - // Note that primaryKeyPropertyIdx is *NOT* the property ID of the primary key property. - - template - static arrow::Status batchPopulateColumnsTask(uint64_t primaryKeyPropertyId, uint64_t blockId, - uint64_t offsetStart, HashIndexBuilder* pkIndex, InMemArrowNodeCopier* copier, - const vector>& batchColumns, char delimiter); - - arrow::Status initCSVReader( - shared_ptr& csv_streaming_reader, const std::string& filePath); - - arrow::Status initArrowReader(std::shared_ptr& ipc_reader, - const std::string& filePath); - - arrow::Status initParquetReader( - std::unique_ptr& reader, const std::string& filePath); - - static Literal getArrowList( - string& l, int64_t from, int64_t to, const DataType& dataType, char delimiter); - -private: - NodeTableSchema* nodeTableSchema; - uint64_t numNodes; - vector> columns; - NodesStatisticsAndDeletedIDs* nodesStatisticsAndDeletedIDs; - FileTypes inputFileType; -}; - -} // namespace storage -} // namespace kuzu diff --git a/src/include/storage/wal/wal.h b/src/include/storage/wal/wal.h index b3004d2c5b..8be24358ae 100644 --- a/src/include/storage/wal/wal.h +++ b/src/include/storage/wal/wal.h @@ -110,9 +110,9 @@ class WAL : public BaseWALAndWALIterator { void logOverflowFileNextBytePosRecord( StorageStructureID storageStructureID, uint64_t prevNextByteToWriteTo); - void logCopyNodeCSVRecord(table_id_t tableID); + void logCopyNodeRecord(table_id_t tableID); - void logCopyRelCSVRecord(table_id_t tableID); + void logCopyRelRecord(table_id_t tableID); void logDropTableRecord(table_id_t tableID); diff --git a/src/include/storage/wal/wal_record.h b/src/include/storage/wal/wal_record.h index 4b49eeb057..ef9d9b9b00 100644 --- a/src/include/storage/wal/wal_record.h +++ b/src/include/storage/wal/wal_record.h @@ -259,8 +259,8 @@ enum class WALRecordType : uint8_t { // Records the nextBytePosToWriteTo field's last value before the write trx started. This is // used when rolling back to restore this value. OVERFLOW_FILE_NEXT_BYTE_POS_RECORD = 6, - COPY_NODE_CSV_RECORD = 7, - COPY_REL_CSV_RECORD = 8, + COPY_NODE_RECORD = 7, + COPY_REL_RECORD = 8, DROP_TABLE_RECORD = 9, DROP_PROPERTY_RECORD = 10, }; @@ -336,24 +336,24 @@ struct DiskOverflowFileNextBytePosRecord { } }; -struct CopyNodeCSVRecord { +struct CopyNodeRecord { table_id_t tableID; - CopyNodeCSVRecord() = default; + CopyNodeRecord() = default; - explicit CopyNodeCSVRecord(table_id_t tableID) : tableID{tableID} {} + explicit CopyNodeRecord(table_id_t tableID) : tableID{tableID} {} - inline bool operator==(const CopyNodeCSVRecord& rhs) const { return tableID == rhs.tableID; } + inline bool operator==(const CopyNodeRecord& rhs) const { return tableID == rhs.tableID; } }; -struct CopyRelCSVRecord { +struct CopyRelRecord { table_id_t tableID; - CopyRelCSVRecord() = default; + CopyRelRecord() = default; - explicit CopyRelCSVRecord(table_id_t tableID) : tableID{tableID} {} + explicit CopyRelRecord(table_id_t tableID) : tableID{tableID} {} - inline bool operator==(const CopyRelCSVRecord& rhs) const { return tableID == rhs.tableID; } + inline bool operator==(const CopyRelRecord& rhs) const { return tableID == rhs.tableID; } }; struct TableStatisticsRecord { @@ -400,8 +400,8 @@ struct WALRecord { NodeTableRecord nodeTableRecord; RelTableRecord relTableRecord; DiskOverflowFileNextBytePosRecord diskOverflowFileNextBytePosRecord; - CopyNodeCSVRecord copyNodeCsvRecord; - CopyRelCSVRecord copyRelCsvRecord; + CopyNodeRecord copyNodeRecord; + CopyRelRecord copyRelRecord; TableStatisticsRecord tableStatisticsRecord; DropTableRecord dropTableRecord; DropPropertyRecord dropPropertyRecord; @@ -434,11 +434,11 @@ struct WALRecord { case WALRecordType::OVERFLOW_FILE_NEXT_BYTE_POS_RECORD: { return diskOverflowFileNextBytePosRecord == rhs.diskOverflowFileNextBytePosRecord; } - case WALRecordType::COPY_NODE_CSV_RECORD: { - return copyNodeCsvRecord == rhs.copyNodeCsvRecord; + case WALRecordType::COPY_NODE_RECORD: { + return copyNodeRecord == rhs.copyNodeRecord; } - case WALRecordType::COPY_REL_CSV_RECORD: { - return copyRelCsvRecord == rhs.copyRelCsvRecord; + case WALRecordType::COPY_REL_RECORD: { + return copyRelRecord == rhs.copyRelRecord; } case WALRecordType::DROP_TABLE_RECORD: { return dropTableRecord == rhs.dropTableRecord; @@ -464,8 +464,8 @@ struct WALRecord { static WALRecord newRelTableRecord(table_id_t tableID); static WALRecord newOverflowFileNextBytePosRecord( StorageStructureID storageStructureID_, uint64_t prevNextByteToWriteTo_); - static WALRecord newCopyNodeCSVRecord(table_id_t tableID); - static WALRecord newCopyRelCSVRecord(table_id_t tableID); + static WALRecord newCopyNodeRecord(table_id_t tableID); + static WALRecord newCopyRelRecord(table_id_t tableID); static WALRecord newDropTableRecord(table_id_t tableID); static WALRecord newDropPropertyRecord(table_id_t tableID, property_id_t propertyID); static void constructWALRecordFromBytes(WALRecord& retVal, uint8_t* bytes, uint64_t& offset); diff --git a/src/planner/planner.cpp b/src/planner/planner.cpp index 588dad12fb..2fc97efd2b 100644 --- a/src/planner/planner.cpp +++ b/src/planner/planner.cpp @@ -1,11 +1,11 @@ #include "planner/planner.h" -#include "binder/copy_csv/bound_copy_csv.h" +#include "binder/copy/bound_copy.h" #include "binder/ddl/bound_create_node_clause.h" #include "binder/ddl/bound_create_rel_clause.h" #include "binder/ddl/bound_drop_property.h" #include "binder/ddl/bound_drop_table.h" -#include "planner/logical_plan/logical_operator/logical_copy_csv.h" +#include "planner/logical_plan/logical_operator/logical_copy.h" #include "planner/logical_plan/logical_operator/logical_create_node_table.h" #include "planner/logical_plan/logical_operator/logical_create_rel_table.h" #include "planner/logical_plan/logical_operator/logical_drop_property.h" @@ -34,7 +34,7 @@ unique_ptr Planner::getBestPlan(const Catalog& catalog, return planDropProperty(statement); } case StatementType::COPY_CSV: { - return planCopyCSV(statement); + return planCopy(statement); } default: assert(false); @@ -95,10 +95,10 @@ unique_ptr Planner::planDropProperty(const BoundStatement& statemen return plan; } -unique_ptr Planner::planCopyCSV(const BoundStatement& statement) { - auto& copyCSVClause = (BoundCopyCSV&)statement; +unique_ptr Planner::planCopy(const BoundStatement& statement) { + auto& copyCSVClause = (BoundCopy&)statement; auto plan = make_unique(); - auto copyCSV = make_shared(copyCSVClause.getCSVDescription(), + auto copyCSV = make_shared(copyCSVClause.getCopyDescription(), copyCSVClause.getTableID(), copyCSVClause.getTableName()); copyCSV->computeSchema(); plan->setLastOperator(std::move(copyCSV)); diff --git a/src/processor/mapper/map_ddl.cpp b/src/processor/mapper/map_ddl.cpp index 7a38be80ad..eec0e6449a 100644 --- a/src/processor/mapper/map_ddl.cpp +++ b/src/processor/mapper/map_ddl.cpp @@ -1,11 +1,11 @@ -#include "planner/logical_plan/logical_operator/logical_copy_csv.h" +#include "planner/logical_plan/logical_operator/logical_copy.h" #include "planner/logical_plan/logical_operator/logical_create_node_table.h" #include "planner/logical_plan/logical_operator/logical_create_rel_table.h" #include "planner/logical_plan/logical_operator/logical_drop_property.h" #include "planner/logical_plan/logical_operator/logical_drop_table.h" #include "processor/mapper/plan_mapper.h" -#include "processor/operator/copy_csv/copy_node_csv.h" -#include "processor/operator/copy_csv/copy_rel_csv.h" +#include "processor/operator/copy/copy_node.h" +#include "processor/operator/copy/copy_rel.h" #include "processor/operator/ddl/create_node_table.h" #include "processor/operator/ddl/create_rel_table.h" #include "processor/operator/ddl/drop_property.h" @@ -40,20 +40,20 @@ unique_ptr PlanMapper::mapLogicalCreateRelTableToPhysical( &storageManager.getRelsStore().getRelsStatistics()); } -unique_ptr PlanMapper::mapLogicalCopyCSVToPhysical( +unique_ptr PlanMapper::mapLogicalCopyToPhysical( LogicalOperator* logicalOperator) { - auto copyCSV = (LogicalCopyCSV*)logicalOperator; - auto tableName = catalog->getReadOnlyVersion()->getTableName(copyCSV->getTableID()); + auto copy = (LogicalCopy*)logicalOperator; + auto tableName = catalog->getReadOnlyVersion()->getTableName(copy->getTableID()); auto nodesStatistics = &storageManager.getNodesStore().getNodesStatisticsAndDeletedIDs(); auto relsStatistics = &storageManager.getRelsStore().getRelsStatistics(); if (catalog->getReadOnlyVersion()->containNodeTable(tableName)) { - return make_unique(catalog, copyCSV->getCSVDescription(), - copyCSV->getTableID(), storageManager.getWAL(), nodesStatistics, getOperatorID(), - copyCSV->getExpressionsForPrinting()); + return make_unique(catalog, copy->getCopyDescription(), copy->getTableID(), + storageManager.getWAL(), nodesStatistics, getOperatorID(), + copy->getExpressionsForPrinting()); } else { - return make_unique(catalog, copyCSV->getCSVDescription(), copyCSV->getTableID(), + return make_unique(catalog, copy->getCopyDescription(), copy->getTableID(), storageManager.getWAL(), nodesStatistics, relsStatistics, getOperatorID(), - copyCSV->getExpressionsForPrinting()); + copy->getExpressionsForPrinting()); } } diff --git a/src/processor/mapper/plan_mapper.cpp b/src/processor/mapper/plan_mapper.cpp index 6500e2e1c3..f27c9a09aa 100644 --- a/src/processor/mapper/plan_mapper.cpp +++ b/src/processor/mapper/plan_mapper.cpp @@ -116,7 +116,7 @@ unique_ptr PlanMapper::mapLogicalOperatorToPhysical( physicalOperator = mapLogicalCreateRelTableToPhysical(logicalOperator.get()); } break; case LogicalOperatorType::COPY_CSV: { - physicalOperator = mapLogicalCopyCSVToPhysical(logicalOperator.get()); + physicalOperator = mapLogicalCopyToPhysical(logicalOperator.get()); } break; case LogicalOperatorType::DROP_PROPERTY: { physicalOperator = mapLogicalDropPropertyToPhysical(logicalOperator.get()); diff --git a/src/processor/operator/CMakeLists.txt b/src/processor/operator/CMakeLists.txt index 2ae8ef29b7..db1b81b91f 100644 --- a/src/processor/operator/CMakeLists.txt +++ b/src/processor/operator/CMakeLists.txt @@ -1,5 +1,5 @@ add_subdirectory(aggregate) -add_subdirectory(copy_csv) +add_subdirectory(copy) add_subdirectory(ddl) add_subdirectory(hash_join) add_subdirectory(intersect) diff --git a/src/processor/operator/copy/CMakeLists.txt b/src/processor/operator/copy/CMakeLists.txt new file mode 100644 index 0000000000..d553bb358f --- /dev/null +++ b/src/processor/operator/copy/CMakeLists.txt @@ -0,0 +1,9 @@ +add_library(kuzu_processor_operator_copy + OBJECT + copy.cpp + copy_node.cpp + copy_rel.cpp) + +set(ALL_OBJECT_FILES + ${ALL_OBJECT_FILES} $ + PARENT_SCOPE) diff --git a/src/processor/operator/copy_csv/copy_csv.cpp b/src/processor/operator/copy/copy.cpp similarity index 63% rename from src/processor/operator/copy_csv/copy_csv.cpp rename to src/processor/operator/copy/copy.cpp index c8214c4219..76a8992516 100644 --- a/src/processor/operator/copy_csv/copy_csv.cpp +++ b/src/processor/operator/copy/copy.cpp @@ -1,9 +1,9 @@ -#include "processor/operator/copy_csv/copy_csv.h" +#include "processor/operator/copy/copy.h" namespace kuzu { namespace processor { -string CopyCSV::execute(TaskScheduler* taskScheduler, ExecutionContext* executionContext) { +string Copy::execute(TaskScheduler* taskScheduler, ExecutionContext* executionContext) { registerProfilingMetrics(executionContext->profiler); metrics->executionTime.start(); errorIfTableIsNonEmpty(); @@ -13,17 +13,17 @@ string CopyCSV::execute(TaskScheduler* taskScheduler, ExecutionContext* executio return getOutputMsg(numTuplesCopied); } -void CopyCSV::errorIfTableIsNonEmpty() { +void Copy::errorIfTableIsNonEmpty() { auto numTuples = getNumTuplesInTable(); if (numTuples > 0) { auto tableName = catalog->getReadOnlyVersion()->getTableSchema(tableID)->tableName; - throw CopyCSVException( - "COPY CSV commands can be executed only on completely empty tables. Table: " + - tableName + " has " + to_string(numTuples) + " many tuples."); + throw CopyException( + "COPY commands can be executed only on completely empty tables. Table: " + tableName + + " has " + to_string(numTuples) + " many tuples."); } } -std::string CopyCSV::getOutputMsg(uint64_t numTuplesCopied) { +std::string Copy::getOutputMsg(uint64_t numTuplesCopied) { return StringUtils::string_format("%d number of tuples has been copied to table: %s.", numTuplesCopied, catalog->getReadOnlyVersion()->getTableName(tableID).c_str()); } diff --git a/src/processor/operator/copy_csv/copy_node_csv.cpp b/src/processor/operator/copy/copy_node.cpp similarity index 51% rename from src/processor/operator/copy_csv/copy_node_csv.cpp rename to src/processor/operator/copy/copy_node.cpp index 49c769ae6d..48f8462496 100644 --- a/src/processor/operator/copy_csv/copy_node_csv.cpp +++ b/src/processor/operator/copy/copy_node.cpp @@ -1,22 +1,22 @@ -#include "processor/operator/copy_csv/copy_node_csv.h" +#include "processor/operator/copy/copy_node.h" -#include "storage/in_mem_csv_copier/in_mem_arrow_node_copier.h" +#include "storage/copy_arrow/copy_node_arrow.h" namespace kuzu { namespace processor { -uint64_t CopyNodeCSV::executeInternal( +uint64_t CopyNode::executeInternal( common::TaskScheduler* taskScheduler, ExecutionContext* executionContext) { - auto nodeCSVCopier = make_unique( - csvDescription, wal->getDirectory(), *taskScheduler, *catalog, tableID, nodesStatistics); + auto nodeCSVCopier = make_unique( + copyDescription, wal->getDirectory(), *taskScheduler, *catalog, tableID, nodesStatistics); auto numNodesCopied = nodeCSVCopier->copy(); - wal->logCopyNodeCSVRecord(tableID); + wal->logCopyNodeRecord(tableID); return numNodesCopied; } -uint64_t CopyNodeCSV::getNumTuplesInTable() { +uint64_t CopyNode::getNumTuplesInTable() { // TODO(Ziyi): this chains looks weird. Fix when refactoring table statistics. Ditto in - // CopyRelCSV. + // CopyRel. return nodesStatistics->getReadOnlyVersion()->tableStatisticPerTable[tableID]->getNumTuples(); } diff --git a/src/processor/operator/copy_csv/copy_rel_csv.cpp b/src/processor/operator/copy/copy_rel.cpp similarity index 60% rename from src/processor/operator/copy_csv/copy_rel_csv.cpp rename to src/processor/operator/copy/copy_rel.cpp index ff7b0455d2..7e466bb131 100644 --- a/src/processor/operator/copy_csv/copy_rel_csv.cpp +++ b/src/processor/operator/copy/copy_rel.cpp @@ -1,21 +1,21 @@ -#include "processor/operator/copy_csv/copy_rel_csv.h" +#include "processor/operator/copy/copy_rel.h" -#include "storage/in_mem_csv_copier/in_mem_rel_csv_copier.h" +#include "storage/copy_arrow/copy_rel_arrow.h" namespace kuzu { namespace processor { -uint64_t CopyRelCSV::executeInternal( +uint64_t CopyRel::executeInternal( kuzu::common::TaskScheduler* taskScheduler, ExecutionContext* executionContext) { - auto relCSVCopier = make_unique(csvDescription, wal->getDirectory(), + auto relCSVCopier = make_unique(copyDescription, wal->getDirectory(), *taskScheduler, *catalog, nodesStatistics->getMaxNodeOffsetPerTable(), executionContext->bufferManager, tableID, relsStatistics); auto numRelsCopied = relCSVCopier->copy(); - wal->logCopyRelCSVRecord(tableID); + wal->logCopyRelRecord(tableID); return numRelsCopied; } -uint64_t CopyRelCSV::getNumTuplesInTable() { +uint64_t CopyRel::getNumTuplesInTable() { return relsStatistics->getReadOnlyVersion()->tableStatisticPerTable[tableID]->getNumTuples(); } diff --git a/src/processor/operator/copy_csv/CMakeLists.txt b/src/processor/operator/copy_csv/CMakeLists.txt deleted file mode 100644 index b7d06e75b0..0000000000 --- a/src/processor/operator/copy_csv/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -add_library(kuzu_processor_operator_copy_csv - OBJECT - copy_csv.cpp - copy_node_csv.cpp - copy_rel_csv.cpp) - -set(ALL_OBJECT_FILES - ${ALL_OBJECT_FILES} $ - PARENT_SCOPE) diff --git a/src/processor/operator/physical_operator.cpp b/src/processor/operator/physical_operator.cpp index 33559bf122..e3f5986ba9 100644 --- a/src/processor/operator/physical_operator.cpp +++ b/src/processor/operator/physical_operator.cpp @@ -15,11 +15,11 @@ std::string PhysicalOperatorUtils::operatorTypeToString(PhysicalOperatorType ope case PhysicalOperatorType::AGGREGATE_SCAN: { return "AGGREGATE_SCAN"; } - case PhysicalOperatorType::COPY_NODE_CSV: { - return "COPY_NODE_CSV"; + case PhysicalOperatorType::COPY_NODE: { + return "COPY_NODE"; } - case PhysicalOperatorType::COPY_REL_CSV: { - return "COPY_REL_CSV"; + case PhysicalOperatorType::COPY_REL: { + return "COPY_REL"; } case PhysicalOperatorType::CREATE_NODE: { return "CREATE_NODE"; diff --git a/src/processor/processor.cpp b/src/processor/processor.cpp index 998618c626..68af5fcbe0 100644 --- a/src/processor/processor.cpp +++ b/src/processor/processor.cpp @@ -1,7 +1,7 @@ #include "processor/processor.h" #include "processor/operator/aggregate/base_aggregate.h" -#include "processor/operator/copy_csv/copy_csv.h" +#include "processor/operator/copy/copy.h" #include "processor/operator/ddl/ddl.h" #include "processor/operator/result_collector.h" #include "processor/operator/sink.h" @@ -18,9 +18,9 @@ QueryProcessor::QueryProcessor(uint64_t numThreads) { shared_ptr QueryProcessor::execute( PhysicalPlan* physicalPlan, ExecutionContext* context) { - if (physicalPlan->isCopyCSV()) { - auto copyCSV = (CopyCSV*)physicalPlan->lastOperator.get(); - auto outputMsg = copyCSV->execute(taskScheduler.get(), context); + if (physicalPlan->isCopy()) { + auto copy = (Copy*)physicalPlan->lastOperator.get(); + auto outputMsg = copy->execute(taskScheduler.get(), context); return getFactorizedTableForOutputMsg(outputMsg, context->memoryManager); } else { auto lastOperator = physicalPlan->lastOperator.get(); diff --git a/src/storage/CMakeLists.txt b/src/storage/CMakeLists.txt index 939479b6d9..8469e58a9d 100644 --- a/src/storage/CMakeLists.txt +++ b/src/storage/CMakeLists.txt @@ -1,5 +1,5 @@ add_subdirectory(buffer_manager) -add_subdirectory(in_mem_csv_copier) +add_subdirectory(copy_arrow) add_subdirectory(in_mem_storage_structure) add_subdirectory(index) add_subdirectory(storage_structure) diff --git a/src/storage/in_mem_csv_copier/CMakeLists.txt b/src/storage/copy_arrow/CMakeLists.txt similarity index 62% rename from src/storage/in_mem_csv_copier/CMakeLists.txt rename to src/storage/copy_arrow/CMakeLists.txt index 8539387d28..dff1beee08 100644 --- a/src/storage/in_mem_csv_copier/CMakeLists.txt +++ b/src/storage/copy_arrow/CMakeLists.txt @@ -1,8 +1,8 @@ add_library(kuzu_storage_in_mem_csv_copier OBJECT - in_mem_arrow_node_copier.cpp - in_mem_rel_csv_copier.cpp - in_mem_structures_copier.cpp) + copy_node_arrow.cpp + copy_rel_arrow.cpp + copy_structures_arrow.cpp) set(ALL_OBJECT_FILES ${ALL_OBJECT_FILES} $ diff --git a/src/storage/copy_arrow/copy_node_arrow.cpp b/src/storage/copy_arrow/copy_node_arrow.cpp new file mode 100644 index 0000000000..49e3eedbce --- /dev/null +++ b/src/storage/copy_arrow/copy_node_arrow.cpp @@ -0,0 +1,301 @@ +#include "storage/copy_arrow/copy_node_arrow.h" + +#include "storage/copy_arrow/copy_task.h" +#include "storage/storage_structure/in_mem_file.h" + +namespace kuzu { +namespace storage { + +CopyNodeArrow::CopyNodeArrow(CopyDescription& copyDescription, string outputDirectory, + TaskScheduler& taskScheduler, Catalog& catalog, table_id_t tableID, + NodesStatisticsAndDeletedIDs* nodesStatisticsAndDeletedIDs) + : CopyStructuresArrow{copyDescription, std::move(outputDirectory), taskScheduler, catalog}, + nodesStatisticsAndDeletedIDs{nodesStatisticsAndDeletedIDs} { + nodeTableSchema = catalog.getReadOnlyVersion()->getNodeTableSchema(tableID); +} + +uint64_t CopyNodeArrow::copy() { + auto read_start = std::chrono::high_resolution_clock::now(); + logger->info( + "Reading " + CopyDescription::getFileTypeName(copyDescription.fileType) + " file."); + + countNumLines(copyDescription.filePath); + initializeColumnsAndList(); + + arrow::Status status; + + switch (nodeTableSchema->getPrimaryKey().dataType.typeID) { + case INT64: { + status = populateColumns(); + } break; + case STRING: { + status = populateColumns(); + } break; + default: { + throw CopyException("Unsupported data type " + + Types::dataTypeToString(nodeTableSchema->getPrimaryKey().dataType) + + " for the ID index."); + } + } + + throwCopyExceptionIfNotOK(status); + + auto read_end = std::chrono::high_resolution_clock::now(); + auto write_start = std::chrono::high_resolution_clock::now(); + + saveToFile(); + nodesStatisticsAndDeletedIDs->setNumTuplesForTable(nodeTableSchema->tableID, numRows); + logger->info("Done copying node {} with table {}.", nodeTableSchema->tableName, + nodeTableSchema->tableID); + + auto write_end = std::chrono::high_resolution_clock::now(); + auto read_time = std::chrono::duration_cast(read_end - read_start); + auto write_time = + std::chrono::duration_cast(write_end - write_start); + auto total_time = std::chrono::duration_cast(write_end - read_start); + logger->debug("read time: {}.", read_time.count()); + logger->debug("write time: {}.", write_time.count()); + logger->debug("total time: {}.", total_time.count()); + return numRows; +} + +void CopyNodeArrow::initializeColumnsAndList() { + logger->info("Initializing in memory columns."); + columns.resize(nodeTableSchema->getNumProperties()); + for (auto& property : nodeTableSchema->properties) { + auto fName = StorageUtils::getNodePropertyColumnFName(outputDirectory, + nodeTableSchema->tableID, property.propertyID, DBFileType::WAL_VERSION); + columns[property.propertyID] = + InMemColumnFactory::getInMemPropertyColumn(fName, property.dataType, numRows); + } + logger->info("Done initializing in memory columns."); +} + +template +arrow::Status CopyNodeArrow::populateColumns() { + logger->info("Populating properties"); + auto pkIndex = + make_unique>(StorageUtils::getNodeIndexFName(this->outputDirectory, + nodeTableSchema->tableID, DBFileType::WAL_VERSION), + nodeTableSchema->getPrimaryKey().dataType); + pkIndex->bulkReserve(numRows); + + arrow::Status status; + switch (copyDescription.fileType) { + case CopyDescription::FileType::CSV: + status = populateColumnsFromCSV(pkIndex); + break; + case CopyDescription::FileType::ARROW: + status = populateColumnsFromArrow(pkIndex); + break; + case CopyDescription::FileType::PARQUET: + status = populateColumnsFromParquet(pkIndex); + break; + } + + logger->info("Flush the pk index to disk."); + pkIndex->flush(); + logger->info("Done populating properties, constructing the pk index."); + return status; +} + +template +arrow::Status CopyNodeArrow::populateColumnsFromCSV(unique_ptr>& pkIndex) { + node_offset_t offsetStart = 0; + + shared_ptr csv_streaming_reader; + auto status = initCSVReader(csv_streaming_reader, copyDescription.filePath); + throwCopyExceptionIfNotOK(status); + + std::shared_ptr currBatch; + + int blockIdx = 0; + auto it = csv_streaming_reader->begin(); + auto endIt = csv_streaming_reader->end(); + while (it != endIt) { + for (int i = 0; i < CopyConfig::NUM_COPIER_TASKS_TO_SCHEDULE_PER_BATCH; ++i) { + if (it == endIt) { + break; + } + ARROW_ASSIGN_OR_RAISE(currBatch, *it); + taskScheduler.scheduleTask(CopyTaskFactory::createCopyTask( + batchPopulateColumnsTask, nodeTableSchema->primaryKeyPropertyID, + blockIdx, offsetStart, pkIndex.get(), this, currBatch->columns(), copyDescription)); + offsetStart += currBatch->num_rows(); + ++blockIdx; + ++it; + } + taskScheduler.waitUntilEnoughTasksFinish( + CopyConfig::MINIMUM_NUM_COPIER_TASKS_TO_SCHEDULE_MORE); + } + taskScheduler.waitAllTasksToCompleteOrError(); + return arrow::Status::OK(); +} + +template +arrow::Status CopyNodeArrow::populateColumnsFromArrow(unique_ptr>& pkIndex) { + node_offset_t offsetStart = 0; + + std::shared_ptr ipc_reader; + auto status = initArrowReader(ipc_reader, copyDescription.filePath); + throwCopyExceptionIfNotOK(status); + + std::shared_ptr currBatch; + + int blockIdx = 0; + while (blockIdx < numBlocks) { + for (int i = 0; i < CopyConfig::NUM_COPIER_TASKS_TO_SCHEDULE_PER_BATCH; ++i) { + if (blockIdx == numBlocks) { + break; + } + ARROW_ASSIGN_OR_RAISE(currBatch, ipc_reader->ReadRecordBatch(blockIdx)); + taskScheduler.scheduleTask(CopyTaskFactory::createCopyTask( + batchPopulateColumnsTask, nodeTableSchema->primaryKeyPropertyID, + blockIdx, offsetStart, pkIndex.get(), this, currBatch->columns(), copyDescription)); + offsetStart += currBatch->num_rows(); + ++blockIdx; + } + taskScheduler.waitUntilEnoughTasksFinish( + CopyConfig::MINIMUM_NUM_COPIER_TASKS_TO_SCHEDULE_MORE); + } + + taskScheduler.waitAllTasksToCompleteOrError(); + return arrow::Status::OK(); +} + +template +arrow::Status CopyNodeArrow::populateColumnsFromParquet(unique_ptr>& pkIndex) { + node_offset_t offsetStart = 0; + + std::unique_ptr reader; + auto status = initParquetReader(reader, copyDescription.filePath); + throwCopyExceptionIfNotOK(status); + + std::shared_ptr currTable; + int blockIdx = 0; + while (blockIdx < numBlocks) { + for (int i = 0; i < CopyConfig::NUM_COPIER_TASKS_TO_SCHEDULE_PER_BATCH; ++i) { + if (blockIdx == numBlocks) { + break; + } + ARROW_RETURN_NOT_OK(reader->RowGroup(blockIdx)->ReadTable(&currTable)); + taskScheduler.scheduleTask( + CopyTaskFactory::createCopyTask(batchPopulateColumnsTask, + nodeTableSchema->primaryKeyPropertyID, blockIdx, offsetStart, pkIndex.get(), + this, currTable->columns(), copyDescription)); + offsetStart += currTable->num_rows(); + ++blockIdx; + } + taskScheduler.waitUntilEnoughTasksFinish( + CopyConfig::MINIMUM_NUM_COPIER_TASKS_TO_SCHEDULE_MORE); + } + + taskScheduler.waitAllTasksToCompleteOrError(); + return arrow::Status::OK(); +} + +template +void CopyNodeArrow::populatePKIndex(InMemColumn* column, HashIndexBuilder* pkIndex, + node_offset_t startOffset, uint64_t numValues) { + for (auto i = 0u; i < numValues; i++) { + auto offset = i + startOffset; + if constexpr (is_same::value) { + auto key = (int64_t*)column->getElement(offset); + if (!pkIndex->append(*key, offset)) { + throw CopyException(Exception::getExistedPKExceptionMsg(to_string(*key))); + } + } else { + auto element = (ku_string_t*)column->getElement(offset); + auto key = column->getInMemOverflowFile()->readString(element); + if (!pkIndex->append(key.c_str(), offset)) { + throw CopyException(Exception::getExistedPKExceptionMsg(key)); + } + } + } +} + +template +arrow::Status CopyNodeArrow::batchPopulateColumnsTask(uint64_t primaryKeyPropertyIdx, + uint64_t blockId, uint64_t offsetStart, HashIndexBuilder* pkIndex, CopyNodeArrow* copier, + const vector>& batchColumns, CopyDescription& copyDescription) { + copier->logger->trace("Start: path={0} blkIdx={1}", copier->copyDescription.filePath, blockId); + vector overflowCursors(copier->nodeTableSchema->getNumProperties()); + for (auto blockOffset = 0u; blockOffset < copier->numLinesPerBlock[blockId]; ++blockOffset) { + putPropsOfLineIntoColumns(copier->columns, overflowCursors, batchColumns, + offsetStart + blockOffset, blockOffset, copyDescription); + } + populatePKIndex(copier->columns[primaryKeyPropertyIdx].get(), pkIndex, offsetStart, + copier->numLinesPerBlock[blockId]); + copier->logger->trace("End: path={0} blkIdx={1}", copier->copyDescription.filePath, blockId); + return arrow::Status::OK(); +} + +template +void CopyNodeArrow::putPropsOfLineIntoColumns(vector>& structuredColumns, + vector& overflowCursors, const std::vector>& arrow_columns, + uint64_t nodeOffset, uint64_t blockOffset, CopyDescription& copyDescription) { + for (auto columnIdx = 0u; columnIdx < structuredColumns.size(); columnIdx++) { + auto column = structuredColumns[columnIdx].get(); + auto currentToken = arrow_columns[columnIdx]->GetScalar(blockOffset); + if ((*currentToken)->is_valid) { + auto stringToken = currentToken->get()->ToString().substr(0, DEFAULT_PAGE_SIZE); + const char* data = stringToken.c_str(); + + switch (column->getDataType().typeID) { + case INT64: { + int64_t val = TypeUtils::convertToInt64(data); + column->setElement(nodeOffset, reinterpret_cast(&val)); + } break; + case DOUBLE: { + double_t val = TypeUtils::convertToDouble(data); + column->setElement(nodeOffset, reinterpret_cast(&val)); + } break; + case BOOL: { + bool val = TypeUtils::convertToBoolean(data); + column->setElement(nodeOffset, reinterpret_cast(&val)); + } break; + case DATE: { + date_t val = Date::FromCString(data, stringToken.length()); + column->setElement(nodeOffset, reinterpret_cast(&val)); + } break; + case TIMESTAMP: { + timestamp_t val = Timestamp::FromCString(data, stringToken.length()); + column->setElement(nodeOffset, reinterpret_cast(&val)); + } break; + case INTERVAL: { + interval_t val = Interval::FromCString(data, stringToken.length()); + column->setElement(nodeOffset, reinterpret_cast(&val)); + } break; + case STRING: { + auto val = + column->getInMemOverflowFile()->copyString(data, overflowCursors[columnIdx]); + + column->setElement(nodeOffset, reinterpret_cast(&val)); + } break; + case LIST: { + Literal listVal = getArrowList(stringToken, 1, stringToken.length() - 2, + column->getDataType(), copyDescription); + auto kuList = + column->getInMemOverflowFile()->copyList(listVal, overflowCursors[columnIdx]); + column->setElement(nodeOffset, reinterpret_cast(&kuList)); + } break; + default: + break; + } + } + } +} + +void CopyNodeArrow::saveToFile() { + logger->debug("Writing node columns to disk."); + assert(!columns.empty()); + for (auto& column : columns) { + taskScheduler.scheduleTask(CopyTaskFactory::createCopyTask( + [&](InMemColumn* x) { x->saveToFile(); }, column.get())); + } + taskScheduler.waitAllTasksToCompleteOrError(); + logger->debug("Done writing node columns to disk."); +} + +} // namespace storage +} // namespace kuzu diff --git a/src/storage/in_mem_csv_copier/in_mem_rel_csv_copier.cpp b/src/storage/copy_arrow/copy_rel_arrow.cpp similarity index 60% rename from src/storage/in_mem_csv_copier/in_mem_rel_csv_copier.cpp rename to src/storage/copy_arrow/copy_rel_arrow.cpp index d0ad8278ab..6a6fab638c 100644 --- a/src/storage/in_mem_csv_copier/in_mem_rel_csv_copier.cpp +++ b/src/storage/copy_arrow/copy_rel_arrow.cpp @@ -1,17 +1,18 @@ -#include "storage/in_mem_csv_copier/in_mem_rel_csv_copier.h" +#include "storage/copy_arrow/copy_rel_arrow.h" #include "spdlog/spdlog.h" -#include "storage/in_mem_csv_copier/copy_csv_task.h" +#include "storage/copy_arrow/copy_task.h" namespace kuzu { namespace storage { -InMemRelCSVCopier::InMemRelCSVCopier(CSVDescription& csvDescription, string outputDirectory, +CopyRelArrow::CopyRelArrow(CopyDescription& copyDescription, string outputDirectory, TaskScheduler& taskScheduler, Catalog& catalog, map maxNodeOffsetsPerNodeTable, BufferManager* bufferManager, table_id_t tableID, RelsStatistics* relsStatistics) - : InMemStructuresCopier{csvDescription, move(outputDirectory), taskScheduler, catalog}, - maxNodeOffsetsPerTable{move(maxNodeOffsetsPerNodeTable)}, relsStatistics{relsStatistics} { + : CopyStructuresArrow{copyDescription, std::move(outputDirectory), taskScheduler, catalog}, + maxNodeOffsetsPerTable{std::move(maxNodeOffsetsPerNodeTable)}, relsStatistics{ + relsStatistics} { dummyReadOnlyTrx = Transaction::getDummyReadOnlyTrx(); startRelID = relsStatistics->getNextRelID(dummyReadOnlyTrx.get()); relTableSchema = catalog.getReadOnlyVersion()->getRelTableSchema(tableID); @@ -24,13 +25,15 @@ InMemRelCSVCopier::InMemRelCSVCopier(CSVDescription& csvDescription, string outp } } -uint64_t InMemRelCSVCopier::copy() { +uint64_t CopyRelArrow::copy() { logger->info( "Copying rel {} with table {}.", relTableSchema->tableName, relTableSchema->tableID); - calculateNumBlocks(csvDescription.filePath, relTableSchema->tableName); - countLinesPerBlock(); - auto numRels = calculateNumRows(csvDescription.csvReaderConfig.hasHeader); + logger->info( + "Reading " + CopyDescription::getFileTypeName(copyDescription.fileType) + " file."); + + countNumLines(copyDescription.filePath); initializeColumnsAndLists(); + // Construct columns and lists. populateAdjColumnsAndCountRelsInAdjLists(); if (!directionTableAdjLists[FWD].empty() || !directionTableAdjLists[BWD].empty()) { @@ -40,24 +43,13 @@ uint64_t InMemRelCSVCopier::copy() { } sortAndCopyOverflowValues(); saveToFile(); - relsStatistics->setNumRelsForTable(relTableSchema->tableID, numRels); + relsStatistics->setNumRelsForTable(relTableSchema->tableID, numRows); logger->info( "Done copying rel {} with table {}.", relTableSchema->tableName, relTableSchema->tableID); - return numRels; + return numRows; } -void InMemRelCSVCopier::countLinesPerBlock() { - logger->info("Counting number of lines in each block"); - numLinesPerBlock.resize(numBlocks); - for (auto blockId = 0u; blockId < numBlocks; blockId++) { - taskScheduler.scheduleTask(CopyCSVTaskFactory::createCopyCSVTask( - countNumLinesPerBlockTask, csvDescription.filePath, blockId, this)); - } - taskScheduler.waitAllTasksToCompleteOrError(); - logger->info("Done counting number of lines in each block."); -} - -void InMemRelCSVCopier::initializeColumnsAndLists() { +void CopyRelArrow::initializeColumnsAndLists() { directionNumRelsPerTable.resize(2); directionTableListSizes.resize(2); for (auto relDirection : REL_DIRECTIONS) { @@ -87,7 +79,7 @@ void InMemRelCSVCopier::initializeColumnsAndLists() { } } -void InMemRelCSVCopier::initializeColumns(RelDirection relDirection) { +void CopyRelArrow::initializeColumns(RelDirection relDirection) { auto boundTableIDs = catalog.getReadOnlyVersion()->getNodeTableIDsForRelTableDirection( relTableSchema->tableID, relDirection); for (auto boundTableID : boundTableIDs) { @@ -112,7 +104,7 @@ void InMemRelCSVCopier::initializeColumns(RelDirection relDirection) { } } -void InMemRelCSVCopier::initializeLists(RelDirection relDirection) { +void CopyRelArrow::initializeLists(RelDirection relDirection) { auto boundTableIDs = catalog.getReadOnlyVersion()->getNodeTableIDsForRelTableDirection( relTableSchema->tableID, relDirection); for (auto boundTableID : boundTableIDs) { @@ -136,23 +128,134 @@ void InMemRelCSVCopier::initializeLists(RelDirection relDirection) { } } -void InMemRelCSVCopier::populateAdjColumnsAndCountRelsInAdjLists() { +arrow::Status CopyRelArrow::executePopulateTask(PopulateTaskType populateTaskType) { + arrow::Status status; + switch (copyDescription.fileType) { + case CopyDescription::FileType::CSV: + status = populateFromCSV(populateTaskType); + break; + + case CopyDescription::FileType::ARROW: + status = populateFromArrow(populateTaskType); + break; + + case CopyDescription::FileType::PARQUET: + status = populateFromParquet(populateTaskType); + break; + } + return status; +} + +void CopyRelArrow::populateAdjColumnsAndCountRelsInAdjLists() { logger->info( "Populating adj columns and rel property columns for rel {}.", relTableSchema->tableName); - auto blockStartOffset = 0ull; - for (auto blockIdx = 0u; blockIdx < numBlocks; blockIdx++) { - taskScheduler.scheduleTask( - CopyCSVTaskFactory::createCopyCSVTask(populateAdjColumnsAndCountRelsInAdjListsTask, - blockIdx, startRelID + blockStartOffset, this)); - blockStartOffset += numLinesPerBlock[blockIdx]; - } - taskScheduler.waitAllTasksToCompleteOrError(); + auto status = + executePopulateTask(PopulateTaskType::populateAdjColumnsAndCountRelsInAdjListsTask); + throwCopyExceptionIfNotOK(status); relsStatistics->setNumRelsPerDirectionBoundTableID( relTableSchema->tableID, directionNumRelsPerTable); logger->info("Done populating adj columns and rel property columns for rel {}.", relTableSchema->tableName); } +arrow::Status CopyRelArrow::populateFromCSV(PopulateTaskType populateTaskType) { + auto populateTask = populateAdjColumnsAndCountRelsInAdjListsTask; + if (populateTaskType == PopulateTaskType::populateListsTask) { + populateTask = populateListsTask; + } + logger->debug("Assigning task {0}", getTaskTypeName(populateTaskType)); + + shared_ptr csv_streaming_reader; + auto status = initCSVReader(csv_streaming_reader, copyDescription.filePath); + throwCopyExceptionIfNotOK(status); + std::shared_ptr currBatch; + int blockIdx = 0; + auto blockStartOffset = 0ull; + auto it = csv_streaming_reader->begin(); + auto endIt = csv_streaming_reader->end(); + while (it != endIt) { + for (int i = 0; i < CopyConfig::NUM_COPIER_TASKS_TO_SCHEDULE_PER_BATCH; ++i) { + if (it == endIt) { + break; + } + ARROW_ASSIGN_OR_RAISE(currBatch, *it); + taskScheduler.scheduleTask(CopyTaskFactory::createCopyTask(populateTask, blockIdx, + startRelID + blockStartOffset, this, currBatch->columns(), copyDescription)); + blockStartOffset += numLinesPerBlock[blockIdx]; + ++it; + ++blockIdx; + } + taskScheduler.waitUntilEnoughTasksFinish( + CopyConfig::MINIMUM_NUM_COPIER_TASKS_TO_SCHEDULE_MORE); + } + taskScheduler.waitAllTasksToCompleteOrError(); + return arrow::Status::OK(); +} + +arrow::Status CopyRelArrow::populateFromArrow(PopulateTaskType populateTaskType) { + auto populateTask = populateAdjColumnsAndCountRelsInAdjListsTask; + if (populateTaskType == PopulateTaskType::populateListsTask) { + populateTask = populateListsTask; + } + logger->debug("Assigning task {0}", getTaskTypeName(populateTaskType)); + + std::shared_ptr ipc_reader; + auto status = initArrowReader(ipc_reader, copyDescription.filePath); + throwCopyExceptionIfNotOK(status); + std::shared_ptr currBatch; + int blockIdx = 0; + auto blockStartOffset = 0ull; + while (blockIdx < numBlocks) { + for (int i = 0; i < CopyConfig::NUM_COPIER_TASKS_TO_SCHEDULE_PER_BATCH; ++i) { + if (blockIdx == numBlocks) { + break; + } + ARROW_ASSIGN_OR_RAISE(currBatch, ipc_reader->ReadRecordBatch(blockIdx)); + taskScheduler.scheduleTask(CopyTaskFactory::createCopyTask(populateTask, blockIdx, + startRelID + blockStartOffset, this, currBatch->columns(), copyDescription)); + blockStartOffset += numLinesPerBlock[blockIdx]; + ++blockIdx; + } + taskScheduler.waitUntilEnoughTasksFinish( + CopyConfig::MINIMUM_NUM_COPIER_TASKS_TO_SCHEDULE_MORE); + } + + taskScheduler.waitAllTasksToCompleteOrError(); + return arrow::Status::OK(); +} + +arrow::Status CopyRelArrow::populateFromParquet(PopulateTaskType populateTaskType) { + auto populateTask = populateAdjColumnsAndCountRelsInAdjListsTask; + if (populateTaskType == PopulateTaskType::populateListsTask) { + populateTask = populateListsTask; + } + logger->debug("Assigning task {0}", getTaskTypeName(populateTaskType)); + + std::unique_ptr reader; + auto status = initParquetReader(reader, copyDescription.filePath); + throwCopyExceptionIfNotOK(status); + std::shared_ptr currTable; + int blockIdx = 0; + auto blockStartOffset = 0ull; + while (blockIdx < numBlocks) { + for (int i = 0; i < CopyConfig::NUM_COPIER_TASKS_TO_SCHEDULE_PER_BATCH; ++i) { + if (blockIdx == numBlocks) { + break; + } + ARROW_RETURN_NOT_OK(reader->RowGroup(blockIdx)->ReadTable(&currTable)); + taskScheduler.scheduleTask(CopyTaskFactory::createCopyTask(populateTask, blockIdx, + startRelID + blockStartOffset, this, currTable->columns(), copyDescription)); + blockStartOffset += numLinesPerBlock[blockIdx]; + ++blockIdx; + } + taskScheduler.waitUntilEnoughTasksFinish( + CopyConfig::MINIMUM_NUM_COPIER_TASKS_TO_SCHEDULE_MORE); + } + + taskScheduler.waitAllTasksToCompleteOrError(); + return arrow::Status::OK(); +} + static void putValueIntoColumns(uint64_t propertyIdx, vector& directionTablePropertyColumns, const vector& nodeIDs, uint8_t* val) { @@ -167,19 +270,12 @@ static void putValueIntoColumns(uint64_t propertyIdx, } } -void InMemRelCSVCopier::skipFirstRowIfNecessary( - uint64_t blockId, const CSVDescription& csvDescription, CSVReader& reader) { - if (0 == blockId && csvDescription.csvReaderConfig.hasHeader && reader.hasNextLine()) { - reader.skipLine(); - } -} - -void InMemRelCSVCopier::populateAdjColumnsAndCountRelsInAdjListsTask( - uint64_t blockId, uint64_t blockStartRelID, InMemRelCSVCopier* copier) { - copier->logger->debug("Start: path=`{0}` blkIdx={1}", copier->csvDescription.filePath, blockId); - CSVReader reader( - copier->csvDescription.filePath, copier->csvDescription.csvReaderConfig, blockId); - skipFirstRowIfNecessary(blockId, copier->csvDescription, reader); +template +void CopyRelArrow::populateAdjColumnsAndCountRelsInAdjListsTask(uint64_t blockId, + uint64_t blockStartRelID, CopyRelArrow* copier, const vector>& batchColumns, + CopyDescription& copyDescription) { + copier->logger->debug( + "Start: path=`{0}` blkIdx={1}", copier->copyDescription.filePath, blockId); vector requireToReadTableLabels{true, true}; vector nodeIDs{2}; vector nodePKTypes{2}; @@ -195,10 +291,12 @@ void InMemRelCSVCopier::populateAdjColumnsAndCountRelsInAdjListsTask( .dataType; } vector inMemOverflowFileCursors{copier->relTableSchema->getNumProperties()}; - int64_t relID = blockStartRelID; - while (reader.hasNextLine()) { - inferTableIDsAndOffsets(reader, nodeIDs, nodePKTypes, copier->pkIndexes, - copier->dummyReadOnlyTrx.get(), copier->catalog, requireToReadTableLabels); + uint64_t relID = blockStartRelID; + for (auto blockOffset = 0u; blockOffset < copier->numLinesPerBlock[blockId]; ++blockOffset) { + int64_t colIndex = 0; + inferTableIDsAndOffsets(batchColumns, nodeIDs, nodePKTypes, copier->pkIndexes, + copier->dummyReadOnlyTrx.get(), copier->catalog, requireToReadTableLabels, blockOffset, + colIndex); for (auto relDirection : REL_DIRECTIONS) { auto tableID = nodeIDs[relDirection].tableID; auto nodeOffset = nodeIDs[relDirection].offset; @@ -206,7 +304,7 @@ void InMemRelCSVCopier::populateAdjColumnsAndCountRelsInAdjListsTask( if (!copier->directionTableAdjColumns[relDirection].at(tableID)->isNullAtNodeOffset( nodeOffset)) { auto relTableSchema = copier->relTableSchema; - throw CopyCSVException(StringUtils::string_format( + throw CopyException(StringUtils::string_format( "RelTable %s is a %s table, but node(nodeOffset: %d, tableName: %s) has " "more than one neighbour in the %s direction.", relTableSchema->tableName.c_str(), @@ -224,127 +322,131 @@ void InMemRelCSVCopier::populateAdjColumnsAndCountRelsInAdjListsTask( copier->directionNumRelsPerTable[relDirection].at(tableID)++; } if (copier->relTableSchema->getNumUserDefinedProperties() != 0) { - putPropsOfLineIntoColumns(copier, inMemOverflowFileCursors, reader, nodeIDs); + putPropsOfLineIntoColumns(copier, inMemOverflowFileCursors, batchColumns, nodeIDs, + blockOffset, colIndex, copyDescription); } putValueIntoColumns(copier->relTableSchema->getRelIDDefinition().propertyID, copier->directionTablePropertyColumns, nodeIDs, (uint8_t*)&relID); relID++; } - copier->logger->debug("End: path=`{0}` blkIdx={1}", copier->csvDescription.filePath, blockId); + copier->logger->debug("End: path=`{0}` blkIdx={1}", copier->copyDescription.filePath, blockId); } -void InMemRelCSVCopier::putPropsOfLineIntoColumns(InMemRelCSVCopier* copier, - vector& inMemOverflowFileCursors, CSVReader& reader, - const vector& nodeIDs) { +template +void CopyRelArrow::putPropsOfLineIntoColumns(CopyRelArrow* copier, + vector& inMemOverflowFileCursors, const vector>& batchColumns, + const vector& nodeIDs, int64_t blockOffset, int64_t& colIndex, + CopyDescription& copyDescription) { auto& properties = copier->relTableSchema->properties; auto& directionTablePropertyColumns = copier->directionTablePropertyColumns; auto& inMemOverflowFilePerPropertyID = copier->overflowFilePerPropertyID; for (auto propertyIdx = RelTableSchema::INTERNAL_REL_ID_PROPERTY_IDX + 1; propertyIdx < properties.size(); propertyIdx++) { - reader.hasNextTokenOrError(); + if (colIndex >= batchColumns.size()) { + throw CopyException("Number of columns mismatch."); + } + auto currentToken = batchColumns[colIndex]->GetScalar(blockOffset); + if (!(*currentToken)->is_valid) { + ++colIndex; + continue; + } + auto stringToken = currentToken->get()->ToString().substr(0, DEFAULT_PAGE_SIZE); + const char* data = stringToken.c_str(); switch (properties[propertyIdx].dataType.typeID) { case INT64: { - if (!reader.skipTokenIfNull()) { - auto int64Val = reader.getInt64(); - putValueIntoColumns(propertyIdx, directionTablePropertyColumns, nodeIDs, - reinterpret_cast(&int64Val)); - } + int64_t val = TypeUtils::convertToInt64(data); + putValueIntoColumns(propertyIdx, directionTablePropertyColumns, nodeIDs, + reinterpret_cast(&val)); } break; case DOUBLE: { - if (!reader.skipTokenIfNull()) { - auto doubleVal = reader.getDouble(); - putValueIntoColumns(propertyIdx, directionTablePropertyColumns, nodeIDs, - reinterpret_cast(&doubleVal)); - } + double_t val = TypeUtils::convertToDouble(data); + putValueIntoColumns(propertyIdx, directionTablePropertyColumns, nodeIDs, + reinterpret_cast(&val)); } break; case BOOL: { - if (!reader.skipTokenIfNull()) { - auto boolVal = reader.getBoolean(); - putValueIntoColumns(propertyIdx, directionTablePropertyColumns, nodeIDs, - reinterpret_cast(&boolVal)); - } + bool val = TypeUtils::convertToBoolean(data); + putValueIntoColumns(propertyIdx, directionTablePropertyColumns, nodeIDs, + reinterpret_cast(&val)); } break; case DATE: { - if (!reader.skipTokenIfNull()) { - auto dateVal = reader.getDate(); - putValueIntoColumns(propertyIdx, directionTablePropertyColumns, nodeIDs, - reinterpret_cast(&dateVal)); - } + date_t val = Date::FromCString(data, stringToken.length()); + putValueIntoColumns(propertyIdx, directionTablePropertyColumns, nodeIDs, + reinterpret_cast(&val)); } break; case TIMESTAMP: { - if (!reader.skipTokenIfNull()) { - auto timestampVal = reader.getTimestamp(); - putValueIntoColumns(propertyIdx, directionTablePropertyColumns, nodeIDs, - reinterpret_cast(×tampVal)); - } + timestamp_t val = Timestamp::FromCString(data, stringToken.length()); + putValueIntoColumns(propertyIdx, directionTablePropertyColumns, nodeIDs, + reinterpret_cast(&val)); } break; case INTERVAL: { - if (!reader.skipTokenIfNull()) { - auto intervalVal = reader.getInterval(); - putValueIntoColumns(propertyIdx, directionTablePropertyColumns, nodeIDs, - reinterpret_cast(&intervalVal)); - } + interval_t val = Interval::FromCString(data, stringToken.length()); + putValueIntoColumns(propertyIdx, directionTablePropertyColumns, nodeIDs, + reinterpret_cast(&val)); } break; case STRING: { - if (!reader.skipTokenIfNull()) { - auto strVal = reader.getString(); - auto kuStr = inMemOverflowFilePerPropertyID[propertyIdx]->copyString( - strVal, inMemOverflowFileCursors[propertyIdx]); - putValueIntoColumns(propertyIdx, directionTablePropertyColumns, nodeIDs, - reinterpret_cast(&kuStr)); - } + auto kuStr = inMemOverflowFilePerPropertyID[propertyIdx]->copyString( + data, inMemOverflowFileCursors[propertyIdx]); + putValueIntoColumns(propertyIdx, directionTablePropertyColumns, nodeIDs, + reinterpret_cast(&kuStr)); } break; case LIST: { - if (!reader.skipTokenIfNull()) { - auto listVal = reader.getList(*properties[propertyIdx].dataType.childType); - auto kuList = inMemOverflowFilePerPropertyID[propertyIdx]->copyList( - listVal, inMemOverflowFileCursors[propertyIdx]); - putValueIntoColumns(propertyIdx, directionTablePropertyColumns, nodeIDs, - reinterpret_cast(&kuList)); - } + Literal listVal = getArrowList(stringToken, 1, stringToken.length() - 2, + properties[propertyIdx].dataType, copyDescription); + auto kuList = inMemOverflowFilePerPropertyID[propertyIdx]->copyList( + listVal, inMemOverflowFileCursors[propertyIdx]); + putValueIntoColumns(propertyIdx, directionTablePropertyColumns, nodeIDs, + reinterpret_cast(&kuList)); } break; default: - if (!reader.skipTokenIfNull()) { - reader.skipToken(); - } + break; } + ++colIndex; } } -void InMemRelCSVCopier::inferTableIDsAndOffsets(CSVReader& reader, vector& nodeIDs, - vector& nodeIDTypes, const map>& pkIndexes, - Transaction* transaction, const Catalog& catalog, vector requireToReadTableLabels) { +template +void CopyRelArrow::inferTableIDsAndOffsets(const vector>& batchColumns, + vector& nodeIDs, vector& nodeIDTypes, + const map>& pkIndexes, Transaction* transaction, + const Catalog& catalog, vector requireToReadTableLabels, int64_t blockOffset, + int64_t& colIndex) { for (auto& relDirection : REL_DIRECTIONS) { - reader.hasNextToken(); if (requireToReadTableLabels[relDirection]) { - auto nodeTableName = reader.getString(); + if (colIndex >= batchColumns.size()) { + throw CopyException("Number of columns mismatch."); + } + auto nodeTableName = batchColumns[colIndex]->GetScalar(blockOffset)->get()->ToString(); if (!catalog.getReadOnlyVersion()->containNodeTable(nodeTableName)) { - throw CopyCSVException( - "NodeTableName: " + string(nodeTableName) + " does not exist."); + throw CopyException("NodeTableName: " + nodeTableName + " does not exist."); } nodeIDs[relDirection].tableID = - catalog.getReadOnlyVersion()->getNodeTableIDFromName(reader.getString()); - reader.hasNextToken(); + catalog.getReadOnlyVersion()->getNodeTableIDFromName(nodeTableName); + ++colIndex; } - auto keyStr = reader.getString(); + if (colIndex >= batchColumns.size()) { + throw CopyException("Number of columns mismatch."); + } + auto keyToken = batchColumns[colIndex]->GetScalar(blockOffset)->get()->ToString(); + auto keyStr = keyToken.c_str(); + ++colIndex; switch (nodeIDTypes[relDirection].typeID) { case INT64: { auto key = TypeUtils::convertToInt64(keyStr); if (!pkIndexes.at(nodeIDs[relDirection].tableID) ->lookup(transaction, key, nodeIDs[relDirection].offset)) { - throw CopyCSVException("Cannot find key: " + to_string(key) + " in the pkIndex."); + throw CopyException("Cannot find key: " + to_string(key) + " in the pkIndex."); } } break; case STRING: { if (!pkIndexes.at(nodeIDs[relDirection].tableID) ->lookup(transaction, keyStr, nodeIDs[relDirection].offset)) { - throw CopyCSVException("Cannot find key: " + string(keyStr) + " in the pkIndex."); + throw CopyException("Cannot find key: " + string(keyStr) + " in the pkIndex."); } } break; default: - throw CopyCSVException("Unsupported data type " + - Types::dataTypeToString(nodeIDTypes[relDirection]) + - " for index lookup."); + throw CopyException("Unsupported data type " + + Types::dataTypeToString(nodeIDTypes[relDirection]) + + " for index lookup."); } } } @@ -367,94 +469,88 @@ static void putValueIntoLists(uint64_t propertyIdx, } } -void InMemRelCSVCopier::putPropsOfLineIntoLists(InMemRelCSVCopier* copier, - vector& inMemOverflowFileCursors, CSVReader& reader, - const vector& nodeIDs, const vector& reversePos) { +template +void CopyRelArrow::putPropsOfLineIntoLists(CopyRelArrow* copier, + vector& inMemOverflowFileCursors, const vector>& batchColumns, + const vector& nodeIDs, const vector& reversePos, int64_t blockOffset, + int64_t& colIndex, CopyDescription& copyDescription) { auto& properties = copier->relTableSchema->properties; auto& directionTablePropertyLists = copier->directionTablePropertyLists; auto& directionTableAdjLists = copier->directionTableAdjLists; auto& inMemOverflowFilesPerProperty = copier->overflowFilePerPropertyID; for (auto propertyIdx = RelTableSchema::INTERNAL_REL_ID_PROPERTY_IDX + 1; propertyIdx < properties.size(); propertyIdx++) { - reader.hasNextToken(); + if (colIndex >= batchColumns.size()) { + throw CopyException("Number of columns mismatch."); + } + auto currentToken = batchColumns[colIndex]->GetScalar(blockOffset); + if (!(*currentToken)->is_valid) { + ++colIndex; + continue; + } + auto stringToken = currentToken->get()->ToString().substr(0, DEFAULT_PAGE_SIZE); + const char* data = stringToken.c_str(); switch (properties[propertyIdx].dataType.typeID) { case INT64: { - if (!reader.skipTokenIfNull()) { - auto intVal = reader.getInt64(); - putValueIntoLists(propertyIdx, directionTablePropertyLists, directionTableAdjLists, - nodeIDs, reversePos, reinterpret_cast(&intVal)); - } + int64_t val = TypeUtils::convertToInt64(data); + putValueIntoLists(propertyIdx, directionTablePropertyLists, directionTableAdjLists, + nodeIDs, reversePos, reinterpret_cast(&val)); } break; case DOUBLE: { - if (!reader.skipTokenIfNull()) { - auto doubleVal = reader.getDouble(); - putValueIntoLists(propertyIdx, directionTablePropertyLists, directionTableAdjLists, - nodeIDs, reversePos, reinterpret_cast(&doubleVal)); - } + double_t val = TypeUtils::convertToDouble(data); + putValueIntoLists(propertyIdx, directionTablePropertyLists, directionTableAdjLists, + nodeIDs, reversePos, reinterpret_cast(&val)); } break; case BOOL: { - if (!reader.skipTokenIfNull()) { - auto boolVal = reader.getBoolean(); - putValueIntoLists(propertyIdx, directionTablePropertyLists, directionTableAdjLists, - nodeIDs, reversePos, reinterpret_cast(&boolVal)); - } + bool val = TypeUtils::convertToBoolean(data); + putValueIntoLists(propertyIdx, directionTablePropertyLists, directionTableAdjLists, + nodeIDs, reversePos, reinterpret_cast(&val)); } break; case DATE: { - if (!reader.skipTokenIfNull()) { - auto dateVal = reader.getDate(); - putValueIntoLists(propertyIdx, directionTablePropertyLists, directionTableAdjLists, - nodeIDs, reversePos, reinterpret_cast(&dateVal)); - } + date_t val = Date::FromCString(data, stringToken.length()); + putValueIntoLists(propertyIdx, directionTablePropertyLists, directionTableAdjLists, + nodeIDs, reversePos, reinterpret_cast(&val)); } break; case TIMESTAMP: { - if (!reader.skipTokenIfNull()) { - auto timestampVal = reader.getTimestamp(); - putValueIntoLists(propertyIdx, directionTablePropertyLists, directionTableAdjLists, - nodeIDs, reversePos, reinterpret_cast(×tampVal)); - } + timestamp_t val = Timestamp::FromCString(data, stringToken.length()); + putValueIntoLists(propertyIdx, directionTablePropertyLists, directionTableAdjLists, + nodeIDs, reversePos, reinterpret_cast(&val)); } break; case INTERVAL: { - if (!reader.skipTokenIfNull()) { - auto intervalVal = reader.getInterval(); - putValueIntoLists(propertyIdx, directionTablePropertyLists, directionTableAdjLists, - nodeIDs, reversePos, reinterpret_cast(&intervalVal)); - } + interval_t val = Interval::FromCString(data, stringToken.length()); + putValueIntoLists(propertyIdx, directionTablePropertyLists, directionTableAdjLists, + nodeIDs, reversePos, reinterpret_cast(&val)); } break; case STRING: { - if (!reader.skipTokenIfNull()) { - auto strVal = reader.getString(); - auto kuStr = inMemOverflowFilesPerProperty[propertyIdx]->copyString( - strVal, inMemOverflowFileCursors[propertyIdx]); - putValueIntoLists(propertyIdx, directionTablePropertyLists, directionTableAdjLists, - nodeIDs, reversePos, reinterpret_cast(&kuStr)); - } + auto kuStr = inMemOverflowFilesPerProperty[propertyIdx]->copyString( + data, inMemOverflowFileCursors[propertyIdx]); + putValueIntoLists(propertyIdx, directionTablePropertyLists, directionTableAdjLists, + nodeIDs, reversePos, reinterpret_cast(&kuStr)); } break; case LIST: { - if (!reader.skipTokenIfNull()) { - auto listVal = reader.getList(*properties[propertyIdx].dataType.childType); - auto kuList = inMemOverflowFilesPerProperty[propertyIdx]->copyList( - listVal, inMemOverflowFileCursors[propertyIdx]); - putValueIntoLists(propertyIdx, directionTablePropertyLists, directionTableAdjLists, - nodeIDs, reversePos, reinterpret_cast(&kuList)); - } + Literal listVal = getArrowList(stringToken, 1, stringToken.length() - 2, + properties[propertyIdx].dataType, copyDescription); + auto kuList = inMemOverflowFilesPerProperty[propertyIdx]->copyList( + listVal, inMemOverflowFileCursors[propertyIdx]); + putValueIntoLists(propertyIdx, directionTablePropertyLists, directionTableAdjLists, + nodeIDs, reversePos, reinterpret_cast(&kuList)); } break; default: - if (!reader.skipTokenIfNull()) { - reader.skipToken(); - } + break; } + ++colIndex; } } -void InMemRelCSVCopier::initAdjListsHeaders() { +void CopyRelArrow::initAdjListsHeaders() { logger->debug("Initializing AdjListHeaders for rel {}.", relTableSchema->tableName); for (auto relDirection : REL_DIRECTIONS) { for (auto& [boundTableID, adjList] : directionTableAdjLists[relDirection]) { auto numBytesPerNode = directionNodeIDCompressionScheme[relDirection][boundTableID] .getNumBytesForNodeIDAfterCompression(); - taskScheduler.scheduleTask(CopyCSVTaskFactory::createCopyCSVTask( - calculateListHeadersTask, maxNodeOffsetsPerTable.at(boundTableID) + 1, - numBytesPerNode, directionTableListSizes[relDirection][boundTableID].get(), + taskScheduler.scheduleTask(CopyTaskFactory::createCopyTask(calculateListHeadersTask, + maxNodeOffsetsPerTable.at(boundTableID) + 1, numBytesPerNode, + directionTableListSizes[relDirection][boundTableID].get(), adjList->getListHeadersBuilder(), logger)); } } @@ -462,21 +558,21 @@ void InMemRelCSVCopier::initAdjListsHeaders() { logger->debug("Done initializing AdjListHeaders for rel {}.", relTableSchema->tableName); } -void InMemRelCSVCopier::initListsMetadata() { +void CopyRelArrow::initListsMetadata() { logger->debug( "Initializing adjLists and propertyLists metadata for rel {}.", relTableSchema->tableName); for (auto relDirection : REL_DIRECTIONS) { for (auto& [boundTableID, adjList] : directionTableAdjLists[relDirection]) { auto numNodes = maxNodeOffsetsPerTable.at(boundTableID) + 1; auto listSizes = directionTableListSizes[relDirection][boundTableID].get(); - taskScheduler.scheduleTask(CopyCSVTaskFactory::createCopyCSVTask( + taskScheduler.scheduleTask(CopyTaskFactory::createCopyTask( calculateListsMetadataAndAllocateInMemListPagesTask, numNodes, directionNodeIDCompressionScheme[relDirection][boundTableID] .getNumBytesForNodeIDAfterCompression(), listSizes, adjList->getListHeadersBuilder(), adjList.get(), false /*hasNULLBytes*/, logger)); for (auto& property : relTableSchema->properties) { - taskScheduler.scheduleTask(CopyCSVTaskFactory::createCopyCSVTask( + taskScheduler.scheduleTask(CopyTaskFactory::createCopyTask( calculateListsMetadataAndAllocateInMemListPagesTask, numNodes, Types::getDataTypeSize(property.dataType), listSizes, adjList->getListHeadersBuilder(), @@ -491,26 +587,21 @@ void InMemRelCSVCopier::initListsMetadata() { relTableSchema->tableName); } -void InMemRelCSVCopier::populateLists() { +void CopyRelArrow::populateLists() { logger->debug( "Populating adjLists and rel property lists for rel {}.", relTableSchema->tableName); - auto blockStartOffset = 0ull; - for (auto blockId = 0u; blockId < numBlocks; blockId++) { - taskScheduler.scheduleTask(CopyCSVTaskFactory::createCopyCSVTask( - populateListsTask, blockId, startRelID + blockStartOffset, this)); - blockStartOffset += numLinesPerBlock[blockId]; - } - taskScheduler.waitAllTasksToCompleteOrError(); + auto status = executePopulateTask(PopulateTaskType::populateListsTask); + throwCopyExceptionIfNotOK(status); logger->debug( "Done populating adjLists and rel property lists for rel {}.", relTableSchema->tableName); } -void InMemRelCSVCopier::populateListsTask( - uint64_t blockId, uint64_t blockStartRelID, InMemRelCSVCopier* copier) { - copier->logger->trace("Start: path=`{0}` blkIdx={1}", copier->csvDescription.filePath, blockId); - CSVReader reader( - copier->csvDescription.filePath, copier->csvDescription.csvReaderConfig, blockId); - skipFirstRowIfNecessary(blockId, copier->csvDescription, reader); +template +void CopyRelArrow::populateListsTask(uint64_t blockId, uint64_t blockStartRelID, + CopyRelArrow* copier, const vector>& batchColumns, + CopyDescription& copyDescription) { + copier->logger->trace( + "Start: path=`{0}` blkIdx={1}", copier->copyDescription.filePath, blockId); vector requireToReadTableLabels{true, true}; vector nodeIDs(2); vector nodePKTypes(2); @@ -527,10 +618,12 @@ void InMemRelCSVCopier::populateListsTask( .dataType; } vector inMemOverflowFileCursors(copier->relTableSchema->getNumProperties()); - int64_t relID = blockStartRelID; - while (reader.hasNextLine()) { - inferTableIDsAndOffsets(reader, nodeIDs, nodePKTypes, copier->pkIndexes, - copier->dummyReadOnlyTrx.get(), copier->catalog, requireToReadTableLabels); + uint64_t relID = blockStartRelID; + for (auto blockOffset = 0u; blockOffset < copier->numLinesPerBlock[blockId]; ++blockOffset) { + int64_t colIndex = 0; + inferTableIDsAndOffsets(batchColumns, nodeIDs, nodePKTypes, copier->pkIndexes, + copier->dummyReadOnlyTrx.get(), copier->catalog, requireToReadTableLabels, blockOffset, + colIndex); for (auto relDirection : REL_DIRECTIONS) { if (!copier->catalog.getReadOnlyVersion()->isSingleMultiplicityInDirection( copier->relTableSchema->tableID, relDirection)) { @@ -545,17 +638,18 @@ void InMemRelCSVCopier::populateListsTask( } } if (copier->relTableSchema->getNumUserDefinedProperties() != 0) { - putPropsOfLineIntoLists(copier, inMemOverflowFileCursors, reader, nodeIDs, reversePos); + putPropsOfLineIntoLists(copier, inMemOverflowFileCursors, batchColumns, nodeIDs, + reversePos, blockOffset, colIndex, copyDescription); } putValueIntoLists(copier->relTableSchema->getRelIDDefinition().propertyID, copier->directionTablePropertyLists, copier->directionTableAdjLists, nodeIDs, reversePos, (uint8_t*)&relID); relID++; } - copier->logger->trace("End: path=`{0}` blkIdx={1}", copier->csvDescription.filePath, blockId); + copier->logger->trace("End: path=`{0}` blkIdx={1}", copier->copyDescription.filePath, blockId); } -void InMemRelCSVCopier::copyStringOverflowFromUnorderedToOrderedPages(ku_string_t* kuStr, +void CopyRelArrow::copyStringOverflowFromUnorderedToOrderedPages(ku_string_t* kuStr, PageByteCursor& unorderedOverflowCursor, PageByteCursor& orderedOverflowCursor, InMemOverflowFile* unorderedOverflowFile, InMemOverflowFile* orderedOverflowFile) { if (kuStr->len > ku_string_t::SHORT_STR_LENGTH) { @@ -568,7 +662,7 @@ void InMemRelCSVCopier::copyStringOverflowFromUnorderedToOrderedPages(ku_string_ } } -void InMemRelCSVCopier::copyListOverflowFromUnorderedToOrderedPages(ku_list_t* kuList, +void CopyRelArrow::copyListOverflowFromUnorderedToOrderedPages(ku_list_t* kuList, const DataType& dataType, PageByteCursor& unorderedOverflowCursor, PageByteCursor& orderedOverflowCursor, InMemOverflowFile* unorderedOverflowFile, InMemOverflowFile* orderedOverflowFile) { @@ -578,7 +672,7 @@ void InMemRelCSVCopier::copyListOverflowFromUnorderedToOrderedPages(ku_list_t* k orderedOverflowCursor, kuList, dataType.childType.get()); } -void InMemRelCSVCopier::sortOverflowValuesOfPropertyColumnTask(const DataType& dataType, +void CopyRelArrow::sortOverflowValuesOfPropertyColumnTask(const DataType& dataType, node_offset_t offsetStart, node_offset_t offsetEnd, InMemColumn* propertyColumn, InMemOverflowFile* unorderedInMemOverflowFile, InMemOverflowFile* orderedInMemOverflowFile) { PageByteCursor unorderedOverflowCursor, orderedOverflowCursor; @@ -597,7 +691,7 @@ void InMemRelCSVCopier::sortOverflowValuesOfPropertyColumnTask(const DataType& d } } -void InMemRelCSVCopier::sortOverflowValuesOfPropertyListsTask(const DataType& dataType, +void CopyRelArrow::sortOverflowValuesOfPropertyListsTask(const DataType& dataType, node_offset_t offsetStart, node_offset_t offsetEnd, InMemAdjLists* adjLists, InMemLists* propertyLists, InMemOverflowFile* unorderedInMemOverflowFile, InMemOverflowFile* orderedInMemOverflowFile) { @@ -632,7 +726,7 @@ void InMemRelCSVCopier::sortOverflowValuesOfPropertyListsTask(const DataType& da } } -void InMemRelCSVCopier::sortAndCopyOverflowValues() { +void CopyRelArrow::sortAndCopyOverflowValues() { for (auto relDirection : REL_DIRECTIONS) { // Sort overflow values of property Lists. for (auto& [tableID, adjList] : directionTableAdjLists[relDirection]) { @@ -648,7 +742,7 @@ void InMemRelCSVCopier::sortAndCopyOverflowValues() { auto propertyList = directionTablePropertyLists[relDirection] .at(tableID)[property.propertyID] .get(); - taskScheduler.scheduleTask(CopyCSVTaskFactory::createCopyCSVTask( + taskScheduler.scheduleTask(CopyTaskFactory::createCopyTask( sortOverflowValuesOfPropertyListsTask, property.dataType, offsetStart, offsetEnd, adjList.get(), propertyList, overflowFilePerPropertyID.at(property.propertyID).get(), @@ -674,11 +768,11 @@ void InMemRelCSVCopier::sortAndCopyOverflowValues() { auto propertyColumn = directionTablePropertyColumns[relDirection] .at(tableID)[property.propertyID] .get(); - taskScheduler.scheduleTask(CopyCSVTaskFactory::createCopyCSVTask( - sortOverflowValuesOfPropertyColumnTask, property.dataType, offsetStart, - offsetEnd, propertyColumn, - overflowFilePerPropertyID.at(property.propertyID).get(), - propertyColumn->getInMemOverflowFile())); + taskScheduler.scheduleTask( + CopyTaskFactory::createCopyTask(sortOverflowValuesOfPropertyColumnTask, + property.dataType, offsetStart, offsetEnd, propertyColumn, + overflowFilePerPropertyID.at(property.propertyID).get(), + propertyColumn->getInMemOverflowFile())); } taskScheduler.waitAllTasksToCompleteOrError(); } @@ -688,7 +782,7 @@ void InMemRelCSVCopier::sortAndCopyOverflowValues() { overflowFilePerPropertyID.clear(); } -void InMemRelCSVCopier::saveToFile() { +void CopyRelArrow::saveToFile() { logger->debug("Writing columns and Lists to disk for rel {}.", relTableSchema->tableName); for (auto relDirection : REL_DIRECTIONS) { // Write columns @@ -696,21 +790,33 @@ void InMemRelCSVCopier::saveToFile() { adjColumn->saveToFile(); } for (auto& [_, propertyColumns] : directionTablePropertyColumns[relDirection]) { - for (auto& property : relTableSchema->properties) { - propertyColumns[property.propertyID]->saveToFile(); + for (auto propertyIdx = 0u; propertyIdx < relTableSchema->getNumProperties(); + propertyIdx++) { + propertyColumns[propertyIdx]->saveToFile(); } } for (auto& [_, adjList] : directionTableAdjLists[relDirection]) { adjList->saveToFile(); } for (auto& [_, propertyLists] : directionTablePropertyLists[relDirection]) { - for (auto& property : relTableSchema->properties) { - propertyLists[property.propertyID]->saveToFile(); + for (auto propertyIdx = 0u; propertyIdx < relTableSchema->getNumProperties(); + propertyIdx++) { + propertyLists[propertyIdx]->saveToFile(); } } } logger->debug("Done writing columns and lists to disk for rel {}.", relTableSchema->tableName); } +std::string CopyRelArrow::getTaskTypeName(PopulateTaskType populateTaskType) { + switch (populateTaskType) { + case PopulateTaskType::populateAdjColumnsAndCountRelsInAdjListsTask: + return "populateAdjColumnsAndCountRelsInAdjListsTask"; + + case PopulateTaskType::populateListsTask: + return "populateListsTask"; + } +} + } // namespace storage } // namespace kuzu diff --git a/src/storage/copy_arrow/copy_structures_arrow.cpp b/src/storage/copy_arrow/copy_structures_arrow.cpp new file mode 100644 index 0000000000..dea3574f2a --- /dev/null +++ b/src/storage/copy_arrow/copy_structures_arrow.cpp @@ -0,0 +1,302 @@ +#include "storage/copy_arrow/copy_structures_arrow.h" + +#include "common/configs.h" +#include "storage/storage_structure/lists/lists.h" + +namespace kuzu { +namespace storage { + +CopyStructuresArrow::CopyStructuresArrow(CopyDescription& copyDescription, string outputDirectory, + TaskScheduler& taskScheduler, Catalog& catalog) + : logger{LoggerUtils::getOrCreateLogger("loader")}, copyDescription{copyDescription}, + outputDirectory{std::move(outputDirectory)}, numBlocks{0}, + taskScheduler{taskScheduler}, catalog{catalog}, numRows{0} {} + +// Lists headers are created for only AdjLists, which store data in the page without NULL bits. +void CopyStructuresArrow::calculateListHeadersTask(node_offset_t numNodes, uint32_t elementSize, + atomic_uint64_vec_t* listSizes, ListHeadersBuilder* listHeadersBuilder, + const shared_ptr& logger) { + logger->trace("Start: ListHeadersBuilder={0:p}", (void*)listHeadersBuilder); + auto numElementsPerPage = PageUtils::getNumElementsInAPage(elementSize, false /* hasNull */); + auto numChunks = StorageUtils::getNumChunks(numNodes); + node_offset_t nodeOffset = 0u; + uint64_t lAdjListsIdx = 0u; + for (auto chunkId = 0u; chunkId < numChunks; chunkId++) { + auto csrOffset = 0u; + auto lastNodeOffsetInChunk = + min(nodeOffset + ListsMetadataConfig::LISTS_CHUNK_SIZE, numNodes); + for (auto i = nodeOffset; i < lastNodeOffsetInChunk; i++) { + auto numElementsInList = (*listSizes)[nodeOffset].load(memory_order_relaxed); + uint32_t header; + if (numElementsInList >= numElementsPerPage) { + header = ListHeaders::getLargeListHeader(lAdjListsIdx++); + } else { + header = ListHeaders::getSmallListHeader(csrOffset, numElementsInList); + csrOffset += numElementsInList; + } + listHeadersBuilder->setHeader(nodeOffset, header); + nodeOffset++; + } + } + logger->trace("End: adjListHeadersBuilder={0:p}", (void*)listHeadersBuilder); +} + +void CopyStructuresArrow::calculateListsMetadataAndAllocateInMemListPagesTask(uint64_t numNodes, + uint32_t elementSize, atomic_uint64_vec_t* listSizes, ListHeadersBuilder* listHeadersBuilder, + InMemLists* inMemList, bool hasNULLBytes, const shared_ptr& logger) { + logger->trace("Start: listsMetadataBuilder={0:p} adjListHeadersBuilder={1:p}", + (void*)inMemList->getListsMetadataBuilder(), (void*)listHeadersBuilder); + auto numChunks = StorageUtils::getNumChunks(numNodes); + node_offset_t nodeOffset = 0u; + auto largeListIdx = 0u; + for (auto chunkId = 0u; chunkId < numChunks; chunkId++) { + auto lastNodeOffsetInChunk = + min(nodeOffset + ListsMetadataConfig::LISTS_CHUNK_SIZE, numNodes); + for (auto i = nodeOffset; i < lastNodeOffsetInChunk; i++) { + if (ListHeaders::isALargeList(listHeadersBuilder->getHeader(nodeOffset))) { + largeListIdx++; + } + nodeOffset++; + } + } + inMemList->getListsMetadataBuilder()->initLargeListPageLists(largeListIdx); + nodeOffset = 0u; + largeListIdx = 0u; + auto numPerPage = PageUtils::getNumElementsInAPage(elementSize, hasNULLBytes); + for (auto chunkId = 0u; chunkId < numChunks; chunkId++) { + auto numPages = 0u, offsetInPage = 0u; + auto lastNodeOffsetInChunk = + min(nodeOffset + ListsMetadataConfig::LISTS_CHUNK_SIZE, numNodes); + while (nodeOffset < lastNodeOffsetInChunk) { + auto numElementsInList = (*listSizes)[nodeOffset].load(memory_order_relaxed); + if (ListHeaders::isALargeList(listHeadersBuilder->getHeader(nodeOffset))) { + auto numPagesForLargeList = numElementsInList / numPerPage; + if (0 != numElementsInList % numPerPage) { + numPagesForLargeList++; + } + inMemList->getListsMetadataBuilder()->populateLargeListPageList(largeListIdx, + numPagesForLargeList, numElementsInList, + inMemList->inMemFile->getNumPages() /* start idx of pages in .lists file */); + inMemList->inMemFile->addNewPages(numPagesForLargeList); + largeListIdx++; + } else { + while (numElementsInList + offsetInPage > numPerPage) { + numElementsInList -= (numPerPage - offsetInPage); + numPages++; + offsetInPage = 0; + } + offsetInPage += numElementsInList; + } + nodeOffset++; + } + if (0 != offsetInPage) { + numPages++; + } + inMemList->getListsMetadataBuilder()->populateChunkPageList(chunkId, numPages, + inMemList->inMemFile->getNumPages() /* start idx of pages in .lists file */); + inMemList->inMemFile->addNewPages(numPages); + } + logger->trace("End: listsMetadata={0:p} listHeadersBuilder={1:p}", + (void*)inMemList->getListsMetadataBuilder(), (void*)listHeadersBuilder); +} + +void CopyStructuresArrow::countNumLines(const std::string& filePath) { + arrow::Status status; + switch (copyDescription.fileType) { + case CopyDescription::FileType::CSV: + status = countNumLinesCSV(filePath); + break; + + case CopyDescription::FileType::ARROW: + status = countNumLinesArrow(filePath); + break; + + case CopyDescription::FileType::PARQUET: + status = countNumLinesParquet(filePath); + break; + } + throwCopyExceptionIfNotOK(status); +} + +arrow::Status CopyStructuresArrow::countNumLinesCSV(const std::string& filePath) { + shared_ptr csv_streaming_reader; + auto status = initCSVReader(csv_streaming_reader, filePath); + + numRows = 0; + numBlocks = 0; + std::shared_ptr currBatch; + + auto endIt = csv_streaming_reader->end(); + for (auto it = csv_streaming_reader->begin(); it != endIt; ++it) { + ARROW_ASSIGN_OR_RAISE(currBatch, *it); + ++numBlocks; + auto currNumRows = currBatch->num_rows(); + numLinesPerBlock.push_back(currNumRows); + numRows += currNumRows; + } + return status; +} + +arrow::Status CopyStructuresArrow::countNumLinesArrow(const std::string& filePath) { + std::shared_ptr ipc_reader; + auto status = initArrowReader(ipc_reader, filePath); + + numRows = 0; + numBlocks = ipc_reader->num_record_batches(); + numLinesPerBlock.resize(numBlocks); + std::shared_ptr rbatch; + + for (uint64_t blockId = 0; blockId < numBlocks; ++blockId) { + ARROW_ASSIGN_OR_RAISE(rbatch, ipc_reader->ReadRecordBatch(blockId)); + numLinesPerBlock[blockId] = rbatch->num_rows(); + numRows += rbatch->num_rows(); + } + return status; +} + +arrow::Status CopyStructuresArrow::countNumLinesParquet(const std::string& filePath) { + std::unique_ptr reader; + auto status = initParquetReader(reader, filePath); + + numRows = 0; + numBlocks = reader->num_row_groups(); + numLinesPerBlock.resize(numBlocks); + std::shared_ptr table; + + for (uint64_t blockId = 0; blockId < numBlocks; ++blockId) { + ARROW_RETURN_NOT_OK(reader->RowGroup(blockId)->ReadTable(&table)); + numLinesPerBlock[blockId] = table->num_rows(); + numRows += table->num_rows(); + } + return status; +} + +arrow::Status CopyStructuresArrow::initCSVReader( + shared_ptr& csv_streaming_reader, const std::string& filePath) { + shared_ptr arrow_input_stream; + ARROW_ASSIGN_OR_RAISE(arrow_input_stream, arrow::io::ReadableFile::Open(filePath)); + auto arrowRead = arrow::csv::ReadOptions::Defaults(); + arrowRead.block_size = CopyConfig::CSV_READING_BLOCK_SIZE; + + if (!copyDescription.csvReaderConfig->hasHeader) { + arrowRead.autogenerate_column_names = true; + } + + auto arrowConvert = arrow::csv::ConvertOptions::Defaults(); + arrowConvert.strings_can_be_null = true; + arrowConvert.quoted_strings_can_be_null = false; + + auto arrowParse = arrow::csv::ParseOptions::Defaults(); + arrowParse.delimiter = copyDescription.csvReaderConfig->delimiter; + arrowParse.escape_char = copyDescription.csvReaderConfig->escapeChar; + arrowParse.quote_char = copyDescription.csvReaderConfig->quoteChar; + arrowParse.escaping = true; + + ARROW_ASSIGN_OR_RAISE( + csv_streaming_reader, arrow::csv::StreamingReader::Make(arrow::io::default_io_context(), + arrow_input_stream, arrowRead, arrowParse, arrowConvert)); + return arrow::Status::OK(); +} + +arrow::Status CopyStructuresArrow::initArrowReader( + std::shared_ptr& ipc_reader, const std::string& filePath) { + std::shared_ptr infile; + + ARROW_ASSIGN_OR_RAISE( + infile, arrow::io::ReadableFile::Open(filePath, arrow::default_memory_pool())); + + ARROW_ASSIGN_OR_RAISE(ipc_reader, arrow::ipc::RecordBatchFileReader::Open(infile)); + return arrow::Status::OK(); +} + +arrow::Status CopyStructuresArrow::initParquetReader( + std::unique_ptr& reader, const std::string& filePath) { + std::shared_ptr infile; + ARROW_ASSIGN_OR_RAISE( + infile, arrow::io::ReadableFile::Open(filePath, arrow::default_memory_pool())); + + ARROW_RETURN_NOT_OK(parquet::arrow::OpenFile(infile, arrow::default_memory_pool(), &reader)); + return arrow::Status::OK(); +} + +Literal CopyStructuresArrow::getArrowList(string& l, int64_t from, int64_t to, + const DataType& dataType, CopyDescription& copyDescription) { + auto childDataType = *dataType.childType; + Literal result(DataType(LIST, make_unique(childDataType))); + + char delimiter = copyDescription.csvReaderConfig->delimiter; + vector> split; + int bracket = 0; + int64_t last = from; + if (dataType.typeID == LIST) { + for (int64_t i = from; i <= to; i++) { + if (l[i] == copyDescription.csvReaderConfig->listBeginChar) { + bracket += 1; + } else if (l[i] == copyDescription.csvReaderConfig->listEndChar) { + bracket -= 1; + } else if (bracket == 0 && l[i] == delimiter) { + split.emplace_back(last, i - last); + last = i + 1; + } + } + } + split.emplace_back(last, to - last + 1); + + for (auto pair : split) { + string element = l.substr(pair.first, pair.second); + if (element.empty()) { + continue; + } + switch (childDataType.typeID) { + case INT64: { + result.listVal.emplace_back((int64_t)stoll(element)); + } break; + case DOUBLE: { + result.listVal.emplace_back(stod(element)); + } break; + case BOOL: { + transform(element.begin(), element.end(), element.begin(), ::tolower); + std::istringstream is(element); + bool b; + is >> std::boolalpha >> b; + result.listVal.emplace_back(b); + } break; + case STRING: { + result.listVal.emplace_back(element); + } break; + case DATE: { + result.listVal.emplace_back(Date::FromCString(element.c_str(), element.length())); + } break; + case TIMESTAMP: { + result.listVal.emplace_back(Timestamp::FromCString(element.c_str(), element.length())); + } break; + case INTERVAL: { + result.listVal.emplace_back(Interval::FromCString(element.c_str(), element.length())); + } break; + case LIST: { + result.listVal.emplace_back(getArrowList(l, pair.first + 1, + pair.second + pair.first - 1, *dataType.childType, copyDescription)); + } break; + default: + throw ReaderException("Unsupported data type " + + Types::dataTypeToString(dataType.childType->typeID) + + " inside LIST"); + } + } + auto numBytesOfOverflow = result.listVal.size() * Types::getDataTypeSize(dataType.typeID); + if (numBytesOfOverflow >= DEFAULT_PAGE_SIZE) { + throw ReaderException(StringUtils::string_format( + "Maximum num bytes of a LIST is %d. Input list's num bytes is %d.", DEFAULT_PAGE_SIZE, + numBytesOfOverflow)); + } + return result; +} + +void CopyStructuresArrow::throwCopyExceptionIfNotOK(const arrow::Status& status) { + if (!status.ok()) { + throw CopyException(status.ToString()); + } +} + +} // namespace storage +} // namespace kuzu diff --git a/src/storage/in_mem_csv_copier/in_mem_arrow_node_copier.cpp b/src/storage/in_mem_csv_copier/in_mem_arrow_node_copier.cpp deleted file mode 100644 index 6b9f72cf76..0000000000 --- a/src/storage/in_mem_csv_copier/in_mem_arrow_node_copier.cpp +++ /dev/null @@ -1,556 +0,0 @@ -#include "storage/in_mem_csv_copier/in_mem_arrow_node_copier.h" - -#include "storage/in_mem_csv_copier/copy_csv_task.h" -#include "storage/storage_structure/in_mem_file.h" - -namespace kuzu { -namespace storage { - -InMemArrowNodeCopier::InMemArrowNodeCopier(CSVDescription& csvDescription, string outputDirectory, - TaskScheduler& taskScheduler, Catalog& catalog, table_id_t tableID, - NodesStatisticsAndDeletedIDs* nodesStatisticsAndDeletedIDs) - : InMemStructuresCopier{csvDescription, std::move(outputDirectory), taskScheduler, catalog}, - numNodes{UINT64_MAX}, nodesStatisticsAndDeletedIDs{nodesStatisticsAndDeletedIDs} { - nodeTableSchema = catalog.getReadOnlyVersion()->getNodeTableSchema(tableID); - - // TODO: refactor this when implementing reading rel files. - setFileType(csvDescription.filePath); -} - -uint64_t InMemArrowNodeCopier::copy() { - auto read_start = std::chrono::high_resolution_clock::now(); - logger->info("Reading " + getFileTypeName(inputFileType) + " file."); - - countNumLines(csvDescription.filePath); - initializeColumnsAndList(); - - arrow::Status status; - - switch (nodeTableSchema->getPrimaryKey().dataType.typeID) { - case INT64: { - status = populateColumns(); - } break; - case STRING: { - status = populateColumns(); - } break; - default: { - throw CopyCSVException("Unsupported data type " + - Types::dataTypeToString(nodeTableSchema->getPrimaryKey().dataType) + - " for the ID index."); - } - } - - if (!status.ok()) { - throw CopyCSVException(status.ToString()); - } - - auto read_end = std::chrono::high_resolution_clock::now(); - auto write_start = std::chrono::high_resolution_clock::now(); - - saveToFile(); - nodesStatisticsAndDeletedIDs->setNumTuplesForTable(nodeTableSchema->tableID, numNodes); - logger->info("Done copying node {} with table {}.", nodeTableSchema->tableName, - nodeTableSchema->tableID); - - auto write_end = std::chrono::high_resolution_clock::now(); - auto read_time = std::chrono::duration_cast(read_end - read_start); - auto write_time = - std::chrono::duration_cast(write_end - write_start); - auto total_time = std::chrono::duration_cast(write_end - read_start); - logger->debug("read time: {}.", read_time.count()); - logger->debug("write time: {}.", write_time.count()); - logger->debug("total time: {}.", total_time.count()); - return numNodes; -} - -arrow::Status InMemArrowNodeCopier::initCSVReader( - shared_ptr& csv_streaming_reader, const std::string& filePath) { - shared_ptr arrow_input_stream; - ARROW_ASSIGN_OR_RAISE(arrow_input_stream, arrow::io::ReadableFile::Open(filePath)); - auto arrowRead = arrow::csv::ReadOptions::Defaults(); - - // TODO: Refactor this once implement reading rel files. - if (!csvDescription.csvReaderConfig.hasHeader) { - arrowRead.autogenerate_column_names = true; - } - - auto arrowConvert = arrow::csv::ConvertOptions::Defaults(); - arrowConvert.strings_can_be_null = true; - arrowConvert.quoted_strings_can_be_null = false; - - auto arrowParse = arrow::csv::ParseOptions::Defaults(); - arrowParse.delimiter = csvDescription.csvReaderConfig.tokenSeparator; - arrowParse.escape_char = csvDescription.csvReaderConfig.escapeChar; - arrowParse.quote_char = csvDescription.csvReaderConfig.quoteChar; - arrowParse.escaping = true; - - ARROW_ASSIGN_OR_RAISE( - csv_streaming_reader, arrow::csv::StreamingReader::Make(arrow::io::default_io_context(), - arrow_input_stream, arrowRead, arrowParse, arrowConvert)); - return arrow::Status::OK(); -} - -arrow::Status InMemArrowNodeCopier::initArrowReader( - std::shared_ptr& ipc_reader, const std::string& filePath) { - std::shared_ptr infile; - - ARROW_ASSIGN_OR_RAISE( - infile, arrow::io::ReadableFile::Open(filePath, arrow::default_memory_pool())); - - ARROW_ASSIGN_OR_RAISE(ipc_reader, arrow::ipc::RecordBatchFileReader::Open(infile)); - return arrow::Status::OK(); -} - -arrow::Status InMemArrowNodeCopier::initParquetReader( - std::unique_ptr& reader, const std::string& filePath) { - std::shared_ptr infile; - ARROW_ASSIGN_OR_RAISE( - infile, arrow::io::ReadableFile::Open(filePath, arrow::default_memory_pool())); - ARROW_RETURN_NOT_OK(parquet::arrow::OpenFile(infile, arrow::default_memory_pool(), &reader)); - return arrow::Status::OK(); -} - -void InMemArrowNodeCopier::countNumLines(const std::string& filePath) { - arrow::Status status; - switch (inputFileType) { - case FileTypes::CSV: - status = countNumLinesCSV(filePath); - break; - case FileTypes::ARROW: - status = countNumLinesArrow(filePath); - break; - case FileTypes::PARQUET: - status = countNumLinesParquet(filePath); - break; - } - if (!status.ok()) { - throw CopyCSVException(status.ToString()); - } -} - -arrow::Status InMemArrowNodeCopier::countNumLinesCSV(const std::string& filePath) { - shared_ptr csv_streaming_reader; - auto status = initCSVReader(csv_streaming_reader, filePath); - - numNodes = 0; - numBlocks = 0; - std::shared_ptr currBatch; - - auto endIt = csv_streaming_reader->end(); - for (auto it = csv_streaming_reader->begin(); it != endIt; ++it) { - ARROW_ASSIGN_OR_RAISE(currBatch, *it); - ++numBlocks; - auto currNumRows = currBatch->num_rows(); - numLinesPerBlock.push_back(currNumRows); - numNodes += currNumRows; - } - return status; -} - -arrow::Status InMemArrowNodeCopier::countNumLinesArrow(const std::string& filePath) { - std::shared_ptr ipc_reader; - auto status = initArrowReader(ipc_reader, filePath); - - numNodes = 0; - numBlocks = ipc_reader->num_record_batches(); - numLinesPerBlock.resize(numBlocks); - std::shared_ptr rbatch; - - for (uint64_t blockId = 0; blockId < numBlocks; ++blockId) { - ARROW_ASSIGN_OR_RAISE(rbatch, ipc_reader->ReadRecordBatch(blockId)); - numLinesPerBlock[blockId] = rbatch->num_rows(); - numNodes += rbatch->num_rows(); - } - return status; -} - -arrow::Status InMemArrowNodeCopier::countNumLinesParquet(const std::string& filePath) { - std::unique_ptr reader; - auto status = initParquetReader(reader, filePath); - - numNodes = 0; - numBlocks = reader->num_row_groups(); - numLinesPerBlock.resize(numBlocks); - std::shared_ptr table; - - for (uint64_t blockId = 0; blockId < numBlocks; ++blockId) { - ARROW_RETURN_NOT_OK(reader->RowGroup(blockId)->ReadTable(&table)); - numLinesPerBlock[blockId] = table->num_rows(); - numNodes += table->num_rows(); - } - return status; -} - -void InMemArrowNodeCopier::setFileType(std::string const& fileName) { - auto csvSuffix = getFileTypeSuffix(FileTypes::CSV); - auto arrowSuffix = getFileTypeSuffix(FileTypes::ARROW); - auto parquetSuffix = getFileTypeSuffix(FileTypes::PARQUET); - - if (fileName.length() >= csvSuffix.length()) { - if (!fileName.compare( - fileName.length() - csvSuffix.length(), csvSuffix.length(), csvSuffix)) { - inputFileType = FileTypes::CSV; - return; - } - } - - if (fileName.length() >= arrowSuffix.length()) { - if (!fileName.compare( - fileName.length() - arrowSuffix.length(), arrowSuffix.length(), arrowSuffix)) { - inputFileType = FileTypes::ARROW; - return; - } - } - - if (fileName.length() >= parquetSuffix.length()) { - if (!fileName.compare(fileName.length() - parquetSuffix.length(), parquetSuffix.length(), - parquetSuffix)) { - inputFileType = FileTypes::PARQUET; - return; - } - } - throw CopyCSVException("Unsupported file type: " + fileName); -} - -void InMemArrowNodeCopier::initializeColumnsAndList() { - logger->info("Initializing in memory columns."); - columns.resize(nodeTableSchema->getNumProperties()); - for (auto& property : nodeTableSchema->properties) { - auto fName = StorageUtils::getNodePropertyColumnFName(outputDirectory, - nodeTableSchema->tableID, property.propertyID, DBFileType::WAL_VERSION); - columns[property.propertyID] = - InMemColumnFactory::getInMemPropertyColumn(fName, property.dataType, numNodes); - } - logger->info("Done initializing in memory columns."); -} - -template -arrow::Status InMemArrowNodeCopier::populateColumns() { - logger->info("Populating properties"); - auto pkIndex = - make_unique>(StorageUtils::getNodeIndexFName(this->outputDirectory, - nodeTableSchema->tableID, DBFileType::WAL_VERSION), - nodeTableSchema->getPrimaryKey().dataType); - pkIndex->bulkReserve(numNodes); - - arrow::Status status; - switch (inputFileType) { - case FileTypes::CSV: - status = populateColumnsFromCSV(pkIndex); - break; - case FileTypes::ARROW: - status = populateColumnsFromArrow(pkIndex); - break; - case FileTypes::PARQUET: - status = populateColumnsFromParquet(pkIndex); - break; - } - - logger->info("Flush the pk index to disk."); - pkIndex->flush(); - logger->info("Done populating properties, constructing the pk index."); - return status; -} - -template -arrow::Status InMemArrowNodeCopier::populateColumnsFromCSV( - unique_ptr>& pkIndex) { - node_offset_t offsetStart = 0; - - shared_ptr csv_streaming_reader; - auto status = initCSVReader(csv_streaming_reader, csvDescription.filePath); - if (!status.ok()) { - return status; - } - - std::shared_ptr currBatch; - - int blockIdx = 0; - auto it = csv_streaming_reader->begin(); - auto endIt = csv_streaming_reader->end(); - while (it != endIt) { - for (int i = 0; i < CopyCSVConfig::NUM_COPIER_TASKS_TO_SCHEDULE_PER_BATCH; ++i) { - if (it == endIt) { - break; - } - ARROW_ASSIGN_OR_RAISE(currBatch, *it); - taskScheduler.scheduleTask( - CopyCSVTaskFactory::createCopyCSVTask(batchPopulateColumnsTask, - nodeTableSchema->primaryKeyPropertyID, blockIdx, offsetStart, pkIndex.get(), - this, currBatch->columns(), csvDescription.csvReaderConfig.tokenSeparator)); - offsetStart += currBatch->num_rows(); - ++blockIdx; - ++it; - } - taskScheduler.waitUntilEnoughTasksFinish( - CopyCSVConfig::MINIMUM_NUM_COPIER_TASKS_TO_SCHEDULE_MORE); - } - taskScheduler.waitAllTasksToCompleteOrError(); - return arrow::Status::OK(); -} - -template -arrow::Status InMemArrowNodeCopier::populateColumnsFromArrow( - unique_ptr>& pkIndex) { - node_offset_t offsetStart = 0; - - std::shared_ptr ipc_reader; - auto status = initArrowReader(ipc_reader, csvDescription.filePath); - if (!status.ok()) { - return status; - } - - std::shared_ptr currBatch; - - int blockIdx = 0; - while (blockIdx < numBlocks) { - for (int i = 0; i < CopyCSVConfig::NUM_COPIER_TASKS_TO_SCHEDULE_PER_BATCH; ++i) { - if (blockIdx == numBlocks) { - break; - } - ARROW_ASSIGN_OR_RAISE(currBatch, ipc_reader->ReadRecordBatch(blockIdx)); - taskScheduler.scheduleTask( - CopyCSVTaskFactory::createCopyCSVTask(batchPopulateColumnsTask, - nodeTableSchema->primaryKeyPropertyID, blockIdx, offsetStart, pkIndex.get(), - this, currBatch->columns(), csvDescription.csvReaderConfig.tokenSeparator)); - offsetStart += currBatch->num_rows(); - ++blockIdx; - } - taskScheduler.waitUntilEnoughTasksFinish( - CopyCSVConfig::MINIMUM_NUM_COPIER_TASKS_TO_SCHEDULE_MORE); - } - - taskScheduler.waitAllTasksToCompleteOrError(); - return arrow::Status::OK(); -} - -template -arrow::Status InMemArrowNodeCopier::populateColumnsFromParquet( - unique_ptr>& pkIndex) { - node_offset_t offsetStart = 0; - - std::unique_ptr reader; - auto status = initParquetReader(reader, csvDescription.filePath); - if (!status.ok()) { - return status; - } - - std::shared_ptr currTable; - int blockIdx = 0; - while (blockIdx < numBlocks) { - for (int i = 0; i < CopyCSVConfig::NUM_COPIER_TASKS_TO_SCHEDULE_PER_BATCH; ++i) { - if (blockIdx == numBlocks) { - break; - } - ARROW_RETURN_NOT_OK(reader->RowGroup(blockIdx)->ReadTable(&currTable)); - taskScheduler.scheduleTask(CopyCSVTaskFactory::createCopyCSVTask( - batchPopulateColumnsTask, - nodeTableSchema->primaryKeyPropertyID, blockIdx, offsetStart, pkIndex.get(), this, - currTable->columns(), csvDescription.csvReaderConfig.tokenSeparator)); - offsetStart += currTable->num_rows(); - ++blockIdx; - } - taskScheduler.waitUntilEnoughTasksFinish( - CopyCSVConfig::MINIMUM_NUM_COPIER_TASKS_TO_SCHEDULE_MORE); - } - - taskScheduler.waitAllTasksToCompleteOrError(); - return arrow::Status::OK(); -} - -template -void InMemArrowNodeCopier::populatePKIndex(InMemColumn* column, HashIndexBuilder* pkIndex, - node_offset_t startOffset, uint64_t numValues) { - for (auto i = 0u; i < numValues; i++) { - auto offset = i + startOffset; - if constexpr (is_same::value) { - auto key = (int64_t*)column->getElement(offset); - if (!pkIndex->append(*key, offset)) { - throw CopyCSVException(Exception::getExistedPKExceptionMsg(to_string(*key))); - } - } else { - auto element = (ku_string_t*)column->getElement(offset); - auto key = column->getInMemOverflowFile()->readString(element); - if (!pkIndex->append(key.c_str(), offset)) { - throw CopyCSVException(Exception::getExistedPKExceptionMsg(key)); - } - } - } -} - -template -arrow::Status InMemArrowNodeCopier::batchPopulateColumnsTask(uint64_t primaryKeyPropertyId, - uint64_t blockId, uint64_t offsetStart, HashIndexBuilder* pkIndex, - InMemArrowNodeCopier* copier, const vector>& batchColumns, char delimiter) { - copier->logger->trace("Start: path={0} blkIdx={1}", copier->csvDescription.filePath, blockId); - vector overflowCursors(copier->nodeTableSchema->getNumProperties()); - for (auto blockOffset = 0u; blockOffset < copier->numLinesPerBlock[blockId]; ++blockOffset) { - putPropsOfLineIntoColumns(copier->columns, overflowCursors, batchColumns, - offsetStart + blockOffset, blockOffset, delimiter); - } - populatePKIndex(copier->columns[primaryKeyPropertyId].get(), pkIndex, offsetStart, - copier->numLinesPerBlock[blockId]); - copier->logger->trace("End: path={0} blkIdx={1}", copier->csvDescription.filePath, blockId); - return arrow::Status::OK(); -} - -template -void InMemArrowNodeCopier::putPropsOfLineIntoColumns(vector>& columns, - vector& overflowCursors, const std::vector>& arrow_columns, - uint64_t nodeOffset, uint64_t blockOffset, char delimiter) { - for (auto columnIdx = 0u; columnIdx < columns.size(); columnIdx++) { - auto column = columns[columnIdx].get(); - auto currentToken = arrow_columns[columnIdx]->GetScalar(blockOffset); - if ((*currentToken)->is_valid) { - auto stringToken = currentToken->get()->ToString(); - const char* data = stringToken.c_str(); - - switch (column->getDataType().typeID) { - case INT64: { - int64_t val = TypeUtils::convertToInt64(data); - column->setElement(nodeOffset, reinterpret_cast(&val)); - } break; - case DOUBLE: { - double_t val = TypeUtils::convertToDouble(data); - column->setElement(nodeOffset, reinterpret_cast(&val)); - } break; - case BOOL: { - bool val = TypeUtils::convertToBoolean(data); - column->setElement(nodeOffset, reinterpret_cast(&val)); - } break; - case DATE: { - date_t val = Date::FromCString(data, stringToken.length()); - column->setElement(nodeOffset, reinterpret_cast(&val)); - } break; - case TIMESTAMP: { - timestamp_t val = Timestamp::FromCString(data, stringToken.length()); - column->setElement(nodeOffset, reinterpret_cast(&val)); - } break; - case INTERVAL: { - interval_t val = Interval::FromCString(data, stringToken.length()); - column->setElement(nodeOffset, reinterpret_cast(&val)); - } break; - case STRING: { - // TODO: Refactor this once implement reading rel files. - stringToken = stringToken.substr(0, DEFAULT_PAGE_SIZE); - data = stringToken.c_str(); - - auto val = - column->getInMemOverflowFile()->copyString(data, overflowCursors[columnIdx]); - - column->setElement(nodeOffset, reinterpret_cast(&val)); - } break; - case LIST: { - Literal listVal = getArrowList( - stringToken, 1, stringToken.length() - 2, column->getDataType(), delimiter); - auto kuList = - column->getInMemOverflowFile()->copyList(listVal, overflowCursors[columnIdx]); - column->setElement(nodeOffset, reinterpret_cast(&kuList)); - } break; - default: - break; - } - } - } -} - -Literal InMemArrowNodeCopier::getArrowList( - string& l, int64_t from, int64_t to, const DataType& dataType, char delimiter) { - auto childDataType = *dataType.childType; - Literal result(DataType(LIST, make_unique(childDataType))); - - vector> split; - int bracket = 0; - int64_t last = from; - if (dataType.typeID == LIST) { - for (int64_t i = from; i <= to; i++) { - if (l[i] == '[') { - bracket += 1; - } else if (l[i] == ']') { - bracket -= 1; - } else if (bracket == 0 && l[i] == delimiter) { - split.emplace_back(last, i - last); - last = i + 1; - } - } - } - split.emplace_back(last, to - last + 1); - - for (auto pair : split) { - string element = l.substr(pair.first, pair.second); - if (element.empty()) { - continue; - } - switch (childDataType.typeID) { - case INT64: { - result.listVal.emplace_back((int64_t)stoll(element)); - } break; - case DOUBLE: { - result.listVal.emplace_back(stod(element)); - } break; - case BOOL: { - transform(element.begin(), element.end(), element.begin(), ::tolower); - std::istringstream is(element); - bool b; - is >> std::boolalpha >> b; - result.listVal.emplace_back(b); - } break; - case STRING: { - result.listVal.emplace_back(element); - } break; - case DATE: { - result.listVal.emplace_back(Date::FromCString(element.c_str(), element.length())); - } break; - case TIMESTAMP: { - result.listVal.emplace_back(Timestamp::FromCString(element.c_str(), element.length())); - } break; - case INTERVAL: { - result.listVal.emplace_back(Interval::FromCString(element.c_str(), element.length())); - } break; - case LIST: { - result.listVal.emplace_back(getArrowList( - l, pair.first + 1, pair.second + pair.first - 1, *dataType.childType, delimiter)); - } break; - default: - throw CSVReaderException("Unsupported data type " + - Types::dataTypeToString(dataType.childType->typeID) + - " inside LIST"); - } - } - auto numBytesOfOverflow = result.listVal.size() * Types::getDataTypeSize(dataType.typeID); - if (numBytesOfOverflow >= DEFAULT_PAGE_SIZE) { - throw CSVReaderException(StringUtils::string_format( - "Maximum num bytes of a LIST is %d. Input list's num bytes is %d.", DEFAULT_PAGE_SIZE, - numBytesOfOverflow)); - } - return result; -} - -void InMemArrowNodeCopier::saveToFile() { - logger->debug("Writing node columns to disk."); - assert(!columns.empty()); - for (auto& column : columns) { - taskScheduler.scheduleTask(CopyCSVTaskFactory::createCopyCSVTask( - [&](InMemColumn* x) { x->saveToFile(); }, column.get())); - } - taskScheduler.waitAllTasksToCompleteOrError(); - logger->debug("Done writing node columns to disk."); -} - -std::string InMemArrowNodeCopier::getFileTypeName(FileTypes fileTypes) { - switch (fileTypes) { - case FileTypes::CSV: - return "csv"; - case FileTypes::ARROW: - return "arrow"; - case FileTypes::PARQUET: - return "parquet"; - } -} - -std::string InMemArrowNodeCopier::getFileTypeSuffix(FileTypes fileTypes) { - return "." + getFileTypeName(fileTypes); -} - -} // namespace storage -} // namespace kuzu diff --git a/src/storage/in_mem_csv_copier/in_mem_structures_copier.cpp b/src/storage/in_mem_csv_copier/in_mem_structures_copier.cpp deleted file mode 100644 index 1df6b00758..0000000000 --- a/src/storage/in_mem_csv_copier/in_mem_structures_copier.cpp +++ /dev/null @@ -1,140 +0,0 @@ -#include "storage/in_mem_csv_copier/in_mem_structures_copier.h" - -#include "common/configs.h" -#include "storage/storage_structure/lists/lists.h" - -namespace kuzu { -namespace storage { - -InMemStructuresCopier::InMemStructuresCopier(CSVDescription& csvDescription, string outputDirectory, - TaskScheduler& taskScheduler, Catalog& catalog) - : logger{LoggerUtils::getOrCreateLogger("loader")}, csvDescription{csvDescription}, - outputDirectory{move(outputDirectory)}, numBlocks{0}, - taskScheduler{taskScheduler}, catalog{catalog} {} - -void InMemStructuresCopier::calculateNumBlocks(const string& filePath, string tableName) { - logger->info("Chunking csv into blocks for table {}.", tableName); - ifstream inf(filePath, ios_base::in); - if (!inf.is_open()) { - throw CopyCSVException("Cannot open file " + filePath + "."); - } - inf.seekg(0, ios_base::end); - numBlocks = 1 + (inf.tellg() / CopyCSVConfig::CSV_READING_BLOCK_SIZE); - inf.close(); - logger->info("Done chunking csv into blocks for table {}.", tableName); -} - -uint64_t InMemStructuresCopier::calculateNumRows(bool hasHeader) { - assert(numLinesPerBlock.size() == numBlocks); - auto numRows = 0u; - if (hasHeader) { - // Decrement the header line. - numLinesPerBlock[0]--; - } - for (auto blockId = 0u; blockId < numBlocks; blockId++) { - numRows += numLinesPerBlock[blockId]; - } - return numRows; -} - -void InMemStructuresCopier::countNumLinesPerBlockTask( - const string& fName, uint64_t blockId, InMemStructuresCopier* copier) { - copier->logger->trace("Start: path=`{0}` blkIdx={1}", fName, blockId); - CSVReader reader(fName, copier->csvDescription.csvReaderConfig, blockId); - copier->numLinesPerBlock[blockId] = 0ull; - while (reader.hasNextLine()) { - copier->numLinesPerBlock[blockId]++; - } - copier->logger->trace("End: path=`{0}` blkIdx={1}", fName, blockId); -} - -// Lists headers are created for only AdjLists, which store data in the page without NULL bits. -void InMemStructuresCopier::calculateListHeadersTask(node_offset_t numNodes, uint32_t elementSize, - atomic_uint64_vec_t* listSizes, ListHeadersBuilder* listHeadersBuilder, - const shared_ptr& logger) { - logger->trace("Start: ListHeadersBuilder={0:p}", (void*)listHeadersBuilder); - auto numElementsPerPage = PageUtils::getNumElementsInAPage(elementSize, false /* hasNull */); - auto numChunks = StorageUtils::getNumChunks(numNodes); - node_offset_t nodeOffset = 0u; - uint64_t lAdjListsIdx = 0u; - for (auto chunkId = 0u; chunkId < numChunks; chunkId++) { - auto csrOffset = 0u; - auto lastNodeOffsetInChunk = - min(nodeOffset + ListsMetadataConfig::LISTS_CHUNK_SIZE, numNodes); - for (auto i = nodeOffset; i < lastNodeOffsetInChunk; i++) { - auto numElementsInList = (*listSizes)[nodeOffset].load(memory_order_relaxed); - uint32_t header; - if (numElementsInList >= numElementsPerPage) { - header = ListHeaders::getLargeListHeader(lAdjListsIdx++); - } else { - header = ListHeaders::getSmallListHeader(csrOffset, numElementsInList); - csrOffset += numElementsInList; - } - listHeadersBuilder->setHeader(nodeOffset, header); - nodeOffset++; - } - } - logger->trace("End: adjListHeadersBuilder={0:p}", (void*)listHeadersBuilder); -} - -void InMemStructuresCopier::calculateListsMetadataAndAllocateInMemListPagesTask(uint64_t numNodes, - uint32_t elementSize, atomic_uint64_vec_t* listSizes, ListHeadersBuilder* listHeadersBuilder, - InMemLists* inMemList, bool hasNULLBytes, const shared_ptr& logger) { - logger->trace("Start: listsMetadataBuilder={0:p} adjListHeadersBuilder={1:p}", - (void*)inMemList->getListsMetadataBuilder(), (void*)listHeadersBuilder); - auto numChunks = StorageUtils::getNumChunks(numNodes); - node_offset_t nodeOffset = 0u; - auto largeListIdx = 0u; - for (auto chunkId = 0u; chunkId < numChunks; chunkId++) { - auto lastNodeOffsetInChunk = - min(nodeOffset + ListsMetadataConfig::LISTS_CHUNK_SIZE, numNodes); - for (auto i = nodeOffset; i < lastNodeOffsetInChunk; i++) { - if (ListHeaders::isALargeList(listHeadersBuilder->getHeader(nodeOffset))) { - largeListIdx++; - } - nodeOffset++; - } - } - inMemList->getListsMetadataBuilder()->initLargeListPageLists(largeListIdx); - nodeOffset = 0u; - largeListIdx = 0u; - auto numPerPage = PageUtils::getNumElementsInAPage(elementSize, hasNULLBytes); - for (auto chunkId = 0u; chunkId < numChunks; chunkId++) { - auto numPages = 0u, offsetInPage = 0u; - auto lastNodeOffsetInChunk = - min(nodeOffset + ListsMetadataConfig::LISTS_CHUNK_SIZE, numNodes); - while (nodeOffset < lastNodeOffsetInChunk) { - auto numElementsInList = (*listSizes)[nodeOffset].load(memory_order_relaxed); - if (ListHeaders::isALargeList(listHeadersBuilder->getHeader(nodeOffset))) { - auto numPagesForLargeList = numElementsInList / numPerPage; - if (0 != numElementsInList % numPerPage) { - numPagesForLargeList++; - } - inMemList->getListsMetadataBuilder()->populateLargeListPageList(largeListIdx, - numPagesForLargeList, numElementsInList, - inMemList->inMemFile->getNumPages() /* start idx of pages in .lists file */); - inMemList->inMemFile->addNewPages(numPagesForLargeList); - largeListIdx++; - } else { - while (numElementsInList + offsetInPage > numPerPage) { - numElementsInList -= (numPerPage - offsetInPage); - numPages++; - offsetInPage = 0; - } - offsetInPage += numElementsInList; - } - nodeOffset++; - } - if (0 != offsetInPage) { - numPages++; - } - inMemList->getListsMetadataBuilder()->populateChunkPageList(chunkId, numPages, - inMemList->inMemFile->getNumPages() /* start idx of pages in .lists file */); - inMemList->inMemFile->addNewPages(numPages); - } - logger->trace("End: listsMetadata={0:p} listHeadersBuilder={1:p}", - (void*)inMemList->getListsMetadataBuilder(), (void*)listHeadersBuilder); -} - -} // namespace storage -} // namespace kuzu diff --git a/src/storage/in_mem_storage_structure/in_mem_column.cpp b/src/storage/in_mem_storage_structure/in_mem_column.cpp index a85aa235c0..1eec80c834 100644 --- a/src/storage/in_mem_storage_structure/in_mem_column.cpp +++ b/src/storage/in_mem_storage_structure/in_mem_column.cpp @@ -60,7 +60,7 @@ unique_ptr InMemColumnFactory::getInMemPropertyColumn( case LIST: return make_unique(fName, dataType, numElements); default: - throw CopyCSVException("Invalid type for property column creation."); + throw CopyException("Invalid type for property column creation."); } } diff --git a/src/storage/in_mem_storage_structure/in_mem_lists.cpp b/src/storage/in_mem_storage_structure/in_mem_lists.cpp index 2013fa41ee..60706e4d89 100644 --- a/src/storage/in_mem_storage_structure/in_mem_lists.cpp +++ b/src/storage/in_mem_storage_structure/in_mem_lists.cpp @@ -92,7 +92,7 @@ unique_ptr InMemListsFactory::getInMemPropertyLists( case LIST: return make_unique(fName, dataType, numNodes); default: - throw CopyCSVException("Invalid type for property list creation."); + throw CopyException("Invalid type for property list creation."); } } diff --git a/src/storage/index/hash_index_utils.cpp b/src/storage/index/hash_index_utils.cpp index 98937bc078..25f5728cf7 100644 --- a/src/storage/index/hash_index_utils.cpp +++ b/src/storage/index/hash_index_utils.cpp @@ -52,7 +52,7 @@ in_mem_equals_function_t InMemHashIndexUtils::initializeEqualsFunc(DataTypeID da return equalsFuncForString; } default: { - throw CopyCSVException( + throw CopyException( "Hash index equals is not supported for dataType other than INT64 and STRING."); } } diff --git a/src/storage/storage_structure/in_mem_file.cpp b/src/storage/storage_structure/in_mem_file.cpp index d848c5e6b7..893d34229d 100644 --- a/src/storage/storage_structure/in_mem_file.cpp +++ b/src/storage/storage_structure/in_mem_file.cpp @@ -34,7 +34,7 @@ uint32_t InMemFile::addANewPage(bool setToZero) { void InMemFile::flush() { if (filePath.empty()) { - throw CopyCSVException("InMemPages: Empty filename"); + throw CopyException("InMemPages: Empty filename"); } auto fileInfo = FileUtils::openFile(filePath, O_CREAT | O_WRONLY); for (auto pageIdx = 0u; pageIdx < pages.size(); pageIdx++) { @@ -160,7 +160,7 @@ ku_list_t InMemOverflowFile::copyList(const Literal& listLiteral, PageByteCursor resultKUList, listLiteral, overflowCursor, numBytesOfListElement); } break; default: { - throw CopyCSVException("Unsupported data type inside LIST."); + throw CopyException("Unsupported data type inside LIST."); } } return resultKUList; diff --git a/src/storage/wal/wal.cpp b/src/storage/wal/wal.cpp index 5ef46d65e4..d044a8b2e3 100644 --- a/src/storage/wal/wal.cpp +++ b/src/storage/wal/wal.cpp @@ -72,15 +72,15 @@ void WAL::logOverflowFileNextBytePosRecord( addNewWALRecordNoLock(walRecord); } -void WAL::logCopyNodeCSVRecord(table_id_t tableID) { +void WAL::logCopyNodeRecord(table_id_t tableID) { lock_t lck{mtx}; - WALRecord walRecord = WALRecord::newCopyNodeCSVRecord(tableID); + WALRecord walRecord = WALRecord::newCopyNodeRecord(tableID); addNewWALRecordNoLock(walRecord); } -void WAL::logCopyRelCSVRecord(table_id_t tableID) { +void WAL::logCopyRelRecord(table_id_t tableID) { lock_t lck{mtx}; - WALRecord walRecord = WALRecord::newCopyRelCSVRecord(tableID); + WALRecord walRecord = WALRecord::newCopyRelRecord(tableID); addNewWALRecordNoLock(walRecord); } diff --git a/src/storage/wal/wal_record.cpp b/src/storage/wal/wal_record.cpp index 9f9ca01ef5..6e7ab01777 100644 --- a/src/storage/wal/wal_record.cpp +++ b/src/storage/wal/wal_record.cpp @@ -101,11 +101,11 @@ string walRecordTypeToString(WALRecordType walRecordType) { case WALRecordType::OVERFLOW_FILE_NEXT_BYTE_POS_RECORD: { return "OVERFLOW_FILE_NEXT_BYTE_POS_RECORD"; } - case WALRecordType::COPY_NODE_CSV_RECORD: { - return "COPY_NODE_CSV_RECORD"; + case WALRecordType::COPY_NODE_RECORD: { + return "COPY_NODE_RECORD"; } - case WALRecordType::COPY_REL_CSV_RECORD: { - return "COPY_REL_CSV_RECORD"; + case WALRecordType::COPY_REL_RECORD: { + return "COPY_REL_RECORD"; } case WALRecordType::DROP_TABLE_RECORD: { return "DROP_TABLE_RECORD"; @@ -183,17 +183,17 @@ WALRecord WALRecord::newOverflowFileNextBytePosRecord( return retVal; } -WALRecord WALRecord::newCopyNodeCSVRecord(table_id_t tableID) { +WALRecord WALRecord::newCopyNodeRecord(table_id_t tableID) { WALRecord retVal; - retVal.recordType = WALRecordType::COPY_NODE_CSV_RECORD; - retVal.copyNodeCsvRecord = CopyNodeCSVRecord(tableID); + retVal.recordType = WALRecordType::COPY_NODE_RECORD; + retVal.copyNodeRecord = CopyNodeRecord(tableID); return retVal; } -WALRecord WALRecord::newCopyRelCSVRecord(table_id_t tableID) { +WALRecord WALRecord::newCopyRelRecord(table_id_t tableID) { WALRecord retVal; - retVal.recordType = WALRecordType::COPY_REL_CSV_RECORD; - retVal.copyRelCsvRecord = CopyRelCSVRecord(tableID); + retVal.recordType = WALRecordType::COPY_REL_RECORD; + retVal.copyRelRecord = CopyRelRecord(tableID); return retVal; } diff --git a/src/storage/wal_replayer.cpp b/src/storage/wal_replayer.cpp index 7fe82d7ff2..ae679ee8be 100644 --- a/src/storage/wal_replayer.cpp +++ b/src/storage/wal_replayer.cpp @@ -243,9 +243,9 @@ void WALReplayer::replayWALRecord(WALRecord& walRecord) { } diskOverflowFile->resetLoggedNewOverflowFileNextBytePosRecord(); } break; - case WALRecordType::COPY_NODE_CSV_RECORD: { + case WALRecordType::COPY_NODE_RECORD: { if (isCheckpoint) { - auto tableID = walRecord.copyNodeCsvRecord.tableID; + auto tableID = walRecord.copyNodeRecord.tableID; if (!isRecovering) { auto nodeTableSchema = catalog->getReadOnlyVersion()->getNodeTableSchema(tableID); // If the WAL version of the file doesn't exist, we must have already replayed @@ -276,14 +276,14 @@ void WALReplayer::replayWALRecord(WALRecord& walRecord) { // impossible for users to roll back a COPY_CSV statement. } } break; - case WALRecordType::COPY_REL_CSV_RECORD: { + case WALRecordType::COPY_REL_RECORD: { if (isCheckpoint) { - auto tableID = walRecord.copyRelCsvRecord.tableID; + auto tableID = walRecord.copyRelRecord.tableID; if (!isRecovering) { - // See comments for COPY_NODE_CSV_RECORD. + // See comments for COPY_NODE_RECORD. WALReplayerUtils::replaceRelPropertyFilesWithVersionFromWALIfExists( catalog->getReadOnlyVersion()->getRelTableSchema(tableID), wal->getDirectory()); - // See comments for COPY_NODE_CSV_RECORD. + // See comments for COPY_NODE_RECORD. storageManager->getRelsStore().getRelTable(tableID)->initializeData( catalog->getReadOnlyVersion()->getRelTableSchema(tableID), *bufferManager); storageManager->getNodesStore() @@ -291,13 +291,13 @@ void WALReplayer::replayWALRecord(WALRecord& walRecord) { .setAdjListsAndColumns(&storageManager->getRelsStore()); } else { auto catalogForRecovery = getCatalogForRecovery(DBFileType::ORIGINAL); - // See comments for COPY_NODE_CSV_RECORD. + // See comments for COPY_NODE_RECORD. WALReplayerUtils::replaceRelPropertyFilesWithVersionFromWALIfExists( catalogForRecovery->getReadOnlyVersion()->getRelTableSchema(tableID), wal->getDirectory()); } } else { - // See comments for COPY_NODE_CSV_RECORD. + // See comments for COPY_NODE_RECORD. } } break; case WALRecordType::DROP_TABLE_RECORD: { @@ -328,7 +328,7 @@ void WALReplayer::replayWALRecord(WALRecord& walRecord) { } } } else { - // See comments for COPY_NODE_CSV_RECORD. + // See comments for COPY_NODE_RECORD. } } break; case WALRecordType::DROP_PROPERTY_RECORD: { @@ -358,7 +358,7 @@ void WALReplayer::replayWALRecord(WALRecord& walRecord) { } } } else { - // See comments for COPY_NODE_CSV_RECORD. + // See comments for COPY_NODE_RECORD. } } break; default: diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index cf547d7a80..d7b16382bb 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -15,7 +15,7 @@ add_subdirectory(test_helper) add_subdirectory(binder) add_subdirectory(catalog) add_subdirectory(common) -add_subdirectory(copy_csv) +add_subdirectory(copy) add_subdirectory(demo_db) add_subdirectory(main) add_subdirectory(parser) diff --git a/test/binder/binder_error_test.cpp b/test/binder/binder_error_test.cpp index 43882b9544..82bf397f6e 100644 --- a/test/binder/binder_error_test.cpp +++ b/test/binder/binder_error_test.cpp @@ -5,7 +5,7 @@ using namespace kuzu::testing; class BinderErrorTest : public DBTest { public: - string getInputCSVDir() override { return TestHelper::appendKuzuRootPath("dataset/tinysnb/"); } + string getInputDir() override { return TestHelper::appendKuzuRootPath("dataset/tinysnb/"); } string getBindingError(const string& input) { auto result = conn->query(input); diff --git a/test/binder/binder_test.cpp b/test/binder/binder_test.cpp index 4d67fa8258..c9249e8614 100644 --- a/test/binder/binder_test.cpp +++ b/test/binder/binder_test.cpp @@ -5,7 +5,7 @@ using namespace kuzu::testing; class BinderTest : public DBTest { public: - string getInputCSVDir() override { return TestHelper::appendKuzuRootPath("dataset/tinysnb/"); } + string getInputDir() override { return TestHelper::appendKuzuRootPath("dataset/tinysnb/"); } }; TEST_F(BinderTest, VarLenExtendMaxDepthTest) { diff --git a/test/copy/CMakeLists.txt b/test/copy/CMakeLists.txt new file mode 100644 index 0000000000..7a6b960d79 --- /dev/null +++ b/test/copy/CMakeLists.txt @@ -0,0 +1,8 @@ +add_kuzu_test(copy_dates_test copy_dates_test.cpp) +add_kuzu_test(copy_dos_style_newline_test copy_dos_style_newline_test.cpp) +add_kuzu_test(copy_fault_test copy_fault_test.cpp) +add_kuzu_test(copy_interval_test copy_interval_test.cpp) +add_kuzu_test(copy_lists_test copy_lists_test.cpp) +add_kuzu_test(copy_test copy_test.cpp) +add_kuzu_test(copy_timestamp_test copy_timestamp_test.cpp) +add_kuzu_test(copy_arrow_test arrow_node_copy_test.cpp) diff --git a/test/copy/arrow_node_copy_test.cpp b/test/copy/arrow_node_copy_test.cpp new file mode 100644 index 0000000000..a50f12f876 --- /dev/null +++ b/test/copy/arrow_node_copy_test.cpp @@ -0,0 +1,34 @@ +#include + +#include "test_helper/test_helper.h" + +using namespace std; +using namespace kuzu::common; +using namespace kuzu::storage; +using namespace kuzu::testing; + +class arrowNodeCopyTest : public DBTest { + void SetUp() override { + BaseGraphTest::SetUp(); + createDBAndConn(); + } + + string getInputDir() override { + return TestHelper::appendKuzuRootPath("dataset/copy-test/node/csv/"); + } +}; + +TEST_F(arrowNodeCopyTest, arrowNodeCopyCSVTest) { + initGraphFromPath(TestHelper::appendKuzuRootPath("dataset/copy-test/node/csv/")); + runTest(TestHelper::appendKuzuRootPath("test/test_files/copy/copy_node.test")); +} + +TEST_F(arrowNodeCopyTest, arrowNodeCopyArrowTest) { + initGraphFromPath(TestHelper::appendKuzuRootPath("dataset/copy-test/node/arrow/")); + runTest(TestHelper::appendKuzuRootPath("test/test_files/copy/copy_node.test")); +} + +TEST_F(arrowNodeCopyTest, arrowNodeCopyParquetTest) { + initGraphFromPath(TestHelper::appendKuzuRootPath("dataset/copy-test/node/parquet/")); + runTest(TestHelper::appendKuzuRootPath("test/test_files/copy/copy_node.test")); +} diff --git a/test/copy_csv/copy_csv_dates_test.cpp b/test/copy/copy_dates_test.cpp similarity index 90% rename from test/copy_csv/copy_csv_dates_test.cpp rename to test/copy/copy_dates_test.cpp index aefc3b7333..4ec1b16f81 100644 --- a/test/copy_csv/copy_csv_dates_test.cpp +++ b/test/copy/copy_dates_test.cpp @@ -5,14 +5,14 @@ using namespace kuzu::common; using namespace kuzu::storage; using namespace kuzu::testing; -class TinySnbCopyCSVDateTest : public InMemoryDBTest { - string getInputCSVDir() override { return TestHelper::appendKuzuRootPath("dataset/tinysnb/"); } +class TinySnbCopyDateTest : public InMemoryDBTest { + string getInputDir() override { return TestHelper::appendKuzuRootPath("dataset/tinysnb/"); } }; // Warning: This test assumes that each line in tinysnb's vPerson.csv gets // the node offsets that start from 0 consecutively (so first line gets person ID 0, second person // ID 1, so on and so forth). -TEST_F(TinySnbCopyCSVDateTest, NodePropertyColumnWithDate) { +TEST_F(TinySnbCopyDateTest, NodePropertyColumnWithDate) { auto catalog = getCatalog(*database); auto tableID = catalog->getReadOnlyVersion()->getNodeTableIDFromName("person"); auto propertyIdx = catalog->getReadOnlyVersion()->getNodeProperty(tableID, "birthdate"); diff --git a/test/copy_csv/copy_csv_dos_style_newline_test.cpp b/test/copy/copy_dos_style_newline_test.cpp similarity index 58% rename from test/copy_csv/copy_csv_dos_style_newline_test.cpp rename to test/copy/copy_dos_style_newline_test.cpp index 08a75488db..a8eff91086 100644 --- a/test/copy_csv/copy_csv_dos_style_newline_test.cpp +++ b/test/copy/copy_dos_style_newline_test.cpp @@ -5,13 +5,13 @@ using namespace kuzu::common; using namespace kuzu::storage; using namespace kuzu::testing; -class TinySnbCopyCSVDOSStyleNewlineTest : public InMemoryDBTest { - string getInputCSVDir() override { - return TestHelper::appendKuzuRootPath("dataset/copy-csv-dos-style-newline/"); +class TinySnbCopyDOSStyleNewlineTest : public InMemoryDBTest { + string getInputDir() override { + return TestHelper::appendKuzuRootPath("dataset/copy-dos-style-newline/"); } }; -TEST_F(TinySnbCopyCSVDOSStyleNewlineTest, copyCSVDOSStyleNewline) { +TEST_F(TinySnbCopyDOSStyleNewlineTest, copyDOSStyleNewline) { auto result = conn->query("MATCH (p:person) return p.ID"); auto groundTruth = vector{"0", "1", "2", "3", "4"}; ASSERT_EQ(TestHelper::convertResultToString(*result), groundTruth); diff --git a/test/copy/copy_fault_test.cpp b/test/copy/copy_fault_test.cpp new file mode 100644 index 0000000000..1bf8044edd --- /dev/null +++ b/test/copy/copy_fault_test.cpp @@ -0,0 +1,138 @@ +#include "common/exception.h" +#include "test_helper/test_helper.h" + +using namespace kuzu::testing; +using namespace std; + +class CopyFaultTest : public EmptyDBTest { +public: + void SetUp() override { + EmptyDBTest::SetUp(); + databaseConfig->inMemoryMode = true; + createDBAndConn(); + } + + void validateCopyException(string copyQuery, string expectedException) { + initGraph(); + auto result = conn->query(copyQuery); + ASSERT_FALSE(result->isSuccess()); + ASSERT_STREQ(result->getErrorMessage().c_str(), expectedException.c_str()); + } +}; + +class CopyDuplicateIDTest : public CopyFaultTest { + string getInputDir() override { + return TestHelper::appendKuzuRootPath("dataset/copy-fault-tests/duplicate-ids/"); + } +}; + +class CopyNodeUnmatchedColumnTypeTest : public CopyFaultTest {}; + +class CopyWrongHeaderTest : public CopyFaultTest {}; + +class CopyRelTableMultiplicityViolationTest : public CopyFaultTest { + string getInputDir() override { + return TestHelper::appendKuzuRootPath( + "dataset/copy-fault-tests/rel-table-multiplicity-violation/"); + } +}; + +TEST_F(CopyDuplicateIDTest, DuplicateIDsError) { + validateCopyException( + "COPY person FROM \"" + + TestHelper::appendKuzuRootPath("dataset/copy-fault-tests/duplicate-ids/vPerson.csv\""), + "Copy exception: " + Exception::getExistedPKExceptionMsg("10")); +} + +TEST_F(CopyNodeUnmatchedColumnTypeTest, UnMatchedColumnTypeError) { + conn->query( + "create node table person (ID INT64, fName INT64, gender INT64, isStudent BOOLEAN, " + "isWorker BOOLEAN, " + "age INT64, eyeSight DOUBLE, birthdate DATE, registerTime TIMESTAMP, lastJobDuration " + "INTERVAL, workedHours INT64[], usedNames STRING[], courseScoresPerTerm INT64[][], " + "PRIMARY " + "KEY (fName))"); + auto result = + conn->query("COPY person FROM \"" + + TestHelper::appendKuzuRootPath("dataset/tinysnb/vPerson.csv\" (HEADER=true)")); + ASSERT_EQ(result->getErrorMessage(), + "Cannot convert string Alice to INT64.. Invalid input. No characters consumed."); +} + +TEST_F(CopyWrongHeaderTest, HeaderError) { + conn->query("create node table person (ID INT64, fName STRING, PRIMARY KEY (ID));"); + conn->query( + "create rel table knows (FROM person TO person, prop1 INT64, prop2 STRING, MANY_MANY);"); + auto result = + conn->query("COPY person FROM \"" + + TestHelper::appendKuzuRootPath( + "dataset/copy-fault-tests/wrong-header/vPersonWrongColumnName.csv\" " + "(HEADER=true)")); + // We assert that headers are ignored, so any mistakes there won't cause an error + ASSERT_TRUE(result->isSuccess()); + result = conn->query("COPY knows FROM \"" + + TestHelper::appendKuzuRootPath( + "dataset/copy-fault-tests/wrong-header/eKnowsWrongColumnName.csv\" " + "(HEADER=true)")); + ASSERT_TRUE(result->isSuccess()); +} + +TEST_F(CopyWrongHeaderTest, CopyToNonEmptyTableErrors) { + conn->query("create node table person (ID INT64, fName STRING, PRIMARY KEY (ID));"); + auto result = + conn->query("COPY person FROM \"" + + TestHelper::appendKuzuRootPath( + "dataset/copy-fault-tests/wrong-header/vPersonWrongColumnName.csv\"" + "(HEADER=true)")); + ASSERT_TRUE(result->isSuccess()); + result = conn->query("COPY person FROM \"" + + TestHelper::appendKuzuRootPath( + "dataset/copy-fault-tests/wrong-header/vPersonWrongColumnName.csv\" " + "(HEADER=true)")); + ASSERT_FALSE(result->isSuccess()); +} + +TEST_F(CopyWrongHeaderTest, MissingColumnErrors) { + conn->query("create node table person (ID INT64, fName STRING, PRIMARY KEY (ID));"); + conn->query( + "create rel table knows (FROM person TO person, prop1 INT64, prop2 STRING, MANY_MANY);"); + // We first copy nodes to the node table correctly, then check if missing columns will trigger + // errors when copying rels. + auto result = + conn->query("COPY person FROM \"" + + TestHelper::appendKuzuRootPath( + "dataset/copy-fault-tests/wrong-header/vPerson.csv\" (HEADER=true)")); + ASSERT_TRUE(result->isSuccess()); + result = conn->query( + "COPY knows FROM \"" + TestHelper::appendKuzuRootPath( + "dataset/copy-fault-tests/wrong-header/eKnowsMissingColumn.csv\"" + "(HEADER=true)")); + ASSERT_FALSE(result->isSuccess()); +} + +TEST_F(CopyRelTableMultiplicityViolationTest, ManyOneMultiplicityViolationError) { + validateCopyException( + "COPY knows FROM \"" + + TestHelper::appendKuzuRootPath( + "dataset/copy-fault-tests/rel-table-multiplicity-violation/eKnows.csv\""), + "Copy exception: RelTable knows is a MANY_ONE table, but node(nodeOffset: 0, tableName: " + "person) has more than one neighbour in the forward direction."); +} + +TEST_F(CopyRelTableMultiplicityViolationTest, OneManyMultiplicityViolationError) { + validateCopyException( + "COPY teaches FROM \"" + + TestHelper::appendKuzuRootPath( + "dataset/copy-fault-tests/rel-table-multiplicity-violation/eTeaches.csv\""), + "Copy exception: RelTable teaches is a ONE_MANY table, but node(nodeOffset: 2, " + "tableName: person) has more than one neighbour in the backward direction."); +} + +TEST_F(CopyRelTableMultiplicityViolationTest, OneOneMultiplicityViolationError) { + validateCopyException( + "COPY matches FROM \"" + + TestHelper::appendKuzuRootPath( + "dataset/copy-fault-tests/rel-table-multiplicity-violation/eMatches.csv\""), + "Copy exception: RelTable matches is a ONE_ONE table, but node(nodeOffset: 1, " + "tableName: person) has more than one neighbour in the forward direction."); +} diff --git a/test/copy_csv/copy_csv_interval_test.cpp b/test/copy/copy_interval_test.cpp similarity index 90% rename from test/copy_csv/copy_csv_interval_test.cpp rename to test/copy/copy_interval_test.cpp index 9e45668ed2..056bd29273 100644 --- a/test/copy_csv/copy_csv_interval_test.cpp +++ b/test/copy/copy_interval_test.cpp @@ -7,14 +7,14 @@ using namespace kuzu::common; using namespace kuzu::storage; using namespace kuzu::testing; -class TinySnbCopyCSVIntervalTest : public InMemoryDBTest { - string getInputCSVDir() override { return TestHelper::appendKuzuRootPath("dataset/tinysnb/"); } +class TinySnbCopyIntervalTest : public InMemoryDBTest { + string getInputDir() override { return TestHelper::appendKuzuRootPath("dataset/tinysnb/"); } }; // Warning: This test assumes that each line in tinysnb's vPerson.csv gets // the node offsets that start from 0 consecutively (so first line gets person ID 0, second person // ID 1, so on and so forth). -TEST_F(TinySnbCopyCSVIntervalTest, NodePropertyColumnWithInterval) { +TEST_F(TinySnbCopyIntervalTest, NodePropertyColumnWithInterval) { auto graph = getStorageManager(*database); auto catalog = getCatalog(*database); auto tableID = catalog->getReadOnlyVersion()->getNodeTableIDFromName("person"); diff --git a/test/copy_csv/copy_csv_lists_test.cpp b/test/copy/copy_lists_test.cpp similarity index 97% rename from test/copy_csv/copy_csv_lists_test.cpp rename to test/copy/copy_lists_test.cpp index 03aeaa6ceb..b68a1940dd 100644 --- a/test/copy_csv/copy_csv_lists_test.cpp +++ b/test/copy/copy_lists_test.cpp @@ -23,7 +23,7 @@ class TinySnbListTest : public InMemoryDBTest { } return true; } - string getInputCSVDir() override { return TestHelper::appendKuzuRootPath("dataset/tinysnb/"); } + string getInputDir() override { return TestHelper::appendKuzuRootPath("dataset/tinysnb/"); } }; // Warning: This test assumes that each line in tinysnb's vPerson.csv gets diff --git a/test/copy_csv/copy_csv_test.cpp b/test/copy/copy_test.cpp similarity index 87% rename from test/copy_csv/copy_csv_test.cpp rename to test/copy/copy_test.cpp index 9b2d9ac5b5..1446ff40b4 100644 --- a/test/copy_csv/copy_csv_test.cpp +++ b/test/copy/copy_test.cpp @@ -10,51 +10,51 @@ using namespace kuzu::testing; namespace kuzu { namespace testing { -class CopyNodeCSVPropertyTest : public InMemoryDBTest { +class CopyNodePropertyTest : public InMemoryDBTest { public: - string getInputCSVDir() override { - return TestHelper::appendKuzuRootPath("dataset/copy-csv-node-property-test/"); + string getInputDir() override { + return TestHelper::appendKuzuRootPath("dataset/copy-node-property-test/"); } }; -class CopyCSVSpecialCharTest : public InMemoryDBTest { +class CopySpecialCharTest : public InMemoryDBTest { public: - string getInputCSVDir() override { - return TestHelper::appendKuzuRootPath("dataset/copy-csv-special-char-test/"); + string getInputDir() override { + return TestHelper::appendKuzuRootPath("dataset/copy-special-char-test/"); } }; -class CopyCSVReadLists2BytesPerEdgeTest : public InMemoryDBTest { +class CopyReadLists2BytesPerEdgeTest : public InMemoryDBTest { public: - string getInputCSVDir() override { + string getInputDir() override { return TestHelper::appendKuzuRootPath("dataset/read-list-tests/2-bytes-per-edge/"); } }; -class CopyCSVReadLists3BytesPerEdgeTest : public InMemoryDBTest { +class CopyReadLists3BytesPerEdgeTest : public InMemoryDBTest { public: - string getInputCSVDir() override { + string getInputDir() override { return TestHelper::appendKuzuRootPath("dataset/read-list-tests/3-bytes-per-edge/"); } }; -class CopyCSVReadLists4BytesPerEdgeTest : public InMemoryDBTest { +class CopyReadLists4BytesPerEdgeTest : public InMemoryDBTest { public: - string getInputCSVDir() override { + string getInputDir() override { return TestHelper::appendKuzuRootPath("dataset/read-list-tests/4-bytes-per-edge/"); } }; -class CopyCSVReadLists5BytesPerEdgeTest : public InMemoryDBTest { +class CopyReadLists5BytesPerEdgeTest : public InMemoryDBTest { public: - string getInputCSVDir() override { + string getInputDir() override { return TestHelper::appendKuzuRootPath("dataset/read-list-tests/5-bytes-per-edge/"); } }; -class CopyCSVLongStringTest : public InMemoryDBTest { - string getInputCSVDir() override { - return TestHelper::appendKuzuRootPath("dataset/copy-csv-fault-tests/long-string/"); +class CopyLongStringTest : public InMemoryDBTest { + string getInputDir() override { + return TestHelper::appendKuzuRootPath("dataset/copy-fault-tests/long-string/"); } }; @@ -96,15 +96,14 @@ ATableAKnowsLists getATableAKnowsLists(const Catalog& catalog, StorageManager* s } // namespace testing } // namespace kuzu -TEST_F(CopyNodeCSVPropertyTest, NodeStructuredStringPropertyTest) { +TEST_F(CopyNodePropertyTest, NodeStructuredStringPropertyTest) { auto graph = getStorageManager(*database); auto catalog = getCatalog(*database); auto tableID = catalog->getReadOnlyVersion()->getNodeTableIDFromName("person"); auto propertyIdx = catalog->getReadOnlyVersion()->getNodeProperty(tableID, "randomString"); auto column = reinterpret_cast( graph->getNodesStore().getNodePropertyColumn(tableID, propertyIdx.propertyID)); - string fName = - TestHelper::appendKuzuRootPath("dataset/copy-csv-node-property-test/vPerson.csv"); + string fName = TestHelper::appendKuzuRootPath("dataset/copy-node-property-test/vPerson.csv"); CSVReaderConfig config; CSVReader csvReader(fName, config); int lineIdx = 0; @@ -198,13 +197,13 @@ void verifyP6001ToP65999(KnowsTablePTablePKnowsLists& knowsTablePTablePKnowsList } } -TEST_F(CopyCSVReadLists2BytesPerEdgeTest, ReadLists2BytesPerEdgeTest) { +TEST_F(CopyReadLists2BytesPerEdgeTest, ReadLists2BytesPerEdgeTest) { auto knowsTablePTablePKnowsLists = getKnowsTablePTablePKnowsLists(*getCatalog(*database), getStorageManager(*database)); verifyP0ToP5999(knowsTablePTablePKnowsLists); } -TEST_F(CopyCSVReadLists3BytesPerEdgeTest, ReadLists3BytesPerEdgeTest) { +TEST_F(CopyReadLists3BytesPerEdgeTest, ReadLists3BytesPerEdgeTest) { auto knowsTablePTablePKnowsLists = getKnowsTablePTablePKnowsLists(*getCatalog(*database), getStorageManager(*database)); verifyP0ToP5999(knowsTablePTablePKnowsLists); @@ -212,14 +211,14 @@ TEST_F(CopyCSVReadLists3BytesPerEdgeTest, ReadLists3BytesPerEdgeTest) { knowsTablePTablePKnowsLists, *getCatalog(*database), getStorageManager(*database)); } -TEST_F(CopyCSVReadLists4BytesPerEdgeTest, ReadLists4BytesPerEdgeTest) { +TEST_F(CopyReadLists4BytesPerEdgeTest, ReadLists4BytesPerEdgeTest) { auto knowsTablePTablePKnowsLists = getKnowsTablePTablePKnowsLists(*getCatalog(*database), getStorageManager(*database)); verifyP0ToP5999(knowsTablePTablePKnowsLists); verifyP6001ToP65999(knowsTablePTablePKnowsLists); } -TEST_F(CopyCSVReadLists5BytesPerEdgeTest, ReadLists5BytesPerEdgeTest) { +TEST_F(CopyReadLists5BytesPerEdgeTest, ReadLists5BytesPerEdgeTest) { auto knowsTablePTablePKnowsLists = getKnowsTablePTablePKnowsLists(*getCatalog(*database), getStorageManager(*database)); verifyP0ToP5999(knowsTablePTablePKnowsLists); @@ -228,7 +227,7 @@ TEST_F(CopyCSVReadLists5BytesPerEdgeTest, ReadLists5BytesPerEdgeTest) { verifyP6001ToP65999(knowsTablePTablePKnowsLists); } -TEST_F(CopyCSVSpecialCharTest, CopySpecialCharsCsv) { +TEST_F(CopySpecialCharTest, CopySpecialChars) { auto storageManager = getStorageManager(*database); auto catalog = getCatalog(*database); auto tableID = catalog->getReadOnlyVersion()->getNodeTableIDFromName("person"); @@ -252,7 +251,7 @@ TEST_F(CopyCSVSpecialCharTest, CopySpecialCharsCsv) { EXPECT_EQ("DEsW#ork", col->readValue(2).strVal); } -TEST_F(CopyCSVLongStringTest, LongStringError) { +TEST_F(CopyLongStringTest, LongStringError) { auto storageManager = getStorageManager(*database); auto catalog = getCatalog(*database); auto tableID = catalog->getReadOnlyVersion()->getNodeTableIDFromName("person"); diff --git a/test/copy_csv/copy_csv_timestamp_test.cpp b/test/copy/copy_timestamp_test.cpp similarity index 95% rename from test/copy_csv/copy_csv_timestamp_test.cpp rename to test/copy/copy_timestamp_test.cpp index 6607757084..82da22e4c5 100644 --- a/test/copy_csv/copy_csv_timestamp_test.cpp +++ b/test/copy/copy_timestamp_test.cpp @@ -6,7 +6,7 @@ using namespace kuzu::storage; using namespace kuzu::testing; class TinySnbTimestampTest : public InMemoryDBTest { - string getInputCSVDir() override { return TestHelper::appendKuzuRootPath("dataset/tinysnb/"); } + string getInputDir() override { return TestHelper::appendKuzuRootPath("dataset/tinysnb/"); } }; // Warning: This test assumes that each line in tinysnb's vPerson.csv gets diff --git a/test/copy_csv/CMakeLists.txt b/test/copy_csv/CMakeLists.txt deleted file mode 100644 index d68d015801..0000000000 --- a/test/copy_csv/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ -add_kuzu_test(copy_csv_dates_test copy_csv_dates_test.cpp) -add_kuzu_test(copy_csv_dos_style_newline_test copy_csv_dos_style_newline_test.cpp) -add_kuzu_test(copy_csv_fault_test copy_csv_fault_test.cpp) -add_kuzu_test(copy_csv_interval_test copy_csv_interval_test.cpp) -add_kuzu_test(copy_csv_lists_test copy_csv_lists_test.cpp) -add_kuzu_test(copy_csv_test copy_csv_test.cpp) -add_kuzu_test(copy_csv_timestamp_test copy_csv_timestamp_test.cpp) -add_kuzu_test(copy_arrow_test arrow_node_copy_test.cpp) diff --git a/test/copy_csv/arrow_node_copy_test.cpp b/test/copy_csv/arrow_node_copy_test.cpp deleted file mode 100644 index 80308d3c65..0000000000 --- a/test/copy_csv/arrow_node_copy_test.cpp +++ /dev/null @@ -1,38 +0,0 @@ -#include - -#include "test_helper/test_helper.h" - -using namespace std; -using namespace kuzu::common; -using namespace kuzu::storage; -using namespace kuzu::testing; - -class arrowNodeCopyCsvTest : public DBTest { - string getInputCSVDir() override { - return TestHelper::appendKuzuRootPath("dataset/copy-test/node/csv/"); - } -}; - -TEST_F(arrowNodeCopyCsvTest, arrowNodeCopyCsvTest) { - runTest(TestHelper::appendKuzuRootPath("test/test_files/copy/copy_node.test")); -} - -class arrowNodeCopyArrowTest : public DBTest { - string getInputCSVDir() override { - return TestHelper::appendKuzuRootPath("dataset/copy-test/node/arrow/"); - } -}; - -TEST_F(arrowNodeCopyArrowTest, arrowNodeCopyArrowTest) { - runTest(TestHelper::appendKuzuRootPath("test/test_files/copy/copy_node.test")); -} - -class arrowNodeCopyParquetTest : public DBTest { - string getInputCSVDir() override { - return TestHelper::appendKuzuRootPath("dataset/copy-test/node/parquet/"); - } -}; - -TEST_F(arrowNodeCopyParquetTest, arrowNodeCopyParquetTest) { - runTest(TestHelper::appendKuzuRootPath("test/test_files/copy/copy_node.test")); -} diff --git a/test/copy_csv/copy_csv_fault_test.cpp b/test/copy_csv/copy_csv_fault_test.cpp deleted file mode 100644 index a735e1eb43..0000000000 --- a/test/copy_csv/copy_csv_fault_test.cpp +++ /dev/null @@ -1,140 +0,0 @@ -#include "common/exception.h" -#include "test_helper/test_helper.h" - -using namespace kuzu::testing; -using namespace std; - -class CopyCSVFaultTest : public EmptyDBTest { -public: - void SetUp() override { - EmptyDBTest::SetUp(); - databaseConfig->inMemoryMode = true; - createDBAndConn(); - } - - void validateCopyCSVException(string copyCSVQuery, string expectedException) { - initGraph(); - auto result = conn->query(copyCSVQuery); - ASSERT_FALSE(result->isSuccess()); - ASSERT_STREQ(result->getErrorMessage().c_str(), expectedException.c_str()); - } -}; - -class CopyCSVDuplicateIDTest : public CopyCSVFaultTest { - string getInputCSVDir() override { - return TestHelper::appendKuzuRootPath("dataset/copy-csv-fault-tests/duplicate-ids/"); - } -}; - -class CopyNodeCSVUnmatchedColumnTypeTest : public CopyCSVFaultTest {}; - -class CopyCSVWrongHeaderTest : public CopyCSVFaultTest {}; - -class CopyCSVRelTableMultiplicityViolationTest : public CopyCSVFaultTest { - string getInputCSVDir() override { - return TestHelper::appendKuzuRootPath( - "dataset/copy-csv-fault-tests/rel-table-multiplicity-violation/"); - } -}; - -TEST_F(CopyCSVDuplicateIDTest, DuplicateIDsError) { - validateCopyCSVException( - "COPY person FROM \"" + TestHelper::appendKuzuRootPath( - "dataset/copy-csv-fault-tests/duplicate-ids/vPerson.csv\""), - "CopyCSV exception: " + Exception::getExistedPKExceptionMsg("10")); -} - -TEST_F(CopyNodeCSVUnmatchedColumnTypeTest, UnMatchedColumnTypeError) { - conn->query( - "create node table person (ID INT64, fName INT64, gender INT64, isStudent BOOLEAN, " - "isWorker BOOLEAN, " - "age INT64, eyeSight DOUBLE, birthdate DATE, registerTime TIMESTAMP, lastJobDuration " - "INTERVAL, workedHours INT64[], usedNames STRING[], courseScoresPerTerm INT64[][], " - "PRIMARY " - "KEY (fName))"); - auto result = - conn->query("COPY person FROM \"" + - TestHelper::appendKuzuRootPath("dataset/tinysnb/vPerson.csv\" (HEADER=true)")); - ASSERT_EQ(result->getErrorMessage(), - "Cannot convert string Alice to INT64.. Invalid input. No characters consumed."); -} - -TEST_F(CopyCSVWrongHeaderTest, CSVHeaderError) { - conn->query("create node table person (ID INT64, fName STRING, PRIMARY KEY (ID));"); - conn->query( - "create rel table knows (FROM person TO person, prop1 INT64, prop2 STRING, MANY_MANY);"); - auto result = - conn->query("COPY person FROM \"" + - TestHelper::appendKuzuRootPath( - "dataset/copy-csv-fault-tests/wrong-header/vPersonWrongColumnName.csv\" " - "(HEADER=true)")); - // We assert that CSV headers are ignored, so any mistakes there won't cause an error - ASSERT_TRUE(result->isSuccess()); - result = - conn->query("COPY knows FROM \"" + - TestHelper::appendKuzuRootPath( - "dataset/copy-csv-fault-tests/wrong-header/eKnowsWrongColumnName.csv\" " - "(HEADER=true)")); - ASSERT_TRUE(result->isSuccess()); -} - -TEST_F(CopyCSVWrongHeaderTest, CopyCSVToNonEmptyTableErrors) { - conn->query("create node table person (ID INT64, fName STRING, PRIMARY KEY (ID));"); - auto result = - conn->query("COPY person FROM \"" + - TestHelper::appendKuzuRootPath( - "dataset/copy-csv-fault-tests/wrong-header/vPersonWrongColumnName.csv\"" - "(HEADER=true)")); - ASSERT_TRUE(result->isSuccess()); - result = - conn->query("COPY person FROM \"" + - TestHelper::appendKuzuRootPath( - "dataset/copy-csv-fault-tests/wrong-header/vPersonWrongColumnName.csv\" " - "(HEADER=true)")); - ASSERT_FALSE(result->isSuccess()); -} - -TEST_F(CopyCSVWrongHeaderTest, MissingColumnErrors) { - conn->query("create node table person (ID INT64, fName STRING, PRIMARY KEY (ID));"); - conn->query( - "create rel table knows (FROM person TO person, prop1 INT64, prop2 STRING, MANY_MANY);"); - // We first copy nodes to the node table correctly, then check if missing columns will trigger - // errors when copying rels. - auto result = - conn->query("COPY person FROM \"" + - TestHelper::appendKuzuRootPath( - "dataset/copy-csv-fault-tests/wrong-header/vPerson.csv\" (HEADER=true)")); - ASSERT_TRUE(result->isSuccess()); - result = conn->query("COPY knows FROM \"" + - TestHelper::appendKuzuRootPath( - "dataset/copy-csv-fault-tests/wrong-header/eKnowsMissingColumn.csv\"" - "(HEADER=true)")); - ASSERT_FALSE(result->isSuccess()); -} - -TEST_F(CopyCSVRelTableMultiplicityViolationTest, ManyOneMultiplicityViolationError) { - validateCopyCSVException( - "COPY knows FROM \"" + - TestHelper::appendKuzuRootPath( - "dataset/copy-csv-fault-tests/rel-table-multiplicity-violation/eKnows.csv\""), - "CopyCSV exception: RelTable knows is a MANY_ONE table, but node(nodeOffset: 0, tableName: " - "person) has more than one neighbour in the forward direction."); -} - -TEST_F(CopyCSVRelTableMultiplicityViolationTest, OneManyMultiplicityViolationError) { - validateCopyCSVException( - "COPY teaches FROM \"" + - TestHelper::appendKuzuRootPath( - "dataset/copy-csv-fault-tests/rel-table-multiplicity-violation/eTeaches.csv\""), - "CopyCSV exception: RelTable teaches is a ONE_MANY table, but node(nodeOffset: 2, " - "tableName: person) has more than one neighbour in the backward direction."); -} - -TEST_F(CopyCSVRelTableMultiplicityViolationTest, OneOneMultiplicityViolationError) { - validateCopyCSVException( - "COPY matches FROM \"" + - TestHelper::appendKuzuRootPath( - "dataset/copy-csv-fault-tests/rel-table-multiplicity-violation/eMatches.csv\""), - "CopyCSV exception: RelTable matches is a ONE_ONE table, but node(nodeOffset: 1, " - "tableName: person) has more than one neighbour in the forward direction."); -} diff --git a/test/demo_db/demo_db_test.cpp b/test/demo_db/demo_db_test.cpp index 2a546c95d9..f588ecdc76 100644 --- a/test/demo_db/demo_db_test.cpp +++ b/test/demo_db/demo_db_test.cpp @@ -5,7 +5,7 @@ using namespace kuzu::testing; class DemoDBTest : public DBTest { public: - string getInputCSVDir() override { return TestHelper::appendKuzuRootPath("dataset/demo-db/"); } + string getInputDir() override { return TestHelper::appendKuzuRootPath("dataset/demo-db/"); } }; TEST_F(DemoDBTest, DemoDBTest) { diff --git a/test/include/main_test_helper/main_test_helper.h b/test/include/main_test_helper/main_test_helper.h index 2f6556c8e0..18a62a26cd 100644 --- a/test/include/main_test_helper/main_test_helper.h +++ b/test/include/main_test_helper/main_test_helper.h @@ -16,7 +16,7 @@ class ApiTest : public BaseGraphTest { initGraph(); } - string getInputCSVDir() override { return TestHelper::appendKuzuRootPath("dataset/tinysnb/"); } + string getInputDir() override { return TestHelper::appendKuzuRootPath("dataset/tinysnb/"); } static void assertMatchPersonCountStar(Connection* conn) { auto result = conn->query("MATCH (a:person) RETURN COUNT(*)"); diff --git a/test/include/test_helper/test_helper.h b/test/include/test_helper/test_helper.h index 567ae5bda6..bb44250ad0 100644 --- a/test/include/test_helper/test_helper.h +++ b/test/include/test_helper/test_helper.h @@ -45,7 +45,7 @@ class TestHelper { static void executeCypherScript(const string& path, Connection& conn); static constexpr char SCHEMA_FILE_NAME[] = "schema.cypher"; - static constexpr char COPY_CSV_FILE_NAME[] = "copy_csv.cypher"; + static constexpr char COPY_CSV_FILE_NAME[] = "copy.cypher"; static string getTmpTestDir() { return appendKuzuRootPath("test/unittest_temp/"); } @@ -69,7 +69,7 @@ class BaseGraphTest : public Test { databaseConfig = make_unique(TestHelper::getTmpTestDir()); } - virtual string getInputCSVDir() = 0; + virtual string getInputDir() = 0; void TearDown() override { FileUtils::removeDir(TestHelper::getTmpTestDir()); } @@ -84,6 +84,8 @@ class BaseGraphTest : public Test { void initGraph(); + void initGraphFromPath(const string& path) const; + void commitOrRollbackConnection(bool isCommit, TransactionTestType transactionTestType) const; protected: @@ -188,7 +190,7 @@ class BaseGraphTest : public Test { // This class starts database without initializing graph. class EmptyDBTest : public BaseGraphTest { - string getInputCSVDir() override { throw NotImplementedException("getInputCSVDir()"); } + string getInputDir() override { throw NotImplementedException("getInputDir()"); } }; // This class starts database in on-disk mode. diff --git a/test/runner/CMakeLists.txt b/test/runner/CMakeLists.txt index faee072090..6d7c1223e4 100644 --- a/test/runner/CMakeLists.txt +++ b/test/runner/CMakeLists.txt @@ -1,4 +1,4 @@ -add_kuzu_test(e2e_copy_csv_transaction_test e2e_copy_csv_transaction_test.cpp) +add_kuzu_test(e2e_copy_csv_transaction_test e2e_copy_transaction_test.cpp) add_kuzu_test(e2e_ddl_test e2e_ddl_test.cpp) add_kuzu_test(e2e_delete_create_transaction_test e2e_delete_create_transaction_test.cpp) add_kuzu_test(e2e_exception_test e2e_exception_test.cpp) diff --git a/test/runner/e2e_copy_csv_transaction_test.cpp b/test/runner/e2e_copy_transaction_test.cpp similarity index 89% rename from test/runner/e2e_copy_csv_transaction_test.cpp rename to test/runner/e2e_copy_transaction_test.cpp index 98969b1db1..6d3d1d311a 100644 --- a/test/runner/e2e_copy_csv_transaction_test.cpp +++ b/test/runner/e2e_copy_transaction_test.cpp @@ -36,7 +36,7 @@ class TinySnbCopyCSVTransactionTest : public EmptyDBTest { ASSERT_EQ(expectedResult, actualResult); } - void validateDatabaseStateBeforeCheckPointCopyNodeCSV(table_id_t tableID) { + void validateDatabaseStateBeforeCheckPointCopyNode(table_id_t tableID) { auto nodeTableSchema = (NodeTableSchema*)catalog->getReadOnlyVersion()->getTableSchema(tableID); // Before checkPointing, we should have two versions of node column and list files. The @@ -56,7 +56,7 @@ class TinySnbCopyCSVTransactionTest : public EmptyDBTest { UINT64_MAX); } - void validateDatabaseStateAfterCheckPointCopyNodeCSV(table_id_t tableID) { + void validateDatabaseStateAfterCheckPointCopyNode(table_id_t tableID) { auto nodeTableSchema = (NodeTableSchema*)catalog->getReadOnlyVersion()->getTableSchema(tableID); // After checkPointing, we should only have one version of node column and list @@ -85,15 +85,15 @@ class TinySnbCopyCSVTransactionTest : public EmptyDBTest { preparedStatement->getExpressionsToCollect(), preparedStatement->statementType); getQueryProcessor(*database)->execute(physicalPlan.get(), executionContext.get()); auto tableID = catalog->getReadOnlyVersion()->getNodeTableIDFromName("person"); - validateDatabaseStateBeforeCheckPointCopyNodeCSV(tableID); + validateDatabaseStateBeforeCheckPointCopyNode(tableID); if (transactionTestType == TransactionTestType::RECOVERY) { commitButSkipCheckpointingForTestingRecovery(*conn); - validateDatabaseStateBeforeCheckPointCopyNodeCSV(tableID); + validateDatabaseStateBeforeCheckPointCopyNode(tableID); initWithoutLoadingGraph(); - validateDatabaseStateAfterCheckPointCopyNodeCSV(tableID); + validateDatabaseStateAfterCheckPointCopyNode(tableID); } else { conn->commit(); - validateDatabaseStateAfterCheckPointCopyNodeCSV(tableID); + validateDatabaseStateAfterCheckPointCopyNode(tableID); } } @@ -122,7 +122,7 @@ class TinySnbCopyCSVTransactionTest : public EmptyDBTest { ASSERT_EQ(expectedResult, actualResult); } - void validateDatabaseStateBeforeCheckPointCopyRelCSV(table_id_t tableID) { + void validateDatabaseStateBeforeCheckPointCopyRel(table_id_t tableID) { auto relTableSchema = (RelTableSchema*)catalog->getReadOnlyVersion()->getTableSchema(tableID); // Before checkPointing, we should have two versions of rel column and list files. @@ -136,7 +136,7 @@ class TinySnbCopyCSVTransactionTest : public EmptyDBTest { 14); } - void validateDatabaseStateAfterCheckPointCopyRelCSV(table_id_t knowsTableID) { + void validateDatabaseStateAfterCheckPointCopyRel(table_id_t knowsTableID) { auto relTableSchema = (RelTableSchema*)catalog->getReadOnlyVersion()->getTableSchema(knowsTableID); // After checkPointing, we should only have one version of rel column and list @@ -171,15 +171,15 @@ class TinySnbCopyCSVTransactionTest : public EmptyDBTest { preparedStatement->getExpressionsToCollect(), preparedStatement->statementType); getQueryProcessor(*database)->execute(physicalPlan.get(), executionContext.get()); auto tableID = catalog->getReadOnlyVersion()->getRelTableIDFromName("knows"); - validateDatabaseStateBeforeCheckPointCopyRelCSV(tableID); + validateDatabaseStateBeforeCheckPointCopyRel(tableID); if (transactionTestType == TransactionTestType::RECOVERY) { commitButSkipCheckpointingForTestingRecovery(*conn); - validateDatabaseStateBeforeCheckPointCopyRelCSV(tableID); + validateDatabaseStateBeforeCheckPointCopyRel(tableID); initWithoutLoadingGraph(); - validateDatabaseStateAfterCheckPointCopyRelCSV(tableID); + validateDatabaseStateAfterCheckPointCopyRel(tableID); } else { conn->commit(); - validateDatabaseStateAfterCheckPointCopyRelCSV(tableID); + validateDatabaseStateAfterCheckPointCopyRel(tableID); } } @@ -204,23 +204,23 @@ class TinySnbCopyCSVTransactionTest : public EmptyDBTest { } // namespace transaction } // namespace kuzu -TEST_F(TinySnbCopyCSVTransactionTest, CopyNodeCSVCommitNormalExecution) { +TEST_F(TinySnbCopyCSVTransactionTest, CopyNodeCommitNormalExecution) { copyNodeCSVCommitAndRecoveryTest(TransactionTestType::NORMAL_EXECUTION); } -TEST_F(TinySnbCopyCSVTransactionTest, CopyNodeCSVCommitRecovery) { +TEST_F(TinySnbCopyCSVTransactionTest, CopyNodeCommitRecovery) { copyNodeCSVCommitAndRecoveryTest(TransactionTestType::RECOVERY); } -TEST_F(TinySnbCopyCSVTransactionTest, CopyRelCSVCommitNormalExecution) { +TEST_F(TinySnbCopyCSVTransactionTest, CopyRelCommitNormalExecution) { copyRelCSVCommitAndRecoveryTest(TransactionTestType::NORMAL_EXECUTION); } -TEST_F(TinySnbCopyCSVTransactionTest, CopyRelCSVCommitRecovery) { +TEST_F(TinySnbCopyCSVTransactionTest, CopyRelCommitRecovery) { copyRelCSVCommitAndRecoveryTest(TransactionTestType::RECOVERY); } -TEST_F(TinySnbCopyCSVTransactionTest, CopyNodeCSVOutputMsg) { +TEST_F(TinySnbCopyCSVTransactionTest, CopyNodeOutputMsg) { conn->query(createPersonTableCMD); conn->query(createKnowsTableCMD); auto result = conn->query(copyPersonTableCMD); diff --git a/test/runner/e2e_ddl_test.cpp b/test/runner/e2e_ddl_test.cpp index 59d0d6ea06..28eb8f7bc7 100644 --- a/test/runner/e2e_ddl_test.cpp +++ b/test/runner/e2e_ddl_test.cpp @@ -17,7 +17,7 @@ class PrimaryKeyTest : public EmptyDBTest { class IntPrimaryKeyTest : public PrimaryKeyTest { public: - string getInputCSVDir() override { + string getInputDir() override { return TestHelper::appendKuzuRootPath("dataset/primary-key-tests/int-pk-tests/"); } @@ -57,7 +57,7 @@ class IntPrimaryKeyTest : public PrimaryKeyTest { class StringPrimaryKeyTest : public PrimaryKeyTest { public: - string getInputCSVDir() override { + string getInputDir() override { return TestHelper::appendKuzuRootPath("dataset/primary-key-tests/string-pk-tests/"); } @@ -118,7 +118,7 @@ class TinySnbDDLTest : public DBTest { catalog = getCatalog(*database); } - string getInputCSVDir() override { return TestHelper::appendKuzuRootPath("dataset/tinysnb/"); } + string getInputDir() override { return TestHelper::appendKuzuRootPath("dataset/tinysnb/"); } void validateDatabaseStateAfterCommitCreateNodeTable() { ASSERT_TRUE(catalog->getReadOnlyVersion()->containNodeTable("EXAM_PAPER")); diff --git a/test/runner/e2e_delete_create_transaction_test.cpp b/test/runner/e2e_delete_create_transaction_test.cpp index 3e565731a7..a290a493f0 100644 --- a/test/runner/e2e_delete_create_transaction_test.cpp +++ b/test/runner/e2e_delete_create_transaction_test.cpp @@ -87,7 +87,7 @@ class BaseDeleteCreateTrxTest : public DBTest { class CreateDeleteInt64NodeTrxTest : public BaseDeleteCreateTrxTest { public: - string getInputCSVDir() override { + string getInputDir() override { return TestHelper::appendKuzuRootPath("dataset/node-insertion-deletion-tests/int64-pk/"); } @@ -184,7 +184,7 @@ class CreateDeleteInt64NodeTrxTest : public BaseDeleteCreateTrxTest { class CreateDeleteStringNodeTrxTest : public BaseDeleteCreateTrxTest { public: - string getInputCSVDir() override { + string getInputDir() override { return TestHelper::appendKuzuRootPath("dataset/node-insertion-deletion-tests/string-pk/"); } @@ -444,7 +444,7 @@ TEST_F(CreateDeleteStringNodeTrxTest, MixedInsertDeleteRollbackRecovery) { // TODO(Guodong/Xiyang): refactor these tests to follow the above convention. class CreateRelTrxTest : public BaseDeleteCreateTrxTest { public: - string getInputCSVDir() override { + string getInputDir() override { return TestHelper::appendKuzuRootPath("dataset/rel-insertion-tests/"); } diff --git a/test/runner/e2e_delete_rel_test.cpp b/test/runner/e2e_delete_rel_test.cpp index 007d05938c..a32cd2be1e 100644 --- a/test/runner/e2e_delete_rel_test.cpp +++ b/test/runner/e2e_delete_rel_test.cpp @@ -4,7 +4,7 @@ using namespace kuzu::testing; class DeleteRelTest : public DBTest { public: - string getInputCSVDir() override { + string getInputDir() override { return TestHelper::appendKuzuRootPath("dataset/rel-insertion-tests/"); } string getDeleteKnowsRelQuery(string srcTable, string dstTable, int64_t srcID, int64_t dstID) { diff --git a/test/runner/e2e_exception_test.cpp b/test/runner/e2e_exception_test.cpp index 6c9dfc8aef..717ae285db 100644 --- a/test/runner/e2e_exception_test.cpp +++ b/test/runner/e2e_exception_test.cpp @@ -5,7 +5,7 @@ using namespace kuzu::testing; class TinySnbExceptionTest : public DBTest { public: - string getInputCSVDir() override { return TestHelper::appendKuzuRootPath("dataset/tinysnb/"); } + string getInputDir() override { return TestHelper::appendKuzuRootPath("dataset/tinysnb/"); } }; TEST_F(TinySnbExceptionTest, ReadVarlengthRelPropertyTest1) { diff --git a/test/runner/e2e_order_by_test.cpp b/test/runner/e2e_order_by_test.cpp index 6eb9e6548e..319118203a 100644 --- a/test/runner/e2e_order_by_test.cpp +++ b/test/runner/e2e_order_by_test.cpp @@ -5,7 +5,7 @@ using namespace kuzu::testing; class OrderByTests : public DBTest { public: - string getInputCSVDir() override { + string getInputDir() override { return TestHelper::appendKuzuRootPath("dataset/order-by-tests/"); } }; diff --git a/test/runner/e2e_read_list_test.cpp b/test/runner/e2e_read_list_test.cpp index 0bff8eef4b..91d1152917 100644 --- a/test/runner/e2e_read_list_test.cpp +++ b/test/runner/e2e_read_list_test.cpp @@ -8,21 +8,21 @@ using namespace kuzu::testing; class EndToEndReadLists2BytesPerEdgeTest : public DBTest { public: - string getInputCSVDir() override { + string getInputDir() override { return TestHelper::appendKuzuRootPath("dataset/read-list-tests/2-bytes-per-edge/"); } }; class EndToEndReadLists4BytesPerEdgeTest : public DBTest { public: - string getInputCSVDir() override { + string getInputDir() override { return TestHelper::appendKuzuRootPath("dataset/read-list-tests/4-bytes-per-edge/"); } }; class EndToEndReadListsSubQueryTest : public DBTest { public: - string getInputCSVDir() override { + string getInputDir() override { return TestHelper::appendKuzuRootPath( "dataset/read-list-tests/large-list-sub-query-tests/"); } diff --git a/test/runner/e2e_read_test.cpp b/test/runner/e2e_read_test.cpp index a035a60d68..a83681f4e5 100644 --- a/test/runner/e2e_read_test.cpp +++ b/test/runner/e2e_read_test.cpp @@ -4,14 +4,14 @@ using ::testing::Test; using namespace kuzu::testing; class LongStringPKTest : public DBTest { - string getInputCSVDir() override { + string getInputDir() override { return TestHelper::appendKuzuRootPath("dataset/long-string-pk-tests/"); } }; class TinySnbReadTest : public DBTest { public: - string getInputCSVDir() override { return TestHelper::appendKuzuRootPath("dataset/tinysnb/"); } + string getInputDir() override { return TestHelper::appendKuzuRootPath("dataset/tinysnb/"); } }; TEST_F(LongStringPKTest, LongStringPKTest) { diff --git a/test/runner/e2e_set_transaction_test.cpp b/test/runner/e2e_set_transaction_test.cpp index 99d660fc1d..970429e9d3 100644 --- a/test/runner/e2e_set_transaction_test.cpp +++ b/test/runner/e2e_set_transaction_test.cpp @@ -33,7 +33,7 @@ class BaseSetNodePropTransactionTest : public DBTest { class SetNodeStructuredPropTransactionTest : public BaseSetNodePropTransactionTest { public: - string getInputCSVDir() override { return TestHelper::appendKuzuRootPath("dataset/tinysnb/"); } + string getInputDir() override { return TestHelper::appendKuzuRootPath("dataset/tinysnb/"); } void insertLongStrings1000TimesAndVerify(Connection* connection) { int numWriteQueries = 1000; diff --git a/test/runner/e2e_update_node_test.cpp b/test/runner/e2e_update_node_test.cpp index f7af3c4a72..3e86fd7c09 100644 --- a/test/runner/e2e_update_node_test.cpp +++ b/test/runner/e2e_update_node_test.cpp @@ -4,7 +4,7 @@ using namespace kuzu::testing; class TinySnbUpdateTest : public DBTest { public: - string getInputCSVDir() override { return TestHelper::appendKuzuRootPath("dataset/tinysnb/"); } + string getInputDir() override { return TestHelper::appendKuzuRootPath("dataset/tinysnb/"); } string getStringExceedsOverflow() { string veryLongList = "["; diff --git a/test/runner/e2e_update_rel_test.cpp b/test/runner/e2e_update_rel_test.cpp index e18c5b8950..716d533172 100644 --- a/test/runner/e2e_update_rel_test.cpp +++ b/test/runner/e2e_update_rel_test.cpp @@ -4,7 +4,7 @@ using namespace kuzu::testing; class UpdateRelTest : public DBTest { public: - string getInputCSVDir() override { + string getInputDir() override { return TestHelper::appendKuzuRootPath("dataset/rel-insertion-tests/"); } string getUpdateRelQuery(string srcTable, string dstTable, string relation, int64_t srcID, diff --git a/test/storage/disk_array_update_test.cpp b/test/storage/disk_array_update_test.cpp index 77084d34ca..1adb3ef921 100644 --- a/test/storage/disk_array_update_test.cpp +++ b/test/storage/disk_array_update_test.cpp @@ -157,13 +157,13 @@ class BaseDiskArrayUpdateTests : public DBTest { class DiskArrayUpdateTests : public BaseDiskArrayUpdateTests { public: - string getInputCSVDir() override { return "dataset/non-empty-disk-array-db/"; } + string getInputDir() override { return "dataset/non-empty-disk-array-db/"; } }; class DiskArrayUpdateEmptyDBTests : public BaseDiskArrayUpdateTests { public: - string getInputCSVDir() override { return "dataset/empty-db/"; } + string getInputDir() override { return "dataset/empty-db/"; } }; TEST_F(DiskArrayUpdateTests, BasicUpdateTestCommitNormalExecution) { diff --git a/test/storage/node_insertion_deletion_test.cpp b/test/storage/node_insertion_deletion_test.cpp index 7a87a13564..bf06dea410 100644 --- a/test/storage/node_insertion_deletion_test.cpp +++ b/test/storage/node_insertion_deletion_test.cpp @@ -14,7 +14,7 @@ class NodeInsertionDeletionTests : public DBTest { initDBAndConnection(); } - string getInputCSVDir() override { + string getInputDir() override { return TestHelper::appendKuzuRootPath("dataset/node-insertion-deletion-tests/int64-pk/"); } diff --git a/test/storage/rel_insertion_test.cpp b/test/storage/rel_insertion_test.cpp index 9fb3aa8008..279b3dff90 100644 --- a/test/storage/rel_insertion_test.cpp +++ b/test/storage/rel_insertion_test.cpp @@ -58,7 +58,7 @@ class RelInsertionTest : public DBTest { return result; } - string getInputCSVDir() override { + string getInputDir() override { return TestHelper::appendKuzuRootPath("dataset/rel-insertion-tests/"); } diff --git a/test/storage/wal_replayer_test.cpp b/test/storage/wal_replayer_test.cpp index 8d1543852d..543c2310d5 100644 --- a/test/storage/wal_replayer_test.cpp +++ b/test/storage/wal_replayer_test.cpp @@ -5,7 +5,7 @@ using namespace kuzu::storage; using namespace kuzu::testing; class WALReplayerTests : public DBTest { - string getInputCSVDir() override { return TestHelper::appendKuzuRootPath("dataset/tinysnb/"); } + string getInputDir() override { return TestHelper::appendKuzuRootPath("dataset/tinysnb/"); } }; TEST_F(WALReplayerTests, ReplayingUncommittedWALForChekpointErrors) { diff --git a/test/test_helper/test_helper.cpp b/test/test_helper/test_helper.cpp index c48cfe8a53..6b86f355a4 100644 --- a/test/test_helper/test_helper.cpp +++ b/test/test_helper/test_helper.cpp @@ -256,8 +256,13 @@ void TestHelper::executeCypherScript(const string& cypherScript, Connection& con } void BaseGraphTest::initGraph() { - TestHelper::executeCypherScript(getInputCSVDir() + TestHelper::SCHEMA_FILE_NAME, *conn); - TestHelper::executeCypherScript(getInputCSVDir() + TestHelper::COPY_CSV_FILE_NAME, *conn); + TestHelper::executeCypherScript(getInputDir() + TestHelper::SCHEMA_FILE_NAME, *conn); + TestHelper::executeCypherScript(getInputDir() + TestHelper::COPY_CSV_FILE_NAME, *conn); +} + +void BaseGraphTest::initGraphFromPath(const string& path) const { + TestHelper::executeCypherScript(path + TestHelper::SCHEMA_FILE_NAME, *conn); + TestHelper::executeCypherScript(path + TestHelper::COPY_CSV_FILE_NAME, *conn); } void BaseGraphTest::commitOrRollbackConnection( diff --git a/test/transaction/transaction_test.cpp b/test/transaction/transaction_test.cpp index 0eb220253e..aa128fb8a9 100644 --- a/test/transaction/transaction_test.cpp +++ b/test/transaction/transaction_test.cpp @@ -10,7 +10,7 @@ class TransactionTests : public DBTest { initWithoutLoadingGraph(); } - string getInputCSVDir() override { return TestHelper::appendKuzuRootPath("dataset/tinysnb/"); } + string getInputDir() override { return TestHelper::appendKuzuRootPath("dataset/tinysnb/"); } void initWithoutLoadingGraph() { systemConfig->largePageBufferPoolSize = (1ull << 22);