├── .gitattributes ├── Question-1 ├── Apache C Programming Backend.c ├── Question-1.cbp ├── Question-1.layout ├── bin │ └── Debug │ │ └── Question-1.exe ├── image │ ├── Final-Output.png │ ├── Specify-title.png │ ├── finish.png │ ├── save-File.png │ └── select-empty-project.png ├── obj │ └── Debug │ │ └── Apache C Programming Backend.o └── readme.md ├── Question-2 ├── Matrix_Exponentiation_Approach.c ├── Question-2.cbp ├── Question-2.layout ├── bin │ └── Debug │ │ └── Question-2.exe ├── image │ ├── Create-new-file.png │ ├── Final-Output.png │ ├── Finish.png │ ├── Save-the-file.png │ ├── select-empty-project.png │ └── specify-title.png ├── obj │ └── Debug │ │ └── Matrix_Exponentiation_Approach.o └── readme.md └── Question-3 ├── Go ├── .gitignore ├── LICENSE ├── README.md ├── age │ ├── age.go │ ├── age_test.go │ ├── builder.go │ ├── builder_test.go │ ├── errors.go │ └── models.go ├── go.mod ├── parser │ ├── Agtype.g4 │ ├── README.md │ ├── agtype_base_listener.go │ ├── agtype_base_visitor.go │ ├── agtype_lexer.go │ ├── agtype_listener.go │ ├── agtype_parser.go │ └── agtype_visitor.go └── samples │ ├── age_wrapper_sample.go │ ├── main.go │ └── sql_api_sample.go └── Python ├── .gitignore ├── LICENSE ├── README.md ├── __init__.py ├── age ├── VERSION.py ├── __init__.py ├── age.py ├── builder.py ├── exceptions.py ├── gen │ ├── AgtypeLexer.py │ ├── AgtypeListener.py │ ├── AgtypeParser.py │ ├── AgtypeVisitor.py │ └── __init__.py └── models.py ├── antlr ├── Agtype.g4 └── README.md ├── register_pypi.sh ├── samples ├── __init__.py ├── apache-age-agtypes.ipynb ├── apache-age-basic.ipynb └── apache-age-note.ipynb ├── setup.py ├── test_age_py.py └── test_agtypes.py /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /Question-1/Apache C Programming Backend.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int fibo(int a) 5 | { 6 | if (a == 1) 7 | return 0; 8 | 9 | if (a == 2) 10 | return 1; 11 | 12 | int fib[a]; 13 | fib[0] = 0; 14 | fib[1] = 1; 15 | for (int i = 2; i < a; i++) 16 | fib[i] = fib[i - 1] + fib[i - 2]; 17 | 18 | return fib[a - 1]; 19 | } 20 | 21 | typedef enum TypeTag 22 | { 23 | ADD, 24 | SUB, 25 | MUL, 26 | FIBO, 27 | } TypeTag; 28 | typedef struct Node 29 | { 30 | TypeTag type; 31 | int val; 32 | } Node; 33 | 34 | Node *constructNode(TypeTag _type, int _val) 35 | { 36 | struct Node *tmp = (Node *)malloc(sizeof(struct Node)); 37 | tmp->val = _val; 38 | tmp->type = _type; 39 | return tmp; 40 | } 41 | Node *add(int a, int b) 42 | { 43 | int sum = a + b; 44 | return constructNode(ADD, a + b); 45 | } 46 | Node *addN(Node *a, Node *b) 47 | { 48 | if (b == NULL) 49 | return constructNode(FIBO, fibo(a->val)); 50 | return constructNode(ADD, a->val + b->val); 51 | } 52 | Node *sub(int a, int b) 53 | { 54 | return constructNode(SUB, a - b); 55 | } 56 | Node *subN(Node *a, Node *b) 57 | { 58 | if (b == NULL) 59 | return constructNode(FIBO, fibo(a->val)); 60 | return constructNode(SUB, a->val - b->val); 61 | } 62 | Node *mul(int a, int b) 63 | { 64 | return constructNode(MUL, a * b); 65 | } 66 | Node *mulN(Node *a, Node *b) 67 | { 68 | if (b == NULL) 69 | return constructNode(FIBO, fibo(a->val)); 70 | return constructNode(MUL, a->val * b->val); 71 | } 72 | 73 | Node *(*makeFunc(TypeTag tag))(int, int) 74 | { 75 | if (tag == ADD) 76 | { 77 | return &add; 78 | } 79 | else if (tag == SUB) 80 | { 81 | return ⊂ 82 | } 83 | else if (tag == MUL) 84 | { 85 | return &mul; 86 | } 87 | 88 | return &add; 89 | } 90 | Node *(*makeFun(TypeTag tag))(Node *, Node *) 91 | { 92 | if (tag == ADD) 93 | { 94 | return &addN; 95 | } 96 | else if (tag == SUB) 97 | { 98 | return &subN; 99 | } 100 | else if (tag == MUL) 101 | { 102 | return &mulN; 103 | } 104 | 105 | return &addN; 106 | } 107 | 108 | Node *ABS(Node *tmp) 109 | { 110 | tmp->val = (tmp->val < 0) ? -tmp->val : tmp->val; 111 | return tmp; 112 | } 113 | 114 | #define abs(tmp) ABS(tmp) 115 | 116 | void calc(Node *tmp) 117 | { 118 | 119 | printf("- "); 120 | switch (tmp->type) 121 | { 122 | case ADD: 123 | printf("add"); 124 | break; 125 | case SUB: 126 | printf("sub"); 127 | break; 128 | case MUL: 129 | printf("mul"); 130 | break; 131 | case FIBO: 132 | printf("fibo"); 133 | break; 134 | } 135 | printf(" : %d\n", tmp->val); 136 | } 137 | 138 | int main() 139 | { 140 | 141 | Node *add = (*makeFunc(ADD))(10, 6); 142 | calc(add); 143 | Node *mul = (*makeFunc(MUL))(5, 4); 144 | calc(mul); 145 | Node *sub = (*makeFun(SUB))(add, mul); 146 | calc(sub); 147 | Node *fibo = (*makeFun(SUB))(abs(sub), NULL); // Get n-th from fibonacci numbers. 148 | calc(fibo); 149 | 150 | return 0; 151 | } 152 | -------------------------------------------------------------------------------- /Question-1/Question-1.cbp: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 41 | 42 | -------------------------------------------------------------------------------- /Question-1/Question-1.layout: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Question-1/bin/Debug/Question-1.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DS-Popeye/Apache-Internship-Program/05c38eeb30bd4065df4a38fde27b271b25f4fefa/Question-1/bin/Debug/Question-1.exe -------------------------------------------------------------------------------- /Question-1/image/Final-Output.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DS-Popeye/Apache-Internship-Program/05c38eeb30bd4065df4a38fde27b271b25f4fefa/Question-1/image/Final-Output.png -------------------------------------------------------------------------------- /Question-1/image/Specify-title.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DS-Popeye/Apache-Internship-Program/05c38eeb30bd4065df4a38fde27b271b25f4fefa/Question-1/image/Specify-title.png -------------------------------------------------------------------------------- /Question-1/image/finish.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DS-Popeye/Apache-Internship-Program/05c38eeb30bd4065df4a38fde27b271b25f4fefa/Question-1/image/finish.png -------------------------------------------------------------------------------- /Question-1/image/save-File.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DS-Popeye/Apache-Internship-Program/05c38eeb30bd4065df4a38fde27b271b25f4fefa/Question-1/image/save-File.png -------------------------------------------------------------------------------- /Question-1/image/select-empty-project.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DS-Popeye/Apache-Internship-Program/05c38eeb30bd4065df4a38fde27b271b25f4fefa/Question-1/image/select-empty-project.png -------------------------------------------------------------------------------- /Question-1/obj/Debug/Apache C Programming Backend.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DS-Popeye/Apache-Internship-Program/05c38eeb30bd4065df4a38fde27b271b25f4fefa/Question-1/obj/Debug/Apache C Programming Backend.o -------------------------------------------------------------------------------- /Question-1/readme.md: -------------------------------------------------------------------------------- 1 | # [Question No. 1] Coding Test – Backend 2 | 3 | ## Installation 4 | 5 | - Download and install MinGw 6 | - Create a new Project 7 | - Select Empty Project 8 | ![plot](./image/select-empty-project.png) 9 | 10 | - Write project title 11 | ![plot](./image/Specify-title.png) 12 | 13 | - Click on Finish Button 14 | ![plot](./image/finish.png) 15 | 16 | - Create a new File 17 | - Save the File 18 | ![plot](./image/save-File.png) 19 | - Now compile and run `Apache C Programming Backend.c` file 20 | 21 | ## Additional Information 22 | 23 | - As c compailer doesn't support operator overloading changed function name `makeFunc` to `makeFun` for multiple use by using different parameter 24 | 25 | ## Final Result 26 | 27 | ![plot](./image/Final-Output.png) 28 | -------------------------------------------------------------------------------- /Question-2/Matrix_Exponentiation_Approach.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | 6 | int mod = 1e9 + 7; 7 | 8 | int arr[200000]; 9 | int Dynamic_Programming_Approach(int n) 10 | { 11 | arr[0] = 0; 12 | arr[1] = 1; 13 | arr[2] = 2; 14 | for (int i = 3; i <= n; i++) 15 | arr[i] = arr[i - 3] + arr[i - 2]; 16 | return arr[n]; 17 | } 18 | 19 | // Declare T[][] as global matrix 20 | int T[2000][2000]; 21 | 22 | // Result matrix 23 | int result[2000][2000]; 24 | 25 | // Function to multiply two matrices 26 | void mul_2(int K) 27 | { 28 | // Create an auxiliary matrix to 29 | // store elements of the 30 | // multiplication matrix 31 | int temp[K + 1][K + 1]; 32 | memset(temp, 0, sizeof temp); 33 | 34 | // Iterate over range [0, K] 35 | for (int i = 1; i <= K; i++) 36 | { 37 | 38 | for (int j = 1; j <= K; j++) 39 | { 40 | 41 | for (int k = 1; k <= K; k++) 42 | { 43 | 44 | // Update temp[i][j] 45 | temp[i][j] = (temp[i][j] + (T[i][k] * T[k][j]) % mod) % mod; 46 | } 47 | } 48 | } 49 | 50 | // Update the final matrix 51 | for (int i = 1; i <= K; i++) 52 | { 53 | for (int j = 1; j <= K; j++) 54 | { 55 | T[i][j] = temp[i][j]; 56 | } 57 | } 58 | } 59 | 60 | // Function to multiply two matrices 61 | void mul_1(int K) 62 | { 63 | // Create an auxiliary matrix to 64 | // store elements of the 65 | // multiplication matrix 66 | int temp[K + 1][K + 1]; 67 | memset(temp, 0, sizeof temp); 68 | 69 | // Iterate over range [0, K] 70 | for (int i = 1; i <= K; i++) 71 | { 72 | 73 | for (int j = 1; j <= K; j++) 74 | { 75 | 76 | for (int k = 1; k <= K; k++) 77 | { 78 | 79 | // Update temp[i][j] 80 | temp[i][j] = (temp[i][j] + (result[i][k] * T[k][j]) % mod) % mod; 81 | } 82 | } 83 | } 84 | 85 | // Update the final matrix 86 | for (int i = 1; i <= K; i++) 87 | { 88 | for (int j = 1; j <= K; j++) 89 | { 90 | result[i][j] = temp[i][j]; 91 | } 92 | } 93 | } 94 | 95 | // Function to calculate matrix^n 96 | // using binary exponentaion 97 | void matrix_pow(int K, int n) 98 | { 99 | // Initialize result matrix 100 | // and unity matrix 101 | for (int i = 1; i <= K; i++) 102 | { 103 | for (int j = 1; j <= K; j++) 104 | { 105 | if (i == j) 106 | result[i][j] = 1; 107 | } 108 | } 109 | 110 | while (n > 0) 111 | { 112 | if (n % 2 == 1) 113 | mul_1(K); 114 | mul_2(K); 115 | n /= 2; 116 | } 117 | } 118 | 119 | // Function to calculate nth term 120 | // of general recurrence 121 | int NthTerm(int F[], int C[], int K, 122 | int n) 123 | { 124 | memset(T, 0, sizeof T); 125 | memset(result, 0, sizeof result); 126 | 127 | // Fill T[][] with appropriate value 128 | for (int i = 1; i <= K; i++) 129 | T[i][K] = C[K - i]; 130 | 131 | for (int i = 1; i <= K; i++) 132 | T[i + 1][i] = 1; 133 | 134 | // Function Call to calculate T^n 135 | matrix_pow(K, n); 136 | 137 | int answer = 0; 138 | 139 | // Calculate nth term as first 140 | // element of F*(T^n) 141 | for (int i = 1; i <= K; i++) 142 | { 143 | answer += (F[i - 1] * result[i][1]) % mod; 144 | answer %= mod; 145 | } 146 | return answer; 147 | } 148 | 149 | // Driver Code 150 | int Matrix_Exponentiation_Approach(int N) 151 | { 152 | // Given Initial terms 153 | int F[] = {0, 1, 2}; 154 | 155 | // Given coefficients 156 | int C[] = {0, 1, 1}; 157 | 158 | // Given K 159 | int K = 3; 160 | 161 | int ans = NthTerm(F, C, K, N); 162 | 163 | return ans; 164 | } 165 | 166 | int Brute_Force_Approach(int n) 167 | { 168 | // rescursion 169 | if (n == 0) 170 | return 0; 171 | else if (n == 1) 172 | return 1; 173 | else if (n == 2) 174 | return 2; 175 | else 176 | return Brute_Force_Approach(n - 3) + Brute_Force_Approach(n - 2); 177 | } 178 | 179 | int main() 180 | { 181 | int ans; 182 | ans = Matrix_Exponentiation_Approach(10); 183 | 184 | printf("%d\n", ans); 185 | 186 | return 0; 187 | } 188 | -------------------------------------------------------------------------------- /Question-2/Question-2.cbp: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 38 | 39 | -------------------------------------------------------------------------------- /Question-2/Question-2.layout: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Question-2/bin/Debug/Question-2.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DS-Popeye/Apache-Internship-Program/05c38eeb30bd4065df4a38fde27b271b25f4fefa/Question-2/bin/Debug/Question-2.exe -------------------------------------------------------------------------------- /Question-2/image/Create-new-file.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DS-Popeye/Apache-Internship-Program/05c38eeb30bd4065df4a38fde27b271b25f4fefa/Question-2/image/Create-new-file.png -------------------------------------------------------------------------------- /Question-2/image/Final-Output.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DS-Popeye/Apache-Internship-Program/05c38eeb30bd4065df4a38fde27b271b25f4fefa/Question-2/image/Final-Output.png -------------------------------------------------------------------------------- /Question-2/image/Finish.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DS-Popeye/Apache-Internship-Program/05c38eeb30bd4065df4a38fde27b271b25f4fefa/Question-2/image/Finish.png -------------------------------------------------------------------------------- /Question-2/image/Save-the-file.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DS-Popeye/Apache-Internship-Program/05c38eeb30bd4065df4a38fde27b271b25f4fefa/Question-2/image/Save-the-file.png -------------------------------------------------------------------------------- /Question-2/image/select-empty-project.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DS-Popeye/Apache-Internship-Program/05c38eeb30bd4065df4a38fde27b271b25f4fefa/Question-2/image/select-empty-project.png -------------------------------------------------------------------------------- /Question-2/image/specify-title.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DS-Popeye/Apache-Internship-Program/05c38eeb30bd4065df4a38fde27b271b25f4fefa/Question-2/image/specify-title.png -------------------------------------------------------------------------------- /Question-2/obj/Debug/Matrix_Exponentiation_Approach.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DS-Popeye/Apache-Internship-Program/05c38eeb30bd4065df4a38fde27b271b25f4fefa/Question-2/obj/Debug/Matrix_Exponentiation_Approach.o -------------------------------------------------------------------------------- /Question-2/readme.md: -------------------------------------------------------------------------------- 1 | # [Question No. 2] Coding Test – Backend 2 | 3 | ## Installation 4 | 5 | - Download and install MinGw 6 | - Create a new Project 7 | - Select Empty Project 8 | ![plot](./image/select-empty-project.png) 9 | 10 | - Write project title 11 | ![plot](./image/specify-title.png) 12 | 13 | - Click on Finish Button 14 | ![plot](./image/Finish.png) 15 | 16 | - Create a new File 17 | ![plot](./image/Create-new-file.png) 18 | - Save the File 19 | ![plot](./image/Save-the-file.png) 20 | - Now compile and run `Matrix_Exponentiation_Approach.c` file 21 | - For Matrix Exponentiation Approach use `Matrix_Exponentiation_Approach(n)` 22 | - For Dynamic Programming Approach use `Dynamic_Programming_Approach(n)` 23 | - For Brute Force Approach use `Brute_Force_Approach(n)` 24 | 25 | ## Solving Approach 26 | 27 | ``` 28 | F(n) = F(n-3) + F(n -2) 29 | F(0) = 0 30 | F(1) = 1 31 | F(2) = 2 32 | ``` 33 | 34 | 1. Matrix Exponentiation Approach 35 | 36 | - Time Complexity : logN 37 | - Space Complexity : (3)^2 \* log(N) 38 | - Advantages : 39 | - Less Time required for getting single value 40 | - Disadvantages : 41 | - Hard to implement 42 | - Hard to Understand Code 43 | - More time required for multiple use as it do not store any value 44 | 45 | 2. Dynamic Programming Approach 46 | 47 | - Time Complexity : N 48 | - Space Complexity : N 49 | - Advantages : 50 | - Easy to Implement 51 | - Less time required for multiple use as it store previous computaiton 52 | - Disadvantages : 53 | - A lot of memory wasted for single iteration 54 | 55 | 3. Brute Force Approach 56 | 57 | - Time Complexity : 3^N 58 | - Space Complexity : 3^N 59 | - Advantages : 60 | - Easy to Implement 61 | - Easy to Understand 62 | - Disadvantages : 63 | - Too much memory wasted required 64 | - Too much time wasted required 65 | 66 | ## Final Result 67 | 68 | ![plot](./image/Final-output.png) 69 | -------------------------------------------------------------------------------- /Question-3/Go/.gitignore: -------------------------------------------------------------------------------- 1 | # ANTLR build 2 | parser/.antlr/ 3 | 4 | # Go 5 | go.sum 6 | 7 | # Binaries for programs and plugins 8 | *.exe 9 | *.exe~ 10 | *.dll 11 | *.so 12 | *.dylib 13 | 14 | # Test binary, built with `go test -c` 15 | *.test 16 | 17 | # Output of the go coverage tool, specifically when used with LiteIDE 18 | *.out 19 | 20 | # Dependency directories (remove the comment below to include it) 21 | # vendor/ 22 | 23 | .vscode/ -------------------------------------------------------------------------------- /Question-3/Go/LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /Question-3/Go/README.md: -------------------------------------------------------------------------------- 1 | # Apache AGE Driver (Interface) 2 | 3 | [Apache AGE](https://age.apache.org/) is a PostgreSQL extension that provides graph database functionality. The goal of the Apache AGE project is to create single storage that can handle both relational and graph model data so that users can use standard ANSI SQL along with openCypher, the Graph query language. This repository hosts the development of the Python driver for this Apache extension (currently in Incubator status). Thanks for checking it out. 4 | 5 | A graph consists of a set of vertices (also called nodes) and edges, where each individual vertex and edge possesses a map of properties. A vertex is the basic object of a graph, that can exist independently of everything else in the graph. An edge creates a directed connection between two vertices. A graph database is simply composed of vertices and edges. This type of database is useful when the meaning is in the relationships between the data. Relational databases can easily handle direct relationships, but indirect relationships are more difficult to deal with in relational databases. A graph database stores relationship information as a first-class entity. Apache AGE gives you the best of both worlds, simultaneously. 6 | 7 | Apache AGE is: 8 | 9 | - **Powerful** -- AGE adds graph database support to the already popular PostgreSQL database: PostgreSQL is used by organizations including Apple, Spotify, and NASA. 10 | - **Flexible** -- AGE allows you to perform openCypher queries, which make complex queries much easier to write. 11 | - **Intelligent** -- AGE allows you to perform graph queries that are the basis for many next level web services such as fraud & intrustion detection, master data management, product recommendations, identity and relationship management, experience personalization, knowledge management and more. 12 | 13 | ### Features 14 | 15 | - Cypher query support for database/sql PostreSQL driver (enables cypher queries directly) 16 | - Deserialize AGE result (AGType) to Vertex, Edge, Path 17 | 18 | ### Go get & gomod 19 | 20 | - over Go 1.16 21 | - This module runs on golang standard api [database/sql](https://golang.org/pkg/database/sql/) and [antlr4-go](https://github.com/antlr/antlr4/tree/master/runtime/Go/antlr) 22 | 23 | ```(shell) 24 | go get github.com/DS-Popeye/Apache-Internship-Program/Question-3/Go 25 | 26 | ``` 27 | 28 | #### gomod 29 | 30 | ```(go) 31 | require github.com/DS-Popeye/Apache-Internship-Program/Question-3/Go {version} 32 | 33 | ``` 34 | 35 | Check [latest version](https://github.com/DS-Popeye/Apache-Internship-Program/Question-3/Go/releases) 36 | 37 | ### For more information about [Apache AGE](https://age.apache.org/) 38 | 39 | - Apache Incubator Age : https://age.apache.org/ 40 | - Github : https://github.com/apache/incubator-age 41 | - Document : https://age.incubator.apache.org/docs/ 42 | 43 | ### Check AGE loaded on your PostgreSQL 44 | 45 | Connect to your containerized Postgres instance and then run the following commands: 46 | 47 | ```(sql) 48 | # psql 49 | CREATE EXTENSION age; 50 | LOAD 'age'; 51 | SET search_path = ag_catalog, "$user", public; 52 | ``` 53 | 54 | ### Test 55 | 56 | Check out and rewrite DSN in incubator-age/drivers/golang/age_test.go 57 | 58 | ``` 59 | cd apache-age-go 60 | go test -v . 61 | 62 | ``` 63 | 64 | ### Samples 65 | 66 | **Usage 1: using database/sql API and Cypher execution function 'ExecCypher'** 67 | 68 | > - Sample : [samples/sql_api_sample.go](samples/sql_api_sample.go) 69 | 70 | **Usage 2: using Age Wrapper** 71 | 72 | > - Sample : [samples/age_wrapper_sample.go](samples/age_wrapper_sample.go) 73 | 74 | **Run Samples** 75 | 76 | > Sample : [samples/main.go](samples/main.go) 77 | 78 | ### License 79 | 80 | Apache-2.0 License 81 | -------------------------------------------------------------------------------- /Question-3/Go/age/age.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package age 20 | 21 | import ( 22 | "bytes" 23 | "database/sql" 24 | "fmt" 25 | ) 26 | 27 | // GetReady prepare AGE extension 28 | // load AGE extension 29 | // set graph path 30 | func GetReady(db *sql.DB, graphName string) (bool, error) { 31 | tx, err := db.Begin() 32 | if err != nil { 33 | return false, err 34 | } 35 | 36 | _, err = tx.Exec("LOAD 'age';") 37 | if err != nil { 38 | return false, err 39 | } 40 | 41 | _, err = tx.Exec("SET search_path = ag_catalog, '$user', public;") 42 | if err != nil { 43 | return false, err 44 | } 45 | 46 | var count int = 0 47 | 48 | err = tx.QueryRow("SELECT count(*) FROM ag_graph WHERE name=$1", graphName).Scan(&count) 49 | 50 | if err != nil { 51 | return false, err 52 | } 53 | 54 | if count == 0 { 55 | _, err = tx.Exec("SELECT create_graph($1);", graphName) 56 | if err != nil { 57 | return false, err 58 | } 59 | } 60 | 61 | tx.Commit() 62 | 63 | return true, nil 64 | } 65 | 66 | type CursorProvider func(columnCount int, rows *sql.Rows) Cursor 67 | 68 | type Cursor interface { 69 | Next() bool 70 | Close() error 71 | } 72 | 73 | func execCypher(cursorProvider CursorProvider, tx *sql.Tx, graphName string, columnCount int, cypher string, args ...interface{}) (Cursor, error) { 74 | var buf bytes.Buffer 75 | 76 | cypherStmt := fmt.Sprintf(cypher, args...) 77 | 78 | buf.WriteString("SELECT * from cypher('") 79 | buf.WriteString(graphName) 80 | buf.WriteString("', $$ ") 81 | buf.WriteString(cypherStmt) 82 | buf.WriteString(" $$)") 83 | buf.WriteString(" as (") 84 | buf.WriteString("v0 agtype") 85 | for i := 1; i < columnCount; i++ { 86 | buf.WriteString(fmt.Sprintf(", v%d agtype", i)) 87 | } 88 | buf.WriteString(")") 89 | 90 | stmt := buf.String() 91 | 92 | if columnCount == 0 { 93 | _, err := tx.Exec(stmt) 94 | if err != nil { 95 | fmt.Println(stmt) 96 | return nil, err 97 | } 98 | return nil, nil 99 | } else { 100 | rows, err := tx.Query(stmt) 101 | if err != nil { 102 | fmt.Println(stmt) 103 | return nil, err 104 | } 105 | return cursorProvider(columnCount, rows), nil 106 | } 107 | } 108 | 109 | // ExecCypher : execute cypher query 110 | // CREATE , DROP .... 111 | // MATCH .... RETURN .... 112 | // CREATE , DROP .... RETURN ... 113 | func ExecCypher(tx *sql.Tx, graphName string, columnCount int, cypher string, args ...interface{}) (*CypherCursor, error) { 114 | cursor, err := execCypher(NewCypherCursor, tx, graphName, columnCount, cypher, args...) 115 | var cypherCursor *CypherCursor 116 | if cursor != nil { 117 | cypherCursor = cursor.(*CypherCursor) 118 | } 119 | return cypherCursor, err 120 | } 121 | 122 | type Age struct { 123 | db *sql.DB 124 | graphName string 125 | } 126 | 127 | type AgeTx struct { 128 | age *Age 129 | tx *sql.Tx 130 | } 131 | 132 | /** 133 | @param dsn host=127.0.0.1 port=5432 dbname=postgres user=postgres password=agens sslmode=disable 134 | */ 135 | func ConnectAge(graphName string, dsn string) (*Age, error) { 136 | db, err := sql.Open("postgres", dsn) 137 | if err != nil { 138 | return nil, err 139 | } 140 | age := &Age{db: db, graphName: graphName} 141 | _, err = age.GetReady() 142 | 143 | if err != nil { 144 | db.Close() 145 | age = nil 146 | } 147 | 148 | return age, err 149 | } 150 | 151 | func NewAge(graphName string, db *sql.DB) *Age { 152 | return &Age{db: db, graphName: graphName} 153 | } 154 | 155 | func (age *Age) GetReady() (bool, error) { 156 | tx, err := age.db.Begin() 157 | if err != nil { 158 | return false, err 159 | } 160 | 161 | _, err = tx.Exec("LOAD 'age';") 162 | if err != nil { 163 | return false, err 164 | } 165 | 166 | _, err = tx.Exec("SET search_path = ag_catalog, '$user', public;") 167 | if err != nil { 168 | return false, err 169 | } 170 | 171 | var count int = 0 172 | 173 | err = tx.QueryRow("SELECT count(*) FROM ag_graph WHERE name=$1", age.graphName).Scan(&count) 174 | 175 | if err != nil { 176 | return false, err 177 | } 178 | 179 | if count == 0 { 180 | _, err = tx.Exec("SELECT create_graph($1);", age.graphName) 181 | if err != nil { 182 | return false, err 183 | } 184 | } 185 | 186 | tx.Commit() 187 | 188 | return true, nil 189 | } 190 | 191 | func (a *Age) Close() error { 192 | return a.db.Close() 193 | } 194 | 195 | func (a *Age) DB() *sql.DB { 196 | return a.db 197 | } 198 | 199 | func (a *Age) Begin() (*AgeTx, error) { 200 | ageTx := &AgeTx{age: a} 201 | tx, err := a.db.Begin() 202 | if err != nil { 203 | return nil, err 204 | } 205 | ageTx.tx = tx 206 | return ageTx, err 207 | } 208 | 209 | func (t *AgeTx) Commit() error { 210 | return t.tx.Commit() 211 | } 212 | 213 | func (t *AgeTx) Rollback() error { 214 | return t.tx.Rollback() 215 | } 216 | 217 | /** CREATE , DROP .... */ 218 | func (a *AgeTx) ExecCypher(columnCount int, cypher string, args ...interface{}) (*CypherCursor, error) { 219 | return ExecCypher(a.tx, a.age.graphName, columnCount, cypher, args...) 220 | } 221 | 222 | type CypherCursor struct { 223 | Cursor 224 | columnCount int 225 | rows *sql.Rows 226 | unmarshaler Unmarshaller 227 | } 228 | 229 | func NewCypherCursor(columnCount int, rows *sql.Rows) Cursor { 230 | return &CypherCursor{columnCount: columnCount, rows: rows, unmarshaler: NewAGUnmarshaler()} 231 | } 232 | 233 | func (c *CypherCursor) Next() bool { 234 | return c.rows.Next() 235 | } 236 | 237 | func (c *CypherCursor) GetRow() ([]Entity, error) { 238 | var gstrs = make([]interface{}, c.columnCount) 239 | for i := 0; i < c.columnCount; i++ { 240 | gstrs[i] = new(sql.NullString) 241 | } 242 | 243 | err := c.rows.Scan(gstrs...) 244 | if err != nil { 245 | return nil, fmt.Errorf("CypherCursor.GetRow:: %s", err) 246 | } 247 | 248 | entArr := make([]Entity, c.columnCount) 249 | for i := 0; i < c.columnCount; i++ { 250 | gstr := gstrs[i].(*sql.NullString) 251 | if gstr.Valid { 252 | e, err := c.unmarshaler.unmarshal(gstr.String) 253 | if err != nil { 254 | fmt.Println(i, ">>", gstr) 255 | return nil, err 256 | } 257 | entArr[i] = e 258 | } else { 259 | entArr[i] = nil 260 | } 261 | } 262 | 263 | return entArr, nil 264 | } 265 | 266 | func (c *CypherCursor) Close() error { 267 | return c.rows.Close() 268 | } 269 | -------------------------------------------------------------------------------- /Question-3/Go/age/age_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package age 20 | 21 | import ( 22 | "fmt" 23 | "testing" 24 | 25 | "database/sql" 26 | 27 | _ "github.com/lib/pq" 28 | ) 29 | 30 | var dsn string = "host=127.0.0.1 port=5432 dbname=postgres user=postgres password=agens sslmode=disable" 31 | var graphName string = "testGraph" 32 | 33 | func TestAdditional(t *testing.T) { 34 | db, err := sql.Open("postgres", dsn) 35 | if err != nil { 36 | t.Fatal(err) 37 | } 38 | 39 | _, err = GetReady(db, graphName) 40 | if err != nil { 41 | t.Fatal(err) 42 | } 43 | 44 | cursor, err := db.Begin() 45 | if err != nil { 46 | t.Fatal(err) 47 | } 48 | 49 | _, err = ExecCypher(cursor, graphName, 0, "CREATE (n:Person {name: '%s', weight:%f})", "Joe", 67.3) 50 | if err != nil { 51 | t.Fatal(err) 52 | } 53 | 54 | _, err = ExecCypher(cursor, graphName, 0, "CREATE (n:Person {name: '%s', weight:77.3, roles:['Dev','marketing']})", "Jack") 55 | if err != nil { 56 | t.Fatal(err) 57 | } 58 | 59 | _, err = ExecCypher(cursor, graphName, 0, "CREATE (n:Person {name: '%s', weight:%d})", "Andy", 59) 60 | if err != nil { 61 | t.Fatal(err) 62 | } 63 | cursor.Commit() 64 | 65 | cursor, err = db.Begin() 66 | if err != nil { 67 | t.Fatal(err) 68 | } 69 | 70 | cypherCursor, err := ExecCypher(cursor, graphName, 1, "MATCH (n:Person) RETURN n") 71 | 72 | if err != nil { 73 | t.Fatal(err) 74 | } 75 | 76 | for cypherCursor.Next() { 77 | entities, err := cypherCursor.GetRow() 78 | if err != nil { 79 | t.Fatal(err) 80 | } 81 | vertex := entities[0].(*Vertex) 82 | fmt.Println(vertex.Id(), vertex.Label(), vertex.Props()) 83 | } 84 | 85 | _, err = ExecCypher(cursor, graphName, 0, "MATCH (a:Person), (b:Person) WHERE a.name='%s' AND b.name='%s' CREATE (a)-[r:workWith {weight: %d}]->(b)", 86 | "Jack", "Joe", 3) 87 | 88 | if err != nil { 89 | t.Fatal(err) 90 | } 91 | 92 | _, err = ExecCypher(cursor, graphName, 0, "MATCH (a:Person {name: '%s'}), (b:Person {name: '%s'}) CREATE (a)-[r:workWith {weight: %d}]->(b)", 93 | "Joe", "Andy", 7) 94 | if err != nil { 95 | t.Fatal(err) 96 | } 97 | 98 | cursor.Commit() 99 | 100 | cursor, err = db.Begin() 101 | if err != nil { 102 | t.Fatal(err) 103 | } 104 | 105 | cypherCursor, err = ExecCypher(cursor, graphName, 1, "MATCH p=()-[:workWith]-() RETURN p") 106 | if err != nil { 107 | t.Fatal(err) 108 | } 109 | 110 | for cypherCursor.Next() { 111 | entities, err := cypherCursor.GetRow() 112 | if err != nil { 113 | t.Fatal(err) 114 | } 115 | 116 | path := entities[0].(*Path) 117 | 118 | vertexStart := path.GetAsVertex(0) 119 | edge := path.GetAsEdge(1) 120 | vertexEnd := path.GetAsVertex(2) 121 | 122 | fmt.Println(vertexStart, edge, vertexEnd) 123 | } 124 | 125 | _, err = ExecCypher(cursor, graphName, 0, "MATCH (n:Person) DETACH DELETE n RETURN *") 126 | if err != nil { 127 | t.Fatal(err) 128 | } 129 | cursor.Commit() 130 | } 131 | 132 | func TestAgeWrapper(t *testing.T) { 133 | ag, err := ConnectAge(graphName, dsn) 134 | 135 | if err != nil { 136 | t.Fatal(err) 137 | } 138 | 139 | tx, err := ag.Begin() 140 | if err != nil { 141 | t.Fatal(err) 142 | } 143 | 144 | _, err = tx.ExecCypher(0, "CREATE (n:Person {name: '%s'})", "Joe") 145 | if err != nil { 146 | t.Fatal(err) 147 | } 148 | 149 | _, err = tx.ExecCypher(0, "CREATE (n:Person {name: '%s', age: %d})", "Smith", 10) 150 | if err != nil { 151 | t.Fatal(err) 152 | } 153 | 154 | _, err = tx.ExecCypher(0, "CREATE (n:Person {name: '%s', weight:%f})", "Jack", 70.3) 155 | if err != nil { 156 | t.Fatal(err) 157 | } 158 | 159 | tx.Commit() 160 | 161 | tx, err = ag.Begin() 162 | if err != nil { 163 | t.Fatal(err) 164 | } 165 | 166 | cursor, err := tx.ExecCypher(1, "MATCH (n:Person) RETURN n") 167 | if err != nil { 168 | t.Fatal(err) 169 | } 170 | 171 | count := 0 172 | for cursor.Next() { 173 | entities, err := cursor.GetRow() 174 | if err != nil { 175 | t.Fatal(err) 176 | } 177 | count++ 178 | vertex := entities[0].(*Vertex) 179 | fmt.Println(count, "]", vertex.Id(), vertex.Label(), vertex.Props()) 180 | } 181 | 182 | fmt.Println("Vertex Count:", count) 183 | 184 | _, err = tx.ExecCypher(0, "MATCH (a:Person), (b:Person) WHERE a.name='%s' AND b.name='%s' CREATE (a)-[r:workWith {weight: %d}]->(b)", 185 | "Jack", "Joe", 3) 186 | if err != nil { 187 | t.Fatal(err) 188 | } 189 | 190 | _, err = tx.ExecCypher(0, "MATCH (a:Person {name: '%s'}), (b:Person {name: '%s'}) CREATE (a)-[r:workWith {weight: %d}]->(b)", 191 | "Joe", "Smith", 7) 192 | if err != nil { 193 | t.Fatal(err) 194 | } 195 | 196 | tx.Commit() 197 | 198 | tx, err = ag.Begin() 199 | if err != nil { 200 | t.Fatal(err) 201 | } 202 | 203 | cursor, err = tx.ExecCypher(1, "MATCH p=()-[:workWith]-() RETURN p") 204 | if err != nil { 205 | t.Fatal(err) 206 | } 207 | 208 | count = 0 209 | for cursor.Next() { 210 | entities, err := cursor.GetRow() 211 | if err != nil { 212 | t.Fatal(err) 213 | } 214 | count++ 215 | path := entities[0].(*Path) 216 | 217 | fmt.Println(count, "]", path.GetAsVertex(0), path.GetAsEdge(1).props, path.GetAsVertex(2)) 218 | } 219 | 220 | _, err = tx.ExecCypher(0, "MATCH (n:Person) DETACH DELETE n RETURN *") 221 | if err != nil { 222 | t.Fatal(err) 223 | } 224 | tx.Commit() 225 | } 226 | 227 | func TestCudReturn(t *testing.T) { 228 | db, err := sql.Open("postgres", dsn) 229 | if err != nil { 230 | t.Fatal(err) 231 | } 232 | 233 | // Confirm graph_path created 234 | _, err = GetReady(db, graphName) 235 | if err != nil { 236 | t.Fatal(err) 237 | } 238 | 239 | // Tx begin for execute create vertex 240 | tx, err := db.Begin() 241 | 242 | if err != nil { 243 | t.Fatal(err) 244 | } 245 | 246 | // Create Vertex 247 | cursor, err := ExecCypher(tx, graphName, 1, "CREATE (n:Person {name: '%s'}) RETURN n", "Joe") 248 | 249 | if err != nil { 250 | t.Fatal(err) 251 | } 252 | 253 | for cursor.Next() { 254 | fmt.Println(cursor.GetRow()) 255 | } 256 | 257 | cursor, err = ExecCypher(tx, graphName, 1, "CREATE (n:Person {name: '%s', age: %d}) RETURN n", "Smith", 10) 258 | 259 | if err != nil { 260 | t.Fatal(err) 261 | } 262 | 263 | for cursor.Next() { 264 | fmt.Println(cursor.GetRow()) 265 | } 266 | 267 | cursor, err = ExecCypher(tx, graphName, 1, "CREATE (n:Person {name: '%s', weight:%f}) RETURN n", "Jack", 70.3) 268 | 269 | if err != nil { 270 | t.Fatal(err) 271 | } 272 | 273 | for cursor.Next() { 274 | fmt.Println(cursor.GetRow()) 275 | } 276 | 277 | tx.Commit() 278 | tx, err = db.Begin() 279 | if err != nil { 280 | t.Fatal(err) 281 | } 282 | 283 | cursor, err = ExecCypher(tx, graphName, 1, "MATCH (n:Person) RETURN n") 284 | 285 | if err != nil { 286 | t.Fatal(err) 287 | } 288 | 289 | for cursor.Next() { 290 | fmt.Println(cursor.GetRow()) 291 | } 292 | 293 | } 294 | 295 | func TestQueryManyReturn(t *testing.T) { 296 | ag, err := ConnectAge(graphName, dsn) 297 | 298 | if err != nil { 299 | t.Fatal(err) 300 | } 301 | 302 | tx, err := ag.Begin() 303 | if err != nil { 304 | t.Fatal(err) 305 | } 306 | 307 | // Create Vertex 308 | tx.ExecCypher(0, "CREATE (n:Person {name: '%s'})", "Joe") 309 | tx.ExecCypher(0, "CREATE (n:Person {name: '%s', age: %d})", "Smith", 10) 310 | tx.ExecCypher(0, "CREATE (n:Person {name: '%s', weight:%f})", "Jack", 70.3) 311 | 312 | tx.Commit() 313 | 314 | tx, err = ag.Begin() 315 | if err != nil { 316 | t.Fatal(err) 317 | } 318 | 319 | // Create Path 320 | tx.ExecCypher(0, "MATCH (a:Person), (b:Person) WHERE a.name='%s' AND b.name='%s' CREATE (a)-[r:workWith {weight: %d}]->(b)", 321 | "Jack", "Joe", 3) 322 | 323 | tx.ExecCypher(0, "MATCH (a:Person {name: '%s'}), (b:Person {name: '%s'}) CREATE (a)-[r:workWith {weight: %d}]->(b)", 324 | "Joe", "Smith", 7) 325 | 326 | tx.ExecCypher(0, "MATCH (a:Person {name: '%s'}), (b:Person {name: '%s'}) CREATE (a)-[r:workWith {weight: %d}]->(b)", 327 | "Jack", "Smith", 7) 328 | 329 | tx.ExecCypher(0, "MATCH (a:Person {name: '%s'}), (b:Person {name: '%s'}) CREATE (a)-[r:workWith {weight: %d}]->(b)", 330 | "Jack", "Andy", 7) 331 | 332 | tx.Commit() 333 | 334 | if err != nil { 335 | t.Fatal(err) 336 | } 337 | 338 | tx, err = ag.Begin() 339 | if err != nil { 340 | t.Fatal(err) 341 | } 342 | // Query Path1 343 | cursor, err := tx.ExecCypher(3, "MATCH (a:Person)-[l:workWith]-(b:Person) RETURN a, l, b") 344 | if err != nil { 345 | t.Fatal(err) 346 | } 347 | 348 | count := 0 349 | for cursor.Next() { 350 | entities, err := cursor.GetRow() 351 | if err != nil { 352 | t.Fatal(err) 353 | } 354 | count++ 355 | v1 := entities[0].(*Vertex) 356 | edge := entities[1].(*Edge) 357 | v2 := entities[2].(*Vertex) 358 | fmt.Println("ROW ", count, ">>", "\n\t", v1, "\n\t", edge, "\n\t", v2) 359 | } 360 | 361 | // Query Path2 362 | cursor, err = tx.ExecCypher(1, "MATCH p=(a:Person)-[l:workWith]-(b:Person) WHERE a.name = '%s' RETURN p", "Joe") 363 | if err != nil { 364 | t.Fatal(err) 365 | } 366 | 367 | count = 0 368 | for cursor.Next() { 369 | entities, err := cursor.GetRow() 370 | if err != nil { 371 | t.Fatal(err) 372 | } 373 | count++ 374 | path := entities[0].(*Path) 375 | fmt.Println("ROW ", count, ">>", "\n\t", path.GetAsVertex(0), 376 | "\n\t", path.GetAsEdge(1), 377 | "\n\t", path.GetAsVertex(2)) 378 | } 379 | 380 | // Clear Data 381 | _, err = tx.ExecCypher(0, "MATCH (n:Person) DETACH DELETE n RETURN *") 382 | if err != nil { 383 | t.Fatal(err) 384 | } 385 | 386 | tx.Commit() 387 | 388 | if err != nil { 389 | t.Fatal(err) 390 | } 391 | 392 | } 393 | 394 | func TestCollect(t *testing.T) { 395 | ag, err := ConnectAge(graphName, dsn) 396 | 397 | if err != nil { 398 | t.Fatal(err) 399 | } 400 | 401 | tx, err := ag.Begin() 402 | if err != nil { 403 | t.Fatal(err) 404 | } 405 | 406 | // Create Vertex 407 | tx.ExecCypher(0, "CREATE (n:Person {name: '%s'})", "Joe") 408 | tx.ExecCypher(0, "CREATE (n:Person {name: '%s', age: %d})", "Smith", 10) 409 | tx.ExecCypher(0, "CREATE (n:Person {name: '%s', weight:%f})", "Jack", 70.3) 410 | tx.ExecCypher(0, "CREATE (n:Person {name: '%s', weight:%f})", "Andy", 70.3) 411 | 412 | tx.Commit() 413 | 414 | tx, err = ag.Begin() 415 | if err != nil { 416 | t.Fatal(err) 417 | } 418 | 419 | // Create Path 420 | tx.ExecCypher(0, "MATCH (a:Person), (b:Person) WHERE a.name='%s' AND b.name='%s' CREATE (a)-[r:workWith {weight: %d}]->(b)", 421 | "Jack", "Joe", 3) 422 | 423 | tx.ExecCypher(0, "MATCH (a:Person {name: '%s'}), (b:Person {name: '%s'}) CREATE (a)-[r:workWith {weight: %d}]->(b)", 424 | "Jack", "Smith", 7) 425 | 426 | tx.ExecCypher(0, "MATCH (a:Person {name: '%s'}), (b:Person {name: '%s'}) CREATE (a)-[r:workWith {weight: %d}]->(b)", 427 | "Jack", "Andy", 7) 428 | 429 | tx.Commit() 430 | 431 | tx, err = ag.Begin() 432 | if err != nil { 433 | t.Fatal(err) 434 | } 435 | 436 | cursor, err := tx.ExecCypher(2, "MATCH (a)-[:workWith]->(c) WITH a as V, COLLECT(c) as CV RETURN V.name, CV") 437 | 438 | if err != nil { 439 | t.Fatal(err) 440 | } 441 | for cursor.Next() { 442 | entities, err := cursor.GetRow() 443 | if err != nil { 444 | t.Fatal(err) 445 | } 446 | 447 | name := entities[0].String() 448 | vertices := entities[1].(*SimpleEntity).AsArr() 449 | fmt.Println(name, ">>") 450 | for idx, v := range vertices { 451 | fmt.Println("\t", idx, v) 452 | } 453 | 454 | } 455 | 456 | // Clear Data 457 | _, err = tx.ExecCypher(0, "MATCH (n:Person) DETACH DELETE n RETURN *") 458 | if err != nil { 459 | t.Fatal(err) 460 | } 461 | 462 | tx.Commit() 463 | 464 | if err != nil { 465 | t.Fatal(err) 466 | } 467 | 468 | } 469 | -------------------------------------------------------------------------------- /Question-3/Go/age/builder.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package age 20 | 21 | import ( 22 | "fmt" 23 | "math" 24 | "math/big" 25 | "strconv" 26 | "strings" 27 | 28 | "github.com/antlr/antlr4/runtime/Go/antlr" 29 | "github.com/DS-Popeye/Apache-Internship-Program/Question-3/Go/parser" 30 | 31 | ) 32 | 33 | const MaxUint = ^uint(0) 34 | const MaxInt = int(MaxUint >> 1) 35 | const MinUint = 0 36 | const MinInt = -MaxInt - 1 37 | 38 | type Unmarshaller interface { 39 | unmarshal(text string) (Entity, error) 40 | } 41 | 42 | type AGUnmarshaler struct { 43 | Unmarshaller 44 | ageParser *parser.AgtypeParser 45 | visitor parser.AgtypeVisitor 46 | errListener *AGErrorListener 47 | vcache map[int64]interface{} 48 | } 49 | 50 | func NewAGUnmarshaler() *AGUnmarshaler { 51 | vcache := make(map[int64]interface{}) 52 | 53 | m := &AGUnmarshaler{ageParser: parser.NewAgtypeParser(nil), 54 | visitor: &UnmarshalVisitor{vcache: vcache}, 55 | errListener: NewAGErrorListener(), 56 | vcache: vcache, 57 | } 58 | m.ageParser.AddErrorListener(m.errListener) 59 | 60 | return m 61 | } 62 | 63 | func (p *AGUnmarshaler) unmarshal(text string) (Entity, error) { 64 | if len(text) == 0 { 65 | return NewSimpleEntity(nil), nil 66 | } 67 | input := antlr.NewInputStream(text) 68 | lexer := parser.NewAgtypeLexer(input) 69 | stream := antlr.NewCommonTokenStream(lexer, 0) 70 | p.ageParser.SetInputStream(stream) 71 | tree := p.ageParser.AgType() 72 | rst := tree.Accept(p.visitor) 73 | 74 | if len(p.errListener.errList) > 0 { 75 | var ape *AgeParseError = nil 76 | errs := make([]string, len(p.errListener.errList)) 77 | for idx, re := range p.errListener.errList { 78 | errs[idx] = re.GetMessage() 79 | fmt.Println(re) 80 | } 81 | p.errListener.ClearErrs() 82 | 83 | ape = &AgeParseError{msg: "Cypher query:" + text, errors: errs} 84 | 85 | return nil, ape 86 | } 87 | 88 | if !IsEntity(rst) { 89 | rst = NewSimpleEntity(rst) 90 | } 91 | 92 | return rst.(Entity), nil 93 | } 94 | 95 | type AGErrorListener struct { 96 | *antlr.DefaultErrorListener 97 | errList []antlr.RecognitionException 98 | } 99 | 100 | func NewAGErrorListener() *AGErrorListener { 101 | return &AGErrorListener{DefaultErrorListener: &antlr.DefaultErrorListener{}, errList: []antlr.RecognitionException{}} 102 | } 103 | 104 | func (el *AGErrorListener) SyntaxError(recognizer antlr.Recognizer, offendingSymbol interface{}, line, column int, msg string, e antlr.RecognitionException) { 105 | el.errList = append(el.errList, e) 106 | } 107 | 108 | func (el *AGErrorListener) GetErrs() []antlr.RecognitionException { 109 | return el.errList 110 | } 111 | func (el *AGErrorListener) ClearErrs() { 112 | el.errList = []antlr.RecognitionException{} 113 | } 114 | 115 | type UnmarshalVisitor struct { 116 | parser.AgtypeVisitor 117 | vcache map[int64]interface{} 118 | } 119 | 120 | func (v *UnmarshalVisitor) Visit(tree antlr.ParseTree) interface{} { return nil } 121 | 122 | func (v *UnmarshalVisitor) VisitChildren(node antlr.RuleNode) interface{} { 123 | var rtn interface{} 124 | for _, c := range node.GetChildren() { 125 | pt := c.(antlr.ParseTree) 126 | rtn = pt.Accept(v) 127 | } 128 | return rtn 129 | } 130 | 131 | func (v *UnmarshalVisitor) VisitTerminal(node antlr.TerminalNode) interface{} { return nil } 132 | func (v *UnmarshalVisitor) VisitErrorNode(node antlr.ErrorNode) interface{} { return nil } 133 | func (v *UnmarshalVisitor) VisitAgType(ctx *parser.AgTypeContext) interface{} { 134 | agv := ctx.AgValue() 135 | if agv != nil { 136 | return agv.Accept(v) 137 | } 138 | return nil 139 | } 140 | 141 | func (v *UnmarshalVisitor) VisitAgValue(ctx *parser.AgValueContext) interface{} { 142 | annoCtx := ctx.TypeAnnotation() 143 | valueCtx := ctx.Value() 144 | 145 | if annoCtx != nil { 146 | annoStr := annoCtx.(*parser.TypeAnnotationContext).IDENT().GetText() 147 | value, err := v.handleAnnotatedValue(annoStr, valueCtx) 148 | if err != nil { 149 | panic(err) 150 | } 151 | 152 | return value 153 | } else { 154 | return valueCtx.Accept(v) 155 | } 156 | } 157 | 158 | // Visit a parse tree produced by AgtypeParser#value. 159 | func (v *UnmarshalVisitor) VisitValue(ctx *parser.ValueContext) interface{} { 160 | rtn := v.VisitChildren(ctx) 161 | return rtn 162 | } 163 | 164 | func (v *UnmarshalVisitor) handleAnnotatedValue(anno string, ctx antlr.ParserRuleContext) (interface{}, error) { 165 | if anno == "numeric" { 166 | numStr := ctx.GetText() 167 | if strings.Contains(numStr, ".") { 168 | bi := new(big.Float) 169 | bi, ok := bi.SetString(numStr) 170 | if !ok { 171 | return nil, &AgeParseError{msg: "Parse big float " + numStr} 172 | } 173 | return bi, nil 174 | } else { 175 | bi := new(big.Int) 176 | bi, ok := bi.SetString(numStr, 10) 177 | if !ok { 178 | return nil, &AgeParseError{msg: "Parse big int " + numStr} 179 | } 180 | return bi, nil 181 | } 182 | } else if anno == "vertex" { 183 | dict := ctx.Accept(v).(map[string]interface{}) 184 | vid, ok := dict["id"].(int64) 185 | if !ok { 186 | return nil, &AgeParseError{msg: "Vertex id is nil. "} 187 | } 188 | vertex, ok := v.vcache[vid].(*Vertex) 189 | 190 | if !ok { 191 | vertex = NewVertex(vid, dict["label"].(string), dict["properties"].(map[string]interface{})) 192 | v.vcache[vid] = vertex 193 | } 194 | 195 | return vertex, nil 196 | } else if anno == "edge" { 197 | dict := ctx.Accept(v).(map[string]interface{}) 198 | edge := NewEdge(int64(dict["id"].(int64)), dict["label"].(string), 199 | int64(dict["start_id"].(int64)), int64(dict["end_id"].(int64)), 200 | dict["properties"].(map[string]interface{})) 201 | 202 | return edge, nil 203 | } else if anno == "path" { 204 | arr := ctx.Accept(v).([]interface{}) 205 | entities := []Entity{} 206 | 207 | for _, child := range arr { 208 | switch child.(type) { 209 | case *Vertex: 210 | entities = append(entities, child.(Entity)) 211 | case *Edge: 212 | entities = append(entities, child.(Entity)) 213 | default: 214 | } 215 | } 216 | 217 | path := NewPath(entities) 218 | return path, nil 219 | } 220 | return ctx.Accept(v), nil 221 | } 222 | 223 | func (v *UnmarshalVisitor) VisitStringValue(ctx *parser.StringValueContext) interface{} { 224 | txt := ctx.GetText() 225 | return strings.Trim(txt, "\"") 226 | } 227 | 228 | func (v *UnmarshalVisitor) VisitIntegerValue(ctx *parser.IntegerValueContext) interface{} { 229 | val, err := strconv.ParseInt(ctx.INTEGER().GetText(), 10, 64) 230 | if err != nil { 231 | panic(err) 232 | } 233 | return val 234 | } 235 | 236 | // Visit a parse tree produced by AgtypeParser#FloatValue. 237 | func (v *UnmarshalVisitor) VisitFloatValue(ctx *parser.FloatValueContext) interface{} { 238 | fCtx := ctx.GetChild(0).(*parser.FloatLiteralContext) 239 | return fCtx.Accept(v) 240 | } 241 | 242 | func (v *UnmarshalVisitor) VisitFloatLiteral(ctx *parser.FloatLiteralContext) interface{} { 243 | c := ctx.GetChild(0) 244 | text := ctx.GetText() 245 | tokenType := c.(antlr.TerminalNode).GetSymbol().GetTokenType() 246 | 247 | switch tokenType { 248 | case parser.AgtypeParserRegularFloat: 249 | val, err := strconv.ParseFloat(text, 64) 250 | if err != nil { 251 | panic(err) 252 | } 253 | return val 254 | case parser.AgtypeParserExponentFloat: 255 | val, err := strconv.ParseFloat(text, 64) 256 | if err != nil { 257 | panic(err) 258 | } 259 | return val 260 | default: 261 | switch text { 262 | case "NaN": 263 | return math.NaN() 264 | case "-Infinity": 265 | return math.Inf(-1) 266 | case "Infinity": 267 | return math.Inf(1) 268 | default: 269 | panic(&AgeParseError{msg: "Unknown float expression:" + text}) 270 | } 271 | } 272 | } 273 | 274 | func (v *UnmarshalVisitor) VisitTrueBoolean(ctx *parser.TrueBooleanContext) interface{} { 275 | return true 276 | } 277 | 278 | func (v *UnmarshalVisitor) VisitFalseBoolean(ctx *parser.FalseBooleanContext) interface{} { 279 | return false 280 | } 281 | 282 | func (v *UnmarshalVisitor) VisitNullValue(ctx *parser.NullValueContext) interface{} { 283 | return nil 284 | } 285 | 286 | // Visit a parse tree produced by AgtypeParser#ObjectValue. 287 | func (v *UnmarshalVisitor) VisitObjectValue(ctx *parser.ObjectValueContext) interface{} { 288 | objCtx := ctx.GetChild(0).(*parser.ObjContext) 289 | return objCtx.Accept(v) 290 | } 291 | 292 | func (v *UnmarshalVisitor) VisitObj(ctx *parser.ObjContext) interface{} { 293 | props := make(map[string]interface{}) 294 | for _, pairCtx := range ctx.AllPair() { 295 | pairCtx.Accept(v) 296 | pair := pairCtx.(*parser.PairContext) 297 | key := strings.Trim(pair.STRING().GetText(), "\"") 298 | value := pair.AgValue().Accept(v) 299 | props[key] = value 300 | } 301 | 302 | return props 303 | } 304 | 305 | func (v *UnmarshalVisitor) VisitPair(ctx *parser.PairContext) interface{} { 306 | return nil 307 | } 308 | 309 | func (v *UnmarshalVisitor) VisitArrayValue(ctx *parser.ArrayValueContext) interface{} { 310 | arrCtx := ctx.GetChild(0).(*parser.ArrayContext) 311 | return arrCtx.Accept(v) 312 | } 313 | 314 | // Visit a parse tree produced by AgtypeParser#array. 315 | func (v *UnmarshalVisitor) VisitArray(ctx *parser.ArrayContext) interface{} { 316 | var arr []interface{} 317 | for _, child := range ctx.GetChildren() { 318 | switch child.(type) { 319 | case *antlr.TerminalNodeImpl: 320 | // skip 321 | break 322 | default: 323 | el := child.(antlr.ParserRuleContext).Accept(v) 324 | arr = append(arr, el) 325 | } 326 | } 327 | return arr 328 | } 329 | 330 | /* 331 | 332 | # Visit a parse tree produced by AgtypeParser#TrueBoolean. 333 | def visitTrueBoolean(self, ctx:AgtypeParser.TrueBooleanContext): 334 | return True 335 | 336 | 337 | # Visit a parse tree produced by AgtypeParser#FalseBoolean. 338 | def visitFalseBoolean(self, ctx:AgtypeParser.FalseBooleanContext): 339 | return False 340 | 341 | 342 | # Visit a parse tree produced by AgtypeParser#NullValue. 343 | def visitNullValue(self, ctx:AgtypeParser.NullValueContext): 344 | return None 345 | 346 | 347 | # Visit a parse tree produced by AgtypeParser#obj. 348 | def visitObj(self, ctx:AgtypeParser.ObjContext): 349 | obj = dict() 350 | for c in ctx.getChildren(): 351 | if isinstance(c, AgtypeParser.PairContext): 352 | namVal = self.visitPair(c) 353 | name = namVal[0] 354 | valCtx = namVal[1] 355 | val = valCtx.accept(self) 356 | obj[name] = val 357 | return obj 358 | 359 | 360 | # Visit a parse tree produced by AgtypeParser#pair. 361 | def visitPair(self, ctx:AgtypeParser.PairContext): 362 | self.visitChildren(ctx) 363 | return (ctx.STRING().getText().strip('"') , ctx.agValue()) 364 | 365 | 366 | # Visit a parse tree produced by AgtypeParser#array. 367 | def visitArray(self, ctx:AgtypeParser.ArrayContext): 368 | li = list() 369 | for c in ctx.getChildren(): 370 | if not isinstance(c, TerminalNode): 371 | val = c.accept(self) 372 | li.append(val) 373 | return li 374 | 375 | */ 376 | -------------------------------------------------------------------------------- /Question-3/Go/age/builder_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package age 20 | 21 | import ( 22 | "fmt" 23 | "math" 24 | "math/big" 25 | "testing" 26 | 27 | "github.com/stretchr/testify/assert" 28 | ) 29 | 30 | func TestPathParsing(t *testing.T) { 31 | rstStr1 := `[{"id": 2251799813685425, "label": "Person", "properties": {"name": "Smith"}}::vertex, 32 | {"id": 2533274790396576, "label": "workWith", "end_id": 2251799813685425, "start_id": 2251799813685424, 33 | "properties": {"weight": 3, "bigFloat":123456789123456789123456789.12345::numeric}}::edge, 34 | {"id": 2251799813685424, "label": "Person", "properties": {"name": "Joe"}}::vertex]::path` 35 | 36 | rstStr2 := `[{"id": 2251799813685424, "label": "Person", "properties": {"name": "Joe"}}::vertex, 37 | {"id": 2533274790396576, "label": "workWith", "end_id": 2251799813685425, "start_id": 2251799813685424, "properties": {"weight": 3}}::edge, 38 | {"id": 2251799813685425, "label": "Person", "properties": {"name": "Smith"}}::vertex]::path` 39 | 40 | rstStr3 := `[{"id": 2251799813685424, "label": "Person", "properties": {"name": "Joe"}}::vertex, 41 | {"id": 2533274790396579, "label": "workWith", "end_id": 2251799813685426, "start_id": 2251799813685424, "properties": {"weight": 5}}::edge, 42 | {"id": 2251799813685426, "label": "Person", "properties": {"name": "Jack", "arrVal":["A","B"]}}::vertex]::path` 43 | 44 | unmarshaler := NewAGUnmarshaler() 45 | entity1, _ := unmarshaler.unmarshal(rstStr1) 46 | entity2, _ := unmarshaler.unmarshal(rstStr2) 47 | entity3, _ := unmarshaler.unmarshal(rstStr3) 48 | 49 | assert.Equal(t, entity1.GType(), entity2.GType(), "Type Check") 50 | p1 := entity1.(*Path) 51 | p2 := entity2.(*Path) 52 | p3 := entity3.(*Path) 53 | 54 | assert.Equal(t, p1.GetAsVertex(0).props["name"], p2.GetAsVertex(2).props["name"]) 55 | assert.Equal(t, p2.GetAsVertex(0).props["name"], p3.GetAsVertex(0).props["name"]) 56 | 57 | bf := new(big.Float) 58 | bf, _ = bf.SetString("123456789123456789123456789.12345") 59 | 60 | bigFloat := p1.GetAsEdge(1).props["bigFloat"] 61 | 62 | assert.Equal(t, bf, bigFloat) 63 | 64 | fmt.Println(entity1) 65 | fmt.Println(entity2) 66 | fmt.Println(entity3) 67 | } 68 | 69 | func TestVertexParsing(t *testing.T) { 70 | rstStr := `{"id": 2251799813685425, "label": "Person", 71 | "properties": {"name": "Smith", "numInt":123, "numIntBig":12345678901235555555555555555::numeric, "numFloat": 384.23424, 72 | "yn":true, "nullVal": null}}::vertex` 73 | 74 | unmarshaler := NewAGUnmarshaler() 75 | entity, _ := unmarshaler.unmarshal(rstStr) 76 | 77 | // fmt.Println(entity) 78 | assert.Equal(t, G_VERTEX, entity.GType()) 79 | 80 | v := entity.(*Vertex) 81 | assert.Equal(t, "Smith", v.props["name"]) 82 | assert.True(t, (int64(123) == v.props["numInt"])) 83 | assert.Equal(t, int64(123), v.props["numInt"]) 84 | 85 | bi := new(big.Int) 86 | bi, ok := bi.SetString("12345678901235555555555555555", 10) 87 | if !ok { 88 | fmt.Println("Cannot reach this line. ") 89 | } 90 | assert.Equal(t, bi, v.props["numIntBig"]) 91 | 92 | assert.True(t, (384.23424 == v.props["numFloat"])) 93 | assert.Equal(t, float64(384.23424), v.props["numFloat"]) 94 | assert.Equal(t, true, v.props["yn"]) 95 | assert.Nil(t, v.props["nullVal"]) 96 | } 97 | 98 | func TestNormalValueParsing(t *testing.T) { 99 | mapStr := `{"name": "Smith", "num":123, "yn":true}` 100 | arrStr := `["name", "Smith", "num", 123, "yn", true]` 101 | strStr := `"abcd"` 102 | intStr := `1234` 103 | floatStr := `1234.56789` 104 | floatStr2 := `6.45161290322581e+46` 105 | numericStr1 := `12345678901234567890123456.789::numeric` 106 | numericStr2 := `12345678901234567890123456::numeric` 107 | boolStr := `true` 108 | nullStr := "" 109 | nanStr := "NaN" 110 | infpStr := "Infinity" 111 | infnStr := "-Infinity" 112 | 113 | unmarshaler := NewAGUnmarshaler() 114 | mapv, _ := unmarshaler.unmarshal(mapStr) 115 | arrv, _ := unmarshaler.unmarshal(arrStr) 116 | str2, _ := unmarshaler.unmarshal(strStr) 117 | intv, _ := unmarshaler.unmarshal(intStr) 118 | fl, _ := unmarshaler.unmarshal(floatStr) 119 | fl2, _ := unmarshaler.unmarshal(floatStr2) 120 | numeric1, _ := unmarshaler.unmarshal(numericStr1) 121 | numeric2, _ := unmarshaler.unmarshal(numericStr2) 122 | b, _ := unmarshaler.unmarshal(boolStr) 123 | nullVal, _ := unmarshaler.unmarshal(nullStr) 124 | nanVal, _ := unmarshaler.unmarshal(nanStr) 125 | infpVal, _ := unmarshaler.unmarshal(infpStr) 126 | infnVal, _ := unmarshaler.unmarshal(infnStr) 127 | 128 | // fmt.Println("intv", intv.GType(), reflect.TypeOf(intv.(*SimpleEntity).Value()), intv) 129 | assert.Equal(t, G_MAP, mapv.GType()) 130 | assert.Equal(t, G_ARR, arrv.GType()) 131 | assert.Equal(t, G_STR, str2.GType()) 132 | assert.Equal(t, G_INT, intv.GType()) 133 | assert.Equal(t, G_FLOAT, fl.GType()) 134 | assert.Equal(t, G_FLOAT, fl2.GType()) 135 | assert.Equal(t, G_FLOATBIG, numeric1.GType()) 136 | assert.Equal(t, G_INTBIG, numeric2.GType()) 137 | assert.Equal(t, G_BOOL, b.GType()) 138 | assert.Equal(t, G_NULL, nullVal.GType()) 139 | assert.Equal(t, G_FLOAT, nanVal.GType()) 140 | assert.Equal(t, G_FLOAT, infpVal.GType()) 141 | assert.Equal(t, G_FLOAT, infnVal.GType()) 142 | 143 | assert.Equal(t, map[string]interface{}{"name": "Smith", "num": int64(123), "yn": true}, mapv.(*SimpleEntity).Value()) 144 | assert.Equal(t, []interface{}{"name", "Smith", "num", int64(123), "yn", true}, arrv.(*SimpleEntity).Value()) 145 | assert.Equal(t, "abcd", str2.(*SimpleEntity).Value()) 146 | assert.Equal(t, int64(1234), intv.(*SimpleEntity).Value()) 147 | assert.Equal(t, 1234.56789, fl.(*SimpleEntity).Value()) 148 | assert.Equal(t, 6.45161290322581e+46, fl2.(*SimpleEntity).Value()) 149 | assert.Equal(t, true, b.(*SimpleEntity).Value()) 150 | assert.Equal(t, nil, nullVal.(*SimpleEntity).Value()) 151 | assert.True(t, math.IsNaN(nanVal.(*SimpleEntity).Value().(float64))) 152 | assert.Equal(t, math.Inf(1), infpVal.(*SimpleEntity).Value()) 153 | assert.Equal(t, math.Inf(-1), infnVal.(*SimpleEntity).Value()) 154 | 155 | bf := new(big.Float) 156 | bf, _ = bf.SetString("12345678901234567890123456.789") 157 | 158 | assert.Equal(t, bf, numeric1.(*SimpleEntity).Value()) 159 | 160 | bi := new(big.Int) 161 | bi, _ = bi.SetString("12345678901234567890123456", 10) 162 | 163 | assert.Equal(t, bi, numeric2.(*SimpleEntity).Value()) 164 | } 165 | 166 | func TestMap(t *testing.T) { 167 | mapStr := `{"name": "Smith", "num":123, "yn":true, "arr":["A","B",1], "map":{"a":1, "b":"bv"}}` 168 | 169 | unmarshaler := NewAGUnmarshaler() 170 | mapv, _ := unmarshaler.unmarshal(mapStr) 171 | assert.Equal(t, G_MAP, mapv.GType()) 172 | 173 | mapValue := mapv.(*SimpleEntity).Value().(map[string]interface{}) 174 | 175 | assert.Equal(t, "Smith", mapValue["name"]) 176 | assert.Equal(t, []interface{}{"A", "B", int64(1)}, mapValue["arr"]) 177 | assert.Equal(t, map[string]interface{}{"a": int64(1), "b": "bv"}, mapValue["map"]) 178 | } 179 | 180 | func TestArray(t *testing.T) { 181 | arrayStr := `[ "Smith", 123, true, ["A","B",1], {"a":1, "b":"bv"}]` 182 | 183 | unmarshaler := NewAGUnmarshaler() 184 | arrayv, _ := unmarshaler.unmarshal(arrayStr) 185 | assert.Equal(t, G_ARR, arrayv.GType()) 186 | 187 | arrValue := arrayv.(*SimpleEntity).Value().([]interface{}) 188 | 189 | assert.Equal(t, "Smith", arrValue[0]) 190 | assert.Equal(t, []interface{}{"A", "B", int64(1)}, arrValue[3]) 191 | assert.Equal(t, map[string]interface{}{"a": int64(1), "b": "bv"}, arrValue[4]) 192 | } 193 | -------------------------------------------------------------------------------- /Question-3/Go/age/errors.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package age 20 | 21 | import ( 22 | "bytes" 23 | "fmt" 24 | ) 25 | 26 | type AgeError struct { 27 | cause error 28 | msg string 29 | } 30 | 31 | func (e *AgeError) Error() string { 32 | if e.cause != nil { 33 | return fmt.Sprintf("%s >> Cause:%s", e.msg, e.cause.Error()) 34 | } 35 | return e.msg 36 | } 37 | 38 | type AgeParseError struct { 39 | msg string 40 | errors []string 41 | } 42 | 43 | func (e *AgeParseError) Error() string { 44 | var buf bytes.Buffer 45 | buf.WriteString(e.msg) 46 | buf.WriteString(" >> Causes:\n") 47 | for _, err := range e.errors { 48 | buf.WriteString(err) 49 | buf.WriteString("\n") 50 | } 51 | return buf.String() 52 | } 53 | -------------------------------------------------------------------------------- /Question-3/Go/age/models.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package age 20 | 21 | import ( 22 | "bytes" 23 | "fmt" 24 | "math/big" 25 | "reflect" 26 | ) 27 | 28 | // GTYPE representing entity types for AGE result data : Vertex, Edge, Path and SimpleEntity 29 | type GTYPE uint8 30 | 31 | const ( 32 | G_OTHER GTYPE = 1 + iota 33 | G_VERTEX 34 | G_EDGE 35 | G_PATH 36 | G_MAP_PATH 37 | G_STR 38 | G_INT 39 | G_INTBIG 40 | G_FLOAT 41 | G_FLOATBIG 42 | G_BOOL 43 | G_NULL 44 | G_MAP 45 | G_ARR 46 | ) 47 | 48 | var _TpV = reflect.TypeOf(&Vertex{}) 49 | var _TpE = reflect.TypeOf(&Edge{}) 50 | var _TpP = reflect.TypeOf(&Path{}) 51 | var _TpMP = reflect.TypeOf(&MapPath{}) 52 | var _TpStr = reflect.TypeOf(string("")) 53 | var _TpInt = reflect.TypeOf(int64(0)) 54 | var _TpIntBig = reflect.TypeOf(big.NewInt(0)) 55 | var _TpFloat = reflect.TypeOf(float64(0)) 56 | var _TpFloatBig = reflect.TypeOf(big.NewFloat(0)) 57 | var _TpBool = reflect.TypeOf(bool(false)) 58 | var _TpMap = reflect.TypeOf(map[string]interface{}{}) 59 | var _TpArr = reflect.TypeOf([]interface{}{}) 60 | 61 | // Entity object interface for parsed AGE result data : Vertex, Edge, Path and SimpleEntity 62 | type Entity interface { 63 | GType() GTYPE 64 | String() string 65 | } 66 | 67 | func IsEntity(v interface{}) bool { 68 | _, ok := v.(Entity) 69 | return ok 70 | } 71 | 72 | type SimpleEntity struct { 73 | Entity 74 | typ GTYPE 75 | value interface{} 76 | } 77 | 78 | func NewSimpleEntity(value interface{}) *SimpleEntity { 79 | if value == nil { 80 | return &SimpleEntity{typ: G_NULL, value: nil} 81 | } 82 | 83 | switch value.(type) { 84 | case string: 85 | return &SimpleEntity{typ: G_STR, value: value} 86 | case int64: 87 | return &SimpleEntity{typ: G_INT, value: value} 88 | case *big.Int: 89 | return &SimpleEntity{typ: G_INTBIG, value: value} 90 | case float64: 91 | return &SimpleEntity{typ: G_FLOAT, value: value} 92 | case *big.Float: 93 | return &SimpleEntity{typ: G_FLOATBIG, value: value} 94 | case bool: 95 | return &SimpleEntity{typ: G_BOOL, value: value} 96 | case map[string]interface{}: 97 | return &SimpleEntity{typ: G_MAP, value: value} 98 | case []interface{}: 99 | return &SimpleEntity{typ: G_ARR, value: value} 100 | default: 101 | return &SimpleEntity{typ: G_OTHER, value: value} 102 | } 103 | } 104 | 105 | func (e *SimpleEntity) GType() GTYPE { 106 | return e.typ 107 | } 108 | 109 | func (e *SimpleEntity) IsNull() bool { 110 | return e.value == nil 111 | } 112 | 113 | func (e *SimpleEntity) Value() interface{} { 114 | return e.value 115 | } 116 | 117 | func (e *SimpleEntity) String() string { 118 | return fmt.Sprintf("%v", e.value) 119 | } 120 | 121 | func (e *SimpleEntity) AsStr() string { 122 | return e.value.(string) 123 | } 124 | 125 | func (e *SimpleEntity) AsInt() int { 126 | return e.value.(int) 127 | } 128 | 129 | func (e *SimpleEntity) AsInt64() int64 { 130 | return e.value.(int64) 131 | } 132 | 133 | func (e *SimpleEntity) AsBigInt() *big.Int { 134 | return e.value.(*big.Int) 135 | } 136 | 137 | func (e *SimpleEntity) AsFloat() float64 { 138 | return e.value.(float64) 139 | } 140 | 141 | func (e *SimpleEntity) AsBigFloat() *big.Float { 142 | return e.value.(*big.Float) 143 | } 144 | 145 | func (e *SimpleEntity) AsBool() bool { 146 | return e.value.(bool) 147 | } 148 | 149 | func (e *SimpleEntity) AsMap() map[string]interface{} { 150 | return e.value.(map[string]interface{}) 151 | } 152 | 153 | func (e *SimpleEntity) AsArr() []interface{} { 154 | return e.value.([]interface{}) 155 | } 156 | 157 | type LabeledEntity struct { 158 | Entity 159 | id int64 160 | label string 161 | props map[string]interface{} 162 | } 163 | 164 | func newLabeledEntity(id int64, label string, props map[string]interface{}) *LabeledEntity { 165 | return &LabeledEntity{id: id, label: label, props: props} 166 | } 167 | 168 | func (n *LabeledEntity) Id() int64 { 169 | return n.id 170 | } 171 | 172 | func (n *LabeledEntity) Label() string { 173 | return n.label 174 | } 175 | 176 | func (n *LabeledEntity) Prop(key string) interface{} { 177 | return n.props[key] 178 | } 179 | 180 | // return properties 181 | func (n *LabeledEntity) Props() map[string]interface{} { 182 | return n.props 183 | } 184 | 185 | type Vertex struct { 186 | *LabeledEntity 187 | } 188 | 189 | func NewVertex(id int64, label string, props map[string]interface{}) *Vertex { 190 | return &Vertex{newLabeledEntity(id, label, props)} 191 | } 192 | 193 | func (v *Vertex) GType() GTYPE { 194 | return G_VERTEX 195 | } 196 | 197 | func (v *Vertex) String() string { 198 | return fmt.Sprintf("V{id:%d, label:%s, props:%v}", v.id, v.label, v.props) 199 | } 200 | 201 | type Edge struct { 202 | *LabeledEntity 203 | start_id int64 204 | end_id int64 205 | } 206 | 207 | func NewEdge(id int64, label string, start int64, end int64, props map[string]interface{}) *Edge { 208 | return &Edge{LabeledEntity: newLabeledEntity(id, label, props), start_id: start, end_id: end} 209 | } 210 | 211 | func (e *Edge) GType() GTYPE { 212 | return G_EDGE 213 | } 214 | 215 | func (e *Edge) StartId() int64 { 216 | return e.start_id 217 | } 218 | 219 | func (e *Edge) EndId() int64 { 220 | return e.end_id 221 | } 222 | 223 | func (e *Edge) String() string { 224 | return fmt.Sprintf("E{id:%d, label:%s, start:%d, end:%d, props:%v}", 225 | e.id, e.label, e.start_id, e.end_id, e.props) 226 | } 227 | 228 | type Path struct { 229 | Entity 230 | entities []Entity 231 | } 232 | 233 | func NewPath(entities []Entity) *Path { 234 | return &Path{entities: entities} 235 | } 236 | 237 | func (e *Path) GType() GTYPE { 238 | return G_PATH 239 | } 240 | 241 | func (e *Path) Size() int { 242 | return len(e.entities) 243 | } 244 | 245 | func (e *Path) Get(index int) Entity { 246 | if index < 0 && index >= len(e.entities) { 247 | panic(fmt.Errorf("Entity index[%d] is out of range (%d) ", index, len(e.entities))) 248 | } 249 | return e.entities[index] 250 | } 251 | 252 | func (e *Path) GetAsVertex(index int) *Vertex { 253 | v := e.Get(index) 254 | 255 | if v.GType() != G_VERTEX { 256 | panic(fmt.Errorf("Entity[%d] is not Vertex", index)) 257 | } 258 | return v.(*Vertex) 259 | } 260 | 261 | func (e *Path) GetAsEdge(index int) *Edge { 262 | v := e.Get(index) 263 | if v.GType() != G_EDGE { 264 | panic(fmt.Errorf("Entity[%d] is not Edge", index)) 265 | } 266 | return v.(*Edge) 267 | } 268 | 269 | func (p *Path) String() string { 270 | var buf bytes.Buffer 271 | buf.WriteString("P[") 272 | for _, e := range p.entities { 273 | buf.WriteString(e.String()) 274 | buf.WriteString(",") 275 | } 276 | buf.WriteString("]") 277 | return buf.String() 278 | } 279 | 280 | type MapPath struct { 281 | Entity 282 | entities []interface{} 283 | } 284 | 285 | func NewMapPath(entities []interface{}) *MapPath { 286 | return &MapPath{entities: entities} 287 | } 288 | 289 | func (e *MapPath) GType() GTYPE { 290 | return G_MAP_PATH 291 | } 292 | 293 | func (e *MapPath) Size() int { 294 | return len(e.entities) 295 | } 296 | 297 | func (e *MapPath) Get(index int) interface{} { 298 | if index < 0 && index >= len(e.entities) { 299 | panic(fmt.Errorf("Entity index[%d] is out of range (%d) ", index, len(e.entities))) 300 | } 301 | return e.entities[index] 302 | } 303 | 304 | func (p *MapPath) String() string { 305 | var buf bytes.Buffer 306 | buf.WriteString("P[") 307 | for _, e := range p.entities { 308 | buf.WriteString(fmt.Sprintf("%v", e)) 309 | buf.WriteString(",") 310 | } 311 | buf.WriteString("]") 312 | return buf.String() 313 | } 314 | -------------------------------------------------------------------------------- /Question-3/Go/go.mod: -------------------------------------------------------------------------------- 1 | // /* 2 | // * Licensed to the Apache Software Foundation (ASF) under one 3 | // * or more contributor license agreements. See the NOTICE file 4 | // * distributed with this work for additional information 5 | // * regarding copyright ownership. The ASF licenses this file 6 | // * to you under the Apache License, Version 2.0 (the 7 | // * "License"); you may not use this file except in compliance 8 | // * with the License. You may obtain a copy of the License at 9 | // * 10 | // * http://www.apache.org/licenses/LICENSE-2.0 11 | // * 12 | // * Unless required by applicable law or agreed to in writing, 13 | // * software distributed under the License is distributed on an 14 | // * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | // * KIND, either express or implied. See the License for the 16 | // * specific language governing permissions and limitations 17 | // * under the License. 18 | // */ 19 | module github.com/DS-Popeye/Apache-Internship-Program/Question-3/Go 20 | 21 | go 1.16 22 | 23 | require ( 24 | github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20210521184019-c5ad59b459ec 25 | github.com/lib/pq v1.10.2 26 | github.com/stretchr/testify v1.7.0 27 | ) 28 | -------------------------------------------------------------------------------- /Question-3/Go/parser/Agtype.g4: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | 20 | grammar Agtype; 21 | 22 | agType 23 | : agValue EOF 24 | ; 25 | 26 | agValue 27 | : value typeAnnotation? 28 | ; 29 | 30 | value 31 | : STRING #StringValue 32 | | INTEGER #IntegerValue 33 | | floatLiteral #FloatValue 34 | | 'true' #TrueBoolean 35 | | 'false' #FalseBoolean 36 | | 'null' #NullValue 37 | | obj #ObjectValue 38 | | array #ArrayValue 39 | ; 40 | 41 | obj 42 | : '{' pair (',' pair)* '}' 43 | | '{' '}' 44 | ; 45 | 46 | pair 47 | : STRING ':' agValue 48 | ; 49 | 50 | array 51 | : '[' agValue (',' agValue)* ']' 52 | | '[' ']' 53 | ; 54 | 55 | typeAnnotation 56 | : '::' IDENT 57 | ; 58 | 59 | IDENT 60 | : [A-Z_a-z][$0-9A-Z_a-z]* 61 | ; 62 | 63 | STRING 64 | : '"' (ESC | SAFECODEPOINT)* '"' 65 | ; 66 | 67 | fragment ESC 68 | : '\\' (["\\/bfnrt] | UNICODE) 69 | ; 70 | 71 | fragment UNICODE 72 | : 'u' HEX HEX HEX HEX 73 | ; 74 | 75 | fragment HEX 76 | : [0-9a-fA-F] 77 | ; 78 | 79 | fragment SAFECODEPOINT 80 | : ~ ["\\\u0000-\u001F] 81 | ; 82 | 83 | INTEGER 84 | : '-'? INT 85 | ; 86 | 87 | fragment INT 88 | : '0' | [1-9] [0-9]* 89 | ; 90 | 91 | floatLiteral 92 | : RegularFloat 93 | | ExponentFloat 94 | | '-'? 'Infinity' 95 | | 'NaN' 96 | ; 97 | 98 | RegularFloat 99 | : '-'? INT DECIMAL 100 | ; 101 | 102 | ExponentFloat 103 | : '-'? INT DECIMAL? SCIENTIFIC 104 | ; 105 | 106 | fragment DECIMAL 107 | : '.' [0-9]+ 108 | ; 109 | 110 | fragment SCIENTIFIC 111 | : [Ee][+-]? [0-9]+ 112 | ; 113 | 114 | WS 115 | : [ \t\n\r] + -> skip 116 | ; 117 | -------------------------------------------------------------------------------- /Question-3/Go/parser/README.md: -------------------------------------------------------------------------------- 1 | # ANTLR4 Go Query Result data parser generation rules for apache-age-go 2 | 3 | Go driver for Apache AGE, graph extention for PostgreSQL. 4 | 5 | ### Build 6 | 7 | #### 1) Generate query result data parser with ANTLR4 8 | 9 | ``` 10 | # prerequisites : 11 | # - java over 8 12 | # - download ANTLR4 from https://www.antlr.org/download/antlr-4.9.2-complete.jar 13 | # - java -cp antlr-4.9.2-complete.jar org.antlr.v4.Tool -Dlanguage=Go -visitor Agtype.g4 14 | ``` 15 | -------------------------------------------------------------------------------- /Question-3/Go/parser/agtype_base_listener.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | // Code generated from Agtype.g4 by ANTLR 4.9.2. DO NOT EDIT. 20 | 21 | package parser // Agtype 22 | 23 | import "github.com/antlr/antlr4/runtime/Go/antlr" 24 | 25 | // BaseAgtypeListener is a complete listener for a parse tree produced by AgtypeParser. 26 | type BaseAgtypeListener struct{} 27 | 28 | var _ AgtypeListener = &BaseAgtypeListener{} 29 | 30 | // VisitTerminal is called when a terminal node is visited. 31 | func (s *BaseAgtypeListener) VisitTerminal(node antlr.TerminalNode) {} 32 | 33 | // VisitErrorNode is called when an error node is visited. 34 | func (s *BaseAgtypeListener) VisitErrorNode(node antlr.ErrorNode) {} 35 | 36 | // EnterEveryRule is called when any rule is entered. 37 | func (s *BaseAgtypeListener) EnterEveryRule(ctx antlr.ParserRuleContext) {} 38 | 39 | // ExitEveryRule is called when any rule is exited. 40 | func (s *BaseAgtypeListener) ExitEveryRule(ctx antlr.ParserRuleContext) {} 41 | 42 | // EnterAgType is called when production agType is entered. 43 | func (s *BaseAgtypeListener) EnterAgType(ctx *AgTypeContext) {} 44 | 45 | // ExitAgType is called when production agType is exited. 46 | func (s *BaseAgtypeListener) ExitAgType(ctx *AgTypeContext) {} 47 | 48 | // EnterAgValue is called when production agValue is entered. 49 | func (s *BaseAgtypeListener) EnterAgValue(ctx *AgValueContext) {} 50 | 51 | // ExitAgValue is called when production agValue is exited. 52 | func (s *BaseAgtypeListener) ExitAgValue(ctx *AgValueContext) {} 53 | 54 | // EnterStringValue is called when production StringValue is entered. 55 | func (s *BaseAgtypeListener) EnterStringValue(ctx *StringValueContext) {} 56 | 57 | // ExitStringValue is called when production StringValue is exited. 58 | func (s *BaseAgtypeListener) ExitStringValue(ctx *StringValueContext) {} 59 | 60 | // EnterIntegerValue is called when production IntegerValue is entered. 61 | func (s *BaseAgtypeListener) EnterIntegerValue(ctx *IntegerValueContext) {} 62 | 63 | // ExitIntegerValue is called when production IntegerValue is exited. 64 | func (s *BaseAgtypeListener) ExitIntegerValue(ctx *IntegerValueContext) {} 65 | 66 | // EnterFloatValue is called when production FloatValue is entered. 67 | func (s *BaseAgtypeListener) EnterFloatValue(ctx *FloatValueContext) {} 68 | 69 | // ExitFloatValue is called when production FloatValue is exited. 70 | func (s *BaseAgtypeListener) ExitFloatValue(ctx *FloatValueContext) {} 71 | 72 | // EnterTrueBoolean is called when production TrueBoolean is entered. 73 | func (s *BaseAgtypeListener) EnterTrueBoolean(ctx *TrueBooleanContext) {} 74 | 75 | // ExitTrueBoolean is called when production TrueBoolean is exited. 76 | func (s *BaseAgtypeListener) ExitTrueBoolean(ctx *TrueBooleanContext) {} 77 | 78 | // EnterFalseBoolean is called when production FalseBoolean is entered. 79 | func (s *BaseAgtypeListener) EnterFalseBoolean(ctx *FalseBooleanContext) {} 80 | 81 | // ExitFalseBoolean is called when production FalseBoolean is exited. 82 | func (s *BaseAgtypeListener) ExitFalseBoolean(ctx *FalseBooleanContext) {} 83 | 84 | // EnterNullValue is called when production NullValue is entered. 85 | func (s *BaseAgtypeListener) EnterNullValue(ctx *NullValueContext) {} 86 | 87 | // ExitNullValue is called when production NullValue is exited. 88 | func (s *BaseAgtypeListener) ExitNullValue(ctx *NullValueContext) {} 89 | 90 | // EnterObjectValue is called when production ObjectValue is entered. 91 | func (s *BaseAgtypeListener) EnterObjectValue(ctx *ObjectValueContext) {} 92 | 93 | // ExitObjectValue is called when production ObjectValue is exited. 94 | func (s *BaseAgtypeListener) ExitObjectValue(ctx *ObjectValueContext) {} 95 | 96 | // EnterArrayValue is called when production ArrayValue is entered. 97 | func (s *BaseAgtypeListener) EnterArrayValue(ctx *ArrayValueContext) {} 98 | 99 | // ExitArrayValue is called when production ArrayValue is exited. 100 | func (s *BaseAgtypeListener) ExitArrayValue(ctx *ArrayValueContext) {} 101 | 102 | // EnterObj is called when production obj is entered. 103 | func (s *BaseAgtypeListener) EnterObj(ctx *ObjContext) {} 104 | 105 | // ExitObj is called when production obj is exited. 106 | func (s *BaseAgtypeListener) ExitObj(ctx *ObjContext) {} 107 | 108 | // EnterPair is called when production pair is entered. 109 | func (s *BaseAgtypeListener) EnterPair(ctx *PairContext) {} 110 | 111 | // ExitPair is called when production pair is exited. 112 | func (s *BaseAgtypeListener) ExitPair(ctx *PairContext) {} 113 | 114 | // EnterArray is called when production array is entered. 115 | func (s *BaseAgtypeListener) EnterArray(ctx *ArrayContext) {} 116 | 117 | // ExitArray is called when production array is exited. 118 | func (s *BaseAgtypeListener) ExitArray(ctx *ArrayContext) {} 119 | 120 | // EnterTypeAnnotation is called when production typeAnnotation is entered. 121 | func (s *BaseAgtypeListener) EnterTypeAnnotation(ctx *TypeAnnotationContext) {} 122 | 123 | // ExitTypeAnnotation is called when production typeAnnotation is exited. 124 | func (s *BaseAgtypeListener) ExitTypeAnnotation(ctx *TypeAnnotationContext) {} 125 | 126 | // EnterFloatLiteral is called when production floatLiteral is entered. 127 | func (s *BaseAgtypeListener) EnterFloatLiteral(ctx *FloatLiteralContext) {} 128 | 129 | // ExitFloatLiteral is called when production floatLiteral is exited. 130 | func (s *BaseAgtypeListener) ExitFloatLiteral(ctx *FloatLiteralContext) {} 131 | -------------------------------------------------------------------------------- /Question-3/Go/parser/agtype_base_visitor.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | // Code generated from Agtype.g4 by ANTLR 4.9.2. DO NOT EDIT. 20 | 21 | package parser // Agtype 22 | 23 | import "github.com/antlr/antlr4/runtime/Go/antlr" 24 | 25 | type BaseAgtypeVisitor struct { 26 | *antlr.BaseParseTreeVisitor 27 | } 28 | 29 | func (v *BaseAgtypeVisitor) VisitAgType(ctx *AgTypeContext) interface{} { 30 | return v.VisitChildren(ctx) 31 | } 32 | 33 | func (v *BaseAgtypeVisitor) VisitAgValue(ctx *AgValueContext) interface{} { 34 | return v.VisitChildren(ctx) 35 | } 36 | 37 | func (v *BaseAgtypeVisitor) VisitStringValue(ctx *StringValueContext) interface{} { 38 | return v.VisitChildren(ctx) 39 | } 40 | 41 | func (v *BaseAgtypeVisitor) VisitIntegerValue(ctx *IntegerValueContext) interface{} { 42 | return v.VisitChildren(ctx) 43 | } 44 | 45 | func (v *BaseAgtypeVisitor) VisitFloatValue(ctx *FloatValueContext) interface{} { 46 | return v.VisitChildren(ctx) 47 | } 48 | 49 | func (v *BaseAgtypeVisitor) VisitTrueBoolean(ctx *TrueBooleanContext) interface{} { 50 | return v.VisitChildren(ctx) 51 | } 52 | 53 | func (v *BaseAgtypeVisitor) VisitFalseBoolean(ctx *FalseBooleanContext) interface{} { 54 | return v.VisitChildren(ctx) 55 | } 56 | 57 | func (v *BaseAgtypeVisitor) VisitNullValue(ctx *NullValueContext) interface{} { 58 | return v.VisitChildren(ctx) 59 | } 60 | 61 | func (v *BaseAgtypeVisitor) VisitObjectValue(ctx *ObjectValueContext) interface{} { 62 | return v.VisitChildren(ctx) 63 | } 64 | 65 | func (v *BaseAgtypeVisitor) VisitArrayValue(ctx *ArrayValueContext) interface{} { 66 | return v.VisitChildren(ctx) 67 | } 68 | 69 | func (v *BaseAgtypeVisitor) VisitObj(ctx *ObjContext) interface{} { 70 | return v.VisitChildren(ctx) 71 | } 72 | 73 | func (v *BaseAgtypeVisitor) VisitPair(ctx *PairContext) interface{} { 74 | return v.VisitChildren(ctx) 75 | } 76 | 77 | func (v *BaseAgtypeVisitor) VisitArray(ctx *ArrayContext) interface{} { 78 | return v.VisitChildren(ctx) 79 | } 80 | 81 | func (v *BaseAgtypeVisitor) VisitTypeAnnotation(ctx *TypeAnnotationContext) interface{} { 82 | return v.VisitChildren(ctx) 83 | } 84 | 85 | func (v *BaseAgtypeVisitor) VisitFloatLiteral(ctx *FloatLiteralContext) interface{} { 86 | return v.VisitChildren(ctx) 87 | } 88 | -------------------------------------------------------------------------------- /Question-3/Go/parser/agtype_lexer.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | // Code generated from Agtype.g4 by ANTLR 4.9.2. DO NOT EDIT. 20 | 21 | package parser 22 | 23 | import ( 24 | "fmt" 25 | "unicode" 26 | 27 | "github.com/antlr/antlr4/runtime/Go/antlr" 28 | ) 29 | 30 | // Suppress unused import error 31 | var _ = fmt.Printf 32 | var _ = unicode.IsLetter 33 | 34 | var serializedLexerAtn = []uint16{ 35 | 3, 24715, 42794, 33075, 47597, 16764, 15335, 30598, 22884, 2, 21, 185, 36 | 8, 1, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 37 | 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 4, 12, 9, 12, 38 | 4, 13, 9, 13, 4, 14, 9, 14, 4, 15, 9, 15, 4, 16, 9, 16, 4, 17, 9, 17, 4, 39 | 18, 9, 18, 4, 19, 9, 19, 4, 20, 9, 20, 4, 21, 9, 21, 4, 22, 9, 22, 4, 23, 40 | 9, 23, 4, 24, 9, 24, 4, 25, 9, 25, 4, 26, 9, 26, 4, 27, 9, 27, 3, 2, 3, 41 | 2, 3, 2, 3, 2, 3, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 3, 4, 3, 42 | 4, 3, 4, 3, 4, 3, 5, 3, 5, 3, 6, 3, 6, 3, 7, 3, 7, 3, 8, 3, 8, 3, 9, 3, 43 | 9, 3, 10, 3, 10, 3, 11, 3, 11, 3, 11, 3, 12, 3, 12, 3, 13, 3, 13, 3, 13, 44 | 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 14, 3, 14, 3, 14, 3, 14, 3, 45 | 15, 3, 15, 7, 15, 104, 10, 15, 12, 15, 14, 15, 107, 11, 15, 3, 16, 3, 16, 46 | 3, 16, 7, 16, 112, 10, 16, 12, 16, 14, 16, 115, 11, 16, 3, 16, 3, 16, 3, 47 | 17, 3, 17, 3, 17, 5, 17, 122, 10, 17, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 48 | 3, 18, 3, 19, 3, 19, 3, 20, 3, 20, 3, 21, 5, 21, 135, 10, 21, 3, 21, 3, 49 | 21, 3, 22, 3, 22, 3, 22, 7, 22, 142, 10, 22, 12, 22, 14, 22, 145, 11, 22, 50 | 5, 22, 147, 10, 22, 3, 23, 5, 23, 150, 10, 23, 3, 23, 3, 23, 3, 23, 3, 51 | 24, 5, 24, 156, 10, 24, 3, 24, 3, 24, 5, 24, 160, 10, 24, 3, 24, 3, 24, 52 | 3, 25, 3, 25, 6, 25, 166, 10, 25, 13, 25, 14, 25, 167, 3, 26, 3, 26, 5, 53 | 26, 172, 10, 26, 3, 26, 6, 26, 175, 10, 26, 13, 26, 14, 26, 176, 3, 27, 54 | 6, 27, 180, 10, 27, 13, 27, 14, 27, 181, 3, 27, 3, 27, 2, 2, 28, 3, 3, 55 | 5, 4, 7, 5, 9, 6, 11, 7, 13, 8, 15, 9, 17, 10, 19, 11, 21, 12, 23, 13, 56 | 25, 14, 27, 15, 29, 16, 31, 17, 33, 2, 35, 2, 37, 2, 39, 2, 41, 18, 43, 57 | 2, 45, 19, 47, 20, 49, 2, 51, 2, 53, 21, 3, 2, 12, 5, 2, 67, 92, 97, 97, 58 | 99, 124, 7, 2, 38, 38, 50, 59, 67, 92, 97, 97, 99, 124, 10, 2, 36, 36, 59 | 49, 49, 94, 94, 100, 100, 104, 104, 112, 112, 116, 116, 118, 118, 5, 2, 60 | 50, 59, 67, 72, 99, 104, 5, 2, 2, 33, 36, 36, 94, 94, 3, 2, 51, 59, 3, 61 | 2, 50, 59, 4, 2, 71, 71, 103, 103, 4, 2, 45, 45, 47, 47, 5, 2, 11, 12, 62 | 15, 15, 34, 34, 2, 191, 2, 3, 3, 2, 2, 2, 2, 5, 3, 2, 2, 2, 2, 7, 3, 2, 63 | 2, 2, 2, 9, 3, 2, 2, 2, 2, 11, 3, 2, 2, 2, 2, 13, 3, 2, 2, 2, 2, 15, 3, 64 | 2, 2, 2, 2, 17, 3, 2, 2, 2, 2, 19, 3, 2, 2, 2, 2, 21, 3, 2, 2, 2, 2, 23, 65 | 3, 2, 2, 2, 2, 25, 3, 2, 2, 2, 2, 27, 3, 2, 2, 2, 2, 29, 3, 2, 2, 2, 2, 66 | 31, 3, 2, 2, 2, 2, 41, 3, 2, 2, 2, 2, 45, 3, 2, 2, 2, 2, 47, 3, 2, 2, 2, 67 | 2, 53, 3, 2, 2, 2, 3, 55, 3, 2, 2, 2, 5, 60, 3, 2, 2, 2, 7, 66, 3, 2, 2, 68 | 2, 9, 71, 3, 2, 2, 2, 11, 73, 3, 2, 2, 2, 13, 75, 3, 2, 2, 2, 15, 77, 3, 69 | 2, 2, 2, 17, 79, 3, 2, 2, 2, 19, 81, 3, 2, 2, 2, 21, 83, 3, 2, 2, 2, 23, 70 | 86, 3, 2, 2, 2, 25, 88, 3, 2, 2, 2, 27, 97, 3, 2, 2, 2, 29, 101, 3, 2, 71 | 2, 2, 31, 108, 3, 2, 2, 2, 33, 118, 3, 2, 2, 2, 35, 123, 3, 2, 2, 2, 37, 72 | 129, 3, 2, 2, 2, 39, 131, 3, 2, 2, 2, 41, 134, 3, 2, 2, 2, 43, 146, 3, 73 | 2, 2, 2, 45, 149, 3, 2, 2, 2, 47, 155, 3, 2, 2, 2, 49, 163, 3, 2, 2, 2, 74 | 51, 169, 3, 2, 2, 2, 53, 179, 3, 2, 2, 2, 55, 56, 7, 118, 2, 2, 56, 57, 75 | 7, 116, 2, 2, 57, 58, 7, 119, 2, 2, 58, 59, 7, 103, 2, 2, 59, 4, 3, 2, 76 | 2, 2, 60, 61, 7, 104, 2, 2, 61, 62, 7, 99, 2, 2, 62, 63, 7, 110, 2, 2, 77 | 63, 64, 7, 117, 2, 2, 64, 65, 7, 103, 2, 2, 65, 6, 3, 2, 2, 2, 66, 67, 78 | 7, 112, 2, 2, 67, 68, 7, 119, 2, 2, 68, 69, 7, 110, 2, 2, 69, 70, 7, 110, 79 | 2, 2, 70, 8, 3, 2, 2, 2, 71, 72, 7, 125, 2, 2, 72, 10, 3, 2, 2, 2, 73, 80 | 74, 7, 46, 2, 2, 74, 12, 3, 2, 2, 2, 75, 76, 7, 127, 2, 2, 76, 14, 3, 2, 81 | 2, 2, 77, 78, 7, 60, 2, 2, 78, 16, 3, 2, 2, 2, 79, 80, 7, 93, 2, 2, 80, 82 | 18, 3, 2, 2, 2, 81, 82, 7, 95, 2, 2, 82, 20, 3, 2, 2, 2, 83, 84, 7, 60, 83 | 2, 2, 84, 85, 7, 60, 2, 2, 85, 22, 3, 2, 2, 2, 86, 87, 7, 47, 2, 2, 87, 84 | 24, 3, 2, 2, 2, 88, 89, 7, 75, 2, 2, 89, 90, 7, 112, 2, 2, 90, 91, 7, 104, 85 | 2, 2, 91, 92, 7, 107, 2, 2, 92, 93, 7, 112, 2, 2, 93, 94, 7, 107, 2, 2, 86 | 94, 95, 7, 118, 2, 2, 95, 96, 7, 123, 2, 2, 96, 26, 3, 2, 2, 2, 97, 98, 87 | 7, 80, 2, 2, 98, 99, 7, 99, 2, 2, 99, 100, 7, 80, 2, 2, 100, 28, 3, 2, 88 | 2, 2, 101, 105, 9, 2, 2, 2, 102, 104, 9, 3, 2, 2, 103, 102, 3, 2, 2, 2, 89 | 104, 107, 3, 2, 2, 2, 105, 103, 3, 2, 2, 2, 105, 106, 3, 2, 2, 2, 106, 90 | 30, 3, 2, 2, 2, 107, 105, 3, 2, 2, 2, 108, 113, 7, 36, 2, 2, 109, 112, 91 | 5, 33, 17, 2, 110, 112, 5, 39, 20, 2, 111, 109, 3, 2, 2, 2, 111, 110, 3, 92 | 2, 2, 2, 112, 115, 3, 2, 2, 2, 113, 111, 3, 2, 2, 2, 113, 114, 3, 2, 2, 93 | 2, 114, 116, 3, 2, 2, 2, 115, 113, 3, 2, 2, 2, 116, 117, 7, 36, 2, 2, 117, 94 | 32, 3, 2, 2, 2, 118, 121, 7, 94, 2, 2, 119, 122, 9, 4, 2, 2, 120, 122, 95 | 5, 35, 18, 2, 121, 119, 3, 2, 2, 2, 121, 120, 3, 2, 2, 2, 122, 34, 3, 2, 96 | 2, 2, 123, 124, 7, 119, 2, 2, 124, 125, 5, 37, 19, 2, 125, 126, 5, 37, 97 | 19, 2, 126, 127, 5, 37, 19, 2, 127, 128, 5, 37, 19, 2, 128, 36, 3, 2, 2, 98 | 2, 129, 130, 9, 5, 2, 2, 130, 38, 3, 2, 2, 2, 131, 132, 10, 6, 2, 2, 132, 99 | 40, 3, 2, 2, 2, 133, 135, 7, 47, 2, 2, 134, 133, 3, 2, 2, 2, 134, 135, 100 | 3, 2, 2, 2, 135, 136, 3, 2, 2, 2, 136, 137, 5, 43, 22, 2, 137, 42, 3, 2, 101 | 2, 2, 138, 147, 7, 50, 2, 2, 139, 143, 9, 7, 2, 2, 140, 142, 9, 8, 2, 2, 102 | 141, 140, 3, 2, 2, 2, 142, 145, 3, 2, 2, 2, 143, 141, 3, 2, 2, 2, 143, 103 | 144, 3, 2, 2, 2, 144, 147, 3, 2, 2, 2, 145, 143, 3, 2, 2, 2, 146, 138, 104 | 3, 2, 2, 2, 146, 139, 3, 2, 2, 2, 147, 44, 3, 2, 2, 2, 148, 150, 7, 47, 105 | 2, 2, 149, 148, 3, 2, 2, 2, 149, 150, 3, 2, 2, 2, 150, 151, 3, 2, 2, 2, 106 | 151, 152, 5, 43, 22, 2, 152, 153, 5, 49, 25, 2, 153, 46, 3, 2, 2, 2, 154, 107 | 156, 7, 47, 2, 2, 155, 154, 3, 2, 2, 2, 155, 156, 3, 2, 2, 2, 156, 157, 108 | 3, 2, 2, 2, 157, 159, 5, 43, 22, 2, 158, 160, 5, 49, 25, 2, 159, 158, 3, 109 | 2, 2, 2, 159, 160, 3, 2, 2, 2, 160, 161, 3, 2, 2, 2, 161, 162, 5, 51, 26, 110 | 2, 162, 48, 3, 2, 2, 2, 163, 165, 7, 48, 2, 2, 164, 166, 9, 8, 2, 2, 165, 111 | 164, 3, 2, 2, 2, 166, 167, 3, 2, 2, 2, 167, 165, 3, 2, 2, 2, 167, 168, 112 | 3, 2, 2, 2, 168, 50, 3, 2, 2, 2, 169, 171, 9, 9, 2, 2, 170, 172, 9, 10, 113 | 2, 2, 171, 170, 3, 2, 2, 2, 171, 172, 3, 2, 2, 2, 172, 174, 3, 2, 2, 2, 114 | 173, 175, 9, 8, 2, 2, 174, 173, 3, 2, 2, 2, 175, 176, 3, 2, 2, 2, 176, 115 | 174, 3, 2, 2, 2, 176, 177, 3, 2, 2, 2, 177, 52, 3, 2, 2, 2, 178, 180, 9, 116 | 11, 2, 2, 179, 178, 3, 2, 2, 2, 180, 181, 3, 2, 2, 2, 181, 179, 3, 2, 2, 117 | 2, 181, 182, 3, 2, 2, 2, 182, 183, 3, 2, 2, 2, 183, 184, 8, 27, 2, 2, 184, 118 | 54, 3, 2, 2, 2, 17, 2, 105, 111, 113, 121, 134, 143, 146, 149, 155, 159, 119 | 167, 171, 176, 181, 3, 8, 2, 2, 120 | } 121 | 122 | var lexerChannelNames = []string{ 123 | "DEFAULT_TOKEN_CHANNEL", "HIDDEN", 124 | } 125 | 126 | var lexerModeNames = []string{ 127 | "DEFAULT_MODE", 128 | } 129 | 130 | var lexerLiteralNames = []string{ 131 | "", "'true'", "'false'", "'null'", "'{'", "','", "'}'", "':'", "'['", "']'", 132 | "'::'", "'-'", "'Infinity'", "'NaN'", 133 | } 134 | 135 | var lexerSymbolicNames = []string{ 136 | "", "", "", "", "", "", "", "", "", "", "", "", "", "", "IDENT", "STRING", 137 | "INTEGER", "RegularFloat", "ExponentFloat", "WS", 138 | } 139 | 140 | var lexerRuleNames = []string{ 141 | "T__0", "T__1", "T__2", "T__3", "T__4", "T__5", "T__6", "T__7", "T__8", 142 | "T__9", "T__10", "T__11", "T__12", "IDENT", "STRING", "ESC", "UNICODE", 143 | "HEX", "SAFECODEPOINT", "INTEGER", "INT", "RegularFloat", "ExponentFloat", 144 | "DECIMAL", "SCIENTIFIC", "WS", 145 | } 146 | 147 | type AgtypeLexer struct { 148 | *antlr.BaseLexer 149 | channelNames []string 150 | modeNames []string 151 | // TODO: EOF string 152 | } 153 | 154 | // NewAgtypeLexer produces a new lexer instance for the optional input antlr.CharStream. 155 | // 156 | // The *AgtypeLexer instance produced may be reused by calling the SetInputStream method. 157 | // The initial lexer configuration is expensive to construct, and the object is not thread-safe; 158 | // however, if used within a Golang sync.Pool, the construction cost amortizes well and the 159 | // objects can be used in a thread-safe manner. 160 | func NewAgtypeLexer(input antlr.CharStream) *AgtypeLexer { 161 | l := new(AgtypeLexer) 162 | lexerDeserializer := antlr.NewATNDeserializer(nil) 163 | lexerAtn := lexerDeserializer.DeserializeFromUInt16(serializedLexerAtn) 164 | lexerDecisionToDFA := make([]*antlr.DFA, len(lexerAtn.DecisionToState)) 165 | for index, ds := range lexerAtn.DecisionToState { 166 | lexerDecisionToDFA[index] = antlr.NewDFA(ds, index) 167 | } 168 | l.BaseLexer = antlr.NewBaseLexer(input) 169 | l.Interpreter = antlr.NewLexerATNSimulator(l, lexerAtn, lexerDecisionToDFA, antlr.NewPredictionContextCache()) 170 | 171 | l.channelNames = lexerChannelNames 172 | l.modeNames = lexerModeNames 173 | l.RuleNames = lexerRuleNames 174 | l.LiteralNames = lexerLiteralNames 175 | l.SymbolicNames = lexerSymbolicNames 176 | l.GrammarFileName = "Agtype.g4" 177 | // TODO: l.EOF = antlr.TokenEOF 178 | 179 | return l 180 | } 181 | 182 | // AgtypeLexer tokens. 183 | const ( 184 | AgtypeLexerT__0 = 1 185 | AgtypeLexerT__1 = 2 186 | AgtypeLexerT__2 = 3 187 | AgtypeLexerT__3 = 4 188 | AgtypeLexerT__4 = 5 189 | AgtypeLexerT__5 = 6 190 | AgtypeLexerT__6 = 7 191 | AgtypeLexerT__7 = 8 192 | AgtypeLexerT__8 = 9 193 | AgtypeLexerT__9 = 10 194 | AgtypeLexerT__10 = 11 195 | AgtypeLexerT__11 = 12 196 | AgtypeLexerT__12 = 13 197 | AgtypeLexerIDENT = 14 198 | AgtypeLexerSTRING = 15 199 | AgtypeLexerINTEGER = 16 200 | AgtypeLexerRegularFloat = 17 201 | AgtypeLexerExponentFloat = 18 202 | AgtypeLexerWS = 19 203 | ) 204 | -------------------------------------------------------------------------------- /Question-3/Go/parser/agtype_listener.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | // Code generated from Agtype.g4 by ANTLR 4.9.2. DO NOT EDIT. 20 | 21 | package parser // Agtype 22 | 23 | import "github.com/antlr/antlr4/runtime/Go/antlr" 24 | 25 | // AgtypeListener is a complete listener for a parse tree produced by AgtypeParser. 26 | type AgtypeListener interface { 27 | antlr.ParseTreeListener 28 | 29 | // EnterAgType is called when entering the agType production. 30 | EnterAgType(c *AgTypeContext) 31 | 32 | // EnterAgValue is called when entering the agValue production. 33 | EnterAgValue(c *AgValueContext) 34 | 35 | // EnterStringValue is called when entering the StringValue production. 36 | EnterStringValue(c *StringValueContext) 37 | 38 | // EnterIntegerValue is called when entering the IntegerValue production. 39 | EnterIntegerValue(c *IntegerValueContext) 40 | 41 | // EnterFloatValue is called when entering the FloatValue production. 42 | EnterFloatValue(c *FloatValueContext) 43 | 44 | // EnterTrueBoolean is called when entering the TrueBoolean production. 45 | EnterTrueBoolean(c *TrueBooleanContext) 46 | 47 | // EnterFalseBoolean is called when entering the FalseBoolean production. 48 | EnterFalseBoolean(c *FalseBooleanContext) 49 | 50 | // EnterNullValue is called when entering the NullValue production. 51 | EnterNullValue(c *NullValueContext) 52 | 53 | // EnterObjectValue is called when entering the ObjectValue production. 54 | EnterObjectValue(c *ObjectValueContext) 55 | 56 | // EnterArrayValue is called when entering the ArrayValue production. 57 | EnterArrayValue(c *ArrayValueContext) 58 | 59 | // EnterObj is called when entering the obj production. 60 | EnterObj(c *ObjContext) 61 | 62 | // EnterPair is called when entering the pair production. 63 | EnterPair(c *PairContext) 64 | 65 | // EnterArray is called when entering the array production. 66 | EnterArray(c *ArrayContext) 67 | 68 | // EnterTypeAnnotation is called when entering the typeAnnotation production. 69 | EnterTypeAnnotation(c *TypeAnnotationContext) 70 | 71 | // EnterFloatLiteral is called when entering the floatLiteral production. 72 | EnterFloatLiteral(c *FloatLiteralContext) 73 | 74 | // ExitAgType is called when exiting the agType production. 75 | ExitAgType(c *AgTypeContext) 76 | 77 | // ExitAgValue is called when exiting the agValue production. 78 | ExitAgValue(c *AgValueContext) 79 | 80 | // ExitStringValue is called when exiting the StringValue production. 81 | ExitStringValue(c *StringValueContext) 82 | 83 | // ExitIntegerValue is called when exiting the IntegerValue production. 84 | ExitIntegerValue(c *IntegerValueContext) 85 | 86 | // ExitFloatValue is called when exiting the FloatValue production. 87 | ExitFloatValue(c *FloatValueContext) 88 | 89 | // ExitTrueBoolean is called when exiting the TrueBoolean production. 90 | ExitTrueBoolean(c *TrueBooleanContext) 91 | 92 | // ExitFalseBoolean is called when exiting the FalseBoolean production. 93 | ExitFalseBoolean(c *FalseBooleanContext) 94 | 95 | // ExitNullValue is called when exiting the NullValue production. 96 | ExitNullValue(c *NullValueContext) 97 | 98 | // ExitObjectValue is called when exiting the ObjectValue production. 99 | ExitObjectValue(c *ObjectValueContext) 100 | 101 | // ExitArrayValue is called when exiting the ArrayValue production. 102 | ExitArrayValue(c *ArrayValueContext) 103 | 104 | // ExitObj is called when exiting the obj production. 105 | ExitObj(c *ObjContext) 106 | 107 | // ExitPair is called when exiting the pair production. 108 | ExitPair(c *PairContext) 109 | 110 | // ExitArray is called when exiting the array production. 111 | ExitArray(c *ArrayContext) 112 | 113 | // ExitTypeAnnotation is called when exiting the typeAnnotation production. 114 | ExitTypeAnnotation(c *TypeAnnotationContext) 115 | 116 | // ExitFloatLiteral is called when exiting the floatLiteral production. 117 | ExitFloatLiteral(c *FloatLiteralContext) 118 | } 119 | -------------------------------------------------------------------------------- /Question-3/Go/parser/agtype_visitor.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | // Code generated from Agtype.g4 by ANTLR 4.9.2. DO NOT EDIT. 20 | 21 | package parser // Agtype 22 | 23 | import "github.com/antlr/antlr4/runtime/Go/antlr" 24 | 25 | // A complete Visitor for a parse tree produced by AgtypeParser. 26 | type AgtypeVisitor interface { 27 | antlr.ParseTreeVisitor 28 | 29 | // Visit a parse tree produced by AgtypeParser#agType. 30 | VisitAgType(ctx *AgTypeContext) interface{} 31 | 32 | // Visit a parse tree produced by AgtypeParser#agValue. 33 | VisitAgValue(ctx *AgValueContext) interface{} 34 | 35 | // Visit a parse tree produced by AgtypeParser#StringValue. 36 | VisitStringValue(ctx *StringValueContext) interface{} 37 | 38 | // Visit a parse tree produced by AgtypeParser#IntegerValue. 39 | VisitIntegerValue(ctx *IntegerValueContext) interface{} 40 | 41 | // Visit a parse tree produced by AgtypeParser#FloatValue. 42 | VisitFloatValue(ctx *FloatValueContext) interface{} 43 | 44 | // Visit a parse tree produced by AgtypeParser#TrueBoolean. 45 | VisitTrueBoolean(ctx *TrueBooleanContext) interface{} 46 | 47 | // Visit a parse tree produced by AgtypeParser#FalseBoolean. 48 | VisitFalseBoolean(ctx *FalseBooleanContext) interface{} 49 | 50 | // Visit a parse tree produced by AgtypeParser#NullValue. 51 | VisitNullValue(ctx *NullValueContext) interface{} 52 | 53 | // Visit a parse tree produced by AgtypeParser#ObjectValue. 54 | VisitObjectValue(ctx *ObjectValueContext) interface{} 55 | 56 | // Visit a parse tree produced by AgtypeParser#ArrayValue. 57 | VisitArrayValue(ctx *ArrayValueContext) interface{} 58 | 59 | // Visit a parse tree produced by AgtypeParser#obj. 60 | VisitObj(ctx *ObjContext) interface{} 61 | 62 | // Visit a parse tree produced by AgtypeParser#pair. 63 | VisitPair(ctx *PairContext) interface{} 64 | 65 | // Visit a parse tree produced by AgtypeParser#array. 66 | VisitArray(ctx *ArrayContext) interface{} 67 | 68 | // Visit a parse tree produced by AgtypeParser#typeAnnotation. 69 | VisitTypeAnnotation(ctx *TypeAnnotationContext) interface{} 70 | 71 | // Visit a parse tree produced by AgtypeParser#floatLiteral. 72 | VisitFloatLiteral(ctx *FloatLiteralContext) interface{} 73 | } 74 | -------------------------------------------------------------------------------- /Question-3/Go/samples/age_wrapper_sample.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package main 20 | 21 | import ( 22 | "fmt" 23 | 24 | "github.com/DS-Popeye/Apache-Internship-Program/Question-3/Go/age" 25 | ) 26 | 27 | // Do cypher query to AGE with Age API 28 | func doWithAgeWrapper(dsn string, graphName string) { 29 | 30 | ag, err := age.ConnectAge(graphName, dsn) 31 | 32 | if err != nil { 33 | panic(err) 34 | } 35 | 36 | tx, err := ag.Begin() 37 | if err != nil { 38 | panic(err) 39 | } 40 | 41 | _, err = tx.ExecCypher(0, "CREATE (n:Person {name: '%s'})", "Joe") 42 | if err != nil { 43 | panic(err) 44 | } 45 | 46 | _, err = tx.ExecCypher(0, "CREATE (n:Person {name: '%s', age: %d})", "Smith", 10) 47 | if err != nil { 48 | panic(err) 49 | } 50 | 51 | _, err = tx.ExecCypher(0, "CREATE (n:Person {name: '%s', weight:%f})", "Jack", 70.3) 52 | if err != nil { 53 | panic(err) 54 | } 55 | 56 | tx.Commit() 57 | 58 | tx, err = ag.Begin() 59 | if err != nil { 60 | panic(err) 61 | } 62 | 63 | cursor, err := tx.ExecCypher(1, "MATCH (n:Person) RETURN n") 64 | if err != nil { 65 | panic(err) 66 | } 67 | 68 | count := 0 69 | for cursor.Next() { 70 | row, err := cursor.GetRow() 71 | if err != nil { 72 | panic(err) 73 | } 74 | count++ 75 | vertex := row[0].(*age.Vertex) 76 | fmt.Println(count, "]", vertex.Id(), vertex.Label(), vertex.Props()) 77 | } 78 | 79 | fmt.Println("Vertex Count:", count) 80 | 81 | _, err = tx.ExecCypher(0, "MATCH (a:Person), (b:Person) WHERE a.name='%s' AND b.name='%s' CREATE (a)-[r:workWith {weight: %d}]->(b)", 82 | "Jack", "Joe", 3) 83 | if err != nil { 84 | panic(err) 85 | } 86 | 87 | _, err = tx.ExecCypher(0, "MATCH (a:Person {name: '%s'}), (b:Person {name: '%s'}) CREATE (a)-[r:workWith {weight: %d}]->(b)", 88 | "Joe", "Smith", 7) 89 | if err != nil { 90 | panic(err) 91 | } 92 | 93 | tx.Commit() 94 | 95 | tx, err = ag.Begin() 96 | if err != nil { 97 | panic(err) 98 | } 99 | 100 | cursor, err = tx.ExecCypher(1, "MATCH p=()-[:workWith]-() RETURN p") 101 | if err != nil { 102 | panic(err) 103 | } 104 | 105 | count = 0 106 | for cursor.Next() { 107 | row, err := cursor.GetRow() 108 | if err != nil { 109 | panic(err) 110 | } 111 | count++ 112 | 113 | path := row[0].(*age.Path) 114 | 115 | vertexStart := path.GetAsVertex(0) 116 | edge := path.GetAsEdge(1) 117 | vertexEnd := path.GetAsVertex(2) 118 | 119 | fmt.Println(count, "]", vertexStart, edge.Props(), vertexEnd) 120 | } 121 | 122 | // Query with return many columns 123 | cursor, err = tx.ExecCypher(3, "MATCH (a:Person)-[l:workWith]-(b:Person) RETURN a, l, b") 124 | if err != nil { 125 | panic(err) 126 | } 127 | 128 | count = 0 129 | for cursor.Next() { 130 | row, err := cursor.GetRow() 131 | if err != nil { 132 | panic(err) 133 | } 134 | 135 | count++ 136 | 137 | v1 := row[0].(*age.Vertex) 138 | edge := row[1].(*age.Edge) 139 | v2 := row[2].(*age.Vertex) 140 | 141 | fmt.Println("ROW ", count, ">>", "\n\t", v1, "\n\t", edge, "\n\t", v2) 142 | } 143 | 144 | _, err = tx.ExecCypher(0, "MATCH (n:Person) DETACH DELETE n RETURN *") 145 | if err != nil { 146 | panic(err) 147 | } 148 | tx.Commit() 149 | } 150 | -------------------------------------------------------------------------------- /Question-3/Go/samples/main.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package main 20 | 21 | import ( 22 | "fmt" 23 | 24 | _ "github.com/lib/pq" 25 | ) 26 | 27 | // var dsn string = "host={host} port={port} dbname={dbname} user={username} password={password} sslmode=disable" 28 | var dsn string = "host=127.0.0.1 port=5432 dbname=postgres user=postgres password=agens sslmode=disable" 29 | 30 | // var graphName string = "{graph_path}" 31 | var graphName string = "testGraph" 32 | 33 | func main() { 34 | 35 | // Do cypher query to AGE with database/sql Tx API transaction conrol 36 | fmt.Println("# Do cypher query with SQL API") 37 | doWithSqlAPI(dsn, graphName) 38 | 39 | // Do cypher query to AGE with Age API 40 | fmt.Println("# Do cypher query with Age API") 41 | doWithAgeWrapper(dsn, graphName) 42 | } 43 | -------------------------------------------------------------------------------- /Question-3/Go/samples/sql_api_sample.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package main 20 | 21 | import ( 22 | "database/sql" 23 | "fmt" 24 | 25 | "github.com/DS-Popeye/Apache-Internship-Program/Question-3/Go/age" 26 | ) 27 | 28 | // Do cypher query to AGE with database/sql Tx API transaction conrol 29 | func doWithSqlAPI(dsn string, graphName string) { 30 | 31 | // Connect to PostgreSQL 32 | db, err := sql.Open("postgres", dsn) 33 | if err != nil { 34 | panic(err) 35 | } 36 | 37 | // Confirm graph_path created 38 | _, err = age.GetReady(db, graphName) 39 | if err != nil { 40 | panic(err) 41 | } 42 | 43 | // Tx begin for execute create vertex 44 | tx, err := db.Begin() 45 | if err != nil { 46 | panic(err) 47 | } 48 | 49 | // Create vertices with Cypher 50 | _, err = age.ExecCypher(tx, graphName, 0, "CREATE (n:Person {name: '%s', weight:%f})", "Joe", 67.3) 51 | if err != nil { 52 | panic(err) 53 | } 54 | 55 | _, err = age.ExecCypher(tx, graphName, 0, "CREATE (n:Person {name: '%s', weight:77.3, roles:['Dev','marketing']})", "Jack") 56 | if err != nil { 57 | panic(err) 58 | } 59 | 60 | _, err = age.ExecCypher(tx, graphName, 0, "CREATE (n:Person {name: '%s', weight:%d})", "Andy", 59) 61 | if err != nil { 62 | panic(err) 63 | } 64 | 65 | // Commit Tx 66 | tx.Commit() 67 | 68 | // Tx begin for queries 69 | tx, err = db.Begin() 70 | if err != nil { 71 | panic(err) 72 | } 73 | // Query cypher 74 | cypherCursor, err := age.ExecCypher(tx, graphName, 1, "MATCH (n:Person) RETURN n") 75 | if err != nil { 76 | panic(err) 77 | } 78 | // Unmarsal result data to Vertex row by row 79 | for cypherCursor.Next() { 80 | row, err := cypherCursor.GetRow() 81 | if err != nil { 82 | panic(err) 83 | } 84 | vertex := row[0].(*age.Vertex) 85 | fmt.Println(vertex.Id(), vertex.Label(), vertex.Props()) 86 | } 87 | 88 | // Create Paths (Edges) 89 | _, err = age.ExecCypher(tx, graphName, 0, "MATCH (a:Person), (b:Person) WHERE a.name='%s' AND b.name='%s' CREATE (a)-[r:workWith {weight: %d}]->(b)", "Jack", "Joe", 3) 90 | if err != nil { 91 | panic(err) 92 | } 93 | 94 | _, err = age.ExecCypher(tx, graphName, 0, "MATCH (a:Person {name: '%s'}), (b:Person {name: '%s'}) CREATE (a)-[r:workWith {weight: %d}]->(b)", "Joe", "Andy", 7) 95 | if err != nil { 96 | panic(err) 97 | } 98 | 99 | tx.Commit() 100 | 101 | tx, err = db.Begin() 102 | if err != nil { 103 | panic(err) 104 | } 105 | // Query Paths with Cypher 106 | cypherCursor, err = age.ExecCypher(tx, graphName, 1, "MATCH p=()-[:workWith]-() RETURN p") 107 | if err != nil { 108 | panic(err) 109 | } 110 | 111 | for cypherCursor.Next() { 112 | row, err := cypherCursor.GetRow() 113 | if err != nil { 114 | panic(err) 115 | } 116 | 117 | path := row[0].(*age.Path) 118 | vertexStart := path.GetAsVertex(0) 119 | edge := path.GetAsEdge(1) 120 | vertexEnd := path.GetAsVertex(2) 121 | 122 | fmt.Println(vertexStart, edge, vertexEnd) 123 | } 124 | 125 | // Query with return many columns 126 | cursor, err := age.ExecCypher(tx, graphName, 3, "MATCH (a:Person)-[l:workWith]-(b:Person) RETURN a, l, b") 127 | if err != nil { 128 | panic(err) 129 | } 130 | 131 | count := 0 132 | for cursor.Next() { 133 | row, err := cursor.GetRow() 134 | if err != nil { 135 | panic(err) 136 | } 137 | count++ 138 | v1 := row[0].(*age.Vertex) 139 | edge := row[1].(*age.Edge) 140 | v2 := row[2].(*age.Vertex) 141 | fmt.Println("ROW ", count, ">>", "\n\t", v1, "\n\t", edge, "\n\t", v2) 142 | } 143 | 144 | // Delete Vertices 145 | _, err = age.ExecCypher(tx, graphName, 0, "MATCH (n:Person) DETACH DELETE n RETURN *") 146 | if err != nil { 147 | panic(err) 148 | } 149 | tx.Commit() 150 | } 151 | -------------------------------------------------------------------------------- /Question-3/Python/.gitignore: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one 2 | # or more contributor license agreements. See the NOTICE file 3 | # distributed with this work for additional information 4 | # regarding copyright ownership. The ASF licenses this file 5 | # to you under the Apache License, Version 2.0 (the 6 | # "License"); you may not use this file except in compliance 7 | # with the License. You may obtain a copy of the License at 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # Unless required by applicable law or agreed to in writing, 10 | # software distributed under the License is distributed on an 11 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 12 | # KIND, either express or implied. See the License for the 13 | # specific language governing permissions and limitations 14 | # under the License. 15 | 16 | # Local python directory 17 | **/.ipynb_checkpoints/ 18 | **/__pycache__/ 19 | apache_age_py.egg-info/ 20 | apache_age_python.egg-info/ 21 | dist/ 22 | build/ 23 | .DS_Store 24 | 25 | # antlr generated files 26 | **/.antlr/ 27 | **/*.interp 28 | **/*.tokens -------------------------------------------------------------------------------- /Question-3/Python/LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /Question-3/Python/README.md: -------------------------------------------------------------------------------- 1 | # Apache AGE Python Driver 2 | 3 | [Apache AGE](https://age.apache.org/) is a PostgreSQL extension that provides graph database functionality. The goal of the Apache AGE project is to create single storage that can handle both relational and graph model data so that users can use standard ANSI SQL along with openCypher, the Graph query language. This repository hosts the development of the Python driver for this Apache extension (currently in Incubator status). Thanks for checking it out. 4 | 5 | A graph consists of a set of vertices (also called nodes) and edges, where each individual vertex and edge possesses a map of properties. A vertex is the basic object of a graph, that can exist independently of everything else in the graph. An edge creates a directed connection between two vertices. A graph database is simply composed of vertices and edges. This type of database is useful when the meaning is in the relationships between the data. Relational databases can easily handle direct relationships, but indirect relationships are more difficult to deal with in relational databases. A graph database stores relationship information as a first-class entity. Apache AGE gives you the best of both worlds, simultaneously. 6 | 7 | Apache AGE is: 8 | 9 | - **Powerful** -- AGE adds graph database support to the already popular PostgreSQL database: PostgreSQL is used by organizations including Apple, Spotify, and NASA. 10 | - **Flexible** -- AGE allows you to perform openCypher queries, which make complex queries much easier to write. 11 | - **Intelligent** -- AGE allows you to perform graph queries that are the basis for many next level web services such as fraud & intrustion detection, master data management, product recommendations, identity and relationship management, experience personalization, knowledge management and more. 12 | 13 | ### Features 14 | 15 | - Cypher query support for Psycopg2 PostreSQL driver (enables cypher queries directly) 16 | - Deserialize AGE result (AGType) to Vertex, Edge, Path 17 | 18 | ### Requirements 19 | 20 | - Python 3.9 or higher 21 | - Python 22 | - This module runs on [psycopg2](https://www.psycopg.org/) and [antlr4-python3](https://pypi.org/project/antlr4-python3-runtime/) 23 | 24 | ``` 25 | sudo apt-get update 26 | sudo apt-get install python3-dev libpq-dev 27 | pip install --no-binary :all: psycopg2 28 | pip install antlr4-python3-runtime==4.9.2 29 | ``` 30 | 31 | ### Install via PIP 32 | 33 | ``` 34 | pip install apache-age-python 35 | ``` 36 | 37 | ### Build from Source 38 | 39 | ``` 40 | git clone https://github.com/DS-Popeye/Apache-Internship-Program.git 41 | cd Apache-Internship-Program 42 | 43 | python setup.py install 44 | ``` 45 | 46 | ### Getting Started 47 | 48 | - [Jupyter Notebook: Basic Examples](samples/apache-age-basic.ipynb) 49 | - [Jupyter Notebook: More Complex Examples](samples/apache-age-note.ipynb) 50 | 51 | ### Tests 52 | 53 | ``` 54 | python -m unittest -v test_age_py.py 55 | python -m unittest -v test_agtypes.py 56 | ``` 57 | 58 | [Agtype data type conversion tests](samples/apache-age-agtypes.ipynb) 59 | 60 | ### For more information about [Apache AGE](https://age.apache.org/) 61 | 62 | - Apache Incubator Age: https://age.apache.org/ 63 | - Github: https://github.com/apache/incubator-age 64 | - Documentation: https://age.incubator.apache.org/docs/ 65 | - apache-age-python GitHub: https://github.com/DS-Popeye/Apache-Internship-Program 66 | 67 | ### Troubleshooting 68 | 69 | 1. Make sure AGE is installed. 70 | 2. Check to see if AGE is loaded in PostgreSQL. 71 | 72 | ``` 73 | # psql 74 | CREATE EXTENSION age; 75 | LOAD 'age'; 76 | SET search_path = ag_catalog, "$user", public; 77 | ``` 78 | 79 | ### License 80 | 81 | [Apache-2.0 License](https://www.apache.org/licenses/LICENSE-2.0) 82 | -------------------------------------------------------------------------------- /Question-3/Python/__init__.py: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one 2 | # or more contributor license agreements. See the NOTICE file 3 | # distributed with this work for additional information 4 | # regarding copyright ownership. The ASF licenses this file 5 | # to you under the Apache License, Version 2.0 (the 6 | # "License"); you may not use this file except in compliance 7 | # with the License. You may obtain a copy of the License at 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # Unless required by applicable law or agreed to in writing, 10 | # software distributed under the License is distributed on an 11 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 12 | # KIND, either express or implied. See the License for the 13 | # specific language governing permissions and limitations 14 | # under the License. 15 | -------------------------------------------------------------------------------- /Question-3/Python/age/VERSION.py: -------------------------------------------------------------------------------- 1 | 2 | # Licensed to the Apache Software Foundation (ASF) under one 3 | # or more contributor license agreements. See the NOTICE file 4 | # distributed with this work for additional information 5 | # regarding copyright ownership. The ASF licenses this file 6 | # to you under the Apache License, Version 2.0 (the 7 | # "License"); you may not use this file except in compliance 8 | # with the License. You may obtain a copy of the License at 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # Unless required by applicable law or agreed to in writing, 11 | # software distributed under the License is distributed on an 12 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | # KIND, either express or implied. See the License for the 14 | # specific language governing permissions and limitations 15 | # under the License. 16 | 17 | VER_MAJOR = 0 18 | VER_MINOR = 0 19 | VER_MICRO = 4 20 | 21 | VERSION = '.'.join([str(VER_MAJOR),str(VER_MINOR),str(VER_MICRO)]) 22 | -------------------------------------------------------------------------------- /Question-3/Python/age/__init__.py: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one 2 | # or more contributor license agreements. See the NOTICE file 3 | # distributed with this work for additional information 4 | # regarding copyright ownership. The ASF licenses this file 5 | # to you under the Apache License, Version 2.0 (the 6 | # "License"); you may not use this file except in compliance 7 | # with the License. You may obtain a copy of the License at 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # Unless required by applicable law or agreed to in writing, 10 | # software distributed under the License is distributed on an 11 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 12 | # KIND, either express or implied. See the License for the 13 | # specific language governing permissions and limitations 14 | # under the License. 15 | from . import age 16 | from .age import * 17 | from .models import * 18 | from .builder import ResultHandler, DummyResultHandler, parseAgeValue, newResultHandler 19 | from . import VERSION 20 | 21 | def version(): 22 | return VERSION.VERSION 23 | 24 | 25 | def connect(dsn=None, graph=None, connection_factory=None, cursor_factory=None, **kwargs): 26 | ag = Age() 27 | ag.connect(dsn=dsn, graph=graph, connection_factory=connection_factory, cursor_factory=cursor_factory, **kwargs) 28 | return ag 29 | 30 | # Dummy ResultHandler 31 | rawPrinter = DummyResultHandler() 32 | 33 | __name__="age" -------------------------------------------------------------------------------- /Question-3/Python/age/age.py: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one 2 | # or more contributor license agreements. See the NOTICE file 3 | # distributed with this work for additional information 4 | # regarding copyright ownership. The ASF licenses this file 5 | # to you under the Apache License, Version 2.0 (the 6 | # "License"); you may not use this file except in compliance 7 | # with the License. You may obtain a copy of the License at 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # Unless required by applicable law or agreed to in writing, 10 | # software distributed under the License is distributed on an 11 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 12 | # KIND, either express or implied. See the License for the 13 | # specific language governing permissions and limitations 14 | # under the License. 15 | import re 16 | import psycopg2 17 | from psycopg2 import errors 18 | from psycopg2 import extensions as ext 19 | from .exceptions import * 20 | from .builder import ResultHandler , parseAgeValue, newResultHandler 21 | 22 | 23 | _EXCEPTION_NoConnection = NoConnection() 24 | _EXCEPTION_GraphNotSet = GraphNotSet() 25 | 26 | WHITESPACE = re.compile('\s') 27 | 28 | def setUpAge(conn:ext.connection, graphName:str): 29 | with conn.cursor() as cursor: 30 | cursor.execute("LOAD 'age';") 31 | cursor.execute("SET search_path = ag_catalog, '$user', public;") 32 | 33 | cursor.execute("SELECT typelem FROM pg_type WHERE typname='_agtype'") 34 | oid = cursor.fetchone()[0] 35 | if oid == None : 36 | raise AgeNotSet() 37 | 38 | AGETYPE = ext.new_type((oid,), 'AGETYPE', parseAgeValue) 39 | ext.register_type(AGETYPE) 40 | # ext.register_adapter(Path, marshalAgtValue) 41 | 42 | # Check graph exists 43 | if graphName != None: 44 | checkGraphCreated(conn, graphName) 45 | 46 | # Create the graph, if it does not exist 47 | def checkGraphCreated(conn:ext.connection, graphName:str): 48 | with conn.cursor() as cursor: 49 | cursor.execute("SELECT count(*) FROM ag_graph WHERE name=%s", (graphName,)) 50 | if cursor.fetchone()[0] == 0: 51 | cursor.execute("SELECT create_graph(%s);", (graphName,)) 52 | conn.commit() 53 | 54 | 55 | def deleteGraph(conn:ext.connection, graphName:str): 56 | with conn.cursor() as cursor: 57 | cursor.execute("SELECT drop_graph(%s, true);", (graphName,)) 58 | conn.commit() 59 | 60 | 61 | def buildCypher(graphName:str, cypherStmt:str, columns:list) ->str: 62 | if graphName == None: 63 | raise _EXCEPTION_GraphNotSet 64 | 65 | columnExp=[] 66 | if columns != None and len(columns) > 0: 67 | for col in columns: 68 | if col.strip() == '': 69 | continue 70 | elif WHITESPACE.search(col) != None: 71 | columnExp.append(col) 72 | else: 73 | columnExp.append(col + " agtype") 74 | else: 75 | columnExp.append('v agtype') 76 | 77 | stmtArr = [] 78 | stmtArr.append("SELECT * from cypher('") 79 | stmtArr.append(graphName) 80 | stmtArr.append("', $$ ") 81 | stmtArr.append(cypherStmt) 82 | stmtArr.append(" $$) as (") 83 | stmtArr.append(','.join(columnExp)) 84 | stmtArr.append(");") 85 | return "".join(stmtArr) 86 | 87 | def execSql(conn:ext.connection, stmt:str, commit:bool=False, params:tuple=None) -> ext.cursor : 88 | if conn == None or conn.closed: 89 | raise _EXCEPTION_NoConnection 90 | 91 | cursor = conn.cursor() 92 | try: 93 | cursor.execute(stmt, params) 94 | if commit: 95 | conn.commit() 96 | 97 | return cursor 98 | except SyntaxError as cause: 99 | conn.rollback() 100 | raise cause 101 | except Exception as cause: 102 | conn.rollback() 103 | raise SqlExcutionError("Excution ERR[" + str(cause) +"](" + stmt +")", cause) 104 | 105 | 106 | def querySql(conn:ext.connection, stmt:str, params:tuple=None) -> ext.cursor : 107 | return execSql(conn, stmt, False, params) 108 | 109 | # Execute cypher statement and return cursor. 110 | # If cypher statement changes data (create, set, remove), 111 | # You must commit session(ag.commit()) 112 | # (Otherwise the execution cannot make any effect.) 113 | def execCypher(conn:ext.connection, graphName:str, cypherStmt:str, cols:list=None, params:tuple=None) -> ext.cursor : 114 | if conn == None or conn.closed: 115 | raise _EXCEPTION_NoConnection 116 | 117 | stmt = buildCypher(graphName, cypherStmt, cols) 118 | 119 | cursor = conn.cursor() 120 | try: 121 | cursor.execute(stmt, params) 122 | return cursor 123 | except SyntaxError as cause: 124 | conn.rollback() 125 | raise cause 126 | except Exception as cause: 127 | conn.rollback() 128 | raise SqlExcutionError("Excution ERR[" + str(cause) +"](" + stmt +")", cause) 129 | 130 | 131 | def cypher(cursor:ext.cursor, graphName:str, cypherStmt:str, cols:list=None, params:tuple=None) -> ext.cursor : 132 | stmt = buildCypher(graphName, cypherStmt, cols) 133 | cursor.execute(stmt, params) 134 | 135 | 136 | # def execCypherWithReturn(conn:ext.connection, graphName:str, cypherStmt:str, columns:list=None , params:tuple=None) -> ext.cursor : 137 | # stmt = buildCypher(graphName, cypherStmt, columns) 138 | # return execSql(conn, stmt, False, params) 139 | 140 | # def queryCypher(conn:ext.connection, graphName:str, cypherStmt:str, columns:list=None , params:tuple=None) -> ext.cursor : 141 | # return execCypherWithReturn(conn, graphName, cypherStmt, columns, params) 142 | 143 | 144 | class Age: 145 | def __init__(self): 146 | self.connection = None # psycopg2 connection] 147 | self.graphName = None 148 | 149 | # Connect to PostgreSQL Server and establish session and type extension environment. 150 | def connect(self, graph:str=None, dsn:str=None, connection_factory=None, cursor_factory=None, **kwargs): 151 | conn = psycopg2.connect(dsn, connection_factory, cursor_factory, **kwargs) 152 | setUpAge(conn, graph) 153 | self.connection = conn 154 | self.graphName = graph 155 | return self 156 | 157 | def connect_new(self, graph, conn): 158 | setUpAge(conn, graph) 159 | self.connection = conn 160 | self.graphName = graph 161 | 162 | def close(self): 163 | self.connection.close() 164 | 165 | def setGraph(self, graph:str): 166 | checkGraphCreated(self.connection, graph) 167 | self.graphName = graph 168 | return self 169 | 170 | def commit(self): 171 | self.connection.commit() 172 | 173 | def rollback(self): 174 | self.connection.rollback() 175 | 176 | def execCypher(self, cypherStmt:str, cols:list=None, params:tuple=None) -> ext.cursor : 177 | return execCypher(self.connection, self.graphName, cypherStmt, cols=cols, params=params) 178 | 179 | def cypher(self, cursor:ext.cursor, cypherStmt:str, cols:list=None, params:tuple=None) -> ext.cursor : 180 | return cypher(cursor, self.graphName, cypherStmt, cols=cols, params=params) 181 | 182 | # def execSql(self, stmt:str, commit:bool=False, params:tuple=None) -> ext.cursor : 183 | # return execSql(self.connection, stmt, commit, params) 184 | 185 | 186 | # def execCypher(self, cypherStmt:str, commit:bool=False, params:tuple=None) -> ext.cursor : 187 | # return execCypher(self.connection, self.graphName, cypherStmt, commit, params) 188 | 189 | # def execCypherWithReturn(self, cypherStmt:str, columns:list=None , params:tuple=None) -> ext.cursor : 190 | # return execCypherWithReturn(self.connection, self.graphName, cypherStmt, columns, params) 191 | 192 | # def queryCypher(self, cypherStmt:str, columns:list=None , params:tuple=None) -> ext.cursor : 193 | # return queryCypher(self.connection, self.graphName, cypherStmt, columns, params) 194 | 195 | 196 | 197 | -------------------------------------------------------------------------------- /Question-3/Python/age/builder.py: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one 2 | # or more contributor license agreements. See the NOTICE file 3 | # distributed with this work for additional information 4 | # regarding copyright ownership. The ASF licenses this file 5 | # to you under the Apache License, Version 2.0 (the 6 | # "License"); you may not use this file except in compliance 7 | # with the License. You may obtain a copy of the License at 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # Unless required by applicable law or agreed to in writing, 10 | # software distributed under the License is distributed on an 11 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 12 | # KIND, either express or implied. See the License for the 13 | # specific language governing permissions and limitations 14 | # under the License. 15 | from . import gen 16 | from .gen.AgtypeLexer import AgtypeLexer 17 | from .gen.AgtypeParser import AgtypeParser 18 | from .gen.AgtypeVisitor import AgtypeVisitor 19 | from .models import * 20 | from .exceptions import * 21 | from antlr4 import * 22 | from antlr4.tree.Tree import * 23 | from decimal import Decimal 24 | 25 | class ResultHandler: 26 | def parse(ageData): 27 | pass 28 | 29 | def newResultHandler(query=""): 30 | resultHandler = Antlr4ResultHandler(None, query) 31 | return resultHandler 32 | 33 | def parseAgeValue(value, cursor=None): 34 | if value is None: 35 | return None 36 | 37 | resultHandler = Antlr4ResultHandler(None) 38 | try: 39 | return resultHandler.parse(value) 40 | except Exception as ex: 41 | raise AGTypeError(value) 42 | 43 | 44 | class Antlr4ResultHandler(ResultHandler): 45 | def __init__(self, vertexCache, query=None): 46 | self.lexer = AgtypeLexer() 47 | self.parser = AgtypeParser(None) 48 | self.visitor = ResultVisitor(vertexCache) 49 | 50 | def parse(self, ageData): 51 | if not ageData: 52 | return None 53 | # print("Parse::", ageData) 54 | 55 | self.lexer.inputStream = InputStream(ageData) 56 | self.parser.setTokenStream(CommonTokenStream(self.lexer)) 57 | self.parser.reset() 58 | tree = self.parser.agType() 59 | parsed = tree.accept(self.visitor) 60 | return parsed 61 | 62 | 63 | # print raw result String 64 | class DummyResultHandler(ResultHandler): 65 | def parse(self, ageData): 66 | print(ageData) 67 | 68 | # default agType visitor 69 | class ResultVisitor(AgtypeVisitor): 70 | vertexCache = None 71 | 72 | def __init__(self, cache) -> None: 73 | super().__init__() 74 | self.vertexCache = cache 75 | 76 | 77 | def visitAgType(self, ctx:AgtypeParser.AgTypeContext): 78 | agVal = ctx.agValue() 79 | if agVal != None: 80 | obj = ctx.agValue().accept(self) 81 | return obj 82 | 83 | return None 84 | 85 | def visitAgValue(self, ctx:AgtypeParser.AgValueContext): 86 | annoCtx = ctx.typeAnnotation() 87 | valueCtx = ctx.value() 88 | 89 | if annoCtx is not None: 90 | annoCtx.accept(self) 91 | anno = annoCtx.IDENT().getText() 92 | return self.handleAnnotatedValue(anno, valueCtx) 93 | else: 94 | return valueCtx.accept(self) 95 | 96 | 97 | # Visit a parse tree produced by AgtypeParser#StringValue. 98 | def visitStringValue(self, ctx:AgtypeParser.StringValueContext): 99 | return ctx.STRING().getText().strip('"') 100 | 101 | 102 | # Visit a parse tree produced by AgtypeParser#IntegerValue. 103 | def visitIntegerValue(self, ctx:AgtypeParser.IntegerValueContext): 104 | return int(ctx.INTEGER().getText()) 105 | 106 | # Visit a parse tree produced by AgtypeParser#floatLiteral. 107 | def visitFloatLiteral(self, ctx:AgtypeParser.FloatLiteralContext): 108 | c = ctx.getChild(0) 109 | tp = c.symbol.type 110 | text = ctx.getText() 111 | if tp == AgtypeParser.RegularFloat: 112 | return float(text) 113 | elif tp == AgtypeParser.ExponentFloat: 114 | return float(text) 115 | else: 116 | if text == 'NaN': 117 | return float('nan') 118 | elif text == '-Infinity': 119 | return float('-inf') 120 | elif text == 'Infinity': 121 | return float('inf') 122 | else: 123 | return Exception("Unknown float expression:"+text) 124 | 125 | 126 | # Visit a parse tree produced by AgtypeParser#TrueBoolean. 127 | def visitTrueBoolean(self, ctx:AgtypeParser.TrueBooleanContext): 128 | return True 129 | 130 | 131 | # Visit a parse tree produced by AgtypeParser#FalseBoolean. 132 | def visitFalseBoolean(self, ctx:AgtypeParser.FalseBooleanContext): 133 | return False 134 | 135 | 136 | # Visit a parse tree produced by AgtypeParser#NullValue. 137 | def visitNullValue(self, ctx:AgtypeParser.NullValueContext): 138 | return None 139 | 140 | 141 | # Visit a parse tree produced by AgtypeParser#obj. 142 | def visitObj(self, ctx:AgtypeParser.ObjContext): 143 | obj = dict() 144 | for c in ctx.getChildren(): 145 | if isinstance(c, AgtypeParser.PairContext): 146 | namVal = self.visitPair(c) 147 | name = namVal[0] 148 | valCtx = namVal[1] 149 | val = valCtx.accept(self) 150 | obj[name] = val 151 | return obj 152 | 153 | 154 | # Visit a parse tree produced by AgtypeParser#pair. 155 | def visitPair(self, ctx:AgtypeParser.PairContext): 156 | self.visitChildren(ctx) 157 | return (ctx.STRING().getText().strip('"') , ctx.agValue()) 158 | 159 | 160 | # Visit a parse tree produced by AgtypeParser#array. 161 | def visitArray(self, ctx:AgtypeParser.ArrayContext): 162 | li = list() 163 | for c in ctx.getChildren(): 164 | if not isinstance(c, TerminalNode): 165 | val = c.accept(self) 166 | li.append(val) 167 | return li 168 | 169 | def handleAnnotatedValue(self, anno:str, ctx:ParserRuleContext): 170 | if anno == "numeric": 171 | return Decimal(ctx.getText()) 172 | elif anno == "vertex": 173 | dict = ctx.accept(self) 174 | vid = dict["id"] 175 | vertex = None 176 | if self.vertexCache != None and vid in self.vertexCache : 177 | vertex = self.vertexCache[vid] 178 | else: 179 | vertex = Vertex() 180 | vertex.id = dict["id"] 181 | vertex.label = dict["label"] 182 | vertex.properties = dict["properties"] 183 | 184 | if self.vertexCache != None: 185 | self.vertexCache[vid] = vertex 186 | 187 | return vertex 188 | 189 | elif anno == "edge": 190 | edge = Edge() 191 | dict = ctx.accept(self) 192 | edge.id = dict["id"] 193 | edge.label = dict["label"] 194 | edge.end_id = dict["end_id"] 195 | edge.start_id = dict["start_id"] 196 | edge.properties = dict["properties"] 197 | 198 | return edge 199 | 200 | elif anno == "path": 201 | arr = ctx.accept(self) 202 | path = Path(arr) 203 | 204 | return path 205 | 206 | return ctx.accept(self) 207 | -------------------------------------------------------------------------------- /Question-3/Python/age/exceptions.py: -------------------------------------------------------------------------------- 1 | 2 | # Licensed to the Apache Software Foundation (ASF) under one 3 | # or more contributor license agreements. See the NOTICE file 4 | # distributed with this work for additional information 5 | # regarding copyright ownership. The ASF licenses this file 6 | # to you under the Apache License, Version 2.0 (the 7 | # "License"); you may not use this file except in compliance 8 | # with the License. You may obtain a copy of the License at 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # Unless required by applicable law or agreed to in writing, 11 | # software distributed under the License is distributed on an 12 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | # KIND, either express or implied. See the License for the 14 | # specific language governing permissions and limitations 15 | # under the License. 16 | from psycopg2.errors import * 17 | 18 | class AgeNotSet(Exception): 19 | def __init__(self, name): 20 | self.name = name 21 | 22 | def __repr__(self) : 23 | return 'AGE extension is not set.' 24 | 25 | class GraphNotFound(Exception): 26 | def __init__(self, name): 27 | self.name = name 28 | 29 | def __repr__(self) : 30 | return 'Graph[' + self.name + '] does not exist.' 31 | 32 | 33 | class GraphAlreadyExists(Exception): 34 | def __init__(self, name): 35 | self.name = name 36 | 37 | def __repr__(self) : 38 | return 'Graph[' + self.name + '] already exists.' 39 | 40 | 41 | class GraphNotSet(Exception): 42 | def __repr__(self) : 43 | return 'Graph name is not set.' 44 | 45 | 46 | class NoConnection(Exception): 47 | def __repr__(self) : 48 | return 'No Connection' 49 | 50 | class NoCursor(Exception): 51 | def __repr__(self) : 52 | return 'No Cursor' 53 | 54 | class SqlExcutionError(Exception): 55 | def __init__(self, msg, cause): 56 | self.msg = msg 57 | self.cause = cause 58 | super().__init__(msg, cause) 59 | 60 | def __repr__(self) : 61 | return 'SqlExcution [' + self.msg + ']' 62 | 63 | class AGTypeError(Exception): 64 | def __init__(self, msg, cause): 65 | self.msg = msg 66 | self.cause = cause 67 | super().__init__(msg, cause) 68 | 69 | 70 | -------------------------------------------------------------------------------- /Question-3/Python/age/gen/AgtypeLexer.py: -------------------------------------------------------------------------------- 1 | # Generated from Agtype.g4 by ANTLR 4.9.2 2 | from antlr4 import * 3 | from io import StringIO 4 | import sys 5 | if sys.version_info[1] > 5: 6 | from typing import TextIO 7 | else: 8 | from typing.io import TextIO 9 | 10 | 11 | 12 | def serializedATN(): 13 | with StringIO() as buf: 14 | buf.write("\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\2\25") 15 | buf.write("\u00b9\b\1\4\2\t\2\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7") 16 | buf.write("\t\7\4\b\t\b\4\t\t\t\4\n\t\n\4\13\t\13\4\f\t\f\4\r\t\r") 17 | buf.write("\4\16\t\16\4\17\t\17\4\20\t\20\4\21\t\21\4\22\t\22\4\23") 18 | buf.write("\t\23\4\24\t\24\4\25\t\25\4\26\t\26\4\27\t\27\4\30\t\30") 19 | buf.write("\4\31\t\31\4\32\t\32\4\33\t\33\3\2\3\2\3\2\3\2\3\2\3\3") 20 | buf.write("\3\3\3\3\3\3\3\3\3\3\3\4\3\4\3\4\3\4\3\4\3\5\3\5\3\6\3") 21 | buf.write("\6\3\7\3\7\3\b\3\b\3\t\3\t\3\n\3\n\3\13\3\13\3\13\3\f") 22 | buf.write("\3\f\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\16\3\16\3\16") 23 | buf.write("\3\16\3\17\3\17\7\17h\n\17\f\17\16\17k\13\17\3\20\3\20") 24 | buf.write("\3\20\7\20p\n\20\f\20\16\20s\13\20\3\20\3\20\3\21\3\21") 25 | buf.write("\3\21\5\21z\n\21\3\22\3\22\3\22\3\22\3\22\3\22\3\23\3") 26 | buf.write("\23\3\24\3\24\3\25\5\25\u0087\n\25\3\25\3\25\3\26\3\26") 27 | buf.write("\3\26\7\26\u008e\n\26\f\26\16\26\u0091\13\26\5\26\u0093") 28 | buf.write("\n\26\3\27\5\27\u0096\n\27\3\27\3\27\3\27\3\30\5\30\u009c") 29 | buf.write("\n\30\3\30\3\30\5\30\u00a0\n\30\3\30\3\30\3\31\3\31\6") 30 | buf.write("\31\u00a6\n\31\r\31\16\31\u00a7\3\32\3\32\5\32\u00ac\n") 31 | buf.write("\32\3\32\6\32\u00af\n\32\r\32\16\32\u00b0\3\33\6\33\u00b4") 32 | buf.write("\n\33\r\33\16\33\u00b5\3\33\3\33\2\2\34\3\3\5\4\7\5\t") 33 | buf.write("\6\13\7\r\b\17\t\21\n\23\13\25\f\27\r\31\16\33\17\35\20") 34 | buf.write("\37\21!\2#\2%\2\'\2)\22+\2-\23/\24\61\2\63\2\65\25\3\2") 35 | buf.write("\f\5\2C\\aac|\7\2&&\62;C\\aac|\n\2$$\61\61^^ddhhppttv") 36 | buf.write("v\5\2\62;CHch\5\2\2!$$^^\3\2\63;\3\2\62;\4\2GGgg\4\2-") 37 | buf.write("-//\5\2\13\f\17\17\"\"\2\u00bf\2\3\3\2\2\2\2\5\3\2\2\2") 38 | buf.write("\2\7\3\2\2\2\2\t\3\2\2\2\2\13\3\2\2\2\2\r\3\2\2\2\2\17") 39 | buf.write("\3\2\2\2\2\21\3\2\2\2\2\23\3\2\2\2\2\25\3\2\2\2\2\27\3") 40 | buf.write("\2\2\2\2\31\3\2\2\2\2\33\3\2\2\2\2\35\3\2\2\2\2\37\3\2") 41 | buf.write("\2\2\2)\3\2\2\2\2-\3\2\2\2\2/\3\2\2\2\2\65\3\2\2\2\3\67") 42 | buf.write("\3\2\2\2\5<\3\2\2\2\7B\3\2\2\2\tG\3\2\2\2\13I\3\2\2\2") 43 | buf.write("\rK\3\2\2\2\17M\3\2\2\2\21O\3\2\2\2\23Q\3\2\2\2\25S\3") 44 | buf.write("\2\2\2\27V\3\2\2\2\31X\3\2\2\2\33a\3\2\2\2\35e\3\2\2\2") 45 | buf.write("\37l\3\2\2\2!v\3\2\2\2#{\3\2\2\2%\u0081\3\2\2\2\'\u0083") 46 | buf.write("\3\2\2\2)\u0086\3\2\2\2+\u0092\3\2\2\2-\u0095\3\2\2\2") 47 | buf.write("/\u009b\3\2\2\2\61\u00a3\3\2\2\2\63\u00a9\3\2\2\2\65\u00b3") 48 | buf.write("\3\2\2\2\678\7v\2\289\7t\2\29:\7w\2\2:;\7g\2\2;\4\3\2") 49 | buf.write("\2\2<=\7h\2\2=>\7c\2\2>?\7n\2\2?@\7u\2\2@A\7g\2\2A\6\3") 50 | buf.write("\2\2\2BC\7p\2\2CD\7w\2\2DE\7n\2\2EF\7n\2\2F\b\3\2\2\2") 51 | buf.write("GH\7}\2\2H\n\3\2\2\2IJ\7.\2\2J\f\3\2\2\2KL\7\177\2\2L") 52 | buf.write("\16\3\2\2\2MN\7<\2\2N\20\3\2\2\2OP\7]\2\2P\22\3\2\2\2") 53 | buf.write("QR\7_\2\2R\24\3\2\2\2ST\7<\2\2TU\7<\2\2U\26\3\2\2\2VW") 54 | buf.write("\7/\2\2W\30\3\2\2\2XY\7K\2\2YZ\7p\2\2Z[\7h\2\2[\\\7k\2") 55 | buf.write("\2\\]\7p\2\2]^\7k\2\2^_\7v\2\2_`\7{\2\2`\32\3\2\2\2ab") 56 | buf.write("\7P\2\2bc\7c\2\2cd\7P\2\2d\34\3\2\2\2ei\t\2\2\2fh\t\3") 57 | buf.write("\2\2gf\3\2\2\2hk\3\2\2\2ig\3\2\2\2ij\3\2\2\2j\36\3\2\2") 58 | buf.write("\2ki\3\2\2\2lq\7$\2\2mp\5!\21\2np\5\'\24\2om\3\2\2\2o") 59 | buf.write("n\3\2\2\2ps\3\2\2\2qo\3\2\2\2qr\3\2\2\2rt\3\2\2\2sq\3") 60 | buf.write("\2\2\2tu\7$\2\2u \3\2\2\2vy\7^\2\2wz\t\4\2\2xz\5#\22\2") 61 | buf.write("yw\3\2\2\2yx\3\2\2\2z\"\3\2\2\2{|\7w\2\2|}\5%\23\2}~\5") 62 | buf.write("%\23\2~\177\5%\23\2\177\u0080\5%\23\2\u0080$\3\2\2\2\u0081") 63 | buf.write("\u0082\t\5\2\2\u0082&\3\2\2\2\u0083\u0084\n\6\2\2\u0084") 64 | buf.write("(\3\2\2\2\u0085\u0087\7/\2\2\u0086\u0085\3\2\2\2\u0086") 65 | buf.write("\u0087\3\2\2\2\u0087\u0088\3\2\2\2\u0088\u0089\5+\26\2") 66 | buf.write("\u0089*\3\2\2\2\u008a\u0093\7\62\2\2\u008b\u008f\t\7\2") 67 | buf.write("\2\u008c\u008e\t\b\2\2\u008d\u008c\3\2\2\2\u008e\u0091") 68 | buf.write("\3\2\2\2\u008f\u008d\3\2\2\2\u008f\u0090\3\2\2\2\u0090") 69 | buf.write("\u0093\3\2\2\2\u0091\u008f\3\2\2\2\u0092\u008a\3\2\2\2") 70 | buf.write("\u0092\u008b\3\2\2\2\u0093,\3\2\2\2\u0094\u0096\7/\2\2") 71 | buf.write("\u0095\u0094\3\2\2\2\u0095\u0096\3\2\2\2\u0096\u0097\3") 72 | buf.write("\2\2\2\u0097\u0098\5+\26\2\u0098\u0099\5\61\31\2\u0099") 73 | buf.write(".\3\2\2\2\u009a\u009c\7/\2\2\u009b\u009a\3\2\2\2\u009b") 74 | buf.write("\u009c\3\2\2\2\u009c\u009d\3\2\2\2\u009d\u009f\5+\26\2") 75 | buf.write("\u009e\u00a0\5\61\31\2\u009f\u009e\3\2\2\2\u009f\u00a0") 76 | buf.write("\3\2\2\2\u00a0\u00a1\3\2\2\2\u00a1\u00a2\5\63\32\2\u00a2") 77 | buf.write("\60\3\2\2\2\u00a3\u00a5\7\60\2\2\u00a4\u00a6\t\b\2\2\u00a5") 78 | buf.write("\u00a4\3\2\2\2\u00a6\u00a7\3\2\2\2\u00a7\u00a5\3\2\2\2") 79 | buf.write("\u00a7\u00a8\3\2\2\2\u00a8\62\3\2\2\2\u00a9\u00ab\t\t") 80 | buf.write("\2\2\u00aa\u00ac\t\n\2\2\u00ab\u00aa\3\2\2\2\u00ab\u00ac") 81 | buf.write("\3\2\2\2\u00ac\u00ae\3\2\2\2\u00ad\u00af\t\b\2\2\u00ae") 82 | buf.write("\u00ad\3\2\2\2\u00af\u00b0\3\2\2\2\u00b0\u00ae\3\2\2\2") 83 | buf.write("\u00b0\u00b1\3\2\2\2\u00b1\64\3\2\2\2\u00b2\u00b4\t\13") 84 | buf.write("\2\2\u00b3\u00b2\3\2\2\2\u00b4\u00b5\3\2\2\2\u00b5\u00b3") 85 | buf.write("\3\2\2\2\u00b5\u00b6\3\2\2\2\u00b6\u00b7\3\2\2\2\u00b7") 86 | buf.write("\u00b8\b\33\2\2\u00b8\66\3\2\2\2\21\2ioqy\u0086\u008f") 87 | buf.write("\u0092\u0095\u009b\u009f\u00a7\u00ab\u00b0\u00b5\3\b\2") 88 | buf.write("\2") 89 | return buf.getvalue() 90 | 91 | 92 | class AgtypeLexer(Lexer): 93 | 94 | atn = ATNDeserializer().deserialize(serializedATN()) 95 | 96 | decisionsToDFA = [ DFA(ds, i) for i, ds in enumerate(atn.decisionToState) ] 97 | 98 | T__0 = 1 99 | T__1 = 2 100 | T__2 = 3 101 | T__3 = 4 102 | T__4 = 5 103 | T__5 = 6 104 | T__6 = 7 105 | T__7 = 8 106 | T__8 = 9 107 | T__9 = 10 108 | T__10 = 11 109 | T__11 = 12 110 | T__12 = 13 111 | IDENT = 14 112 | STRING = 15 113 | INTEGER = 16 114 | RegularFloat = 17 115 | ExponentFloat = 18 116 | WS = 19 117 | 118 | channelNames = [ u"DEFAULT_TOKEN_CHANNEL", u"HIDDEN" ] 119 | 120 | modeNames = [ "DEFAULT_MODE" ] 121 | 122 | literalNames = [ "", 123 | "'true'", "'false'", "'null'", "'{'", "','", "'}'", "':'", "'['", 124 | "']'", "'::'", "'-'", "'Infinity'", "'NaN'" ] 125 | 126 | symbolicNames = [ "", 127 | "IDENT", "STRING", "INTEGER", "RegularFloat", "ExponentFloat", 128 | "WS" ] 129 | 130 | ruleNames = [ "T__0", "T__1", "T__2", "T__3", "T__4", "T__5", "T__6", 131 | "T__7", "T__8", "T__9", "T__10", "T__11", "T__12", "IDENT", 132 | "STRING", "ESC", "UNICODE", "HEX", "SAFECODEPOINT", "INTEGER", 133 | "INT", "RegularFloat", "ExponentFloat", "DECIMAL", "SCIENTIFIC", 134 | "WS" ] 135 | 136 | grammarFileName = "Agtype.g4" 137 | 138 | def __init__(self, input=None, output:TextIO = sys.stdout): 139 | super().__init__(input, output) 140 | self.checkVersion("4.9.2") 141 | self._interp = LexerATNSimulator(self, self.atn, self.decisionsToDFA, PredictionContextCache()) 142 | self._actions = None 143 | self._predicates = None 144 | 145 | 146 | -------------------------------------------------------------------------------- /Question-3/Python/age/gen/AgtypeListener.py: -------------------------------------------------------------------------------- 1 | # Generated from Agtype.g4 by ANTLR 4.9.2 2 | from antlr4 import * 3 | if __name__ is not None and "." in __name__: 4 | from .AgtypeParser import AgtypeParser 5 | else: 6 | from AgtypeParser import AgtypeParser 7 | 8 | # This class defines a complete listener for a parse tree produced by AgtypeParser. 9 | class AgtypeListener(ParseTreeListener): 10 | 11 | # Enter a parse tree produced by AgtypeParser#agType. 12 | def enterAgType(self, ctx:AgtypeParser.AgTypeContext): 13 | pass 14 | 15 | # Exit a parse tree produced by AgtypeParser#agType. 16 | def exitAgType(self, ctx:AgtypeParser.AgTypeContext): 17 | pass 18 | 19 | 20 | # Enter a parse tree produced by AgtypeParser#agValue. 21 | def enterAgValue(self, ctx:AgtypeParser.AgValueContext): 22 | pass 23 | 24 | # Exit a parse tree produced by AgtypeParser#agValue. 25 | def exitAgValue(self, ctx:AgtypeParser.AgValueContext): 26 | pass 27 | 28 | 29 | # Enter a parse tree produced by AgtypeParser#StringValue. 30 | def enterStringValue(self, ctx:AgtypeParser.StringValueContext): 31 | pass 32 | 33 | # Exit a parse tree produced by AgtypeParser#StringValue. 34 | def exitStringValue(self, ctx:AgtypeParser.StringValueContext): 35 | pass 36 | 37 | 38 | # Enter a parse tree produced by AgtypeParser#IntegerValue. 39 | def enterIntegerValue(self, ctx:AgtypeParser.IntegerValueContext): 40 | pass 41 | 42 | # Exit a parse tree produced by AgtypeParser#IntegerValue. 43 | def exitIntegerValue(self, ctx:AgtypeParser.IntegerValueContext): 44 | pass 45 | 46 | 47 | # Enter a parse tree produced by AgtypeParser#FloatValue. 48 | def enterFloatValue(self, ctx:AgtypeParser.FloatValueContext): 49 | pass 50 | 51 | # Exit a parse tree produced by AgtypeParser#FloatValue. 52 | def exitFloatValue(self, ctx:AgtypeParser.FloatValueContext): 53 | pass 54 | 55 | 56 | # Enter a parse tree produced by AgtypeParser#TrueBoolean. 57 | def enterTrueBoolean(self, ctx:AgtypeParser.TrueBooleanContext): 58 | pass 59 | 60 | # Exit a parse tree produced by AgtypeParser#TrueBoolean. 61 | def exitTrueBoolean(self, ctx:AgtypeParser.TrueBooleanContext): 62 | pass 63 | 64 | 65 | # Enter a parse tree produced by AgtypeParser#FalseBoolean. 66 | def enterFalseBoolean(self, ctx:AgtypeParser.FalseBooleanContext): 67 | pass 68 | 69 | # Exit a parse tree produced by AgtypeParser#FalseBoolean. 70 | def exitFalseBoolean(self, ctx:AgtypeParser.FalseBooleanContext): 71 | pass 72 | 73 | 74 | # Enter a parse tree produced by AgtypeParser#NullValue. 75 | def enterNullValue(self, ctx:AgtypeParser.NullValueContext): 76 | pass 77 | 78 | # Exit a parse tree produced by AgtypeParser#NullValue. 79 | def exitNullValue(self, ctx:AgtypeParser.NullValueContext): 80 | pass 81 | 82 | 83 | # Enter a parse tree produced by AgtypeParser#ObjectValue. 84 | def enterObjectValue(self, ctx:AgtypeParser.ObjectValueContext): 85 | pass 86 | 87 | # Exit a parse tree produced by AgtypeParser#ObjectValue. 88 | def exitObjectValue(self, ctx:AgtypeParser.ObjectValueContext): 89 | pass 90 | 91 | 92 | # Enter a parse tree produced by AgtypeParser#ArrayValue. 93 | def enterArrayValue(self, ctx:AgtypeParser.ArrayValueContext): 94 | pass 95 | 96 | # Exit a parse tree produced by AgtypeParser#ArrayValue. 97 | def exitArrayValue(self, ctx:AgtypeParser.ArrayValueContext): 98 | pass 99 | 100 | 101 | # Enter a parse tree produced by AgtypeParser#obj. 102 | def enterObj(self, ctx:AgtypeParser.ObjContext): 103 | pass 104 | 105 | # Exit a parse tree produced by AgtypeParser#obj. 106 | def exitObj(self, ctx:AgtypeParser.ObjContext): 107 | pass 108 | 109 | 110 | # Enter a parse tree produced by AgtypeParser#pair. 111 | def enterPair(self, ctx:AgtypeParser.PairContext): 112 | pass 113 | 114 | # Exit a parse tree produced by AgtypeParser#pair. 115 | def exitPair(self, ctx:AgtypeParser.PairContext): 116 | pass 117 | 118 | 119 | # Enter a parse tree produced by AgtypeParser#array. 120 | def enterArray(self, ctx:AgtypeParser.ArrayContext): 121 | pass 122 | 123 | # Exit a parse tree produced by AgtypeParser#array. 124 | def exitArray(self, ctx:AgtypeParser.ArrayContext): 125 | pass 126 | 127 | 128 | # Enter a parse tree produced by AgtypeParser#typeAnnotation. 129 | def enterTypeAnnotation(self, ctx:AgtypeParser.TypeAnnotationContext): 130 | pass 131 | 132 | # Exit a parse tree produced by AgtypeParser#typeAnnotation. 133 | def exitTypeAnnotation(self, ctx:AgtypeParser.TypeAnnotationContext): 134 | pass 135 | 136 | 137 | # Enter a parse tree produced by AgtypeParser#floatLiteral. 138 | def enterFloatLiteral(self, ctx:AgtypeParser.FloatLiteralContext): 139 | pass 140 | 141 | # Exit a parse tree produced by AgtypeParser#floatLiteral. 142 | def exitFloatLiteral(self, ctx:AgtypeParser.FloatLiteralContext): 143 | pass 144 | 145 | 146 | 147 | del AgtypeParser -------------------------------------------------------------------------------- /Question-3/Python/age/gen/AgtypeVisitor.py: -------------------------------------------------------------------------------- 1 | # Generated from Agtype.g4 by ANTLR 4.9.2 2 | from antlr4 import * 3 | if __name__ is not None and "." in __name__: 4 | from .AgtypeParser import AgtypeParser 5 | else: 6 | from AgtypeParser import AgtypeParser 7 | 8 | # This class defines a complete generic visitor for a parse tree produced by AgtypeParser. 9 | 10 | class AgtypeVisitor(ParseTreeVisitor): 11 | 12 | # Visit a parse tree produced by AgtypeParser#agType. 13 | def visitAgType(self, ctx:AgtypeParser.AgTypeContext): 14 | return self.visitChildren(ctx) 15 | 16 | 17 | # Visit a parse tree produced by AgtypeParser#agValue. 18 | def visitAgValue(self, ctx:AgtypeParser.AgValueContext): 19 | return self.visitChildren(ctx) 20 | 21 | 22 | # Visit a parse tree produced by AgtypeParser#StringValue. 23 | def visitStringValue(self, ctx:AgtypeParser.StringValueContext): 24 | return self.visitChildren(ctx) 25 | 26 | 27 | # Visit a parse tree produced by AgtypeParser#IntegerValue. 28 | def visitIntegerValue(self, ctx:AgtypeParser.IntegerValueContext): 29 | return self.visitChildren(ctx) 30 | 31 | 32 | # Visit a parse tree produced by AgtypeParser#FloatValue. 33 | def visitFloatValue(self, ctx:AgtypeParser.FloatValueContext): 34 | return self.visitChildren(ctx) 35 | 36 | 37 | # Visit a parse tree produced by AgtypeParser#TrueBoolean. 38 | def visitTrueBoolean(self, ctx:AgtypeParser.TrueBooleanContext): 39 | return self.visitChildren(ctx) 40 | 41 | 42 | # Visit a parse tree produced by AgtypeParser#FalseBoolean. 43 | def visitFalseBoolean(self, ctx:AgtypeParser.FalseBooleanContext): 44 | return self.visitChildren(ctx) 45 | 46 | 47 | # Visit a parse tree produced by AgtypeParser#NullValue. 48 | def visitNullValue(self, ctx:AgtypeParser.NullValueContext): 49 | return self.visitChildren(ctx) 50 | 51 | 52 | # Visit a parse tree produced by AgtypeParser#ObjectValue. 53 | def visitObjectValue(self, ctx:AgtypeParser.ObjectValueContext): 54 | return self.visitChildren(ctx) 55 | 56 | 57 | # Visit a parse tree produced by AgtypeParser#ArrayValue. 58 | def visitArrayValue(self, ctx:AgtypeParser.ArrayValueContext): 59 | return self.visitChildren(ctx) 60 | 61 | 62 | # Visit a parse tree produced by AgtypeParser#obj. 63 | def visitObj(self, ctx:AgtypeParser.ObjContext): 64 | return self.visitChildren(ctx) 65 | 66 | 67 | # Visit a parse tree produced by AgtypeParser#pair. 68 | def visitPair(self, ctx:AgtypeParser.PairContext): 69 | return self.visitChildren(ctx) 70 | 71 | 72 | # Visit a parse tree produced by AgtypeParser#array. 73 | def visitArray(self, ctx:AgtypeParser.ArrayContext): 74 | return self.visitChildren(ctx) 75 | 76 | 77 | # Visit a parse tree produced by AgtypeParser#typeAnnotation. 78 | def visitTypeAnnotation(self, ctx:AgtypeParser.TypeAnnotationContext): 79 | return self.visitChildren(ctx) 80 | 81 | 82 | # Visit a parse tree produced by AgtypeParser#floatLiteral. 83 | def visitFloatLiteral(self, ctx:AgtypeParser.FloatLiteralContext): 84 | return self.visitChildren(ctx) 85 | 86 | 87 | 88 | del AgtypeParser -------------------------------------------------------------------------------- /Question-3/Python/age/gen/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DS-Popeye/Apache-Internship-Program/05c38eeb30bd4065df4a38fde27b271b25f4fefa/Question-3/Python/age/gen/__init__.py -------------------------------------------------------------------------------- /Question-3/Python/age/models.py: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one 2 | # or more contributor license agreements. See the NOTICE file 3 | # distributed with this work for additional information 4 | # regarding copyright ownership. The ASF licenses this file 5 | # to you under the Apache License, Version 2.0 (the 6 | # "License"); you may not use this file except in compliance 7 | # with the License. You may obtain a copy of the License at 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # Unless required by applicable law or agreed to in writing, 10 | # software distributed under the License is distributed on an 11 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 12 | # KIND, either express or implied. See the License for the 13 | # specific language governing permissions and limitations 14 | # under the License. 15 | import json 16 | from io import StringIO 17 | 18 | 19 | TP_NONE = 0 20 | TP_VERTEX = 1 21 | TP_EDGE = 2 22 | TP_PATH = 3 23 | 24 | 25 | class Graph(): 26 | def __init__(self, stmt=None) -> None: 27 | self.statement = stmt 28 | self.rows = list() 29 | self.vertices = dict() 30 | 31 | def __iter__(self): 32 | return self.rows.__iter__() 33 | 34 | def __len__(self): 35 | return self.rows.__len__() 36 | 37 | def __getitem__(self,index): 38 | return self.rows[index] 39 | 40 | def size(self): 41 | return self.rows.__len__() 42 | 43 | def append(self, agObj): 44 | self.rows.append(agObj) 45 | 46 | def getVertices(self): 47 | return self.vertices 48 | 49 | def getVertex(self, id): 50 | if id in self.vertices: 51 | return self.vertices[id] 52 | else: 53 | return None 54 | 55 | class AGObj: 56 | @property 57 | def gtype(self): 58 | return TP_NONE 59 | 60 | 61 | class Path(AGObj): 62 | entities = [] 63 | def __init__(self, entities=None) -> None: 64 | self.entities = entities 65 | 66 | @property 67 | def _nodes(self): 68 | return [each_node for each_node in self.entities if each_node.gtype == TP_VERTEX] 69 | 70 | @property 71 | def _edges(self): 72 | return [each_edge for each_edge in self.entities if each_edge.gtype == TP_EDGE] 73 | 74 | @property 75 | def gtype(self): 76 | return TP_PATH 77 | 78 | def __iter__(self): 79 | return self.entities.__iter__() 80 | 81 | def __len__(self): 82 | return self.entities.__len__() 83 | 84 | def __getitem__(self,index): 85 | return self.entities[index] 86 | 87 | def size(self): 88 | return self.entities.__len__() 89 | 90 | def append(self, agObj:AGObj ): 91 | self.entities.append(agObj) 92 | 93 | def __str__(self) -> str: 94 | return self.toString() 95 | 96 | def __repr__(self) -> str: 97 | return self.toString() 98 | 99 | def toString(self) -> str: 100 | buf = StringIO() 101 | buf.write("[") 102 | max = len(self.entities) 103 | idx = 0 104 | while idx < max: 105 | if idx > 0: 106 | buf.write(",") 107 | self.entities[idx]._toString(buf) 108 | idx += 1 109 | buf.write("]::PATH") 110 | 111 | return buf.getvalue() 112 | 113 | def toJson(self) -> str: 114 | buf = StringIO() 115 | buf.write("{\"gtype\": \"path\", \"elements\": [") 116 | 117 | max = len(self.entities) 118 | idx = 0 119 | while idx < max: 120 | if idx > 0: 121 | buf.write(",") 122 | self.entities[idx]._toJson(buf) 123 | idx += 1 124 | buf.write("]}") 125 | 126 | return buf.getvalue() 127 | 128 | 129 | 130 | 131 | class Vertex(AGObj): 132 | def __init__(self, id=None, label=None, properties=None) -> None: 133 | self.id = id 134 | self.label = label 135 | self.properties = properties 136 | 137 | @property 138 | def gtype(self): 139 | return TP_VERTEX 140 | 141 | def __setitem__(self,name, value): 142 | self.properties[name]=value 143 | 144 | def __getitem__(self,name): 145 | if name in self.properties: 146 | return self.properties[name] 147 | else: 148 | return None 149 | 150 | def __str__(self) -> str: 151 | return self.toString() 152 | 153 | def __repr__(self) -> str: 154 | return self.toString() 155 | 156 | def toString(self) -> str: 157 | return nodeToString(self) 158 | 159 | def _toString(self, buf): 160 | _nodeToString(self, buf) 161 | 162 | def toJson(self) -> str: 163 | return nodeToJson(self) 164 | 165 | def _toJson(self, buf): 166 | _nodeToJson(self, buf) 167 | 168 | 169 | class Edge(AGObj): 170 | def __init__(self, id=None, label=None, properties=None) -> None: 171 | self.id = id 172 | self.label = label 173 | self.start_id = None 174 | self.end_id = None 175 | self.properties = properties 176 | 177 | @property 178 | def gtype(self): 179 | return TP_EDGE 180 | 181 | def __setitem__(self,name, value): 182 | self.properties[name]=value 183 | 184 | def __getitem__(self,name): 185 | if name in self.properties: 186 | return self.properties[name] 187 | else: 188 | return None 189 | 190 | def __str__(self) -> str: 191 | return self.toString() 192 | 193 | def __repr__(self) -> str: 194 | return self.toString() 195 | 196 | def extraStrFormat(node, buf): 197 | if node.start_id != None: 198 | buf.write(", start_id:") 199 | buf.write(str(node.start_id)) 200 | 201 | if node.end_id != None: 202 | buf.write(", end_id:") 203 | buf.write(str(node.end_id)) 204 | 205 | 206 | def toString(self) -> str: 207 | return nodeToString(self, Edge.extraStrFormat) 208 | 209 | def _toString(self, buf): 210 | _nodeToString(self, buf, Edge.extraStrFormat) 211 | 212 | def extraJsonFormat(node, buf): 213 | if node.start_id != None: 214 | buf.write(", \"start_id\": \"") 215 | buf.write(str(node.start_id)) 216 | buf.write("\"") 217 | 218 | if node.end_id != None: 219 | buf.write(", \"end_id\": \"") 220 | buf.write(str(node.end_id)) 221 | buf.write("\"") 222 | 223 | def toJson(self) -> str: 224 | return nodeToJson(self, Edge.extraJsonFormat) 225 | 226 | def _toJson(self, buf): 227 | _nodeToJson(self, buf, Edge.extraJsonFormat) 228 | 229 | 230 | def nodeToString(node, extraFormatter=None): 231 | buf = StringIO() 232 | _nodeToString(node,buf,extraFormatter=extraFormatter) 233 | return buf.getvalue() 234 | 235 | 236 | def _nodeToString(node, buf, extraFormatter=None): 237 | buf.write("{") 238 | if node.label != None: 239 | buf.write("label:") 240 | buf.write(node.label) 241 | 242 | if node.id != None: 243 | buf.write(", id:") 244 | buf.write(str(node.id)) 245 | 246 | if node.properties != None: 247 | buf.write(", properties:{") 248 | for k,v in node.properties.items(): 249 | buf.write(k) 250 | buf.write(": ") 251 | buf.write(str(v)) 252 | buf.write(", ") 253 | buf.write("}") 254 | 255 | if extraFormatter != None: 256 | extraFormatter(node, buf) 257 | 258 | if node.gtype == TP_VERTEX: 259 | buf.write("}::VERTEX") 260 | if node.gtype == TP_EDGE: 261 | buf.write("}::EDGE") 262 | 263 | 264 | def nodeToJson(node, extraFormatter=None): 265 | buf = StringIO() 266 | _nodeToJson(node, buf, extraFormatter=extraFormatter) 267 | return buf.getvalue() 268 | 269 | 270 | def _nodeToJson(node, buf, extraFormatter=None): 271 | buf.write("{\"gtype\": ") 272 | if node.gtype == TP_VERTEX: 273 | buf.write("\"vertex\", ") 274 | if node.gtype == TP_EDGE: 275 | buf.write("\"edge\", ") 276 | 277 | if node.label != None: 278 | buf.write("\"label\":\"") 279 | buf.write(node.label) 280 | buf.write("\"") 281 | 282 | if node.id != None: 283 | buf.write(", \"id\":") 284 | buf.write(str(node.id)) 285 | 286 | if extraFormatter != None: 287 | extraFormatter(node, buf) 288 | 289 | if node.properties != None: 290 | buf.write(", \"properties\":{") 291 | for k,v in node.properties.items(): 292 | buf.write("\"") 293 | buf.write(k) 294 | buf.write("\": \"") 295 | buf.write(str(v)) 296 | buf.write("\", ") 297 | buf.write("}") 298 | buf.write("}") 299 | -------------------------------------------------------------------------------- /Question-3/Python/antlr/Agtype.g4: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | 20 | grammar Agtype; 21 | 22 | agType 23 | : agValue EOF 24 | ; 25 | 26 | agValue 27 | : value typeAnnotation? 28 | ; 29 | 30 | value 31 | : STRING #StringValue 32 | | INTEGER #IntegerValue 33 | | floatLiteral #FloatValue 34 | | 'true' #TrueBoolean 35 | | 'false' #FalseBoolean 36 | | 'null' #NullValue 37 | | obj #ObjectValue 38 | | array #ArrayValue 39 | ; 40 | 41 | obj 42 | : '{' pair (',' pair)* '}' 43 | | '{' '}' 44 | ; 45 | 46 | pair 47 | : STRING ':' agValue 48 | ; 49 | 50 | array 51 | : '[' agValue (',' agValue)* ']' 52 | | '[' ']' 53 | ; 54 | 55 | typeAnnotation 56 | : '::' IDENT 57 | ; 58 | 59 | IDENT 60 | : [A-Z_a-z][$0-9A-Z_a-z]* 61 | ; 62 | 63 | STRING 64 | : '"' (ESC | SAFECODEPOINT)* '"' 65 | ; 66 | 67 | fragment ESC 68 | : '\\' (["\\/bfnrt] | UNICODE) 69 | ; 70 | 71 | fragment UNICODE 72 | : 'u' HEX HEX HEX HEX 73 | ; 74 | 75 | fragment HEX 76 | : [0-9a-fA-F] 77 | ; 78 | 79 | fragment SAFECODEPOINT 80 | : ~ ["\\\u0000-\u001F] 81 | ; 82 | 83 | INTEGER 84 | : '-'? INT 85 | ; 86 | 87 | fragment INT 88 | : '0' | [1-9] [0-9]* 89 | ; 90 | 91 | floatLiteral 92 | : RegularFloat 93 | | ExponentFloat 94 | | '-'? 'Infinity' 95 | | 'NaN' 96 | ; 97 | 98 | RegularFloat 99 | : '-'? INT DECIMAL 100 | ; 101 | 102 | ExponentFloat 103 | : '-'? INT DECIMAL? SCIENTIFIC 104 | ; 105 | 106 | fragment DECIMAL 107 | : '.' [0-9]+ 108 | ; 109 | 110 | fragment SCIENTIFIC 111 | : [Ee][+-]? [0-9]+ 112 | ; 113 | 114 | WS 115 | : [ \t\n\r] + -> skip 116 | ; 117 | -------------------------------------------------------------------------------- /Question-3/Python/antlr/README.md: -------------------------------------------------------------------------------- 1 | # ANTLR4 Python3 Query Result data parser generation rules for apache-age-python 2 | Python driver for Apache AGE, graph extention for PostgreSQL. 3 | 4 | 5 | ### Build 6 | #### 1) Generate query result data parser with ANTLR4 7 | ``` 8 | # prerequisites : 9 | # - java over 8 10 | # - download ANTLR4 from https://www.antlr.org/download/antlr-4.9.2-complete.jar 11 | # - java -cp antlr-4.9.2-complete.jar org.antlr.v4.Tool -Dlanguage=Python3 -visitor -o ../age/gen Agtype.g4 12 | ``` 13 | 14 | -------------------------------------------------------------------------------- /Question-3/Python/register_pypi.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | python3 setup.py clean --all 4 | rm -Rf build dist 5 | 6 | python3 setup.py install 7 | python3 setup.py sdist bdist_wheel 8 | 9 | #python3 -m pip install --user --upgrade twine 10 | 11 | python3 -m twine upload dist/* 12 | -------------------------------------------------------------------------------- /Question-3/Python/samples/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DS-Popeye/Apache-Internship-Program/05c38eeb30bd4065df4a38fde27b271b25f4fefa/Question-3/Python/samples/__init__.py -------------------------------------------------------------------------------- /Question-3/Python/samples/apache-age-agtypes.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": null, 6 | "id": "6301516b-a3fa-48e2-a95f-0f79903a6cdd", 7 | "metadata": {}, 8 | "outputs": [], 9 | "source": [ 10 | "import unittest\n", 11 | "from decimal import Decimal\n", 12 | "import age \n", 13 | "\n", 14 | "resultHandler = age.newResultHandler()\n", 15 | " \n", 16 | "def evalExp(exp):\n", 17 | " value = resultHandler.parse(exp) \n", 18 | " print(type(value), \"|\", exp, \" --> \" ,value )\n", 19 | " \n", 20 | " " 21 | ] 22 | }, 23 | { 24 | "cell_type": "code", 25 | "execution_count": null, 26 | "id": "adf14fe9-692c-4701-86d4-8c84fd53d966", 27 | "metadata": {}, 28 | "outputs": [], 29 | "source": [ 30 | "\n", 31 | "mapStr = '{\"name\": \"Smith\", \"num\":123, \"yn\":true, \"bigInt\":123456789123456789123456789123456789::numeric}' \n", 32 | "arrStr = '[\"name\", \"Smith\", \"num\", 123, \"yn\", true, 123456789123456789123456789123456789.8888::numeric]' \n", 33 | "strStr = '\"abcd\"' \n", 34 | "intStr = '1234' \n", 35 | "floatStr = '1234.56789' \n", 36 | "numericStr1 = '12345678901234567890123456789123456789.789::numeric' \n", 37 | "numericStr2 = '12345678901234567890123456789123456789::numeric' \n", 38 | "boolStr = 'true' \n", 39 | "\n", 40 | "evalExp(mapStr)\n", 41 | "evalExp(arrStr)\n", 42 | "evalExp(strStr)\n", 43 | "evalExp(intStr)\n", 44 | "evalExp(floatStr)\n", 45 | "evalExp(numericStr1)\n", 46 | "evalExp(numericStr2)\n", 47 | "evalExp(boolStr)\n", 48 | "\n", 49 | "evalExp('-6.45161290322581e+46') \n", 50 | "evalExp('-123456789.99::numeric') \n", 51 | "evalExp('-6.45161290322581e+46::numeric') \n", 52 | "evalExp('1234') \n", 53 | "evalExp('NaN') \n", 54 | "evalExp('-Infinity') \n", 55 | "evalExp('Infinity') " 56 | ] 57 | }, 58 | { 59 | "cell_type": "code", 60 | "execution_count": null, 61 | "id": "8881804e-d71d-4704-b74c-376ed55be808", 62 | "metadata": {}, 63 | "outputs": [], 64 | "source": [ 65 | " vertexExp = '''{\"id\": 2251799813685425, \"label\": \"Person\", \n", 66 | " \"properties\": {\"name\": \"Smith\", \"numInt\":123, \"numFloat\": 384.23424, \n", 67 | " \"bigInt\":123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789::numeric, \n", 68 | " \"bigFloat\":123456789123456789123456789123456789.12345::numeric, \n", 69 | " \"yn\":true, \"nullVal\": null}}::vertex'''\n", 70 | "\n", 71 | "vertex = age.parseAgeValue(vertexExp)\n", 72 | "print(type(vertex.id), vertex.id)\n", 73 | "print(type(vertex.label), vertex.label)\n", 74 | "print(type(vertex[\"name\"]), vertex[\"name\"])\n", 75 | "print(type(vertex[\"numInt\"]), vertex[\"numInt\"])\n", 76 | "print(type(vertex[\"numFloat\"]), vertex[\"numFloat\"])\n", 77 | "print(type(vertex[\"bigInt\"]), vertex[\"bigInt\"])\n", 78 | "print(type(vertex[\"bigFloat\"]), vertex[\"bigFloat\"])\n", 79 | "print(type(vertex[\"yn\"]), vertex[\"yn\"])\n", 80 | "print(type(vertex[\"nullVal\"]), vertex[\"nullVal\"])" 81 | ] 82 | }, 83 | { 84 | "cell_type": "code", 85 | "execution_count": null, 86 | "id": "0a70e467-9587-4eb7-b97d-895223009bcc", 87 | "metadata": {}, 88 | "outputs": [], 89 | "source": [ 90 | "\n", 91 | "pathExp = '''[{\"id\": 2251799813685425, \"label\": \"Person\", \"properties\": {\"name\": \"Smith\"}}::vertex, \n", 92 | " {\"id\": 2533274790396576, \"label\": \"workWith\", \"end_id\": 2251799813685425, \"start_id\": 2251799813685424, \n", 93 | " \"properties\": {\"weight\": 3, \"bigFloat\":123456789123456789123456789.12345::numeric}}::edge, \n", 94 | " {\"id\": 2251799813685424, \"label\": \"Person\", \"properties\": {\"name\": \"Joe\"}}::vertex]::path'''\n", 95 | "\n", 96 | "path = age.parseAgeValue(pathExp)\n", 97 | "vertexStart = path[0]\n", 98 | "edge = path[1]\n", 99 | "vertexEnd = path[2]\n", 100 | "\n", 101 | "print(type(vertexStart.id), vertexStart.id)\n", 102 | "print(type(vertexStart.label), vertexStart.label)\n", 103 | "print(type(vertexStart[\"name\"]), vertexStart[\"name\"])\n", 104 | "\n", 105 | "print(type(edge.id), edge.id)\n", 106 | "print(type(edge.label), edge.label)\n", 107 | "print(type(edge[\"weight\"]), edge[\"weight\"])\n", 108 | "print(type(edge[\"bigFloat\"]), edge[\"bigFloat\"])\n", 109 | "\n", 110 | "print(type(vertexEnd.id), vertexEnd.id)\n", 111 | "print(type(vertexEnd.label), vertexEnd.label)\n", 112 | "print(type(vertexEnd[\"name\"]), vertexEnd[\"name\"])\n", 113 | "\n" 114 | ] 115 | }, 116 | { 117 | "cell_type": "code", 118 | "execution_count": null, 119 | "id": "62b7273f-ac6c-4dec-af7e-0467daa140f4", 120 | "metadata": {}, 121 | "outputs": [], 122 | "source": [] 123 | } 124 | ], 125 | "metadata": { 126 | "kernelspec": { 127 | "display_name": "Python 3", 128 | "language": "python", 129 | "name": "python3" 130 | }, 131 | "language_info": { 132 | "codemirror_mode": { 133 | "name": "ipython", 134 | "version": 3 135 | }, 136 | "file_extension": ".py", 137 | "mimetype": "text/x-python", 138 | "name": "python", 139 | "nbconvert_exporter": "python", 140 | "pygments_lexer": "ipython3", 141 | "version": "3.9.13 (tags/v3.9.13:6de2ca5, May 17 2022, 16:36:42) [MSC v.1929 64 bit (AMD64)]" 142 | }, 143 | "vscode": { 144 | "interpreter": { 145 | "hash": "1d5c1156327dacead463cc502c55ebae8ce9c8c01979cf154173ff808e75bf55" 146 | } 147 | } 148 | }, 149 | "nbformat": 4, 150 | "nbformat_minor": 5 151 | } 152 | -------------------------------------------------------------------------------- /Question-3/Python/samples/apache-age-basic.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "2e236ac7-6f78-4a59-bed7-45f593d060c2", 6 | "metadata": {}, 7 | "source": [ 8 | "# Basic Samples : Agtype mapper for Psycopg2 driver\n", 9 | "\n", 10 | "You can make transactions and queries for PostgreSQL with Psycopg2.\n", 11 | "\n", 12 | "This module enable to mapping agtype to python class(Path, Vertex, Edge)\n", 13 | "\n", 14 | "## Connect to PostgreSQL and agType setting" 15 | ] 16 | }, 17 | { 18 | "cell_type": "code", 19 | "execution_count": null, 20 | "id": "98a5863c-1e79-438e-81d4-d1f5354a1bdb", 21 | "metadata": {}, 22 | "outputs": [], 23 | "source": [ 24 | "import psycopg2 \n", 25 | "import age\n", 26 | "\n", 27 | "GRAPH_NAME = \"test_graph\"\n", 28 | "conn = psycopg2.connect(host=\"172.17.0.2\", port=\"5432\", dbname=\"postgres\", user=\"postgres\", password=\"agens\")\n", 29 | "\n", 30 | "age.setUpAge(conn, GRAPH_NAME)\n" 31 | ] 32 | }, 33 | { 34 | "cell_type": "code", 35 | "execution_count": null, 36 | "id": "ebcf65a5-de7c-4224-aacc-2695c9e5f8d5", 37 | "metadata": {}, 38 | "outputs": [], 39 | "source": [ 40 | "with conn.cursor() as cursor:\n", 41 | " try :\n", 42 | " cursor.execute(\"\"\"SELECT * from cypher(%s, $$ CREATE (n:Person {name: 'Joe', title: 'Developer'}) $$) as (v agtype); \"\"\", (GRAPH_NAME,) )\n", 43 | " cursor.execute(\"\"\"SELECT * from cypher(%s, $$ CREATE (n:Person {name: 'Smith', title: 'Developer'}) $$) as (v agtype); \"\"\", (GRAPH_NAME,))\n", 44 | " cursor.execute(\"\"\"SELECT * from cypher(%s, $$ \n", 45 | " CREATE (n:Person {name: 'Tom', title: 'Manager'}) \n", 46 | " RETURN n\n", 47 | " $$) as (v agtype); \"\"\", (GRAPH_NAME,))\n", 48 | " for row in cursor:\n", 49 | " print(\"CREATED::\", row[0])\n", 50 | " \n", 51 | " \n", 52 | " cursor.execute(\"\"\"SELECT * from cypher(%s, $$ \n", 53 | " MATCH (a:Person {name: 'Joe'}), (b:Person {name: 'Smith'}) CREATE (a)-[r:workWith {weight: 5}]->(b)\n", 54 | " $$) as (v agtype); \"\"\", (GRAPH_NAME,))\n", 55 | " \n", 56 | " cursor.execute(\"\"\"SELECT * from cypher(%s, $$ \n", 57 | " MATCH (a:Person {name: 'Smith'}), (b:Person {name: 'Tom'}) CREATE (a)-[r:workWith {weight: 3}]->(b)\n", 58 | " $$) as (v agtype); \"\"\", (GRAPH_NAME,))\n", 59 | " \n", 60 | " # When data inserted or updated, You must commit.\n", 61 | " conn.commit()\n", 62 | " except Exception as ex:\n", 63 | " print(type(ex), ex)\n", 64 | " # if exception occurs, you must rollback all transaction. \n", 65 | " conn.rollback()\n", 66 | "\n", 67 | "with conn.cursor() as cursor:\n", 68 | " try:\n", 69 | " print(\"------- [Select Vertices] --------\")\n", 70 | " cursor.execute(\"\"\"SELECT * from cypher(%s, $$ MATCH (n) RETURN n $$) as (v agtype); \"\"\", (GRAPH_NAME,))\n", 71 | " for row in cursor:\n", 72 | " vertex = row[0]\n", 73 | " print(vertex.id, vertex.label, vertex[\"name\"], vertex[\"title\"])\n", 74 | " print(\"-->\", vertex)\n", 75 | " \n", 76 | " print(type(cursor))\n", 77 | " print(\"------- [Select Paths] --------\")\n", 78 | " cursor.execute(\"\"\"SELECT * from cypher(%s, $$ MATCH p=()-[]->() RETURN p LIMIT 10 $$) as (v agtype); \"\"\", (GRAPH_NAME,))\n", 79 | " for row in cursor:\n", 80 | " path = row[0]\n", 81 | " v1 = path[0]\n", 82 | " e1 = path[1]\n", 83 | " v2 = path[2]\n", 84 | " print(v1.gtype , v1[\"name\"], e1.gtype , e1.label, e1[\"weight\"], v2.gtype , v2[\"name\"])\n", 85 | " print(\"-->\", path)\n", 86 | " except Exception as ex:\n", 87 | " print(type(ex), ex)\n", 88 | " # if exception occurs, you must rollback even though just retrieving.\n", 89 | " conn.rollback()" 90 | ] 91 | }, 92 | { 93 | "cell_type": "code", 94 | "execution_count": null, 95 | "id": "f45f7c7d-2256-4aea-92f6-e0ad71017feb", 96 | "metadata": {}, 97 | "outputs": [], 98 | "source": [ 99 | "with conn.cursor() as cursor:\n", 100 | " try:\n", 101 | " cursor.execute(\"\"\"SELECT * from cypher(%s, $$ \n", 102 | " MATCH p=(a)-[b]->(c) RETURN a.name, label(b), c.name \n", 103 | " $$) as (a agtype, b agtype, c agtype); \"\"\", (GRAPH_NAME,))\n", 104 | " for row in cursor:\n", 105 | " print(row[0], row[1], row[2])\n", 106 | " print(\"-->\", row)\n", 107 | " except Exception as ex:\n", 108 | " print(ex)\n", 109 | " conn.rollback()" 110 | ] 111 | }, 112 | { 113 | "cell_type": "code", 114 | "execution_count": null, 115 | "id": "c40b9076-d45e-43e6-85ae-296ba68a3031", 116 | "metadata": {}, 117 | "outputs": [], 118 | "source": [ 119 | "with conn.cursor() as cursor:\n", 120 | " try :\n", 121 | " cursor.execute(\"\"\"SELECT * from cypher(%s, $$ \n", 122 | " CREATE (n:Person {name: 'Jack', title: 'Developer', score:-6.45161290322581e+46}) \n", 123 | " $$) as (v agtype); \"\"\", (GRAPH_NAME,) )\n", 124 | " cursor.execute(\"\"\"SELECT * from cypher(%s, $$ \n", 125 | " CREATE (n:Person {name: 'John', title: 'Developer'}) \n", 126 | " $$) as (v agtype); \"\"\", (GRAPH_NAME,))\n", 127 | "\n", 128 | " cursor.execute(\"\"\"SELECT * from cypher(%s, $$ \n", 129 | " MATCH (a:Person {name: 'Jack'}), (b:Person {name: 'John'}) \n", 130 | " CREATE (a)-[r:workWith {weight: 2}]->(b)\n", 131 | " $$) as (v agtype); \"\"\", (GRAPH_NAME,))\n", 132 | " \n", 133 | " # When data inserted or updated, You must commit \n", 134 | " conn.commit()\n", 135 | " except Exception as ex:\n", 136 | " print(ex)\n", 137 | " conn.rollback()\n", 138 | "\n", 139 | "with conn.cursor() as cursor:\n", 140 | " try :\n", 141 | " cursor.execute(\"\"\"SELECT * from cypher(%s, $$ \n", 142 | " MATCH p=(a )-[b]->(c) RETURN a , b, c \n", 143 | " $$) as (ta agtype, tb agtype, tc agtype); \"\"\", (GRAPH_NAME,))\n", 144 | " \n", 145 | " for row in cursor:\n", 146 | " print(row[0][\"name\"], row[1].properties, row[2][\"name\"])\n", 147 | " \n", 148 | " except Exception as ex:\n", 149 | " print(ex)\n", 150 | " conn.rollback()\n" 151 | ] 152 | }, 153 | { 154 | "cell_type": "code", 155 | "execution_count": null, 156 | "id": "29ffe1b7-86df-446a-9df0-635be25a9eea", 157 | "metadata": {}, 158 | "outputs": [], 159 | "source": [ 160 | "with conn.cursor() as cursor:\n", 161 | " try:\n", 162 | " cursor.execute(\"\"\"SELECT * from cypher(%s, $$ \n", 163 | " MATCH p=(a)-[b]->(c) RETURN p \n", 164 | " $$) as (v agtype); \"\"\", (GRAPH_NAME,))\n", 165 | " for row in cursor:\n", 166 | " path = row[0]\n", 167 | " print(path[0][\"name\"], path[1].id, path[1].properties, path[2][\"name\"])\n", 168 | " except Exception as ex:\n", 169 | " print(ex)\n", 170 | " conn.rollback()" 171 | ] 172 | }, 173 | { 174 | "cell_type": "code", 175 | "execution_count": null, 176 | "id": "428e6ddf-3958-49ff-af73-809b9a1ce42b", 177 | "metadata": {}, 178 | "outputs": [], 179 | "source": [ 180 | "age.deleteGraph(conn, GRAPH_NAME)\n", 181 | "conn.close()" 182 | ] 183 | }, 184 | { 185 | "cell_type": "code", 186 | "execution_count": null, 187 | "id": "a4819e39-9f37-4dd5-bdbd-337b6d289158", 188 | "metadata": {}, 189 | "outputs": [], 190 | "source": [ 191 | "\n", 192 | " " 193 | ] 194 | }, 195 | { 196 | "cell_type": "code", 197 | "execution_count": null, 198 | "id": "02041ef2-9761-4eb3-b270-ded23e1caa6d", 199 | "metadata": {}, 200 | "outputs": [], 201 | "source": [] 202 | } 203 | ], 204 | "metadata": { 205 | "kernelspec": { 206 | "display_name": "Python 3", 207 | "language": "python", 208 | "name": "python3" 209 | }, 210 | "language_info": { 211 | "codemirror_mode": { 212 | "name": "ipython", 213 | "version": 3 214 | }, 215 | "file_extension": ".py", 216 | "mimetype": "text/x-python", 217 | "name": "python", 218 | "nbconvert_exporter": "python", 219 | "pygments_lexer": "ipython3", 220 | "version": "3.9.2" 221 | } 222 | }, 223 | "nbformat": 4, 224 | "nbformat_minor": 5 225 | } 226 | -------------------------------------------------------------------------------- /Question-3/Python/setup.py: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one 2 | # or more contributor license agreements. See the NOTICE file 3 | # distributed with this work for additional information 4 | # regarding copyright ownership. The ASF licenses this file 5 | # to you under the Apache License, Version 2.0 (the 6 | # "License"); you may not use this file except in compliance 7 | # with the License. You may obtain a copy of the License at 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # Unless required by applicable law or agreed to in writing, 10 | # software distributed under the License is distributed on an 11 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 12 | # KIND, either express or implied. See the License for the 13 | # specific language governing permissions and limitations 14 | # under the License. 15 | 16 | from setuptools import setup, find_packages 17 | from age import VERSION 18 | 19 | with open("README.md", "r", encoding='utf8') as fh: 20 | long_description = fh.read() 21 | 22 | setup( 23 | name = 'apache-age-python', 24 | version = VERSION.VERSION, 25 | description = 'Python driver support for Apache AGE', 26 | long_description=long_description, 27 | long_description_content_type="text/markdown", 28 | author = 'MD RABIUL AWAL SHUVO', 29 | author_email = 'rabiul35-487@diu.edu.bd', 30 | url = 'https://github.com/DS-Popeye/Apache-Internship-Program/tree/main/Question-3', 31 | download_url = 'https://github.com/DS-Popeye/Apache-Internship-Program/tree/main/Question-3' , 32 | license = 'Apache2.0', 33 | install_requires = [ 'psycopg2', 'antlr4-python3-runtime==4.9.2' ], 34 | packages = ['age', 'age.gen'], 35 | keywords = ['Graph Database', 'Apache AGE', 'PostgreSQL'], 36 | python_requires = '>=3.9', 37 | # package_data = {}, 38 | # zip_safe=False, 39 | classifiers = [ 40 | 'Programming Language :: Python :: 3.9' 41 | ] 42 | ) 43 | -------------------------------------------------------------------------------- /Question-3/Python/test_age_py.py: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one 2 | # or more contributor license agreements. See the NOTICE file 3 | # distributed with this work for additional information 4 | # regarding copyright ownership. The ASF licenses this file 5 | # to you under the Apache License, Version 2.0 (the 6 | # "License"); you may not use this file except in compliance 7 | # with the License. You may obtain a copy of the License at 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # Unless required by applicable law or agreed to in writing, 10 | # software distributed under the License is distributed on an 11 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 12 | # KIND, either express or implied. See the License for the 13 | # specific language governing permissions and limitations 14 | # under the License. 15 | 16 | from age.models import Vertex 17 | import unittest 18 | import decimal 19 | import age 20 | 21 | DSN = "host=172.17.0.2 port=5432 dbname=postgres user=postgres password=agens" 22 | TEST_HOST = "172.17.0.2" 23 | TEST_PORT = 5432 24 | TEST_DB = "postgres" 25 | TEST_USER = "postgres" 26 | TEST_PASSWORD = "agens" 27 | TEST_GRAPH_NAME = "test_graph" 28 | 29 | class TestAgeBasic(unittest.TestCase): 30 | ag = None 31 | def setUp(self): 32 | print("Connecting to Test Graph.....") 33 | self.ag = age.connect(graph=TEST_GRAPH_NAME, host=TEST_HOST, port=TEST_PORT, dbname=TEST_DB, user=TEST_USER, password=TEST_PASSWORD) 34 | 35 | 36 | def tearDown(self): 37 | # Clear test data 38 | print("Deleting Test Graph.....") 39 | age.deleteGraph(self.ag.connection, self.ag.graphName) 40 | self.ag.close() 41 | 42 | def testExec(self): 43 | ag = self.ag 44 | # Create and Return single column 45 | cursor = ag.execCypher("CREATE (n:Person {name: %s, title: 'Developer'}) RETURN n", params=('Andy',)) 46 | for row in cursor: 47 | print(Vertex, type(row[0])) 48 | 49 | 50 | # Create and Return multi columns 51 | cursor = ag.execCypher("CREATE (n:Person {name: %s, title: %s}) RETURN id(n), n.name", cols=['id','name'], params=('Jack','Manager')) 52 | row = cursor.fetchone() 53 | print(row[0], row[1]) 54 | self.assertEqual(int, type(row[0])) 55 | ag.commit() 56 | 57 | 58 | 59 | def testQuery(self): 60 | ag = self.ag 61 | ag.execCypher("CREATE (n:Person {name: %s}) ", params=('Jack',)) 62 | ag.execCypher("CREATE (n:Person {name: %s}) ", params=('Andy',)) 63 | ag.execCypher("CREATE (n:Person {name: %s}) ", params=('Smith',)) 64 | ag.execCypher("MATCH (a:Person), (b:Person) WHERE a.name = 'Andy' AND b.name = 'Jack' CREATE (a)-[r:workWith {weight: 3}]->(b)") 65 | ag.execCypher("""MATCH (a:Person), (b:Person) 66 | WHERE a.name = %s AND b.name = %s 67 | CREATE p=((a)-[r:workWith]->(b)) """, params=('Jack', 'Smith',)) 68 | 69 | ag.commit() 70 | 71 | cursor = ag.execCypher("MATCH p=()-[:workWith]-() RETURN p") 72 | for row in cursor: 73 | path = row[0] 74 | print("START:", path[0]) 75 | print("EDGE:", path[1]) 76 | print("END:", path[2]) 77 | 78 | cursor = ag.execCypher("MATCH p=(a)-[b]-(c) WHERE b.weight>2 RETURN a,label(b), b.weight, c", cols=["a","bl","bw", "c"], params=(2,)) 79 | for row in cursor: 80 | start = row[0] 81 | edgel = row[1] 82 | edgew = row[2] 83 | end = row[3] 84 | print(start["name"] , edgel, edgew, end["name"]) 85 | 86 | 87 | def testChangeData(self): 88 | ag = self.ag 89 | # Create Vertices 90 | # Commit automatically 91 | ag.execCypher("CREATE (n:Person {name: 'Joe'})") 92 | 93 | cursor = ag.execCypher("CREATE (n:Person {name: %s, title: 'Developer'}) RETURN n", params=('Smith',)) 94 | row = cursor.fetchone() 95 | print("CREATED: ", row[0]) 96 | 97 | # You must commit explicitly 98 | ag.commit() 99 | 100 | cursor = ag.execCypher("MATCH (n:Person {name: %s}) SET n.title=%s RETURN n", params=('Smith','Manager',)) 101 | row = cursor.fetchone() 102 | vertex = row[0] 103 | title1 = vertex["title"] 104 | print("SET title: ", title1) 105 | 106 | ag.commit() 107 | 108 | cursor = ag.execCypher("MATCH (p:Person {name: 'Smith'}) RETURN p.title") 109 | row = cursor.fetchone() 110 | title2 = row[0] 111 | 112 | self.assertEqual(title1, title2) 113 | 114 | cursor = ag.execCypher("MATCH (n:Person {name: %s}) SET n.bigNum=-6.45161e+46::numeric RETURN n", params=('Smith',)) 115 | row = cursor.fetchone() 116 | vertex = row[0] 117 | for row in cursor: 118 | print("SET bigNum: ", vertex) 119 | 120 | bigNum1 = vertex["bigNum"] 121 | 122 | self.assertEqual(decimal.Decimal("-6.45161e+46"), bigNum1) 123 | ag.commit() 124 | 125 | 126 | cursor = ag.execCypher("MATCH (p:Person {name: 'Smith'}) RETURN p.bigNum") 127 | row = cursor.fetchone() 128 | bigNum2 = row[0] 129 | 130 | self.assertEqual(bigNum1, bigNum2) 131 | 132 | 133 | cursor = ag.execCypher("MATCH (n:Person {name: %s}) REMOVE n.title RETURN n", params=('Smith',)) 134 | for row in cursor: 135 | print("REMOVE Prop title: ", row[0]) 136 | 137 | # You must commit explicitly 138 | ag.commit() 139 | 140 | 141 | def testCypher(self): 142 | ag = self.ag 143 | 144 | with ag.connection.cursor() as cursor: 145 | try : 146 | ag.cypher(cursor, "CREATE (n:Person {name: %s}) ", params=('Jone',)) 147 | ag.cypher(cursor, "CREATE (n:Person {name: %s}) ", params=('Jack',)) 148 | ag.cypher(cursor, "CREATE (n:Person {name: %s}) ", params=('Andy',)) 149 | ag.cypher(cursor, "CREATE (n:Person {name: %s}) ", params=('Smith',)) 150 | ag.cypher(cursor, "CREATE (n:Person {name: %s}) ", params=('Tom',)) 151 | 152 | # You must commit explicitly 153 | ag.commit() 154 | except Exception as ex: 155 | print(ex) 156 | ag.rollback() 157 | 158 | with ag.connection.cursor() as cursor: 159 | try :# Create Edges 160 | ag.cypher(cursor,"MATCH (a:Person), (b:Person) WHERE a.name = 'Joe' AND b.name = 'Smith' CREATE (a)-[r:workWith {weight: 3}]->(b)") 161 | ag.cypher(cursor,"MATCH (a:Person), (b:Person) WHERE a.name = 'Andy' AND b.name = 'Tom' CREATE (a)-[r:workWith {weight: 1}]->(b)") 162 | ag.cypher(cursor,"MATCH (a:Person {name: 'Jack'}), (b:Person {name: 'Andy'}) CREATE (a)-[r:workWith {weight: 5}]->(b)") 163 | 164 | # You must commit explicitly 165 | ag.commit() 166 | except Exception as ex: 167 | print(ex) 168 | ag.rollback() 169 | 170 | 171 | # With Params 172 | cursor = ag.execCypher("""MATCH (a:Person), (b:Person) 173 | WHERE a.name = %s AND b.name = %s 174 | CREATE p=((a)-[r:workWith]->(b)) RETURN p""", 175 | params=('Andy', 'Smith',)) 176 | 177 | for row in cursor: 178 | print(row[0]) 179 | 180 | cursor = ag.execCypher("""MATCH (a:Person {name: 'Joe'}), (b:Person {name: 'Jack'}) 181 | CREATE p=((a)-[r:workWith {weight: 5}]->(b)) 182 | RETURN p """) 183 | 184 | for row in cursor: 185 | print(row[0]) 186 | 187 | 188 | 189 | def testMultipleEdges(self): 190 | ag = self.ag 191 | with ag.connection.cursor() as cursor: 192 | try : 193 | ag.cypher(cursor, "CREATE (n:Country {name: %s}) ", params=('USA',)) 194 | ag.cypher(cursor, "CREATE (n:Country {name: %s}) ", params=('France',)) 195 | ag.cypher(cursor, "CREATE (n:Country {name: %s}) ", params=('Korea',)) 196 | ag.cypher(cursor, "CREATE (n:Country {name: %s}) ", params=('Russia',)) 197 | 198 | # You must commit explicitly after all executions. 199 | ag.connection.commit() 200 | except Exception as ex: 201 | ag.rollback() 202 | raise ex 203 | 204 | with ag.connection.cursor() as cursor: 205 | try :# Create Edges 206 | ag.cypher(cursor,"MATCH (a:Country), (b:Country) WHERE a.name = 'USA' AND b.name = 'France' CREATE (a)-[r:distance {unit:'miles', value: 4760}]->(b)") 207 | ag.cypher(cursor,"MATCH (a:Country), (b:Country) WHERE a.name = 'France' AND b.name = 'Korea' CREATE (a)-[r:distance {unit: 'km', value: 9228}]->(b)") 208 | ag.cypher(cursor,"MATCH (a:Country {name: 'Korea'}), (b:Country {name: 'Russia'}) CREATE (a)-[r:distance {unit:'km', value: 3078}]->(b)") 209 | 210 | # You must commit explicitly 211 | ag.connection.commit() 212 | except Exception as ex: 213 | ag.rollback() 214 | raise ex 215 | 216 | 217 | cursor = ag.execCypher("""MATCH p=(:Country {name:"USA"})-[:distance]-(:Country)-[:distance]-(:Country) 218 | RETURN p""") 219 | 220 | count = 0 221 | for row in cursor: 222 | path = row[0] 223 | indent = "" 224 | for e in path: 225 | if e.gtype == age.TP_VERTEX: 226 | print(indent, e.label, e["name"]) 227 | elif e.gtype == age.TP_EDGE: 228 | print(indent, e.label, e["value"], e["unit"]) 229 | else: 230 | print(indent, "Unknown element.", e) 231 | 232 | count += 1 233 | indent += " >" 234 | 235 | self.assertEqual(5,count) 236 | 237 | def testCollect(self): 238 | ag = self.ag 239 | 240 | with ag.connection.cursor() as cursor: 241 | try : 242 | ag.cypher(cursor, "CREATE (n:Person {name: %s}) ", params=('Joe',)) 243 | ag.cypher(cursor, "CREATE (n:Person {name: %s}) ", params=('Jack',)) 244 | ag.cypher(cursor, "CREATE (n:Person {name: %s}) ", params=('Andy',)) 245 | ag.cypher(cursor, "CREATE (n:Person {name: %s}) ", params=('Smith',)) 246 | ag.cypher(cursor, "CREATE (n:Person {name: %s}) ", params=('Tom',)) 247 | 248 | # You must commit explicitly 249 | ag.commit() 250 | except Exception as ex: 251 | print(ex) 252 | ag.rollback() 253 | 254 | with ag.connection.cursor() as cursor: 255 | try :# Create Edges 256 | ag.cypher(cursor,"MATCH (a:Person), (b:Person) WHERE a.name = 'Joe' AND b.name = 'Smith' CREATE (a)-[r:workWith {weight: 3}]->(b)") 257 | ag.cypher(cursor,"MATCH (a:Person), (b:Person) WHERE a.name = 'Joe' AND b.name = 'Tom' CREATE (a)-[r:workWith {weight: 1}]->(b)") 258 | ag.cypher(cursor,"MATCH (a:Person {name: 'Joe'}), (b:Person {name: 'Andy'}) CREATE (a)-[r:workWith {weight: 5}]->(b)") 259 | 260 | # You must commit explicitly 261 | ag.commit() 262 | except Exception as ex: 263 | print(ex) 264 | ag.rollback() 265 | 266 | print(" - COLLECT 1 --------") 267 | with ag.connection.cursor() as cursor: 268 | ag.cypher(cursor, "MATCH (a)-[:workWith]->(c) WITH a as V, COLLECT(c) as CV RETURN V.name, CV", cols=["V","CV"]) 269 | for row in cursor: 270 | nm = row[0] 271 | collected = row[1] 272 | print(nm, "workWith", [i["name"] for i in collected]) 273 | self.assertEqual(3,len(collected)) 274 | 275 | 276 | print(" - COLLECT 2 --------") 277 | for row in ag.execCypher("MATCH (a)-[:workWith]->(c) WITH a as V, COLLECT(c) as CV RETURN V.name, CV", cols=["V1","CV"]): 278 | nm = row[0] 279 | collected = row[1] 280 | print(nm, "workWith", [i["name"] for i in collected]) 281 | self.assertEqual(3,len(collected)) 282 | 283 | if __name__ == '__main__': 284 | unittest.main() -------------------------------------------------------------------------------- /Question-3/Python/test_agtypes.py: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one 2 | # or more contributor license agreements. See the NOTICE file 3 | # distributed with this work for additional information 4 | # regarding copyright ownership. The ASF licenses this file 5 | # to you under the Apache License, Version 2.0 (the 6 | # "License"); you may not use this file except in compliance 7 | # with the License. You may obtain a copy of the License at 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # Unless required by applicable law or agreed to in writing, 10 | # software distributed under the License is distributed on an 11 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 12 | # KIND, either express or implied. See the License for the 13 | # specific language governing permissions and limitations 14 | # under the License. 15 | 16 | import unittest 17 | from decimal import Decimal 18 | import math 19 | import age 20 | 21 | class TestAgtype(unittest.TestCase): 22 | resultHandler = None 23 | 24 | def __init__(self, methodName: str) -> None: 25 | super().__init__(methodName=methodName) 26 | self.resultHandler = age.newResultHandler() 27 | 28 | def parse(self, exp): 29 | return self.resultHandler.parse(exp) 30 | 31 | def test_scalar(self): 32 | mapStr = '{"name": "Smith", "num":123, "yn":true, "bigInt":123456789123456789123456789123456789::numeric}' 33 | arrStr = '["name", "Smith", "num", 123, "yn", true, 123456789123456789123456789123456789.8888::numeric]' 34 | strStr = '"abcd"' 35 | intStr = '1234' 36 | floatStr = '1234.56789' 37 | floatStr2 = '6.45161290322581e+46' 38 | numericStr1 = '12345678901234567890123456789123456789.789::numeric' 39 | numericStr2 = '12345678901234567890123456789123456789::numeric' 40 | boolStr = 'true' 41 | nullStr = '' 42 | nanStr = "NaN" 43 | infpStr = "Infinity" 44 | infnStr = "-Infinity" 45 | 46 | mapVal = self.parse(mapStr) 47 | arrVal = self.parse(arrStr) 48 | str = self.parse(strStr) 49 | intVal = self.parse(intStr) 50 | floatVal = self.parse(floatStr) 51 | floatVal2 = self.parse(floatStr2) 52 | bigFloat = self.parse(numericStr1) 53 | bigInt = self.parse(numericStr2) 54 | boolVal = self.parse(boolStr) 55 | nullVal = self.parse(nullStr) 56 | nanVal = self.parse(nanStr) 57 | infpVal = self.parse(infpStr) 58 | infnVal = self.parse(infnStr) 59 | 60 | print("map", type(mapVal), mapVal) 61 | print("arr", type(arrVal), arrVal) 62 | print("str", type(str), str) 63 | print("intVal", type(intVal), intVal) 64 | print("floatVal", type(floatVal), floatVal) 65 | print("floatVal", type(floatVal2), floatVal2) 66 | print("bigFloat", type(bigFloat), bigFloat) 67 | print("bigInt", type(bigInt), bigInt) 68 | print("bool", type(boolVal), boolVal) 69 | print("null", type(nullVal), nullVal) 70 | print("nanVal", type(nanVal), nanVal) 71 | print("infpVal", type(infpVal), infpVal) 72 | print("infnVal", type(infnVal), infnVal) 73 | 74 | self.assertEqual(mapVal, {'name': 'Smith', 'num': 123, 'yn': True, 'bigInt': Decimal('123456789123456789123456789123456789')}) 75 | self.assertEqual(arrVal, ["name", "Smith", "num", 123, "yn", True, Decimal("123456789123456789123456789123456789.8888")] ) 76 | self.assertEqual(str, "abcd") 77 | self.assertEqual(intVal, 1234) 78 | self.assertEqual(floatVal, 1234.56789) 79 | self.assertEqual(floatVal2, 6.45161290322581e+46) 80 | self.assertEqual(bigFloat, Decimal("12345678901234567890123456789123456789.789")) 81 | self.assertEqual(bigInt, Decimal("12345678901234567890123456789123456789")) 82 | self.assertEqual(boolVal, True) 83 | self.assertTrue(math.isnan(nanVal)) 84 | self.assertTrue(math.isinf(infpVal)) 85 | self.assertTrue(math.isinf(infnVal)) 86 | 87 | def test_vertex(self): 88 | vertexExp = '''{"id": 2251799813685425, "label": "Person", 89 | "properties": {"name": "Smith", "numInt":123, "numFloat": 384.23424, 90 | "bigInt":123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789::numeric, 91 | "bigFloat":123456789123456789123456789123456789.12345::numeric, 92 | "yn":true, "nullVal": null}}::vertex''' 93 | 94 | vertex = self.parse(vertexExp) 95 | self.assertEqual(vertex.id, 2251799813685425) 96 | self.assertEqual(vertex.label, "Person") 97 | self.assertEqual(vertex["name"], "Smith") 98 | self.assertEqual(vertex["numInt"], 123) 99 | self.assertEqual(vertex["numFloat"], 384.23424) 100 | self.assertEqual(vertex["bigInt"], Decimal("123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789")) 101 | self.assertEqual(vertex["bigFloat"], Decimal("123456789123456789123456789123456789.12345")) 102 | self.assertEqual(vertex["yn"], True) 103 | self.assertEqual(vertex["nullVal"], None) 104 | 105 | def test_path(self): 106 | pathExp = '''[{"id": 2251799813685425, "label": "Person", "properties": {"name": "Smith"}}::vertex, 107 | {"id": 2533274790396576, "label": "workWith", "end_id": 2251799813685425, "start_id": 2251799813685424, 108 | "properties": {"weight": 3, "bigFloat":123456789123456789123456789.12345::numeric}}::edge, 109 | {"id": 2251799813685424, "label": "Person", "properties": {"name": "Joe"}}::vertex]::path''' 110 | 111 | path = self.parse(pathExp) 112 | vertexStart = path[0] 113 | edge = path[1] 114 | vertexEnd = path[2] 115 | self.assertEqual(vertexStart.id, 2251799813685425) 116 | self.assertEqual(vertexStart.label, "Person") 117 | self.assertEqual(vertexStart["name"], "Smith") 118 | 119 | self.assertEqual(edge.id, 2533274790396576) 120 | self.assertEqual(edge.label, "workWith") 121 | self.assertEqual(edge["weight"], 3) 122 | self.assertEqual(edge["bigFloat"], Decimal("123456789123456789123456789.12345")) 123 | 124 | self.assertEqual(vertexEnd.id, 2251799813685424) 125 | self.assertEqual(vertexEnd.label, "Person") 126 | self.assertEqual(vertexEnd["name"], "Joe") 127 | 128 | 129 | if __name__ == '__main__': 130 | unittest.main() --------------------------------------------------------------------------------