├── .gitignore
├── LICENSE
├── README.md
├── examples
├── CompoundElements.java
├── CrudOperations.java
├── PreparedStatements.java
├── README.md
├── SimpleSelects.java
├── UseCredentials.java
└── UseSQLJSON.java
├── pom.xml
└── src
├── main
├── java
│ └── com
│ │ └── couchbase
│ │ ├── jdbc
│ │ ├── CBArray.java
│ │ ├── CBConnection.java
│ │ ├── CBDatabaseMetaData.java
│ │ ├── CBDriver.java
│ │ ├── CBParameterMetaData.java
│ │ ├── CBPreparedResult.java
│ │ ├── CBPreparedStatement.java
│ │ ├── CBResultSet.java
│ │ ├── CBResultSetMetaData.java
│ │ ├── CBStatement.java
│ │ ├── ConnectionParameters.java
│ │ ├── connect
│ │ │ ├── Cluster.java
│ │ │ ├── Instance.java
│ │ │ └── Protocol.java
│ │ ├── core
│ │ │ ├── CouchBaseSQLException.java
│ │ │ ├── CouchError.java
│ │ │ ├── CouchMetrics.java
│ │ │ ├── CouchResponse.java
│ │ │ ├── EscapedFunctions.java
│ │ │ ├── Field.java
│ │ │ ├── Parser.java
│ │ │ ├── ProtocolImpl.java
│ │ │ └── SqlJsonImplementation.java
│ │ └── util
│ │ │ ├── Credentials.java
│ │ │ ├── JSONTypes.java
│ │ │ ├── SqlParser.java
│ │ │ ├── StringUtil.java
│ │ │ └── TimestampUtils.java
│ │ └── json
│ │ └── SQLJSON.java
└── resources
│ └── META-INF
│ └── services
│ └── java.sql.Driver
└── test
├── java
└── com
│ └── couchbase
│ └── jdbc
│ ├── BigDataJDBCDriverTests.java
│ ├── BucketInfo.java
│ ├── CBDatabaseMetaDataTest.java
│ ├── ClusterAwareTests.java
│ ├── ClusterInfo.java
│ ├── ClusterSetupUtils.java
│ ├── ClusterTest.java
│ ├── ConnectionTest.java
│ ├── CouchBaseTestCase.java
│ ├── DriverTest.java
│ ├── JDBCTestUtils.java
│ ├── N1QLErrorJDBCDriverHandlingTests.java
│ ├── NodeInfo.java
│ ├── PreparedStatementTest.java
│ ├── ProjectionJDBCDriverTests.java
│ ├── QueryInfo.java
│ ├── RQGJDBCTests.java
│ ├── ResultSetMetaDataTest.java
│ ├── ResultSetTest.java
│ ├── SSLConnectionTest.java
│ ├── SqlParserTest.java
│ ├── StatementTest.java
│ ├── Test16017.java
│ ├── TestBoon.java
│ ├── TestResultAnalysis.java
│ ├── TestSQLJson.java
│ ├── TestUser.java
│ ├── TestUtil.java
│ └── WrapperTest.java
└── resources
├── config.json
├── dev_config.json
├── dev_environment.properties
├── dev_rqg_config.json
├── environment.properties
├── example1.json
├── local_config.json
├── local_environment.properties
├── logback-test.xml
├── rqg_config.json
└── rqg_config.properties
/.gitignore:
--------------------------------------------------------------------------------
1 | /target/
2 | /.idea/
3 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 |
2 | Apache License
3 | Version 2.0, January 2004
4 | http://www.apache.org/licenses/
5 |
6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7 |
8 | 1. Definitions.
9 |
10 | "License" shall mean the terms and conditions for use, reproduction,
11 | and distribution as defined by Sections 1 through 9 of this document.
12 |
13 | "Licensor" shall mean the copyright owner or entity authorized by
14 | the copyright owner that is granting the License.
15 |
16 | "Legal Entity" shall mean the union of the acting entity and all
17 | other entities that control, are controlled by, or are under common
18 | control with that entity. For the purposes of this definition,
19 | "control" means (i) the power, direct or indirect, to cause the
20 | direction or management of such entity, whether by contract or
21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
22 | outstanding shares, or (iii) beneficial ownership of such entity.
23 |
24 | "You" (or "Your") shall mean an individual or Legal Entity
25 | exercising permissions granted by this License.
26 |
27 | "Source" form shall mean the preferred form for making modifications,
28 | including but not limited to software source code, documentation
29 | source, and configuration files.
30 |
31 | "Object" form shall mean any form resulting from mechanical
32 | transformation or translation of a Source form, including but
33 | not limited to compiled object code, generated documentation,
34 | and conversions to other media types.
35 |
36 | "Work" shall mean the work of authorship, whether in Source or
37 | Object form, made available under the License, as indicated by a
38 | copyright notice that is included in or attached to the work
39 | (an example is provided in the Appendix below).
40 |
41 | "Derivative Works" shall mean any work, whether in Source or Object
42 | form, that is based on (or derived from) the Work and for which the
43 | editorial revisions, annotations, elaborations, or other modifications
44 | represent, as a whole, an original work of authorship. For the purposes
45 | of this License, Derivative Works shall not include works that remain
46 | separable from, or merely link (or bind by name) to the interfaces of,
47 | the Work and Derivative Works thereof.
48 |
49 | "Contribution" shall mean any work of authorship, including
50 | the original version of the Work and any modifications or additions
51 | to that Work or Derivative Works thereof, that is intentionally
52 | submitted to Licensor for inclusion in the Work by the copyright owner
53 | or by an individual or Legal Entity authorized to submit on behalf of
54 | the copyright owner. For the purposes of this definition, "submitted"
55 | means any form of electronic, verbal, or written communication sent
56 | to the Licensor or its representatives, including but not limited to
57 | communication on electronic mailing lists, source code control systems,
58 | and issue tracking systems that are managed by, or on behalf of, the
59 | Licensor for the purpose of discussing and improving the Work, but
60 | excluding communication that is conspicuously marked or otherwise
61 | designated in writing by the copyright owner as "Not a Contribution."
62 |
63 | "Contributor" shall mean Licensor and any individual or Legal Entity
64 | on behalf of whom a Contribution has been received by Licensor and
65 | subsequently incorporated within the Work.
66 |
67 | 2. Grant of Copyright License. Subject to the terms and conditions of
68 | this License, each Contributor hereby grants to You a perpetual,
69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70 | copyright license to reproduce, prepare Derivative Works of,
71 | publicly display, publicly perform, sublicense, and distribute the
72 | Work and such Derivative Works in Source or Object form.
73 |
74 | 3. Grant of Patent License. Subject to the terms and conditions of
75 | this License, each Contributor hereby grants to You a perpetual,
76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77 | (except as stated in this section) patent license to make, have made,
78 | use, offer to sell, sell, import, and otherwise transfer the Work,
79 | where such license applies only to those patent claims licensable
80 | by such Contributor that are necessarily infringed by their
81 | Contribution(s) alone or by combination of their Contribution(s)
82 | with the Work to which such Contribution(s) was submitted. If You
83 | institute patent litigation against any entity (including a
84 | cross-claim or counterclaim in a lawsuit) alleging that the Work
85 | or a Contribution incorporated within the Work constitutes direct
86 | or contributory patent infringement, then any patent licenses
87 | granted to You under this License for that Work shall terminate
88 | as of the date such litigation is filed.
89 |
90 | 4. Redistribution. You may reproduce and distribute copies of the
91 | Work or Derivative Works thereof in any medium, with or without
92 | modifications, and in Source or Object form, provided that You
93 | meet the following conditions:
94 |
95 | (a) You must give any other recipients of the Work or
96 | Derivative Works a copy of this License; and
97 |
98 | (b) You must cause any modified files to carry prominent notices
99 | stating that You changed the files; and
100 |
101 | (c) You must retain, in the Source form of any Derivative Works
102 | that You distribute, all copyright, patent, trademark, and
103 | attribution notices from the Source form of the Work,
104 | excluding those notices that do not pertain to any part of
105 | the Derivative Works; and
106 |
107 | (d) If the Work includes a "NOTICE" text file as part of its
108 | distribution, then any Derivative Works that You distribute must
109 | include a readable copy of the attribution notices contained
110 | within such NOTICE file, excluding those notices that do not
111 | pertain to any part of the Derivative Works, in at least one
112 | of the following places: within a NOTICE text file distributed
113 | as part of the Derivative Works; within the Source form or
114 | documentation, if provided along with the Derivative Works; or,
115 | within a display generated by the Derivative Works, if and
116 | wherever such third-party notices normally appear. The contents
117 | of the NOTICE file are for informational purposes only and
118 | do not modify the License. You may add Your own attribution
119 | notices within Derivative Works that You distribute, alongside
120 | or as an addendum to the NOTICE text from the Work, provided
121 | that such additional attribution notices cannot be construed
122 | as modifying the License.
123 |
124 | You may add Your own copyright statement to Your modifications and
125 | may provide additional or different license terms and conditions
126 | for use, reproduction, or distribution of Your modifications, or
127 | for any such Derivative Works as a whole, provided Your use,
128 | reproduction, and distribution of the Work otherwise complies with
129 | the conditions stated in this License.
130 |
131 | 5. Submission of Contributions. Unless You explicitly state otherwise,
132 | any Contribution intentionally submitted for inclusion in the Work
133 | by You to the Licensor shall be under the terms and conditions of
134 | this License, without any additional terms or conditions.
135 | Notwithstanding the above, nothing herein shall supersede or modify
136 | the terms of any separate license agreement you may have executed
137 | with Licensor regarding such Contributions.
138 |
139 | 6. Trademarks. This License does not grant permission to use the trade
140 | names, trademarks, service marks, or product names of the Licensor,
141 | except as required for reasonable and customary use in describing the
142 | origin of the Work and reproducing the content of the NOTICE file.
143 |
144 | 7. Disclaimer of Warranty. Unless required by applicable law or
145 | agreed to in writing, Licensor provides the Work (and each
146 | Contributor provides its Contributions) on an "AS IS" BASIS,
147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148 | implied, including, without limitation, any warranties or conditions
149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150 | PARTICULAR PURPOSE. You are solely responsible for determining the
151 | appropriateness of using or redistributing the Work and assume any
152 | risks associated with Your exercise of permissions under this License.
153 |
154 | 8. Limitation of Liability. In no event and under no legal theory,
155 | whether in tort (including negligence), contract, or otherwise,
156 | unless required by applicable law (such as deliberate and grossly
157 | negligent acts) or agreed to in writing, shall any Contributor be
158 | liable to You for damages, including any direct, indirect, special,
159 | incidental, or consequential damages of any character arising as a
160 | result of this License or out of the use or inability to use the
161 | Work (including but not limited to damages for loss of goodwill,
162 | work stoppage, computer failure or malfunction, or any and all
163 | other commercial damages or losses), even if such Contributor
164 | has been advised of the possibility of such damages.
165 |
166 | 9. Accepting Warranty or Additional Liability. While redistributing
167 | the Work or Derivative Works thereof, You may choose to offer,
168 | and charge a fee for, acceptance of support, warranty, indemnity,
169 | or other liability obligations and/or rights consistent with this
170 | License. However, in accepting such obligations, You may act only
171 | on Your own behalf and on Your sole responsibility, not on behalf
172 | of any other Contributor, and only if You agree to indemnify,
173 | defend, and hold each Contributor harmless for any liability
174 | incurred by, or claims asserted against, such Contributor by reason
175 | of your accepting any such warranty or additional liability.
176 |
177 | END OF TERMS AND CONDITIONS
178 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Couchbase JDBC Driver
2 |
3 | This project is a JDBC driver for accessing the Couchbase NoSQL database. Couchbase stores data as JSON documents.
4 | The N1QL query language is based on SQL, but designed for querying JSON data sources, such as Couchbase.
5 | This driver lets the user run N1QL queries against Couchbase, and retrieve JSON data through the standard
6 | JDBC interfaces.
7 |
8 | Both simple JSON values (string/numbers/booleans) and compound JSON values (objects/arrays) are supported.
9 | Both types of values can be retrieved as fields and supplied as parameters.
10 |
11 | Users who do not have a pre-existing investment in JDBC but still want to access Couchbase through Java
12 | may find the [Couchbase Java SDK](http://developer.couchbase.com/documentation/server/current/sdk/java/start-using-sdk.html)
13 | a more convenient solution.
14 |
15 | ## Brief Setup Instructions
16 |
17 | The Maven coordinates of the driver are
18 |
19 |
20 | com.couchbase.jdbc
21 | jdbc-n1ql
22 | 1.0-BETA
23 |
24 |
25 | The driver enables communication with Couchbase through the standard JDBC interfaces. Use connect string `jdbc:couchbase://localhost:8093` to connect to the Couchbase instance on your local machine.
26 |
27 | If you have the *beer-sample* sample bucket installed, this query returns a manageable set of ten rows with two fields per row:
28 |
29 | select name, code from `beer-sample` where city = 'San Francisco' and type = 'brewery'
30 |
31 | To run the query, you will need to create a primary index on *beer-sample*.
32 |
33 | ## Detailed Setup Instructions
34 |
35 | These instructions assume you are conversant with the Java ecosystem, and therefore
36 | know your way around Maven. Use Maven 3 and Java 8.
37 |
38 | Install Couchbase on your local machine. Instructions are [here](http://developer.couchbase.com/documentation/server/current/getting-started/installing.html).
39 |
40 | Go to to Administration Console at *http://localhost:8091* and log in using the Administrator password you supplied during installation. In the *Settings* tab you will find the *Sample Buckets* section, with a set of available sample buckets. Check the *beer-sample* box to create this set of sample data.
41 |
42 | CBQ is the tool for running N1QL queries against Couchbase. Instructions for running it are [here](http://developer.couchbase.com/documentation/server/current/n1ql/n1ql-intro/cbq.html). Create a primary index on the *beer-sample* bucket by running this command in CBQ:
43 |
44 | create primary index on `beer-sample`;
45 |
46 | Create a new Maven project. Add this dependency to the *pom.xml* file, which should already exist in your new project:
47 |
48 |
49 |
50 | com.couchbase.jdbc
51 | jdbc-n1ql
52 | 1.0-BETA/version>
53 |
54 |
55 |
56 | Add a new Java class to the src/main/java/trial directory of the project:
57 |
58 | package com.couchbase.jdbc.examples;
59 | import java.sql.Connection;
60 | import java.sql.DriverManager;
61 | import java.sql.ResultSet;
62 | import java.sql.Statement;
63 | public class SimpleVerification {
64 | static String ConnectionURL = "jdbc:couchbase://localhost:8093";
65 | public static void main(String[] args) throws Exception {
66 | Connection con = DriverManager.getConnection(ConnectionURL);
67 | Statement stmt = con.createStatement();
68 | ResultSet rs = stmt.executeQuery("select name,code from `beer-sample` where city = 'San Francisco' and type = 'brewery'");
69 | while (rs.next()) {
70 | String name = rs.getString("name");
71 | String code = rs.getString("code");
72 | System.out.println("name: " + name + ", code: " + code);
73 | }
74 | }
75 | }
76 |
77 | Run the new class. You should see this output:
78 |
79 | 12:35:19.121 [main] DEBUG com.couchbase.CBResultSet - Loaded result set
80 | name: 21st Amendment Brewery Cafe, code: 94107
81 | name: Anchor Brewing, code: 94107
82 | name: Beach Chalet Brewery, code: 94121
83 | name: Big Bang Brewery (Closed), code: 94107
84 | name: Golden Gate Park Brewery, code:
85 | name: Magnolia Pub and Brewery, code: 94117
86 | name: Shmaltz Brewing Company, code:
87 | name: Shmaltz Enterprises, code: 94110
88 | name: Speakeasy Ales and Lagers, code: 94124
89 | name: ThirstyBear Brewing, code: 94105
90 |
91 | The */examples* directory contains additional example files, showing how to use the driver.
92 |
93 | ## Additional Usage Notes
94 |
95 | The connection string, used in the `DriverManager.getConnection()` call, should be of the form `jdbc:couchbase://:`.
96 |
97 | If you are working with an instance of Couchbase on your local machine, use the string `jdbc:couchbase://localhost:8093`.
98 |
99 | If you are working with a Couchbase cluster, the host should be the name or ip address of a Couchbase node running the Query service.
100 | The driver will then distribute the queries around the nodes of the cluster in round-robin fashion. You can check which nodes are
101 | running the Query service on the "Server Nodes" tab of the Couchbase Admin Console. The "Services" column shows which nodes are
102 | running which service. The port is the port of the query service; 8093 by default.
103 |
104 | Couchbase supports access over SSL-protected connections, but only Enterprise Edition supports this, not Community Edition.
105 | To use SSL, connect on the 18093 port rather than the standard 8093 port. For a more detailed example of how to use SSL, consult
106 | the SSL connection test at *src/test/java/com/couchbase/jdbc/SSLConnectionTest.java*.
107 |
108 | ## Building the Driver from Source
109 |
110 | You need to have Git, Maven 3 and Java 8 installed on your machine.
111 |
112 | Run the following commands:
113 |
114 | git clone https://github.com/jdbc-json/jdbc-cb
115 | cd jdbc-cb
116 | mvn -Dmaven.test.skip=true package
117 |
118 | The JAR file will be in the */target* directory.
119 |
120 | By default, `mvn package` runs the unit tests before creating the JAR.
121 | These directions specifically omit running the unit tests, because the tests require additional setup, as explained in the next section.
122 | After the setup is complete, you can run `mvn package` without the extra flag.
123 |
124 | ## Running the Unit Tests
125 |
126 | (Assuming you have downloaded and built the driver from source, as described above.)
127 |
128 | The unit tests assume an instance of Couchbase Enterprise Edition is set up and accessible on
129 | the local machine. If the Couchbase instance is Community Edition, the SSLConnectionTest will fail because
130 | Community Edition instances are not accessible over SSL.
131 | The administrator and password should be "Administrator" and "password",
132 | respectively. The *beer-sample* and *default* data buckets
133 | should be present. The *default* bucket is always present; *beer-sample* is created on request at installation time.
134 |
135 | The beer-sample and default buckets must be indexed for the tests to run correctly.
136 | You can index them by running these two commands in the CBQ:
137 |
138 | create primary index on default;
139 | create primary index on `beer-sample`;
140 |
141 | Note the back-ticks in the second line.
142 |
143 | Run all the tests with this command:
144 |
145 | mvn test
146 |
147 | Run a specific test with a command like this:
148 |
149 | mvn test -Dtest=com.couchbase.jdbc.PreparedStatementTest
150 |
--------------------------------------------------------------------------------
/examples/CompoundElements.java:
--------------------------------------------------------------------------------
1 | package com.couchbase.jdbc.examples;
2 |
3 | import java.sql.Array;
4 | import java.sql.Connection;
5 | import java.sql.DriverManager;
6 | import java.sql.PreparedStatement;
7 | import java.sql.ResultSet;
8 | import java.sql.Statement;
9 | import java.util.HashMap;
10 | import java.util.Map;
11 |
12 | /*
13 | * This example shows how work with JSON objects and arrays using the Couchbase JDBC driver.
14 | * It creates a value with two fields, received as parameters, one a JSON object and the
15 | * other a JSON array.
16 | * It then retrieves these two fields, and makes the accessible as a map and an array.
17 | */
18 |
19 | public class CompoundElements {
20 | static String ConnectionURL = "jdbc:couchbase://localhost:8093";
21 |
22 | @SuppressWarnings("unchecked")
23 | public static void main(String[] args) throws Exception {
24 | Connection con = DriverManager.getConnection(ConnectionURL);
25 | PreparedStatement ps = con.prepareStatement("insert into default(key, value) values ('comp1', { 'obj': ?, 'arr': ?, 'type': 'compound'})");
26 |
27 | // Set a JSON object parameter.
28 | HashMap m = new HashMap();
29 | m.put("length", "234");
30 | m.put("width", "12");
31 | ps.setObject(1, m);
32 |
33 | // Set a JSON array parameter.
34 | Object[] arrElems = new Object[]{ "one", "two", "three" };
35 | Array arr = con.createArrayOf(null, arrElems);
36 | ps.setArray(2, arr);
37 |
38 | int numUpdate = ps.executeUpdate();
39 | System.out.println("Created " + numUpdate);
40 | System.out.println();
41 | Thread.sleep(1000);
42 |
43 | // Retrieve the object.
44 | Statement stmt = con.createStatement();
45 | ResultSet rs = stmt.executeQuery("select obj, arr from default where type = 'compound'");
46 | rs.next();
47 |
48 | // Retrieve the JSON object field.
49 | System.out.println("RETRIEVED OBJECT FIELDS");
50 | Map objResult = (Map) rs.getObject("obj");
51 | System.out.println("length: " + objResult.get("length"));
52 | System.out.println("width: " + objResult.get("width"));
53 | System.out.println();
54 |
55 | // Retrieve the JSON array field.
56 | System.out.println("RETRIEVED ARRAY ELEMENTS");
57 | Array arrResult= rs.getArray("arr");
58 | Object[] elements = (Object[]) arrResult.getArray();
59 | for (Object o : elements) {
60 | System.out.println(o.toString());
61 | }
62 | System.out.println();
63 |
64 | // Clean up.
65 | numUpdate = stmt.executeUpdate("delete from default where type = 'compound'");
66 | System.out.println("Deleted " + numUpdate);
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/examples/CrudOperations.java:
--------------------------------------------------------------------------------
1 | package com.couchbase.jdbc.examples;
2 |
3 | import java.sql.Connection;
4 | import java.sql.DriverManager;
5 | import java.sql.ResultSet;
6 | import java.sql.Statement;
7 |
8 | /*
9 | * This example shows how to insert, update, select, and delete values
10 | * using the Couchbase JDBC driver.
11 | *
12 | * This example adds, modifies, retrieves, and deletes a value from the "default" bucket.
13 | */
14 | public class CrudOperations {
15 |
16 | static String ConnectionURL = "jdbc:couchbase://localhost:8093";
17 |
18 | public static void main(String[] args) throws Exception {
19 |
20 | Connection con = DriverManager.getConnection(ConnectionURL);
21 | Statement stmt = con.createStatement();
22 |
23 | int numUpdates;
24 |
25 | // Create a value.
26 | numUpdates = stmt.executeUpdate("insert into default (key, value) values ('crud-test1', { 'type': 'crud', 'num': 55 }), ('crud-test2', { 'type': 'crud', 'num': 65 }) ");
27 | System.out.println("Created " + numUpdates + " values.");
28 | Thread.sleep(1000); // Wait for the update to propagate.
29 |
30 | // Modify a value.
31 | numUpdates = stmt.executeUpdate("update default set name = 'apple' where type = 'crud' and num = 55");
32 | System.out.println("Modified " + numUpdates + " values.");
33 | Thread.sleep(1000); // Wait for the update to propagate.
34 |
35 |
36 | // Retrieve the values.
37 | ResultSet rs = stmt.executeQuery("select * from default where type = 'crud'");
38 | while (rs.next()) {
39 | System.out.println("Value: " + rs.getString(1));
40 | }
41 |
42 | // Delete the values.
43 | numUpdates = stmt.executeUpdate("delete from default where type = 'crud'");
44 | System.out.println("Deleted " + numUpdates + " values.");
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/examples/PreparedStatements.java:
--------------------------------------------------------------------------------
1 | package com.couchbase.jdbc.examples;
2 |
3 | import java.sql.Connection;
4 | import java.sql.DriverManager;
5 | import java.sql.PreparedStatement;
6 | import java.sql.ResultSet;
7 | import java.sql.Statement;
8 |
9 | /*
10 | * This example shows how to use prepared statements and set parameters
11 | * through the Couchbase JDBC driver.
12 | */
13 | public class PreparedStatements {
14 | static String ConnectionURL = "jdbc:couchbase://localhost:8093";
15 |
16 | public static void main(String[] args) throws Exception {
17 | Connection con = DriverManager.getConnection(ConnectionURL);
18 | PreparedStatement ps = con.prepareStatement("insert into default(key, value) values (?, [?, ?, ?, ?])");
19 | int numUpdates;
20 |
21 | // Insert first array.
22 | ps.setString(1, "ps1");
23 | ps.setInt(2, 33);
24 | ps.setDouble(3, 950.3);
25 | ps.setBoolean(4, false);
26 | ps.setString(5, "ps");
27 | numUpdates = ps.executeUpdate();
28 | System.out.println("Inserted " + numUpdates);
29 |
30 | // Insert second array.
31 | ps.setString(1, "ps2");
32 | ps.setString(2, "second");
33 | ps.setString(3, "second");
34 | ps.setString(4, "second");
35 | ps.setString(5, "ps");
36 | numUpdates = ps.executeUpdate();
37 | System.out.println("Inserted " + numUpdates);
38 |
39 | // Insert third array.
40 | ps.setString(1, "ps3");
41 | ps.setInt(2, 3);
42 | ps.setInt(3, 3);
43 | ps.setInt(4, 3);
44 | ps.setString(5, "ps");
45 | numUpdates = ps.executeUpdate();
46 | System.out.println("Inserted " + numUpdates);
47 |
48 | // Retrieve what we inserted.
49 | Thread.sleep(1000); // Wait for the updates to propagate.
50 | Statement stmt = con.createStatement();
51 | ResultSet rs = stmt.executeQuery("select meta(d).id, * from default d where d[3] = 'ps'");
52 | while (rs.next()) {
53 | System.out.println("key: " + rs.getString("id") + ", value: " + rs.getString("d"));
54 | }
55 |
56 | // Clean up.
57 | numUpdates = stmt.executeUpdate("delete from default d where d[3] = 'ps'");
58 | System.out.println("Deleted " + numUpdates);
59 | }
60 |
61 | }
62 |
--------------------------------------------------------------------------------
/examples/README.md:
--------------------------------------------------------------------------------
1 | # How to Use the Driver
2 |
3 | This directory contains example files that show how to use the driver.
4 | All five files have `main()` functions, so you can run them directly;
5 | they are set up to connect to the Couchbase instance running on the local machine.
6 |
7 | The first four require *beer-sample* and *default* buckets to exist and have primary indexes.
8 | The last one has more specific set-up instructions in the comments of the file itself.
9 |
10 | * *SimpleSelects.java* shows how to retrieve simple JSON values -- strings, numbers, and booleans -- from Couchbase.
11 | * *CrudOperations.java* shows how to create, read, update, and delete entries in Couchbase using the N1QL query languge,
12 | through the driver.
13 | * *PreparedStatements.java* shows how to use prepared statements and parameters. There queries are readied once, and can then
14 | be executed multiple times with varying parameters.
15 | * *CompoundElements.java* shows how to insert and retrieve JSON object and array values.
16 | * *UseSQLJSON.java* shows how to use SQLJSON, an extended interface for results, available only in this driver.
17 | * In Couchbase, buckets can be protected with passwords. *UseCredentials.java* shows how to provide such passwords to the driver
18 | to allow access to these buckets.
19 |
--------------------------------------------------------------------------------
/examples/SimpleSelects.java:
--------------------------------------------------------------------------------
1 | package com.couchbase.jdbc.examples;
2 |
3 | import java.sql.Connection;
4 | import java.sql.DriverManager;
5 | import java.sql.ResultSet;
6 | import java.sql.Statement;
7 |
8 | /*
9 | * This example shows
10 | * a) How to run a simple SELECT statement using the Couchbase JDBC driver.
11 | * b) How to retrieve scalar field values from the rows.
12 | */
13 | public class SimpleSelects {
14 | static String ConnectionURL = "jdbc:couchbase://localhost:8093";
15 |
16 | public static void main(String[] args) throws Exception {
17 | Connection con = DriverManager.getConnection(ConnectionURL);
18 | Statement stmt = con.createStatement();
19 |
20 | ResultSet rs = stmt
21 | .executeQuery("select name, abv, (abv > 5) as strong from `beer-sample` where type = 'beer' limit 10");
22 | System.out.println("TEN BEERS");
23 | while (rs.next()) {
24 | String name = rs.getString("name");
25 | double abv = rs.getDouble("abv");
26 | boolean strong = rs.getBoolean("strong");
27 | System.out.println("name: " + name + ", abv: " + abv + ", strong: " + strong);
28 | }
29 | System.out.println();
30 |
31 | rs = stmt.executeQuery("select category, count(*) as num from `beer-sample` where type = 'beer' group by category");
32 | System.out.println("BEER CATEGORIES");
33 | while (rs.next()) {
34 | System.out.println(rs.getString("category") + ": " + rs.getInt("num"));
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/examples/UseCredentials.java:
--------------------------------------------------------------------------------
1 | package com.couchbase.jdbc.examples;
2 |
3 | import java.sql.Connection;
4 | import java.sql.DriverManager;
5 | import java.sql.Statement;
6 | import java.util.Properties;
7 |
8 | import com.couchbase.jdbc.util.Credentials;
9 |
10 | /*
11 | * This example shows how to provide per-bucket credentials (passwords)
12 | * through the Couchbase JDBC driver.
13 | *
14 | * Initially, this code will not work. It requires some setup.
15 | * First create two buckets, rb1 and rb2. Then use the CBQ tool to create primary indexes on both
16 | * buckets. Finally add passwords rb1p and rb2p on the two buckets.
17 | * The code will then run correctly.
18 | *
19 | * Instead of supplying both per-bucket passwords, you can supply the Administrator
20 | * and admin password instead. That overrides the per-bucket passwords.
21 | */
22 | public class UseCredentials {
23 | static String ConnectionURL = "jdbc:couchbase://localhost:8093";
24 |
25 | public static void main(String[] args) throws Exception {
26 | Credentials cred = new Credentials();
27 | cred.add("rb1", "rb1p");
28 | cred.add("rb2", "rb2p");
29 | // cred.add("Administrator", "password"); // Alternate credential.
30 |
31 | Properties prop = new Properties();
32 | prop.setProperty("credentials", cred.toString());
33 |
34 | Connection con = DriverManager.getConnection(ConnectionURL, prop);
35 | Statement stmt = con.createStatement();
36 | stmt.executeQuery("select count(*) from rb1 union select count(*) from rb2");
37 | System.out.println("Success.");
38 | }
39 |
40 | }
41 |
--------------------------------------------------------------------------------
/examples/UseSQLJSON.java:
--------------------------------------------------------------------------------
1 | package com.couchbase.jdbc.examples;
2 |
3 | import java.sql.DriverManager;
4 | import java.sql.Statement;
5 | import java.util.Arrays;
6 | import java.util.HashMap;
7 |
8 | import com.couchbase.jdbc.CBConnection;
9 | import com.couchbase.jdbc.CBPreparedStatement;
10 | import com.couchbase.jdbc.CBResultSet;
11 | import com.couchbase.json.SQLJSON;
12 |
13 | /*
14 | * This example shows how work with SQLJSON objects and arrays using the Couchbase JDBC driver.
15 | * It creates a value with two fields, received as parameters, one a JSON object and the
16 | * other a JSON array.
17 | * It then retrieves these two fields, and makes the accessible as a map and a list.
18 | */
19 |
20 | public class UseSQLJSON {
21 | static String ConnectionURL = "jdbc:couchbase://localhost:8093";
22 |
23 | public static void main(String[] args) throws Exception {
24 | // Note the use of specialized versions of Connection and PreparedStatement,
25 | // so we can use to the SQLJSON access functions.
26 | CBConnection con = (CBConnection)DriverManager.getConnection(ConnectionURL);
27 | CBPreparedStatement ps = (CBPreparedStatement)con.prepareStatement("insert into default(key, value) values ('comp1', { 'obj': ?, 'arr': ?, 'type': 'sqljson-compound'})");
28 |
29 | // Set a JSON object parameter.
30 | HashMap m = new HashMap<>();
31 | m.put("length", "234");
32 | m.put("width", "12");
33 | SQLJSON json = con.createSQLJSON();
34 | json.setMap(m);
35 | ps.setSQLJSON(1, json);
36 |
37 | // Set a JSON array parameter.
38 | SQLJSON arr = con.createSQLJSON();
39 | arr.setArray(Arrays.asList("one", "two", "three" ));
40 | ps.setSQLJSON(2, arr);
41 |
42 | int numUpdate = ps.executeUpdate();
43 | System.out.println("Created " + numUpdate);
44 | System.out.println();
45 | Thread.sleep(1000);
46 |
47 | // Retrieve the object.
48 | Statement stmt = con.createStatement();
49 | CBResultSet rs = (CBResultSet)stmt.executeQuery("select obj, arr from default where type = 'sqljson-compound'");
50 | rs.next();
51 |
52 | // Retrieve the JSON object field.
53 | System.out.println("RETRIEVED OBJECT FIELDS");
54 | SQLJSON objField = rs.getSQLJSON("obj");
55 | System.out.println("length: " + objField.getMap().get("length"));
56 | System.out.println("width: " + objField.getMap().get("width"));
57 | System.out.println();
58 |
59 | // Retrieve the JSON array field.
60 | System.out.println("RETRIEVED ARRAY ELEMENTS");
61 | SQLJSON arrField = rs.getSQLJSON("arr");
62 | for (Object o : arrField.getArray()) {
63 | System.out.println(o);
64 | }
65 | System.out.println();
66 |
67 | // Clean up.
68 | numUpdate = stmt.executeUpdate("delete from default where type = 'sqljson-compound'");
69 | System.out.println("Deleted " + numUpdate);
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
3 | 4.0.0
4 |
5 | com.couchbase.jdbc
6 | jdbc-n1ql
7 | 1.0-SNAPSHOT
8 |
9 | jar
10 |
11 |
12 | org.sonatype.oss
13 | oss-parent
14 | 7
15 |
16 |
17 | Couchbase JDBC-JSON Driver
18 | A JDBC driver for the Couchbase database, based on the N1QL query language.
19 | http://maven.apache.org
20 |
21 |
22 |
23 | The Apache License, Version 2.0
24 | http://www.apache.org/licenses/LICENSE-2.0.txt
25 |
26 |
27 |
28 |
29 |
30 | Johan Larson
31 | johan.larson@couchbase.com
32 | Couchbase
33 | http://www.couchbase.com
34 |
35 |
36 | David Cramer
37 | davecramer@gmail.com
38 |
39 |
40 |
41 |
42 | scm:git:git@github.com:jdbc-json/jdbc-cb.git
43 | scm:git:git@github.com:jdbc-json/jdbc-cb.git
44 | git@github.com:jdbc-json/jdbc-cb.git
45 |
46 |
47 |
48 | UTF-8
49 | /var/www/html
50 |
51 |
52 |
53 |
54 | junit
55 | junit
56 | 4.11
57 | test
58 |
59 |
60 | org.apache.httpcomponents
61 | httpclient
62 | 4.4
63 |
64 |
65 | com.googlecode.json-simple
66 | json-simple
67 | 1.1
68 |
69 |
70 | org.slf4j
71 | slf4j-api
72 | 1.7.12
73 |
74 |
75 | ch.qos.logback
76 | logback-classic
77 | 1.1.2
78 |
79 |
80 | io.fastjson
81 | boon
82 | 0.33
83 |
84 |
85 |
86 |
87 |
88 | ossrh
89 | https://oss.sonatype.org/content/repositories/snapshots
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 | org.apache.maven.plugins
98 | maven-compiler-plugin
99 | 3.3
100 |
101 | 1.7
102 | 1.7
103 |
104 |
105 |
106 | org.apache.maven.plugins
107 | maven-shade-plugin
108 | 2.4
109 |
110 |
111 | package
112 |
113 | shade
114 |
115 |
116 |
117 |
118 | junit:junit
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 | release
133 |
134 |
135 |
136 | org.apache.maven.plugins
137 | maven-source-plugin
138 | 2.2.1
139 |
140 |
141 | attach-sources
142 |
143 | jar-no-fork
144 |
145 |
146 |
147 |
148 |
149 | org.apache.maven.plugins
150 | maven-javadoc-plugin
151 | 2.9.1
152 |
153 |
154 | attach-javadocs
155 |
156 | jar
157 |
158 |
159 |
160 |
161 |
162 | org.sonatype.plugins
163 | nexus-staging-maven-plugin
164 | 1.6.3
165 | true
166 |
167 | ossrh
168 | https://oss.sonatype.org/
169 | true
170 |
171 |
172 |
173 | org.apache.maven.plugins
174 | maven-gpg-plugin
175 | 1.5
176 |
177 |
178 | sign-artifacts
179 | verify
180 |
181 | sign
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
--------------------------------------------------------------------------------
/src/main/java/com/couchbase/jdbc/CBDriver.java:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | * // Copyright (c) 2015 Couchbase, Inc.
4 | * // Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
5 | * // except in compliance with the License. You may obtain a copy of the License at
6 | * // http://www.apache.org/licenses/LICENSE-2.0
7 | * // Unless required by applicable law or agreed to in writing, software distributed under the
8 | * // License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
9 | * // either express or implied. See the License for the specific language governing permissions
10 | * // and limitations under the License.
11 | */
12 |
13 | package com.couchbase.jdbc;
14 |
15 |
16 | import ch.qos.logback.classic.Level;
17 | import ch.qos.logback.classic.Logger;
18 |
19 | import org.slf4j.LoggerFactory;
20 |
21 | import java.sql.*;
22 | import java.text.MessageFormat;
23 | import java.util.Properties;
24 | import java.util.concurrent.ConcurrentLinkedQueue;
25 |
26 |
27 | public class CBDriver implements java.sql.Driver
28 | {
29 | public static final org.slf4j.Logger logger = LoggerFactory.getLogger(CBDriver.class.getName());
30 |
31 | public static final int MAJOR_VERSION = 1;
32 |
33 | public static final int MINOR_VERSION = 1;
34 |
35 | public static final String DRIVER_NAME = "n1ql_jdbc";
36 |
37 | static CBDriver registered;
38 |
39 | final Thread houseKeepingThread;
40 | final ClusterThread ct;
41 | static
42 | {
43 | try
44 | {
45 | registered = new CBDriver();
46 | java.sql.DriverManager.registerDriver(registered);
47 |
48 | }
49 | catch (SQLException e)
50 | {
51 | logger.error("Error registering driver", e);
52 | }
53 |
54 |
55 | }
56 |
57 | public CBDriver() throws SQLException
58 | {
59 | ct = new ClusterThread();
60 | houseKeepingThread = new Thread(ct, "Couchbase housekeeping thread");
61 | houseKeepingThread.setDaemon(true);
62 | houseKeepingThread.start();
63 | }
64 | /**
65 | * Attempts to make a database connection to the given URL.
66 | * The driver should return "null" if it realizes it is the wrong kind
67 | * of driver to connect to the given URL. This will be common, as when
68 | * the JDBC driver manager is asked to connect to a given URL it passes
69 | * the URL to each loaded driver in turn.
70 | *
71 | *
The driver should throw an SQLException if it is the right
72 | * driver to connect to the given URL but has trouble connecting to
73 | * the database.
74 | *
75 | *
The java.util.Properties argument can be used to pass
76 | * arbitrary string tag/value pairs as connection arguments.
77 | * Normally at least "user" and "password" properties should be
78 | * included in the Properties object.
79 | *
80 | * @param url the URL of the database to which to connect
81 | * @param info a list of arbitrary string tag/value pairs as
82 | * connection arguments. Normally at least a "user" and
83 | * "password" property should be included.
84 | * @return a Connection object that represents a
85 | * connection to the URL
86 | * @throws java.sql.SQLException if a database access error occurs
87 | */
88 | @Override
89 | public Connection connect(String url, Properties info) throws SQLException
90 | {
91 |
92 | if (acceptsURL(url))
93 | {
94 | CBConnection con = new CBConnection(url, info);
95 | ct.addConnection(con);
96 | return con;
97 | }
98 | else
99 | {
100 | return null;
101 | }
102 | }
103 |
104 | /**
105 | * Retrieves whether the driver thinks that it can open a connection
106 | * to the given URL. Typically drivers will return true if they
107 | * understand the subprotocol specified in the URL and false if
108 | * they do not.
109 | *
110 | * @param url the URL of the database
111 | * @return true if this driver understands the given URL;
112 | * false otherwise
113 | * @throws java.sql.SQLException if a database access error occurs
114 | */
115 | @Override
116 | public boolean acceptsURL(String url) throws SQLException
117 | {
118 | return url.startsWith("jdbc:couchbase:");
119 | }
120 |
121 | /**
122 | * Gets information about the possible properties for this driver.
123 | *
124 | * The getPropertyInfo method is intended to allow a generic
125 | * GUI tool to discover what properties it should prompt
126 | * a human for in order to get
127 | * enough information to connect to a database. Note that depending on
128 | * the values the human has supplied so far, additional values may become
129 | * necessary, so it may be necessary to iterate though several calls
130 | * to the getPropertyInfo method.
131 | *
132 | * @param url the URL of the database to which to connect
133 | * @param info a proposed list of tag/value pairs that will be sent on
134 | * connect open
135 | * @return an array of DriverPropertyInfo objects describing
136 | * possible properties. This array may be an empty array if
137 | * no properties are required.
138 | * @throws java.sql.SQLException if a database access error occurs
139 | */
140 | @Override
141 | public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) throws SQLException
142 | {
143 | return new DriverPropertyInfo[0];
144 | }
145 |
146 | /**
147 | * Retrieves the driver's major version number. Initially this should be 1.
148 | *
149 | * @return this driver's major version number
150 | */
151 | @Override
152 | public int getMajorVersion()
153 | {
154 | return 0;
155 | }
156 |
157 | /**
158 | * Gets the driver's minor version number. Initially this should be 0.
159 | *
160 | * @return this driver's minor version number
161 | */
162 | @Override
163 | public int getMinorVersion()
164 | {
165 | return 0;
166 | }
167 |
168 | /**
169 | * Reports whether this driver is a genuine JDBC
170 | * Compliant(TM) driver.
171 | * A driver may only report true here if it passes the JDBC
172 | * compliance tests; otherwise it is required to return false.
173 | *
174 | * JDBC compliance requires full support for the JDBC API and full support
175 | * for SQL 92 Entry Level. It is expected that JDBC compliant drivers will
176 | * be available for all the major commercial databases.
177 | *
178 | * This method is not intended to encourage the development of non-JDBC
179 | * compliant drivers, but is a recognition of the fact that some vendors
180 | * are interested in using the JDBC API and framework for lightweight
181 | * databases that do not support full database functionality, or for
182 | * special databases such as document information retrieval where a SQL
183 | * implementation may not be feasible.
184 | *
185 | * @return true if this driver is JDBC Compliant; false
186 | * otherwise
187 | */
188 | @Override
189 | public boolean jdbcCompliant()
190 | {
191 | return false;
192 | }
193 |
194 | private static final MessageFormat mf = new MessageFormat("Method {0}.{1} is not yet implemented.");
195 |
196 | public static java.sql.SQLFeatureNotSupportedException notImplemented(Class callClass, String functionName)
197 | {
198 |
199 | return new java.sql.SQLFeatureNotSupportedException(mf.format(new Object [] {callClass.getName(),functionName}));
200 | }
201 |
202 | public static void setLogLevel(Level logLevel)
203 | {
204 | synchronized (CBDriver.class)
205 | {
206 | Logger logger = (ch.qos.logback.classic.Logger) LoggerFactory.getLogger("com.couchbase");
207 | logger.setLevel(logLevel);
208 | //logLevelSet = true;
209 | }
210 | }
211 |
212 | public static Level getLogLevel()
213 | {
214 | synchronized (CBDriver.class)
215 | {
216 | Logger logger = (ch.qos.logback.classic.Logger) LoggerFactory.getLogger("com.couchbase");
217 | return logger.getLevel();
218 | }
219 | }
220 |
221 | /**
222 | * Return the parent Logger of all the Loggers used by this driver. This
223 | * should be the Logger farthest from the root Logger that is
224 | * still an ancestor of all of the Loggers used by this driver. Configuring
225 | * this Logger will affect all of the log messages generated by the driver.
226 | * In the worst case, this may be the root Logger.
227 | *
228 | * @return the parent Logger for this driver
229 | * @throws java.sql.SQLFeatureNotSupportedException if the driver does not use java.util.logging.
230 | * @since 1.7
231 | */
232 | @Override
233 | public java.util.logging.Logger getParentLogger() throws SQLFeatureNotSupportedException
234 | {
235 | throw notImplemented(CBDriver.class, "getParentLogger");
236 | }
237 |
238 | public static void cleanup()
239 | {
240 | if (registered != null)
241 | {
242 | try
243 | {
244 | DriverManager.deregisterDriver(registered);
245 |
246 | //stop the thread below
247 | runCluster=false;
248 | Thread.currentThread().interrupt();
249 |
250 |
251 | }
252 | catch (SQLException e)
253 | {
254 | logger.warn("Error deregistering driver", e);
255 | }
256 | }
257 | }
258 | public void cleanup(CBConnection con)
259 | {
260 | ct.removeConnection(con);
261 | }
262 |
263 | static boolean runCluster=true;
264 |
265 | private static class ClusterThread implements Runnable
266 | {
267 |
268 | ConcurrentLinkedQueue connections;
269 | ClusterThread()
270 | {
271 | connections = new ConcurrentLinkedQueue();
272 | }
273 | @Override
274 | public void run()
275 | {
276 | while(runCluster)
277 | {
278 | CBConnection connection = connections.poll();
279 | if ( connection != null )
280 | {
281 | try
282 | {
283 | connection.pollCluster();
284 | } catch (SQLException e)
285 | {
286 | logger.error("Error polling cluster", e);
287 | }
288 | }
289 | try
290 | {
291 | Thread.sleep(1000);
292 | }
293 | catch (InterruptedException e)
294 | {
295 | // ignore it
296 | }
297 | }
298 | }
299 | public void addConnection(CBConnection connection)
300 | {
301 | connections.add(connection);
302 | }
303 | public void removeConnection(CBConnection connection)
304 | {
305 | connections.remove(connection);
306 | }
307 | }
308 | }
309 |
--------------------------------------------------------------------------------
/src/main/java/com/couchbase/jdbc/CBParameterMetaData.java:
--------------------------------------------------------------------------------
1 | /*
2 | * // Copyright (c) 2015 Couchbase, Inc.
3 | * // Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
4 | * // except in compliance with the License. You may obtain a copy of the License at
5 | * // http://www.apache.org/licenses/LICENSE-2.0
6 | * // Unless required by applicable law or agreed to in writing, software distributed under the
7 | * // License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
8 | * // either express or implied. See the License for the specific language governing permissions
9 | * // and limitations under the License.
10 | */
11 |
12 | package com.couchbase.jdbc;
13 |
14 |
15 | import java.sql.ParameterMetaData;
16 | import java.sql.SQLException;
17 |
18 | /**
19 | * Created by davec on 2015-07-28.
20 | */
21 | public class CBParameterMetaData implements ParameterMetaData
22 | {
23 | final CBPreparedResult preparedResult;
24 |
25 | public CBParameterMetaData(CBPreparedResult preparedResult)
26 | {
27 | this.preparedResult = preparedResult;
28 | }
29 | /**
30 | * Retrieves the number of parameters in the PreparedStatement
31 | * object for which this ParameterMetaData object contains
32 | * information.
33 | *
34 | * @return the number of parameters
35 | * @throws SQLException if a database access error occurs
36 | * @since 1.4
37 | */
38 | @Override
39 | public int getParameterCount() throws SQLException
40 | {
41 | return 0;
42 | }
43 |
44 | /**
45 | * Retrieves whether null values are allowed in the designated parameter.
46 | *
47 | * @param param the first parameter is 1, the second is 2, ...
48 | * @return the nullability status of the given parameter; one of
49 | * ParameterMetaData.parameterNoNulls,
50 | * ParameterMetaData.parameterNullable, or
51 | * ParameterMetaData.parameterNullableUnknown
52 | * @throws SQLException if a database access error occurs
53 | * @since 1.4
54 | */
55 | @Override
56 | public int isNullable(int param) throws SQLException
57 | {
58 | return parameterNullable;
59 | }
60 |
61 | /**
62 | * Retrieves whether values for the designated parameter can be signed numbers.
63 | *
64 | * @param param the first parameter is 1, the second is 2, ...
65 | * @return true if so; false otherwise
66 | * @throws SQLException if a database access error occurs
67 | * @since 1.4
68 | */
69 | @Override
70 | public boolean isSigned(int param) throws SQLException
71 | {
72 | return false;
73 | }
74 |
75 | /**
76 | * Retrieves the designated parameter's specified column size.
77 | *
78 | *
The returned value represents the maximum column size for the given parameter.
79 | * For numeric data, this is the maximum precision. For character data, this is the length in characters.
80 | * For datetime datatypes, this is the length in characters of the String representation (assuming the
81 | * maximum allowed precision of the fractional seconds component). For binary data, this is the length in bytes. For the ROWID datatype,
82 | * this is the length in bytes. 0 is returned for data types where the
83 | * column size is not applicable.
84 | *
85 | * @param param the first parameter is 1, the second is 2, ...
86 | * @return precision
87 | * @throws SQLException if a database access error occurs
88 | * @since 1.4
89 | */
90 | @Override
91 | public int getPrecision(int param) throws SQLException
92 | {
93 | return 0;
94 | }
95 |
96 | /**
97 | * Retrieves the designated parameter's number of digits to right of the decimal point.
98 | * 0 is returned for data types where the scale is not applicable.
99 | *
100 | * @param param the first parameter is 1, the second is 2, ...
101 | * @return scale
102 | * @throws SQLException if a database access error occurs
103 | * @since 1.4
104 | */
105 | @Override
106 | public int getScale(int param) throws SQLException
107 | {
108 | return 0;
109 | }
110 |
111 | /**
112 | * Retrieves the designated parameter's SQL type.
113 | *
114 | * @param param the first parameter is 1, the second is 2, ...
115 | * @return SQL type from java.sql.Types
116 | * @throws SQLException if a database access error occurs
117 | * @see java.sql.Types
118 | * @since 1.4
119 | */
120 | @Override
121 | public int getParameterType(int param) throws SQLException
122 | {
123 | return 0;
124 | }
125 |
126 | /**
127 | * Retrieves the designated parameter's database-specific type name.
128 | *
129 | * @param param the first parameter is 1, the second is 2, ...
130 | * @return type the name used by the database. If the parameter type is
131 | * a user-defined type, then a fully-qualified type name is returned.
132 | * @throws SQLException if a database access error occurs
133 | * @since 1.4
134 | */
135 | @Override
136 | public String getParameterTypeName(int param) throws SQLException
137 | {
138 | return null;
139 | }
140 |
141 | /**
142 | * Retrieves the fully-qualified name of the Java class whose instances
143 | * should be passed to the method PreparedStatement.setObject.
144 | *
145 | * @param param the first parameter is 1, the second is 2, ...
146 | * @return the fully-qualified name of the class in the Java programming
147 | * language that would be used by the method
148 | * PreparedStatement.setObject to set the value
149 | * in the specified parameter. This is the class name used
150 | * for custom mapping.
151 | * @throws SQLException if a database access error occurs
152 | * @since 1.4
153 | */
154 | @Override
155 | public String getParameterClassName(int param) throws SQLException
156 | {
157 | return null;
158 | }
159 |
160 | /**
161 | * Retrieves the designated parameter's mode.
162 | *
163 | * @param param the first parameter is 1, the second is 2, ...
164 | * @return mode of the parameter; one of
165 | * ParameterMetaData.parameterModeIn,
166 | * ParameterMetaData.parameterModeOut, or
167 | * ParameterMetaData.parameterModeInOut
168 | * ParameterMetaData.parameterModeUnknown.
169 | * @throws SQLException if a database access error occurs
170 | * @since 1.4
171 | */
172 | @Override
173 | public int getParameterMode(int param) throws SQLException
174 | {
175 | return parameterModeIn;
176 | }
177 |
178 | /**
179 | * Returns an object that implements the given interface to allow access to
180 | * non-standard methods, or standard methods not exposed by the proxy.
181 | *
182 | * If the receiver implements the interface then the result is the receiver
183 | * or a proxy for the receiver. If the receiver is a wrapper
184 | * and the wrapped object implements the interface then the result is the
185 | * wrapped object or a proxy for the wrapped object. Otherwise return the
186 | * the result of calling unwrap recursively on the wrapped object
187 | * or a proxy for that result. If the receiver is not a
188 | * wrapper and does not implement the interface, then an SQLException is thrown.
189 | *
190 | * @param iface A Class defining an interface that the result must implement.
191 | * @return an object that implements the interface. May be a proxy for the actual implementing object.
192 | * @throws SQLException If no object found that implements the interface
193 | * @since 1.6
194 | */
195 | @Override
196 | public T unwrap(Class iface) throws SQLException
197 | {
198 | if (iface.isAssignableFrom(getClass()))
199 | {
200 | return iface.cast(this);
201 | }
202 | throw new SQLException("Cannot unwrap to " + iface.getName());
203 | }
204 |
205 | /**
206 | * Returns true if this either implements the interface argument or is directly or indirectly a wrapper
207 | * for an object that does. Returns false otherwise. If this implements the interface then return true,
208 | * else if this is a wrapper then return the result of recursively calling isWrapperFor on the wrapped
209 | * object. If this does not implement the interface and is not a wrapper, return false.
210 | * This method should be implemented as a low-cost operation compared to unwrap so that
211 | * callers can use this method to avoid expensive unwrap calls that may fail. If this method
212 | * returns true then calling unwrap with the same argument should succeed.
213 | *
214 | * @param iface a Class defining an interface.
215 | * @return true if this implements the interface or directly or indirectly wraps an object that does.
216 | * @throws SQLException if an error occurs while determining whether this is a wrapper
217 | * for an object with the given interface.
218 | * @since 1.6
219 | */
220 | @Override
221 | public boolean isWrapperFor(Class> iface) throws SQLException
222 | {
223 | return iface.isAssignableFrom(getClass());
224 | }
225 | }
226 |
--------------------------------------------------------------------------------
/src/main/java/com/couchbase/jdbc/CBPreparedResult.java:
--------------------------------------------------------------------------------
1 | /*
2 | * // Copyright (c) 2015 Couchbase, Inc.
3 | * // Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
4 | * // except in compliance with the License. You may obtain a copy of the License at
5 | * // http://www.apache.org/licenses/LICENSE-2.0
6 | * // Unless required by applicable law or agreed to in writing, software distributed under the
7 | * // License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
8 | * // either express or implied. See the License for the specific language governing permissions
9 | * // and limitations under the License.
10 | */
11 |
12 | package com.couchbase.jdbc;
13 |
14 | import org.slf4j.Logger;
15 | import org.slf4j.LoggerFactory;
16 |
17 | import java.util.Map;
18 |
19 | /**
20 | * Created by davec on 2015-07-28.
21 | */
22 | public class CBPreparedResult
23 | {
24 | private static final Logger logger = LoggerFactory.getLogger(CBPreparedResult.class);
25 |
26 | String name;
27 | String encodedPlan;
28 | Map operator;
29 | Map signature;
30 |
31 | public CBPreparedResult( Map preparedResult )
32 | {
33 | name = (String)preparedResult.get("name");
34 | encodedPlan = (String)preparedResult.get("encoded_plan");
35 |
36 | operator = (Map)preparedResult.get("operator");
37 | signature = (Map)preparedResult.get("signature");
38 |
39 | logger.trace("Prepared statement {}\nencoded_plan {}\noperator {}\nsignature {}", name, encodedPlan, operator, signature);
40 | }
41 | public String getName()
42 | {
43 | return name;
44 | }
45 | public String getEncodedPlan() { return encodedPlan; }
46 | public Map getSignature()
47 | {
48 | return signature;
49 | }
50 |
51 |
52 | }
53 |
--------------------------------------------------------------------------------
/src/main/java/com/couchbase/jdbc/CBResultSetMetaData.java:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | * // Copyright (c) 2015 Couchbase, Inc.
4 | * // Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
5 | * // except in compliance with the License. You may obtain a copy of the License at
6 | * // http://www.apache.org/licenses/LICENSE-2.0
7 | * // Unless required by applicable law or agreed to in writing, software distributed under the
8 | * // License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
9 | * // either express or implied. See the License for the specific language governing permissions
10 | * // and limitations under the License.
11 | */
12 |
13 | package com.couchbase.jdbc;
14 |
15 | import java.sql.ResultSetMetaData;
16 | import java.sql.SQLException;
17 |
18 | /**
19 | * Created by davec on 2015-02-20.
20 | */
21 | public class CBResultSetMetaData implements ResultSetMetaData
22 | {
23 | final CBResultSet resultSet;
24 |
25 | CBResultSetMetaData(CBResultSet resultSet)
26 | {
27 | this.resultSet = resultSet;
28 | }
29 | /**
30 | * Returns the number of columns in this ResultSet object.
31 | *
32 | * @return the number of columns
33 | * @throws java.sql.SQLException if a database access error occurs
34 | */
35 | @Override
36 | public int getColumnCount() throws SQLException
37 | {
38 | return resultSet.fields.size();
39 | }
40 |
41 | /**
42 | * Indicates whether the designated column is automatically numbered.
43 | *
44 | * @param column the first column is 1, the second is 2, ...
45 | * @return true if so; false otherwise
46 | * @throws java.sql.SQLException if a database access error occurs
47 | */
48 | @Override
49 | public boolean isAutoIncrement(int column) throws SQLException
50 | {
51 | return false;
52 | }
53 |
54 | /**
55 | * Indicates whether a column's case matters.
56 | *
57 | * @param column the first column is 1, the second is 2, ...
58 | * @return true if so; false otherwise
59 | * @throws java.sql.SQLException if a database access error occurs
60 | */
61 | @Override
62 | public boolean isCaseSensitive(int column) throws SQLException
63 | {
64 | return false;
65 | }
66 |
67 | /**
68 | * Indicates whether the designated column can be used in a where clause.
69 | *
70 | * @param column the first column is 1, the second is 2, ...
71 | * @return true if so; false otherwise
72 | * @throws java.sql.SQLException if a database access error occurs
73 | */
74 | @Override
75 | public boolean isSearchable(int column) throws SQLException
76 | {
77 | return false;
78 | }
79 |
80 | /**
81 | * Indicates whether the designated column is a cash value.
82 | *
83 | * @param column the first column is 1, the second is 2, ...
84 | * @return true if so; false otherwise
85 | * @throws java.sql.SQLException if a database access error occurs
86 | */
87 | @Override
88 | public boolean isCurrency(int column) throws SQLException
89 | {
90 | return false;
91 | }
92 |
93 | /**
94 | * Indicates the nullability of values in the designated column.
95 | *
96 | * @param column the first column is 1, the second is 2, ...
97 | * @return the nullability status of the given column; one of columnNoNulls,
98 | * columnNullable or columnNullableUnknown
99 | * @throws java.sql.SQLException if a database access error occurs
100 | */
101 | @Override
102 | public int isNullable(int column) throws SQLException
103 | {
104 | return columnNullable;
105 | }
106 |
107 | /**
108 | * Indicates whether values in the designated column are signed numbers.
109 | *
110 | * @param column the first column is 1, the second is 2, ...
111 | * @return true if so; false otherwise
112 | * @throws java.sql.SQLException if a database access error occurs
113 | */
114 | @Override
115 | public boolean isSigned(int column) throws SQLException
116 | {
117 | return false;
118 | }
119 |
120 | /**
121 | * Indicates the designated column's normal maximum width in characters.
122 | *
123 | * @param column the first column is 1, the second is 2, ...
124 | * @return the normal maximum number of characters allowed as the width
125 | * of the designated column
126 | * @throws java.sql.SQLException if a database access error occurs
127 | */
128 | @Override
129 | public int getColumnDisplaySize(int column) throws SQLException
130 | {
131 | return 0;
132 | }
133 |
134 | /**
135 | * Gets the designated column's suggested title for use in printouts and
136 | * displays. The suggested title is usually specified by the SQL AS
137 | * clause. If a SQL AS is not specified, the value returned from
138 | * getColumnLabel will be the same as the value returned by the
139 | * getColumnName method.
140 | *
141 | * @param column the first column is 1, the second is 2, ...
142 | * @return the suggested column title
143 | * @throws java.sql.SQLException if a database access error occurs
144 | */
145 | @Override
146 | public String getColumnLabel(int column) throws SQLException
147 | {
148 |
149 | return resultSet.getField(column).getName();
150 | }
151 |
152 | /**
153 | * Get the designated column's name.
154 | *
155 | * @param column the first column is 1, the second is 2, ...
156 | * @return column name
157 | * @throws java.sql.SQLException if a database access error occurs
158 | */
159 | @Override
160 | public String getColumnName(int column) throws SQLException
161 | {
162 | return resultSet.getField(column).getName();
163 | }
164 |
165 | /**
166 | * Get the designated column's table's schema.
167 | *
168 | * @param column the first column is 1, the second is 2, ...
169 | * @return schema name or "" if not applicable
170 | * @throws java.sql.SQLException if a database access error occurs
171 | */
172 | @Override
173 | public String getSchemaName(int column) throws SQLException
174 | {
175 | return null;
176 | }
177 |
178 | /**
179 | * Get the designated column's specified column size.
180 | * For numeric data, this is the maximum precision. For character data, this is the length in characters.
181 | * For datetime datatypes, this is the length in characters of the String representation (assuming the
182 | * maximum allowed precision of the fractional seconds component). For binary data, this is the length in bytes. For the ROWID datatype,
183 | * this is the length in bytes. 0 is returned for data types where the
184 | * column size is not applicable.
185 | *
186 | * @param column the first column is 1, the second is 2, ...
187 | * @return precision
188 | * @throws java.sql.SQLException if a database access error occurs
189 | */
190 | @Override
191 | public int getPrecision(int column) throws SQLException
192 | {
193 | return 0;
194 | }
195 |
196 | /**
197 | * Gets the designated column's number of digits to right of the decimal point.
198 | * 0 is returned for data types where the scale is not applicable.
199 | *
200 | * @param column the first column is 1, the second is 2, ...
201 | * @return scale
202 | * @throws java.sql.SQLException if a database access error occurs
203 | */
204 | @Override
205 | public int getScale(int column) throws SQLException
206 | {
207 | return 0;
208 | }
209 |
210 | /**
211 | * Gets the designated column's table name.
212 | *
213 | * @param column the first column is 1, the second is 2, ...
214 | * @return table name or "" if not applicable
215 | * @throws java.sql.SQLException if a database access error occurs
216 | */
217 | @Override
218 | public String getTableName(int column) throws SQLException
219 | {
220 | return null;
221 | }
222 |
223 | /**
224 | * Gets the designated column's table's catalog name.
225 | *
226 | * @param column the first column is 1, the second is 2, ...
227 | * @return the name of the catalog for the table in which the given column
228 | * appears or "" if not applicable
229 | * @throws java.sql.SQLException if a database access error occurs
230 | */
231 | @Override
232 | public String getCatalogName(int column) throws SQLException
233 | {
234 | return null;
235 | }
236 |
237 | /**
238 | * Retrieves the designated column's SQL type.
239 | *
240 | * @param column the first column is 1, the second is 2, ...
241 | * @return SQL type from java.sql.Types
242 | * @throws java.sql.SQLException if a database access error occurs
243 | * @see java.sql.Types
244 | */
245 | @Override
246 | public int getColumnType(int column) throws SQLException
247 | {
248 | return resultSet.getField(column).getSqlType();
249 | }
250 |
251 | /**
252 | * Retrieves the designated column's database-specific type name.
253 | *
254 | * @param column the first column is 1, the second is 2, ...
255 | * @return type name used by the database. If the column type is
256 | * a user-defined type, then a fully-qualified type name is returned.
257 | * @throws java.sql.SQLException if a database access error occurs
258 | */
259 | @Override
260 | public String getColumnTypeName(int column) throws SQLException
261 | {
262 | return resultSet.getField(column).getType();
263 | }
264 |
265 | /**
266 | * Indicates whether the designated column is definitely not writable.
267 | *
268 | * @param column the first column is 1, the second is 2, ...
269 | * @return true if so; false otherwise
270 | * @throws java.sql.SQLException if a database access error occurs
271 | */
272 | @Override
273 | public boolean isReadOnly(int column) throws SQLException
274 | {
275 | return false;
276 | }
277 |
278 | /**
279 | * Indicates whether it is possible for a write on the designated column to succeed.
280 | *
281 | * @param column the first column is 1, the second is 2, ...
282 | * @return true if so; false otherwise
283 | * @throws java.sql.SQLException if a database access error occurs
284 | */
285 | @Override
286 | public boolean isWritable(int column) throws SQLException
287 | {
288 | return false;
289 | }
290 |
291 | /**
292 | * Indicates whether a write on the designated column will definitely succeed.
293 | *
294 | * @param column the first column is 1, the second is 2, ...
295 | * @return true if so; false otherwise
296 | * @throws java.sql.SQLException if a database access error occurs
297 | */
298 | @Override
299 | public boolean isDefinitelyWritable(int column) throws SQLException
300 | {
301 | return false;
302 | }
303 |
304 | /**
305 | *
Returns the fully-qualified name of the Java class whose instances
306 | * are manufactured if the method ResultSet.getObject
307 | * is called to retrieve a value
308 | * from the column. ResultSet.getObject may return a subclass of the
309 | * class returned by this method.
310 | *
311 | * @param column the first column is 1, the second is 2, ...
312 | * @return the fully-qualified name of the class in the Java programming
313 | * language that would be used by the method
314 | * ResultSet.getObject to retrieve the value in the specified
315 | * column. This is the class name used for custom mapping.
316 | * @throws java.sql.SQLException if a database access error occurs
317 | * @since 1.2
318 | */
319 | @Override
320 | public String getColumnClassName(int column) throws SQLException
321 | {
322 | return null;
323 | }
324 |
325 | /**
326 | * Returns an object that implements the given interface to allow access to
327 | * non-standard methods, or standard methods not exposed by the proxy.
328 | *
329 | * If the receiver implements the interface then the result is the receiver
330 | * or a proxy for the receiver. If the receiver is a wrapper
331 | * and the wrapped object implements the interface then the result is the
332 | * wrapped object or a proxy for the wrapped object. Otherwise return the
333 | * the result of calling unwrap recursively on the wrapped object
334 | * or a proxy for that result. If the receiver is not a
335 | * wrapper and does not implement the interface, then an SQLException is thrown.
336 | *
337 | * @param iface A Class defining an interface that the result must implement.
338 | * @return an object that implements the interface. May be a proxy for the actual implementing object.
339 | * @throws java.sql.SQLException If no object found that implements the interface
340 | * @since 1.6
341 | */
342 | @Override
343 | public T unwrap(Class iface) throws SQLException
344 | {
345 | return null;
346 | }
347 |
348 | /**
349 | * Returns true if this either implements the interface argument or is directly or indirectly a wrapper
350 | * for an object that does. Returns false otherwise. If this implements the interface then return true,
351 | * else if this is a wrapper then return the result of recursively calling isWrapperFor on the wrapped
352 | * object. If this does not implement the interface and is not a wrapper, return false.
353 | * This method should be implemented as a low-cost operation compared to unwrap so that
354 | * callers can use this method to avoid expensive unwrap calls that may fail. If this method
355 | * returns true then calling unwrap with the same argument should succeed.
356 | *
357 | * @param iface a Class defining an interface.
358 | * @return true if this implements the interface or directly or indirectly wraps an object that does.
359 | * @throws java.sql.SQLException if an error occurs while determining whether this is a wrapper
360 | * for an object with the given interface.
361 | * @since 1.6
362 | */
363 | @Override
364 | public boolean isWrapperFor(Class> iface) throws SQLException
365 | {
366 | return false;
367 | }
368 | }
369 |
--------------------------------------------------------------------------------
/src/main/java/com/couchbase/jdbc/ConnectionParameters.java:
--------------------------------------------------------------------------------
1 | /*
2 | * // Copyright (c) 2015 Couchbase, Inc.
3 | * // Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
4 | * // except in compliance with the License. You may obtain a copy of the License at
5 | * // http://www.apache.org/licenses/LICENSE-2.0
6 | * // Unless required by applicable law or agreed to in writing, software distributed under the
7 | * // License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
8 | * // either express or implied. See the License for the specific language governing permissions
9 | * // and limitations under the License.
10 | */
11 |
12 | package com.couchbase.jdbc;
13 |
14 | /**
15 | * Created by davec on 2015-03-04.
16 | */
17 | public class ConnectionParameters
18 | {
19 | public final static String CONNECTION_TIMEOUT="connectionTimeout";
20 | public final static String USER="user";
21 | public final static String PASSWORD="password";
22 | public final static String SCAN_CONSISTENCY="ScanConsistency";
23 | public final static String ENABLE_SSL="EnableSSL";
24 | public final static String REDUNDANCY="Redundancy";
25 | public final static String SSL_CERTIFICATE="SSLCertificate";
26 | }
27 |
--------------------------------------------------------------------------------
/src/main/java/com/couchbase/jdbc/connect/Cluster.java:
--------------------------------------------------------------------------------
1 | /*
2 | * // Copyright (c) 2015 Couchbase, Inc.
3 | * // Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
4 | * // except in compliance with the License. You may obtain a copy of the License at
5 | * // http://www.apache.org/licenses/LICENSE-2.0
6 | * // Unless required by applicable law or agreed to in writing, software distributed under the
7 | * // License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
8 | * // either express or implied. See the License for the specific language governing permissions
9 | * // and limitations under the License.
10 | */
11 |
12 | package com.couchbase.jdbc.connect;
13 |
14 | import org.slf4j.Logger;
15 | import org.slf4j.LoggerFactory;
16 |
17 | import java.sql.SQLException;
18 | import java.util.ArrayList;
19 | import java.util.List;
20 | import java.util.Map;
21 | import java.util.concurrent.atomic.AtomicInteger;
22 |
23 | /**
24 | * Created by davec on 2015-05-22.
25 | */
26 | public class Cluster
27 | {
28 | private static final Logger logger = LoggerFactory.getLogger(Cluster.class);
29 |
30 | Integer instanceIndex = new Integer(0);
31 | AtomicInteger numInstances = new AtomicInteger(0);
32 | List endpoints = new ArrayList();
33 |
34 | /*
35 | [{"cluster":"default","name":"10.168.209.119","queryEndpoint":"http://10.168.209.119:8093/query/service","adminEndpoint":"http://10.168.209.119:8093/admin","options":null},
36 | {"cluster":"default","name":"10.169.93.182","queryEndpoint":"http://10.169.93.182:8093/query/service","adminEndpoint":"http://10.169.93.182:8093/admin","options":null},
37 | {"cluster":"default","name":"10.181.71.84","queryEndpoint":"http://10.181.71.84:8093/query/service","adminEndpoint":"http://10.181.71.84:8093/admin","options":null},
38 | {"cluster":"default","name":"10.30.210.238","queryEndpoint":"http://10.30.210.238:8093/query/service","adminEndpoint":"http://10.30.210.238:8093/admin","options":null}]
39 | */
40 |
41 | public Cluster( List