Postgres Advisory Locks
This post is part of the series Postgres for Everything. Nowadays, we typically develop stateless applications, making it easier to scale them horizontally. However, locking is an essential tool to prevent race conditions in software development. In applications with multiple instances, programming language-level locks are insufficient because they only work locally within an instance. A centralized locking mechanism, valid across all instances, is required. Redis SETNX You can use SETNX to implement a simple lock. SETNX sets a value for a key only if the key does not already exist. ...
Postgres Collation
From my previous post, I realized that pattern matching operators (LIKE, ILIKE) do not utilize indexes. As I explored further, I came across the concept of collation and decided to take some notes in this post. Encoding Encoding maps human-readable characters to numbers so computers can understand them. Essentially, it assigns a unique number to each character. Common encodings include UTF-8 and ASCII. ASCII: Represents 256 unique characters. UTF-8: Represents 1,112,064 characters, covering almost all characters from any language. Most modern programming languages, such as Go, natively support UTF-8. Unlike ASCII, which uses 1 byte per character, UTF-8 uses up to 4 bytes. Strings in programming languages are typically represented as byte arrays. In ASCII, the number of bytes corresponds to the number of characters. However, this is not true for UTF-8. ...
What does it mean to listen on localhost:8080?
Have you ever asked, why do we usually listen on localhost:8080 during development process, can we listen on Google IP instead of localhost? I have a little code snippet written in NodeJS: 1 2 3 4 5 var http = require('http'); http.createServer(function (req, res) { res.writeHead(200, {'Content-Type': 'text/plain'}); res.end('Hello World\n'); }).listen(8080, 'localhost'); It doesn’t do anything complex, just starts a new server, listens on localhost:8080, and responds ‘Hello World’ to requests. I need you to do a little more thing, open your terminal, and execute this command (MacOS or Linux) to get your local IP: ...
The pointer receiver and value receiver in Go are just syntax sugar
If you are a Gopher, you probably heard some advice that goes like this: when you edit a value then use a pointer receiver, when you read use a value receiver. That’s not always correct and you should be careful when using them. Issue Today I encountered an issue which can be simplified by the bellow code snippet: 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 package main import ( "fmt" "time" ) type Counter struct { Count int } // Method with pointer receiver func (c *Counter) Increment() { go func() { for i := 0; i < 10; i++ { c.Count++ time.Sleep(1 * time.Second) } }() } // Method with value receiver func (c Counter) Display() { go func() { for i := 0; i < 10; i++ { fmt.Println("counter value: ", c.Count) time.Sleep(1 * time.Second) } }() } func main() { c := Counter{Count: 0} c.Display() c.Increment() time.Sleep(15 * time.Second) fmt.Println("counter final value: ", c.Count) } I have a struct with two methods, Increment uses the pointer receiver to change the property of the struct, and Display uses the value receiver to read the value from the struct. Here is the result: ...
Why would sometimes 0.1 + 0.2 equals to 0.3, but sometimes it’s not in Go
You may have heard about 0.1 + 0.2 != 0.3 already, it’s a common issue in most programming languages. The reason behind that is the floating point (IEEE 754) as the computer can’t represent exactly a decimal in binary. By utilizing the floating point, the computer can hold a very large decimal, but the trade-off is it now can only represent the approximate of the true value. However, in this post, I will not explain how floating point works but something else – constant. ...
A Note About Rust Smart Pointer and Deref
this article assumes you have some basic knowledge about Rust smart pointers. the dereference (*) operator dereference operator * is used for getting the actual value from a reference: 1 2 3 let a: i32 = 5; let b: &i32 = &a; assert_eq!(*b, 5); in the above example, b is a reference to a, *b will return the value that b pointing to. the smart pointers Box<T> here is an example of how you can init and modify the value of a Box: ...
Floyd’s cycle detection
a linked list If we use two pointers slow and fast, the first one moves forward one step at a time, and the second one moves forward two steps at a time. Eventually, the two pointers will meet somewhere. In the above example, they meet at number 9 (or G). G is where two-pointers fast and slow meet. E is the entrance of the loop. S is the first node of the linked list. F is the distance from the chain’s beginning to the loop’s entrance (from S to E). (eg: 1 – 3 – 5) a is the distance from the loop’s entrance to the point where two pointers meet (from E to G). (eg: 5 – 6 – 7 – 8 – 9) C is the length of the loop. (eg: the loop is 5 – 6 – 7 – 8 – 9 – 10, the length is 6 ) The total distance that the slow pointer has moved is $F + a + xC$. $x$ is the number of times the slow pointer completes the loop. The total distance that the fast pointer has moved is $F + a + yC$. Likewise, $y$ is the number of times the fast pointer completes the loop. ...
Disjoin-Set/Union-Find notes
1. Definition set is a collection of unique elements. the word disjoin means non-overlapping – two sets are considered as disjoining if they have no element in common disjoin-set contains a collection of non-overlapping sets it has two method find(x): return the representative element of the set that contains of x if u and v are in the same set, find(u) = find(v) union(u, v): merge two sets that contain u and v after merging, find(v) = find(u) 2. Implementations View the visualization of the data structure here. ...
Which operator is faster: like vs =
Explain Explaining the query will help you to estimate how expensive your query is and which query plan will be used. 1 2 3 4 5 6 khanh=# explain select g from grades where g = 100; QUERY PLAN ------------------------------------------------------------------------------- Index Only Scan using g_index on grades (cost=0.42..97.55 rows=4636 width=4) Index Cond: (g = 100) (2 rows) So, this query will use Index-Only-Scan. The cost of the query is ranging from 0.42 to 97.55, 4636 is number of estimated return rows, width is size of return data in byte. ...
Postgres Timezone
Check timezone of the current session 1 2 3 4 5 khanh=# show timezone; TimeZone ---------- UTC (1 row) Change timezone of a session 1 2 3 4 5 6 7 khanh=# set timezone='asia/ho_chi_minh'; SET khanh=# show timezone; TimeZone ------------------ Asia/Ho_Chi_Minh (1 row) you can get timezone names here: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones timestamp and timestamptz timestamptz aka timestamp with time zone, the time when return to the client will be converted to the timezone has picked in the session. ...