I'm facing a problem when writing some UDFs, I searched related posts in site but I'm afraid I haven't got any useful ideas yet.
The question is:
I'm going to execute a SQL statement in UDF, then print query result. Here's my code:
public final class AnalyzeConstraints extends UDF {
private Connection connToHive = null;
public Connection getHiveConn() throws SQLException {
if (connToHive == null) {
try {
Class.forName("org.apache.hive.jdbc.HiveDriver");
} catch (ClassNotFoundException err) {
err.printStackTrace();
System.exit(1);
}
// hive cluster IP address
connToHive = DriverManager.getConnection(
"jdbc:hive://XXXXX:10004/default", "user", "passwd");
System.out.println("loggin");
}
return connToHive;
}
public void closeHiveConn() throws SQLException {
if (connToHive != null) {
connToHive.close();
}
}
//# end region
//# region HiveUtility
// query data
public ResultSet queryData(String sql) throws SQLException {
Connection conn = getHiveConn();
Statement stmt = conn.createStatement();
ResultSet res = stmt.executeQuery(sql);
return res;
}
//# end region
//# region UDF implement
public String evaluate(String table) throws SQLException {
StringBuffer result = new StringBuffer();
String schema = null;
String table_name = null;
if (table.length() > 0 && table.indexOf(".") > 0 && table.split("\\.").length == 2) {
schema = table.split("\\.")[0];
table_name = table.split("\\.")[1];
// For debug
System.out.println(schema + ":" + table_name);
}
else
result.append("ERROR: \'" + table + "\' is not a valid table in the current search_path\n");
//# region analyze PK
StringBuffer sqlPK = new StringBuffer();
sqlPK.append(String.format("select constraint_name, column_name from catalog.constraint_columns where table_schema = \'%s\' and Upper(table_name) = \'%s\' and constraint_type = \'p\';\n", schema, table_name.toUpperCase()));
// For debug
System.out.println(sqlPK.toString());
ResultSet resPK = queryData(sqlPK.toString());
// Print resultset here
}
Here's error message:
FAILED: SemanticException [Error 10014]: Line 1:8 Wrong arguments ''catalog.systables'': org.apache.hadoop.hive.ql.metadata.HiveException: Unable to execute method public java.lang.String AnalyzeConstraints.evaluate(java.lang.String) throws java.sql.SQLException on object AnalyzeConstraints#4f86c135 of class AnalyzeConstraints with arguments {catalog.systables:java.lang.String} of size 1
hive>
Any ideas will be highly appreciated! Thanks in advance!
Related
I am writing methods through JDBC to create a table and a sequence to recall in a Trigger, I want to set up an id column which auto-increments before every insert on the table. I succeeded in building both the createTable method and the createSequence method in the DAO, but when I run the method to create the Trigger I got the java.sql.SQLException: Missing IN or OUT parameter at index:: 1
public void createTrigger() {
PreparedStatement ps;
StringBuilder queryTrigger = new StringBuilder();
queryTrigger.append("CREATE OR REPLACE TRIGGER ");
queryTrigger.append(Tables.getInstance().getName() + "_INSERTED\n");
queryTrigger.append("BEFORE INSERT ON " + Tabelle.getInstance().getName());
queryTrigger.append("\nFOR EACH ROW\n");
queryTrigger.append("BEGIN\n");
queryTrigger.append("SELECT " + Tables.getInstance().getName() + "SEQ.NEXTVAL\n");
queryTrigger.append("INTO :new.id\n");
queryTrigger.append("FROM dual;\n ");
queryTrigger.append("END;\n");
queryTrigger.append("/\n");
queryTrigger.append("ALTER TRIGGER " +Tabelle.getInstance().getName() + "_INSERTED ENABLE\n");
queryTrigger.append("/\n");
String stringQueryTrigger = queryTrigger.toString();
Connection conn = JDBCUtility.openConnection();
try {
ps = (PreparedStatement) conn.prepareStatement(stringQueryTrigger);
ps.executeUpdate();
ps.close();
} catch(SQLException e) {
e.printStackTrace();
}
JDBCUtility.closeConnection(conn);}
Here instead the creation of the table does actually work even if I don't
write the classic lines with parametrized "?" for the preparedStatement.setString(index, String)
public void createTable(Columns c) {
PreparedStatement ps;
StringBuilder query = new StringBuilder();
query.append("CREATE TABLE " + Tabelle.getInstance().getName() + "(");
query.append(Columns.getInstance().getColumnName() + " ");
query.append(Columns.getInstance().getDataType());
if(Columns.getInstance().isNullOrNot() == true) {
query.append(" NOT NULL");
}
else {
query.append("");
}
if(Columns.getInstance().isPrimaryKeyOrNot() == true) {
query.append(" PRIMARY KEY)");
}
else {
query.append(")");
}
String queryToString = query.toString();
Connection conn = JDBCUtility.openConnection();
try {
ps = (PreparedStatement) conn.prepareStatement(queryToString);
ps.executeUpdate();
ps.close();
} catch(SQLException e) {
e.printStackTrace();
}
JDBCUtility.closeConnection(conn);
}
//EDIT
turns out that is enough to substitute the PreparedStatement with a simple Statement, to get rid of the indexes mechanism and get the DB to accept the query
I would suggest creating an auto-increment sequnce in oracle that can be used for all ids and just add the string id.NextVal to the string query
What I mean is:
Rem in oracle create sequence
CREATE SEQUENCE ID
START BY 1
INCREMENT 1
// in java to execute query
String query = "INSERT INTO TABLE VALUES(ID.NEXTVAL);" ;
//rest of code
I've found one totally working query, which gets columns and their data from Oracle DB and puts the output in console printout.
I've spent 3 hours trying to display this data in Swing JTable.
When I am trying to bind data with JTable:
jTable1.setModel(new javax.swing.table.DefaultTableModel(
data, header
));
it keeps telling me that constructor is invalid. That's true, because I need arrays [] and [][] to make that. Any ideas how this can be implemented?
Here is the original query:
package com.javacoderanch.example.sql;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
public class MetadataColumnExample {
private static final String DRIVER = "oracle.jdbc.OracleDriver";
private static final String URL = "jdbc:oracle:thin:#//XXX";
private static final String USERNAME = "XXX";
private static final String PASSWORD = "XXX";
public static void main(String[] args) throws Exception {
Connection connection = null;
try {
//
// As the usual ritual, load the driver class and get connection
// from database.
//
Class.forName(DRIVER);
connection = DriverManager.getConnection(URL, USERNAME, PASSWORD);
//
// In the statement below we'll select all records from users table
// and then try to find all the columns it has.
//
Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery("select *\n"
+ "from booking\n"
+ "where TRACKING_NUMBER = 1000001741");
//
// The ResultSetMetaData is where all metadata related information
// for a result set is stored.
//
ResultSetMetaData metadata = resultSet.getMetaData();
int columnCount = metadata.getColumnCount();
//
// To get the column names we do a loop for a number of column count
// returned above. And please remember a JDBC operation is 1-indexed
// so every index begin from 1 not 0 as in array.
//
ArrayList<String> columns = new ArrayList<String>();
for (int i = 1; i < columnCount; i++) {
String columnName = metadata.getColumnName(i);
columns.add(columnName);
}
//
// Later we use the collected column names to get the value of the
// column it self.
//
while (resultSet.next()) {
for (String columnName : columns) {
String value = resultSet.getString(columnName);
System.out.println(columnName + " = " + value);
}
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
connection.close();
}
}
}
Ok I found a bit better way adding SQL query to JTable without even using the ArrayList. Maybe will be helpful for someone, completely working:
import java.awt.*;
import javax.swing.*;
import java.sql.*;
import java.awt.image.BufferedImage;
public class report extends JFrame {
PreparedStatement ps;
Connection con;
ResultSet rs;
Statement st;
JLabel l1;
String bn;
int bid;
Date d1, d2;
int rows = 0;
Object data1[][];
JScrollPane scroller;
JTable table;
public report() {
Container cp = getContentPane();
cp.setLayout(new BorderLayout());
setSize(600, 600);
setLocation(50, 50);
setLayout(new BorderLayout());
setTitle("Library Report");
try {
Class.forName("oracle.jdbc.OracleDriver");
con = DriverManager.getConnection("jdbc:oracle:thin:#XXXXX", "XXXXX", "XXXXX");
} catch (Exception e) {
}
try {
/*
* JDBC 2.0 provides a way to retrieve a rowcount from a ResultSet without having to scan through all the rows
* So we add TYPE_SCROLL_INSENSITIVE & CONCUR_READ_ONLY
*/
st = con.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY); //Creating Statement Object
} catch (SQLException sqlex) {
System.out.println("!!!###");
}
try {
rs = st.executeQuery("select TRACKING_NUMBER, INCO_TERM_CODE, MODE_OF_TRANSPORT\n"
+ "from salog.booking\n"
+ "where rownum < 5");
// Counting rows
rs.last();
int rows = rs.getRow();
rs.beforeFirst();
System.out.println("cc " + rows);
ResultSetMetaData metaData = rs.getMetaData();
int colummm = metaData.getColumnCount();
System.out.println("colms =" + colummm);
Object[] Colheads = {"BookId", "BookName", "rtyry"};
if (Colheads.length != colummm) {
// System.out.println("EPT!!");
JOptionPane.showMessageDialog(rootPane, "Incorrect Column Headers quantity listed in array! The program will now exit.", "System Error", JOptionPane.ERROR_MESSAGE);
System.exit(0);
}
data1 = new Object[rows][Colheads.length];
for (int i1 = 0; i1 < rows; i1++) {
rs.next();
for (int j1 = 0; j1 < Colheads.length; j1++) {
data1[i1][j1] = rs.getString(j1 + 1);
}
}
JTable table = new JTable(data1, Colheads);
JScrollPane jsp = new JScrollPane(table);
getContentPane().add(jsp);
} catch (Exception e) {
}
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String args[]) {
JFrame frm = new report();
frm.setSize(600, 600);
frm.setLocation(50, 50);
BufferedImage image = null;
frm.setIconImage(image);
frm.setVisible(true);
frm.show();
}
}
can you please guys help me, i'm having trouble on making my primary key into auto-increment, My table name is books and the column that i want to be auto-increment is serial_no which is a primary key.
public class donate extends javax.swing.JFrame {
Connection con;
Statement stmt;
ResultSet rs;
PreparedStatement pst;
DefaultTableModel loginModel = new DefaultTableModel();
int curRow = 0;
/**
* Creates new form donate
*/
public donate() {
initComponents();
DoConnect();
showAll();
}
void showAll(){
try{
rs = stmt.executeQuery("SELECT * FROM books");
while(rs.next())
{
String book = rs.getString("book_title");
String categorie = rs.getString("category");
String status = rs.getString("book_status");
String donators = rs.getString("donator");
int serial_nos = rs.getInt("serial_no");
loginModel.addRow(new Object[]{book, categorie, status, donators, serial_nos});
}
}catch(SQLException err){
System.out.println(err);
}
}
void DoConnect( ) {
try{
//CONNECT TO THE DATABASE
String host = "jdbc:derby://localhost:1527/Dafuq7";
String uName ="Dafuq7";
String uPass ="Dafuq7";
con = DriverManager.getConnection(host, uName, uPass);
//EXECUTE SOME SQL AND LOAD THE RECORDS INTO THE RESULTSET
stmt = con.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_UPDATABLE);
String sql = "SELECT * FROM books";
rs = stmt.executeQuery(sql);
}
catch(SQLException err){
JOptionPane.showMessageDialog(donate.this, err.getMessage());
}
}
and here is for may button, which when i input all the data will be submitted to my table books
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
String bookttl = bookt.getText();
String yourn = yn.getText();
String categ = cat.getSelectedItem().toString();
String bstat = bs.getSelectedItem().toString();
try {
rs.moveToInsertRow();
rs.updateString( "book_title", bookttl );
rs.updateString( "category", yourn );
rs.updateString( "book_status", categ );
rs.updateString( "donator", bstat );
loginModel.addRow(new Object[]{bookttl, yourn, categ, bstat});
rs.insertRow( );
stmt.close();
rs.close();
stmt = con.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_UPDATABLE);
String sql = "SELECT * FROM books";
rs = stmt.executeQuery(sql);
}
catch (SQLException err) {
System.out.println(err.getMessage() );
}// TODO add your handling code here:
}
BTW i found another way around by doing this, grabbing my table and reconstructing it and put this code in the create table script
SERIAL_NO INTEGER default AUTOINCREMENT: start 1 increment 1 not null primary key
Simply define your serial_no column as int primary key generated always as identity and then Derby will automatically assign the numbers for you. Here is some example code:
public static void main(String[] args) {
try (Connection conn = DriverManager.getConnection(
"jdbc:derby:C:/__tmp/derbytest;create=true")) {
String sql;
sql = "DROP TABLE books";
try (Statement s = conn.createStatement()) {
s.executeUpdate(sql);
} catch (Exception e) {
// assume table did not previously exist
}
sql = "CREATE TABLE books (" +
"serial_no int primary key " +
"generated always as identity, " +
"title varchar(100))";
try (Statement s = conn.createStatement()) {
s.executeUpdate(sql);
}
sql = "INSERT INTO books (title) VALUES (?)";
try (PreparedStatement ps = conn.prepareStatement(sql)) {
ps.setString(1, "The Book of Foo");
ps.executeUpdate();
ps.setString(1, "The Book of Bar");
ps.executeUpdate();
ps.setString(1, "The Book of Baz");
ps.executeUpdate();
}
sql = "SELECT * FROM books";
try (Statement s = conn.createStatement()) {
try (ResultSet rs = s.executeQuery(sql)) {
while (rs.next()) {
System.out.println(String.format(
"%d: %s",
rs.getInt("serial_no"),
rs.getString("title")));
}
}
}
} catch (SQLException se) {
se.printStackTrace(System.out);
System.exit(0);
}
}
which produces
1: The Book of Foo
2: The Book of Bar
3: The Book of Baz
I had the error in this code snippet:
private String[][] connectToDB(String query) throws ClassNotFoundException{
String[][] results = null;
try {
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
String db = "jdbc:odbc:Driver={Microsoft Access Driver (*.mdb, *.accdb)};DBQ=E:/EACA_AgroVentures1.accdb";
conn = DriverManager.getConnection(db);
stmt = conn.prepareStatement(query);
ResultSet rs = stmt.executeQuery();
ResultSetMetaData rsm = rs.getMetaData();
rs.beforeFirst();
int columns = rsm.getColumnCount();
int rows = getRowCount(rs);
//int rows = rs.getFetchSize();
int rowCount = 0;
results = new String[rows][columns];
//System.out.println(rows+" "+columns);
while((rs!=null) && (rs.next())){
for(int i = 1; i < columns; i++){
results[rowCount][i-1] = rs.getString(i); // --> ERROR SHOWS HERE
//System.out.println(rowCount+","+i+" = "+rs.getString(i));
}
rowCount++;
}
rs.getStatement().close();
conn.close();
} catch (SQLException ex) {
Logger.getLogger(MainFrame.class.getName()).log(Level.SEVERE, null, ex);
}
return results;
}
My query consists of the following:
private void loadMR(){
try {
String query = "SELECT dealerCode, SUM(kg) AS totalKG, SUM(price) AS totalPrice, returnDate, BID FROM meatReturns GROUP BY BID, dealerCode, returnDate;";
Object[][] result = connectToDB(query);
// some more code below..
I tried using the first code with some other query given in another method:
private void loadDealers(){
try {
String query = "SELECT * FROM Dealers";
Object[][] result = connectToDBWithRows(
query);
// some more code..
and it runs perfectly well. What is going on here? How can i fix this problem?
UPDATE: the only difference of connectToDBWithRows and connectToDB is the while loop that manages the resultSet
// Snippet from connectToDBWithRows()
while((rs!=null) && (rs.next())){
for(int i = 0; i < columns; i++){
if (i == 0){
// Do nothing
}else{
results[rowCount][i] = rs.getString(i);
//System.out.println(rowCount+","+i+" = "+rs.getString(i));
}
}
rowCount++;
}
and this is my getRowCount() method
private int getRowCount(ResultSet resultSet){
int size = 0;
try {
resultSet.last();
size = resultSet.getRow();
resultSet.beforeFirst();
}
catch(Exception ex) {
return 0;
}
return size;
}
I've noticed that sometimes, Access needs you to specify the table name when referring to columns in sql statements. Try the following:
private void loadMR(){
try {
String query = "SELECT meatReturns.dealerCode, SUM(meatReturns.kg) AS totalKG, SUM(meatReturns.price) AS totalPrice, meatReturns.returnDate, meatReturns.BID FROM meatReturns GROUP BY meatReturns.BID, meatReturns.dealerCode, meatReturns.returnDate";
Object[][] result = connectToDBWithRows(query);
I am trying to find where a specific string exist in a database (all tables). I have the following code:
DatabaseMetaData md = con.getMetaData();
ResultSet rs = md.getTables(null, null, "%", null);
while (rs.next()) {
stm = con.createStatement();
String sql;
sql = "SELECT * FROM "+rs.getString(3)+"WHERE F01 = '0000000000998'";
rs2 = stm.executeQuery(sql);
while(rs2.next()){
System.out.println(rs.getString(3));
}
}
The problem is in some of the tables F01 doesn't exist, so it throws an exception. Is there any way that even without specifying the column I can search through the whole table?
which database you are using.
Look over this discussion post. you may get good ideas about how to make sure column exists before you call your check
http://www.coderanch.com/t/299298/JDBC/databases/Oracle-describe-table-jdbc
For oracle
you can check these queries
select COLUMN_NAME, DATA_LENGTH, DATA_TYPE from user_tab_columns where Lower(table_name) = 'product'
select table_name, COLUMN_NAME, DATA_LENGTH, DATA_TYPE from user_tab_columns where upper(column_name) = 'PRODUCTID'
therefore your call should be something like this
select table_name from user_tab_columns where upper(column_name) = 'F01'
and then
SELECT * FROM "+rs.getString(1)+"WHERE F01 = '0000000000998'
as you see I am using LOWER and UPPER, you need to make sure you include them, reason as you can understand even though SQL is not case sensitive in its statements, but the value for which conditional check is happening is case sensitive.
The following Java code loops through each VARCHAR/NVARCHAR column in each table and performs a SELECT TOP 1 on that column to see if it gets a hit:
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
public class JDBCQuery {
public static void main(String args[]) {
String textToSearchFor = "Gord"; // test data
System.out.println(String.format("The value '%s' was found in the following locations:", textToSearchFor));
Connection conn = null;
PreparedStatement ps = null;
try {
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
String connectionString =
"jdbc:odbc:Driver={SQL Server};" +
"Server=.\\SQLEXPRESS;" +
"Trusted_Connection=yes;" +
"Database=myDb";
conn = DriverManager.getConnection(connectionString);
DatabaseMetaData md = conn.getMetaData();
ResultSet mdrs = md.getTables(null, null, "%", new String[] { "TABLE" });
List<String> tableList = new ArrayList<String>();
while (mdrs.next()) {
tableList.add(String.format("[%s].[%s].[%s]", mdrs.getString(1), mdrs.getString(2), mdrs.getString(3)));
// i.e., [catalogName].[schemaName].[tableName]
}
mdrs.close();
for (String tableName : tableList) {
Statement stmt = conn.createStatement();
stmt.execute("SELECT * FROM " + tableName + " WHERE 0=1");
ResultSet rs0 = stmt.getResultSet();
ResultSetMetaData rsmd = rs0.getMetaData();
List<String> columnList = new ArrayList<String>();
for (int colIndex = 1; colIndex <= rsmd.getColumnCount(); colIndex++) {
switch (rsmd.getColumnType(colIndex)) {
case java.sql.Types.VARCHAR:
case java.sql.Types.NVARCHAR:
columnList.add("[" + rsmd.getColumnName(colIndex) + "]");
break;
}
}
rs0.close();
stmt.close();
for (String columnName : columnList) {
String psSql = String.format("SELECT TOP 1 * FROM %s WHERE %s = ?", tableName, columnName);
ps = conn.prepareStatement(psSql);
ps.setString(1, textToSearchFor);
ResultSet rs1 = ps.executeQuery();
if (rs1.next()) {
System.out.println(String.format("column %s in %s", columnName, tableName));
}
rs1.close();
ps.close();
}
}
} catch( Exception e ) {
e.printStackTrace();
} finally {
try {
if (ps != null) {
ps.close();
}
if (conn != null) {
conn.close();
}
} catch( Exception e ) {
e.printStackTrace();
}
}
}
}
The results look like this;
The value 'Gord' was found in the following locations:
column [textCol] in [myDb].[dbo].[linkedTable]
column [FirstName] in [myDb].[dbo].[myContacts]