summaryrefslogtreecommitdiff
path: root/src/database/QueryUtils.java
blob: 2cc6fd62a484333c2d29bc4cdd7bcda4d3cd7fa0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
package database;

import java.sql.SQLException;
import java.util.Locale;

/**
 * Utilities to create queries.
 *
 * @author Maurice Laveaux
 */
public class QueryUtils {
    public final static String insertRating 
            = buildQuery("mentionsbrand", new String[]{"tweetid","brand"},"tweetid","brand", "rating");
    public final static String insertProfile
            = buildQuery("twitteruser", new String[]{"userid"},
            "userid", "displayname", "timezone", "tweetcount", "followercount",
            "followedcount", "location", "tweetname", "createdat::timestamptz",
            "language", "description", "verified");

    public final static String insertTweet
            = buildQuery("tweet", new String[]{"tweetid"},
            "tweetid", "createdat::timestamptz", "favcount", "retweetcount",
            "text", "coordinates::point",
            "language", "retweetid", "replyid", "place",
            "userid");

    public final static String insertHash
            = buildQuery("hashtag", null, "tweetid", "hashtag");

    public final static String insertUserUrl
            = buildQuery("userUrl", null, "userid", "url");

    public final static String insertTweetUrl
            = buildQuery("tweetUrl", null, "tweetid", "url");

    public final static String insertMentions
            = buildQuery("mentionsuser", null, "tweetid", "userid");

    public final static String insertBrand
            = buildQuery("mentionsbrand", null, "tweetid", "brand");

    /**
     * Builds an upsert query for a table and keys.
     *
     * @param table Table to insert or update the data.
     * @param primaryKeys The primary keys for the table or null if all keys
     * form the primary key.
     * @param keys The keys to be inserted or updated.
     * @return A SQL query containing named parameters.
     */
    private static String buildQuery(String table, String[] primaryKeys,
            String... keys) {
        String sep = "";
        String fields = ""; // a, b, c
        String values = ""; // :a, :b, :c
        String set_values = ""; // a = nv.a, b = nv.b, c = nv.c
        String pkey_matches = "";
        for (String field : keys) {
            String key = field.replaceFirst("::\\w+", "");
            fields += sep + key;
            values += sep + ":" + field;
            // "u" is "table that gets updated", "nv" is "new values"
            set_values += sep + key + " = nv." + key;
            sep = ", ";
        }
        sep = "";
        // assume that all fields form the primary key if pks are missing
        if (primaryKeys == null) {
            primaryKeys = keys;
        }
        for (String pkey : primaryKeys) {
            assert !pkey.contains("::") : "Specify primary keys when type cast is given";
            pkey_matches += sep + "u." + pkey + " = nv." + pkey;
            sep = " AND ";
        }

        String sql;
        // CTE that holds new values
        sql = "WITH nv (" + fields + ") AS (\n";
        sql += "    VALUES (" + values + ")\n";
        sql += ")\n";
        // CTE that tries to update the table with new values (PSQL extension)
        sql += ", upsert AS (\n";
        sql += "    UPDATE " + table + " u SET " + set_values + " FROM nv\n";
        sql += "    WHERE " + pkey_matches + " RETURNING 1\n";
        sql += ")\n";
        // if nothing got updated, insert new entry
        sql += "INSERT INTO " + table + " (" + fields + ")\n";
        sql += "SELECT " + fields + " FROM nv\n";
        sql += "WHERE NOT EXISTS (SELECT 1 FROM upsert)";
        return sql;
    }

    public static void setInsertParams(NamedPreparedStatement statement,
            Long tweetid, String brand, int rating) throws SQLException {
        statement.setLong("tweetid", tweetid);
        statement.setInt("rating", rating);
        statement.setString("brand", brand);
        
    }

    public static void setInsertBrandParams(NamedPreparedStatement brandStmt,
            long id, String brand) throws SQLException {
        brandStmt.setLong("tweetid", id);
        brandStmt.setString("brand", brand);
        // TODO: rating (positive)
    }
}